package sniper import ( "fmt" "strconv" "strings" ) // TargetSummary 把目标列表渲染成「13437(冠军之刃)」这样的单行摘要,供启动日志使用。 // // 2026-10-16 的复盘正卡在「日志里没有目标 pid」:三台机器都只记了 sid 与 targets=1, // 看不出各自打的是哪个奖品,也就无法解释为什么一台售罄、另一台库存完好。 func TargetSummary(targets []Target) string { parts := make([]string, 0, len(targets)) for _, target := range targets { name := strings.TrimSpace(target.Name) switch { case target.PID > 0 && name != "": parts = append(parts, fmt.Sprintf("%d(%s)", target.PID, name)) case target.PID > 0: parts = append(parts, strconv.FormatInt(int64(target.PID), 10)) case name != "": parts = append(parts, name) case target.Auto: parts = append(parts, "自动选择") } } if len(parts) == 0 { return "未指定" } return strings.Join(parts, ",") } // CategoryLabel 返回结局分类的中文短标签,供任务结束时的结局日志使用。 func CategoryLabel(category string) string { switch category { case CategorySuccess: return "已抢到" case CategorySoldOut: return "售罄" case CategoryTooFrequent: return "被限流" case CategoryNotOpen: return "未开放" case CategoryNotEnough: return "积分不足" case CategoryAlreadyDone: return "已兑换过" case CategoryOffShelf: return "已下架" case CategorySessionLost: return "会话失效" case CategoryProtocol: return "协议异常" case CategoryCondition: return "条件未达成" case CategoryNotFound: return "未匹配到奖品" case CategoryError: return "请求异常" default: return "失败" } } // CategoryText 把类目限制渲染成日志文案(空串表示不限类目)。 func CategoryText(category string) string { key := strings.TrimSpace(category) if key == "" { return "不限" } return key } // LogLevelForCategory 把结果分类映射成日志等级,供界面按等级高亮与筛选。 func LogLevelForCategory(category string) string { switch category { case CategorySuccess: return "success" case CategoryError, CategoryProtocol: return "error" case CategoryFailed, CategoryTooFrequent, CategoryCondition, CategorySessionLost: return "warn" default: return "info" } }