Files
silk/server-go/internal/service/trace.go
T

185 lines
6.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package service
import (
"fmt"
"time"
)
// EnvSample 环境回溯样本
type EnvSample struct {
Time time.Time
Temp *float64
Humidity *float64
}
// EnvironmentResult 环境回溯结果
type EnvironmentResult struct {
HighHumidity bool
TempSwing bool
Summary string
}
// EnvironmentBacktrack 发病前环境回溯:湿度≥阈值 或 温度>30/<20 触发(规格书 3.8.3
func EnvironmentBacktrack(samples []EnvSample, humidityThreshold float64) EnvironmentResult {
r := EnvironmentResult{}
if len(samples) == 0 {
r.Summary = "无可用环境遥测数据"
return r
}
for _, s := range samples {
if s.Humidity != nil && *s.Humidity >= humidityThreshold {
r.HighHumidity = true
}
if s.Temp != nil && (*s.Temp > 30 || *s.Temp < 20) {
r.TempSwing = true
}
}
switch {
case r.HighHumidity && r.TempSwing:
r.Summary = "发病前环境存在持续高湿与温度突变,符合真菌病与核型多角体病诱发条件"
case r.HighHumidity:
r.Summary = fmt.Sprintf("发病前环境湿度 ≥%.0f%%,符合高湿诱病条件", humidityThreshold)
case r.TempSwing:
r.Summary = "发病前环境温度突变(>30℃ 或 <20℃),易诱发潜伏感染转急性"
default:
r.Summary = "发病前环境温湿度未见明显异常"
}
return r
}
// PastEvent 历史发病事件
type PastEvent struct {
Disease string
DaysAgo int
}
// HistoryAssociation 历史发病关联:同房间/同病种既往 90 天内有发病 → 连发性
func HistoryAssociation(past []PastEvent, disease string) bool {
for _, e := range past {
if e.Disease == disease && e.DaysAgo <= 90 {
return true
}
}
return false
}
// TransmissionInference 按病种推断传播途径(规格书 3.8.2)
func TransmissionInference(disease string) (mode, source string) {
switch disease {
case "核型多角体病":
return "食下传染为主,创伤传染次之", "多角体污染蚕座/桑叶/蚕具,环境残留或新引入"
case "白僵病", "其他真菌病(绿僵病/黄僵病/曲霉病)":
return "接触传染/气流扩散", "分生孢子经气流带入,或蚕房尸体产孢内源扩散"
case "软化病", "浓核病/传染性软化病":
return "食下传染", "桑园害虫粪便污染桑叶,或蚕座环境累积污染"
case "微粒子病":
return "食下传染+胚种传染", "蚕种带毒(垂直传播)或环境孢子水平传播"
case "细菌性败血病":
return "创伤传染", "蚕具刮伤/互相抓伤后环境细菌侵入"
case "猝倒病":
return "食下传染(细菌毒素)", "桑叶被细菌污染"
default:
return "未知", "病种不明,建议先确认病原"
}
}
// ChecklistItem 排查清单项
type ChecklistItem struct {
Key string `json:"key"`
Label string `json:"label"`
InternalBias bool `json:"internalBias"`
}
// DiseaseChecklist 分病种二级排查清单(规格书 3.8.3)
func DiseaseChecklist(disease string) []ChecklistItem {
switch disease {
case "核型多角体病":
return []ChecklistItem{
{Key: "disinfect", Label: "上批次是否发生过同种病?消毒是否彻底(含蚕具浸泡)?", InternalBias: true},
{Key: "tray_share", Label: "蚕具是否跨批次共用?", InternalBias: true},
{Key: "mulberry", Label: "桑叶来源是否变更?", InternalBias: false},
{Key: "entry", Label: "近期人员进出/蚕具借用记录是否有异常?", InternalBias: false},
}
case "白僵病":
return []ChecklistItem{
{Key: "vent", Label: "近期是否连续阴雨且通风不足?", InternalBias: true},
{Key: "corpse", Label: "蚕房附近是否堆放蚕沙或病蚕尸体?", InternalBias: true},
{Key: "outdoor", Label: "蚕房周边桑园昆虫是否有白僵病死亡个体?", InternalBias: false},
{Key: "filter", Label: "通风口是否有过滤防虫措施?", InternalBias: false},
}
case "微粒子病":
return []ChecklistItem{
{Key: "seed", Label: "蚕种来源批次与供应商是否可追溯?", InternalBias: true},
{Key: "quarantine", Label: "检疫证明与母蛾镜检结果是否齐全?", InternalBias: true},
{Key: "wild", Label: "桑园周边野外昆虫是否有微孢子虫?", InternalBias: false},
{Key: "cross", Label: "同批次蚕种在其他蚕房是否发病?", InternalBias: false},
}
case "软化病", "浓核病/传染性软化病":
return []ChecklistItem{
{Key: "density", Label: "蚕头密度是否过大?", InternalBias: true},
{Key: "vent", Label: "通风是否不良?", InternalBias: true},
{Key: "mulberry", Label: "桑叶是否潮湿或储运不达标?", InternalBias: true},
{Key: "pest", Label: "桑园近期害虫防治记录是否正常?", InternalBias: false},
}
case "细菌性败血病":
return []ChecklistItem{
{Key: "tool", Label: "蚕具是否有尖锐边缘/毛刺?", InternalBias: true},
{Key: "density", Label: "蚕头密度是否超标导致相互抓伤?", InternalBias: true},
{Key: "op", Label: "给桑操作是否粗暴?", InternalBias: true},
{Key: "disinfect", Label: "消毒是否有盲区?", InternalBias: true},
}
default:
return nil
}
}
// ChecklistAnswer 清单作答
type ChecklistAnswer struct {
Key string `json:"key"`
Label string `json:"label"`
Answer string `json:"answer"` // yes/no/unknown
InternalBias bool `json:"internalBias"`
}
// AnalyzeChecklist 按作答统计内源/外源倾向并给出结论
func AnalyzeChecklist(answers []ChecklistAnswer) (origin string, confidence float64, conclusion string) {
internal, external, unknown := 0, 0, 0
for _, a := range answers {
switch a.Answer {
case "yes":
if a.InternalBias {
internal++
} else {
external++
}
case "no":
if a.InternalBias {
external++
} else {
internal++
}
default:
unknown++
}
}
total := internal + external + unknown
if total == 0 {
return "unknown", 0, "未填写排查清单,无法判定来源"
}
switch {
case internal > external:
origin = "internal"
confidence = 0.5 + 0.3*float64(internal)/float64(total)
conclusion = "倾向内源扩散(环境残留/蚕座污染),建议定向清除环境残留并升级消毒"
case external > internal:
origin = "external"
confidence = 0.5 + 0.3*float64(external)/float64(total)
conclusion = "倾向外源侵入(桑叶/气流/种源),建议封堵外部侵入途径"
default:
origin = "unknown"
confidence = 0.5
conclusion = "内源与外源线索相当,建议结合专家会诊进一步确认"
}
return origin, confidence, conclusion
}