From efde7398c10bdd10cb4612c162f14169084fdc50 Mon Sep 17 00:00:00 2001
From: liu <liujiatong112@163.com>
Date: Mon, 5 Feb 2024 13:12:13 +0800
Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E9=9B=B7=E8=BE=BE=E5=9B=BE?=
 =?UTF-8?q?=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../AskDiagnosisResultController.java         |  14 +-
 .../supervision/pojo/vo/RadarChartResVO.java  |  20 ++
 .../service/AskDiagnosisResultService.java    |   5 +-
 .../impl/AskDiagnosisResultServiceImpl.java   | 171 +++++++++++++++++-
 4 files changed, 204 insertions(+), 6 deletions(-)
 create mode 100644 virtual-patient-web/src/main/java/com/supervision/pojo/vo/RadarChartResVO.java

diff --git a/virtual-patient-web/src/main/java/com/supervision/controller/AskDiagnosisResultController.java b/virtual-patient-web/src/main/java/com/supervision/controller/AskDiagnosisResultController.java
index 313e5b9e..e4245d1b 100644
--- a/virtual-patient-web/src/main/java/com/supervision/controller/AskDiagnosisResultController.java
+++ b/virtual-patient-web/src/main/java/com/supervision/controller/AskDiagnosisResultController.java
@@ -1,12 +1,14 @@
 package com.supervision.controller;
 
 import com.supervision.pojo.vo.DiagnosisResultResVO;
-import com.supervision.pojo.vo.FinishAskReqVO;
+import com.supervision.pojo.vo.RadarChartResVO;
 import com.supervision.service.AskDiagnosisResultService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.RequiredArgsConstructor;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
 
 @Api(tags = "评估详情")
 @RestController
