feat: 完善环境规则、会诊治理、知识审核与效果评估
This commit is contained in:
@@ -3,6 +3,7 @@ package service
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// HealthInput 健康画像输入
|
||||
@@ -85,3 +86,99 @@ func AggregateMonthlyStats(entries []MonthDiseaseEntry) []MonthStat {
|
||||
sort.Slice(result, func(i, j int) bool { return result[i].Month < result[j].Month })
|
||||
return result
|
||||
}
|
||||
|
||||
// EffectWindow 处置前后评估窗口。
|
||||
type EffectWindow struct {
|
||||
BeforeStart time.Time `json:"beforeStart"`
|
||||
BeforeEnd time.Time `json:"beforeEnd"`
|
||||
AfterStart time.Time `json:"afterStart"`
|
||||
AfterEnd time.Time `json:"afterEnd"`
|
||||
}
|
||||
|
||||
// EffectMetrics 处置前后指标输入。
|
||||
type EffectMetrics struct {
|
||||
RiskSamples []float64 `json:"riskSamples"`
|
||||
LampPositive int `json:"lampPositive"`
|
||||
LampTotal int `json:"lampTotal"`
|
||||
Recurrences int `json:"recurrences"`
|
||||
Loss *float64 `json:"loss,omitempty"`
|
||||
Cost *float64 `json:"cost,omitempty"`
|
||||
}
|
||||
|
||||
// EffectReport 防控效果报告;缺失维度不按 0 当改善。
|
||||
type EffectReport struct {
|
||||
EventID string `json:"eventId"`
|
||||
Window EffectWindow `json:"window"`
|
||||
BeforeRiskAvg *float64 `json:"beforeRiskAvg,omitempty"`
|
||||
AfterRiskAvg *float64 `json:"afterRiskAvg,omitempty"`
|
||||
BeforePositiveRate *float64 `json:"beforePositiveRate,omitempty"`
|
||||
AfterPositiveRate *float64 `json:"afterPositiveRate,omitempty"`
|
||||
Recurrences int `json:"recurrences"`
|
||||
Missing []string `json:"missing"`
|
||||
Conclusion string `json:"conclusion"`
|
||||
}
|
||||
|
||||
// EvaluateControlEffect 对比指定窗口风险、阳性率和复发;缺失维度单独列出。
|
||||
func EvaluateControlEffect(eventID string, window EffectWindow, before, after EffectMetrics) EffectReport {
|
||||
report := EffectReport{
|
||||
EventID: eventID,
|
||||
Window: window,
|
||||
Recurrences: after.Recurrences,
|
||||
Missing: []string{},
|
||||
}
|
||||
if len(before.RiskSamples) > 0 {
|
||||
value := avg(before.RiskSamples)
|
||||
report.BeforeRiskAvg = &value
|
||||
} else {
|
||||
report.Missing = append(report.Missing, "before_risk")
|
||||
}
|
||||
if len(after.RiskSamples) > 0 {
|
||||
value := avg(after.RiskSamples)
|
||||
report.AfterRiskAvg = &value
|
||||
} else {
|
||||
report.Missing = append(report.Missing, "after_risk")
|
||||
}
|
||||
if before.LampTotal > 0 {
|
||||
value := float64(before.LampPositive) / float64(before.LampTotal)
|
||||
report.BeforePositiveRate = &value
|
||||
} else {
|
||||
report.Missing = append(report.Missing, "before_lamp")
|
||||
}
|
||||
if after.LampTotal > 0 {
|
||||
value := float64(after.LampPositive) / float64(after.LampTotal)
|
||||
report.AfterPositiveRate = &value
|
||||
} else {
|
||||
report.Missing = append(report.Missing, "after_lamp")
|
||||
}
|
||||
if before.Loss == nil {
|
||||
report.Missing = append(report.Missing, "before_loss")
|
||||
}
|
||||
if after.Loss == nil {
|
||||
report.Missing = append(report.Missing, "after_loss")
|
||||
}
|
||||
if before.Cost == nil {
|
||||
report.Missing = append(report.Missing, "before_cost")
|
||||
}
|
||||
if after.Cost == nil {
|
||||
report.Missing = append(report.Missing, "after_cost")
|
||||
}
|
||||
switch {
|
||||
case report.AfterRiskAvg == nil || report.BeforeRiskAvg == nil:
|
||||
report.Conclusion = "证据不足,无法判断效果"
|
||||
case *report.AfterRiskAvg < *report.BeforeRiskAvg && after.Recurrences == 0:
|
||||
report.Conclusion = "改善"
|
||||
case *report.AfterRiskAvg >= *report.BeforeRiskAvg:
|
||||
report.Conclusion = "未改善"
|
||||
default:
|
||||
report.Conclusion = "需人工复核"
|
||||
}
|
||||
return report
|
||||
}
|
||||
|
||||
func avg(values []float64) float64 {
|
||||
sum := 0.0
|
||||
for _, v := range values {
|
||||
sum += v
|
||||
}
|
||||
return sum / float64(len(values))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user