|
@@ -0,0 +1,281 @@
|
|
|
|
|
+package com.coffee.bus.stats.analyse;
|
|
|
|
|
+
|
|
|
|
|
+import cn.hutool.core.collection.CollectionUtil;
|
|
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
|
|
+import com.coffee.bus.entity.BusConMixEntity;
|
|
|
|
|
+import com.coffee.bus.enums.DeviceAlarmEnum;
|
|
|
|
|
+import com.coffee.bus.enums.StatsAnalyseEnum;
|
|
|
|
|
+import com.coffee.bus.enums.StatsTimeUnit;
|
|
|
|
|
+import com.coffee.bus.service.LocalBusInfusionHistoryService;
|
|
|
|
|
+import com.coffee.bus.service.dto.CombineAlarmResult;
|
|
|
|
|
+import com.coffee.bus.service.dto.CombineQuery;
|
|
|
|
|
+import com.coffee.bus.stats.CommonStats;
|
|
|
|
|
+import com.coffee.bus.stats.entity.*;
|
|
|
|
|
+import com.coffee.bus.stats.enums.PieEnum;
|
|
|
|
|
+import lombok.AllArgsConstructor;
|
|
|
|
|
+import lombok.Data;
|
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
|
+
|
|
|
|
|
+import java.math.BigDecimal;
|
|
|
|
|
+import java.util.*;
|
|
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * @author lifang
|
|
|
|
|
+ * @version 1.0.0
|
|
|
|
|
+ * @ClassName AlarmAndWarnStatsAnalyse.java
|
|
|
|
|
+ * @Description 提示统计
|
|
|
|
|
+ * @createTime 2022年06月07日 10:04:00
|
|
|
|
|
+ */
|
|
|
|
|
+@Data
|
|
|
|
|
+@AllArgsConstructor
|
|
|
|
|
+@Service
|
|
|
|
|
+public class AlarmStatsAnalyse implements CommonStats<CombineAlarmResult> {
|
|
|
|
|
+ private final LocalBusInfusionHistoryService infusionHistoryService;
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public List<CombineAlarmResult> queryResult(CombineQuery query) {
|
|
|
|
|
+ return infusionHistoryService.queryStatsAlarm(query);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public StatsAnalyseEnum getId() {
|
|
|
|
|
+ return StatsAnalyseEnum.alarm;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public List<PieResult> handlePie(List<CombineAlarmResult> results) {
|
|
|
|
|
+ ArrayList<PieResult> result = new ArrayList<>();
|
|
|
|
|
+ result.add(totalPie(results));
|
|
|
|
|
+ result.addAll(alarmAnalysePie(results));
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public List<LineResult> handleLine(List<CombineAlarmResult> results, StatsTimeUnit unit) {
|
|
|
|
|
+ //根据时间对结果进行区分统计
|
|
|
|
|
+ Map<String, List<CombineAlarmResult>> groupByTime = groupByTime(results, unit);
|
|
|
|
|
+ List<LineResult> result = new ArrayList<>();
|
|
|
|
|
+ result.add(countLine(groupByTime));
|
|
|
|
|
+ result.add(ratioLine(groupByTime));
|
|
|
|
|
+ //比率
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 描述: 提示比率折线图
|
|
|
|
|
+ * @author lifang
|
|
|
|
|
+ * @date 2022/6/7 13:24
|
|
|
|
|
+ * @param results
|
|
|
|
|
+ * @return LineResult
|
|
|
|
|
+ */
|
|
|
|
|
+ private LineResult ratioLine(Map<String, List<CombineAlarmResult>> results) {
|
|
|
|
|
+ LineResult<BigDecimal> result = new LineResult<>();
|
|
|
|
|
+ List<String> time = new ArrayList<>();
|
|
|
|
|
+ result.setTime(time);
|
|
|
|
|
+ result.setId("count");
|
|
|
|
|
+ result.setDescription("此数据为 报警率 【次数统计】");
|
|
|
|
|
+ Map<String, AlarmTotalPieResult> groupByTime = new HashMap<>();
|
|
|
|
|
+ //根据时间区间对镇痛方式进行统计
|
|
|
|
|
+ results.forEach((timeRange,combineResults)->{
|
|
|
|
|
+ AlarmTotalPieResult alarmTotalPieResult = groupByTime.computeIfAbsent(timeRange, k -> new AlarmTotalPieResult());
|
|
|
|
|
+ combineResults.forEach(alarmTotalPieResult::handle);
|
|
|
|
|
+ time.add(timeRange);
|
|
|
|
|
+ });
|
|
|
|
|
+ //将每一时区的报警数量进行分类汇总
|
|
|
|
|
+ Map<String, LineResult.LineContent<BigDecimal>> lineContentMap=new HashMap<>();
|
|
|
|
|
+ groupByTime.forEach((timeRange,totalResult)->{
|
|
|
|
|
+ BigDecimal total = BigDecimal.valueOf(totalResult.getTotal());
|
|
|
|
|
+ lineContentMap.computeIfAbsent("堵塞率",k->new LineResult.LineContent<>("堵塞")).getValue()
|
|
|
|
|
+ .add(computeRatio(BigDecimal.valueOf(totalResult.getJam().getValue()),total));
|
|
|
|
|
+ lineContentMap.computeIfAbsent("极限率",k->new LineResult.LineContent<>("极限")).getValue()
|
|
|
|
|
+ .add(computeRatio(BigDecimal.valueOf(totalResult.getLimit().getValue()),total));
|
|
|
|
|
+ lineContentMap.computeIfAbsent("未装药盒率",k->new LineResult.LineContent<>("未装药盒")).getValue()
|
|
|
|
|
+ .add(computeRatio(BigDecimal.valueOf(totalResult.getNoBox().getValue()),total));
|
|
|
|
|
+ lineContentMap.computeIfAbsent("电机失控率",k->new LineResult.LineContent<>("电机失控")).getValue()
|
|
|
|
|
+ .add(computeRatio(BigDecimal.valueOf(totalResult.getOutOfControl().getValue()),total));
|
|
|
|
|
+ lineContentMap.computeIfAbsent("镇痛不足率",k->new LineResult.LineContent<>("镇痛不足")).getValue()
|
|
|
|
|
+ .add(computeRatio(BigDecimal.valueOf(totalResult.getAnalgesicPoor().getValue()),total));
|
|
|
|
|
+ lineContentMap.computeIfAbsent("不在服务区率",k->new LineResult.LineContent<>("不在服务区")).getValue()
|
|
|
|
|
+ .add(computeRatio(BigDecimal.valueOf(totalResult.getNoSignal().getValue()),total));
|
|
|
|
|
+ lineContentMap.computeIfAbsent("机械故障率",k->new LineResult.LineContent<>("机械故障")).getValue()
|
|
|
|
|
+ .add(computeRatio(BigDecimal.valueOf(totalResult.getMachine().getValue()),total));
|
|
|
|
|
+ lineContentMap.computeIfAbsent("电量耗尽率",k->new LineResult.LineContent<>("电量耗尽")).getValue()
|
|
|
|
|
+ .add(computeRatio(BigDecimal.valueOf(totalResult.getLowBattery().getValue()),total));
|
|
|
|
|
+ lineContentMap.computeIfAbsent("气泡无液率",k->new LineResult.LineContent<>("气泡无液")).getValue()
|
|
|
|
|
+ .add(computeRatio(BigDecimal.valueOf(totalResult.getBubble().getValue()),total));
|
|
|
|
|
+ lineContentMap.computeIfAbsent("低输注率",k->new LineResult.LineContent<>("低输注")).getValue()
|
|
|
|
|
+ .add(computeRatio(BigDecimal.valueOf(totalResult.getLowInfusion().getValue()),total));
|
|
|
|
|
+ });
|
|
|
|
|
+ result.setContent(new ArrayList<>(lineContentMap.values()));
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 描述: 提示次数折线图
|
|
|
|
|
+ * @author lifang
|
|
|
|
|
+ * @date 2022/6/7 13:24
|
|
|
|
|
+ * @param results
|
|
|
|
|
+ * @return LineResult
|
|
|
|
|
+ */
|
|
|
|
|
+ private LineResult countLine(Map<String, List<CombineAlarmResult>> results) {
|
|
|
|
|
+ LineResult<Long> result = new LineResult<>();
|
|
|
|
|
+ List<String> time = new ArrayList<>();
|
|
|
|
|
+ result.setTime(time);
|
|
|
|
|
+ result.setId("count");
|
|
|
|
|
+ result.setDescription("此数据为 报警方式 【次数统计】");
|
|
|
|
|
+ Map<String, AlarmTotalPieResult> groupByTime = new HashMap<>();
|
|
|
|
|
+ //根据时间区间对镇痛方式进行统计
|
|
|
|
|
+ results.forEach((timeRange,combineResults)->{
|
|
|
|
|
+ AlarmTotalPieResult alarmTotalPieResult = groupByTime.computeIfAbsent(timeRange, k -> new AlarmTotalPieResult());
|
|
|
|
|
+ combineResults.forEach(alarmTotalPieResult::handle);
|
|
|
|
|
+ time.add(timeRange);
|
|
|
|
|
+ });
|
|
|
|
|
+ //将每一时区的报警数量进行分类汇总
|
|
|
|
|
+ Map<String, LineResult.LineContent<Long>> lineContentMap=new HashMap<>();
|
|
|
|
|
+ groupByTime.forEach((timeRange,totalResult)->{
|
|
|
|
|
+ lineContentMap.computeIfAbsent("堵塞",k->new LineResult.LineContent<>("堵塞")).getValue().add(totalResult.getJam().getValue());
|
|
|
|
|
+ lineContentMap.computeIfAbsent("极限",k->new LineResult.LineContent<>("极限")).getValue().add(totalResult.getLimit().getValue());
|
|
|
|
|
+ lineContentMap.computeIfAbsent("未装药盒",k->new LineResult.LineContent<>("未装药盒")).getValue().add(totalResult.getNoBox().getValue());
|
|
|
|
|
+ lineContentMap.computeIfAbsent("电机失控",k->new LineResult.LineContent<>("电机失控")).getValue().add(totalResult.getOutOfControl().getValue());
|
|
|
|
|
+ lineContentMap.computeIfAbsent("镇痛不足",k->new LineResult.LineContent<>("镇痛不足")).getValue().add(totalResult.getAnalgesicPoor().getValue());
|
|
|
|
|
+ lineContentMap.computeIfAbsent("不在服务区",k->new LineResult.LineContent<>("不在服务区")).getValue().add(totalResult.getNoSignal().getValue());
|
|
|
|
|
+ lineContentMap.computeIfAbsent("机械故障",k->new LineResult.LineContent<>("机械故障")).getValue().add(totalResult.getMachine().getValue());
|
|
|
|
|
+ lineContentMap.computeIfAbsent("电量耗尽",k->new LineResult.LineContent<>("电量耗尽")).getValue().add(totalResult.getLowBattery().getValue());
|
|
|
|
|
+ lineContentMap.computeIfAbsent("气泡无液",k->new LineResult.LineContent<>("气泡无液")).getValue().add(totalResult.getBubble().getValue());
|
|
|
|
|
+ lineContentMap.computeIfAbsent("低输注",k->new LineResult.LineContent<>("低输注")).getValue().add(totalResult.getLowInfusion().getValue());
|
|
|
|
|
+ });
|
|
|
|
|
+ result.setContent(new ArrayList<>(lineContentMap.values()));
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public TableResult handleTable(List<CombineAlarmResult> results, StatsTimeUnit unit) {
|
|
|
|
|
+ TableResult result = new TableResult();
|
|
|
|
|
+ //根据时间对结果进行区分统计
|
|
|
|
|
+ Map<String, List<CombineAlarmResult>> groupByTimeResults = groupByTime(results, unit);
|
|
|
|
|
+ //顺序不可错! 先数量后比率
|
|
|
|
|
+ List<StatsColumn> allColumn = getAllColumn(Arrays.asList("堵塞","极限","未装药盒","电机失控","镇痛不足","不在服务区","机械故障","电量耗尽","气泡无液","返厂维护","低输注"));
|
|
|
|
|
+ allColumn.add(1,StatsColumn.of("输注总数","输注总数"));
|
|
|
|
|
+ allColumn.add(2,StatsColumn.of("提示总数","提示总数"));
|
|
|
|
|
+ List<Map<String, Object>> contents = new ArrayList<>();
|
|
|
|
|
+ result.setContent(contents);
|
|
|
|
|
+ result.setColumn(allColumn);
|
|
|
|
|
+ //根据时间区间对镇痛方式进行统计
|
|
|
|
|
+ Map<String, AlarmTotalPieResult> groupByTimeCountResult = new HashMap<>();
|
|
|
|
|
+ //根据时间区间对镇痛方式进行统计
|
|
|
|
|
+ groupByTimeResults.forEach((timeRange,combineResults)->{
|
|
|
|
|
+ AlarmTotalPieResult alarmTotalPieResult = groupByTimeCountResult.computeIfAbsent(timeRange, k -> new AlarmTotalPieResult());
|
|
|
|
|
+ combineResults.forEach(alarmTotalPieResult::handle);
|
|
|
|
|
+ alarmTotalPieResult.setInfusionCount(combineResults.stream().map(CombineAlarmResult::getId).distinct().count());
|
|
|
|
|
+ });
|
|
|
|
|
+ groupByTimeCountResult.forEach((timeRange,totalResult)->{
|
|
|
|
|
+ //表格内容
|
|
|
|
|
+ LinkedHashMap<String, Object> contentValues = new LinkedHashMap<>();
|
|
|
|
|
+ BigDecimal total =BigDecimal.valueOf( totalResult.getTotal());
|
|
|
|
|
+ contentValues.put("time",timeRange);
|
|
|
|
|
+ contentValues.put("输注总数",totalResult.getInfusionCount());
|
|
|
|
|
+ contentValues.put("提示总数",total);
|
|
|
|
|
+ contentValues.put("堵塞",totalResult.getJam().getValue());
|
|
|
|
|
+ contentValues.put("极限",totalResult.getLimit().getValue());
|
|
|
|
|
+ contentValues.put("未装药盒",totalResult.getNoBox().getValue());
|
|
|
|
|
+ contentValues.put("电机失控",totalResult.getOutOfControl().getValue());
|
|
|
|
|
+ contentValues.put("镇痛不足",totalResult.getAnalgesicPoor().getValue());
|
|
|
|
|
+ contentValues.put("不在服务区",totalResult.getNoSignal().getValue());
|
|
|
|
|
+ contentValues.put("机械故障",totalResult.getMachine().getValue());
|
|
|
|
|
+ contentValues.put("电量耗尽",totalResult.getLowBattery().getValue());
|
|
|
|
|
+ contentValues.put("气泡无液",totalResult.getBubble().getValue());
|
|
|
|
|
+ contentValues.put("低输注",totalResult.getLowInfusion().getValue());
|
|
|
|
|
+
|
|
|
|
|
+ contentValues.put("堵塞比率",computeRatio(BigDecimal.valueOf(totalResult.getJam().getValue()),total));
|
|
|
|
|
+ contentValues.put("极限比率",computeRatio(BigDecimal.valueOf(totalResult.getLimit().getValue()),total));
|
|
|
|
|
+ contentValues.put("未装药盒比率",computeRatio(BigDecimal.valueOf(totalResult.getNoBox().getValue()),total));
|
|
|
|
|
+ contentValues.put("电机失控比率",computeRatio(BigDecimal.valueOf(totalResult.getOutOfControl().getValue()),total));
|
|
|
|
|
+ contentValues.put("镇痛不足比率",computeRatio(BigDecimal.valueOf(totalResult.getAnalgesicPoor().getValue()),total));
|
|
|
|
|
+ contentValues.put("不在服务区比率",computeRatio(BigDecimal.valueOf(totalResult.getNoSignal().getValue()),total));
|
|
|
|
|
+ contentValues.put("机械故障比率",computeRatio(BigDecimal.valueOf(totalResult.getMachine().getValue()),total));
|
|
|
|
|
+ contentValues.put("电量耗尽比率",computeRatio(BigDecimal.valueOf(totalResult.getLowBattery().getValue()),total));
|
|
|
|
|
+ contentValues.put("气泡无液比率",computeRatio(BigDecimal.valueOf(totalResult.getBubble().getValue()),total));
|
|
|
|
|
+ contentValues.put("低输注比率",computeRatio(BigDecimal.valueOf(totalResult.getLowInfusion().getValue()),total));
|
|
|
|
|
+
|
|
|
|
|
+ contents.add(contentValues);
|
|
|
|
|
+ });
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 描述: 获取总量饼图
|
|
|
|
|
+ * 1、堵塞
|
|
|
|
|
+ * 2、极限
|
|
|
|
|
+ * 3、未装药盒
|
|
|
|
|
+ * 4、电机失控
|
|
|
|
|
+ * 5、镇痛不足
|
|
|
|
|
+ * 6、不在服务区
|
|
|
|
|
+ * 7、机械故障
|
|
|
|
|
+ * 8、电量耗尽
|
|
|
|
|
+ * 9、气泡无液
|
|
|
|
|
+ * 10、低输注状态
|
|
|
|
|
+ * 11、返厂维护
|
|
|
|
|
+ * @author lifang
|
|
|
|
|
+ * @date 2022/6/7 10:07
|
|
|
|
|
+ * @param results
|
|
|
|
|
+ * @return PieResult
|
|
|
|
|
+ */
|
|
|
|
|
+ private PieResult totalPie(List<CombineAlarmResult> results){
|
|
|
|
|
+ PieResult result = PieResult.of(PieEnum.total.name(),PieEnum.total.getText());
|
|
|
|
|
+ AlarmTotalPieResult alarmTotalPieResult = new AlarmTotalPieResult();
|
|
|
|
|
+ results.forEach(alarmTotalPieResult::handle);
|
|
|
|
|
+ result.setContent(new ArrayList<>(alarmTotalPieResult.values()));
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 描述: 报警原因分析饼图
|
|
|
|
|
+ * 堵塞
|
|
|
|
|
+ * 极限
|
|
|
|
|
+ * 未装药盒
|
|
|
|
|
+ * 电机失控
|
|
|
|
|
+ * 机械故障
|
|
|
|
|
+ * 电量耗尽
|
|
|
|
|
+ * 气泡无液
|
|
|
|
|
+ * 返厂维修
|
|
|
|
|
+ * @author lifang
|
|
|
|
|
+ * @date 2022/6/7 10:50
|
|
|
|
|
+ * @param results
|
|
|
|
|
+ * @return List<PieResult>
|
|
|
|
|
+ */
|
|
|
|
|
+ private List<PieResult> alarmAnalysePie(List<CombineAlarmResult> results){
|
|
|
|
|
+ Map<DeviceAlarmEnum, PieResult> resultMap = new HashMap<>();
|
|
|
|
|
+ resultMap.put(DeviceAlarmEnum.Jam,PieResult.of("jam","堵塞报警原因分析饼图"));
|
|
|
|
|
+ resultMap.put(DeviceAlarmEnum.Limit,PieResult.of("limit","极限报警原因分析饼图"));
|
|
|
|
|
+ resultMap.put(DeviceAlarmEnum.NotBox,PieResult.of("noBox","未装药盒报警原因分析饼图"));
|
|
|
|
|
+ resultMap.put(DeviceAlarmEnum.OutOfControl,PieResult.of("outOfControl","电机失控报警原因分析饼图"));
|
|
|
|
|
+ resultMap.put(DeviceAlarmEnum.Machine,PieResult.of("machine","机械故障报警原因分析饼图"));
|
|
|
|
|
+ resultMap.put(DeviceAlarmEnum.LowBattery,PieResult.of("lowBattery","电量耗尽报警原因分析饼图"));
|
|
|
|
|
+ resultMap.put(DeviceAlarmEnum.Bubble,PieResult.of("bubble","气泡无液报警原因分析饼图"));
|
|
|
|
|
+ resultMap.put(DeviceAlarmEnum.InfusionMax,PieResult.of("infusionMax","返厂维护报警原因分析饼图"));
|
|
|
|
|
+ //按照报警类型分类
|
|
|
|
|
+ Map<DeviceAlarmEnum, List<CombineAlarmResult>> alarmMap = results.stream()
|
|
|
|
|
+ .peek(r->{
|
|
|
|
|
+ if(StrUtil.isBlank(r.getCause())){
|
|
|
|
|
+ r.setCause("未填写");
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ .filter(r -> Boolean.TRUE.equals(r.getIsAlarm())).collect(Collectors.groupingBy(CombineAlarmResult::getAlarm));
|
|
|
|
|
+
|
|
|
|
|
+ resultMap.forEach((alarmType,result)->{
|
|
|
|
|
+ List<CombineAlarmResult> alarmResults = alarmMap.get(alarmType);
|
|
|
|
|
+ if (CollectionUtil.isNotEmpty(alarmResults)) {
|
|
|
|
|
+ Map<String, List<CombineAlarmResult>> causeMap = alarmResults.stream().collect(Collectors.groupingBy(CombineAlarmResult::getCause));
|
|
|
|
|
+ causeMap.forEach((cause,alarmCauses)->{
|
|
|
|
|
+ result.addContent(cause,Long.valueOf(CollectionUtil.size(alarmCauses)));
|
|
|
|
|
+ });
|
|
|
|
|
+ }else {
|
|
|
|
|
+ result.addContent("未填写",0);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ return new ArrayList<>(resultMap.values());
|
|
|
|
|
+ }
|
|
|
|
|
+}
|