package com.estate.expert.admin.stat.report.data;
|
|
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONObject;
|
import com.estate.expert.admin.domain.business.device.Device;
|
import com.estate.expert.admin.domain.business.device.DeviceType;
|
import com.estate.expert.admin.domain.exam.eval.fuzzy.FuzzyResult;
|
import com.estate.expert.admin.domain.exam.record.error.ErrorLevel;
|
import com.estate.expert.admin.domain.exam.record.error.ErrorRecord;
|
import com.estate.expert.admin.domain.standard.hierachy.HierarchyData;
|
import com.estate.expert.admin.utils.tree.TreeNode;
|
import com.estate.expert.admin.utils.tree.TreeRoot;
|
import lombok.experimental.SuperBuilder;
|
import org.springframework.util.StringUtils;
|
|
import java.util.ArrayList;
|
import java.util.Comparator;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Objects;
|
import java.util.TreeMap;
|
|
/**
|
* 代管设备风险评估报告数据。
|
*/
|
@SuperBuilder
|
public abstract class DaiguanDeviceReportData extends ReportDataBase {
|
|
List<ErrorRecord> records;
|
|
protected Map<Integer, FuzzyResult> deviceResMap;
|
|
TreeRoot<HierarchyData> deviceHierarchy;
|
|
Map<String, Long> deviceProblemHazardCounts;
|
|
Map<Integer, Long> deviceCheckCounts;
|
|
/**
|
* 生成报告数据
|
* @return 报告数据
|
*/
|
public JSONObject generate() {
|
var result = buildReportInfo();
|
result.put("工程概况", buildProjectInfo());
|
result.put("设备信息", buildDeviceInfo());
|
result.put("设备分组信息", buildDeviceGroupInfo());
|
result.put("评估结果", buildEvalInfo());
|
return result;
|
}
|
|
/**
|
* 构建评估信息
|
* @return 评估信息
|
*/
|
@Override
|
protected JSONObject buildEvalInfo() {
|
JSONObject evalInfo = new JSONObject();
|
var deviceScoreInfo = buildDeviceScoreInfo();
|
|
evalInfo.put("分类评估", buildDeviceTypeCheckItem(deviceScoreInfo.size() + 1));
|
evalInfo.put("设备得分情况", deviceScoreInfo);
|
evalInfo.put("隐患等级分布汇总", buildDeviceErrorLevels());
|
return evalInfo;
|
}
|
|
/**
|
* 按设备类型汇总设备信息,供新版设备报告使用。
|
*/
|
private List<Object> buildDeviceGroupInfo() {
|
Map<String, List<Device>> groupedDevices = devices.stream()
|
.sorted(Comparator.comparing(device -> device.getType() != null ? device.getType().ordinal() : Integer.MAX_VALUE))
|
.collect(java.util.stream.Collectors.groupingBy(
|
device -> device.getType() != null ? device.getType().getDesc() : "",
|
java.util.LinkedHashMap::new,
|
java.util.stream.Collectors.toList()
|
));
|
|
List<Object> groupInfos = new ArrayList<>();
|
groupedDevices.forEach((deviceType, groupDevices) -> {
|
var deviceNumbers = groupDevices.stream()
|
.map(Device::getManufacturerNumber)
|
.filter(StringUtils::hasText)
|
.toList();
|
var numbers = deviceNumbers.isEmpty() ? List.of("") : deviceNumbers;
|
|
for (int i = 0; i < numbers.size(); i++) {
|
JSONObject groupInfo = new JSONObject();
|
groupInfo.put("设备类型", i == 0 ? deviceType : "");
|
groupInfo.put("设备数量", i == 0 ? groupDevices.size() : "");
|
groupInfo.put("设备编号", numbers.get(i));
|
groupInfos.add(groupInfo);
|
}
|
});
|
return groupInfos;
|
}
|
|
private JSONObject buildDeviceTypeCheckItem(int startIndex) {
|
JSONObject result = new JSONObject();
|
var details = new ArrayList<>();
|
float totalScore = 0;
|
int totalTypes = 0;
|
int totalDevices = 0;
|
for (var deviceType : DeviceType.values()) {
|
var detail = buildDeviceTypeCheckDetail(deviceType);
|
if (detail != null) {
|
details.add(detail);
|
totalTypes++;
|
totalScore += Float.parseFloat((String) detail.get("分数"));
|
totalDevices += (int) detail.get("数量");
|
}
|
}
|
result.put("详情", details);
|
result.put("总数", totalTypes);
|
result.put("设备总数", totalDevices);
|
result.put("总分", totalTypes == 0 ? formatFloat(0) : formatFloat(totalScore / totalTypes));
|
fillIndexes(details, startIndex);
|
fillDetailIndexes(details);
|
return result;
|
}
|
|
private List<Object> buildDeviceScoreInfo() {
|
List<Object> result = new ArrayList<>();
|
for (var deviceType : DeviceType.values()) {
|
List<Object> details = new ArrayList<>();
|
float totalScore = 0;
|
int totalDevices = 0;
|
|
for (var deviceId : deviceResMap.keySet()) {
|
var device = devices.stream().filter(d -> d.getId().equals(deviceId)).findFirst().orElse(null);
|
if (device == null || device.getType() != deviceType) {
|
continue;
|
}
|
|
var score = getDeviceScore(deviceId);
|
JSONObject detail = new JSONObject();
|
detail.put("分项名称", device.getManufacturerNumber());
|
detail.put("分项得分", formatFloat(score));
|
details.add(detail);
|
totalScore += score;
|
totalDevices++;
|
}
|
|
if (totalDevices == 0) {
|
continue;
|
}
|
|
JSONObject summary = new JSONObject();
|
summary.put("分项名称", "管理行为得分");
|
summary.put("分项得分", formatFloat(totalScore / totalDevices));
|
details.add(summary);
|
|
JSONObject info = new JSONObject();
|
info.put("设备类型", deviceType.getDesc());
|
info.put("详情", details);
|
result.add(info);
|
}
|
fillIndexes(result, 1);
|
return result;
|
}
|
|
private void fillIndexes(List<Object> items, int startIndex) {
|
int index = startIndex;
|
for (Object item : items) {
|
if (item instanceof JSONObject jsonObject) {
|
jsonObject.put("序号", index++);
|
}
|
}
|
}
|
|
private void fillDetailIndexes(List<Object> items) {
|
int index = 1;
|
for (Object item : items) {
|
if (item instanceof JSONObject jsonObject) {
|
jsonObject.put("隐患详单序号", toChineseIndex(index++));
|
}
|
}
|
}
|
|
private String toChineseIndex(int index) {
|
return switch (index) {
|
case 1 -> "一";
|
case 2 -> "二";
|
case 3 -> "三";
|
case 4 -> "四";
|
case 5 -> "五";
|
case 6 -> "六";
|
case 7 -> "七";
|
case 8 -> "八";
|
case 9 -> "九";
|
case 10 -> "十";
|
default -> String.valueOf(index);
|
};
|
}
|
|
/**
|
* 获取设备分数
|
* @param deviceId 设备ID
|
* @return 设备分数
|
*/
|
protected abstract float getDeviceScore(Integer deviceId);
|
|
private JSONObject buildDeviceTypeCheckDetail(DeviceType deviceType) {
|
int totalDevice = 0;
|
float totalScore = 0;
|
List<Object> deviceCheckItems = new ArrayList<>();
|
JSONArray records = new JSONArray();
|
int[] totalErrors = new int[4];
|
|
for (var deviceId : deviceResMap.keySet()) {
|
var device = devices.stream().filter(d -> d.getId().equals(deviceId)).findFirst().orElse(null);
|
if (device == null || device.getType() != deviceType) {
|
continue;
|
}
|
|
var deviceData = deviceResMap.get(deviceId).root().getData();
|
totalScore += getDeviceScore(deviceId);
|
totalDevice++;
|
for (int i = 0; i < 4; i++) {
|
totalErrors[i] += deviceData.getTotalErrorCounts()[i];
|
}
|
|
var errorLevels = buildDeviceErrorLevels(device);
|
if (errorLevels != null) {
|
deviceCheckItems.addAll(errorLevels);
|
}
|
|
var errorRecords = buildDeviceErrorRecords(device);
|
if (errorRecords != null) {
|
records.addAll(errorRecords);
|
}
|
}
|
fillProblemDetailIndexes(records);
|
|
if (totalDevice > 0) {
|
JSONObject info = new JSONObject();
|
info.put("设备类型", deviceType.getDesc());
|
info.put("数量", totalDevice);
|
info.put("分数", formatFloat(totalScore / totalDevice));
|
info.put("分项隐患", deviceCheckItems);
|
info.put("分项问题", records);
|
info.put("一级隐患", totalErrors[0]);
|
info.put("二级隐患", totalErrors[1]);
|
info.put("三级隐患", totalErrors[2]);
|
info.put("四级隐患", totalErrors[3]);
|
return info;
|
}
|
return null;
|
}
|
|
private void fillProblemDetailIndexes(JSONArray deviceRecords) {
|
int index = 1;
|
for (Object deviceRecord : deviceRecords) {
|
if (!(deviceRecord instanceof JSONObject deviceInfo)) {
|
continue;
|
}
|
var problems = deviceInfo.getJSONArray("问题");
|
if (problems == null) {
|
continue;
|
}
|
for (Object problem : problems) {
|
if (!(problem instanceof JSONObject problemInfo)) {
|
continue;
|
}
|
var problemDetail = problemInfo.getJSONObject("问题详情");
|
if (problemDetail != null) {
|
problemDetail.put("隐患详单问题序号", index++);
|
}
|
}
|
}
|
}
|
|
private JSONObject buildDeviceErrorLevels() {
|
int totalErrors = 0;
|
var totalErrorCounts = new int[4];
|
|
for (var device : devices) {
|
var deviceRes = deviceResMap.get(device.getId());
|
if (deviceRes == null) {
|
continue;
|
}
|
var deviceErrorCounts = deviceRes.root().getData().getTotalErrorCounts();
|
for (int i = 0; i < 4; i++) {
|
totalErrorCounts[i] += deviceErrorCounts[i];
|
totalErrors += deviceErrorCounts[i];
|
}
|
}
|
|
List<Object> errorInfos = new ArrayList<>();
|
for (int i = 0; i < 4; i++) {
|
var errorLevel = ErrorLevel.values()[i];
|
var count = totalErrorCounts[i];
|
var info = new TreeMap<>();
|
info.put("隐患等级", errorLevel.getDesc());
|
info.put("隐患程度", errorLevel.getDesc2());
|
info.put("数量", count);
|
info.put("比例", totalErrors == 0 ? formatPercent(0) : formatPercent(count * 1.0 / totalErrors));
|
errorInfos.add(info);
|
}
|
|
JSONObject result = new JSONObject();
|
result.put("隐患数量", totalErrors);
|
result.put("一级隐患数量", totalErrorCounts[0]);
|
result.put("二级隐患数量", totalErrorCounts[1]);
|
result.put("三级隐患数量", totalErrorCounts[2]);
|
result.put("四级隐患数量", totalErrorCounts[3]);
|
result.put("分项", errorInfos);
|
return result;
|
}
|
|
private List<Object> buildDeviceErrorLevels(Device device) {
|
var deviceRes = deviceResMap.get(device.getId());
|
if (deviceRes == null) {
|
return null;
|
}
|
List<Object> result = new ArrayList<>();
|
|
JSONObject info = new JSONObject();
|
info.put("设备编号", device.getManufacturerNumber());
|
|
var errorCounts = deviceRes.root().getData().getTotalErrorCounts();
|
info.put("一级隐患", errorCounts[0]);
|
info.put("二级隐患", errorCounts[1]);
|
info.put("三级隐患", errorCounts[2]);
|
info.put("四级隐患", errorCounts[3]);
|
result.add(info);
|
return result;
|
}
|
|
private List<Object> buildDeviceErrorRecords(Device device) {
|
var deviceRes = deviceResMap.get(device.getId());
|
if (deviceRes == null) {
|
return null;
|
}
|
List<Object> result = new ArrayList<>();
|
|
JSONObject info = new JSONObject();
|
info.put("设备编号", device.getManufacturerNumber());
|
info.put("问题", buildDeviceErrorInfo(device));
|
result.add(info);
|
return result;
|
}
|
|
private List<Object> buildDeviceErrorInfo(Device device) {
|
var deviceRecords = buildDeviceRecords(device);
|
List<Object> result = new ArrayList<>();
|
for (var record : deviceRecords) {
|
JSONObject info = new JSONObject();
|
info.put("检查问题", StringUtils.hasText(record.getRemark()) ? record.getRemark() : record.getProblem().getDescription());
|
info.put("隐患等级", record.getLevel().getDesc());
|
info.put("同类隐患出现频次", getDeviceProblemHazardCount(record));
|
info.put("检查频次", getDeviceProblemCheckCount(record));
|
var subItem = buildRecordDetail(record);
|
subItem.put("项目级别", errorNode(record).getName());
|
info.put("问题详情", subItem);
|
result.add(info);
|
}
|
return result;
|
}
|
|
private long getDeviceProblemHazardCount(ErrorRecord record) {
|
if (deviceProblemHazardCounts == null) {
|
return 0L;
|
}
|
return deviceProblemHazardCounts.getOrDefault(buildDeviceProblemKey(record), 0L);
|
}
|
|
private long getDeviceProblemCheckCount(ErrorRecord record) {
|
Integer deviceId = record != null && record.getDevice() != null ? record.getDevice().getId() : null;
|
if (deviceId == null || deviceCheckCounts == null) {
|
return 0L;
|
}
|
return Math.max(deviceCheckCounts.getOrDefault(deviceId, 0L), 0L);
|
}
|
|
private String buildDeviceProblemKey(ErrorRecord record) {
|
Integer deviceId = record != null && record.getDevice() != null ? record.getDevice().getId() : null;
|
Integer problemId = record != null && record.getProblem() != null ? record.getProblem().getId() : null;
|
return buildDeviceProblemKey(deviceId, problemId);
|
}
|
|
public static String buildDeviceProblemKey(Integer deviceId, Integer problemId) {
|
return Objects.toString(deviceId, "") + "::" + Objects.toString(problemId, "");
|
}
|
|
private List<ErrorRecord> buildDeviceRecords(Device device) {
|
return records.stream()
|
.filter(r -> r.getDevice().getId().equals(device.getId()))
|
.sorted(Comparator.comparing(r -> r.getLevel() != null ? r.getLevel().ordinal() : ErrorLevel.P4.ordinal()))
|
.toList();
|
}
|
|
protected TreeNode<HierarchyData> errorNode(ErrorRecord record) {
|
var hierarchyPath = record.getProblem().getHierarchyPath();
|
return deviceHierarchy.get(hierarchyPath);
|
}
|
}
|