|
|
|
@ -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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|