Browse Source

1、小鼠公式结构

guanxinyi 10 months ago
parent
commit
ea92ab2be4

+ 22 - 4
lib/process/calcuators/formulas/Urology.dart

@@ -1,13 +1,31 @@
 // ignore_for_file:  constant_identifier_names
 
-import 'dart:math' as math;
-
-import 'package:fis_measure/interfaces/date_types/point.dart';
+import 'package:fis_measure/configs/patient.dart';
+import 'package:fis_measure/interfaces/enums/species.dart';
 
 class UrologyFormulas {
-  /// 计算残余尿
+  UrologyFormulas._();
+  static final IUrologyFormulaStrategy _singleton =
+      GlobalPatientConfig.speciesType != SpeciesType.general
+          ? BaseUrologyFormulas()
+          : MouseUrologyFormulas();
+
   static double calcRUV(double d1, double d2) {
+    return _singleton.calcRUV(d1, d2);
+  }
+}
+
+abstract class IUrologyFormulaStrategy {
+  double calcRUV(double d1, double d2);
+}
+
+class BaseUrologyFormulas implements IUrologyFormulaStrategy {
+  /// 计算残余尿
+  @override
+  double calcRUV(double d1, double d2) {
     double ruv = d1 * d2 * 5.9 - 14.9;
     return ruv < 0 ? 0 : ruv;
   }
 }
+
+class MouseUrologyFormulas extends BaseUrologyFormulas {}

+ 11 - 2
lib/process/calcuators/formulas/cardiac.dart

@@ -44,6 +44,10 @@ class CardiacFormulas {
       _singleton.dviByVTI(otvti, vti);
   static double avaIndex(double avaByVTI, double bsa) =>
       _singleton.avaIndex(avaByVTI, bsa);
+  static double lvevi(double lvev, double bsa) => _singleton.lvevi(lvev, bsa);
+  static double lvSimsonVolume(double l, List<double>? a, List<double>? b,
+          [int num = 20]) =>
+      _singleton.lvSimsonVolume(l, a, b, num);
 
   CardiacFormulas._internal(); // 私有构造函数
 }