@@ -18,7 +20,13 @@ public class AskDiagnosisResultController {
 
     @ApiOperation("查询最终诊断结果")
     @GetMapping("queryDiagnosisResult")
-    public DiagnosisResultResVO queryDiagnosisResult(String processId){
+    public DiagnosisResultResVO queryDiagnosisResult(String processId) {
         return askDiagnosisResultService.queryDiagnosisResult(processId);
     }
+
+    @ApiOperation("查询诊断结果的雷达图")
+    @GetMapping("queryRadarChart")
+    public RadarChartResVO queryRadarChart(String processId) {
+        return askDiagnosisResultService.queryRadarChart(processId);
+    }
 }
diff --git a/virtual-patient-web/src/main/java/com/supervision/pojo/vo/RadarChartResVO.java b/virtual-patient-web/src/main/java/com/supervision/pojo/vo/RadarChartResVO.java
new file mode 100644
index 00000000..99d7cf2d
--- /dev/null
+++ b/virtual-patient-web/src/main/java/com/supervision/pojo/vo/RadarChartResVO.java
@@ -0,0 +1,20 @@
+package com.supervision.pojo.vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class RadarChartResVO {
+
+    // 生成问诊雷达图
+    private BigDecimal askChart;
+    // 生成体格检查雷达图
+    private BigDecimal physicalChart;
+    // 生成辅助检查雷达图
+    private BigDecimal ancillaryChart;
+    // 生成处置计划雷达图
+    private BigDecimal treatmentPlanChart;
+    // 临床思维=前面几项平均值
+    private BigDecimal clinicalThinking;
+}
diff --git a/virtual-patient-web/src/main/java/com/supervision/service/AskDiagnosisResultService.java b/virtual-patient-web/src/main/java/com/supervision/service/AskDiagnosisResultService.java
index b76ce9e6..feb6da81 100644
--- a/virtual-patient-web/src/main/java/com/supervision/service/AskDiagnosisResultService.java
+++ b/virtual-patient-web/src/main/java/com/supervision/service/AskDiagnosisResultService.java
@@ -1,10 +1,11 @@
 package com.supervision.service;
 
 import com.supervision.pojo.vo.DiagnosisResultResVO;
-import com.supervision.pojo.vo.FinishAskReqVO;
-import org.springframework.web.bind.annotation.RequestBody;
+import com.supervision.pojo.vo.RadarChartResVO;
 
 public interface AskDiagnosisResultService {
 
     DiagnosisResultResVO queryDiagnosisResult(String processId);
+
+    RadarChartResVO queryRadarChart(String processId);
 }
diff --git a/virtual-patient-web/src/main/java/com/supervision/service/impl/AskDiagnosisResultServiceImpl.java b/virtual-patient-web/src/main/java/com/supervision/service/impl/AskDiagnosisResultServiceImpl.java
index 1f3a5429..47feeb7b 100644
--- a/virtual-patient-web/src/main/java/com/supervision/service/impl/AskDiagnosisResultServiceImpl.java
+++ b/virtual-patient-web/src/main/java/com/supervision/service/impl/AskDiagnosisResultServiceImpl.java
@@ -4,10 +4,12 @@ package com.supervision.service.impl;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.NumberUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
-import com.supervision.model.*;
+import com.supervision.exception.BusinessException;
 import com.supervision.model.Process;
+import com.supervision.model.*;
 import com.supervision.pojo.vo.*;
 import com.supervision.service.*;
 import com.supervision.vo.ask.TreatmentPlanRecordVo;
@@ -17,6 +19,8 @@ import com.supervision.vo.result.PhysicalRecordByResultDTO;
 import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.Function;
@@ -49,6 +53,10 @@ public class AskDiagnosisResultServiceImpl implements AskDiagnosisResultService
 
     private final DiseaseTreatmentPlanDrugService diseaseTreatmentPlanDrugService;
 
+    private final DiseasePhysicalService diseasePhysicalService;
+
+    private final DiseaseAncillaryService diseaseAncillaryService;
+
 
     @Override
     public DiagnosisResultResVO queryDiagnosisResult(String processId) {
@@ -284,4 +292,165 @@ public class AskDiagnosisResultServiceImpl implements AskDiagnosisResultService
 
     }
 
+    /**
+     * 生成雷达图
+     * <p>
+     * ( 用户命中病历配置问题数 / 病历问题总数 ) * (用户提问命中病历配置问题数 / 用户实际提问的数量 )
+     * <p>
+     * Q:是否要区分是否是正常的检查结果?
+     * A:雷达图 不管正常异常检查结果  只看该不该检查这个项目
+     * Q:该不该,指的是病历的配置项是吗?只要配置了,就是该检查的
+     * A:是的
+     *
+     * @param processId
+     */
+    @Override
+    public RadarChartResVO queryRadarChart(String processId) {
+        Process process = Optional.ofNullable(processService.getById(processId)).orElseThrow(() -> new BusinessException("未找到流程"));
+        // 生成问诊雷达图
+        BigDecimal askChart = computeAskChart(process);
+        // 生成体格检查雷达图
+        BigDecimal physicalChart = computePhysicalChart(process);
+        // 生成辅助检查雷达图
+        BigDecimal ancillaryChart = computeAncillaryChart(process);
+        // 生成处置计划雷达图
+        BigDecimal treatmentPlanChart = computeTreatmentPlanChart(process);
+        RadarChartResVO radarChartResVO = new RadarChartResVO();
+        radarChartResVO.setAskChart(askChart);
+        radarChartResVO.setPhysicalChart(physicalChart);
+        radarChartResVO.setAncillaryChart(ancillaryChart);
+        radarChartResVO.setTreatmentPlanChart(treatmentPlanChart);
+        BigDecimal clinicalThinking = NumberUtil.add(askChart, physicalChart, ancillaryChart, treatmentPlanChart).divide(BigDecimal.valueOf(4), 1, RoundingMode.HALF_UP);
+        radarChartResVO.setClinicalThinking(clinicalThinking);
+        return radarChartResVO;
+
+
+    }
+
+    /**
+     * 生成处置计划雷达图
+     * ( 用户命中病历治疗计划配置问题数 / 疾病配置的治疗计划总数 ) * (用户命中病历治疗计划配置问题数 / 用户实际填写的治疗计划的数量 )
+     */
+    private BigDecimal computeTreatmentPlanChart(Process process) {
+        // 查询用户填写的治疗计划
+        List<TreatmentPlanRecord> userTreatmentPlanRecordList = treatmentPlanRecordService.lambdaQuery().eq(TreatmentPlanRecord::getProcessId, process.getId()).list();
+        int userTreatmentPlanCount = userTreatmentPlanRecordList.size();
+        // 查询疾病配置的治疗计划
+        List<DiseaseTreatmentPlan> planList = diseaseTreatmentPlanService.lambdaQuery().eq(DiseaseTreatmentPlan::getDiseaseId, process.getDiseaseId()).select(DiseaseTreatmentPlan::getId).list();
+        List<String> planIdList = planList.stream().map(DiseaseTreatmentPlan::getId).collect(Collectors.toList());
+        // 疾病配置的治疗计划总数
+        int medicalCount = planIdList.size();
+        // 找到用户配置的药物计划
+        List<DiseaseTreatmentPlanDrug> drugList = diseaseTreatmentPlanDrugService.lambdaQuery().eq(DiseaseTreatmentPlanDrug::getDiseaseId, process.getDiseaseId()).select(DiseaseTreatmentPlanDrug::getDrugId).list();
+        List<String> drugIdList = drugList.stream().map(DiseaseTreatmentPlanDrug::getDrugId).collect(Collectors.toList());
+        int hitPlanCount = 0;
+        for (TreatmentPlanRecord treatmentPlanRecord : userTreatmentPlanRecordList) {
+            // 需要分别看是否是药物计划
+            if (StrUtil.isNotBlank(treatmentPlanRecord.getTreatmentPlanId()) && planIdList.contains(treatmentPlanRecord.getTreatmentPlanId())) {
+                hitPlanCount++;
+            }
+            if (StrUtil.isNotBlank(treatmentPlanRecord.getDrugId()) && drugIdList.contains(treatmentPlanRecord.getDrugId())) {
+                hitPlanCount++;
+            }
+        }
+        // 过程数据3:问诊vs问诊正确率
+        BigDecimal num3 = BigDecimal.ZERO;
+        if (userTreatmentPlanCount > 0) {
+            num3 = BigDecimal.valueOf(hitPlanCount).divide(BigDecimal.valueOf(userTreatmentPlanCount), 1, RoundingMode.HALF_UP);
+        }
+        // 过程数据2:问诊vs标准正确率
+        BigDecimal num2 = BigDecimal.ZERO;
+        if (medicalCount > 0) {
+            num2 = BigDecimal.valueOf(hitPlanCount).divide(BigDecimal.valueOf(medicalCount), 1, RoundingMode.HALF_UP);
+        }
+        return num2.multiply(num3);
+
+    }
+
+    /**
+     * 生成辅助检查雷达图
+     * ( 用户命中病历配置问题数 / 病历问题总数 ) * (用户提问命中病历配置问题数 / 用户实际提问的数量 )
+     */
+    private BigDecimal computeAncillaryChart(Process process) {
+        Integer userHitCount = diagnosisAncillaryRecordService.lambdaQuery().isNotNull(DiagnosisAncillaryRecord::getAncillaryId)
+                .eq(DiagnosisAncillaryRecord::getProcessId, process.getId()).count();
+        Integer userCount = diagnosisAncillaryRecordService.lambdaQuery().eq(DiagnosisAncillaryRecord::getProcessId, process.getId()).count();
+        Integer medicalCount = diseaseAncillaryService.lambdaQuery().eq(DiseaseAncillary::getDiseaseId, process.getDiseaseId()).count();
+        // 过程数据3:问诊vs问诊正确率
+        BigDecimal num3 = BigDecimal.ZERO;
+        if (userCount > 0) {
+            num3 = BigDecimal.valueOf(userHitCount).divide(BigDecimal.valueOf(userCount), 1, RoundingMode.HALF_UP);
+        }
+        // 过程数据2:问诊vs标准正确率
+        BigDecimal num2 = BigDecimal.ZERO;
+        if (medicalCount > 0) {
+            num2 = BigDecimal.valueOf(userHitCount).divide(BigDecimal.valueOf(medicalCount), 1, RoundingMode.HALF_UP);
+        }
+        return num2.multiply(num3);
+    }
+
+    /**
+     * 计算体格检查雷达图
+     * 2. 体格检查:( 用户命中病历配置问题数 / 病历问题总数 ) * (用户提问命中病历配置问题数 / 用户实际提问的数量 )
+     */
+    private BigDecimal computePhysicalChart(Process process) {
+        // 查询用户命中病历配置问题数
+        Integer userHitCount = diagnosisPhysicalRecordService.lambdaQuery().isNotNull(DiagnosisPhysicalRecord::getPhysicalId)
+                .eq(DiagnosisPhysicalRecord::getProcessId, process.getId()).count();
+        // 查询用户实际检查数量
+        Integer userCount = diagnosisPhysicalRecordService.lambdaQuery().eq(DiagnosisPhysicalRecord::getProcessId, process.getId()).count();
+        // 查询病例配置的数量
+        Integer medicalCount = diseasePhysicalService.lambdaQuery().eq(DiseasePhysical::getDiseaseId, process.getDiseaseId()).count();
+        // 过程数据3:问诊vs问诊正确率
+        BigDecimal num3 = BigDecimal.ZERO;
+        if (userCount > 0) {
+            num3 = BigDecimal.valueOf(userHitCount).divide(BigDecimal.valueOf(userCount), 1, RoundingMode.HALF_UP);
+        }
+        // 过程数据2:问诊vs标准正确率
+        BigDecimal num2 = BigDecimal.ZERO;
+        if (medicalCount > 0) {
+            num2 = BigDecimal.valueOf(userHitCount).divide(BigDecimal.valueOf(medicalCount), 1, RoundingMode.HALF_UP);
+        }
+        return num2.multiply(num3);
+    }
+
+
+    /**
+     * 生成问诊雷达图数据
+     * 1. 问诊: ( 用户提问命中病历配置问题数 / 病历问题总数 ) * (用户提问命中病历配置问题数 / 用户实际提问的数量 )
+     * 问诊vs标准正确率 * 问诊vs问诊正确率 = 综合正确率
+     * 上面的数量都是去重的,未识别出来的问题,不包含在用户提问的数据里面
+     * 默认语句不参与统计
+     */
+    public BigDecimal computeAskChart(Process process) {
+        // 首先查询用户提问的病历问题(这里questionId不为null,即为识别出来的用户问题)
+        List<DiagnosisQaRecord> qaRecordList = diagnosisQaRecordService.lambdaQuery().isNotNull(DiagnosisQaRecord::getQuestionLibraryId)
+                .eq(DiagnosisQaRecord::getProcessId, process.getId()).list();
+        // 用户实际提问数量(包含默认问题)
+        Set<String> userQuestionIdSet = qaRecordList.stream().map(DiagnosisQaRecord::getQuestionLibraryId).collect(Collectors.toSet());
+        // 查询病例配置的问题
+        List<AskPatientAnswer> answerList = askPatientAnswerService.lambdaQuery().eq(AskPatientAnswer::getMedicalId, process.getMedicalRecId()).list();
+        // 病历问题总数(统计非默认语句的病历问题总数)
+        long medicalQuestionCount = answerList.stream().filter(e -> ObjectUtil.isNotEmpty(e.getAnswerType()) && 1 == e.getAnswerType()).count();
+        // 用户实际提问的数量(去除默认问题)
+        Set<String> defaultqQuestionIdSet = answerList.stream().filter(e -> ObjectUtil.isNotEmpty(e.getAnswerType()) && 0 == e.getAnswerType()).map(AskPatientAnswer::getLibraryQuestionId).collect(Collectors.toSet());
+        userQuestionIdSet.removeAll(defaultqQuestionIdSet);
+        int userQuestionCount = userQuestionIdSet.size();
+        // 用户提问命中病历配置问题数(去除默认问题之后的交集)
+        Collection<String> intersection = CollUtil.intersection(defaultqQuestionIdSet, answerList.stream().map(AskPatientAnswer::getLibraryQuestionId).collect(Collectors.toSet()));
+        int userHitQuestionCount = intersection.size();
+
+        // 过程数据3:问诊vs问诊正确率
+        BigDecimal num3 = BigDecimal.ZERO;
+        if (userQuestionCount > 0) {
+            num3 = BigDecimal.valueOf(userHitQuestionCount).divide(BigDecimal.valueOf(userQuestionCount), 1, RoundingMode.HALF_UP);
+        }
+        // 过程数据2:问诊vs标准正确率
+        BigDecimal num2 = BigDecimal.ZERO;
+        if (medicalQuestionCount > 0) {
+            num2 = BigDecimal.valueOf(userHitQuestionCount).divide(BigDecimal.valueOf(medicalQuestionCount), 1, RoundingMode.HALF_UP);
+        }
+
+        return num2.multiply(num3);
+    }
 }