From 35cea796f9f53d7de0ebf399bfd1c04444260234 Mon Sep 17 00:00:00 2001 From: Yuan Si Date: Sat, 1 Apr 2023 08:26:37 +0800 Subject: [PATCH] Fix live reward Signed-off-by: Yuan Si --- handler/live.go | 418 +++++++++++++++++++++++++++++++++++++++++++++++- main.go | 2 + model/live.go | 394 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 813 insertions(+), 1 deletion(-) diff --git a/handler/live.go b/handler/live.go index 8ea4bed..7df54f1 100644 --- a/handler/live.go +++ b/handler/live.go @@ -186,7 +186,7 @@ func PlayLiveHandler(ctx *gin.Context) { TotalSmile: 9, TotalCute: 9, TotalCool: 9, - TotalHp: 99, + TotalHp: 999, PreparedHpDamage: 0, UnitList: unitList, }, @@ -273,3 +273,419 @@ func GameOverHandler(ctx *gin.Context) { ctx.Header("X-Message-Sign", xms64) ctx.String(http.StatusOK, resp) } + +func PlayScoreHandler(ctx *gin.Context) { + reqTime := time.Now().Unix() + + playScoreReq := model.PlayScoreReq{} + err := json.Unmarshal([]byte(ctx.PostForm("request_data")), &playScoreReq) + if err != nil { + panic(err) + } + + authorizeStr := ctx.Request.Header["Authorize"] + authToken, err := utils.GetAuthorizeToken(authorizeStr) + if err != nil { + ctx.String(http.StatusForbidden, "Fuck you!") + return + } + userId := ctx.Request.Header[http.CanonicalHeaderKey("User-ID")] + if len(userId) == 0 { + ctx.String(http.StatusForbidden, "Fuck you!") + return + } + + if !database.MatchTokenUid(authToken, userId[0]) { + ctx.String(http.StatusForbidden, "Fuck you!") + return + } + + nonce, err := utils.GetAuthorizeNonce(authorizeStr) + if err != nil { + fmt.Println(err) + ctx.String(http.StatusForbidden, "Fuck you!") + return + } + nonce++ + + respTime := time.Now().Unix() + newAuthorizeStr := fmt.Sprintf("consumerKey=lovelive_test&timeStamp=%d&version=1.1&token=%s&nonce=%d&user_id=%s&requestTimeStamp=%d", respTime, authToken, nonce, userId[0], reqTime) + // fmt.Println(newAuthorizeStr) + + // resp := utils.ReadAllText("assets/playsong.json") + db, err := sql.Open("sqlite3", "assets/live.db") + if err != nil { + panic(err) + } + defer db.Close() + db.SetMaxOpenConns(1) + + tDifficultyId := playScoreReq.LiveDifficultyID + difficultyId, err := strconv.Atoi(tDifficultyId) + if err != nil { + panic(err) + } + + // Song type: normal / special + // sqlite3 doesn't support FULL OUTER JOIN so use UNION ALL here. + sql := `SELECT notes_list,c_rank_score,b_rank_score,a_rank_score,s_rank_score,ac_flag,swing_flag FROM live_setting_m WHERE live_setting_id IN (SELECT live_setting_id FROM normal_live_m WHERE live_difficulty_id = ? UNION ALL SELECT live_setting_id FROM special_live_m WHERE live_difficulty_id = ?)` + rows, err := db.Query(sql, difficultyId, difficultyId) + if err != nil { + panic(err) + } + + var notes_list string + var c_rank_score, b_rank_score, a_rank_score, s_rank_score, ac_flag, swing_flag int + for rows.Next() { + err = rows.Scan(¬es_list, &c_rank_score, &b_rank_score, &a_rank_score, &s_rank_score, &ac_flag, &swing_flag) + if err != nil { + panic(err) + } + } + + // fmt.Println(len(notes_list)) + // fmt.Println(c_rank_score, b_rank_score, a_rank_score, s_rank_score) + + notes := []model.NotesList{} + err = json.Unmarshal([]byte(notes_list), ¬es) + if err != nil { + panic(err) + } + + ranks := []model.RankInfo{} + ranks = append(ranks, model.RankInfo{ + Rank: 5, + RankMin: 0, + RankMax: c_rank_score, + }, model.RankInfo{ + Rank: 4, + RankMin: c_rank_score + 1, + RankMax: b_rank_score, + }, model.RankInfo{ + Rank: 3, + RankMin: b_rank_score + 1, + RankMax: a_rank_score, + }, model.RankInfo{ + Rank: 2, + RankMin: a_rank_score + 1, + RankMax: s_rank_score, + }, model.RankInfo{ + Rank: 1, + RankMin: s_rank_score + 1, + RankMax: 0, + }) + + resp := model.PlayScoreResponseData{ + On: model.On{ + HasRecord: false, + LiveInfo: model.LiveInfo{ + LiveDifficultyID: difficultyId, + IsRandom: false, + AcFlag: ac_flag, + SwingFlag: swing_flag, + NotesList: notes, + }, + }, + Off: model.Off{ + HasRecord: false, + LiveInfo: model.LiveInfo{ + LiveDifficultyID: difficultyId, + IsRandom: false, + AcFlag: ac_flag, + SwingFlag: swing_flag, + NotesList: notes, + }, + }, + RankInfo: ranks, + CanActivateEffect: true, + ServerTimestamp: int(time.Now().Unix()), + } + + m, err := json.Marshal(resp) + if err != nil { + panic(err) + } + + res := model.Response{ + ResponseData: m, + ReleaseInfo: []interface{}{}, + StatusCode: 200, + } + + mm, err := json.Marshal(res) + if err != nil { + panic(err) + } + fmt.Println(string(mm)) + + xms := encrypt.RSA_Sign_SHA1(mm, "privatekey.pem") + xms64 := base64.RawStdEncoding.EncodeToString(xms) + + ctx.Header("Server-Version", config.Conf.Server.VersionNumber) + ctx.Header("user_id", userId[0]) + ctx.Header("authorize", newAuthorizeStr) + ctx.Header("X-Message-Sign", xms64) + ctx.String(http.StatusOK, string(mm)) +} + +func PlayRewardHandler(ctx *gin.Context) { + reqTime := time.Now().Unix() + + playRewardReq := model.PlayRewardReq{} + err := json.Unmarshal([]byte(ctx.PostForm("request_data")), &playRewardReq) + if err != nil { + panic(err) + } + + authorizeStr := ctx.Request.Header["Authorize"] + authToken, err := utils.GetAuthorizeToken(authorizeStr) + if err != nil { + ctx.String(http.StatusForbidden, "Fuck you!") + return + } + userId := ctx.Request.Header[http.CanonicalHeaderKey("User-ID")] + if len(userId) == 0 { + ctx.String(http.StatusForbidden, "Fuck you!") + return + } + + if !database.MatchTokenUid(authToken, userId[0]) { + ctx.String(http.StatusForbidden, "Fuck you!") + return + } + + nonce, err := utils.GetAuthorizeNonce(authorizeStr) + if err != nil { + fmt.Println(err) + ctx.String(http.StatusForbidden, "Fuck you!") + return + } + nonce++ + + respTime := time.Now().Unix() + newAuthorizeStr := fmt.Sprintf("consumerKey=lovelive_test&timeStamp=%d&version=1.1&token=%s&nonce=%d&user_id=%s&requestTimeStamp=%d", respTime, authToken, nonce, userId[0], reqTime) + // fmt.Println(newAuthorizeStr) + + // resp := utils.ReadAllText("assets/playsong.json") + db, err := sql.Open("sqlite3", "assets/live.db") + if err != nil { + panic(err) + } + defer db.Close() + db.SetMaxOpenConns(1) + + difficultyId := playRewardReq.LiveDifficultyID + + // Song type: normal / special + // sqlite3 doesn't support FULL OUTER JOIN so use UNION ALL here. + sql := `SELECT c_rank_score,b_rank_score,a_rank_score,s_rank_score,c_rank_combo,b_rank_combo,a_rank_combo,s_rank_combo,ac_flag,swing_flag FROM live_setting_m WHERE live_setting_id IN (SELECT live_setting_id FROM normal_live_m WHERE live_difficulty_id = ? UNION ALL SELECT live_setting_id FROM special_live_m WHERE live_difficulty_id = ?)` + rows, err := db.Query(sql, difficultyId, difficultyId) + if err != nil { + panic(err) + } + + var c_rank_score, b_rank_score, a_rank_score, s_rank_score, c_rank_combo, b_rank_combo, a_rank_combo, s_rank_combo, ac_flag, swing_flag int + for rows.Next() { + err = rows.Scan(&c_rank_score, &b_rank_score, &a_rank_score, &s_rank_score, &c_rank_combo, &b_rank_combo, &a_rank_combo, &s_rank_combo, &ac_flag, &swing_flag) + if err != nil { + panic(err) + } + } + + // HACK UnitList + unitsList := []model.PlayRewardUnitList{} + unitId := 3071290940 + for i := 0; i < 9; i++ { + unitList := model.PlayRewardUnitList{ + UnitOwningUserID: int64(unitId + i), + UnitID: 2122, + Position: i + 1, + Level: 120, + LevelLimitID: 1, + DisplayRank: 2, + Love: 1000, + UnitSkillLevel: 8, + IsRankMax: true, + IsLoveMax: true, + IsLevelMax: true, + IsSigned: true, + BeforeLove: 1000, + MaxLove: 1000, + } + unitsList = append(unitsList, unitList) + } + + totalScore := playRewardReq.ScoreSmile + playRewardReq.ScoreCool + playRewardReq.ScoreCute + resp := model.RewardResponseData{ + LiveInfo: []model.RewardLiveInfo{ + { + LiveDifficultyID: difficultyId, + IsRandom: false, + AcFlag: ac_flag, + SwingFlag: swing_flag, + }, + }, + TotalLove: 0, + IsHighScore: true, + HiScore: totalScore, + BaseRewardInfo: model.BaseRewardInfo{ + PlayerExp: 830, + PlayerExpUnitMax: model.PlayerExpUnitMax{ + Before: 900, + After: 900, + }, + PlayerExpFriendMax: model.PlayerExpFriendMax{ + Before: 99, + After: 99, + }, + PlayerExpLpMax: model.PlayerExpLpMax{ + Before: 417, + After: 417, + }, + GameCoin: 4500, + GameCoinRewardBoxFlag: false, + SocialPoint: 10, + }, + RewardUnitList: model.RewardUnitList{ + LiveClear: []model.LiveClear{}, + LiveRank: []model.LiveRank{}, + LiveCombo: []interface{}{}, + }, + UnlockedSubscenarioIds: []interface{}{}, + UnlockedMultiUnitScenarioIds: []interface{}{}, + EffortPoint: []model.EffortPoint{}, + IsEffortPointVisible: false, + LimitedEffortBox: []interface{}{}, + UnitList: unitsList, + BeforeUserInfo: model.BeforeUserInfo{ + Level: 1028, + Exp: 28823566, + PreviousExp: 27734700, + NextExp: 28941885, + GameCoin: 86505544, + SnsCoin: 49, + FreeSnsCoin: 48, + PaidSnsCoin: 1, + SocialPoint: 1438165, + UnitMax: 5000, + WaitingUnitMax: 1000, + CurrentEnergy: 392, + EnergyMax: 417, + TrainingEnergy: 9, + TrainingEnergyMax: 10, + EnergyFullTime: "2023-03-20 01:28:55", + LicenseLiveEnergyRecoverlyTime: 60, + FriendMax: 99, + TutorialState: -1, + OverMaxEnergy: 0, + UnlockRandomLiveMuse: 1, + UnlockRandomLiveAqours: 1, + }, + AfterUserInfo: model.AfterUserInfo{ + Level: 1028, + Exp: 28824396, + PreviousExp: 27734700, + NextExp: 28941885, + GameCoin: 86520044, + SnsCoin: 50, + FreeSnsCoin: 49, + PaidSnsCoin: 1, + SocialPoint: 1438375, + UnitMax: 5000, + WaitingUnitMax: 1000, + CurrentEnergy: 392, + EnergyMax: 417, + TrainingEnergy: 9, + TrainingEnergyMax: 10, + EnergyFullTime: "2023-03-20 01:28:55", + LicenseLiveEnergyRecoverlyTime: 60, + FriendMax: 99, + TutorialState: -1, + OverMaxEnergy: 0, + UnlockRandomLiveMuse: 1, + UnlockRandomLiveAqours: 1, + }, + NextLevelInfo: []model.NextLevelInfo{ + { + Level: 1028, + FromExp: 28823566, + }, + }, + GoalAccompInfo: model.GoalAccompInfo{ + AchievedIds: []interface{}{}, + Rewards: []interface{}{}, + }, + SpecialRewardInfo: []interface{}{}, + EventInfo: []interface{}{}, + DailyRewardInfo: []interface{}{}, + CanSendFriendRequest: false, + UsingBuffInfo: []interface{}{}, + ClassSystem: model.ClassSystem{ + RankInfo: model.RewardRankInfo{ + BeforeClassRankID: 10, + AfterClassRankID: 10, + RankUpDate: "2020-02-12 11:57:15", + }, + CompleteFlag: false, + IsOpened: true, + IsVisible: true, + }, + AccomplishedAchievementList: []model.AccomplishedAchievementList{}, + UnaccomplishedAchievementCnt: 15, + AddedAchievementList: []interface{}{}, + MuseumInfo: model.RewardMuseumInfo{}, + UnitSupportList: []model.RewardUnitSupportList{}, + ServerTimestamp: 1679238066, + PresentCnt: 2159, + } + + if playRewardReq.MaxCombo > s_rank_combo { + resp.ComboRank = 1 + } else if playRewardReq.MaxCombo > a_rank_combo { + resp.ComboRank = 2 + } else if playRewardReq.MaxCombo > b_rank_combo { + resp.ComboRank = 3 + } else if playRewardReq.MaxCombo > c_rank_combo { + resp.ComboRank = 4 + } else { + resp.ComboRank = 5 + } + + if totalScore > s_rank_score { + resp.Rank = 1 + } else if totalScore > a_rank_score { + resp.Rank = 2 + } else if totalScore > b_rank_score { + resp.Rank = 3 + } else if totalScore > c_rank_score { + resp.Rank = 4 + } else { + resp.Rank = 5 + } + + m, err := json.Marshal(resp) + if err != nil { + panic(err) + } + + res := model.Response{ + ResponseData: m, + ReleaseInfo: []interface{}{}, + StatusCode: 200, + } + + mm, err := json.Marshal(res) + if err != nil { + panic(err) + } + fmt.Println(string(mm)) + + xms := encrypt.RSA_Sign_SHA1(mm, "privatekey.pem") + xms64 := base64.RawStdEncoding.EncodeToString(xms) + + ctx.Header("Server-Version", config.Conf.Server.VersionNumber) + ctx.Header("user_id", userId[0]) + ctx.Header("authorize", newAuthorizeStr) + ctx.Header("X-Message-Sign", xms64) + ctx.String(http.StatusOK, string(mm)) +} diff --git a/main.go b/main.go index b4387aa..2035815 100644 --- a/main.go +++ b/main.go @@ -71,6 +71,8 @@ func main() { m.POST("/payment/productList", handler.ProductListHandler) m.POST("/live/partyList", handler.PartyListHandler) m.POST("/live/play", handler.PlayLiveHandler) + m.POST("/live/preciseScore", handler.PlayScoreHandler) + m.POST("/live/reward", handler.PlayRewardHandler) m.POST("/live/gameover", handler.GameOverHandler) m.POST("/unit/setDisplayRank", handler.SetDisplayRankHandler) m.POST("/unit/favorite", handler.SetDisplayRankHandler) diff --git a/model/live.go b/model/live.go index daf230f..1abca49 100644 --- a/model/live.go +++ b/model/live.go @@ -166,3 +166,397 @@ type PlayResponseData struct { CanActivateEffect bool `json:"can_activate_effect"` ServerTimestamp int `json:"server_timestamp"` } + +// preciseScore +type PlayScoreReq struct { + Module string `json:"module"` + Action string `json:"action"` + TimeStamp int `json:"timeStamp"` + Mgd int `json:"mgd"` + LiveDifficultyID string `json:"live_difficulty_id"` + CommandNum string `json:"commandNum"` +} + +type On struct { + HasRecord bool `json:"has_record"` + LiveInfo LiveInfo `json:"live_info"` + RandomSeed interface{} `json:"random_seed"` + MaxCombo interface{} `json:"max_combo"` + UpdateDate interface{} `json:"update_date"` + PreciseList interface{} `json:"precise_list"` + DeckInfo interface{} `json:"deck_info"` + TapAdjust interface{} `json:"tap_adjust"` + CanReplay bool `json:"can_replay"` +} + +type Off struct { + HasRecord bool `json:"has_record"` + LiveInfo LiveInfo `json:"live_info"` + RandomSeed interface{} `json:"random_seed"` + MaxCombo interface{} `json:"max_combo"` + UpdateDate interface{} `json:"update_date"` + PreciseList interface{} `json:"precise_list"` + DeckInfo interface{} `json:"deck_info"` + TapAdjust interface{} `json:"tap_adjust"` + CanReplay bool `json:"can_replay"` +} + +type PlayScoreResponseData struct { + On On `json:"on"` + Off Off `json:"off"` + RankInfo []RankInfo `json:"rank_info"` + CanActivateEffect bool `json:"can_activate_effect"` + ServerTimestamp int `json:"server_timestamp"` +} + +// reward +type PlayRewardReq struct { + Module string `json:"module"` + Action string `json:"action"` + GoodCnt int `json:"good_cnt"` + MissCnt int `json:"miss_cnt"` + IsTraining bool `json:"is_training"` + GreatCnt int `json:"great_cnt"` + CommandNum string `json:"commandNum"` + LoveCnt int `json:"love_cnt"` + RemainHp int `json:"remain_hp"` + MaxCombo int `json:"max_combo"` + ScoreSmile int `json:"score_smile"` + PerfectCnt int `json:"perfect_cnt"` + BadCnt int `json:"bad_cnt"` + Mgd int `json:"mgd"` + EventPoint int `json:"event_point"` + LiveDifficultyID int `json:"live_difficulty_id"` + TimeStamp int `json:"timeStamp"` + PreciseScoreLog PreciseScoreLog `json:"precise_score_log"` + ScoreCute int `json:"score_cute"` + EventID interface{} `json:"event_id"` + ScoreCool int `json:"score_cool"` +} + +type Icon struct { + SlideID int `json:"slide_id"` + JustID int `json:"just_id"` + NormalID int `json:"normal_id"` +} + +type LiveSetting struct { + StringSize int `json:"string_size"` + PreciseScoreAutoUpdateFlag bool `json:"precise_score_auto_update_flag"` + SeID int `json:"se_id"` + CutinBrightness int `json:"cutin_brightness"` + RandomValue int `json:"random_value"` + PreciseScoreUpdateType int `json:"precise_score_update_type"` + EffectFlag bool `json:"effect_flag"` + NotesSpeed float64 `json:"notes_speed"` + Icon Icon `json:"icon"` + CutinType int `json:"cutin_type"` +} + +type PreciseList struct { + Effect int `json:"effect"` + Count int `json:"count"` + Tap float64 `json:"tap"` + NoteNumber int `json:"note_number"` + Position int `json:"position"` + Accuracy int `json:"accuracy"` + IsSame bool `json:"is_same"` +} + +type BackgroundScore struct { + Smile int `json:"smile"` + Cute int `json:"cute"` + Cool int `json:"cool"` +} + +type TriggerLog struct { + ActivationRate int `json:"activation_rate"` + Position int `json:"position"` +} +type PreciseScoreLog struct { + LiveSetting LiveSetting `json:"live_setting"` + TapAdjust int `json:"tap_adjust"` + PreciseList []PreciseList `json:"precise_list"` + BackgroundScore BackgroundScore `json:"background_score"` + IsLogOn bool `json:"is_log_on"` + ScoreLog []int `json:"score_log"` + IsSkillOn bool `json:"is_skill_on"` + TriggerLog []TriggerLog `json:"trigger_log"` + RandomSeed int `json:"random_seed"` +} + +type RewardLiveInfo struct { + LiveDifficultyID int `json:"live_difficulty_id"` + IsRandom bool `json:"is_random"` + AcFlag int `json:"ac_flag"` + SwingFlag int `json:"swing_flag"` +} + +type PlayerExpUnitMax struct { + Before int `json:"before"` + After int `json:"after"` +} + +type PlayerExpFriendMax struct { + Before int `json:"before"` + After int `json:"after"` +} + +type PlayerExpLpMax struct { + Before int `json:"before"` + After int `json:"after"` +} + +type BaseRewardInfo struct { + PlayerExp int `json:"player_exp"` + PlayerExpUnitMax PlayerExpUnitMax `json:"player_exp_unit_max"` + PlayerExpFriendMax PlayerExpFriendMax `json:"player_exp_friend_max"` + PlayerExpLpMax PlayerExpLpMax `json:"player_exp_lp_max"` + GameCoin int `json:"game_coin"` + GameCoinRewardBoxFlag bool `json:"game_coin_reward_box_flag"` + SocialPoint int `json:"social_point"` +} + +type LiveClear struct { + AddType int `json:"add_type"` + Amount int `json:"amount"` + ItemCategoryID int `json:"item_category_id"` + UnitID int `json:"unit_id"` + UnitOwningUserID int64 `json:"unit_owning_user_id"` + IsSupportMember bool `json:"is_support_member"` + Exp int `json:"exp"` + NextExp int `json:"next_exp"` + MaxHp int `json:"max_hp"` + Level int `json:"level"` + MaxLevel int `json:"max_level"` + LevelLimitID int `json:"level_limit_id"` + SkillLevel int `json:"skill_level"` + Rank int `json:"rank"` + Love int `json:"love"` + IsRankMax bool `json:"is_rank_max"` + IsLevelMax bool `json:"is_level_max"` + IsLoveMax bool `json:"is_love_max"` + IsSigned bool `json:"is_signed"` + NewUnitFlag bool `json:"new_unit_flag"` + RewardBoxFlag bool `json:"reward_box_flag"` + UnitSkillExp int `json:"unit_skill_exp"` + DisplayRank int `json:"display_rank"` + UnitRemovableSkillCapacity int `json:"unit_removable_skill_capacity"` + RemovableSkillIds []interface{} `json:"removable_skill_ids"` +} + +type LiveRank struct { + AddType int `json:"add_type"` + Amount int `json:"amount"` + ItemCategoryID int `json:"item_category_id"` + UnitID int `json:"unit_id"` + UnitOwningUserID int64 `json:"unit_owning_user_id"` + IsSupportMember bool `json:"is_support_member"` + Exp int `json:"exp"` + NextExp int `json:"next_exp"` + MaxHp int `json:"max_hp"` + Level int `json:"level"` + MaxLevel int `json:"max_level"` + LevelLimitID int `json:"level_limit_id"` + SkillLevel int `json:"skill_level"` + Rank int `json:"rank"` + Love int `json:"love"` + IsRankMax bool `json:"is_rank_max"` + IsLevelMax bool `json:"is_level_max"` + IsLoveMax bool `json:"is_love_max"` + IsSigned bool `json:"is_signed"` + NewUnitFlag bool `json:"new_unit_flag"` + RewardBoxFlag bool `json:"reward_box_flag"` + UnitSkillExp int `json:"unit_skill_exp"` + DisplayRank int `json:"display_rank"` + UnitRemovableSkillCapacity int `json:"unit_removable_skill_capacity"` + RemovableSkillIds []interface{} `json:"removable_skill_ids"` +} + +type RewardUnitList struct { + LiveClear []LiveClear `json:"live_clear"` + LiveRank []LiveRank `json:"live_rank"` + LiveCombo []interface{} `json:"live_combo"` +} + +type Rewards struct { + Rarity int `json:"rarity"` + ItemID int `json:"item_id"` + AddType int `json:"add_type"` + Amount int `json:"amount"` + ItemCategoryID int `json:"item_category_id"` + RewardBoxFlag bool `json:"reward_box_flag"` + InsertDate string `json:"insert_date"` +} + +type EffortPoint struct { + LiveEffortPointBoxSpecID int `json:"live_effort_point_box_spec_id"` + Capacity int `json:"capacity"` + Before int `json:"before"` + After int `json:"after"` + Rewards []Rewards `json:"rewards"` +} + +type PlayRewardUnitList struct { + UnitOwningUserID int64 `json:"unit_owning_user_id"` + UnitID int `json:"unit_id"` + Position int `json:"position"` + Level int `json:"level"` + LevelLimitID int `json:"level_limit_id"` + DisplayRank int `json:"display_rank"` + Love int `json:"love"` + UnitSkillLevel int `json:"unit_skill_level"` + IsRankMax bool `json:"is_rank_max"` + IsLoveMax bool `json:"is_love_max"` + IsLevelMax bool `json:"is_level_max"` + IsSigned bool `json:"is_signed"` + BeforeLove int `json:"before_love"` + MaxLove int `json:"max_love"` + // Costume Costume `json:"costume,omitempty"` +} + +type BeforeUserInfo struct { + Level int `json:"level"` + Exp int `json:"exp"` + PreviousExp int `json:"previous_exp"` + NextExp int `json:"next_exp"` + GameCoin int `json:"game_coin"` + SnsCoin int `json:"sns_coin"` + FreeSnsCoin int `json:"free_sns_coin"` + PaidSnsCoin int `json:"paid_sns_coin"` + SocialPoint int `json:"social_point"` + UnitMax int `json:"unit_max"` + WaitingUnitMax int `json:"waiting_unit_max"` + CurrentEnergy int `json:"current_energy"` + EnergyMax int `json:"energy_max"` + TrainingEnergy int `json:"training_energy"` + TrainingEnergyMax int `json:"training_energy_max"` + EnergyFullTime string `json:"energy_full_time"` + LicenseLiveEnergyRecoverlyTime int `json:"license_live_energy_recoverly_time"` + FriendMax int `json:"friend_max"` + TutorialState int `json:"tutorial_state"` + OverMaxEnergy int `json:"over_max_energy"` + UnlockRandomLiveMuse int `json:"unlock_random_live_muse"` + UnlockRandomLiveAqours int `json:"unlock_random_live_aqours"` +} + +type AfterUserInfo struct { + Level int `json:"level"` + Exp int `json:"exp"` + PreviousExp int `json:"previous_exp"` + NextExp int `json:"next_exp"` + GameCoin int `json:"game_coin"` + SnsCoin int `json:"sns_coin"` + FreeSnsCoin int `json:"free_sns_coin"` + PaidSnsCoin int `json:"paid_sns_coin"` + SocialPoint int `json:"social_point"` + UnitMax int `json:"unit_max"` + WaitingUnitMax int `json:"waiting_unit_max"` + CurrentEnergy int `json:"current_energy"` + EnergyMax int `json:"energy_max"` + TrainingEnergy int `json:"training_energy"` + TrainingEnergyMax int `json:"training_energy_max"` + EnergyFullTime string `json:"energy_full_time"` + LicenseLiveEnergyRecoverlyTime int `json:"license_live_energy_recoverly_time"` + FriendMax int `json:"friend_max"` + TutorialState int `json:"tutorial_state"` + OverMaxEnergy int `json:"over_max_energy"` + UnlockRandomLiveMuse int `json:"unlock_random_live_muse"` + UnlockRandomLiveAqours int `json:"unlock_random_live_aqours"` +} + +type NextLevelInfo struct { + Level int `json:"level"` + FromExp int `json:"from_exp"` +} + +type GoalAccompInfo struct { + AchievedIds []interface{} `json:"achieved_ids"` + Rewards []interface{} `json:"rewards"` +} + +type RewardRankInfo struct { + BeforeClassRankID int `json:"before_class_rank_id"` + AfterClassRankID int `json:"after_class_rank_id"` + RankUpDate string `json:"rank_up_date"` +} + +type ClassSystem struct { + RankInfo RewardRankInfo `json:"rank_info"` + CompleteFlag bool `json:"complete_flag"` + IsOpened bool `json:"is_opened"` + IsVisible bool `json:"is_visible"` +} + +type PlayRewardList struct { + ItemID int `json:"item_id"` + AddType int `json:"add_type"` + Amount int `json:"amount"` + ItemCategoryID int `json:"item_category_id"` + RewardBoxFlag bool `json:"reward_box_flag"` +} + +type AccomplishedAchievementList struct { + AchievementID int `json:"achievement_id"` + Count int `json:"count"` + IsAccomplished bool `json:"is_accomplished"` + InsertDate string `json:"insert_date"` + EndDate string `json:"end_date"` + RemainingTime string `json:"remaining_time"` + IsNew bool `json:"is_new"` + ForDisplay bool `json:"for_display"` + IsLocked bool `json:"is_locked"` + OpenConditionString string `json:"open_condition_string"` + AccomplishID string `json:"accomplish_id"` + RewardList []PlayRewardList `json:"reward_list"` +} + +type Parameter struct { + Smile int `json:"smile"` + Pure int `json:"pure"` + Cool int `json:"cool"` +} + +type RewardMuseumInfo struct { + Parameter Parameter `json:"parameter"` + ContentsIDList []int `json:"contents_id_list"` +} + +type RewardUnitSupportList struct { + UnitID int `json:"unit_id"` + Amount int `json:"amount"` +} + +type RewardResponseData struct { + LiveInfo []RewardLiveInfo `json:"live_info"` + Rank int `json:"rank"` + ComboRank int `json:"combo_rank"` + TotalLove int `json:"total_love"` + IsHighScore bool `json:"is_high_score"` + HiScore int `json:"hi_score"` + BaseRewardInfo BaseRewardInfo `json:"base_reward_info"` + RewardUnitList RewardUnitList `json:"reward_unit_list"` + UnlockedSubscenarioIds []interface{} `json:"unlocked_subscenario_ids"` + UnlockedMultiUnitScenarioIds []interface{} `json:"unlocked_multi_unit_scenario_ids"` + EffortPoint []EffortPoint `json:"effort_point"` + IsEffortPointVisible bool `json:"is_effort_point_visible"` + LimitedEffortBox []interface{} `json:"limited_effort_box"` + UnitList []PlayRewardUnitList `json:"unit_list"` + BeforeUserInfo BeforeUserInfo `json:"before_user_info"` + AfterUserInfo AfterUserInfo `json:"after_user_info"` + NextLevelInfo []NextLevelInfo `json:"next_level_info"` + GoalAccompInfo GoalAccompInfo `json:"goal_accomp_info"` + SpecialRewardInfo []interface{} `json:"special_reward_info"` + EventInfo []interface{} `json:"event_info"` + DailyRewardInfo []interface{} `json:"daily_reward_info"` + CanSendFriendRequest bool `json:"can_send_friend_request"` + UsingBuffInfo []interface{} `json:"using_buff_info"` + ClassSystem ClassSystem `json:"class_system"` + AccomplishedAchievementList []AccomplishedAchievementList `json:"accomplished_achievement_list"` + UnaccomplishedAchievementCnt int `json:"unaccomplished_achievement_cnt"` + AddedAchievementList []interface{} `json:"added_achievement_list"` + MuseumInfo RewardMuseumInfo `json:"museum_info"` + UnitSupportList []RewardUnitSupportList `json:"unit_support_list"` + ServerTimestamp int `json:"server_timestamp"` + PresentCnt int `json:"present_cnt"` +}