浏览代码

抗生素相关规则修改逻辑

huj 5 年之前
父节点
当前提交
bd5ea64179

+ 1 - 1
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR02985.java

@@ -136,7 +136,7 @@ public class THR02985 extends QCCatalogue {
         //从出院小结中获取信息
         if (leaveHospitalDoc != null) {
             Map<String, String> structureMap = leaveHospitalDoc.getStructureMap();
-            getInfo(info, structureMap, "出院小结", "出院时间", "诊治经过");
+            getInfo(info, structureMap, "出院小结", "出院时间", "诊治经过","出院带药");
         }
 
         String infoStr = "";

+ 112 - 57
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03069.java

@@ -8,17 +8,19 @@ 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.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
@@ -37,7 +39,9 @@ public class THR03069 extends QCCatalogue {
         status.set("0");
         List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
         List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
-        if (doctorAdviceDocs.size() == 0 || threeLevelWardDocs.size() == 0) {
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        LeaveHospitalDoc leaveHospitalDoc = inputInfo.getLeaveHospitalDoc();
+        if (doctorAdviceDocs.size() == 0) {
             return;
         }
         //抗生素及开医嘱时间(包括加用过抗生素的时间)     key:抗生素名    "2020-08-20,2020-08-21 ..."
@@ -54,21 +58,12 @@ public class THR03069 extends QCCatalogue {
                 .filter(x -> StringUtil.isNotBlank(x.get("药品类型")) && x.get("药品类型").contains("抗生素") && StringUtil.isNotBlank(x.get("医嘱单次剂量")))
                 .collect(Collectors.toList());
 
-        docAdvStruct
-                .stream()
-                .map(x -> x.get("医嘱项目名称"))
-                .forEach(y -> antibioticStatus.put(removeBracket(y), 0));
-
         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);
-            String drugStandardWord = similarityUtil.getDrugStandardWord(drugName);
-            if (StringUtil.isNotBlank(drugStandardWord)) {
-                drugName = drugStandardWord;
-            }
             collectAntibioticInfo(antibioticDate, antibioticStatus, antibioticValue, drugName, value, startDateStr);
         }
 
@@ -76,6 +71,7 @@ public class THR03069 extends QCCatalogue {
         for (Map.Entry<String, Integer> as : antibioticStatus.entrySet()) {
             if (as.getValue() == 0) {
                 antibioticDate.remove(as.getKey());
+                antibioticValue.remove(as.getKey());
             }
         }
         //抗生素加用过的集合如果为空,则一个抗生素都没有加用过,直接返回0
@@ -83,62 +79,80 @@ public class THR03069 extends QCCatalogue {
             return;
         }
 
-        //查房记录中抗生素及查房时间(包括加用过抗生素的时间)     key:抗生素名    "2020-08-20,2020-08-21 ..."
-        Map<String, List<String>> antibioticDateWard = Maps.newHashMap();
-        //查房记录中抗生素加用集合   key:抗生素名    value:  0:未加用,1及以上:加用次数
-        Map<String, Integer> antibioticStatusWard = Maps.newHashMap();
-        //查房记录中抗生素及各初始剂量     key:抗生素名    value:抗生素第一次使用时剂量
-        Map<String, List<Double>> antibioticValueWard = Maps.newHashMap();
-        List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
-        for (ThreeLevelWardDoc doc : allDoctorWradDocs) {
-            if (doc.getThreeLevelWardLabel().size() == 0) {
-                continue;
-            }
-            ThreeLevelWardLabel label = doc.getThreeLevelWardLabel().get(0);
-            List<Drug> drugs = label.getDrugs();
-            for (Drug drug : drugs) {
-                String wardDrug = drug.getName();
-                wardDrug = removeBracket(wardDrug);
-                String drugStandardWord = similarityUtil.getDrugStandardWord(wardDrug);
-                if (StringUtil.isNotBlank(drugStandardWord)) {
-                    wardDrug = drugStandardWord;
+        //病程记录中抗生素及查房时间(包括加用过抗生素的时间)     key:抗生素名    "2020-08-20,2020-08-21 ..."
+        Map<String, List<String>> antibioticDateCourse = Maps.newHashMap();
+        //病程记录中抗生素加用集合   key:抗生素名    value:  0:未加用,1及以上:加用次数
+        Map<String, Integer> antibioticStatusCourse = Maps.newHashMap();
+        //病程记录中抗生素及各初始剂量     key:抗生素名    value:抗生素第一次使用时剂量
+        Map<String, List<Double>> antibioticValueCourse = 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;
                 }
-                //药品用量和使用原因都有时
-                if (drug.getConsumption() != null) {
-                    //查房记录抗生素加用过的集合中没包含该抗生素,则认为该抗生素是第一次出现,此时不需要加用原因
-                    if (!antibioticStatusWard.containsKey(wardDrug) || drug.getUsageWardRound() != null) {
-                        String consumption = drug.getConsumption().getName();
-                        collectAntibioticInfo(antibioticDateWard, antibioticStatusWard, antibioticValueWard, wardDrug, consumption, doc.getStructureMap().get("查房日期"));
-                    }
+                dateStr = doc.getStructureMap().get("查房日期");
+                ThreeLevelWardLabel label = doc.getThreeLevelWardLabel().get(0);
+                List<Drug> drugs = label.getDrugs();
+                getCourseDrugInfo(antibioticDateCourse, antibioticStatusCourse, antibioticValueCourse, 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, antibioticStatusCourse, antibioticValueCourse, dateStr, drugs);
             }
         }
-        //把查房记录中没加用过的抗生素删除
-        /*for (Map.Entry<String, Integer> as : antibioticStatusWard.entrySet()) {
-            if (as.getValue() == 0) {
-                antibioticDateWard.remove(as.getKey());
+        /*********************************************出院大结********************************************************/
+        if (leaveHospitalDoc != null) {
+            LeaveHospitalLabel leaveHospitalLabel = leaveHospitalDoc.getLeaveHospitalLabel();
+            dateStr = leaveHospitalDoc.getStructureMap().get("出院时间");
+            if (leaveHospitalLabel != null && StringUtil.isNotBlank(dateStr)) {
+                List<Drug> drugs = leaveHospitalLabel.getDrugs();
+                getCourseDrugInfo(antibioticDateCourse, antibioticStatusCourse, antibioticValueCourse, dateStr, drugs);
             }
-        }*/
+        }
+        //将病程日期排序
+        antibioticDateCourse.forEach((x, y) -> y.sort(Comparator.naturalOrder()));
 
         /**
          * 1.antibioticDate:从医嘱中取   key:抗生素名    value:医嘱中该抗生素所有加用时的时间(包括初始使用时间)
-         * 2.antibioticDateWard:从查房记录中取     key:抗生素名    value:查房记录中该抗生素所有已加用并且该抗生素有加用原因的查房时间(包括初始使用时间)
+         * 2.antibioticDateWard:从查房记录中取     key:抗生素名    value:查房记录中该抗生素所有加用时的查房时间(包括初始使用时间)
          * 3.医嘱中该抗生素初始使用时间往后两天内,查房记录中该抗生素初始使用时间也在这两天内,则满足一半。
          * 4.医嘱中该抗生素加用时的时间往后两天内,查房记录中该抗生素加用时间也在这两天内,则满足条件,该抗生素通过该条规则
          * 5.继续判断下一个抗生素
          * 6.若医嘱中加用过的抗生素,查房记录中没出现过,则该抗生素会报出来(存入miss,规则最后会把所有不符合的抗生素都报出来)
          */
-        List<String> miss = Lists.newArrayList();
+        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();
-            if (!antibioticDateWard.containsKey(drugKey)) {
-                miss.add(drugKey);
+            List<Double> antibioticValueList = antibioticValue.get(drugKey);//医嘱中该药品对应的所有用量
+            String drugStandardWord = similarityUtil.getDrugStandardWord(drugKey);
+            if (StringUtil.isNotBlank(drugStandardWord)) {
+                drugKey = drugStandardWord;
+            }
+            if (!antibioticDateCourse.containsKey(drugKey)) {
+                for (String date : ad.getValue()) {
+                    infoAppend(sb, drugKey, date);
+                }
                 continue;
             }
-            List<Double> antibioticValueList = antibioticValue.get(drugKey);
-            List<Double> antibioticValueWardList = antibioticValueWard.get(drugKey);
+            List<Double> antibioticValueWardList = antibioticValueCourse.get(drugKey);//病程记录中该药品对应的所有用量
             int findNum = 0;
             for (int i = 1; i < antibioticValueList.size(); i++) {//从加用的值开始,如果加用过的值查房记录中都有,则不报该药
                 if (antibioticValueWardList.contains(antibioticValueList.get(i))) {
@@ -150,7 +164,7 @@ public class THR03069 extends QCCatalogue {
             }
             dateList = ad.getValue();
             int matchNum = 0;
-            List<String> wardDateStr = antibioticDateWard.get(drugKey);
+            List<String> wardDateStr = antibioticDateCourse.get(drugKey);
             for (int i = 0; i < dateList.size() - 1; i++) {
                 start = dateList.get(i);        //抗生素开医嘱时间
                 change = dateList.get(i + 1);   //抗生素用量改变时间
@@ -167,13 +181,42 @@ public class THR03069 extends QCCatalogue {
                 }
             }
             if (dateList.size() - 1 != matchNum) {
-                miss.add(drugKey);
+                infoAppend(sb, drugKey, change);
             }
         }
 
-        if (miss.size() > 0) {
+        if (sb.toString().length() > 0) {
             status.set("-1");
-            info.set(miss.toString().replaceAll("[\\[\\]]", ""));
+            info.set(sb.toString().substring(0, sb.toString().length() - 1));
+        }
+    }
+
+    /**
+     * 收集各模块药品信息
+     *
+     * @param antibioticDateWard   病程中抗生素使用所有时间
+     * @param antibioticStatusWard 病程中抗生素用量改变状态
+     * @param antibioticValueWard  病程中抗生素及用量
+     * @param dateStr              记录日期
+     * @param drugs                模型提取出的药品列表
+     */
+    private void getCourseDrugInfo(Map<String, List<String>> antibioticDateWard, Map<String, Integer> antibioticStatusWard,
+                                   Map<String, List<Double>> antibioticValueWard, 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 (!antibioticStatusWard.containsKey(wardDrug) || drug.getUsageWardRound() != null) {
+                    String consumption = drug.getConsumption().getName();
+                    collectAntibioticInfo(antibioticDateWard, antibioticStatusWard, antibioticValueWard, wardDrug, consumption, dateStr);
+                }
+            }
         }
     }
 
@@ -187,12 +230,13 @@ public class THR03069 extends QCCatalogue {
      * @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) {
+    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("THR03069:       " + drugName + ":" + value + "解析异常");
+            System.out.println("THR03075:       " + drugName + ":" + value + "解析异常");
         }
         if (v < 0) {
             return;
@@ -236,4 +280,15 @@ public class THR03069 extends QCCatalogue {
         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(",");
+    }
+
 }

+ 113 - 58
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03072.java

@@ -8,17 +8,19 @@ 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.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
@@ -37,7 +39,9 @@ public class THR03072 extends QCCatalogue {
         status.set("0");
         List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
         List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
-        if (doctorAdviceDocs.size() == 0 || threeLevelWardDocs.size() == 0) {
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        LeaveHospitalDoc leaveHospitalDoc = inputInfo.getLeaveHospitalDoc();
+        if (doctorAdviceDocs.size() == 0) {
             return;
         }
         //抗生素及开医嘱时间(包括减用过抗生素的时间)     key:抗生素名    "2020-08-20,2020-08-21 ..."
@@ -54,21 +58,12 @@ public class THR03072 extends QCCatalogue {
                 .filter(x -> StringUtil.isNotBlank(x.get("药品类型")) && x.get("药品类型").contains("抗生素") && StringUtil.isNotBlank(x.get("医嘱单次剂量")))
                 .collect(Collectors.toList());
 
-        docAdvStruct
-                .stream()
-                .map(x -> x.get("医嘱项目名称"))
-                .forEach(y -> antibioticStatus.put(removeBracket(y), 0));
-
         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);
-            String drugStandardWord = similarityUtil.getDrugStandardWord(drugName);
-            if (StringUtil.isNotBlank(drugStandardWord)) {
-                drugName = drugStandardWord;
-            }
             collectAntibioticInfo(antibioticDate, antibioticStatus, antibioticValue, drugName, value, startDateStr);
         }
 
@@ -76,6 +71,7 @@ public class THR03072 extends QCCatalogue {
         for (Map.Entry<String, Integer> as : antibioticStatus.entrySet()) {
             if (as.getValue() == 0) {
                 antibioticDate.remove(as.getKey());
+                antibioticValue.remove(as.getKey());
             }
         }
         //抗生素减用过的集合如果为空,则一个抗生素都没有减用过,直接返回0
@@ -83,64 +79,82 @@ public class THR03072 extends QCCatalogue {
             return;
         }
 
-        //查房记录中抗生素及查房时间(包括减用过抗生素的时间)     key:抗生素名    "2020-08-20,2020-08-21 ..."
-        Map<String, List<String>> antibioticDateWard = Maps.newHashMap();
-        //查房记录中抗生素减用集合   key:抗生素名    value:  0:未减用,1及以上:减用次数
-        Map<String, Integer> antibioticStatusWard = Maps.newHashMap();
-        //查房记录中抗生素及各初始剂量     key:抗生素名    value:抗生素第一次使用时剂量
-        Map<String, List<Double>> antibioticValueWard = Maps.newHashMap();
-        List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
-        for (ThreeLevelWardDoc doc : allDoctorWradDocs) {
-            if (doc.getThreeLevelWardLabel().size() == 0) {
-                continue;
-            }
-            ThreeLevelWardLabel label = doc.getThreeLevelWardLabel().get(0);
-            List<Drug> drugs = label.getDrugs();
-            for (Drug drug : drugs) {
-                String wardDrug = drug.getName();
-                wardDrug = removeBracket(wardDrug);
-                String drugStandardWord = similarityUtil.getDrugStandardWord(wardDrug);
-                if (StringUtil.isNotBlank(drugStandardWord)) {
-                    wardDrug = drugStandardWord;
+        //病程记录中抗生素及查房时间(包括减用过抗生素的时间)     key:抗生素名    "2020-08-20,2020-08-21 ..."
+        Map<String, List<String>> antibioticDateCourse = Maps.newHashMap();
+        //病程记录中抗生素减用集合   key:抗生素名    value:  0:未减用,1及以上:减用次数
+        Map<String, Integer> antibioticStatusCourse = Maps.newHashMap();
+        //病程记录中抗生素及各初始剂量     key:抗生素名    value:抗生素第一次使用时剂量
+        Map<String, List<Double>> antibioticValueCourse = 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;
                 }
-                //药品用量和使用原因都有时
-                if (drug.getConsumption() != null) {
-                    //查房记录抗生素减用过的集合中没包含该抗生素,则认为该抗生素是第一次出现,此时不需要减用原因
-                    if (!antibioticStatusWard.containsKey(wardDrug) || drug.getUsageWardRound() != null) {
-                        String consumption = drug.getConsumption().getName();
-                        collectAntibioticInfo(antibioticDateWard, antibioticStatusWard, antibioticValueWard, wardDrug, consumption, doc.getStructureMap().get("查房日期"));
-                    }
+                dateStr = doc.getStructureMap().get("查房日期");
+                ThreeLevelWardLabel label = doc.getThreeLevelWardLabel().get(0);
+                List<Drug> drugs = label.getDrugs();
+                getCourseDrugInfo(antibioticDateCourse, antibioticStatusCourse, antibioticValueCourse, 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, antibioticStatusCourse, antibioticValueCourse, dateStr, drugs);
             }
         }
-        //把查房记录中没减用过的抗生素删除
-        /*for (Map.Entry<String, Integer> as : antibioticStatusWard.entrySet()) {
-            if (as.getValue() == 0) {
-                antibioticDateWard.remove(as.getKey());
+        /*********************************************出院小结********************************************************/
+        if (leaveHospitalDoc != null) {
+            LeaveHospitalLabel leaveHospitalLabel = leaveHospitalDoc.getLeaveHospitalLabel();
+            dateStr = leaveHospitalDoc.getStructureMap().get("出院时间");
+            if (leaveHospitalLabel != null && StringUtil.isNotBlank(dateStr)) {
+                List<Drug> drugs = leaveHospitalLabel.getDrugs();
+                getCourseDrugInfo(antibioticDateCourse, antibioticStatusCourse, antibioticValueCourse, dateStr, drugs);
             }
-        }*/
+        }
+        //将病程日期排序
+        antibioticDateCourse.forEach((x, y) -> y.sort(Comparator.naturalOrder()));
 
         /**
          * 1.antibioticDate:从医嘱中取   key:抗生素名    value:医嘱中该抗生素所有减用时的时间(包括初始使用时间)
-         * 2.antibioticDateWard:从查房记录中取     key:抗生素名    value:查房记录中该抗生素所有已减用并且该抗生素有减用原因的查房时间(包括初始使用时间)
+         * 2.antibioticDateWard:从查房记录中取     key:抗生素名    value:查房记录中该抗生素所有减用时的查房时间(包括初始使用时间)
          * 3.医嘱中该抗生素初始使用时间往后两天内,查房记录中该抗生素初始使用时间也在这两天内,则满足一半。
          * 4.医嘱中该抗生素减用时的时间往后两天内,查房记录中该抗生素减用时间也在这两天内,则满足条件,该抗生素通过该条规则
          * 5.继续判断下一个抗生素
          * 6.若医嘱中减用过的抗生素,查房记录中没出现过,则该抗生素会报出来(存入miss,规则最后会把所有不符合的抗生素都报出来)
          */
-        List<String> miss = Lists.newArrayList();
+        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();
-            if (!antibioticDateWard.containsKey(drugKey)) {
-                miss.add(drugKey);
+            List<Double> antibioticValueList = antibioticValue.get(drugKey);//医嘱中该药品对应的所有用量
+            String drugStandardWord = similarityUtil.getDrugStandardWord(drugKey);
+            if (StringUtil.isNotBlank(drugStandardWord)) {
+                drugKey = drugStandardWord;
+            }
+            if (!antibioticDateCourse.containsKey(drugKey)) {
+                for (String date : ad.getValue()) {
+                    infoAppend(sb, drugKey, date);
+                }
                 continue;
             }
-            List<Double> antibioticValueList = antibioticValue.get(drugKey);
-            List<Double> antibioticValueWardList = antibioticValueWard.get(drugKey);
+            List<Double> antibioticValueWardList = antibioticValueCourse.get(drugKey);//病程记录中该药品对应的所有用量
             int findNum = 0;
-            for (int i = 1; i < antibioticValueList.size(); i++) {//从减用的值开始,如果减用过的值查房记录中都有,则不报该药
+            for (int i = 1; i < antibioticValueList.size(); i++) {//从加用的值开始,如果加用过的值查房记录中都有,则不报该药
                 if (antibioticValueWardList.contains(antibioticValueList.get(i))) {
                     findNum++;
                 }
@@ -150,7 +164,7 @@ public class THR03072 extends QCCatalogue {
             }
             dateList = ad.getValue();
             int matchNum = 0;
-            List<String> wardDateStr = antibioticDateWard.get(drugKey);
+            List<String> wardDateStr = antibioticDateCourse.get(drugKey);
             for (int i = 0; i < dateList.size() - 1; i++) {
                 start = dateList.get(i);        //抗生素开医嘱时间
                 change = dateList.get(i + 1);   //抗生素用量改变时间
@@ -167,13 +181,42 @@ public class THR03072 extends QCCatalogue {
                 }
             }
             if (dateList.size() - 1 != matchNum) {
-                miss.add(drugKey);
+                infoAppend(sb, drugKey, change);
             }
         }
 
-        if (miss.size() > 0) {
+        if (sb.toString().length() > 0) {
             status.set("-1");
-            info.set(miss.toString().replaceAll("[\\[\\]]", ""));
+            info.set(sb.toString().substring(0, sb.toString().length() - 1));
+        }
+    }
+
+    /**
+     * 收集各模块药品信息
+     *
+     * @param antibioticDateWard   病程中抗生素使用所有时间
+     * @param antibioticStatusWard 病程中抗生素用量改变状态
+     * @param antibioticValueWard  病程中抗生素及用量
+     * @param dateStr              记录日期
+     * @param drugs                模型提取出的药品列表
+     */
+    private void getCourseDrugInfo(Map<String, List<String>> antibioticDateWard, Map<String, Integer> antibioticStatusWard,
+                                   Map<String, List<Double>> antibioticValueWard, 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 (!antibioticStatusWard.containsKey(wardDrug) || drug.getUsageWardRound() != null) {
+                    String consumption = drug.getConsumption().getName();
+                    collectAntibioticInfo(antibioticDateWard, antibioticStatusWard, antibioticValueWard, wardDrug, consumption, dateStr);
+                }
+            }
         }
     }
 
@@ -187,12 +230,13 @@ public class THR03072 extends QCCatalogue {
      * @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) {
+    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("THR03072:       " + drugName + ":" + value + "解析异常");
+            System.out.println("THR03075:       " + drugName + ":" + value + "解析异常");
         }
         if (v < 0) {
             return;
@@ -236,4 +280,15 @@ public class THR03072 extends QCCatalogue {
         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(",");
+    }
+
 }

+ 107 - 52
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03074.java

@@ -8,17 +8,19 @@ 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.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
@@ -37,7 +39,9 @@ public class THR03074 extends QCCatalogue {
         status.set("0");
         List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
         List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
-        if (doctorAdviceDocs.size() == 0 || threeLevelWardDocs.size() == 0) {
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        LeaveHospitalDoc leaveHospitalDoc = inputInfo.getLeaveHospitalDoc();
+        if (doctorAdviceDocs.size() == 0) {
             return;
         }
         //抗生素及开医嘱时间(包括加用过抗生素的时间)     key:抗生素名    "2020-08-20,2020-08-21 ..."
@@ -54,21 +58,12 @@ public class THR03074 extends QCCatalogue {
                 .filter(x -> StringUtil.isNotBlank(x.get("药品类型")) && x.get("药品类型").contains("抗生素") && StringUtil.isNotBlank(x.get("医嘱单次剂量")))
                 .collect(Collectors.toList());
 
-        docAdvStruct
-                .stream()
-                .map(x -> x.get("医嘱项目名称"))
-                .forEach(y -> antibioticStatus.put(removeBracket(y), 0));
-
         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);
-            String drugStandardWord = similarityUtil.getDrugStandardWord(drugName);
-            if (StringUtil.isNotBlank(drugStandardWord)) {
-                drugName = drugStandardWord;
-            }
             collectAntibioticInfo(antibioticDate, antibioticStatus, antibioticValue, drugName, value, startDateStr);
         }
 
@@ -76,6 +71,7 @@ public class THR03074 extends QCCatalogue {
         for (Map.Entry<String, Integer> as : antibioticStatus.entrySet()) {
             if (as.getValue() == 0) {
                 antibioticDate.remove(as.getKey());
+                antibioticValue.remove(as.getKey());
             }
         }
         //抗生素加用过的集合如果为空,则一个抗生素都没有加用过,直接返回0
@@ -83,38 +79,54 @@ public class THR03074 extends QCCatalogue {
             return;
         }
 
-        //查房记录中抗生素及查房时间(包括加用过抗生素的时间)     key:抗生素名    "2020-08-20,2020-08-21 ..."
-        Map<String, List<String>> antibioticDateWard = Maps.newHashMap();
-        //查房记录中抗生素加用集合   key:抗生素名    value:  0:未加用,1及以上:加用次数
-        Map<String, Integer> antibioticStatusWard = Maps.newHashMap();
-        //查房记录中抗生素及各初始剂量     key:抗生素名    value:抗生素第一次使用时剂量
-        Map<String, List<Double>> antibioticValueWard = Maps.newHashMap();
-        List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
-        for (ThreeLevelWardDoc doc : allDoctorWradDocs) {
-            if (doc.getThreeLevelWardLabel().size() == 0) {
-                continue;
-            }
-            ThreeLevelWardLabel label = doc.getThreeLevelWardLabel().get(0);
-            List<Drug> drugs = label.getDrugs();
-            for (Drug drug : drugs) {
-                String wardDrug = drug.getName();
-                wardDrug = removeBracket(wardDrug);
-                String drugStandardWord = similarityUtil.getDrugStandardWord(wardDrug);
-                if (StringUtil.isNotBlank(drugStandardWord)) {
-                    wardDrug = drugStandardWord;
+        //病程记录中抗生素及查房时间(包括加用过抗生素的时间)     key:抗生素名    "2020-08-20,2020-08-21 ..."
+        Map<String, List<String>> antibioticDateCourse = Maps.newHashMap();
+        //病程记录中抗生素加用集合   key:抗生素名    value:  0:未加用,1及以上:加用次数
+        Map<String, Integer> antibioticStatusCourse = Maps.newHashMap();
+        //病程记录中抗生素及各初始剂量     key:抗生素名    value:抗生素第一次使用时剂量
+        Map<String, List<Double>> antibioticValueCourse = 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;
                 }
-                if (drug.getConsumption() != null) {
-                    String consumption = drug.getConsumption().getName();
-                    collectAntibioticInfo(antibioticDateWard, antibioticStatusWard, antibioticValueWard, wardDrug, consumption, doc.getStructureMap().get("查房日期"));
+                dateStr = doc.getStructureMap().get("查房日期");
+                ThreeLevelWardLabel label = doc.getThreeLevelWardLabel().get(0);
+                List<Drug> drugs = label.getDrugs();
+                getCourseDrugInfo(antibioticDateCourse, antibioticStatusCourse, antibioticValueCourse, 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, antibioticStatusCourse, antibioticValueCourse, dateStr, drugs);
             }
         }
-        //把查房记录中没加用过的抗生素删除
-        /*for (Map.Entry<String, Integer> as : antibioticStatusWard.entrySet()) {
-            if (as.getValue() == 0) {
-                antibioticDateWard.remove(as.getKey());
+        /*********************************************出院小结********************************************************/
+        if (leaveHospitalDoc != null) {
+            LeaveHospitalLabel leaveHospitalLabel = leaveHospitalDoc.getLeaveHospitalLabel();
+            dateStr = leaveHospitalDoc.getStructureMap().get("出院时间");
+            if (leaveHospitalLabel != null && StringUtil.isNotBlank(dateStr)) {
+                List<Drug> drugs = leaveHospitalLabel.getDrugs();
+                getCourseDrugInfo(antibioticDateCourse, antibioticStatusCourse, antibioticValueCourse, dateStr, drugs);
             }
-        }*/
+        }
+        //将病程日期排序
+        antibioticDateCourse.forEach((x, y) -> y.sort(Comparator.naturalOrder()));
 
         /**
          * 1.antibioticDate:从医嘱中取   key:抗生素名    value:医嘱中该抗生素所有加用时的时间(包括初始使用时间)
@@ -122,19 +134,25 @@ public class THR03074 extends QCCatalogue {
          * 3.医嘱中该抗生素初始使用时间往后两天内,查房记录中该抗生素初始使用时间也在这两天内,则满足一半。
          * 4.医嘱中该抗生素加用时的时间往后两天内,查房记录中该抗生素加用时间也在这两天内,则满足条件,该抗生素通过该条规则
          * 5.继续判断下一个抗生素
-         * 6.若医嘱中加用过的抗生素,查房记录中没出现过,则该抗生素会报出来(存入miss,规则最后会把所有不符合的抗生素都报出来)
+         * 6.若医嘱中加用过的抗生素,查房记录中没出现过,则该抗生素会报出来
          */
-        List<String> miss = Lists.newArrayList();
+        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();
-            if (!antibioticDateWard.containsKey(drugKey)) {
-                miss.add(drugKey);
+            List<Double> antibioticValueList = antibioticValue.get(drugKey);//医嘱中该药品对应的所有用量
+            String drugStandardWord = similarityUtil.getDrugStandardWord(drugKey);
+            if (StringUtil.isNotBlank(drugStandardWord)) {
+                drugKey = drugStandardWord;
+            }
+            if (!antibioticDateCourse.containsKey(drugKey)) {
+                for (String date : ad.getValue()) {
+                    infoAppend(sb, drugKey, date);
+                }
                 continue;
             }
-            List<Double> antibioticValueList = antibioticValue.get(drugKey);
-            List<Double> antibioticValueWardList = antibioticValueWard.get(drugKey);
+            List<Double> antibioticValueWardList = antibioticValueCourse.get(drugKey);//病程记录中该药品对应的所有用量
             int findNum = 0;
             for (int i = 1; i < antibioticValueList.size(); i++) {//从加用的值开始,如果加用过的值查房记录中都有,则不报该药
                 if (antibioticValueWardList.contains(antibioticValueList.get(i))) {
@@ -146,7 +164,7 @@ public class THR03074 extends QCCatalogue {
             }
             dateList = ad.getValue();
             int matchNum = 0;
-            List<String> wardDateStr = antibioticDateWard.get(drugKey);
+            List<String> wardDateStr = antibioticDateCourse.get(drugKey);
             for (int i = 0; i < dateList.size() - 1; i++) {
                 start = dateList.get(i);        //抗生素开医嘱时间
                 change = dateList.get(i + 1);   //抗生素用量改变时间
@@ -163,13 +181,38 @@ public class THR03074 extends QCCatalogue {
                 }
             }
             if (dateList.size() - 1 != matchNum) {
-                miss.add(drugKey);
+                infoAppend(sb, drugKey, change);
             }
         }
 
-        if (miss.size() > 0) {
+        if (sb.toString().length() > 0) {
             status.set("-1");
-            info.set(miss.toString().replaceAll("[\\[\\]]", ""));
+            info.set(sb.toString().substring(0, sb.toString().length() - 1));
+        }
+    }
+
+    /**
+     * 收集各模块药品信息
+     *
+     * @param antibioticDateWard   病程中抗生素使用所有时间
+     * @param antibioticStatusWard 病程中抗生素用量改变状态
+     * @param antibioticValueWard  病程中抗生素及用量
+     * @param dateStr              记录日期
+     * @param drugs                模型提取出的药品列表
+     */
+    private void getCourseDrugInfo(Map<String, List<String>> antibioticDateWard, Map<String, Integer> antibioticStatusWard,
+                                   Map<String, List<Double>> antibioticValueWard, 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) {
+                String consumption = drug.getConsumption().getName();
+                collectAntibioticInfo(antibioticDateWard, antibioticStatusWard, antibioticValueWard, wardDrug, consumption, dateStr);
+            }
         }
     }
 
@@ -183,7 +226,8 @@ public class THR03074 extends QCCatalogue {
      * @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) {
+    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));
@@ -232,4 +276,15 @@ public class THR03074 extends QCCatalogue {
         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(",");
+    }
+
 }

+ 116 - 52
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03075.java

@@ -8,17 +8,19 @@ 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.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
@@ -37,7 +39,9 @@ public class THR03075 extends QCCatalogue {
         status.set("0");
         List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
         List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
-        if (doctorAdviceDocs.size() == 0 || threeLevelWardDocs.size() == 0) {
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        LeaveHospitalDoc leaveHospitalDoc = inputInfo.getLeaveHospitalDoc();
+        if (doctorAdviceDocs.size() == 0) {
             return;
         }
         //抗生素及开医嘱时间(包括减用过抗生素的时间)     key:抗生素名    "2020-08-20,2020-08-21 ..."
@@ -54,21 +58,12 @@ public class THR03075 extends QCCatalogue {
                 .filter(x -> StringUtil.isNotBlank(x.get("药品类型")) && x.get("药品类型").contains("抗生素") && StringUtil.isNotBlank(x.get("医嘱单次剂量")))
                 .collect(Collectors.toList());
 
-        docAdvStruct
-                .stream()
-                .map(x -> x.get("医嘱项目名称"))
-                .forEach(y -> antibioticStatus.put(removeBracket(y), 0));
-
         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);
-            String drugStandardWord = similarityUtil.getDrugStandardWord(drugName);
-            if (StringUtil.isNotBlank(drugStandardWord)) {
-                drugName = drugStandardWord;
-            }
             collectAntibioticInfo(antibioticDate, antibioticStatus, antibioticValue, drugName, value, startDateStr);
         }
 
@@ -76,6 +71,7 @@ public class THR03075 extends QCCatalogue {
         for (Map.Entry<String, Integer> as : antibioticStatus.entrySet()) {
             if (as.getValue() == 0) {
                 antibioticDate.remove(as.getKey());
+                antibioticValue.remove(as.getKey());
             }
         }
         //抗生素减用过的集合如果为空,则一个抗生素都没有减用过,直接返回0
@@ -83,52 +79,82 @@ public class THR03075 extends QCCatalogue {
             return;
         }
 
-        //查房记录中抗生素及查房时间(包括减用过抗生素的时间)     key:抗生素名    "2020-08-20,2020-08-21 ..."
-        Map<String, List<String>> antibioticDateWard = Maps.newHashMap();
-        //查房记录中抗生素减用集合   key:抗生素名    value:  0:未减用,1及以上:减用次数
-        Map<String, Integer> antibioticStatusWard = Maps.newHashMap();
-        //查房记录中抗生素及各初始剂量     key:抗生素名    value:抗生素第一次使用时剂量
-        Map<String, List<Double>> antibioticValueWard = Maps.newHashMap();
-        List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
-        for (ThreeLevelWardDoc doc : allDoctorWradDocs) {
-            if (doc.getThreeLevelWardLabel().size() == 0) {
-                continue;
-            }
-            ThreeLevelWardLabel label = doc.getThreeLevelWardLabel().get(0);
-            List<Drug> drugs = label.getDrugs();
-            for (Drug drug : drugs) {
-                String wardDrug = drug.getName();
-                wardDrug = removeBracket(wardDrug);
-                String drugStandardWord = similarityUtil.getDrugStandardWord(wardDrug);
-                if (StringUtil.isNotBlank(drugStandardWord)) {
-                    wardDrug = drugStandardWord;
+        //病程记录中抗生素及查房时间(包括减用过抗生素的时间)     key:抗生素名    "2020-08-20,2020-08-21 ..."
+        Map<String, List<String>> antibioticDateCourse = Maps.newHashMap();
+        //病程记录中抗生素减用集合   key:抗生素名    value:  0:未减用,1及以上:减用次数
+        Map<String, Integer> antibioticStatusCourse = Maps.newHashMap();
+        //病程记录中抗生素及各初始剂量     key:抗生素名    value:抗生素第一次使用时剂量
+        Map<String, List<Double>> antibioticValueCourse = 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;
                 }
-                if (drug.getConsumption() != null) {
-                    String consumption = drug.getConsumption().getName();
-                    collectAntibioticInfo(antibioticDateWard, antibioticStatusWard, antibioticValueWard, wardDrug, consumption, doc.getStructureMap().get("查房日期"));
+                dateStr = doc.getStructureMap().get("查房日期");
+                ThreeLevelWardLabel label = doc.getThreeLevelWardLabel().get(0);
+                List<Drug> drugs = label.getDrugs();
+                getCourseDrugInfo(antibioticDateCourse, antibioticStatusCourse, antibioticValueCourse, 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, antibioticStatusCourse, antibioticValueCourse, dateStr, drugs);
             }
         }
-        //把查房记录中没减用过的抗生素删除
-        /*for (Map.Entry<String, Integer> as : antibioticStatusWard.entrySet()) {
-            if (as.getValue() == 0) {
-                antibioticDateWard.remove(as.getKey());
+        /*********************************************出院小结********************************************************/
+        if (leaveHospitalDoc != null) {
+            LeaveHospitalLabel leaveHospitalLabel = leaveHospitalDoc.getLeaveHospitalLabel();
+            dateStr = leaveHospitalDoc.getStructureMap().get("出院时间");
+            if (leaveHospitalLabel != null && StringUtil.isNotBlank(dateStr)) {
+                List<Drug> drugs = leaveHospitalLabel.getDrugs();
+                getCourseDrugInfo(antibioticDateCourse, antibioticStatusCourse, antibioticValueCourse, dateStr, drugs);
             }
-        }*/
+        }
+        //将病程日期排序
+        antibioticDateCourse.forEach((x, y) -> y.sort(Comparator.naturalOrder()));
 
-        List<String> miss = Lists.newArrayList();
+        /**
+         * 1.antibioticDate:从医嘱中取   key:抗生素名    value:医嘱中该抗生素所有减用时的时间(包括初始使用时间)
+         * 2.antibioticDateWard:从查房记录中取     key:抗生素名    value:查房记录中该抗生素所有减用时的查房时间(包括初始使用时间)
+         * 3.医嘱中该抗生素初始使用时间往后两天内,查房记录中该抗生素初始使用时间也在这两天内,则满足一半。
+         * 4.医嘱中该抗生素减用时的时间往后两天内,查房记录中该抗生素减用时间也在这两天内,则满足条件,该抗生素通过该条规则
+         * 5.继续判断下一个抗生素
+         * 6.若医嘱中减用过的抗生素,查房记录中没出现过,则该抗生素会报出来(存入miss,规则最后会把所有不符合的抗生素都报出来)
+         */
+        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();
-            if (!antibioticDateWard.containsKey(drugKey)) {
-                miss.add(drugKey);
+            List<Double> antibioticValueList = antibioticValue.get(drugKey);//医嘱中该药品对应的所有用量
+            String drugStandardWord = similarityUtil.getDrugStandardWord(drugKey);
+            if (StringUtil.isNotBlank(drugStandardWord)) {
+                drugKey = drugStandardWord;
+            }
+            if (!antibioticDateCourse.containsKey(drugKey)) {
+                for (String date : ad.getValue()) {
+                    infoAppend(sb, drugKey, date);
+                }
                 continue;
             }
-            List<Double> antibioticValueList = antibioticValue.get(drugKey);
-            List<Double> antibioticValueWardList = antibioticValueWard.get(drugKey);
+            List<Double> antibioticValueWardList = antibioticValueCourse.get(drugKey);//病程记录中该药品对应的所有用量
             int findNum = 0;
-            for (int i = 1; i < antibioticValueList.size(); i++) {//从减用的值开始,如果减用过的值查房记录中都有,则不报该药
+            for (int i = 1; i < antibioticValueList.size(); i++) {//从加用的值开始,如果加用过的值查房记录中都有,则不报该药
                 if (antibioticValueWardList.contains(antibioticValueList.get(i))) {
                     findNum++;
                 }
@@ -138,7 +164,7 @@ public class THR03075 extends QCCatalogue {
             }
             dateList = ad.getValue();
             int matchNum = 0;
-            List<String> wardDateStr = antibioticDateWard.get(drugKey);
+            List<String> wardDateStr = antibioticDateCourse.get(drugKey);
             for (int i = 0; i < dateList.size() - 1; i++) {
                 start = dateList.get(i);        //抗生素开医嘱时间
                 change = dateList.get(i + 1);   //抗生素用量改变时间
@@ -155,13 +181,38 @@ public class THR03075 extends QCCatalogue {
                 }
             }
             if (dateList.size() - 1 != matchNum) {
-                miss.add(drugKey);
+                infoAppend(sb, drugKey, change);
             }
         }
 
-        if (miss.size() > 0) {
+        if (sb.toString().length() > 0) {
             status.set("-1");
-            info.set(miss.toString().replaceAll("[\\[\\]]", ""));
+            info.set(sb.toString().substring(0, sb.toString().length() - 1));
+        }
+    }
+
+    /**
+     * 收集各模块药品信息
+     *
+     * @param antibioticDateWard   病程中抗生素使用所有时间
+     * @param antibioticStatusWard 病程中抗生素用量改变状态
+     * @param antibioticValueWard  病程中抗生素及用量
+     * @param dateStr              记录日期
+     * @param drugs                模型提取出的药品列表
+     */
+    private void getCourseDrugInfo(Map<String, List<String>> antibioticDateWard, Map<String, Integer> antibioticStatusWard,
+                                   Map<String, List<Double>> antibioticValueWard, 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) {
+                String consumption = drug.getConsumption().getName();
+                collectAntibioticInfo(antibioticDateWard, antibioticStatusWard, antibioticValueWard, wardDrug, consumption, dateStr);
+            }
         }
     }
 
@@ -175,7 +226,8 @@ public class THR03075 extends QCCatalogue {
      * @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) {
+    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));
@@ -223,4 +275,16 @@ public class THR03075 extends QCCatalogue {
         }
         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(",");
+    }
+
 }

+ 61 - 20
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03076.java

@@ -8,8 +8,12 @@ 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;
@@ -37,6 +41,8 @@ public class THR03076 extends QCCatalogue {
         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 || threeLevelWardDocs.size() == 0) {
             return;
         }
@@ -55,33 +61,49 @@ public class THR03076 extends QCCatalogue {
             value = structMap.get("医嘱单次剂量");
             startDateStr = structMap.get("医嘱开始时间");
             drugName = removeBracket(drugName);
-            String drugStandardWord = similarityUtil.getDrugStandardWord(drugName);
-            if (StringUtil.isNotBlank(drugStandardWord)) {
-                drugName = drugStandardWord;
-            }
             collectAntibioticInfo(antibioticInfo, drugName, value, startDateStr);
         }
 
         //抗生素及开医嘱时间 <抗生素名,<抗生素用量,[抗生素使用时间...]>>
         Map<String, Map<Double, List<String>>> antibioticWardInfo = Maps.newLinkedHashMap();
-        List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
-        for (ThreeLevelWardDoc doc : allDoctorWradDocs) {
-            if (doc.getThreeLevelWardLabel().size() == 0) {
-                continue;
-            }
-            ThreeLevelWardLabel label = doc.getThreeLevelWardLabel().get(0);
-            List<Drug> drugs = label.getDrugs();
-            for (Drug drug : drugs) {
-                String wardDrug = drug.getName();
-                wardDrug = removeBracket(wardDrug);
-                String drugStandardWord = similarityUtil.getDrugStandardWord(wardDrug);
-                if (StringUtil.isNotBlank(drugStandardWord)) {
-                    wardDrug = drugStandardWord;
+        String dateStr = null;
+        /*********************************************查房记录********************************************************/
+        if (threeLevelWardDocs.size() > 0) {
+            List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
+            for (ThreeLevelWardDoc doc : allDoctorWradDocs) {
+                if (doc.getThreeLevelWardLabel().size() == 0) {
+                    continue;
                 }
-                if (drug.getConsumption() != null) {
-                    String consumption = drug.getConsumption().getName();
-                    collectAntibioticInfo(antibioticWardInfo, wardDrug, consumption, doc.getStructureMap().get("查房日期"));
+                dateStr = doc.getStructureMap().get("查房日期");
+                ThreeLevelWardLabel label = doc.getThreeLevelWardLabel().get(0);
+                List<Drug> drugs = label.getDrugs();
+                getCourseDrugInfo(antibioticWardInfo, drugs, dateStr);
+            }
+        }
+        /*********************************************术后首程********************************************************/
+        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(antibioticWardInfo, drugs, dateStr);
+            }
+        }
+        /*********************************************出院小结********************************************************/
+        if (leaveHospitalDoc != null) {
+            LeaveHospitalLabel leaveHospitalLabel = leaveHospitalDoc.getLeaveHospitalLabel();
+            dateStr = leaveHospitalDoc.getStructureMap().get("出院时间");
+            if (leaveHospitalLabel != null && StringUtil.isNotBlank(dateStr)) {
+                List<Drug> drugs = leaveHospitalLabel.getDrugs();
+                getCourseDrugInfo(antibioticWardInfo, drugs, dateStr);
             }
         }
 
@@ -95,6 +117,10 @@ public class THR03076 extends QCCatalogue {
         String drugKey = null;
         for (Map.Entry<String, Map<Double, List<String>>> ai : antibioticInfo.entrySet()) {
             drugKey = ai.getKey();
+            String drugStandardWord = similarityUtil.getDrugStandardWord(drugKey);
+            if (StringUtil.isNotBlank(drugStandardWord)) {
+                drugKey = drugStandardWord;
+            }
             if (!antibioticWardInfo.containsKey(drugKey)) {
                 for (Map.Entry<Double, List<String>> ad : ai.getValue().entrySet()) {
                     for (String date : ad.getValue()) {
@@ -137,6 +163,21 @@ public class THR03076 extends QCCatalogue {
         }
     }
 
+    private void getCourseDrugInfo(Map<String, Map<Double, List<String>>> antibioticWardInfo, List<Drug> drugs, String dateStr) {
+        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) {
+                String consumption = drug.getConsumption().getName();
+                collectAntibioticInfo(antibioticWardInfo, wardDrug, consumption, dateStr);
+            }
+        }
+    }
+
     /**
      * 拼接提示信息
      *

+ 63 - 21
kernel/src/main/java/com/lantone/qc/kernel/structure/ai/LeaveHospitalAI.java

@@ -2,12 +2,17 @@ package com.lantone.qc.kernel.structure.ai;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.google.common.collect.Lists;
 import com.lantone.qc.kernel.client.CRFServiceClient;
+import com.lantone.qc.kernel.structure.ai.process.EntityProcessDiag;
+import com.lantone.qc.kernel.structure.ai.process.EntityProcessDrug;
 import com.lantone.qc.kernel.structure.ai.process.EntityProcessLeaveHospital;
 import com.lantone.qc.kernel.util.CatalogueUtil;
 import com.lantone.qc.pub.Content;
 import com.lantone.qc.pub.model.InputInfo;
 import com.lantone.qc.pub.model.doc.LeaveHospitalDoc;
+import com.lantone.qc.pub.model.entity.Diag;
+import com.lantone.qc.pub.model.entity.Drug;
 import com.lantone.qc.pub.model.label.DiagLabel;
 import com.lantone.qc.pub.model.label.LeaveHospitalLabel;
 import com.lantone.qc.pub.util.StringUtil;
@@ -27,7 +32,7 @@ public class LeaveHospitalAI extends ModelAI {
     /**
      *
      */
-    public static List<String> medicalTextType = Arrays.asList("DischargeQA_cx", "Diagnoses_cx");
+    public static List<String> medicalTextType = Arrays.asList("DischargeQA_cx", "Diagnoses_cx", "CourseRecordSRR");
     public static String entityRelationObject = "entity_relation_object";
     public static String outputs = "outputs";
     public static String content = "content";
@@ -42,33 +47,38 @@ public class LeaveHospitalAI extends ModelAI {
             }
 
             Map<String, String> leaveHospitalStructureMap = leaveHospitalDoc.getStructureMap();
-            if (leaveHospitalStructureMap != null) {
-                //                //入院情况
-                //                if (leaveHospitalStructureMap.get(Content.inStatus) != null) {
-                //                    putContent(crfContent, medicalTextType.get(1), leaveHospitalStructureMap.get(Content.inStatus), Content.inStatus);
-                //                }
-                //出院诊断
-                if (StringUtil.isNotBlank(leaveHospitalStructureMap.get(Content.dischargeDiag))) {
-                    String dischargeDiag = leaveHospitalStructureMap.get(Content.dischargeDiag);
+            //入院情况
+            //if (leaveHospitalStructureMap.get(Content.inStatus) != null) {
+            //    putContent(crfContent, medicalTextType.get(1), leaveHospitalStructureMap.get(Content.inStatus), Content.inStatus);
+            //}
+            //出院诊断
+            if (StringUtil.isNotBlank(leaveHospitalStructureMap.get(Content.dischargeDiag))) {
+                String dischargeDiag = leaveHospitalStructureMap.get(Content.dischargeDiag);
                     /*if (CatalogueUtil.numberExist(dischargeDiag)) {
                         dischargeDiag = CatalogueUtil.removeBetweenWordSpace(dischargeDiag);
                     }*/
-                    putContent(crfContent, medicalTextType.get(1), dischargeDiag, Content.dischargeDiag);
-                }
+                putContent(crfContent, medicalTextType.get(1), dischargeDiag, Content.dischargeDiag);
             }
             if (leaveHospitalDoc.getLeaveHospitalDoctorAdviceLabel() != null
                     && StringUtils.isNotEmpty(leaveHospitalDoc.getLeaveHospitalDoctorAdviceLabel().getAiText())) {
                 putContent(crfContent, medicalTextType.get(0), leaveHospitalDoc.getLeaveHospitalDoctorAdviceLabel().getAiText(), Content.leaveHospitalDoctorAdvice);
             }
+            //药品
+            String drugContent = CatalogueUtil.structureMapJoin(leaveHospitalStructureMap, Lists.newArrayList("诊治经过", "出院带药"));
+            putContent(crfContent, medicalTextType.get(2), drugContent, "药品");
+
             JSONObject midData = loadAI(inputInfo.isUseCrfCache(), inputInfo.getMedicalRecordInfoDoc().getStructureMap().get("behospitalCode"), crfContent, crfServiceClient);//crf返回数据
             if (midData.containsKey(Content.discharge)) {
                 putDischargeCrfData(midData.getJSONObject(Content.discharge), inputInfo);//出院小结
             }
             if (midData.containsKey(Content.dischargeDiag)) {
-                putDischargeCrfData(midData.getJSONObject(Content.dischargeDiag), inputInfo);//出院诊断
+                putDiagCrfData(midData.getJSONObject(Content.dischargeDiag), inputInfo);//出院诊断
             }
             if (midData.containsKey(Content.leaveHospitalDoctorAdvice)) {
-//                putLeaveHospitalDoctorAdviceCrfData(midData.getJSONObject(Content.leaveHospitalDoctorAdvice), inputInfo);//出院医嘱
+                //putLeaveHospitalDoctorAdviceCrfData(midData.getJSONObject(Content.leaveHospitalDoctorAdvice), inputInfo);//出院医嘱
+            }
+            if (midData.containsKey("药品")) {
+                putDrugCrfData(midData.getJSONObject("药品"), inputInfo);
             }
         }
     }
@@ -85,18 +95,50 @@ public class LeaveHospitalAI extends ModelAI {
         if (aiOut == null) {
             return;
         }
-        //使用现病史结构来处理病历特点
         EntityProcessLeaveHospital entityProcessLeaveHospital = new EntityProcessLeaveHospital();
         LeaveHospitalLabel leaveHospitalLabel = entityProcessLeaveHospital.extractEntity(aiOut);
-        if (inputInfo.getLeaveHospitalDoc().getLeaveDiagLabel() == null) {
-            DiagLabel diagLabel = new DiagLabel();
-            diagLabel.setDiags(leaveHospitalLabel.getDiags());
-            inputInfo.getLeaveHospitalDoc().setLeaveDiagLabel(diagLabel);
+        inputInfo.getLeaveHospitalDoc().setLeaveHospitalLabel(leaveHospitalLabel);
+    }
+
+    /**
+     * 存放抓取的疾病
+     *
+     * @param jsonObject
+     * @param inputInfo
+     */
+    public void putDiagCrfData(JSONObject jsonObject, InputInfo inputInfo) {
+        JSONObject aiOut = loadEntity(jsonObject, entityRelationObject, outputs, content);
+        if (aiOut == null) {
+            return;
+        }
+        EntityProcessDiag entityProcessDiag = new EntityProcessDiag();
+        List<Diag> diags = entityProcessDiag.extractEntity(aiOut);
+        DiagLabel diagLabel = new DiagLabel();
+        diagLabel.setDiags(diags);
+        inputInfo.getLeaveHospitalDoc().setLeaveDiagLabel(diagLabel);
+    }
+
+    /**
+     * 存放抓取的药品
+     *
+     * @param jsonObject
+     * @param inputInfo
+     */
+    public void putDrugCrfData(JSONObject jsonObject, InputInfo inputInfo) {
+        JSONObject aiOut = loadEntity(jsonObject, entityRelationObject, outputs, content);
+        if (aiOut == null) {
+            return;
+        }
+        EntityProcessDrug entityProcessDrug = new EntityProcessDrug();
+        List<Drug> drugs = entityProcessDrug.extractEntity(aiOut);
+        LeaveHospitalDoc leaveHospitalDoc = inputInfo.getLeaveHospitalDoc();
+        if (leaveHospitalDoc.getLeaveHospitalLabel() == null) {
+            LeaveHospitalLabel label = new LeaveHospitalLabel();
+            label.setDrugs(drugs);
+            leaveHospitalDoc.setLeaveHospitalLabel(label);
         } else {
-            inputInfo.getLeaveHospitalDoc().getLeaveDiagLabel().setDiags(leaveHospitalLabel.getDiags());
+            leaveHospitalDoc.getLeaveHospitalLabel().setDrugs(drugs);
         }
-        //临床表现
-        inputInfo.getLeaveHospitalDoc().setLeaveHospitalLabel(leaveHospitalLabel);
     }
 
     /**

+ 44 - 16
kernel/src/main/java/com/lantone/qc/kernel/structure/ai/OperationAI.java

@@ -2,18 +2,22 @@ package com.lantone.qc.kernel.structure.ai;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.google.common.collect.Lists;
 import com.lantone.qc.kernel.client.CRFServiceClient;
+import com.lantone.qc.kernel.structure.ai.process.EntityProcessDrug;
 import com.lantone.qc.kernel.structure.ai.process.EntityProcessOperationDiscussion;
 import com.lantone.qc.kernel.util.CatalogueUtil;
 import com.lantone.qc.pub.Content;
 import com.lantone.qc.pub.model.InputInfo;
 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.OperationDiscussionLabel;
 import com.lantone.qc.pub.util.StringUtil;
 
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 
 /**
  * @ClassName : OperationAI
@@ -25,10 +29,12 @@ public class OperationAI extends ModelAI {
     /**
      *
      */
-    public static List<String> medicalTextType = Arrays.asList("CourseAfterOperation_cx");
+    public static List<String> medicalTextType = Arrays.asList("CourseAfterOperation_cx", "CourseRecordSRR");
     public static String entityRelationObject = "entity_relation_object";
     public static String outputs = "outputs";
     public static String content = "content";
+    public static List<String> discussionKey = Lists.newArrayList("术前诊断", "术中诊断", "手术名称", "麻醉方式"
+            , "手术经过", "目前情况", "术后注意事项");
 
     public void medrec(InputInfo inputInfo, CRFServiceClient crfServiceClient) {
         JSONArray crfContent = new JSONArray();
@@ -38,7 +44,12 @@ public class OperationAI extends ModelAI {
                 continue;
             }
             OperationDiscussionDoc operationDiscussionDoc = operationDocs.get(i).getOperationDiscussionDoc();
-            putContent(crfContent, medicalTextType.get(0), operationDiscussionDoc.getText(), Content.operation_Discussion + i);
+            Map<String, String> structureMap = operationDiscussionDoc.getStructureMap();
+            String discussionText = CatalogueUtil.structureMapJoin(structureMap, discussionKey);
+            putContent(crfContent, medicalTextType.get(0), discussionText, Content.operation_Discussion + i);
+            //存放抓取的药品
+            String content = CatalogueUtil.structureMapJoin(structureMap, Lists.newArrayList("治疗计划和措施"));
+            putContent(crfContent, medicalTextType.get(1), content, Content.operation_Discussion + i + "药物");
         }
 
         JSONObject midData = loadAI(inputInfo.isUseCrfCache(), inputInfo.getMedicalRecordInfoDoc().getStructureMap().get("behospitalCode"), crfContent, crfServiceClient);//crf返回数据
@@ -47,7 +58,19 @@ public class OperationAI extends ModelAI {
             if (midData.get(Content.operation_Discussion + i) == null) {
                 continue;
             }
-            putOperationDiscussionCrfData(midData.getJSONObject(Content.operation_Discussion + i), inputInfo);
+            OperationDiscussionDoc discussionDoc = operationDocs.get(i).getOperationDiscussionDoc();
+            OperationDiscussionLabel discussionLabel = putOperationDiscussionCrfData(midData.getJSONObject(Content.operation_Discussion + i));
+            if (discussionLabel != null) {
+                discussionDoc.setOperationDiscussionLabel(discussionLabel);
+            }
+            //药品
+            if (midData.get(Content.operation_Discussion + i + "药物") != null) {
+                discussionLabel = operationDocs.get(i).getOperationDiscussionDoc().getOperationDiscussionLabel();
+                if (discussionLabel == null) {
+                    discussionLabel = new OperationDiscussionLabel();
+                }
+                putDrugCrfData(midData.getJSONObject(Content.operation_Discussion + i + "药物"), discussionLabel);
+            }
         }
     }
 
@@ -55,26 +78,31 @@ public class OperationAI extends ModelAI {
      * 处理手术记录
      *
      * @param jsonObject
-     * @param inputInfo
      */
-    public void putOperationDiscussionCrfData(JSONObject jsonObject, InputInfo inputInfo) {
+    public OperationDiscussionLabel putOperationDiscussionCrfData(JSONObject jsonObject) {
         JSONObject aiOut = loadEntity(jsonObject, entityRelationObject, outputs, content);
         if (aiOut == null) {
-            return;
+            return null;
         }
         String originalText = jsonObject.getString("originalText");
-        //使用现病史结构来处理病历特点
         EntityProcessOperationDiscussion entityProcessOperationDiscussion = new EntityProcessOperationDiscussion();
-        OperationDiscussionLabel operationDiscussionLabel = entityProcessOperationDiscussion.extractEntity(aiOut);
-        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
-        for (OperationDoc operationDoc : operationDocs) {
-            OperationDiscussionDoc operationDiscussionDoc = operationDoc.getOperationDiscussionDoc();
-            String text = operationDiscussionDoc.getText();
-            if (StringUtil.isNotBlank(text) && StringUtil.isNotBlank(originalText) && text.equals(originalText)) {
-                operationDiscussionDoc.setOperationDiscussionLabel(operationDiscussionLabel);
-                break;
-            }
+        return entityProcessOperationDiscussion.extractEntity(aiOut);
+    }
+
+    /**
+     * 存放抓取的药品
+     *
+     * @param jsonObject
+     * @param operationDiscussionLabel
+     */
+    public void putDrugCrfData(JSONObject jsonObject, OperationDiscussionLabel operationDiscussionLabel) {
+        JSONObject aiOut = loadEntity(jsonObject, entityRelationObject, outputs, content);
+        if (aiOut == null) {
+            return;
         }
+        EntityProcessDrug entityProcessDrug = new EntityProcessDrug();
+        List<Drug> drugs = entityProcessDrug.extractEntity(aiOut);
+        operationDiscussionLabel.setDrugs(drugs);
     }
 
     protected void putContent(JSONArray crfContent, String medicalTextType, String text, String sign) {

+ 41 - 39
kernel/src/main/java/com/lantone/qc/kernel/structure/ai/ThreeLevelWardAI.java

@@ -96,19 +96,19 @@ public class ThreeLevelWardAI extends ModelAI {
 
         //主治医师首次查房记录模型输出
         if (midData.get(Content.attend) != null) {
-            putWardRoundCrfData(midData.getJSONObject(Content.attend), inputInfo, 0);//查房记录
+            attendingDocs.get(0).setThreeLevelWardLabel(putWardRoundCrfData(midData.getJSONObject(Content.attend)));
         }
         //主任医师首次查房记录模型输出
         if (midData.get(Content.director) != null) {
-            putWardRoundCrfData(midData.getJSONObject(Content.director), inputInfo, 0);//查房记录
+            directorDocs.get(0).setThreeLevelWardLabel(putWardRoundCrfData(midData.getJSONObject(Content.director)));
         }
         //主任医师最后一次查房记录模型输出
         if (midData.get(Content.director + "最后一次") != null) {
-            putWardRoundCrfData(midData.getJSONObject(Content.director + "最后一次"), inputInfo, 0);//最后一次查房记录
+            directorDocs.get(directorDocs.size() - 1).setThreeLevelWardLabel(putWardRoundCrfData(midData.getJSONObject(Content.director + "最后一次")));
         }
         //最后一次查房记录模型输出
         if (midData.get("末次查房") != null) {
-            putWardRoundCrfData(midData.getJSONObject("末次查房"), inputInfo, 0);//最后一次查房记录
+            allDoctorWradDocs.get(allDoctorWradDocs.size() - 1).setThreeLevelWardLabel(Lists.newArrayList(putWardRoundCrfData(midData.getJSONObject("末次查房"))));
         }
         //疑难患者副高及以上查房记录模型输出
         if (inputInfo.getDifficultCaseDiscussDocs().size() > 0 && ListUtil.isNotEmpty(directorDifficultRecord)) {
@@ -153,7 +153,7 @@ public class ThreeLevelWardAI extends ModelAI {
     }
 
     /**
-     * 处理查房记录
+     * 处理全部查房记录
      *
      * @param jsonObject
      * @param inputInfo
@@ -165,51 +165,53 @@ public class ThreeLevelWardAI extends ModelAI {
         }
         String wardDate = jsonObject.getString("wardDate");
         String detailTitle = jsonObject.getString("detail_title");
-        //使用现病史结构来处理病历特点
         EntityProcessThreeLevelWard entityProcessThreeLevelWard = new EntityProcessThreeLevelWard();
         ThreeLevelWardLabel threeLevelWardLabel = entityProcessThreeLevelWard.extractEntity(aiOut);
         threeLevelWardLabel.setTitle(detailTitle);
         threeLevelWardLabel.setSerious(serious);
         ThreeLevelWardDoc threeLevelWardDoc = inputInfo.getThreeLevelWardDocs().get(0);
-        if (serious == 0) {//处理主治/主任查房记录
-            switch (detailTitle) {
-                case Content.attend:
-                    threeLevelWardDoc.getAttendingDoctorWardDocs().get(0).setThreeLevelWardLabel(threeLevelWardLabel);
-                    break;
-                case Content.director:
-                    threeLevelWardDoc.getDirectorDoctorWardDocs().get(0).setThreeLevelWardLabel(threeLevelWardLabel);
-                    break;
-                case Content.director + "最后一次":
-                    List<DirectorDoctorWardDoc> director = threeLevelWardDoc.getDirectorDoctorWardDocs();
-                    director.get(director.size() - 1).setThreeLevelWardLabel(threeLevelWardLabel);
-                    break;
-                case "末次查房":
-                    List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDoc.getAllDoctorWradDocs();
-                    List<ThreeLevelWardLabel> lastWardLebelList = new ArrayList<>();
-                    lastWardLebelList.add(threeLevelWardLabel);
-                    allDoctorWradDocs.get(allDoctorWradDocs.size() - 1).setThreeLevelWardLabel(lastWardLebelList);
-                    break;
-            }
-            //2020/08/20新增所有查房记录抽取:实验室检查、辅助检查、药品等
-            Pattern p = Pattern.compile("\\d");
-            Matcher matcher = p.matcher(detailTitle);
-            if (matcher.find()) {
-                String num = matcher.group(0);
-                int n = Integer.parseInt(num);
+        //2020/08/20新增所有查房记录抽取:实验室检查、辅助检查、药品等
+        Pattern p = Pattern.compile("\\d+");
+        Matcher matcher = p.matcher(detailTitle);
+        if (matcher.find()) {
+            String num = matcher.group(0);
+            int n = Integer.parseInt(num);
+            ThreeLevelWardDoc doc = threeLevelWardDoc.getAllDoctorWradDocs().get(n);
+            if (doc.getThreeLevelWardLabel().size() > 0) {
+                doc.getThreeLevelWardLabel().add(threeLevelWardLabel);
+            } else {
                 threeLevelWardDoc.getAllDoctorWradDocs().get(n).setThreeLevelWardLabel(Lists.newArrayList(threeLevelWardLabel));
             }
-        } else {
-            List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDoc.getAllDoctorWradDocs();
-            for (ThreeLevelWardDoc wardDoc : allDoctorWradDocs) {
-                String date = wardDoc.getStructureMap().get("查房日期");
-                if (StringUtil.isNotBlank(date) && StringUtil.isNotBlank(wardDate) && date.equals(wardDate)) {
-                    wardDoc.getThreeLevelWardLabel().add(threeLevelWardLabel);
-                    break;
-                }
+        }
+        List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDoc.getAllDoctorWradDocs();
+        for (ThreeLevelWardDoc wardDoc : allDoctorWradDocs) {
+            String date = wardDoc.getStructureMap().get("查房日期");
+            if (StringUtil.isNotBlank(date) && StringUtil.isNotBlank(wardDate) && date.equals(wardDate)) {
+                wardDoc.getThreeLevelWardLabel().add(threeLevelWardLabel);
+                break;
             }
         }
     }
 
+    /**
+     * 处理主治主任首次、末次查房
+     *
+     * @param jsonObject
+     * @return
+     */
+    public ThreeLevelWardLabel putWardRoundCrfData(JSONObject jsonObject) {
+        JSONObject aiOut = loadEntity(jsonObject, entityRelationObject, outputs, content);
+        if (aiOut == null) {
+            return new ThreeLevelWardLabel();
+        }
+        String detailTitle = jsonObject.getString("detail_title");
+        EntityProcessThreeLevelWard entityProcessThreeLevelWard = new EntityProcessThreeLevelWard();
+        ThreeLevelWardLabel threeLevelWardLabel = entityProcessThreeLevelWard.extractEntity(aiOut);
+        threeLevelWardLabel.setTitle(detailTitle);
+        return entityProcessThreeLevelWard.extractEntity(aiOut);
+
+    }
+
     /**
      * 存放每条疑难病例讨论记录后第一条查房记录
      *

+ 39 - 0
kernel/src/main/java/com/lantone/qc/kernel/structure/ai/process/EntityProcessDrug.java

@@ -0,0 +1,39 @@
+package com.lantone.qc.kernel.structure.ai.process;
+
+import com.alibaba.fastjson.JSONObject;
+import com.lantone.qc.kernel.structure.ai.model.EntityEnum;
+import com.lantone.qc.kernel.structure.ai.model.Lemma;
+import com.lantone.qc.pub.model.entity.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Component
+public class EntityProcessDrug extends EntityProcess {
+    private Logger logger = LoggerFactory.getLogger(EntityProcessDrug.class);
+
+    public List<Drug> extractEntity(JSONObject aiOut) {
+        //药物
+        List<Drug> drugs = new ArrayList<>();
+        try {
+            List<Lemma> DrugLemmas = createEntityTree(aiOut, EntityEnum.DRUG.toString());
+            for (Lemma lemma : DrugLemmas) {
+                Drug drug = new Drug();
+                drug.setName(lemma.getText());
+                drug.setConsumption(findT(lemma, new Consumption(), EntityEnum.CONSUMPTION.toString().split("-")[0]));
+                drug.setUsageWardRound(findT(lemma, new UsageWardRound(), EntityEnum.USAGE_WARD_ROUND.toString()));
+                drug.setFrequency(findT(lemma, new Frequency(), EntityEnum.FREQUENCY.toString()));
+                drug.setStop(findT(lemma, new Stop(), EntityEnum.STOP.toString()));
+                drug.setReasonsForAntibiotic(findT(lemma, new ReasonsForAntibiotic(), EntityEnum.REASONS_FOR_ANTIBIOTIC.toString()));
+                drugs.add(drug);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            logger.error(e.getMessage(), e);
+        }
+        return drugs;
+    }
+}

+ 10 - 17
public/src/main/java/com/lantone/qc/pub/model/label/LeaveHospitalLabel.java

@@ -1,14 +1,6 @@
 package com.lantone.qc.pub.model.label;
 
-import com.lantone.qc.pub.model.entity.BetterFinding;
-import com.lantone.qc.pub.model.entity.Chief;
-import com.lantone.qc.pub.model.entity.Diag;
-import com.lantone.qc.pub.model.entity.DoctorAdvice;
-import com.lantone.qc.pub.model.entity.Notes;
-import com.lantone.qc.pub.model.entity.Outcome;
-import com.lantone.qc.pub.model.entity.OutcomeCure;
-import com.lantone.qc.pub.model.entity.OutcomeToBetter;
-import com.lantone.qc.pub.model.entity.PositiveFinding;
+import com.lantone.qc.pub.model.entity.*;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -24,12 +16,13 @@ import java.util.List;
 @Getter
 @Setter
 public class LeaveHospitalLabel {
-    List<Chief> chiefs = new ArrayList<>();   //主诉
-    List<Notes> noteses = new ArrayList<>();   //注意事项
-    DoctorAdvice doctorAdvices;   //医嘱信息
-    List<Diag> diags = new ArrayList<>();   //出院诊断
-    List<BetterFinding> betterFindings = new ArrayList<>();   //好转表现
-    List<OutcomeToBetter> outcomeToBetters = new ArrayList<>();   //转归情况-好转
-    List<OutcomeCure> outcomeCures = new ArrayList<>();   //转归情况-治愈
-    List<PositiveFinding> positiveFindings = new ArrayList<>();   //阳性表现
+    private List<Chief> chiefs = new ArrayList<>();   //主诉
+    private List<Notes> noteses = new ArrayList<>();   //注意事项
+    private DoctorAdvice doctorAdvices;   //医嘱信息
+    private List<Diag> diags = new ArrayList<>();   //出院诊断
+    private List<BetterFinding> betterFindings = new ArrayList<>();   //好转表现
+    private List<OutcomeToBetter> outcomeToBetters = new ArrayList<>();   //转归情况-好转
+    private List<OutcomeCure> outcomeCures = new ArrayList<>();   //转归情况-治愈
+    private List<PositiveFinding> positiveFindings = new ArrayList<>();   //阳性表现
+    private List<Drug> drugs = new ArrayList<>();  //药物
 }

+ 7 - 10
public/src/main/java/com/lantone/qc/pub/model/label/OperationDiscussionLabel.java

@@ -1,10 +1,6 @@
 package com.lantone.qc.pub.model.label;
 
-import com.lantone.qc.pub.model.entity.Clinical;
-import com.lantone.qc.pub.model.entity.Diag;
-import com.lantone.qc.pub.model.entity.Sign;
-import com.lantone.qc.pub.model.entity.TreatmentPlan;
-import com.lantone.qc.pub.model.entity.Vital;
+import com.lantone.qc.pub.model.entity.*;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -20,9 +16,10 @@ import java.util.List;
 @Getter
 @Setter
 public class OperationDiscussionLabel {
-    String operativeFindings;   //手术经过文本(术中所见)
-    String riskAfterOp;    //术后风险文本
-    String attentionAfterOp;    //术后注意事项文本(处理及注意事项)
-    String measuresAfterOp;    //术后处理措施文本(处理及注意事项)
-    List<Vital> vitals = new ArrayList<>();   //生命体征实体
+    private String operativeFindings;   //手术经过文本(术中所见)
+    private String riskAfterOp;    //术后风险文本
+    private String attentionAfterOp;    //术后注意事项文本(处理及注意事项)
+    private String measuresAfterOp;    //术后处理措施文本(处理及注意事项)
+    private List<Vital> vitals = new ArrayList<>();   //生命体征实体
+    private List<Drug> drugs = new ArrayList<>();  //药物
 }