You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
virtual-patient/virtual-patient-web/src/main/java/com/supervision/service/impl/AskDiagnosisResultServiceIm...

614 lines
36 KiB
Java

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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.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;
import com.supervision.vo.manage.DiseaseAncillaryResVo;
import com.supervision.vo.manage.DiseasePhysicalResVo;
import com.supervision.vo.manage.DiseaseTreatmentPlanResVo;
import com.supervision.vo.result.AncillaryRecordByResultDTO;
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.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class AskDiagnosisResultServiceImpl implements AskDiagnosisResultService {
private final DiagnosisPrimaryService diagnosisPrimaryService;
private final AskPatientAnswerService askPatientAnswerService;
private final MedicalRecService medicalRecService;
private final DiagnosisQaRecordService diagnosisQaRecordService;
private final DiagnosisPhysicalRecordService diagnosisPhysicalRecordService;
private final DiagnosisAncillaryRecordService diagnosisAncillaryRecordService;
private final ProcessService processService;
private final ProcessEvaluationService processEvaluationService;
private final DiseaseService diseaseService;
private final TreatmentPlanRecordService treatmentPlanRecordService;
private final DiseaseTreatmentPlanService diseaseTreatmentPlanService;
private final DiseaseTreatmentPlanDrugService diseaseTreatmentPlanDrugService;
private final DiseasePhysicalService diseasePhysicalService;
private final DiseaseAncillaryService diseaseAncillaryService;
@Override
public DiagnosisResultResVO queryDiagnosisResult(String processId) {
DiagnosisResultResVO diagnosisResultResVO = new DiagnosisResultResVO();
diagnosisResultResVO.setId(processId);
Process process = processService.getById(processId);
MedicalRec medicalRec = medicalRecService.getById(process.getMedicalRecId());
List<Disease> diseasesList = diseaseService.listDiseaseNestIfComposite(medicalRec.getDiseaseId());
// 1.生成预期诊断结果
diagnosisResultResVO.setExpertDiagnosisResult(creatExpertDiagnosisResult(medicalRec, diseasesList, processId));
// 2.生成初步诊断依据
diagnosisResultResVO.setBasisPrimaryResultResVO(createBasisPrimaryResult(medicalRec, process));
// 3.生成证实诊断依据
diagnosisResultResVO.setBasisConfirmResultResVO(createBasisConfirmResult(medicalRec, processId));
// 4.生成鉴别诊断依据
diagnosisResultResVO.setBasisIdentificationResult(createBasisIdentificationResult(medicalRec, processId));
// 5.全面检查-(暂无相关数据) 后面再看
diagnosisResultResVO.setFullCheck(null);
// 6.处置方案
diagnosisResultResVO.setDealPlan(createDealPlan(process.getDiseaseId(), processId));
return diagnosisResultResVO;
}
private DealPlanResVO createDealPlan(String diseaseId, String processId) {
DealPlanResVO dealPlanResVO = new DealPlanResVO();
// 1. 查询处置计划记录
List<? extends TreatmentPlanRecord> treatmentPlanRecordList = treatmentPlanRecordService.queryByProcessId(processId);
if (CollectionUtil.isEmpty(treatmentPlanRecordList)) {
return dealPlanResVO;
}
// 2. 查询出疾病处置计划(疾病配置的处置计划)
List<DiseaseTreatmentPlanResVo> diseaseTreatmentPlanResVos = diseaseTreatmentPlanService.queryListByDiseaseId(diseaseId);
List<String> treatmentPlanId = diseaseTreatmentPlanResVos.stream().map(DiseaseTreatmentPlanResVo::getTreatmentPlanId).distinct().collect(Collectors.toList());
// 3. 查出疾病处置计划用药(疾病配置的用药计划)
List<DiseaseTreatmentPlanDrug> diseaseTreatmentPlanDrugList = diseaseTreatmentPlanDrugService.lambdaQuery().eq(DiseaseTreatmentPlanDrug::getDiseaseId, diseaseId).list();
List<String> drugIds = diseaseTreatmentPlanDrugList.stream().map(DiseaseTreatmentPlanDrug::getDrugId).distinct().collect(Collectors.toList());
// 4. 组装数据
ArrayList<TreatmentPlanRecordVo> drugTreatmentPlanResults = new ArrayList<>();
ArrayList<TreatmentPlanRecordVo> otherTreatmentPlanResults = new ArrayList<>();
for (TreatmentPlanRecord treatmentPlanRecord : treatmentPlanRecordList) {
TreatmentPlanRecordVo bean = BeanUtil.toBean(treatmentPlanRecord, TreatmentPlanRecordVo.class);
// 是否正确
boolean flag = StrUtil.isNotEmpty(bean.getDrugId()) ? drugIds.contains(bean.getDrugId()) : treatmentPlanId.contains(bean.getTreatmentPlanId());
bean.setFlag(flag ? 1 : 0);
if (StrUtil.isNotEmpty(bean.getDrugId())) {
drugTreatmentPlanResults.add(bean);
} else {
otherTreatmentPlanResults.add(bean);
}
}
dealPlanResVO.setUserTreatmentPlanType(CollectionUtil.getFirst(treatmentPlanRecordList).getDisposalMethod());
dealPlanResVO.setDrugTreatmentPlan(drugTreatmentPlanResults);
dealPlanResVO.setOtherTreatmentPlan(otherTreatmentPlanResults.stream().sorted(
Comparator.comparing(TreatmentPlanRecord::getDisposalPlan)).collect(Collectors.toList()));
return dealPlanResVO;
}
private BasisIdentificationResultResVO createBasisIdentificationResult(MedicalRec medicalRec, String processId) {
BasisIdentificationResultResVO basisIdentificationResultResVO = new BasisIdentificationResultResVO();
// 鉴别诊断依据,来自于medicalRec的DifferentialDiagnosisCriteria
basisIdentificationResultResVO.setIdentificationDiagnosis(medicalRec.getDifferentialDiagnosisCriteria());
// 2.2 获取体格检查
List<PhysicalRecordByResultDTO> physicalRecordList = diagnosisPhysicalRecordService.queryPhysicalResultByProcessId(processId);
List<DiseasePhysicalResVo> diseasePhysicalResVos = diseasePhysicalService.queryListByDiseaseId(medicalRec.getDiseaseId());
List<BasisDiagnosisNodeResVO> nodeList = physicalRecordMergeListsIdentification(physicalRecordList, diseasePhysicalResVos);
// 2.3 获取辅助检查
List<AncillaryRecordByResultDTO> ancillaryRecordList = diagnosisAncillaryRecordService.queryAncillaryResultByProcessId(processId);
List<DiseaseAncillaryResVo> diseaseAncillaryResVos = diseaseAncillaryService.queryListByDiseaseId(medicalRec.getDiseaseId());
nodeList.addAll(ancillaryRecordMergeListsIdentification(ancillaryRecordList, diseaseAncillaryResVos));
basisIdentificationResultResVO.setNodeList(nodeList);
return basisIdentificationResultResVO;
}
private BasisConfirmResultResVO createBasisConfirmResult(MedicalRec medicalRec, String processId) {
BasisConfirmResultResVO basisConfirmResultResVO = new BasisConfirmResultResVO();
// 证实诊断依据,来自于medicalRec的ConfirmDiagnosisCriteria
basisConfirmResultResVO.setConfirmingDiagnosis(medicalRec.getConfirmDiagnosisCriteria());
// 2.2 获取体格检查的证实诊断依据
List<PhysicalRecordByResultDTO> physicalRecordList = diagnosisPhysicalRecordService.queryPhysicalResultByProcessId(processId);
List<DiseasePhysicalResVo> diseasePhysicalResVos = diseasePhysicalService.queryListByDiseaseId(medicalRec.getDiseaseId());
List<BasisDiagnosisNodeResVO> nodeList = physicalRecordMergeListsConfirm(physicalRecordList, diseasePhysicalResVos);
// 2.3 获取辅助检查
List<AncillaryRecordByResultDTO> ancillaryRecordList = diagnosisAncillaryRecordService.queryAncillaryResultByProcessId(processId);
List<DiseaseAncillaryResVo> diseaseAncillaryResVos = diseaseAncillaryService.queryListByDiseaseId(medicalRec.getDiseaseId());
nodeList.addAll(ancillaryRecordMergeListsConfirm(ancillaryRecordList, diseaseAncillaryResVos));
basisConfirmResultResVO.setNodeList(nodeList);
return basisConfirmResultResVO;
}
private BasisPrimaryResultResVO createBasisPrimaryResult(MedicalRec medicalRec, Process process) {
BasisPrimaryResultResVO basisPrimaryResultResVO = new BasisPrimaryResultResVO();
// 初步诊断依据 vp_medical_rec的primarily_diagnosis_criteria
basisPrimaryResultResVO.setPreliminaryDiagnosis(medicalRec.getPrimarilyDiagnosisCriteria());
// 根据record记录寻找符合初步诊断依据的项目
// 2.1 首先获取对话
List<DiagnosisQaRecord> qaRecordList = diagnosisQaRecordService.lambdaQuery().eq(DiagnosisQaRecord::getProcessId, process.getId()).list();
List<AskPatientAnswer> list = askPatientAnswerService.lambdaQuery()
.eq(AskPatientAnswer::getMedicalId, medicalRec.getId()).list();
// 获取配置了答案的项目(配置了答案的,认为是正确,没有配置答案的,走默认回答的,不标记为以正确)
List<BasisDiagnosisNodeResVO> basisDiagnosisNodeResVOS = new ArrayList<>(qaRecordMergeListsBasisPrimary(qaRecordList, list));
// 2.2 获取体格检查
List<PhysicalRecordByResultDTO> physicalRecordList = diagnosisPhysicalRecordService.queryPhysicalResultByProcessId(process.getId());
List<DiseasePhysicalResVo> diseasePhysicalResVos = diseasePhysicalService.queryListByDiseaseId(medicalRec.getDiseaseId());
basisDiagnosisNodeResVOS.addAll(physicalRecordMergeListsBasisPrimary(physicalRecordList, diseasePhysicalResVos));
// 2.3 获取辅助检查
List<AncillaryRecordByResultDTO> ancillaryRecordList = diagnosisAncillaryRecordService.queryAncillaryResultByProcessId(process.getId());
List<DiseaseAncillaryResVo> diseaseAncillaryResVos = diseaseAncillaryService.queryListByDiseaseId(medicalRec.getDiseaseId());
basisDiagnosisNodeResVOS.addAll(ancillaryRecordMergeListsBasisPrimary(ancillaryRecordList, diseaseAncillaryResVos));
basisPrimaryResultResVO.setNodeList(basisDiagnosisNodeResVOS);
return basisPrimaryResultResVO;
}
private List<BasisDiagnosisNodeResVO> qaRecordMergeListsBasisPrimary(List<DiagnosisQaRecord> qaRecordList, List<AskPatientAnswer> list) {
BiFunction<DiagnosisQaRecord, AskPatientAnswer, Boolean> biFunction = (qaRecord, qa) -> qa.getLibraryQuestionId().equals(qaRecord.getQuestionLibraryId());
list = list.stream().filter(item -> !Integer.valueOf("0").equals(item.getAnswerType())).collect(Collectors.toList());
Set<String> requireCheckIdSet = list.stream().map(AskPatientAnswer::getId).collect(Collectors.toSet());
Function<DiagnosisQaRecord, BasisDiagnosisNodeResVO> t1 = r -> new BasisDiagnosisNodeResVO(0, r.getQuestion(), r.getId(),
requireCheckIdSet.contains(r.getAnswerId()) ? 1 : 0);
Function<AskPatientAnswer, BasisDiagnosisNodeResVO> t2 = item -> new BasisDiagnosisNodeResVO(0, item.getQuestion(), item.getId(), 0);
return mergeListsBasedOnCondition(qaRecordList, list, biFunction, t1, t2);
}
private List<BasisDiagnosisNodeResVO> physicalRecordMergeLists(List<PhysicalRecordByResultDTO> physicalRecordList,
List<DiseasePhysicalResVo> diseasePhysicalResVos,
Function<PhysicalRecordByResultDTO, Integer> functionCorrect) {
physicalRecordList = physicalRecordList.stream()
.filter(distinctPredicateNotNull(PhysicalRecordByResultDTO::getToolLocationName)).collect(Collectors.toList());
// 工具id相等且 位置为空或者位置id相等
BiFunction<PhysicalRecordByResultDTO, DiseasePhysicalResVo, Boolean> biFunction = (r, diseasePhysical) -> StrUtil.equals(diseasePhysical.getToolId(), r.getToolId())
&& ((StrUtil.isEmpty(diseasePhysical.getLocationId()) && StrUtil.isEmpty(diseasePhysical.getLocationId()))
|| StrUtil.equals(diseasePhysical.getLocationId(), (r.getLocationId())));
Function<PhysicalRecordByResultDTO, BasisDiagnosisNodeResVO> t1 = r -> new BasisDiagnosisNodeResVO(1, r.getToolLocationName(),
r.getRecordId(), functionCorrect.apply(r));
// 这里的recordId只为了展示用diseasePhysical.getId()代替。只是为展示使用correct的值固定为不正确
Function<DiseasePhysicalResVo, BasisDiagnosisNodeResVO> t2 = diseasePhysical -> new BasisDiagnosisNodeResVO(1,
diseasePhysical.getToolName() + (StrUtil.isEmpty(diseasePhysical.getLocationName()) ? "" : "|" + diseasePhysical.getLocationName()),
diseasePhysical.getId(), 0);
return mergeListsBasedOnCondition(physicalRecordList, diseasePhysicalResVos, biFunction, t1, t2);
}
private List<BasisDiagnosisNodeResVO> ancillaryRecordMergeLists(List<AncillaryRecordByResultDTO> ancillaryRecordList,
List<DiseaseAncillaryResVo> diseaseAncillaryResVos,
Function<AncillaryRecordByResultDTO, Integer> functionCorrect) {
ancillaryRecordList = ancillaryRecordList.stream()
.filter(distinctPredicateNotNull(AncillaryRecordByResultDTO::getItemName)).collect(Collectors.toList());
BiFunction<AncillaryRecordByResultDTO, DiseaseAncillaryResVo, Boolean> biFunction = (r, diseaseAncillary) -> StrUtil.equals(diseaseAncillary.getItemId(), r.getItemId());
Function<AncillaryRecordByResultDTO, BasisDiagnosisNodeResVO> t1 = record -> new BasisDiagnosisNodeResVO(2, record.getItemName(), record.getRecordId(),
functionCorrect.apply(record));
// 这里的recordId只为了展示用diseaseAncillary.getId()代替。只是为展示使用correct的值固定为不正确
Function<DiseaseAncillaryResVo, BasisDiagnosisNodeResVO> t2 = diseaseAncillary -> new BasisDiagnosisNodeResVO(2, diseaseAncillary.getItemName(),
diseaseAncillary.getId(), 0);
return mergeListsBasedOnCondition(ancillaryRecordList, diseaseAncillaryResVos, biFunction, t1, t2);
}
private List<BasisDiagnosisNodeResVO> physicalRecordMergeListsBasisPrimary(List<PhysicalRecordByResultDTO> physicalRecordList,
List<DiseasePhysicalResVo> diseasePhysicalResVos) {
diseasePhysicalResVos = diseasePhysicalResVos.stream()
.filter(diseasePhysicalResVo -> Integer.valueOf(1).equals(diseasePhysicalResVo.getPrimarilyDiagnosisCriteriaFlag())).collect(Collectors.toList());
return physicalRecordMergeLists(physicalRecordList, diseasePhysicalResVos, PhysicalRecordByResultDTO::getPrimarilyDiagnosisCriteriaFlag);
}
private List<BasisDiagnosisNodeResVO> physicalRecordMergeListsConfirm(List<PhysicalRecordByResultDTO> physicalRecordList,
List<DiseasePhysicalResVo> diseasePhysicalResVos) {
Function<PhysicalRecordByResultDTO, Integer> functionCorrect = record -> (ObjectUtil.isNotNull(record.getBasisConfirm()) && 1 == record.getBasisConfirm()
&& Objects.equals(record.getBasisConfirm(), record.getRecordBasisConfirmFlag())) ? 1 : 0;
diseasePhysicalResVos = diseasePhysicalResVos.stream()
.filter(diseasePhysicalResVo -> Integer.valueOf(1).equals(diseasePhysicalResVo.getBasisConfirmFlag())).collect(Collectors.toList());
return physicalRecordMergeLists(physicalRecordList, diseasePhysicalResVos, functionCorrect);
}
private List<BasisDiagnosisNodeResVO> physicalRecordMergeListsIdentification(List<PhysicalRecordByResultDTO> physicalRecordList,
List<DiseasePhysicalResVo> diseasePhysicalResVos) {
Function<PhysicalRecordByResultDTO, Integer> functionCorrect = record -> (Integer.valueOf(1).equals(record.getBasisIdentification())
&& Objects.equals(record.getBasisIdentification(), record.getRecordBasisIdentificationFlag())) ? 1 : 0;
diseasePhysicalResVos = diseasePhysicalResVos.stream()
.filter(diseasePhysicalResVo -> Integer.valueOf(1).equals(diseasePhysicalResVo.getBasisIdentificationFlag())).collect(Collectors.toList());
return physicalRecordMergeLists(physicalRecordList, diseasePhysicalResVos, functionCorrect);
}
private List<BasisDiagnosisNodeResVO> ancillaryRecordMergeListsBasisPrimary(List<AncillaryRecordByResultDTO> ancillaryRecordList,
List<DiseaseAncillaryResVo> diseaseAncillaryResVos) {
diseaseAncillaryResVos = diseaseAncillaryResVos.stream()
.filter(diseaseAncillaryResVo -> Integer.valueOf(1).equals(diseaseAncillaryResVo.getPrimarilyDiagnosisCriteriaFlag())).collect(Collectors.toList());
return ancillaryRecordMergeLists(ancillaryRecordList, diseaseAncillaryResVos,
AncillaryRecordByResultDTO::getPrimarilyDiagnosisCriteriaFlag);
}
private List<BasisDiagnosisNodeResVO> ancillaryRecordMergeListsConfirm(List<AncillaryRecordByResultDTO> ancillaryRecordList,
List<DiseaseAncillaryResVo> diseaseAncillaryResVos) {
Function<AncillaryRecordByResultDTO, Integer> functionCorrect = record -> ObjectUtil.isNotNull(record.getBasisConfirm()) && 1 == record.getBasisConfirm()
&& Objects.equals(record.getBasisConfirm(), record.getRecordBasisConfirmFlag()) ? 1 : 0;
diseaseAncillaryResVos = diseaseAncillaryResVos.stream()
.filter(diseaseAncillaryResVo -> Integer.valueOf(1).equals(diseaseAncillaryResVo.getBasisConfirmFlag())).collect(Collectors.toList());
return ancillaryRecordMergeLists(ancillaryRecordList, diseaseAncillaryResVos, functionCorrect);
}
private List<BasisDiagnosisNodeResVO> ancillaryRecordMergeListsIdentification(List<AncillaryRecordByResultDTO> ancillaryRecordList,
List<DiseaseAncillaryResVo> diseaseAncillaryResVos) {
Function<AncillaryRecordByResultDTO, Integer> functionCorrect = record -> (Integer.valueOf(1).equals(record.getBasisIdentification())
&& Objects.equals(record.getBasisIdentification(), record.getRecordBasisIdentificationFlag())) ? 1 : 0;
diseaseAncillaryResVos = diseaseAncillaryResVos.stream()
.filter(diseaseAncillaryResVo -> Integer.valueOf(1).equals(diseaseAncillaryResVo.getBasisIdentificationFlag())).collect(Collectors.toList());
return ancillaryRecordMergeLists(ancillaryRecordList, diseaseAncillaryResVos, functionCorrect);
}
/**
* 根据指定条件合并两个列表。
*
* @param simpleList 要处理的简单列表。
* @param poolList 用于比较的池列表。
* @param biFunction 定义合并元素条件。
* @param t1 用于处理简单列表中元素的函数。
* @param t2 用于处理池列表中元素的函数。
* @return 包含根据条件合并的元素的列表。
*/
private <T, M, R> List<R> mergeListsBasedOnCondition(List<T> simpleList, List<M> poolList,
BiFunction<T, M, Boolean> biFunction,
Function<T, R> t1, Function<M, R> t2) {
List<R> rs = new ArrayList<>();
// 检查两个列表是否都为空,在这种情况下返回空列表
if (CollUtil.isEmpty(simpleList) && CollUtil.isEmpty(poolList)) {
return CollUtil.newArrayList();
}
// 如果简单列表为空但池列表不为空,则映射和收集池列表元素
if (CollUtil.isEmpty(simpleList) && CollUtil.isNotEmpty(poolList)) {
return poolList.stream().map(t2).collect(Collectors.toList());
}
// 根据定义的条件合并列表
for (M m : poolList) {
boolean find = false;
for (T t : simpleList) {
if (biFunction.apply(t, m)) {
rs.add(t1.apply(t));
find = true;
break;
}
}
if (!find) {
rs.add(t2.apply(m));
}
}
return rs;
}
/**
* 预期诊断结果
*/
private ExpertDiagnosisResultResVO creatExpertDiagnosisResult(MedicalRec medicalRec, List<Disease> diseasesList, String processId) {
ExpertDiagnosisResultResVO expertDiagnosisResultResVO = new ExpertDiagnosisResultResVO();
expertDiagnosisResultResVO.setDiagnosis(diseasesList.stream().map(Disease::getDiseaseNameAlias).collect(Collectors.joining(";")));
Set<String> expertDiseaseIdSet = diseasesList.stream().map(Disease::getId).collect(Collectors.toSet());
// 从vp_diagnosis_primary中找到确认诊断时,确认的
List<DiagnosisPrimary> userPrimaryDiseaseList = diagnosisPrimaryService.lambdaQuery()
.eq(DiagnosisPrimary::getProcessId, processId)
// 1确诊
.eq(DiagnosisPrimary::getExcludeFlag, 1).list();
List<Disease> userDiagnosisDiseaseList = CollUtil.isEmpty(userPrimaryDiseaseList) ? CollUtil.newArrayList()
: diseaseService.listByIds(userPrimaryDiseaseList.stream().map(DiagnosisPrimary::getPrimaryDiagnosisId).collect(Collectors.toList()));
// 用户的诊断
expertDiagnosisResultResVO.setUserDiagnosisResult(userDiagnosisDiseaseList.stream().map(e -> {
DiagnosisDiseaseResultNodeVO userNode = new DiagnosisDiseaseResultNodeVO();
userNode.setDiseaseName(e.getDiseaseNameAlias());
// 如果用户诊断在预期诊断里面,则正确,否则错误
userNode.setCorrect(expertDiseaseIdSet.contains(e.getId()) ? 1 : 0);
userNode.setDiseaseId(e.getId());
return userNode;
}).collect(Collectors.toList()));
// 预期诊断
expertDiagnosisResultResVO.setExpertDiagnosisResult(diseasesList.stream().map(e -> {
DiagnosisDiseaseResultNodeVO node = new DiagnosisDiseaseResultNodeVO();
node.setDiseaseName(e.getDiseaseNameAlias());
node.setDiseaseId(e.getId());
return node;
}).collect(Collectors.toList()));
return expertDiagnosisResultResVO;
}
public static <K> Predicate<K> distinctPredicateNotNull(Function<K, Object> function) {
ConcurrentHashMap<Object, Boolean> map = new ConcurrentHashMap<>();
// 根据key进行去重,并排除为null的数据
return t -> null != function.apply(t) && null == map.putIfAbsent(function.apply(t), true);
}
/**
* 生成雷达图
* <p>
* ( 用户命中病历配置问题数 / 病历问题总数 ) * (用户提问命中病历配置问题数 / 用户实际提问的数量 )
* <p>
* Q:是否要区分是否是正常的检查结果?
* A:雷达图 不管正常异常检查结果 只看该不该检查这个项目
* Q:该不该,指的是病历的配置项是吗?只要配置了,就是该检查的
* A:是的
*
* @param processId
*/
@Override
public RadarChartResVO queryRadarChart(String processId) {
Process process = Optional.ofNullable(processService.getById(processId)).orElseThrow(() -> new BusinessException("未找到流程"));
// 生成问诊雷达图
ChartNodeVO askChart = computeAskChart(process);
// 生成体格检查雷达图
ChartNodeVO physicalChart = computePhysicalChart(process);
// 生成辅助检查雷达图
ChartNodeVO ancillaryChart = computeAncillaryChart(process);
// 生成处置计划雷达图
ChartNodeVO treatmentPlanChart = computeTreatmentPlanChart(process);
RadarChartResVO radarChartResVO = new RadarChartResVO();
radarChartResVO.setAskChart(askChart);
radarChartResVO.setPhysicalChart(physicalChart);
radarChartResVO.setAncillaryChart(ancillaryChart);
radarChartResVO.setTreatmentPlanChart(treatmentPlanChart);
BigDecimal clinicalThinking = NumberUtil.add(askChart.getNodePer(), physicalChart.getNodePer(), ancillaryChart.getNodePer(), treatmentPlanChart.getNodePer()).divide(BigDecimal.valueOf(4), 1, RoundingMode.HALF_UP);
ChartNodeVO chartNodeVO = new ChartNodeVO();
chartNodeVO.setNodePer(clinicalThinking);
chartNodeVO.setScoreLevel(chartNodeVO.computeScoreLevel());
chartNodeVO.setTotal(NumberUtil.add(askChart.getTotal(), physicalChart.getTotal(), ancillaryChart.getTotal(), treatmentPlanChart.getTotal()).intValue());
chartNodeVO.setCorrect(NumberUtil.add(askChart.getCorrect(), physicalChart.getCorrect(), ancillaryChart.getCorrect(), treatmentPlanChart.getCorrect()).intValue());
chartNodeVO.setUnCorrect(NumberUtil.add(askChart.getUnCorrect(), physicalChart.getUnCorrect(), ancillaryChart.getUnCorrect(), treatmentPlanChart.getUnCorrect()).intValue());
chartNodeVO.setStandard(NumberUtil.add(askChart.getStandard(), physicalChart.getStandard(), ancillaryChart.getStandard(), treatmentPlanChart.getStandard()).intValue());
radarChartResVO.setClinicalThinking(chartNodeVO);
// 查询考核评估内容
ProcessEvaluation processEvaluation = processEvaluationService.lambdaQuery().eq(ProcessEvaluation::getProcessId, processId).one();
radarChartResVO.setProcessEvaluation(processEvaluation);
return radarChartResVO;
}
/**
* 生成处置计划雷达图
* ( 用户命中病历治疗计划配置问题数 / 疾病配置的治疗计划总数 ) * (用户命中病历治疗计划配置问题数 / 用户实际填写的治疗计划的数量 )
*/
private ChartNodeVO computeTreatmentPlanChart(Process process) {
// 查询用户填写的治疗计划(包含处置计划和用药计划)
List<TreatmentPlanRecord> userTreatmentPlanRecordList = treatmentPlanRecordService.lambdaQuery().eq(TreatmentPlanRecord::getProcessId, process.getId()).list();
int userTreatmentPlanCount = userTreatmentPlanRecordList.size();
// 2. 查询出疾病处置计划(疾病配置的处置计划)
List<DiseaseTreatmentPlanResVo> diseaseTreatmentPlanResVos = diseaseTreatmentPlanService.queryListByDiseaseId(process.getDiseaseId());
Set<String> treatmentPlanIdSet = diseaseTreatmentPlanResVos.stream().map(DiseaseTreatmentPlanResVo::getTreatmentPlanId).collect(Collectors.toSet());
// 3. 查出疾病处置计划用药(疾病配置的用药计划)
List<DiseaseTreatmentPlanDrug> diseaseTreatmentPlanDrugList = diseaseTreatmentPlanDrugService.lambdaQuery().eq(DiseaseTreatmentPlanDrug::getDiseaseId, process.getDiseaseId()).list();
Set<String> drugIdSet = diseaseTreatmentPlanDrugList.stream().map(DiseaseTreatmentPlanDrug::getDrugId).collect(Collectors.toSet());
// 计算总数时,只看疾病配置的处置计划(用药计划来自于处置计划)
int medicalCount = diseaseTreatmentPlanResVos.size();
// 疾病配置的治疗计划ID集合,用来计算命中的数量
Collection<String> planIdSet = CollUtil.union(treatmentPlanIdSet, drugIdSet);
int hitPlanCount = 0;
for (TreatmentPlanRecord treatmentPlanRecord : userTreatmentPlanRecordList) {
// 需要分别看是否是药物计划
if (StrUtil.isNotBlank(treatmentPlanRecord.getTreatmentPlanId()) && planIdSet.contains(treatmentPlanRecord.getTreatmentPlanId())) {
hitPlanCount++;
continue;
}
if (StrUtil.isNotBlank(treatmentPlanRecord.getDrugId()) && planIdSet.contains(treatmentPlanRecord.getDrugId())) {
hitPlanCount++;
}
}
// 过程数据3问诊vs问诊正确率
BigDecimal num3 = BigDecimal.ZERO;
if (userTreatmentPlanCount > 0) {
num3 = BigDecimal.valueOf(hitPlanCount).divide(BigDecimal.valueOf(userTreatmentPlanCount), 2, RoundingMode.HALF_UP);
}
// 过程数据2问诊vs标准正确率
BigDecimal num2 = BigDecimal.ZERO;
if (medicalCount > 0) {
num2 = BigDecimal.valueOf(hitPlanCount).divide(BigDecimal.valueOf(medicalCount), 2, RoundingMode.HALF_UP);
}
ChartNodeVO chartNodeVO = new ChartNodeVO();
chartNodeVO.setNodePer(num2.multiply(num3).multiply(BigDecimal.valueOf(100)));
chartNodeVO.setScoreLevel(chartNodeVO.computeScoreLevel());
chartNodeVO.setCorrect(hitPlanCount);
chartNodeVO.setUnCorrect(medicalCount - hitPlanCount);
chartNodeVO.setStandard(medicalCount);
chartNodeVO.setTotal(NumberUtil.add(chartNodeVO.getUnCorrect(), chartNodeVO.getStandard(), chartNodeVO.getCorrect()).intValue());
return chartNodeVO;
}
/**
* 生成辅助检查雷达图
* ( 用户命中病历配置问题数 / 病历问题总数 ) * (用户提问命中病历配置问题数 / 用户实际提问的数量 )
*/
private ChartNodeVO computeAncillaryChart(Process process) {
Long userHitCount = diagnosisAncillaryRecordService.lambdaQuery().isNotNull(DiagnosisAncillaryRecord::getAncillaryId)
.eq(DiagnosisAncillaryRecord::getProcessId, process.getId()).count();
Long userCount = diagnosisAncillaryRecordService.lambdaQuery().eq(DiagnosisAncillaryRecord::getProcessId, process.getId()).count();
Long 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), 2, RoundingMode.HALF_UP);
}
// 过程数据2问诊vs标准正确率
BigDecimal num2 = BigDecimal.ZERO;
if (medicalCount > 0) {
num2 = BigDecimal.valueOf(userHitCount).divide(BigDecimal.valueOf(medicalCount), 2, RoundingMode.HALF_UP);
}
ChartNodeVO chartNodeVO = new ChartNodeVO();
chartNodeVO.setNodePer(num2.multiply(num3).multiply(BigDecimal.valueOf(100)));
chartNodeVO.setScoreLevel(chartNodeVO.computeScoreLevel());
chartNodeVO.setCorrect(Math.toIntExact(userHitCount));
chartNodeVO.setUnCorrect((int) (medicalCount - userHitCount));
chartNodeVO.setStandard(Math.toIntExact(medicalCount));
chartNodeVO.setTotal(NumberUtil.add(chartNodeVO.getUnCorrect(), chartNodeVO.getStandard(), chartNodeVO.getCorrect()).intValue());
return chartNodeVO;
}
/**
* 计算体格检查雷达图
* 2. 体格检查:( 用户命中病历配置问题数 / 病历问题总数 ) * (用户提问命中病历配置问题数 / 用户实际提问的数量 )
*/
private ChartNodeVO computePhysicalChart(Process process) {
// 查询用户命中病历配置问题数
Long userHitCount = diagnosisPhysicalRecordService.lambdaQuery().isNotNull(DiagnosisPhysicalRecord::getPhysicalId)
.eq(DiagnosisPhysicalRecord::getProcessId, process.getId()).count();
// 查询用户实际检查数量
Long userCount = diagnosisPhysicalRecordService.lambdaQuery().eq(DiagnosisPhysicalRecord::getProcessId, process.getId()).count();
// 查询病例配置的数量
Long 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), 2, RoundingMode.HALF_UP);
}
// 过程数据2问诊vs标准正确率
BigDecimal num2 = BigDecimal.ZERO;
if (medicalCount > 0) {
num2 = BigDecimal.valueOf(userHitCount).divide(BigDecimal.valueOf(medicalCount), 2, RoundingMode.HALF_UP);
}
ChartNodeVO chartNodeVO = new ChartNodeVO();
chartNodeVO.setNodePer(num2.multiply(num3).multiply(BigDecimal.valueOf(100)));
chartNodeVO.setScoreLevel(chartNodeVO.computeScoreLevel());
chartNodeVO.setCorrect(Math.toIntExact(userHitCount));
chartNodeVO.setUnCorrect((int) (medicalCount - userHitCount));
chartNodeVO.setStandard(Math.toIntExact(medicalCount));
chartNodeVO.setTotal(NumberUtil.add(chartNodeVO.getUnCorrect(), chartNodeVO.getStandard(), chartNodeVO.getCorrect()).intValue());
return chartNodeVO;
}
/**
* 生成问诊雷达图数据
* 1. 问诊: ( 用户提问命中病历配置问题数 / 病历问题总数 ) * (用户提问命中病历配置问题数 / 用户实际提问的数量 )
* 问诊vs标准正确率 * 问诊vs问诊正确率 = 综合正确率
* 上面的数量都是去重的,未识别出来的问题,不包含在用户提问的数据里面
* 默认语句不参与统计
*/
public ChartNodeVO 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();
// 用户提问命中病历配置问题数(去除默认问题之后的数量)
userQuestionIdSet.removeAll(defaultqQuestionIdSet);
int userHitQuestionCount = userQuestionIdSet.size();
// 过程数据3问诊vs问诊正确率
BigDecimal num3 = BigDecimal.ZERO;
if (userQuestionCount > 0) {
num3 = BigDecimal.valueOf(userHitQuestionCount).divide(BigDecimal.valueOf(userQuestionCount), 2, RoundingMode.HALF_UP);
}
// 过程数据2问诊vs标准正确率
BigDecimal num2 = BigDecimal.ZERO;
if (medicalQuestionCount > 0) {
num2 = BigDecimal.valueOf(userHitQuestionCount).divide(BigDecimal.valueOf(medicalQuestionCount), 2, RoundingMode.HALF_UP);
}
ChartNodeVO chartNodeVO = new ChartNodeVO();
chartNodeVO.setNodePer(num2.multiply(num3).multiply(BigDecimal.valueOf(100)));
chartNodeVO.setScoreLevel(chartNodeVO.computeScoreLevel());
chartNodeVO.setCorrect(userHitQuestionCount);
chartNodeVO.setStandard(Integer.parseInt(String.valueOf(medicalQuestionCount)));
chartNodeVO.setUnCorrect(NumberUtil.sub(chartNodeVO.getStandard(), chartNodeVO.getCorrect()).intValue());
chartNodeVO.setTotal(NumberUtil.add(chartNodeVO.getUnCorrect(), chartNodeVO.getStandard(), chartNodeVO.getCorrect()).intValue());
return chartNodeVO;
}
}