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 records; protected Map deviceResMap; TreeRoot deviceHierarchy; Map deviceProblemHazardCounts; Map 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; } /** * 按设备类型汇总设备信息,供新版设备报告使用。 */ protected List buildDeviceGroupInfo() { Map> 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 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 buildDeviceScoreInfo() { List result = new ArrayList<>(); for (var deviceType : DeviceType.values()) { List 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 items, int startIndex) { int index = startIndex; for (Object item : items) { if (item instanceof JSONObject jsonObject) { jsonObject.put("序号", index++); } } } private void fillDetailIndexes(List 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 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 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 buildDeviceErrorLevels(Device device) { var deviceRes = deviceResMap.get(device.getId()); if (deviceRes == null) { return null; } List 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 buildDeviceErrorRecords(Device device) { var deviceRes = deviceResMap.get(device.getId()); if (deviceRes == null) { return null; } List result = new ArrayList<>(); JSONObject info = new JSONObject(); info.put("设备编号", device.getManufacturerNumber()); info.put("问题", buildDeviceErrorInfo(device)); result.add(info); return result; } private List buildDeviceErrorInfo(Device device) { var deviceRecords = buildDeviceRecords(device); List 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 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 errorNode(ErrorRecord record) { var hierarchyPath = record.getProblem().getHierarchyPath(); return deviceHierarchy.get(hierarchyPath); } }