feat(i18n): integrate i18next for internationalization support and add initial translation setup
This commit is contained in:
@@ -10,8 +10,12 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -19,6 +23,9 @@ type ParserService struct {
|
||||
config *config.Config
|
||||
logger *utils.Logger
|
||||
hexParser *parser.HexParser
|
||||
heroBase map[string]heroBaseStats
|
||||
heroOnce sync.Once
|
||||
heroErr error
|
||||
}
|
||||
|
||||
func NewParserService(cfg *config.Config, logger *utils.Logger) *ParserService {
|
||||
@@ -26,6 +33,7 @@ func NewParserService(cfg *config.Config, logger *utils.Logger) *ParserService {
|
||||
config: cfg,
|
||||
logger: logger,
|
||||
hexParser: parser.NewHexParser(),
|
||||
heroBase: make(map[string]heroBaseStats),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,6 +215,8 @@ func (ps *ParserService) convertSingleItem(item map[string]interface{}) map[stri
|
||||
// convertUnits 转换英雄数据
|
||||
func (ps *ParserService) convertUnits(rawUnits []interface{}) []map[string]interface{} {
|
||||
var convertedUnits []map[string]interface{}
|
||||
ps.ensureHeroBaseData()
|
||||
|
||||
|
||||
for _, rawUnit := range rawUnits {
|
||||
if unitMap, ok := rawUnit.(map[string]interface{}); ok {
|
||||
@@ -225,6 +235,12 @@ func (ps *ParserService) convertUnits(rawUnits []interface{}) []map[string]inter
|
||||
convertedUnit["awaken"] = z
|
||||
}
|
||||
|
||||
if code, ok := unitMap["code"].(string); ok && code != "" {
|
||||
if base, ok := ps.heroBase[code]; ok {
|
||||
ps.applyHeroBase(convertedUnit, base)
|
||||
}
|
||||
}
|
||||
|
||||
convertedUnits = append(convertedUnits, convertedUnit)
|
||||
}
|
||||
}
|
||||
@@ -520,3 +536,232 @@ func (ps *ParserService) convertItemsAllWithLog(rawItems []interface{}) []map[st
|
||||
}
|
||||
return convertedItems
|
||||
}
|
||||
|
||||
|
||||
type heroBaseStats struct {
|
||||
Atk float64
|
||||
Def float64
|
||||
Hp float64
|
||||
Spd float64
|
||||
Cr float64
|
||||
Cd float64
|
||||
Eff float64
|
||||
Res float64
|
||||
}
|
||||
|
||||
type heroDataEntry struct {
|
||||
Code string `json:"code"`
|
||||
Name string `json:"name"`
|
||||
CalculatedStatus struct {
|
||||
Lv60SixStarFullyAwakened struct {
|
||||
Atk float64 `json:"atk"`
|
||||
Def float64 `json:"def"`
|
||||
Hp float64 `json:"hp"`
|
||||
Spd float64 `json:"spd"`
|
||||
Chc float64 `json:"chc"`
|
||||
Chd float64 `json:"chd"`
|
||||
Eff float64 `json:"eff"`
|
||||
Efr float64 `json:"efr"`
|
||||
} `json:"lv60SixStarFullyAwakened"`
|
||||
} `json:"calculatedStatus"`
|
||||
}
|
||||
|
||||
func (ps *ParserService) ensureHeroBaseData() {
|
||||
ps.heroOnce.Do(func() {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
ps.heroErr = err
|
||||
ps.logger.Error("load hero data failed", "error", err)
|
||||
return
|
||||
}
|
||||
path := filepath.Join(homeDir, ".equipment-analyzer", "herodata.json")
|
||||
body, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
ps.heroErr = err
|
||||
ps.logger.Error("load hero data failed", "error", err)
|
||||
return
|
||||
}
|
||||
var raw map[string]heroDataEntry
|
||||
if err := json.Unmarshal(body, &raw); err != nil {
|
||||
ps.heroErr = err
|
||||
ps.logger.Error("load hero data failed", "error", err)
|
||||
return
|
||||
}
|
||||
for _, entry := range raw {
|
||||
if entry.Code == "" {
|
||||
continue
|
||||
}
|
||||
stats := entry.CalculatedStatus.Lv60SixStarFullyAwakened
|
||||
ps.heroBase[entry.Code] = heroBaseStats{
|
||||
Atk: stats.Atk,
|
||||
Def: stats.Def,
|
||||
Hp: stats.Hp,
|
||||
Spd: stats.Spd,
|
||||
Cr: stats.Chc * 100,
|
||||
Cd: stats.Chd * 100,
|
||||
Eff: stats.Eff * 100,
|
||||
Res: stats.Efr * 100,
|
||||
}
|
||||
}
|
||||
ps.logger.Info("hero base data loaded", "count", len(ps.heroBase))
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
func (ps *ParserService) FillHeroBase(heroes []model.OptimizeHero) error {
|
||||
ps.ensureHeroBaseData()
|
||||
if len(ps.heroBase) == 0 {
|
||||
return fmt.Errorf("hero base data not loaded")
|
||||
}
|
||||
for i := range heroes {
|
||||
code := heroes[i].Code
|
||||
if code == "" {
|
||||
continue
|
||||
}
|
||||
base, ok := ps.heroBase[code]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if heroes[i].BaseAtk == 0 {
|
||||
heroes[i].BaseAtk = base.Atk
|
||||
}
|
||||
if heroes[i].BaseDef == 0 {
|
||||
heroes[i].BaseDef = base.Def
|
||||
}
|
||||
if heroes[i].BaseHp == 0 {
|
||||
heroes[i].BaseHp = base.Hp
|
||||
}
|
||||
if heroes[i].BaseSpd == 0 {
|
||||
heroes[i].BaseSpd = base.Spd
|
||||
}
|
||||
if heroes[i].BaseCr == 0 {
|
||||
heroes[i].BaseCr = base.Cr
|
||||
}
|
||||
if heroes[i].BaseCd == 0 {
|
||||
heroes[i].BaseCd = base.Cd
|
||||
}
|
||||
if heroes[i].BaseEff == 0 {
|
||||
heroes[i].BaseEff = base.Eff
|
||||
}
|
||||
if heroes[i].BaseRes == 0 {
|
||||
heroes[i].BaseRes = base.Res
|
||||
}
|
||||
|
||||
if heroes[i].Atk == 0 {
|
||||
heroes[i].Atk = base.Atk
|
||||
}
|
||||
if heroes[i].Def == 0 {
|
||||
heroes[i].Def = base.Def
|
||||
}
|
||||
if heroes[i].Hp == 0 {
|
||||
heroes[i].Hp = base.Hp
|
||||
}
|
||||
if heroes[i].Spd == 0 {
|
||||
heroes[i].Spd = base.Spd
|
||||
}
|
||||
if heroes[i].Cr == 0 {
|
||||
heroes[i].Cr = base.Cr
|
||||
}
|
||||
if heroes[i].Cd == 0 {
|
||||
heroes[i].Cd = base.Cd
|
||||
}
|
||||
if heroes[i].Eff == 0 {
|
||||
heroes[i].Eff = base.Eff
|
||||
}
|
||||
if heroes[i].Res == 0 {
|
||||
heroes[i].Res = base.Res
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ps *ParserService) GetHeroTemplates() ([]model.HeroTemplate, error) {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
path := filepath.Join(homeDir, ".equipment-analyzer", "herodata.json")
|
||||
body, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var raw map[string]heroDataEntry
|
||||
if err := json.Unmarshal(body, &raw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
list := make([]model.HeroTemplate, 0, len(raw))
|
||||
for _, entry := range raw {
|
||||
if entry.Code == "" {
|
||||
continue
|
||||
}
|
||||
stats := entry.CalculatedStatus.Lv60SixStarFullyAwakened
|
||||
list = append(list, model.HeroTemplate{
|
||||
Code: entry.Code,
|
||||
Name: entry.Name,
|
||||
BaseAtk: stats.Atk,
|
||||
BaseDef: stats.Def,
|
||||
BaseHp: stats.Hp,
|
||||
BaseSpd: stats.Spd,
|
||||
BaseCr: stats.Chc * 100,
|
||||
BaseCd: stats.Chd * 100,
|
||||
BaseEff: stats.Eff * 100,
|
||||
BaseRes: stats.Efr * 100,
|
||||
})
|
||||
}
|
||||
sort.Slice(list, func(i, j int) bool {
|
||||
return list[i].Name < list[j].Name
|
||||
})
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (ps *ParserService) applyHeroBase(unit map[string]interface{}, base heroBaseStats) {
|
||||
if _, ok := unit["baseAtk"]; !ok {
|
||||
unit["baseAtk"] = base.Atk
|
||||
}
|
||||
if _, ok := unit["baseDef"]; !ok {
|
||||
unit["baseDef"] = base.Def
|
||||
}
|
||||
if _, ok := unit["baseHp"]; !ok {
|
||||
unit["baseHp"] = base.Hp
|
||||
}
|
||||
if _, ok := unit["baseSpd"]; !ok {
|
||||
unit["baseSpd"] = base.Spd
|
||||
}
|
||||
if _, ok := unit["baseCr"]; !ok {
|
||||
unit["baseCr"] = base.Cr
|
||||
}
|
||||
if _, ok := unit["baseCd"]; !ok {
|
||||
unit["baseCd"] = base.Cd
|
||||
}
|
||||
if _, ok := unit["baseEff"]; !ok {
|
||||
unit["baseEff"] = base.Eff
|
||||
}
|
||||
if _, ok := unit["baseRes"]; !ok {
|
||||
unit["baseRes"] = base.Res
|
||||
}
|
||||
|
||||
if _, ok := unit["atk"]; !ok {
|
||||
unit["atk"] = base.Atk
|
||||
}
|
||||
if _, ok := unit["def"]; !ok {
|
||||
unit["def"] = base.Def
|
||||
}
|
||||
if _, ok := unit["hp"]; !ok {
|
||||
unit["hp"] = base.Hp
|
||||
}
|
||||
if _, ok := unit["spd"]; !ok {
|
||||
unit["spd"] = base.Spd
|
||||
}
|
||||
if _, ok := unit["cr"]; !ok {
|
||||
unit["cr"] = base.Cr
|
||||
}
|
||||
if _, ok := unit["cd"]; !ok {
|
||||
unit["cd"] = base.Cd
|
||||
}
|
||||
if _, ok := unit["eff"]; !ok {
|
||||
unit["eff"] = base.Eff
|
||||
}
|
||||
if _, ok := unit["res"]; !ok {
|
||||
unit["res"] = base.Res
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user