diff --git a/internal/consts/consts.go b/internal/consts/consts.go index d709a2b..ec77963 100644 --- a/internal/consts/consts.go +++ b/internal/consts/consts.go @@ -1 +1,20 @@ package consts + +const ( + // 笑门官网查询英雄名称和神器名称,用作中文翻译 + SimileHeroName = "https://static.smilegatemegaport.com/gameRecord/epic7/epic7_hero.json?_=1729322698936" + SimileArtifactName = "https://static.smilegatemegaport.com/gameRecord/epic7/epic7_artifact.json?_=1729322698936" + + // 获取角色信息 + HeroListURL = "https://e7-optimizer-game-data.s3-accelerate.amazonaws.com/herodata.json" + + // 获取神器信息 + ArtifactDataURL = "https://e7-optimizer-game-data.s3-accelerate.amazonaws.com/artifactdata.json" + + // 根据角色名字查询配装 + HeroNameURL = "https://krivpfvxi0.execute-api.us-west-2.amazonaws.com/dev/getBuilds" + + // 官方数据接口示例:https://static.smilegatemegaport.com/event/live/epic7/guide/images/hero/c2027_s.png + // 角色图片基础 URL + GfHeroPngURL = "https://static.smilegatemegaport.com/event/live/epic7/guide/images/hero/" +) diff --git a/internal/logic/cron/cron_test.go b/internal/logic/cron/cron_test.go deleted file mode 100644 index 5c14661..0000000 --- a/internal/logic/cron/cron_test.go +++ /dev/null @@ -1,114 +0,0 @@ -package cron - -import ( - "context" - "testing" - "time" -) - -func TestCronLogic_AddJob(t *testing.T) { - ctx := context.Background() - logic := New() - - // 测试添加任务 - err := logic.AddJob(ctx, "test_job", "* * * * *", func() { - t.Log("Test job executed") - }) - - if err != nil { - t.Errorf("Failed to add job: %v", err) - } - - // 测试重复添加同名任务 - err = logic.AddJob(ctx, "test_job", "* * * * *", func() { - t.Log("Test job executed again") - }) - - if err == nil { - t.Error("Expected error when adding duplicate job name") - } - - // 清理 - logic.RemoveJob(ctx, "test_job") -} - -func TestCronLogic_GetJobStatus(t *testing.T) { - ctx := context.Background() - logic := New() - - // 添加任务 - err := logic.AddJob(ctx, "status_test_job", "* * * * *", func() { - t.Log("Status test job executed") - }) - if err != nil { - t.Fatalf("Failed to add job: %v", err) - } - - // 测试获取任务状态 - status, err := logic.GetJobStatus(ctx, "status_test_job") - if err != nil { - t.Errorf("Failed to get job status: %v", err) - } - - if !status { - t.Error("Expected job to be active") - } - - // 测试获取不存在的任务状态 - status, err = logic.GetJobStatus(ctx, "non_existent_job") - if err != nil { - t.Errorf("Failed to get non-existent job status: %v", err) - } - - if status { - t.Error("Expected non-existent job to be inactive") - } - - // 清理 - logic.RemoveJob(ctx, "status_test_job") -} - -func TestCronLogic_RemoveJob(t *testing.T) { - ctx := context.Background() - logic := New() - - // 添加任务 - err := logic.AddJob(ctx, "remove_test_job", "* * * * *", func() { - t.Log("Remove test job executed") - }) - if err != nil { - t.Fatalf("Failed to add job: %v", err) - } - - // 测试移除任务 - err = logic.RemoveJob(ctx, "remove_test_job") - if err != nil { - t.Errorf("Failed to remove job: %v", err) - } - - // 测试移除不存在的任务 - err = logic.RemoveJob(ctx, "non_existent_job") - if err == nil { - t.Error("Expected error when removing non-existent job") - } -} - -func TestCronLogic_StartStopJobs(t *testing.T) { - ctx := context.Background() - logic := New() - - // 启动任务 - err := logic.StartAllJobs(ctx) - if err != nil { - t.Errorf("Failed to start jobs: %v", err) - } - - // 等待一段时间让任务执行 - time.Sleep(2 * time.Second) - - // 停止任务 - err = logic.StopAllJobs(ctx) - if err != nil { - t.Errorf("Failed to stop jobs: %v", err) - } -} \ No newline at end of file diff --git a/internal/logic/cron/third_party_sync.go b/internal/logic/cron/third_party_sync.go index 2647c13..5697e79 100644 --- a/internal/logic/cron/third_party_sync.go +++ b/internal/logic/cron/third_party_sync.go @@ -2,6 +2,7 @@ package cron import ( "context" + "epic/internal/consts" "epic/internal/model/dto" "epic/utility" "fmt" @@ -30,7 +31,7 @@ func (t *ThirdPartyDataSync) SyncHeroData(ctx context.Context) error { // 示例:从第三方API获取英雄数据 heroData, err := t.fetchHeroDataFromAPI(ctx) - if err != nil { + if err != nil || heroData == nil { g.Log().Error(ctx, "获取英雄数据失败:", err) return err } @@ -71,7 +72,7 @@ func (t *ThirdPartyDataSync) SyncArtifactData(ctx context.Context) error { // fetchHeroDataFromAPI 从API获取英雄数据 func (t *ThirdPartyDataSync) fetchHeroDataFromAPI(ctx context.Context) ([]byte, error) { // 示例API地址,实际使用时需要替换为真实的API - apiURL := "https://api.example.com/heroes" + apiURL := consts.HeroListURL // 添加请求头 headers := map[string]string{ @@ -128,23 +129,24 @@ func (t *ThirdPartyDataSync) fetchArtifactDataFromAPI(ctx context.Context) (stri func (t *ThirdPartyDataSync) processAndSaveHeroData(ctx context.Context, data []byte) error { // 使用 gjson 解析 j := gjson.New(data) - // 检查json对象本身和其内部值,并使用 .Var().IsSlice() 这种更可靠的方式判断是否为数组 - if j == nil || j.IsNil() || !j.Var().IsSlice() { - return fmt.Errorf("英雄数据格式错误,期望是一个JSON数组") + + if j == nil || j.IsNil() { + return fmt.Errorf("英雄数据格式错误,期望是一个JSON对象") } - var heroes []*dto.ThirdPartyHeroDTO + // 先解析为 map[string]*ThirdPartyHeroDTO + var heroes map[string]*dto.ThirdPartyHeroDTO if err := j.Scan(&heroes); err != nil { return fmt.Errorf("解析英雄数据到DTO失败: %v", err) } g.Log().Info(ctx, "解析到", len(heroes), "个英雄数据") - // 批量处理数据 - for _, hero := range heroes { + // 遍历 map,设置 Name 字段,并保存 + for name, hero := range heroes { + hero.Name = name // 将 map 的 key 作为 Name 字段 if err := t.saveHeroData(ctx, hero); err != nil { g.Log().Error(ctx, "保存英雄数据失败:", err) - // 继续处理其他数据,不中断整个流程 continue } } diff --git a/internal/logic/cron/third_party_sync_test.go b/internal/logic/cron/third_party_sync_test.go index 4cb2d5e..3ac6700 100644 --- a/internal/logic/cron/third_party_sync_test.go +++ b/internal/logic/cron/third_party_sync_test.go @@ -13,7 +13,7 @@ import ( func TestMain(m *testing.M) { // 必须在任何import和g.Cfg()调用前设置环境变量 - genv.Set("GF_GCFG_FILE", "D:/code/go/epic/manifest/config/config.yaml") + genv.Set("GF_GCFG_FILE", "../../../../manifest/config/config.yaml") ctx := gctx.New() _ = g.Cfg().MustGet(ctx, "server.address") fmt.Println(g.Cfg().Get(ctx, "redis.default.address")) @@ -50,17 +50,18 @@ func (m *mockSync) processAndSaveArtifactData(ctx context.Context, data []byte) return m.processArtifactErr } -//func TestSyncHeroData_Success(t *testing.T) { -// sync := &ThirdPartyDataSync{} -// // 替换方法为mock -// sync.fetchHeroDataFromAPI = (&mockSync{}).fetchHeroDataFromAPI -// sync.processAndSaveHeroData = (&mockSync{}).processAndSaveHeroData -// -// err := sync.SyncHeroData(context.Background()) -// if err != nil { -// t.Errorf("expected success, got error: %v", err) -// } -//} +/** + * 测试同步英雄数据 + */ +func TestSyncHeroData(t *testing.T) { + thirdPartyDataSync := NewThirdPartyDataSync() + + err := thirdPartyDataSync.SyncHeroData(context.Background()) + if err != nil { + t.Errorf("expected success, got error: %v", err) + } +} + // //func TestSyncHeroData_FetchError(t *testing.T) { // sync := &ThirdPartyDataSync{} @@ -96,6 +97,7 @@ func (m *mockSync) processAndSaveArtifactData(ctx context.Context, data []byte) //} // //func TestSyncArtifactData_FetchError(t *testing.T) { + // sync := &ThirdPartyDataSync{} // sync.fetchArtifactDataFromAPI = (&mockSync{fetchArtifactDataErr: errors.New("fetch error")}).fetchArtifactDataFromAPI // sync.processAndSaveArtifactData = (&mockSync{}).processAndSaveArtifactData diff --git a/internal/model/dto/third_party.go b/internal/model/dto/third_party.go index 993e881..4c0842d 100644 --- a/internal/model/dto/third_party.go +++ b/internal/model/dto/third_party.go @@ -17,10 +17,63 @@ type ThirdPartyArtifactDTO struct { // ThirdPartyHeroDTO represents a hero from the third-party API. // Note: This is a placeholder structure. Adjust it according to the actual API response. +// ThirdPartyHeroDTO 第三方英雄数据传输对象 type ThirdPartyHeroDTO struct { - Code string `json:"code"` - Name string `json:"name"` - Rarity int `json:"rarity"` - Attribute string `json:"attribute"` - Role string `json:"role"` -} \ No newline at end of file + Code string `json:"code"` + ID string `json:"_id"` + Name string `json:"-"` + Rarity int `json:"rarity"` + Attribute string `json:"attribute"` + Role string `json:"role"` + Zodiac string `json:"zodiac"` + SelfDevotion SelfDevotion `json:"self_devotion"` + Assets Assets `json:"assets"` + ExEquip []ExEquip `json:"ex_equip"` + Skills map[string]Skill `json:"skills"` + CalculatedStatus map[string]Status `json:"calculatedStatus"` +} +type SelfDevotion struct { + Type string `json:"type"` + Grades map[string]float64 `json:"grades"` +} + +type Assets struct { + Icon string `json:"icon"` + Image string `json:"image"` + Thumbnail string `json:"thumbnail"` +} + +type ExEquip struct { + Stat struct { + Type string `json:"type"` + Value float64 `json:"value"` + } `json:"stat"` +} + +type Skill struct { + HitTypes []string `json:"hitTypes"` + Rate float64 `json:"rate,omitempty"` + Pow float64 `json:"pow,omitempty"` + Targets int `json:"targets,omitempty"` + SelfHpScale float64 `json:"selfHpScaling,omitempty"` + SelfDefScale float64 `json:"selfDefScaling,omitempty"` + Options []any `json:"options"` +} + +type Status struct { + Lv50FiveStarFullyAwakened Stats `json:"lv50FiveStarFullyAwakened"` + Lv60SixStarFullyAwakened Stats `json:"lv60SixStarFullyAwakened"` +} + +type Stats struct { + CP int `json:"cp"` + ATK int `json:"atk"` + HP int `json:"hp"` + SPD int `json:"spd"` + DEF int `json:"def"` + CHC float64 `json:"chc"` + CHD float64 `json:"chd"` + DAC float64 `json:"dac"` + EFF int `json:"eff"` + EFR int `json:"efr"` +}