MedicalCalculator.php 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. <?php
  2. declare (strict_types = 1);
  3. namespace app\model;
  4. use think\Model;
  5. class MedicalCalculator extends Model
  6. {
  7. protected $name = 'medical_calculators';
  8. protected $autoWriteTimestamp = false;
  9. protected $schema = [
  10. 'id' => 'int',
  11. 'name' => 'string',
  12. 'disease_name'=> 'string',
  13. 'formula' => 'string',
  14. 'instructions'=> 'string',
  15. 'results' => 'string'
  16. ];
  17. protected $json = ['results'];
  18. public function questions()
  19. {
  20. return $this->hasMany(MedicalQuestion::class, 'medical_calculator_id', 'id');
  21. }
  22. public function calculateResult(array $inputs)
  23. {
  24. $formula = $this->formula;
  25. // 检查公式中 `=` 的数量
  26. $equalsCount = substr_count($formula, '=');
  27. if ($equalsCount > 0) {
  28. // 分割公式,使用换行符作为分隔符
  29. $formulas = preg_split('/\r\n|\r|\n/', $formula);
  30. foreach ($formulas as $f) {
  31. // 提取等号右边的表达式
  32. if (strpos($f, '=') !== false) {
  33. list($label, $expr) = explode('=', $f);
  34. // 检查公式中的变量是否都在输入中
  35. preg_match_all('/\b([a-zA-Z_]\w*)\b/', $expr, $matches);
  36. $formulaVariables = array_unique($matches[1]);
  37. $allVariablesExist = true;
  38. foreach ($formulaVariables as $variable) {
  39. if (!isset($inputs[$variable])) {
  40. $allVariablesExist = false;
  41. break;
  42. }
  43. }
  44. if ($allVariablesExist) {
  45. $formula = $expr;
  46. break;
  47. }
  48. }
  49. }
  50. } else {
  51. // 如果没有等号,直接使用整个公式
  52. preg_match_all('/\b([a-zA-Z_]\w*)\b/', $formula, $matches);
  53. $formulaVariables = array_unique($matches[1]);
  54. }
  55. // 将百分比转换为小数
  56. $formula = str_replace('%', '/100', $formula);
  57. foreach ($formulaVariables as $variable) {
  58. if (!isset($inputs[$variable])) {
  59. throw new \Exception("缺少变量: {$variable}");
  60. }
  61. if (!is_numeric($inputs[$variable])) {
  62. throw new \Exception("变量不是数字: {$variable}");
  63. }
  64. // 使用正则表达式确保只替换完整的变量名,并用括号包裹数值避免运算优先级问题
  65. $formula = preg_replace('/\b' . preg_quote($variable, '/') . '\b/',
  66. '(' . floatval($inputs[$variable]) . ')',
  67. $formula
  68. );
  69. }
  70. // 输出替换后的公式以便调试
  71. trace('Processed formula: ' . $formula);
  72. try {
  73. // 计算结果
  74. $result = eval('return ' . $formula . ';');
  75. if ($result === false || !is_numeric($result)) {
  76. throw new \Exception("计算公式错误");
  77. }
  78. return floatval($result);
  79. } catch (\ParseError $e) {
  80. throw new \Exception("计算公式语法错误: " . $e->getMessage());
  81. }
  82. }
  83. public function getResultInterpretation($value)
  84. {
  85. $results = $this->results;
  86. if (!is_array($results)) {
  87. return null;
  88. }
  89. foreach ($results as $result) {
  90. if (isset($result['min']) && isset($result['max'])) {
  91. if ($value >= $result['min'] && $value <= $result['max']) {
  92. return $result;
  93. }
  94. }
  95. }
  96. return null;
  97. }
  98. }