package service import ( "bytes" "encoding/json" "equipment-analyzer/internal/config" "equipment-analyzer/internal/model" "equipment-analyzer/internal/parser" "equipment-analyzer/internal/utils" "fmt" "io/ioutil" "net/http" "time" ) type ParserService struct { config *config.Config logger *utils.Logger hexParser *parser.HexParser } func NewParserService(cfg *config.Config, logger *utils.Logger) *ParserService { return &ParserService{ config: cfg, logger: logger, hexParser: parser.NewHexParser(), } } // ParseHexData 解析十六进制数据 func (ps *ParserService) ParseHexData(hexDataList []string) (*model.ParsedResult, string, error) { if len(hexDataList) == 0 { ps.logger.Warn("没有数据需要解析") return &model.ParsedResult{ Items: make([]interface{}, 0), Heroes: make([]interface{}, 0), }, "", nil } ps.logger.Info("开始远程解析数据", "count", len(hexDataList)) url := "https://krivpfvxi0.execute-api.us-west-2.amazonaws.com/dev/getItems" reqBody := map[string]interface{}{ "data": hexDataList, } jsonBytes, _ := json.Marshal(reqBody) client := &http.Client{Timeout: 15 * time.Second} req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBytes)) if err == nil { req.Header.Set("Content-Type", "application/json") resp, err := client.Do(req) if err == nil && resp.StatusCode == 200 { defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) // 新校验逻辑:校验data和units字段 var raw map[string]interface{} if err := json.Unmarshal(body, &raw); err != nil { ps.logger.Error("远程json解析失败", "error", err) return nil, "", fmt.Errorf("远程json解析失败: %v", err) } // 校验data字段 dataArr, dataOk := raw["data"].([]interface{}) if !dataOk || len(dataArr) == 0 { ps.logger.Error("远程json校验失败,data字段缺失或为空") return nil, "", fmt.Errorf("远程json校验失败,data字段缺失或为空") } // 校验通过,直接解析数据 ps.logger.Info("远程原始数据校验通过,开始解析") parsedResult, err := ps.ReadRawJsonFile(string(body)) if err != nil { return nil, "", err } return parsedResult, "", nil } else if err != nil { ps.logger.Error("远程解析请求失败", "error", err) return nil, "", fmt.Errorf("远程解析请求失败: %v", err) } else { ps.logger.Error("远程解析响应码异常", "status", resp.StatusCode) return nil, "", fmt.Errorf("远程解析响应码异常: %d", resp.StatusCode) } } else { ps.logger.Error("远程解析请求构建失败", "error", err) return nil, "", fmt.Errorf("远程解析请求构建失败: %v", err) } } // ReadRawJsonFile 读取rawJson内容并进行数据转换,返回ParsedResult对象 func (ps *ParserService) ReadRawJsonFile(rawJson string) (*model.ParsedResult, error) { var rawData map[string]interface{} if err := json.Unmarshal([]byte(rawJson), &rawData); err != nil { ps.logger.Error("解析JSON失败", "error", err) return nil, err } // 提取装备和英雄数据 equips, _ := rawData["data"].([]interface{}) // 修正:units 取最大长度的那组 var rawUnits []interface{} if unitsRaw, ok := rawData["units"].([]interface{}); ok && len(unitsRaw) > 0 { maxLen := 0 for _, u := range unitsRaw { if arr, ok := u.([]interface{}); ok && len(arr) > maxLen { maxLen = len(arr) rawUnits = arr } } } // 过滤有效装备 (x => !!x.f) var validEquips []interface{} for _, equip := range equips { if equipMap, ok := equip.(map[string]interface{}); ok { if f, exists := equipMap["f"]; exists && f != nil && f != "" { validEquips = append(validEquips, equip) } } } // 转换装备数据 convertedItems := ps.convertItemsAllWithLog(validEquips) // 转换英雄数据(只对最大组) convertedHeroes := ps.convertUnits(rawUnits) result := &model.ParsedResult{ Items: make([]interface{}, len(convertedItems)), Heroes: make([]interface{}, len(convertedHeroes)), } for i, v := range convertedItems { result.Items[i] = v } for i, v := range convertedHeroes { result.Heroes[i] = v } return result, nil } // convertItems 转换装备数据 func (ps *ParserService) convertItems(rawItems []interface{}) []map[string]interface{} { var convertedItems []map[string]interface{} for _, rawItem := range rawItems { if itemMap, ok := rawItem.(map[string]interface{}); ok { convertedItem := ps.convertSingleItem(itemMap) if convertedItem != nil { convertedItems = append(convertedItems, convertedItem) } } } var filteredItems []map[string]interface{} for _, item := range convertedItems { filteredItems = append(filteredItems, item) } return filteredItems } // convertSingleItem 转换单个装备 func (ps *ParserService) convertSingleItem(item map[string]interface{}) map[string]interface{} { converted := make(map[string]interface{}) // 复制基本字段 for key, value := range item { converted[key] = value } // 转换装备类型 ps.convertGear(converted) // 转换等级 ps.convertRank(converted) // 转换套装 ps.convertSet(converted) // 转换名称 ps.convertName(converted) // 转换等级 ps.convertLevel(converted) // 转换增强 ps.convertEnhance(converted) // 转换主属性 ps.convertMainStat(converted) // 转换副属性 ps.convertSubStats(converted) // 转换ID ps.convertId(converted) // 转换装备ID ps.convertEquippedId(converted) return converted } // convertUnits 转换英雄数据 func (ps *ParserService) convertUnits(rawUnits []interface{}) []map[string]interface{} { var convertedUnits []map[string]interface{} for _, rawUnit := range rawUnits { if unitMap, ok := rawUnit.(map[string]interface{}); ok { if name, exists := unitMap["name"]; exists && name != nil && name != "" { if id, exists := unitMap["id"]; exists && id != nil { convertedUnit := make(map[string]interface{}) for key, value := range unitMap { convertedUnit[key] = value } // 转换星星和觉醒 if g, exists := unitMap["g"]; exists { convertedUnit["stars"] = g } if z, exists := unitMap["z"]; exists { convertedUnit["awaken"] = z } convertedUnits = append(convertedUnits, convertedUnit) } } } } return convertedUnits } // 转换函数实现 func (ps *ParserService) convertGear(item map[string]interface{}) { if _, exists := item["type"]; !exists { if code, exists := item["code"].(string); exists { baseCode := code if idx := len(baseCode) - 1; idx >= 0 { gearLetter := string(baseCode[idx]) item["gear"] = gearByGearLetter[gearLetter] } } } else { if itemType, exists := item["type"].(string); exists { item["gear"] = gearByIngameType[itemType] } } } func (ps *ParserService) convertRank(item map[string]interface{}) { if g, exists := item["g"].(float64); exists { rankIndex := int(g) if rankIndex >= 0 && rankIndex < len(rankByIngameGrade) { item["rank"] = rankByIngameGrade[rankIndex] } } } func (ps *ParserService) convertSet(item map[string]interface{}) { if f, exists := item["f"].(string); exists { item["set"] = setsByIngameSet[f] } } func (ps *ParserService) convertName(item map[string]interface{}) { if _, exists := item["name"]; !exists { item["name"] = "Unknown" } } func (ps *ParserService) convertLevel(item map[string]interface{}) { if _, exists := item["level"]; !exists { item["level"] = 0 } } func (ps *ParserService) convertEnhance(item map[string]interface{}) { rank, rankExists := item["rank"].(string) op, opExists := item["op"].([]interface{}) if rankExists && opExists { countByRank := map[string]int{ "Normal": 5, "Good": 6, "Rare": 7, "Heroic": 8, "Epic": 9, } offsetByRank := map[string]int{ "Normal": 0, "Good": 1, "Rare": 2, "Heroic": 3, "Epic": 4, } count := countByRank[rank] offset := offsetByRank[rank] subsCount := len(op) - 1 if subsCount > count { subsCount = count } enhance := (subsCount - offset) * 3 if enhance < 0 { enhance = 0 } item["enhance"] = enhance } } func (ps *ParserService) convertMainStat(item map[string]interface{}) { op, opExists := item["op"].([]interface{}) mainStatValue, mainStatExists := item["mainStatValue"].(float64) if opExists && len(op) > 0 && mainStatExists { if mainOp, ok := op[0].([]interface{}); ok && len(mainOp) > 0 { if mainOpType, ok := mainOp[0].(string); ok { mainType := statByIngameStat[mainOpType] var mainValue float64 if ps.isFlat(mainOpType) { mainValue = mainStatValue } else { mainValue = mainStatValue * 100 } if mainValue == 0 || mainValue != mainValue { // NaN check mainValue = 0 } item["main"] = map[string]interface{}{ "type": mainType, "value": mainValue, } } } } } func (ps *ParserService) convertSubStats(item map[string]interface{}) { op, opExists := item["op"].([]interface{}) if !opExists || len(op) <= 1 { item["substats"] = []interface{}{} return } statAcc := make(map[string]map[string]interface{}) // 处理副属性 (从索引1开始) for i := 1; i < len(op); i++ { if opItem, ok := op[i].([]interface{}); ok && len(opItem) >= 2 { opType, _ := opItem[0].(string) opValue, _ := opItem[1].(float64) annotation := "" if len(opItem) > 2 { annotation, _ = opItem[2].(string) } statType := statByIngameStat[opType] var value float64 if ps.isFlat(opType) { value = opValue } else { value = opValue * 100 } if existingStat, exists := statAcc[statType]; exists { existingStat["value"] = existingStat["value"].(float64) + value if annotation == "c" { existingStat["modified"] = true } else if annotation != "u" { rolls := existingStat["rolls"].(int) + 1 existingStat["rolls"] = rolls existingStat["ingameRolls"] = rolls } } else { rolls := 1 if annotation == "u" { rolls = 0 } statAcc[statType] = map[string]interface{}{ "value": value, "rolls": rolls, "ingameRolls": rolls, "modified": annotation == "c", } } } } // 转换为最终格式 var substats []interface{} for statType, statData := range statAcc { substat := map[string]interface{}{ "type": statType, "value": statData["value"], "rolls": statData["rolls"], "ingameRolls": statData["ingameRolls"], "modified": statData["modified"], } substats = append(substats, substat) } item["substats"] = substats } func (ps *ParserService) convertId(item map[string]interface{}) { if id, exists := item["id"]; exists { item["ingameId"] = id } } func (ps *ParserService) convertEquippedId(item map[string]interface{}) { if p, exists := item["p"]; exists { item["ingameEquippedId"] = fmt.Sprintf("%v", p) } } func (ps *ParserService) isFlat(text string) bool { return text == "max_hp" || text == "speed" || text == "att" || text == "def" } // 映射常量 var ( rankByIngameGrade = []string{ "Unknown", "Normal", "Good", "Rare", "Heroic", "Epic", } gearByIngameType = map[string]string{ "weapon": "Weapon", "helm": "Helmet", "armor": "Armor", "neck": "Necklace", "ring": "Ring", "boot": "Boots", } gearByGearLetter = map[string]string{ "w": "Weapon", "h": "Helmet", "a": "Armor", "n": "Necklace", "r": "Ring", "b": "Boots", } setsByIngameSet = map[string]string{ "set_acc": "HitSet", "set_att": "AttackSet", "set_coop": "UnitySet", "set_counter": "CounterSet", "set_cri_dmg": "DestructionSet", "set_cri": "CriticalSet", "set_def": "DefenseSet", "set_immune": "ImmunitySet", "set_max_hp": "HealthSet", "set_penetrate": "PenetrationSet", "set_rage": "RageSet", "set_res": "ResistSet", "set_revenge": "RevengeSet", "set_scar": "InjurySet", "set_speed": "SpeedSet", "set_vampire": "LifestealSet", "set_shield": "ProtectionSet", "set_torrent": "TorrentSet", } statByIngameStat = map[string]string{ "att_rate": "AttackPercent", "max_hp_rate": "HealthPercent", "def_rate": "DefensePercent", "att": "Attack", "max_hp": "Health", "def": "Defense", "speed": "Speed", "res": "EffectResistancePercent", "cri": "CriticalHitChancePercent", "cri_dmg": "CriticalHitDamagePercent", "acc": "EffectivenessPercent", "coop": "DualAttackChancePercent", } ) // 新增:不做enhance过滤的convertItems func (ps *ParserService) convertItemsAllWithLog(rawItems []interface{}) []map[string]interface{} { var convertedItems []map[string]interface{} for _, rawItem := range rawItems { if itemMap, ok := rawItem.(map[string]interface{}); ok { convertedItem := ps.convertSingleItem(itemMap) if convertedItem != nil { convertedItems = append(convertedItems, convertedItem) } } } return convertedItems }