diff --git a/pom.xml b/pom.xml
index 6d7a6c7..a632091 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@
com.iflytop
a800
- 0.0.10
+ 0.0.11
boditech-a800
boditech-a800
@@ -20,7 +20,7 @@
com.iflytop
uf
- 0.0.43
+ 0.0.57
diff --git a/src/main/java/com/iflytop/a800/utils/ScanResultAnalyseResultItem.java b/src/main/java/com/iflytop/a800/utils/ScanResultAnalyseResultItem.java
new file mode 100644
index 0000000..ad0b268
--- /dev/null
+++ b/src/main/java/com/iflytop/a800/utils/ScanResultAnalyseResultItem.java
@@ -0,0 +1,6 @@
+package com.iflytop.a800.utils;
+public class ScanResultAnalyseResultItem {
+ public String name;
+ public double value;
+ public String unit;
+}
diff --git a/src/main/java/com/iflytop/a800/utils/ScanResultAnalyser.java b/src/main/java/com/iflytop/a800/utils/ScanResultAnalyser.java
new file mode 100644
index 0000000..8538d93
--- /dev/null
+++ b/src/main/java/com/iflytop/a800/utils/ScanResultAnalyser.java
@@ -0,0 +1,143 @@
+package com.iflytop.a800.utils;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.iflytop.a800.model.MdbIdChip;
+import com.iflytop.uf.util.UfJsonHelper;
+import java.util.*;
+public class ScanResultAnalyser {
+ // id chip
+ private final MdbIdChip idChip;
+
+ // constructor
+ public ScanResultAnalyser( MdbIdChip idChip ) {
+ this.idChip = idChip;
+ }
+
+ // analyse
+ public List analyse( String sampleType, float[] scanResult ) {
+ var algo = new ScanResultAnalysisAlgo();
+ var algoResult = algo.calculate(scanResult, this.idChip.peakCount);
+
+ // 处理
+ List results = new ArrayList<>();
+ var projects = UfJsonHelper.jsonToNode(idChip.items);
+ for ( var i=0; i< idChip.itemCount; i++ ) {
+ double valueX = 0;
+ JsonNode funcInfo = null;
+
+ var project = projects.get(i);
+ var itemName = project.get("item").asText();
+ var isPiecewiseFunction = project.get("isPiecewiseFunction").asBoolean();
+ if ( !isPiecewiseFunction ) { // 非分段函数
+ var func = project.get("nonPiecewiseFunction");
+ var xValueSource = func.get("xValueSource").asInt();
+ valueX = this.calculateRatio(algoResult, xValueSource, itemName);
+ funcInfo = func.get("serum");
+ if ("WB".equals(sampleType)) {
+ funcInfo = func.get("wb");
+ }
+ } else { // 分段函数
+ var func = project.get("piecewiseFunction");
+ var piecewiseValueSrc = func.get("piecewiseValueSrc").asInt();
+ var piecewiseValueSrcValue = this.calculateRatio(algoResult, piecewiseValueSrc, itemName);
+ var piecewiseValue = func.get("piecewiseValue").asDouble();
+ if ( piecewiseValueSrcValue > piecewiseValue ) { // 高浓度
+ var highXValueSource = func.get("highXValueSource").asInt();
+ valueX = this.calculateRatio(algoResult, highXValueSource, itemName);
+ funcInfo = func.get("serumHigh");
+ if ("WB".equals(sampleType)) {
+ funcInfo = func.get("wbHigh");
+ }
+ } else { // 低浓度
+ var lowXValueSource = func.get("lowXValueSource").asInt();
+ valueX = this.calculateRatio(algoResult, lowXValueSource, itemName);
+ funcInfo = func.get("serumLow");
+ if ("WB".equals(sampleType)) {
+ funcInfo = func.get("wbLow");
+ }
+ }
+ }
+
+ double valueD = funcInfo.get("d").asDouble();
+ double valueB = funcInfo.get("b").asDouble();
+ double valueC = funcInfo.get("c").asDouble();
+ double valueA = funcInfo.get("a").asDouble();
+ double value = valueA * Math.pow(valueX,3) + valueB * Math.pow(valueX,2) + valueC * valueX + valueD;
+
+ // @TODO : 单位也要从配置中读取
+ var result = new ScanResultAnalyseResultItem();
+ result.name = itemName;
+ result.value = value;
+ result.unit = "xx/xx";
+ results.add(result);
+ }
+
+ return results;
+ }
+
+ /**
+ * @link https://iflytop1.feishu.cn/docx/UnRtdSG4qouMTaxzRb2cjiTTnZe
+ * @link https://iflytop1.feishu.cn/docx/A0CHdQL6OoTTCSx8MB7cQKEjnSc
+ * @param result - algo result
+ * @param xSource - x source
+ * @return double - value of ratio
+ */
+ private double calculateRatio(ScanResultAnalysisAlgo.AlgoResult result, int xSource, String itenName) {
+ // 计算 ratio
+ Map ratios = new HashMap<>();
+ if ( 5 == idChip.scanPeakCount ) {
+ var peaks = result.peakInfos;
+ ratios.put("ratio", peaks[3].area / peaks[4].area); // T/C
+ ratios.put("antiRatio", peaks[3].area / peaks[4].area); // H/C
+ ratios.put("antiTestRatio", peaks[3].area / peaks[2].area); // T/H
+ ratios.put("rfRatio", peaks[1].area / peaks[4].area); // R/C
+ ratios.put("rtRatio", peaks[3].area / peaks[1].area); // T/R
+ ratios.put("t4Ratio", peaks[0].area / peaks[4].area); // T4/C
+ ratios.put("t4t3Ratio", peaks[1].area / peaks[0].area); // R/T4
+ } else if ( 4 == idChip.scanPeakCount && Objects.equals(idChip.scanType, 1) ) { // F 光学
+ var peaks = result.peakInfos; // H T C
+ ratios.put("ratio", peaks[1].area / peaks[2].area); // T/C
+ ratios.put("antiRatio", peaks[0].area / peaks[2].area); // H/C
+ ratios.put("antiTestRatio", peaks[1].area / peaks[0].area); // T/H
+ ratios.put("rfRatio", peaks[0].area / peaks[2].area); // R/C @TODO : 待定, 三联卡F光学没有R
+ ratios.put("rtRatio", peaks[1].area / peaks[0].area); // T/R @TODO : 待定, 三联卡F光学没有R
+ } else if ( 4 == idChip.scanPeakCount && Objects.equals(idChip.scanType, 2) ) { // T 光学
+ var peaks = result.peakInfos; // R H T C
+ ratios.put("ratio", peaks[2].area / peaks[3].area); // T/C
+ ratios.put("antiRatio", peaks[1].area / peaks[3].area); // H/C
+ ratios.put("antiTestRatio", peaks[2].area / peaks[1].area); // T/H
+ ratios.put("rfRatio", peaks[0].area / peaks[3].area); // R/C
+ ratios.put("rtRatio", peaks[2].area / peaks[0].area); // T/R
+ } else if ( 3 == idChip.scanPeakCount ) {
+ var peaks = result.peakInfos; // H T C
+ ratios.put("ratio", peaks[1].area / peaks[2].area); // T/C
+ ratios.put("antiRatio", peaks[0].area / peaks[2].area); // H/C
+ ratios.put("antiTestRatio", peaks[1].area / peaks[0].area); // T/H
+ } else if ("PCT".equals(itenName)) {
+ var peaks = result.peakInfos; // C T
+ ratios.put("ratio", peaks[1].area / peaks[0].area); // T/C
+ } else if ( 2 == idChip.scanPeakCount ) {
+ var peaks = result.peakInfos; // T C
+ ratios.put("ratio", peaks[0].area / peaks[1].area); // T/C
+ } else {
+ throw new RuntimeException("unknown scan peak count" + idChip.scanPeakCount);
+ }
+
+ // calculate ratio by x source
+ if ( 1 == xSource ) {
+ return ratios.get("ratio");
+ } else if ( 2 == xSource ) {
+ return ratios.get("antiTestRatio");
+ } else if ( 3 == xSource ) {
+ return ratios.get("antiRatio");
+ } else if ( 4 == xSource ) {
+ return ratios.get("ratio") + ratios.get("antiTestRatio");
+ } else if ( 5 == xSource ) {
+ // @TODO : 这里 R-ratio 不知道是啥
+ throw new RuntimeException("不知道 R-Ratio 是啥");
+ } else if ( 6 == xSource ) {
+ return ratios.get("t4Ratio");
+ } else {
+ throw new RuntimeException("unknown x source" + xSource);
+ }
+ }
+}