Files
silk/server-go/internal/service/detection_recommend.go

142 lines
4.1 KiB
Go

package service
import "sort"
// DetectionRecommendInput 多检测方式推荐输入
type DetectionRecommendInput struct {
HasLamp bool
HasSers bool
HasQPCR bool
HasHyperspectral bool
Urgency string // routine/urgent
OperatorLevel string // novice/expert
CostPreference string // balanced/low_cost/fastest
}
// DetectionRecommendation 推荐结果
type DetectionRecommendation struct {
Method string `json:"method"`
Name string `json:"name"`
Reason string `json:"reason"`
Time string `json:"time"`
Cost string `json:"cost"`
Difficulty string `json:"difficulty"`
}
type methodScore struct {
info DetectionRecommendation
time int
cost int
diff int
}
// RecommendMethod 按设备条件/紧急程度/操作者水平/成本偏好推荐检测方式
// 规则取自规格书 3.3.2 与 11.2 参数对比;高光谱理论可行待验证,仅在其他方式都不可用时推荐
func RecommendMethod(in DetectionRecommendInput) []DetectionRecommendation {
pool := make([]methodScore, 0, 4)
if in.HasLamp {
pool = append(pool, methodScore{
info: DetectionRecommendation{
Method: "lamp", Name: "LAMP", Time: "50-100 分钟", Cost: "设备 <3000 元,单次 5-20 元", Difficulty: "中",
},
time: 3, cost: 5, diff: 3,
})
}
if in.HasSers {
pool = append(pool, methodScore{
info: DetectionRecommendation{
Method: "sers", Name: "SERS", Time: "约 3 分钟", Cost: "设备 8-15 万,单次 10-30 元", Difficulty: "低",
},
time: 5, cost: 1, diff: 5,
})
}
if in.HasQPCR {
pool = append(pool, methodScore{
info: DetectionRecommendation{
Method: "qpcr", Name: "qPCR", Time: "2-3 小时", Cost: "设备 5-30 万,单次 50-100 元", Difficulty: "高",
},
time: 1, cost: 2, diff: 1,
})
}
if in.HasHyperspectral {
pool = append(pool, methodScore{
info: DetectionRecommendation{
Method: "hyperspectral", Name: "高光谱", Time: "秒级~分钟级", Cost: "设备数万-十几万,单次 0 元", Difficulty: "低(待验证)",
},
time: 5, cost: 2, diff: 5,
})
}
if len(pool) == 0 {
return nil
}
// 高光谱理论可行待验证:仅当它是唯一可用方式时推荐,否则剔除
if len(pool) > 1 {
filtered := pool[:0]
for _, m := range pool {
if m.info.Method != "hyperspectral" {
filtered = append(filtered, m)
}
}
pool = filtered
}
// 权重
wt, wc, wd := 0.3, 0.4, 0.3
if in.Urgency == "urgent" {
wt, wc, wd = 0.6, 0.2, 0.2
}
if in.OperatorLevel == "novice" {
wt, wc, wd = 0.2, 0.2, 0.6
}
if in.CostPreference == "low_cost" {
wt, wc, wd = 0.2, 0.6, 0.2
} else if in.CostPreference == "fastest" {
wt, wc, wd = 0.6, 0.2, 0.2
}
scores := make([]float64, len(pool))
for i, m := range pool {
scores[i] = wt*float64(m.time) + wc*float64(m.cost) + wd*float64(m.diff)
}
order := make([]int, len(pool))
for i := range order {
order[i] = i
}
sort.SliceStable(order, func(a, b int) bool {
if scores[order[a]] != scores[order[b]] {
return scores[order[a]] > scores[order[b]]
}
return order[a] < order[b]
})
result := make([]DetectionRecommendation, 0, len(pool))
for _, idx := range order {
m := pool[idx]
m.info.Reason = reasonFor(m.info.Method, in)
result = append(result, m.info)
}
return result
}
func reasonFor(method string, in DetectionRecommendInput) string {
switch method {
case "sers":
return "出结果最快(约 3 分钟)、操作难度低,适合紧急或新手场景;设备投入较高"
case "lamp":
if in.CostPreference == "low_cost" {
return "设备投入最低(<3000 元)、基层最务实,性价比高"
}
if in.Urgency == "urgent" {
return "在无 SERS 时最快的可选方案(50-100 分钟),设备投入低"
}
return "设备投入低、基层最务实,是目前蚕业领域最常用的分子检测方案"
case "qpcr":
return "金标准准确率最高,适合争议仲裁;设备投入大、操作门槛高、耗时 2-3 小时"
case "hyperspectral":
return "非接触秒级检测,但蚕病领域理论可行待验证,建议先做可行性实验"
default:
return ""
}
}