@@ -69,6 +73,9 @@ abstract class ICardiacFormulaStrategy {
   double flowAreaByVTI(double otDiam, double otvti, double vti);
   double dviByVTI(double otvti, double vti);
   double avaIndex(double avaByVTI, double bsa);
+  double lvevi(double lvev, double bsa);
+  double lvSimsonVolume(double l, List<double>? a, List<double>? b,
+      [int num = 20]);
 }
 
 class BaseCardiacFormulas implements ICardiacFormulaStrategy {
@@ -192,7 +199,8 @@ class BaseCardiacFormulas implements ICardiacFormulaStrategy {
   /// <param name="lvev">Unit cm³</param>
   /// <param name="bsa">Unit m²</param>
   /// <returns>cm³/m²</returns>
-  static double lvevi(double lvev, double bsa) {
+  @override
+  double lvevi(double lvev, double bsa) {
     return lvev / bsa;
   }
 
@@ -316,7 +324,8 @@ class BaseCardiacFormulas implements ICardiacFormulaStrategy {
   /// Formular : V= π/4×∑_(i=1)^20▒〖(a_i×b_i)〗×L/20
   /// </summary>
   /// <returns></returns>
-  static double lvSimsonVolume(double l, List<double>? a, List<double>? b,
+  @override
+  double lvSimsonVolume(double l, List<double>? a, List<double>? b,
       [int num = 20]) {
     double volume = double.nan;
     if (a != null && b != null) {

+ 128 - 19
lib/process/calcuators/formulas/general.dart

@@ -2,11 +2,101 @@
 
 import 'dart:math' as math;
 
+import 'package:fis_measure/configs/patient.dart';
 import 'package:fis_measure/interfaces/date_types/point.dart';
+import 'package:fis_measure/interfaces/enums/species.dart';
 
 class GeneralFormulas {
   GeneralFormulas._();
+  static const double VolumeCofficient = math.pi / 6.0;
+
+  static final IGeneralFormulaStrategy _singleton =
+      GlobalPatientConfig.speciesType != SpeciesType.general
+          ? BaseGeneralFormulas()
+          : MouseGeneralFormulas();
+
+  static double volumeTwoLine(double d1, double d2,
+          [bool useBigValue = true]) =>
+      _singleton.volumeTwoLine(d1, d2, useBigValue);
+
+  static double volumeWithCoefficient(
+          double d1, double d2, double d3, double coefficient) =>
+      _singleton.volumeWithCoefficient(d1, d2, d3, coefficient);
+
+  static double countStenosis(double d1, double d2) =>
+      _singleton.countStenosis(d1, d2);
+
+  static bool doubleAlmostEquals(double num1, double num2,
+          [double precision = 0.000001]) =>
+      _singleton.doubleAlmostEquals(num1, num2, precision);
+
+  static double distance2Line(DPoint pt1, DPoint pt2, DPoint pt) =>
+      _singleton.distance2Line(pt1, pt2, pt);
+
+  static double countSlope(DPoint p1, DPoint p2) =>
+      _singleton.countSlope(p1, p2);
+
+  static double countEnvelopeTime(List<DPoint> points) =>
+      _singleton.countEnvelopeTime(points);
+
+  static double countPressure(double v) => _singleton.countPressure(v);
+
+  static double countRI(double ps, double mdEd) => _singleton.countRI(ps, mdEd);
+
+  static double countMaxPG(double v1, double v2) =>
+      _singleton.countMaxPG(v1, v2);
+
+  static double countHR(double timeSpan) => _singleton.countHR(timeSpan);
+
+  static List<double> countVTI(List<DPoint> tracePoints) =>
+      _singleton.countVTI(tracePoints);
+
+  static double svDiam(double diam, double vti) => _singleton.svDiam(diam, vti);
+
+  static double csa(double diam) => _singleton.csa(diam);
 
+  static double dpDtRatio(DPoint p1, DPoint p2) => _singleton.dpDtRatio(p1, p2);
+
+  static double maxPG(double v1, double v2) => _singleton.maxPG(v1, v2);
+
+  static double area(double d1, double d2) => _singleton.area(d1, d2);
+
+  static double flowVolTAMAX(
+          double flowArea, double tamean, double coefficient) =>
+      _singleton.flowVolTAMAX(flowArea, tamean, coefficient);
+}
+
+abstract class IGeneralFormulaStrategy {
+  double volumeTwoLine(double d1, double d2, [bool useBigValue = true]);
+  double volumeWithCoefficient(
+    double d1,
+    double d2,
+    double d3,
+    double coefficient,
+  );
+  double countStenosis(double d1, double d2);
+
+  bool doubleAlmostEquals(double num1, double num2,
+      [double precision = 0.000001]);
+  double distance2Line(DPoint pt1, DPoint pt2, DPoint pt);
+  double countSlope(DPoint p1, DPoint p2);
+  double countEnvelopeTime(List<DPoint> points);
+  double countPressure(double v);
+  double countRI(double ps, double mdEd);
+  double countMaxPG(double v1, double v2);
+  double countHR(double timeSpan);
+  List<double> countVTI(
+    List<DPoint> tracePoints,
+  );
+  double svDiam(double diam, double vti);
+  double csa(double diam);
+  double dpDtRatio(DPoint p1, DPoint p2);
+  double maxPG(double v1, double v2);
+  double area(double d1, double d2);
+  double flowVolTAMAX(double flowArea, double tamean, double coefficient);
+}
+
+class BaseGeneralFormulas implements IGeneralFormulaStrategy {
   /// Volume:1/6 x π
   static const double VolumeCofficient = math.pi / 6.0;
 
@@ -15,7 +105,8 @@ class GeneralFormulas {
   /// 1/6 x π x D1 x D2^2 (D1 ≤ D2)
   ///
   /// return unit: cm³</returns>
-  static double volumeTwoLine(double d1, double d2, [bool useBigValue = true]) {
+  @override
+  double volumeTwoLine(double d1, double d2, [bool useBigValue = true]) {
     double volume = 0;
     if (!doubleAlmostEquals(d1, 0) && !doubleAlmostEquals(d2, 0)) {
       if (useBigValue) {
@@ -38,7 +129,8 @@ class GeneralFormulas {
   /// 带比率系数算体积
   ///
   /// [coefficient] 比率系数
-  static double volumeWithCoefficient(
+  @override
+  double volumeWithCoefficient(
     double d1,
     double d2,
     double d3,
@@ -54,7 +146,8 @@ class GeneralFormulas {
   }
 
   /// 狭窄率计算
-  static double countStenosis(double d1, double d2) {
+  @override
+  double countStenosis(double d1, double d2) {
     double residual;
     double lumen;
     if (d1 > d2) {
@@ -67,7 +160,8 @@ class GeneralFormulas {
     return (1.0 - residual / lumen) * 100;
   }
 
-  static bool doubleAlmostEquals(double num1, double num2,
+  @override
+  bool doubleAlmostEquals(double num1, double num2,
       [double precision = 0.000001]) {
     if (num1.isNaN && num2.isNaN) return true;
     return (num1 - num2).abs() <= precision;
@@ -80,7 +174,8 @@ class GeneralFormulas {
   /// [pt2] 线端点2
   ///
   /// [pt] 点
-  static double distance2Line(DPoint pt1, DPoint pt2, DPoint pt) {
+  @override
+  double distance2Line(DPoint pt1, DPoint pt2, DPoint pt) {
     double dis = 0;
     if (pt1.x == pt2.x) {
       dis = (pt.x - pt1.x).abs();
@@ -93,7 +188,8 @@ class GeneralFormulas {
   }
 
   ///计算斜率
-  static double countSlope(DPoint p1, DPoint p2) {
+  @override
+  double countSlope(DPoint p1, DPoint p2) {
     if (doubleAlmostEquals(p2.x, p1.x)) return 0;
     double vertical = p2.y - p1.y;
     double time = (p2.x - p1.x).abs();
@@ -103,7 +199,8 @@ class GeneralFormulas {
 
   ///计算包络时间
   ///Origin: Vinno.Modules.MeasureModule\Formulas\GeneralFormulas.cs [632:67]
-  static double countEnvelopeTime(List<DPoint> points) {
+  @override
+  double countEnvelopeTime(List<DPoint> points) {
     if (points.length < 2) return 0;
     double startTime = double.maxFinite;
     double endTime = -double.maxFinite;
@@ -123,7 +220,8 @@ class GeneralFormulas {
   /// </summary>
   /// <param name="v">Unit cm/s</param>
   /// <returns>Unit mmHg</returns>
-  static double countPressure(double v) {
+  @override
+  double countPressure(double v) {
     // The velocity is in cm/s, but it should be m/s in this formula, so divide it by 100.
     double pg = 4.0 * math.pow(v * 0.01, 2);
     return pg;
@@ -136,7 +234,8 @@ class GeneralFormulas {
   /// </summary>
   /// <param name="ps">Unit cm/s</param>
   /// <param name="mdEd">Unit cm/s</param>
-  static double countRI(double ps, double mdEd) {
+  @override
+  double countRI(double ps, double mdEd) {
     ps = ps.abs();
     mdEd = mdEd.abs();
     double ri = (ps - mdEd) / ps;
@@ -152,7 +251,8 @@ class GeneralFormulas {
   /// <param name="v1">Unit cm/s</param>
   /// <param name="v2">Unit cm/s</param>
   /// <returns>Unit mmHg</returns>
-  static double countMaxPG(double v1, double v2) {
+  @override
+  double countMaxPG(double v1, double v2) {
     // The velocity is in cm/s, but it should be m/s in this formula, so divide it by 100.
     double meanPG =
         4.0 * (math.pow(v1 * 0.01, 2) - math.pow(v2 * 0.01, 2)).abs();
@@ -162,14 +262,16 @@ class GeneralFormulas {
   // 计算心率
   // TODO: 心脏周期(可配置) DefaultHeartCycle = 2;
   // Origin: Vinno.Modules.MeasureModule\Primitives\DopplerTraceBase.cs
-  static double countHR(double timeSpan) {
+  @override
+  double countHR(double timeSpan) {
     const defaultHeartCycle = 1;
     double hr = (defaultHeartCycle * 60 / timeSpan).roundToDouble();
     return hr;
   }
 
   // return [VTI,tiEnv,timeAveragedVelocity,pv,meanPG,hr];
-  static List<double> countVTI(
+  @override
+  List<double> countVTI(
     List<DPoint> tracePoints,
   ) {
     var tiEnv = 0.0;
@@ -239,7 +341,8 @@ class GeneralFormulas {
   /// [vti] `cm`
   ///
   /// return `cm3`
-  static double svDiam(double diam, double vti) {
+  @override
+  double svDiam(double diam, double vti) {
     double sv = math.pi * math.pow(diam, 2) * vti / 4;
     return sv;
   }
@@ -251,7 +354,8 @@ class GeneralFormulas {
   /// [diam] `cm`
   ///
   /// return `cm²`
-  static double csa(double diam) {
+  @override
+  double csa(double diam) {
     double csa = math.pi * math.pow(diam, 2) / 4;
     return csa;
   }
@@ -259,7 +363,8 @@ class GeneralFormulas {
   /// CW/PW Mode: dp/dt = (4* V2 * V2 - 4 * V1 * V1)/ (T2 - T1)
   ///
   /// return `mmHg/s`
-  static double dpDtRatio(DPoint p1, DPoint p2) {
+  @override
+  double dpDtRatio(DPoint p1, DPoint p2) {
     double dp = maxPG(p2.y, p1.y);
     double dt = (p2.x - p1.x).abs();
     double result = dp / dt;
@@ -273,7 +378,8 @@ class GeneralFormulas {
   /// [v2] `cm/s`
   ///
   /// reutrn `mmHg`
-  static double maxPG(double v1, double v2) {
+  @override
+  double maxPG(double v1, double v2) {
     // The velocity is in cm/s, but it should be m/s in this formula, so divide it by 100.
     double meanPG =
         4.0 * (math.pow(v1 * 0.01, 2) - math.pow(v2 * 0.01, 2)).abs();
@@ -287,7 +393,8 @@ class GeneralFormulas {
   /// [d2] `cm`
   ///
   /// return `cm²`
-  static double area(double d1, double d2) {
+  @override
+  double area(double d1, double d2) {
     double area = 0;
     if (!doubleAlmostEquals(d1, 0) && !doubleAlmostEquals(d2, 0)) {
       if ((d1 < 0.001 * d2) || (d2 < 0.001 * d1)) {
@@ -310,8 +417,8 @@ class GeneralFormulas {
   /// [coefficient] `[0.5,1.0]`
   ///
   /// return `cm³/s`
-  static double flowVolTAMAX(
-      double flowArea, double tamean, double coefficient) {
+  @override
+  double flowVolTAMAX(double flowArea, double tamean, double coefficient) {
     if (coefficient < 0.5 || coefficient > 1.0) {
       return double.nan;
     }
@@ -319,3 +426,5 @@ class GeneralFormulas {
     return flowVol;
   }
 }
+
+class MouseGeneralFormulas extends BaseGeneralFormulas {}

+ 24 - 2
lib/process/calcuators/formulas/obstetrics.dart

@@ -1,9 +1,27 @@
 import 'dart:math' as math;
+import 'package:fis_measure/configs/patient.dart';
+import 'package:fis_measure/interfaces/enums/species.dart';
 import 'package:fis_measure/utils/number.dart';
 
 class ObstetricsFormulas {
   ObstetricsFormulas._();
+  static final IObstetricsFormulaStrategy _singleton =
+      GlobalPatientConfig.speciesType != SpeciesType.general
+          ? BaseObstetricsFormulas()
+          : MouseObstetricsFormulas();
 
+  static double gsMean(double d1, double d2, double d3) =>
+      _singleton.gsMean(d1, d2, d3);
+  static double gsMax(double d1, double d2, double d3) =>
+      _singleton.gsMax(d1, d2, d3);
+}
+
+abstract class IObstetricsFormulaStrategy {
+  double gsMean(double d1, double d2, double d3);
+  double gsMax(double d1, double d2, double d3);
+}
+
+class BaseObstetricsFormulas implements IObstetricsFormulaStrategy {
   /// (D1 + D2 + D3)/3.0
   ///
   /// return Unit cm
@@ -13,7 +31,8 @@ class ObstetricsFormulas {
   /// [d2] Unit cm
   ///
   /// [d3] Unit cm
-  static double gsMean(double d1, double d2, double d3) {
+  @override
+  double gsMean(double d1, double d2, double d3) {
     double mean = double.nan;
     if (!NumUtil.almostEquals(d1, 0) &&
         !NumUtil.almostEquals(d2, 0) &&
@@ -24,7 +43,8 @@ class ObstetricsFormulas {
   }
 
   ///Max(D1, D2, D3)
-  static double gsMax(double d1, double d2, double d3) {
+  @override
+  double gsMax(double d1, double d2, double d3) {
     double max = double.nan;
     if (!(NumUtil.almostEquals(d1, 0) &&
         NumUtil.almostEquals(d2, 0) &&
@@ -34,3 +54,5 @@ class ObstetricsFormulas {
     return max;
   }
 }
+
+class MouseObstetricsFormulas extends BaseObstetricsFormulas {}