feat(server-go): 蚕房健康画像与年度发病统计(#24)
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// HealthInput 健康画像输入
|
||||
type HealthInput struct {
|
||||
RecentRiskLevels []string // 近 30 天巡检风险等级
|
||||
LampPositive int
|
||||
LampTotal int
|
||||
ConsultationCount int
|
||||
TraceCount int
|
||||
}
|
||||
|
||||
// ComputeHealthScore 综合健康分(0-100)与评级(优/良/中/差)
|
||||
func ComputeHealthScore(in HealthInput) (float64, string) {
|
||||
score := 100.0
|
||||
for _, level := range in.RecentRiskLevels {
|
||||
switch level {
|
||||
case "red":
|
||||
score -= 25
|
||||
case "orange":
|
||||
score -= 12
|
||||
case "yellow":
|
||||
score -= 4
|
||||
}
|
||||
}
|
||||
if in.LampTotal > 0 {
|
||||
score -= float64(in.LampPositive) / float64(in.LampTotal) * 30
|
||||
}
|
||||
score -= float64(in.ConsultationCount) * 10
|
||||
score -= float64(in.TraceCount) * 8
|
||||
if score < 0 {
|
||||
score = 0
|
||||
}
|
||||
if score > 100 {
|
||||
score = 100
|
||||
}
|
||||
grade := "差"
|
||||
switch {
|
||||
case score >= 85:
|
||||
grade = "优"
|
||||
case score >= 70:
|
||||
grade = "良"
|
||||
case score >= 55:
|
||||
grade = "中"
|
||||
}
|
||||
return score, grade
|
||||
}
|
||||
|
||||
// MonthDiseaseEntry 月度发病条目
|
||||
type MonthDiseaseEntry struct {
|
||||
Month string
|
||||
Disease string
|
||||
}
|
||||
|
||||
// MonthStat 月度发病统计
|
||||
type MonthStat struct {
|
||||
Month string `json:"month"`
|
||||
Total int `json:"total"`
|
||||
Diseases map[string]int `json:"diseases"`
|
||||
}
|
||||
|
||||
// AggregateMonthlyStats 按月份聚合发病数与病种分布(升序)
|
||||
func AggregateMonthlyStats(entries []MonthDiseaseEntry) []MonthStat {
|
||||
byMonth := make(map[string]*MonthStat)
|
||||
for _, e := range entries {
|
||||
if strings.TrimSpace(e.Month) == "" {
|
||||
continue
|
||||
}
|
||||
s, ok := byMonth[e.Month]
|
||||
if !ok {
|
||||
s = &MonthStat{Month: e.Month, Diseases: map[string]int{}}
|
||||
byMonth[e.Month] = s
|
||||
}
|
||||
s.Total++
|
||||
s.Diseases[e.Disease]++
|
||||
}
|
||||
result := make([]MonthStat, 0, len(byMonth))
|
||||
for _, s := range byMonth {
|
||||
result = append(result, *s)
|
||||
}
|
||||
sort.Slice(result, func(i, j int) bool { return result[i].Month < result[j].Month })
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user