|
@@ -0,0 +1,280 @@
|
|
|
+package com.lantone.qc.kernel.catalogue.threelevelward;
|
|
|
+
|
|
|
+import com.google.common.collect.Lists;
|
|
|
+import com.google.common.collect.Maps;
|
|
|
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
|
|
|
+import com.lantone.qc.kernel.util.CatalogueUtil;
|
|
|
+import com.lantone.qc.kernel.util.SimilarityUtil;
|
|
|
+import com.lantone.qc.pub.model.InputInfo;
|
|
|
+import com.lantone.qc.pub.model.OutputInfo;
|
|
|
+import com.lantone.qc.pub.model.doc.DoctorAdviceDoc;
|
|
|
+import com.lantone.qc.pub.model.doc.LeaveHospitalDoc;
|
|
|
+import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
|
|
|
+import com.lantone.qc.pub.model.doc.operation.OperationDiscussionDoc;
|
|
|
+import com.lantone.qc.pub.model.doc.operation.OperationDoc;
|
|
|
+import com.lantone.qc.pub.model.entity.Drug;
|
|
|
+import com.lantone.qc.pub.model.label.LeaveHospitalLabel;
|
|
|
+import com.lantone.qc.pub.model.label.ThreeLevelWardLabel;
|
|
|
+import com.lantone.qc.pub.util.DateUtil;
|
|
|
+import com.lantone.qc.pub.util.StringUtil;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+
|
|
|
+import java.util.*;
|
|
|
+import java.util.regex.Matcher;
|
|
|
+import java.util.regex.Pattern;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @author HUJING
|
|
|
+ * @create 2020-08-28 14:10
|
|
|
+ * @desc 病程中未记录抗生素用量
|
|
|
+ **/
|
|
|
+@Component
|
|
|
+public class THR03077 extends QCCatalogue {
|
|
|
+ @Autowired
|
|
|
+ SimilarityUtil similarityUtil;
|
|
|
+
|
|
|
+ public void start(InputInfo inputInfo, OutputInfo outputInfo) {
|
|
|
+ status.set("0");
|
|
|
+ List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
|
|
|
+ List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
|
|
|
+ List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
|
|
|
+ LeaveHospitalDoc leaveHospitalDoc = inputInfo.getLeaveHospitalDoc();
|
|
|
+ if (doctorAdviceDocs.size() == 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //抗生素及开医嘱时间(包括加用过抗生素的时间) key:抗生素名 "2020-08-20,2020-08-21 ..."
|
|
|
+ Map<String, List<String>> antibioticDate = Maps.newHashMap();
|
|
|
+ //抗生素加用集合 key:抗生素名 value: 0:未加用,1及以上:加用次数
|
|
|
+ Map<String, Integer> antibioticStatus = Maps.newHashMap();
|
|
|
+ //抗生素及各初始剂量 key:抗生素名 value:抗生素第一次使用时剂量
|
|
|
+ Map<String, List<Double>> antibioticValue = Maps.newHashMap();
|
|
|
+
|
|
|
+ List<Map<String, String>> docAdvStruct = doctorAdviceDocs
|
|
|
+ .stream()
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ .map(DoctorAdviceDoc::getStructureMap)
|
|
|
+ .filter(x -> StringUtil.isNotBlank(x.get("药品类型")) && x.get("药品类型").contains("抗生素") && StringUtil.isNotBlank(x.get("医嘱单次剂量")))
|
|
|
+ .filter(x -> StringUtil.isNotBlank(x.get("医嘱状态判别")) && !x.get("医嘱状态判别").contains("已停止"))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ String drugName = null, value = null, startDateStr = null;
|
|
|
+ for (Map<String, String> structMap : docAdvStruct) {
|
|
|
+ drugName = structMap.get("医嘱项目名称");
|
|
|
+ value = structMap.get("医嘱单次剂量");
|
|
|
+ startDateStr = structMap.get("医嘱开始时间");
|
|
|
+ drugName = removeBracket(drugName);
|
|
|
+ collectAntibioticInfo(antibioticDate, antibioticStatus, antibioticValue, drugName, value, startDateStr);
|
|
|
+ }
|
|
|
+
|
|
|
+ //把抗生素没加用过的抗生素删除
|
|
|
+ for (Map.Entry<String, Integer> as : antibioticStatus.entrySet()) {
|
|
|
+ if (as.getValue() == 0) {
|
|
|
+ antibioticDate.remove(as.getKey());
|
|
|
+ antibioticValue.remove(as.getKey());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //抗生素加用过的集合如果为空,则一个抗生素都没有加用过,直接返回0
|
|
|
+ if (antibioticDate.size() == 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ //病程记录中没有用量的抗生素及查房时间 key:抗生素名 "2020-08-20,2020-08-21 ..."
|
|
|
+ Map<String, List<String>> antibioticDateCourse = Maps.newHashMap();
|
|
|
+ String dateStr = null;
|
|
|
+ /*********************************************查房记录********************************************************/
|
|
|
+ if (threeLevelWardDocs.size() > 0) {
|
|
|
+ List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
|
|
|
+ for (ThreeLevelWardDoc doc : allDoctorWradDocs) {
|
|
|
+ if (doc.getThreeLevelWardLabel().size() == 0) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ dateStr = doc.getStructureMap().get("查房日期");
|
|
|
+ ThreeLevelWardLabel label = doc.getThreeLevelWardLabel().get(0);
|
|
|
+ List<Drug> drugs = label.getDrugs();
|
|
|
+ getCourseDrugInfo(antibioticDateCourse, dateStr, drugs);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /*********************************************术后首程********************************************************/
|
|
|
+ if (operationDocs.size() > 0) {
|
|
|
+ List<OperationDiscussionDoc> operationDiscussionDocs = operationDocs
|
|
|
+ .stream()
|
|
|
+ .map(OperationDoc::getOperationDiscussionDoc)
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ .filter(x -> x.getOperationDiscussionLabel() != null)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ for (OperationDiscussionDoc discussionDoc : operationDiscussionDocs) {
|
|
|
+ dateStr = discussionDoc.getStructureMap().get("记录日期");
|
|
|
+ if (StringUtil.isBlank(dateStr)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ List<Drug> drugs = discussionDoc.getOperationDiscussionLabel().getDrugs();
|
|
|
+ getCourseDrugInfo(antibioticDateCourse, dateStr, drugs);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /*********************************************出院小结********************************************************/
|
|
|
+ if (leaveHospitalDoc != null) {
|
|
|
+ LeaveHospitalLabel leaveHospitalLabel = leaveHospitalDoc.getLeaveHospitalLabel();
|
|
|
+ dateStr = leaveHospitalDoc.getStructureMap().get("出院时间");
|
|
|
+ if (leaveHospitalLabel != null && StringUtil.isNotBlank(dateStr)) {
|
|
|
+ List<Drug> drugs = leaveHospitalLabel.getDrugs();
|
|
|
+ getCourseDrugInfo(antibioticDateCourse, dateStr, drugs);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //将病程日期排序
|
|
|
+ antibioticDateCourse.forEach((x, y) -> y.sort(Comparator.naturalOrder()));
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 1.antibioticDate:从医嘱中取 key:抗生素名 value:医嘱中该抗生素所有加用时的时间(包括初始使用时间)
|
|
|
+ * 2.antibioticDateWard:从查房记录中取 key:抗生素名 value:病程记录中该抗生素所有没有用量时的查房时间(包括初始使用时间)
|
|
|
+ * 3.医嘱中该抗生素初始使用时间往后两天内,查房记录中该抗生素初始使用时间也在这两天内,则满足一半。
|
|
|
+ * 4.医嘱中该抗生素加用时的时间往后两天内,查房记录中该抗生素加用时间也在这两天内,则满足条件,该抗生素通过该条规则
|
|
|
+ */
|
|
|
+ StringBuffer sb = new StringBuffer();
|
|
|
+ String drugKey = null, start = null, change = null, wardStartStr = null, wardChangeStr = null;
|
|
|
+ List<String> dateList = null;
|
|
|
+ for (Map.Entry<String, List<String>> ad : antibioticDate.entrySet()) {
|
|
|
+ drugKey = ad.getKey();
|
|
|
+ String drugStandardWord = similarityUtil.getDrugStandardWord(drugKey);
|
|
|
+ if (StringUtil.isNotBlank(drugStandardWord)) {
|
|
|
+ drugKey = drugStandardWord;
|
|
|
+ }
|
|
|
+ if (antibioticDateCourse.containsKey(drugKey)) {
|
|
|
+ dateList = ad.getValue();
|
|
|
+ List<String> wardDateStr = antibioticDateCourse.get(drugKey);
|
|
|
+ for (int i = 0; i < dateList.size(); i++) {
|
|
|
+ start = dateList.get(i); //抗生素开医嘱时间
|
|
|
+ Date adStart = DateUtil.dateZeroClear(StringUtil.parseDateTime(start));
|
|
|
+ for (int j = 0; j < wardDateStr.size(); j++) {
|
|
|
+ wardStartStr = wardDateStr.get(j); //查房记录开抗生素时间
|
|
|
+ Date wardStart = StringUtil.parseDateTime(wardStartStr);
|
|
|
+ if ((adStart.before(wardStart) && !CatalogueUtil.compareTime(adStart, wardStart, 48 * 60L))
|
|
|
+ || (wardStart.before(adStart) && !CatalogueUtil.compareTime(wardStart, adStart, 24 * 60L))) {
|
|
|
+ infoAppend(sb, drugKey, start);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (sb.toString().length() > 0) {
|
|
|
+ status.set("-1");
|
|
|
+ info.set(sb.toString().substring(0, sb.toString().length() - 1));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 收集各模块药品信息
|
|
|
+ *
|
|
|
+ * @param antibioticDateWard 病程中抗生素使用所有时间
|
|
|
+ * @param dateStr 记录日期
|
|
|
+ * @param drugs 模型提取出的药品列表
|
|
|
+ */
|
|
|
+ private void getCourseDrugInfo(Map<String, List<String>> antibioticDateWard, String dateStr, List<Drug> drugs) {
|
|
|
+ for (Drug drug : drugs) {
|
|
|
+ String wardDrug = drug.getName();
|
|
|
+ wardDrug = removeBracket(wardDrug);
|
|
|
+ String drugStandardWord = similarityUtil.getDrugStandardWord(wardDrug);
|
|
|
+ if (StringUtil.isNotBlank(drugStandardWord)) {
|
|
|
+ wardDrug = drugStandardWord;
|
|
|
+ }
|
|
|
+ if (drug.getConsumption() == null) {
|
|
|
+ if (antibioticDateWard.containsKey(wardDrug)) {
|
|
|
+ antibioticDateWard.get(wardDrug).add(dateStr);
|
|
|
+ } else {
|
|
|
+ antibioticDateWard.put(wardDrug, Lists.newArrayList(dateStr));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 收集抗生素各种信息
|
|
|
+ *
|
|
|
+ * @param antibioticDate 抗生素使用所有时间
|
|
|
+ * @param antibioticStatus 抗生素用量改变状态
|
|
|
+ * @param antibioticValue 抗生素及用量
|
|
|
+ * @param drugName 抗生素名称
|
|
|
+ * @param value 抗生素用量
|
|
|
+ * @param startDateStr 抗生素使用时间(医嘱开始时间或查房时间)
|
|
|
+ */
|
|
|
+ private void collectAntibioticInfo(Map<String, List<String>> antibioticDate, Map<String, Integer> antibioticStatus,
|
|
|
+ Map<String, List<Double>> antibioticValue, String drugName, String value, String startDateStr) {
|
|
|
+ double v = -1;
|
|
|
+ try {
|
|
|
+ v = Double.parseDouble(getNumber(value));
|
|
|
+ } catch (Exception e) {
|
|
|
+ System.out.println("THR03074: " + drugName + ":" + value + "解析异常");
|
|
|
+ }
|
|
|
+ if (v < 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (v > 100) {
|
|
|
+ v = v / 1000;
|
|
|
+ }
|
|
|
+ if (!antibioticValue.containsKey(drugName)) {
|
|
|
+ antibioticValue.put(drugName, Lists.newArrayList(v));
|
|
|
+ antibioticDate.put(drugName, Lists.newArrayList(startDateStr));
|
|
|
+ antibioticStatus.put(drugName, 0);
|
|
|
+ } else {
|
|
|
+ //1.如果抗生素剂量有变化,则记录该抗生素开始时间
|
|
|
+ List<Double> beforeValue = antibioticValue.get(drugName);
|
|
|
+ if (beforeValue.get(beforeValue.size() - 1) != v) {
|
|
|
+ beforeValue.add(v);
|
|
|
+ antibioticValue.put(drugName, beforeValue);//添加该抗生素更大的值
|
|
|
+ antibioticStatus.put(drugName, antibioticStatus.get(drugName) + 1);
|
|
|
+ antibioticDate.get(drugName).add(startDateStr);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //2.如果抗生素剂量两次开启的时间间隔相差3天,也记录该抗生素开始时间
|
|
|
+ if (antibioticDate.get(drugName).size() > 0) {
|
|
|
+ List<String> currentAntibioticDate = antibioticDate.get(drugName);
|
|
|
+ String lastDate = currentAntibioticDate.get(currentAntibioticDate.size() - 1);
|
|
|
+ if (CatalogueUtil.compareTime(StringUtil.parseDateTime(lastDate), StringUtil.parseDateTime(startDateStr), 72 * 60L)) {
|
|
|
+ beforeValue.add(v);
|
|
|
+ antibioticValue.put(drugName, beforeValue);//添加该抗生素值
|
|
|
+ antibioticStatus.put(drugName, antibioticStatus.get(drugName) + 1);
|
|
|
+ antibioticDate.get(drugName).add(startDateStr);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String getNumber(String content) {
|
|
|
+ String group = "";
|
|
|
+ String compile = "([1-9]\\d*\\.?\\d*)|(0\\.\\d*[1-9]|\\.\\d*[1-9]|0)";
|
|
|
+ Pattern p = Pattern.compile(compile);
|
|
|
+ Matcher matcher = p.matcher(content);
|
|
|
+ if (matcher.find()) {
|
|
|
+ group = matcher.group(0);
|
|
|
+ }
|
|
|
+ return group;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 如果文本包含中括号([海正]美罗培南针),取括号之后的文字
|
|
|
+ *
|
|
|
+ * @param str
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private String removeBracket(String str) {
|
|
|
+ if (str.contains("]") && str.indexOf("]") != str.length() - 1) {
|
|
|
+ return str.substring(str.indexOf("]") + 1);
|
|
|
+ }
|
|
|
+ return str;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 拼接提示信息
|
|
|
+ *
|
|
|
+ * @param sb
|
|
|
+ * @param drugKey
|
|
|
+ * @param date
|
|
|
+ */
|
|
|
+ private void infoAppend(StringBuffer sb, String drugKey, String date) {
|
|
|
+ sb.append(drugKey).append("(").append(DateUtil.formatDate(StringUtil.parseDateTime(date))).append(")").append(",");
|
|
|
+ }
|
|
|
+
|
|
|
+}
|