commit 74fd6dcbee3d4cb9cd3c277a3884060082481729 Author: Branden J Brown Date: Tue Jul 28 01:30:29 2026 -0400 initial commit diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..f989397 --- /dev/null +++ b/go.mod @@ -0,0 +1,8 @@ +module git.sunturtle.xyz/zephyr/ismdata + +go 1.26.5 + +require ( + git.sunturtle.xyz/zephyr/horse v0.0.0-20260725155724-79d4e7609089 + github.com/google/go-cmp v0.7.0 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..ba73237 --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +git.sunturtle.xyz/zephyr/horse v0.0.0-20260725155724-79d4e7609089 h1:6Li/Q/KxUeH8KaN46iYKjbkthP5fAXXC6DkpMgxFSFA= +git.sunturtle.xyz/zephyr/horse v0.0.0-20260725155724-79d4e7609089/go.mod h1:Kqy1/kbqYbQuRe2RqUWJ1XfWjBzORXuto8/DXoqRMI4= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= diff --git a/ism.go b/ism.go new file mode 100644 index 0000000..bb5e913 --- /dev/null +++ b/ism.go @@ -0,0 +1,231 @@ +package main + +import "git.sunturtle.xyz/zephyr/horse" + +type SupportCardID int32 // package horse doesn't have this yet + +type WorkIdleSingleMode struct { + Chara SingleModeChara `json:"charaInfo"` + StartTime int64 `json:"startTime"` + EndTime int64 `json:"endTime"` + ProgressLog IdleSingleModeProgressLog `json:"progressLogInfo"` +} + +type Skill struct { + SkillID horse.SkillID `json:"skill_id"` + Level int32 `json:"level"` +} + +type SkillTip struct { + GroupID horse.SkillGroupID `json:"group_id"` + Rarity int32 `json:"rarity"` + Level int32 `json:"level"` +} + +type SingleModeSupportCard struct { + Position int32 `json:"position"` + SupportCardID SupportCardID `json:"support_card_id"` + LimitBreakCount int32 `json:"limit_break_count"` + Exp int32 `json:"exp"` + TrainingPartnerState int32 `json:"training_partner_state"` + OwnerViewerID int64 `json:"owner_viewer_id"` + RentalType int32 `json:"rental_type"` +} + +type GroupOuting struct { + CharaID horse.CharacterID `json:"chara_id"` + IsOuting int32 `json:"is_outing"` + StoryStep int32 `json:"story_step"` +} + +type Evaluation struct { + TargetID int32 `json:"target_id"` + Evaluation int32 `json:"evaluation"` + IsOuting int32 `json:"is_outing"` + StoryStep int32 `json:"story_step"` + IsAppear int32 `json:"is_appear"` + GroupOutingInfo []GroupOuting `json:"group_outing_info_array"` +} + +type TrainingLevel struct { + CommandID int32 `json:"command_id"` + Level int32 `json:"level"` +} + +type GuestOuting struct { + SupportCardID SupportCardID `json:"support_card_id"` + StoryStep int32 `json:"story_step"` + GroupOutingInfo []GroupOuting `json:"group_outing_info_array"` +} + +type SingleModeSkillUpgrade struct { + ConditionID int32 `json:"condition_id"` + TotalCount int32 `json:"total_count"` + CurrentCount int32 `json:"current_count"` +} + +type SingleModeChara struct { + SingleModeCharaID int32 `json:"single_mode_chara_id"` + CardID horse.UmaID `json:"card_id"` + CharaGrade int32 `json:"chara_grade"` + Speed int32 `json:"speed"` + Stamina int32 `json:"stamina"` + Power int32 `json:"power"` + Wiz int32 `json:"wiz"` + Guts int32 `json:"guts"` + Vital int32 `json:"vital"` + MaxSpeed int32 `json:"max_speed"` + MaxStamina int32 `json:"max_stamina"` + MaxPower int32 `json:"max_power"` + MaxWiz int32 `json:"max_wiz"` + MaxGuts int32 `json:"max_guts"` + DefaultMaxSpeed int32 `json:"default_max_speed"` + DefaultMaxStamina int32 `json:"default_max_stamina"` + DefaultMaxPower int32 `json:"default_max_power"` + DefaultMaxWiz int32 `json:"default_max_wiz"` + DefaultMaxGuts int32 `json:"default_max_guts"` + MaxVital int32 `json:"max_vital"` + Motivation int32 `json:"motivation"` + Fans int32 `json:"fans"` + Rarity int32 `json:"rarity"` + RaceProgramID int32 `json:"race_program_id"` + ReserveRaceProgramID int32 `json:"reserve_race_program_id"` + RaceRunningStyle int32 `json:"race_running_style"` + IsShortRace int32 `json:"is_short_race"` + TalentLevel int32 `json:"talent_level"` + Skills []Skill `json:"skill_array"` + DisableSkillIDs []horse.SkillID `json:"disable_skill_id_array"` + SkillTips []SkillTip `json:"skill_tips_array"` + SupportCards []SingleModeSupportCard `json:"support_card_array"` + SuccessionTrainedCharaID1 int32 `json:"succession_trained_chara_id_1"` + SuccessionTrainedCharaID2 int32 `json:"succession_trained_chara_id_2"` + ProperDistanceShort horse.AptitudeLevel `json:"proper_distance_short"` + ProperDistanceMile horse.AptitudeLevel `json:"proper_distance_mile"` + ProperDistanceMiddle horse.AptitudeLevel `json:"proper_distance_middle"` + ProperDistanceLong horse.AptitudeLevel `json:"proper_distance_long"` + ProperRunningStyleNige horse.AptitudeLevel `json:"proper_running_style_nige"` + ProperRunningStyleSenko horse.AptitudeLevel `json:"proper_running_style_senko"` + ProperRunningStyleSashi horse.AptitudeLevel `json:"proper_running_style_sashi"` + ProperRunningStyleOikomi horse.AptitudeLevel `json:"proper_running_style_oikomi"` + ProperGroundTurf horse.AptitudeLevel `json:"proper_ground_turf"` + ProperGroundDirt horse.AptitudeLevel `json:"proper_ground_dirt"` + Turn int32 `json:"turn"` + SkillPoint int32 `json:"skill_point"` + ShortCutState int32 `json:"short_cut_state"` + State int32 `json:"state"` + PlayingState int32 `json:"playing_state"` + ScenarioID horse.ScenarioID `json:"scenario_id"` + RouteID int32 `json:"route_id"` + StartTime string `json:"start_time"` + Evaluations []Evaluation `json:"evaluation_info_array"` + TrainingLevels []TrainingLevel `json:"training_level_info_array"` + NicknameIDs []int32 `json:"nickname_id_array"` + CharaEffectIDs []int32 `json:"chara_effect_id_array"` + RouteRaceIDs []int32 `json:"route_race_id_array"` + GuestOutings []GuestOuting `json:"guest_outing_info_array"` + SkillUpgrades []SingleModeSkillUpgrade `json:"skill_upgrade_info_array"` +} + +type CharaEffectLog struct { + CharaEffectID int32 `json:"charaEffectId"` + IsActive bool `json:"isActive"` +} + +type IdleSingleModeSignedInt struct { + Sign int32 `json:"sign"` + Value int32 `json:"value"` +} + +type IdleSingleModeGainInfo struct { + Speed IdleSingleModeSignedInt `json:"speed"` + Stamina IdleSingleModeSignedInt `json:"stamina"` + Power IdleSingleModeSignedInt `json:"power"` + Wiz IdleSingleModeSignedInt `json:"wiz"` + Guts IdleSingleModeSignedInt `json:"guts"` + MaxSpeed int32 `json:"maxSpeed"` + MaxStamina int32 `json:"maxStamina"` + MaxPower int32 `json:"maxPower"` + MaxWiz int32 `json:"maxWiz"` + MaxGuts int32 `json:"maxGuts"` + ProperDistanceShort horse.AptitudeLevel `json:"properDistanceShort"` + ProperDistanceMile horse.AptitudeLevel `json:"properDistanceMile"` + ProperDistanceMiddle horse.AptitudeLevel `json:"properDistanceMiddle"` + ProperDistanceLong horse.AptitudeLevel `json:"properDistanceLong"` + ProperRunningStyleNige horse.AptitudeLevel `json:"properRunningStyleNige"` + ProperRunningStyleSenko horse.AptitudeLevel `json:"properRunningStyleSenko"` + ProperRunningStyleSashi horse.AptitudeLevel `json:"properRunningStyleSashi"` + ProperRunningStyleOikomi horse.AptitudeLevel `json:"properRunningStyleOikomi"` + ProperGroundTurf horse.AptitudeLevel `json:"properGroundTurf"` + ProperGroundDirt horse.AptitudeLevel `json:"properGroundDirt"` + SkillPoint int32 `json:"skillPoint"` + SkillTips []SkillTip `json:"skillTips"` +} + +type IdleSingleModeSupportCardGain struct { + SupportCardID SupportCardID `json:"supportCardId"` + GainInfo IdleSingleModeGainInfo `json:"gainInfo"` +} + +type Factor struct { + FactorID horse.SparkID `json:"factorId"` + Level int32 `json:"level"` +} + +type IdleSingleModeSuccessionFactorGain struct { + Year int32 `json:"year"` + GainFactorInfo []Factor `json:"gainFactorInfoArray"` +} + +type SingleRaceHistory struct { + Turn int32 `json:"turn"` + ProgramID int32 `json:"program_id"` + Weather int32 `json:"weather"` + GroundCondition int32 `json:"ground_condition"` + RunningStyle int32 `json:"running_style"` + ResultRank int32 `json:"result_rank"` + FrameOrder int32 `json:"frame_order"` + NpcCount int32 `json:"npc_count"` +} + +type RaceReward struct { + ItemType int32 `json:"item_type"` + ItemID int32 `json:"item_id"` + ItemNum int32 `json:"item_num"` +} + +type RaceRewardLimit struct { + RewardID int32 `json:"reward_id"` + ItemType int32 `json:"item_type"` + ItemID int32 `json:"item_id"` + ItemNum int32 `json:"item_num"` + RestCount int32 `json:"rest_count"` +} + +type CharaRaceReward struct { + ResultRank int32 `json:"result_rank"` + ResultTime int32 `json:"result_time"` + RaceReward []RaceReward `json:"race_reward"` + RaceRewardBonus []RaceReward `json:"race_reward_bonus"` + RaceRewardPlusBonus []RaceReward `json:"race_reward_plus_bonus"` + RaceRewardBonusWin []RaceReward `json:"race_reward_bonus_win"` + RaceRewardLimit []RaceRewardLimit `json:"race_reward_limit"` + GainedFans int32 `json:"gained_fans"` + CampaignIDs []int32 `json:"campaign_id_array"` +} + +type IdleSingleModeRaceHistory struct { + RaceHistory SingleRaceHistory `json:"race_history"` + RaceRewardInfo CharaRaceReward `json:"race_reward_info"` + LoseTipsID int32 `json:"lose_tips_id"` +} + +type IdleSingleModeProgressLog struct { + CharaEffectLog []CharaEffectLog `json:"charaEffectLog"` + SupportCardGains []IdleSingleModeSupportCardGain `json:"supportCardGainInfo"` + EventGain IdleSingleModeGainInfo `json:"eventGainInfo"` + SuccessionGain IdleSingleModeGainInfo `json:"successionGainInfo"` + SuccessionFactorGains []IdleSingleModeSuccessionFactorGain `json:"successionFactorGainArray"` + RaceHistory []IdleSingleModeRaceHistory `json:"raceHistoryArray"` + GainSkillIDs []horse.SkillID `json:"gainSkillIdArray"` + TotalSkillPoint int32 `json:"totalSkillPoint"` +} diff --git a/ism_test.go b/ism_test.go new file mode 100644 index 0000000..3b04965 --- /dev/null +++ b/ism_test.go @@ -0,0 +1,810 @@ +package main + +import ( + _ "embed" + "encoding/json" + "strings" + "testing" + + "git.sunturtle.xyz/zephyr/horse" + "github.com/google/go-cmp/cmp" +) + +//go:embed testdata.json +var testJSON string + +func TestModel(t *testing.T) { + want := WorkIdleSingleMode{ + Chara: SingleModeChara{ + SingleModeCharaID: 1823, + CardID: 102401, + CharaGrade: 1, + Speed: 107, + Stamina: 118, + Power: 103, + Wiz: 147, + Guts: 133, + Vital: 100, + MaxSpeed: 1616, + MaxStamina: 1300, + MaxPower: 1318, + MaxWiz: 1332, + MaxGuts: 1516, + DefaultMaxSpeed: 1200, + DefaultMaxStamina: 1200, + DefaultMaxPower: 1200, + DefaultMaxWiz: 1200, + DefaultMaxGuts: 1200, + MaxVital: 100, + Motivation: 3, + Fans: 1, + Rarity: 4, + RaceProgramID: 0, + ReserveRaceProgramID: 0, + RaceRunningStyle: 1, + IsShortRace: 0, + TalentLevel: 5, + Skills: []Skill{ + {SkillID: 100241, Level: 2}, + }, + DisableSkillIDs: []horse.SkillID{}, + SkillTips: []SkillTip{ + {GroupID: 90014, Rarity: 1, Level: 2}, + {GroupID: 90020, Rarity: 1, Level: 1}, + }, + SupportCards: []SingleModeSupportCard{ + { + Position: 1, + SupportCardID: 30010, + LimitBreakCount: 4, + Exp: 118185, + TrainingPartnerState: 0, + OwnerViewerID: 0, + RentalType: 0, + }, + { + Position: 2, + SupportCardID: 30108, + LimitBreakCount: 4, + Exp: 118185, + TrainingPartnerState: 0, + OwnerViewerID: 0, + RentalType: 0, + }, + { + Position: 3, + SupportCardID: 30062, + LimitBreakCount: 4, + Exp: 118185, + TrainingPartnerState: 0, + OwnerViewerID: 0, + RentalType: 0, + }, + { + Position: 4, + SupportCardID: 30107, + LimitBreakCount: 4, + Exp: 118185, + TrainingPartnerState: 0, + OwnerViewerID: 0, + RentalType: 0, + }, + { + Position: 5, + SupportCardID: 30028, + LimitBreakCount: 4, + Exp: 118185, + TrainingPartnerState: 0, + OwnerViewerID: 0, + RentalType: 0, + }, + { + Position: 6, + SupportCardID: 30052, + LimitBreakCount: 4, + Exp: 118185, + TrainingPartnerState: 0, + OwnerViewerID: 818784439809, + RentalType: 0, + }, + }, + SuccessionTrainedCharaID1: 4637, + SuccessionTrainedCharaID2: 4670, + ProperDistanceShort: horse.AptitudeLvD, + ProperDistanceMile: horse.AptitudeLvC, + ProperDistanceMiddle: horse.AptitudeLvA, + ProperDistanceLong: horse.AptitudeLvA, + ProperRunningStyleNige: horse.AptitudeLvA, + ProperRunningStyleSenko: horse.AptitudeLvA, + ProperRunningStyleSashi: horse.AptitudeLvB, + ProperRunningStyleOikomi: horse.AptitudeLvB, + ProperGroundTurf: horse.AptitudeLvA, + ProperGroundDirt: horse.AptitudeLvA, + Turn: 1, + SkillPoint: 0, + ShortCutState: 0, + State: 0, + PlayingState: 1, + ScenarioID: 3, + RouteID: 14, + StartTime: "2026-07-27 15:37:29", + Evaluations: []Evaluation{ + { + TargetID: 1, + Evaluation: 15, + IsOuting: 0, + StoryStep: 0, + IsAppear: 1, + GroupOutingInfo: []GroupOuting{}, + }, + { + TargetID: 2, + Evaluation: 20, + IsOuting: 0, + StoryStep: 0, + IsAppear: 1, + GroupOutingInfo: []GroupOuting{}, + }, + { + TargetID: 3, + Evaluation: 30, + IsOuting: 0, + StoryStep: 0, + IsAppear: 1, + GroupOutingInfo: []GroupOuting{}, + }, + { + TargetID: 4, + Evaluation: 30, + IsOuting: 0, + StoryStep: 0, + IsAppear: 1, + GroupOutingInfo: []GroupOuting{}, + }, + { + TargetID: 5, + Evaluation: 35, + IsOuting: 0, + StoryStep: 0, + IsAppear: 1, + GroupOutingInfo: []GroupOuting{}, + }, + { + TargetID: 6, + Evaluation: 30, + IsOuting: 0, + StoryStep: 0, + IsAppear: 0, + GroupOutingInfo: []GroupOuting{}, + }, + { + TargetID: 101, + Evaluation: 0, + IsOuting: 0, + StoryStep: 0, + IsAppear: 0, + GroupOutingInfo: []GroupOuting{}, + }, + { + TargetID: 102, + Evaluation: 0, + IsOuting: 0, + StoryStep: 0, + IsAppear: 0, + GroupOutingInfo: []GroupOuting{}, + }, + { + TargetID: 103, + Evaluation: 0, + IsOuting: 0, + StoryStep: 0, + IsAppear: 0, + GroupOutingInfo: []GroupOuting{}, + }, + { + TargetID: 104, + Evaluation: 0, + IsOuting: 0, + StoryStep: 0, + IsAppear: 0, + GroupOutingInfo: []GroupOuting{}, + }, + { + TargetID: 106, + Evaluation: 0, + IsOuting: 0, + StoryStep: 0, + IsAppear: 0, + GroupOutingInfo: []GroupOuting{}, + }, + }, + TrainingLevels: []TrainingLevel{ + {CommandID: 101, Level: 1}, + {CommandID: 102, Level: 1}, + {CommandID: 103, Level: 1}, + {CommandID: 105, Level: 1}, + {CommandID: 106, Level: 1}, + {CommandID: 601, Level: 5}, + {CommandID: 602, Level: 5}, + {CommandID: 603, Level: 5}, + {CommandID: 604, Level: 5}, + {CommandID: 605, Level: 5}, + }, + NicknameIDs: []int32{}, + CharaEffectIDs: []int32{}, + RouteRaceIDs: []int32{ + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + }, + GuestOutings: []GuestOuting{}, + SkillUpgrades: []SingleModeSkillUpgrade{}, + }, + StartTime: 1785166649, + EndTime: 1785169649, + ProgressLog: IdleSingleModeProgressLog{ + CharaEffectLog: []CharaEffectLog{ + {CharaEffectID: 7, IsActive: true}, + }, + SupportCardGains: []IdleSingleModeSupportCardGain{ + { + SupportCardID: 30010, + GainInfo: IdleSingleModeGainInfo{ + Speed: IdleSingleModeSignedInt{Value: 56}, + Stamina: IdleSingleModeSignedInt{Value: 33}, + Power: IdleSingleModeSignedInt{Value: 33}, + Wiz: IdleSingleModeSignedInt{Value: 193}, + Guts: IdleSingleModeSignedInt{Value: 33}, + SkillPoint: 319, + SkillTips: []SkillTip{ + {GroupID: 20019, Rarity: 1, Level: 1}, + {GroupID: 20001, Rarity: 1, Level: 1}, + }, + }, + }, + { + SupportCardID: 30108, + GainInfo: IdleSingleModeGainInfo{ + Speed: IdleSingleModeSignedInt{Value: 54}, + Stamina: IdleSingleModeSignedInt{Value: 35}, + Power: IdleSingleModeSignedInt{Value: 35}, + Wiz: IdleSingleModeSignedInt{Value: 135}, + Guts: IdleSingleModeSignedInt{Value: 35}, + SkillPoint: 408, + SkillTips: []SkillTip{ + {GroupID: 20157, Rarity: 1, Level: 4}, + {GroupID: 20203, Rarity: 1, Level: 4}, + {GroupID: 20156, Rarity: 1, Level: 4}, + }, + }, + }, + { + SupportCardID: 30062, + GainInfo: IdleSingleModeGainInfo{ + Speed: IdleSingleModeSignedInt{Value: 31}, + Stamina: IdleSingleModeSignedInt{Value: 184}, + Power: IdleSingleModeSignedInt{Value: 31}, + Wiz: IdleSingleModeSignedInt{Value: 31}, + Guts: IdleSingleModeSignedInt{Value: 65}, + SkillPoint: 234, + SkillTips: []SkillTip{ + {GroupID: 20127, Rarity: 1, Level: 2}, + }, + }, + }, + { + SupportCardID: 30107, + GainInfo: IdleSingleModeGainInfo{ + Speed: IdleSingleModeSignedInt{Value: 136}, + Stamina: IdleSingleModeSignedInt{Value: 35}, + Power: IdleSingleModeSignedInt{Value: 88}, + Wiz: IdleSingleModeSignedInt{Value: 35}, + Guts: IdleSingleModeSignedInt{Value: 35}, + SkillPoint: 287, + SkillTips: []SkillTip{ + {GroupID: 20043, Rarity: 1, Level: 3}, + {GroupID: 20127, Rarity: 1, Level: 3}, + {GroupID: 20124, Rarity: 1, Level: 3}, + }, + }, + }, + { + SupportCardID: 30028, + GainInfo: IdleSingleModeGainInfo{ + Speed: IdleSingleModeSignedInt{Value: 116}, + Stamina: IdleSingleModeSignedInt{Value: 33}, + Power: IdleSingleModeSignedInt{Value: 86}, + Wiz: IdleSingleModeSignedInt{Value: 33}, + Guts: IdleSingleModeSignedInt{Value: 33}, + SkillPoint: 284, + SkillTips: []SkillTip{ + {GroupID: 20043, Rarity: 1, Level: 1}, + {GroupID: 20076, Rarity: 1, Level: 3}, + {GroupID: 20033, Rarity: 1, Level: 3}, + {GroupID: 20118, Rarity: 1, Level: 3}, + }, + }, + }, + { + SupportCardID: 30052, + GainInfo: IdleSingleModeGainInfo{ + Speed: IdleSingleModeSignedInt{Value: 68}, + Stamina: IdleSingleModeSignedInt{Value: 28}, + Power: IdleSingleModeSignedInt{Value: 28}, + Wiz: IdleSingleModeSignedInt{Value: 28}, + Guts: IdleSingleModeSignedInt{Value: 68}, + SkillPoint: 553, + SkillTips: []SkillTip{}, + }, + }, + }, + EventGain: IdleSingleModeGainInfo{ + Speed: IdleSingleModeSignedInt{Value: 817}, + Stamina: IdleSingleModeSignedInt{Value: 313}, + Power: IdleSingleModeSignedInt{Value: 427}, + Wiz: IdleSingleModeSignedInt{Value: 498}, + Guts: IdleSingleModeSignedInt{Value: 300}, + SkillPoint: 1819, + SkillTips: []SkillTip{ + {GroupID: 20166, Rarity: 2, Level: 3}, + {GroupID: 20071, Rarity: 2, Level: 1}, + {GroupID: 20027, Rarity: 1, Level: 2}, + {GroupID: 20059, Rarity: 1, Level: 1}, + {GroupID: 21007, Rarity: 1, Level: 1}, + {GroupID: 21007, Rarity: 2, Level: 3}, + {GroupID: 20021, Rarity: 1, Level: 1}, + {GroupID: 20043, Rarity: 1, Level: 1}, + {GroupID: 20043, Rarity: 2, Level: 1}, + {GroupID: 20127, Rarity: 2, Level: 1}, + {GroupID: 20135, Rarity: 1, Level: 1}, + {GroupID: 20118, Rarity: 1, Level: 2}, + {GroupID: 20207, Rarity: 1, Level: 1}, + {GroupID: 20137, Rarity: 1, Level: 1}, + {GroupID: 20209, Rarity: 1, Level: 1}, + }, + }, + SuccessionGain: IdleSingleModeGainInfo{ + Speed: IdleSingleModeSignedInt{Value: 67}, + Stamina: IdleSingleModeSignedInt{Value: 0}, + Power: IdleSingleModeSignedInt{Value: 94}, + Wiz: IdleSingleModeSignedInt{Value: 118}, + Guts: IdleSingleModeSignedInt{Value: 59}, + MaxSpeed: 22, + MaxStamina: 2, + MaxPower: 28, + MaxWiz: 45, + MaxGuts: 22, + ProperDistanceShort: 0, + ProperDistanceMile: 1, + ProperDistanceMiddle: 0, + ProperDistanceLong: 0, + ProperRunningStyleNige: 0, + ProperRunningStyleSenko: 0, + ProperRunningStyleSashi: 0, + ProperRunningStyleOikomi: 0, + ProperGroundTurf: 0, + ProperGroundDirt: 5, + SkillPoint: 0, + SkillTips: []SkillTip{ + {GroupID: 90014, Rarity: 1, Level: 2}, + {GroupID: 90020, Rarity: 1, Level: 2}, + {GroupID: 90019, Rarity: 1, Level: 2}, + {GroupID: 20166, Rarity: 1, Level: 3}, + {GroupID: 20233, Rarity: 1, Level: 2}, + {GroupID: 20160, Rarity: 1, Level: 4}, + {GroupID: 21005, Rarity: 1, Level: 3}, + {GroupID: 20019, Rarity: 1, Level: 3}, + {GroupID: 21001, Rarity: 1, Level: 4}, + {GroupID: 20035, Rarity: 1, Level: 1}, + {GroupID: 20091, Rarity: 1, Level: 4}, + {GroupID: 20126, Rarity: 1, Level: 2}, + {GroupID: 20159, Rarity: 1, Level: 2}, + {GroupID: 20125, Rarity: 1, Level: 1}, + {GroupID: 20007, Rarity: 1, Level: 1}, + }, + }, + SuccessionFactorGains: []IdleSingleModeSuccessionFactorGain{ + { + Year: 1, + GainFactorInfo: []Factor{ + {FactorID: 103, Level: 0}, + {FactorID: 10200101, Level: 0}, + {FactorID: 503, Level: 0}, + {FactorID: 1202, Level: 0}, + {FactorID: 10140102, Level: 0}, + {FactorID: 503, Level: 0}, + {FactorID: 1202, Level: 0}, + {FactorID: 403, Level: 0}, + {FactorID: 3202, Level: 0}, + {FactorID: 302, Level: 0}, + {FactorID: 1203, Level: 0}, + {FactorID: 302, Level: 0}, + {FactorID: 1203, Level: 0}, + }, + }, + { + Year: 2, + GainFactorInfo: []Factor{ + {FactorID: 103, Level: 0}, + {FactorID: 1000802, Level: 0}, + {FactorID: 2016603, Level: 0}, + {FactorID: 2023302, Level: 0}, + {FactorID: 503, Level: 0}, + {FactorID: 2102103, Level: 0}, + {FactorID: 503, Level: 0}, + {FactorID: 2016002, Level: 0}, + {FactorID: 2100502, Level: 0}, + {FactorID: 403, Level: 0}, + {FactorID: 2001902, Level: 0}, + {FactorID: 302, Level: 0}, + {FactorID: 302, Level: 0}, + {FactorID: 1203, Level: 0}, + {FactorID: 10190102, Level: 0}, + }, + }, + { + Year: 3, + GainFactorInfo: []Factor{ + {FactorID: 103, Level: 0}, + {FactorID: 2003501, Level: 0}, + {FactorID: 2009102, Level: 0}, + {FactorID: 10200101, Level: 0}, + {FactorID: 503, Level: 0}, + {FactorID: 1002002, Level: 0}, + {FactorID: 2012502, Level: 0}, + {FactorID: 503, Level: 0}, + {FactorID: 2012602, Level: 0}, + {FactorID: 2015902, Level: 0}, + {FactorID: 403, Level: 0}, + {FactorID: 302, Level: 0}, + {FactorID: 302, Level: 0}, + }, + }, + }, + RaceHistory: []IdleSingleModeRaceHistory{ + { + RaceHistory: SingleRaceHistory{ + Turn: 12, + ProgramID: 1067, + Weather: 2, + GroundCondition: 2, + RunningStyle: 1, + ResultRank: 1, + FrameOrder: 2, + NpcCount: 0, + }, + RaceRewardInfo: CharaRaceReward{ + ResultRank: 1, + ResultTime: 0, + RaceReward: []RaceReward{ + {ItemType: 91, ItemID: 59, ItemNum: 400}, + }, + RaceRewardBonus: []RaceReward{}, + RaceRewardPlusBonus: []RaceReward{}, + RaceRewardBonusWin: []RaceReward{}, + RaceRewardLimit: []RaceRewardLimit{}, + GainedFans: 1398, + CampaignIDs: []int32{223}, + }, + LoseTipsID: 0, + }, + { + RaceHistory: SingleRaceHistory{ + Turn: 44, + ProgramID: 168, + Weather: 1, + GroundCondition: 1, + RunningStyle: 1, + ResultRank: 1, + FrameOrder: 11, + NpcCount: 0, + }, + RaceRewardInfo: CharaRaceReward{ + ResultRank: 1, + ResultTime: 0, + RaceReward: []RaceReward{ + {ItemType: 11, ItemID: 83, ItemNum: 2}, + {ItemType: 91, ItemID: 59, ItemNum: 800}, + {ItemType: 11, ItemID: 10, ItemNum: 2}, + }, + RaceRewardBonus: []RaceReward{ + {ItemType: 30, ItemID: 110, ItemNum: 40}, + }, + RaceRewardPlusBonus: []RaceReward{}, + RaceRewardBonusWin: []RaceReward{}, + RaceRewardLimit: []RaceRewardLimit{}, + GainedFans: 23976, + CampaignIDs: []int32{223}, + }, + LoseTipsID: 0, + }, + { + RaceHistory: SingleRaceHistory{ + Turn: 48, + ProgramID: 81, + Weather: 1, + GroundCondition: 1, + RunningStyle: 1, + ResultRank: 1, + FrameOrder: 4, + NpcCount: 0, + }, + RaceRewardInfo: CharaRaceReward{ + ResultRank: 1, + ResultTime: 0, + RaceReward: []RaceReward{ + {ItemType: 11, ItemID: 91, ItemNum: 2}, + {ItemType: 91, ItemID: 59, ItemNum: 800}, + {ItemType: 11, ItemID: 10, ItemNum: 2}, + }, + RaceRewardBonus: []RaceReward{ + {ItemType: 91, ItemID: 59, ItemNum: 800}, + {ItemType: 30, ItemID: 110, ItemNum: 40}, + }, + RaceRewardPlusBonus: []RaceReward{}, + RaceRewardBonusWin: []RaceReward{}, + RaceRewardLimit: []RaceRewardLimit{}, + GainedFans: 59940, + CampaignIDs: []int32{223}, + }, + LoseTipsID: 0, + }, + { + RaceHistory: SingleRaceHistory{ + Turn: 54, + ProgramID: 12, + Weather: 2, + GroundCondition: 1, + RunningStyle: 1, + ResultRank: 1, + FrameOrder: 7, + NpcCount: 0, + }, + RaceRewardInfo: CharaRaceReward{ + ResultRank: 1, + ResultTime: 0, + RaceReward: []RaceReward{ + {ItemType: 91, ItemID: 59, ItemNum: 800}, + {ItemType: 11, ItemID: 10, ItemNum: 2}, + }, + RaceRewardBonus: []RaceReward{}, + RaceRewardPlusBonus: []RaceReward{}, + RaceRewardBonusWin: []RaceReward{}, + RaceRewardLimit: []RaceRewardLimit{}, + GainedFans: 13387, + CampaignIDs: []int32{223}, + }, + LoseTipsID: 0, + }, + { + RaceHistory: SingleRaceHistory{ + Turn: 56, + ProgramID: 4, + Weather: 1, + GroundCondition: 1, + RunningStyle: 1, + ResultRank: 1, + FrameOrder: 6, + NpcCount: 0, + }, + RaceRewardInfo: CharaRaceReward{ + ResultRank: 1, + ResultTime: 0, + RaceReward: []RaceReward{ + {ItemType: 11, ItemID: 74, ItemNum: 2}, + {ItemType: 91, ItemID: 59, ItemNum: 800}, + {ItemType: 11, ItemID: 10, ItemNum: 2}, + }, + RaceRewardBonus: []RaceReward{ + {ItemType: 91, ItemID: 59, ItemNum: 800}, + {ItemType: 30, ItemID: 110, ItemNum: 40}, + }, + RaceRewardPlusBonus: []RaceReward{}, + RaceRewardBonusWin: []RaceReward{}, + RaceRewardLimit: []RaceRewardLimit{}, + GainedFans: 29970, + CampaignIDs: []int32{223}, + }, + LoseTipsID: 0, + }, + { + RaceHistory: SingleRaceHistory{ + Turn: 60, + ProgramID: 74, + Weather: 2, + GroundCondition: 1, + RunningStyle: 1, + ResultRank: 1, + FrameOrder: 8, + NpcCount: 0, + }, + RaceRewardInfo: CharaRaceReward{ + ResultRank: 1, + ResultTime: 0, + RaceReward: []RaceReward{ + {ItemType: 11, ItemID: 80, ItemNum: 2}, + {ItemType: 91, ItemID: 59, ItemNum: 800}, + {ItemType: 11, ItemID: 7, ItemNum: 2}, + }, + RaceRewardBonus: []RaceReward{ + {ItemType: 91, ItemID: 59, ItemNum: 800}, + }, + RaceRewardPlusBonus: []RaceReward{}, + RaceRewardBonusWin: []RaceReward{}, + RaceRewardLimit: []RaceRewardLimit{}, + GainedFans: 29970, + CampaignIDs: []int32{223}, + }, + LoseTipsID: 0, + }, + { + RaceHistory: SingleRaceHistory{ + Turn: 68, + ProgramID: 76, + Weather: 1, + GroundCondition: 1, + RunningStyle: 1, + ResultRank: 1, + FrameOrder: 14, + NpcCount: 0, + }, + RaceRewardInfo: CharaRaceReward{ + ResultRank: 1, + ResultTime: 0, + RaceReward: []RaceReward{ + {ItemType: 11, ItemID: 84, ItemNum: 2}, + {ItemType: 91, ItemID: 59, ItemNum: 800}, + {ItemType: 11, ItemID: 7, ItemNum: 2}, + }, + RaceRewardBonus: []RaceReward{ + {ItemType: 91, ItemID: 59, ItemNum: 800}, + }, + RaceRewardPlusBonus: []RaceReward{}, + RaceRewardBonusWin: []RaceReward{}, + RaceRewardLimit: []RaceRewardLimit{}, + GainedFans: 29970, + CampaignIDs: []int32{223}, + }, + LoseTipsID: 0, + }, + { + RaceHistory: SingleRaceHistory{ + Turn: 72, + ProgramID: 81, + Weather: 2, + GroundCondition: 1, + RunningStyle: 1, + ResultRank: 1, + FrameOrder: 6, + NpcCount: 0, + }, + RaceRewardInfo: CharaRaceReward{ + ResultRank: 1, + ResultTime: 0, + RaceReward: []RaceReward{ + {ItemType: 11, ItemID: 91, ItemNum: 2}, + {ItemType: 91, ItemID: 59, ItemNum: 800}, + {ItemType: 11, ItemID: 10, ItemNum: 2}, + }, + RaceRewardBonus: []RaceReward{ + {ItemType: 91, ItemID: 59, ItemNum: 800}, + {ItemType: 30, ItemID: 110, ItemNum: 40}, + }, + RaceRewardPlusBonus: []RaceReward{}, + RaceRewardBonusWin: []RaceReward{}, + RaceRewardLimit: []RaceRewardLimit{}, + GainedFans: 59940, + CampaignIDs: []int32{223}, + }, + LoseTipsID: 0, + }, + { + RaceHistory: SingleRaceHistory{ + Turn: 74, + ProgramID: 2031, + Weather: 2, + GroundCondition: 2, + RunningStyle: 1, + ResultRank: 1, + FrameOrder: 10, + NpcCount: 0, + }, + RaceRewardInfo: CharaRaceReward{ + ResultRank: 1, + ResultTime: 0, + RaceReward: []RaceReward{ + {ItemType: 91, ItemID: 59, ItemNum: 1200}, + {ItemType: 11, ItemID: 10, ItemNum: 2}, + }, + RaceRewardBonus: []RaceReward{}, + RaceRewardPlusBonus: []RaceReward{}, + RaceRewardBonusWin: []RaceReward{}, + RaceRewardLimit: []RaceRewardLimit{}, + GainedFans: 13986, + CampaignIDs: []int32{223}, + }, + LoseTipsID: 0, + }, + { + RaceHistory: SingleRaceHistory{ + Turn: 76, + ProgramID: 2130, + Weather: 1, + GroundCondition: 1, + RunningStyle: 1, + ResultRank: 1, + FrameOrder: 1, + NpcCount: 0, + }, + RaceRewardInfo: CharaRaceReward{ + ResultRank: 1, + ResultTime: 0, + RaceReward: []RaceReward{ + {ItemType: 91, ItemID: 59, ItemNum: 1200}, + {ItemType: 11, ItemID: 10, ItemNum: 2}, + }, + RaceRewardBonus: []RaceReward{ + {ItemType: 30, ItemID: 110, ItemNum: 80}, + }, + RaceRewardPlusBonus: []RaceReward{}, + RaceRewardBonusWin: []RaceReward{}, + RaceRewardLimit: []RaceRewardLimit{}, + GainedFans: 19980, + CampaignIDs: []int32{223}, + }, + LoseTipsID: 0, + }, + { + RaceHistory: SingleRaceHistory{ + Turn: 78, + ProgramID: 2228, + Weather: 2, + GroundCondition: 2, + RunningStyle: 1, + ResultRank: 1, + FrameOrder: 4, + NpcCount: 0, + }, + RaceRewardInfo: CharaRaceReward{ + ResultRank: 1, + ResultTime: 0, + RaceReward: []RaceReward{ + {ItemType: 91, ItemID: 59, ItemNum: 1200}, + {ItemType: 11, ItemID: 10, ItemNum: 2}, + }, + RaceRewardBonus: []RaceReward{ + {ItemType: 91, ItemID: 59, ItemNum: 1200}, + {ItemType: 30, ItemID: 110, ItemNum: 80}, + }, + RaceRewardPlusBonus: []RaceReward{}, + RaceRewardBonusWin: []RaceReward{}, + RaceRewardLimit: []RaceRewardLimit{}, + GainedFans: 59940, + CampaignIDs: []int32{223}, + }, + LoseTipsID: 0, + }, + }, + GainSkillIDs: []horse.SkillID{}, + TotalSkillPoint: 3904, + }, + } + var got WorkIdleSingleMode + d := json.NewDecoder(strings.NewReader(testJSON)) + d.DisallowUnknownFields() + if err := d.Decode(&got); err != nil { + t.Error(err) + } + if diff := cmp.Diff(want, got); diff != "" { + t.Errorf("wrong data (+got/-want):\n%s", diff) + } +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..20dc0eb --- /dev/null +++ b/main.go @@ -0,0 +1,61 @@ +package main + +import ( + "bufio" + "encoding/csv" + "encoding/json" + "flag" + "log/slog" + "os" + "slices" +) + +func main() { + var outf string + flag.StringVar(&outf, "o", "idle_single_mode.csv", "output CSV `file`") + flag.Parse() + + out, err := os.Create(outf) + if err != nil { + slog.Error("create output", slog.Any("err", err)) + os.Exit(1) + } + b := bufio.NewWriter(out) + defer b.Flush() + w := csv.NewWriter(b) + defer w.Flush() + if err := w.Write(headers); err != nil { + slog.Error("write header", slog.Any("err", err)) + } + + files := flag.Args() + slices.Sort(files) + for _, in := range files { + dofile(w, in) + } +} + +func dofile(w *csv.Writer, name string) { + log := slog.With(slog.String("file", name)) + log.Info("process") + f, err := os.Open(name) + if err != nil { + log.Error("open", slog.Any("err", err)) + return + } + defer f.Close() + + var ism WorkIdleSingleMode + d := json.NewDecoder(f) + d.DisallowUnknownFields() + if err := d.Decode(&ism); err != nil { + log.Error("decode", slog.Any("err", err)) + return + } + + for row := range ismRows(name, ism.ProgressLog) { + if err := w.Write(row.csv()); err != nil { + log.Error("write row", slog.Any("err", err)) + } + } +} diff --git a/row.go b/row.go new file mode 100644 index 0000000..d79e536 --- /dev/null +++ b/row.go @@ -0,0 +1,161 @@ +package main + +import ( + "iter" + "log/slog" + "reflect" + "strconv" +) + +type Row struct { + File string + GainSource string + Speed int + Stamina int + Power int + Guts int + Wit int + SP int + NumSkills int + Deck1 int + Deck2 int + Deck3 int + Deck4 int + Deck5 int + Deck6 int + Races int + Wins int + NightOwl bool // chara effect id 1 + Slacker bool // 2 + SkinOutbreak bool // 3 + SlowMetabolism bool // 4 + Migraine bool // 5 + PracticePoor bool // 6 + FastLearner bool // 7 + Charming bool // 8 + HotTopic bool // 9 + PracticePerfect bool // 10 + VeryGoodAtTraining bool // 11 +} + +var headers []string + +func init() { + t := reflect.TypeFor[Row]() + for f := range t.Fields() { + headers = append(headers, f.Name) + } +} + +func ismRows(key string, ism IdleSingleModeProgressLog) iter.Seq[Row] { + return func(yield func(Row) bool) { + races := len(ism.RaceHistory) + var wins int + for _, r := range ism.RaceHistory { + if r.RaceHistory.ResultRank == 1 { + wins++ + } + } + var conditions [11]bool + for _, v := range ism.CharaEffectLog { + if v.CharaEffectID < 1 || v.CharaEffectID > 11 { + slog.Warn("skipping unknown charaEffectID", slog.Int("id", int(v.CharaEffectID)), slog.Bool("active", v.IsActive)) + continue + } + conditions[v.CharaEffectID-1] = true + } + row := Row{ + File: key, + Deck1: int(ism.SupportCardGains[0].SupportCardID), + Deck2: int(ism.SupportCardGains[1].SupportCardID), + Deck3: int(ism.SupportCardGains[2].SupportCardID), + Deck4: int(ism.SupportCardGains[3].SupportCardID), + Deck5: int(ism.SupportCardGains[4].SupportCardID), + Deck6: int(ism.SupportCardGains[5].SupportCardID), + Races: races, + Wins: wins, + NightOwl: conditions[0], + Slacker: conditions[1], + SkinOutbreak: conditions[2], + SlowMetabolism: conditions[3], + Migraine: conditions[4], + PracticePoor: conditions[5], + FastLearner: conditions[6], + Charming: conditions[7], + HotTopic: conditions[8], + PracticePerfect: conditions[9], + VeryGoodAtTraining: conditions[10], + } + + row.GainSource = "Events" + row.Speed = int(ism.EventGain.Speed.Value) + row.Stamina = int(ism.EventGain.Stamina.Value) + row.Power = int(ism.EventGain.Power.Value) + row.Guts = int(ism.EventGain.Guts.Value) + row.Wit = int(ism.EventGain.Wiz.Value) + row.SP = int(ism.EventGain.SkillPoint) + row.NumSkills = len(ism.EventGain.SkillTips) + if !yield(row) { + return + } + + row.GainSource = "Inspiration" + row.Speed = int(ism.SuccessionGain.Speed.Value) + row.Stamina = int(ism.SuccessionGain.Stamina.Value) + row.Power = int(ism.SuccessionGain.Power.Value) + row.Guts = int(ism.SuccessionGain.Guts.Value) + row.Wit = int(ism.SuccessionGain.Wiz.Value) + row.SP = int(ism.SuccessionGain.SkillPoint) + row.NumSkills = len(ism.SuccessionGain.SkillTips) + if !yield(row) { + return + } + + for _, sup := range ism.SupportCardGains { + row.GainSource = strconv.Itoa(int(sup.SupportCardID)) + row.Speed = int(sup.GainInfo.Speed.Value) + row.Stamina = int(sup.GainInfo.Stamina.Value) + row.Power = int(sup.GainInfo.Power.Value) + row.Guts = int(sup.GainInfo.Guts.Value) + row.Wit = int(sup.GainInfo.Wiz.Value) + row.SP = int(sup.GainInfo.SkillPoint) + row.NumSkills = len(sup.GainInfo.SkillTips) + if !yield(row) { + return + } + } + } +} + +func (r Row) csv() []string { + return []string{ + r.File, + r.GainSource, + strconv.Itoa(r.Speed), + strconv.Itoa(r.Stamina), + strconv.Itoa(r.Power), + strconv.Itoa(r.Guts), + strconv.Itoa(r.Wit), + strconv.Itoa(r.SP), + strconv.Itoa(r.NumSkills), + strconv.Itoa(r.Deck1), + strconv.Itoa(r.Deck2), + strconv.Itoa(r.Deck3), + strconv.Itoa(r.Deck4), + strconv.Itoa(r.Deck5), + strconv.Itoa(r.Deck6), + strconv.Itoa(r.Races), + strconv.Itoa(r.Wins), + strconv.FormatBool(r.NightOwl), + strconv.FormatBool(r.Slacker), + strconv.FormatBool(r.SkinOutbreak), + strconv.FormatBool(r.SlowMetabolism), + strconv.FormatBool(r.Migraine), + strconv.FormatBool(r.PracticePoor), + strconv.FormatBool(r.FastLearner), + strconv.FormatBool(r.Charming), + strconv.FormatBool(r.HotTopic), + strconv.FormatBool(r.PracticePerfect), + strconv.FormatBool(r.VeryGoodAtTraining), + } +} diff --git a/testdata.json b/testdata.json new file mode 100644 index 0000000..ed06b0d --- /dev/null +++ b/testdata.json @@ -0,0 +1,1526 @@ +{ + "charaInfo": { + "single_mode_chara_id": 1823, + "card_id": 102401, + "chara_grade": 1, + "speed": 107, + "stamina": 118, + "power": 103, + "wiz": 147, + "guts": 133, + "vital": 100, + "max_speed": 1616, + "max_stamina": 1300, + "max_power": 1318, + "max_wiz": 1332, + "max_guts": 1516, + "default_max_speed": 1200, + "default_max_stamina": 1200, + "default_max_power": 1200, + "default_max_wiz": 1200, + "default_max_guts": 1200, + "max_vital": 100, + "motivation": 3, + "fans": 1, + "rarity": 4, + "race_program_id": 0, + "reserve_race_program_id": 0, + "race_running_style": 1, + "is_short_race": 0, + "talent_level": 5, + "skill_array": [ + { + "skill_id": 100241, + "level": 2 + } + ], + "disable_skill_id_array": [], + "skill_tips_array": [ + { + "group_id": 90014, + "rarity": 1, + "level": 2 + }, + { + "group_id": 90020, + "rarity": 1, + "level": 1 + } + ], + "support_card_array": [ + { + "position": 1, + "support_card_id": 30010, + "limit_break_count": 4, + "exp": 118185, + "training_partner_state": 0, + "owner_viewer_id": 0, + "rental_type": 0 + }, + { + "position": 2, + "support_card_id": 30108, + "limit_break_count": 4, + "exp": 118185, + "training_partner_state": 0, + "owner_viewer_id": 0, + "rental_type": 0 + }, + { + "position": 3, + "support_card_id": 30062, + "limit_break_count": 4, + "exp": 118185, + "training_partner_state": 0, + "owner_viewer_id": 0, + "rental_type": 0 + }, + { + "position": 4, + "support_card_id": 30107, + "limit_break_count": 4, + "exp": 118185, + "training_partner_state": 0, + "owner_viewer_id": 0, + "rental_type": 0 + }, + { + "position": 5, + "support_card_id": 30028, + "limit_break_count": 4, + "exp": 118185, + "training_partner_state": 0, + "owner_viewer_id": 0, + "rental_type": 0 + }, + { + "position": 6, + "support_card_id": 30052, + "limit_break_count": 4, + "exp": 118185, + "training_partner_state": 0, + "owner_viewer_id": 818784439809, + "rental_type": 0 + } + ], + "succession_trained_chara_id_1": 4637, + "succession_trained_chara_id_2": 4670, + "proper_distance_short": 4, + "proper_distance_mile": 5, + "proper_distance_middle": 7, + "proper_distance_long": 7, + "proper_running_style_nige": 7, + "proper_running_style_senko": 7, + "proper_running_style_sashi": 6, + "proper_running_style_oikomi": 6, + "proper_ground_turf": 7, + "proper_ground_dirt": 7, + "turn": 1, + "skill_point": 0, + "short_cut_state": 0, + "state": 0, + "playing_state": 1, + "scenario_id": 3, + "route_id": 14, + "start_time": "2026-07-27 15:37:29", + "evaluation_info_array": [ + { + "target_id": 1, + "evaluation": 15, + "is_outing": 0, + "story_step": 0, + "is_appear": 1, + "group_outing_info_array": [] + }, + { + "target_id": 2, + "evaluation": 20, + "is_outing": 0, + "story_step": 0, + "is_appear": 1, + "group_outing_info_array": [] + }, + { + "target_id": 3, + "evaluation": 30, + "is_outing": 0, + "story_step": 0, + "is_appear": 1, + "group_outing_info_array": [] + }, + { + "target_id": 4, + "evaluation": 30, + "is_outing": 0, + "story_step": 0, + "is_appear": 1, + "group_outing_info_array": [] + }, + { + "target_id": 5, + "evaluation": 35, + "is_outing": 0, + "story_step": 0, + "is_appear": 1, + "group_outing_info_array": [] + }, + { + "target_id": 6, + "evaluation": 30, + "is_outing": 0, + "story_step": 0, + "is_appear": 0, + "group_outing_info_array": [] + }, + { + "target_id": 101, + "evaluation": 0, + "is_outing": 0, + "story_step": 0, + "is_appear": 0, + "group_outing_info_array": [] + }, + { + "target_id": 102, + "evaluation": 0, + "is_outing": 0, + "story_step": 0, + "is_appear": 0, + "group_outing_info_array": [] + }, + { + "target_id": 103, + "evaluation": 0, + "is_outing": 0, + "story_step": 0, + "is_appear": 0, + "group_outing_info_array": [] + }, + { + "target_id": 104, + "evaluation": 0, + "is_outing": 0, + "story_step": 0, + "is_appear": 0, + "group_outing_info_array": [] + }, + { + "target_id": 106, + "evaluation": 0, + "is_outing": 0, + "story_step": 0, + "is_appear": 0, + "group_outing_info_array": [] + } + ], + "training_level_info_array": [ + { + "command_id": 101, + "level": 1 + }, + { + "command_id": 102, + "level": 1 + }, + { + "command_id": 103, + "level": 1 + }, + { + "command_id": 105, + "level": 1 + }, + { + "command_id": 106, + "level": 1 + }, + { + "command_id": 601, + "level": 5 + }, + { + "command_id": 602, + "level": 5 + }, + { + "command_id": 603, + "level": 5 + }, + { + "command_id": 604, + "level": 5 + }, + { + "command_id": 605, + "level": 5 + } + ], + "nickname_id_array": [], + "chara_effect_id_array": [], + "route_race_id_array": [ + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156 + ], + "guest_outing_info_array": [], + "skill_upgrade_info_array": [] + }, + "startTime": 1785166649, + "endTime": 1785169649, + "progressLogInfo": { + "charaEffectLog": [ + { + "charaEffectId": 7, + "isActive": true + } + ], + "supportCardGainInfo": [ + { + "supportCardId": 30010, + "gainInfo": { + "speed": { + "sign": 0, + "value": 56 + }, + "stamina": { + "sign": 0, + "value": 33 + }, + "power": { + "sign": 0, + "value": 33 + }, + "wiz": { + "sign": 0, + "value": 193 + }, + "guts": { + "sign": 0, + "value": 33 + }, + "maxSpeed": 0, + "maxStamina": 0, + "maxPower": 0, + "maxWiz": 0, + "maxGuts": 0, + "properDistanceShort": 0, + "properDistanceMile": 0, + "properDistanceMiddle": 0, + "properDistanceLong": 0, + "properRunningStyleNige": 0, + "properRunningStyleSenko": 0, + "properRunningStyleSashi": 0, + "properRunningStyleOikomi": 0, + "properGroundTurf": 0, + "properGroundDirt": 0, + "skillPoint": 319, + "skillTips": [ + { + "group_id": 20019, + "rarity": 1, + "level": 1 + }, + { + "group_id": 20001, + "rarity": 1, + "level": 1 + } + ] + } + }, + { + "supportCardId": 30108, + "gainInfo": { + "speed": { + "sign": 0, + "value": 54 + }, + "stamina": { + "sign": 0, + "value": 35 + }, + "power": { + "sign": 0, + "value": 35 + }, + "wiz": { + "sign": 0, + "value": 135 + }, + "guts": { + "sign": 0, + "value": 35 + }, + "maxSpeed": 0, + "maxStamina": 0, + "maxPower": 0, + "maxWiz": 0, + "maxGuts": 0, + "properDistanceShort": 0, + "properDistanceMile": 0, + "properDistanceMiddle": 0, + "properDistanceLong": 0, + "properRunningStyleNige": 0, + "properRunningStyleSenko": 0, + "properRunningStyleSashi": 0, + "properRunningStyleOikomi": 0, + "properGroundTurf": 0, + "properGroundDirt": 0, + "skillPoint": 408, + "skillTips": [ + { + "group_id": 20157, + "rarity": 1, + "level": 4 + }, + { + "group_id": 20203, + "rarity": 1, + "level": 4 + }, + { + "group_id": 20156, + "rarity": 1, + "level": 4 + } + ] + } + }, + { + "supportCardId": 30062, + "gainInfo": { + "speed": { + "sign": 0, + "value": 31 + }, + "stamina": { + "sign": 0, + "value": 184 + }, + "power": { + "sign": 0, + "value": 31 + }, + "wiz": { + "sign": 0, + "value": 31 + }, + "guts": { + "sign": 0, + "value": 65 + }, + "maxSpeed": 0, + "maxStamina": 0, + "maxPower": 0, + "maxWiz": 0, + "maxGuts": 0, + "properDistanceShort": 0, + "properDistanceMile": 0, + "properDistanceMiddle": 0, + "properDistanceLong": 0, + "properRunningStyleNige": 0, + "properRunningStyleSenko": 0, + "properRunningStyleSashi": 0, + "properRunningStyleOikomi": 0, + "properGroundTurf": 0, + "properGroundDirt": 0, + "skillPoint": 234, + "skillTips": [ + { + "group_id": 20127, + "rarity": 1, + "level": 2 + } + ] + } + }, + { + "supportCardId": 30107, + "gainInfo": { + "speed": { + "sign": 0, + "value": 136 + }, + "stamina": { + "sign": 0, + "value": 35 + }, + "power": { + "sign": 0, + "value": 88 + }, + "wiz": { + "sign": 0, + "value": 35 + }, + "guts": { + "sign": 0, + "value": 35 + }, + "maxSpeed": 0, + "maxStamina": 0, + "maxPower": 0, + "maxWiz": 0, + "maxGuts": 0, + "properDistanceShort": 0, + "properDistanceMile": 0, + "properDistanceMiddle": 0, + "properDistanceLong": 0, + "properRunningStyleNige": 0, + "properRunningStyleSenko": 0, + "properRunningStyleSashi": 0, + "properRunningStyleOikomi": 0, + "properGroundTurf": 0, + "properGroundDirt": 0, + "skillPoint": 287, + "skillTips": [ + { + "group_id": 20043, + "rarity": 1, + "level": 3 + }, + { + "group_id": 20127, + "rarity": 1, + "level": 3 + }, + { + "group_id": 20124, + "rarity": 1, + "level": 3 + } + ] + } + }, + { + "supportCardId": 30028, + "gainInfo": { + "speed": { + "sign": 0, + "value": 116 + }, + "stamina": { + "sign": 0, + "value": 33 + }, + "power": { + "sign": 0, + "value": 86 + }, + "wiz": { + "sign": 0, + "value": 33 + }, + "guts": { + "sign": 0, + "value": 33 + }, + "maxSpeed": 0, + "maxStamina": 0, + "maxPower": 0, + "maxWiz": 0, + "maxGuts": 0, + "properDistanceShort": 0, + "properDistanceMile": 0, + "properDistanceMiddle": 0, + "properDistanceLong": 0, + "properRunningStyleNige": 0, + "properRunningStyleSenko": 0, + "properRunningStyleSashi": 0, + "properRunningStyleOikomi": 0, + "properGroundTurf": 0, + "properGroundDirt": 0, + "skillPoint": 284, + "skillTips": [ + { + "group_id": 20043, + "rarity": 1, + "level": 1 + }, + { + "group_id": 20076, + "rarity": 1, + "level": 3 + }, + { + "group_id": 20033, + "rarity": 1, + "level": 3 + }, + { + "group_id": 20118, + "rarity": 1, + "level": 3 + } + ] + } + }, + { + "supportCardId": 30052, + "gainInfo": { + "speed": { + "sign": 0, + "value": 68 + }, + "stamina": { + "sign": 0, + "value": 28 + }, + "power": { + "sign": 0, + "value": 28 + }, + "wiz": { + "sign": 0, + "value": 28 + }, + "guts": { + "sign": 0, + "value": 68 + }, + "maxSpeed": 0, + "maxStamina": 0, + "maxPower": 0, + "maxWiz": 0, + "maxGuts": 0, + "properDistanceShort": 0, + "properDistanceMile": 0, + "properDistanceMiddle": 0, + "properDistanceLong": 0, + "properRunningStyleNige": 0, + "properRunningStyleSenko": 0, + "properRunningStyleSashi": 0, + "properRunningStyleOikomi": 0, + "properGroundTurf": 0, + "properGroundDirt": 0, + "skillPoint": 553, + "skillTips": [] + } + } + ], + "eventGainInfo": { + "speed": { + "sign": 0, + "value": 817 + }, + "stamina": { + "sign": 0, + "value": 313 + }, + "power": { + "sign": 0, + "value": 427 + }, + "wiz": { + "sign": 0, + "value": 498 + }, + "guts": { + "sign": 0, + "value": 300 + }, + "maxSpeed": 0, + "maxStamina": 0, + "maxPower": 0, + "maxWiz": 0, + "maxGuts": 0, + "properDistanceShort": 0, + "properDistanceMile": 0, + "properDistanceMiddle": 0, + "properDistanceLong": 0, + "properRunningStyleNige": 0, + "properRunningStyleSenko": 0, + "properRunningStyleSashi": 0, + "properRunningStyleOikomi": 0, + "properGroundTurf": 0, + "properGroundDirt": 0, + "skillPoint": 1819, + "skillTips": [ + { + "group_id": 20166, + "rarity": 2, + "level": 3 + }, + { + "group_id": 20071, + "rarity": 2, + "level": 1 + }, + { + "group_id": 20027, + "rarity": 1, + "level": 2 + }, + { + "group_id": 20059, + "rarity": 1, + "level": 1 + }, + { + "group_id": 21007, + "rarity": 1, + "level": 1 + }, + { + "group_id": 21007, + "rarity": 2, + "level": 3 + }, + { + "group_id": 20021, + "rarity": 1, + "level": 1 + }, + { + "group_id": 20043, + "rarity": 1, + "level": 1 + }, + { + "group_id": 20043, + "rarity": 2, + "level": 1 + }, + { + "group_id": 20127, + "rarity": 2, + "level": 1 + }, + { + "group_id": 20135, + "rarity": 1, + "level": 1 + }, + { + "group_id": 20118, + "rarity": 1, + "level": 2 + }, + { + "group_id": 20207, + "rarity": 1, + "level": 1 + }, + { + "group_id": 20137, + "rarity": 1, + "level": 1 + }, + { + "group_id": 20209, + "rarity": 1, + "level": 1 + } + ] + }, + "successionGainInfo": { + "speed": { + "sign": 0, + "value": 67 + }, + "stamina": { + "sign": 0, + "value": 0 + }, + "power": { + "sign": 0, + "value": 94 + }, + "wiz": { + "sign": 0, + "value": 118 + }, + "guts": { + "sign": 0, + "value": 59 + }, + "maxSpeed": 22, + "maxStamina": 2, + "maxPower": 28, + "maxWiz": 45, + "maxGuts": 22, + "properDistanceShort": 0, + "properDistanceMile": 1, + "properDistanceMiddle": 0, + "properDistanceLong": 0, + "properRunningStyleNige": 0, + "properRunningStyleSenko": 0, + "properRunningStyleSashi": 0, + "properRunningStyleOikomi": 0, + "properGroundTurf": 0, + "properGroundDirt": 5, + "skillPoint": 0, + "skillTips": [ + { + "group_id": 90014, + "rarity": 1, + "level": 2 + }, + { + "group_id": 90020, + "rarity": 1, + "level": 2 + }, + { + "group_id": 90019, + "rarity": 1, + "level": 2 + }, + { + "group_id": 20166, + "rarity": 1, + "level": 3 + }, + { + "group_id": 20233, + "rarity": 1, + "level": 2 + }, + { + "group_id": 20160, + "rarity": 1, + "level": 4 + }, + { + "group_id": 21005, + "rarity": 1, + "level": 3 + }, + { + "group_id": 20019, + "rarity": 1, + "level": 3 + }, + { + "group_id": 21001, + "rarity": 1, + "level": 4 + }, + { + "group_id": 20035, + "rarity": 1, + "level": 1 + }, + { + "group_id": 20091, + "rarity": 1, + "level": 4 + }, + { + "group_id": 20126, + "rarity": 1, + "level": 2 + }, + { + "group_id": 20159, + "rarity": 1, + "level": 2 + }, + { + "group_id": 20125, + "rarity": 1, + "level": 1 + }, + { + "group_id": 20007, + "rarity": 1, + "level": 1 + } + ] + }, + "successionFactorGainArray": [ + { + "year": 1, + "gainFactorInfoArray": [ + { + "factorId": 103, + "level": 0 + }, + { + "factorId": 10200101, + "level": 0 + }, + { + "factorId": 503, + "level": 0 + }, + { + "factorId": 1202, + "level": 0 + }, + { + "factorId": 10140102, + "level": 0 + }, + { + "factorId": 503, + "level": 0 + }, + { + "factorId": 1202, + "level": 0 + }, + { + "factorId": 403, + "level": 0 + }, + { + "factorId": 3202, + "level": 0 + }, + { + "factorId": 302, + "level": 0 + }, + { + "factorId": 1203, + "level": 0 + }, + { + "factorId": 302, + "level": 0 + }, + { + "factorId": 1203, + "level": 0 + } + ] + }, + { + "year": 2, + "gainFactorInfoArray": [ + { + "factorId": 103, + "level": 0 + }, + { + "factorId": 1000802, + "level": 0 + }, + { + "factorId": 2016603, + "level": 0 + }, + { + "factorId": 2023302, + "level": 0 + }, + { + "factorId": 503, + "level": 0 + }, + { + "factorId": 2102103, + "level": 0 + }, + { + "factorId": 503, + "level": 0 + }, + { + "factorId": 2016002, + "level": 0 + }, + { + "factorId": 2100502, + "level": 0 + }, + { + "factorId": 403, + "level": 0 + }, + { + "factorId": 2001902, + "level": 0 + }, + { + "factorId": 302, + "level": 0 + }, + { + "factorId": 302, + "level": 0 + }, + { + "factorId": 1203, + "level": 0 + }, + { + "factorId": 10190102, + "level": 0 + } + ] + }, + { + "year": 3, + "gainFactorInfoArray": [ + { + "factorId": 103, + "level": 0 + }, + { + "factorId": 2003501, + "level": 0 + }, + { + "factorId": 2009102, + "level": 0 + }, + { + "factorId": 10200101, + "level": 0 + }, + { + "factorId": 503, + "level": 0 + }, + { + "factorId": 1002002, + "level": 0 + }, + { + "factorId": 2012502, + "level": 0 + }, + { + "factorId": 503, + "level": 0 + }, + { + "factorId": 2012602, + "level": 0 + }, + { + "factorId": 2015902, + "level": 0 + }, + { + "factorId": 403, + "level": 0 + }, + { + "factorId": 302, + "level": 0 + }, + { + "factorId": 302, + "level": 0 + } + ] + } + ], + "raceHistoryArray": [ + { + "race_history": { + "turn": 12, + "program_id": 1067, + "weather": 2, + "ground_condition": 2, + "running_style": 1, + "result_rank": 1, + "frame_order": 2, + "npc_count": 0 + }, + "race_reward_info": { + "result_rank": 1, + "result_time": 0, + "race_reward": [ + { + "item_type": 91, + "item_id": 59, + "item_num": 400 + } + ], + "race_reward_bonus": [], + "race_reward_plus_bonus": [], + "race_reward_bonus_win": [], + "race_reward_limit": [], + "gained_fans": 1398, + "campaign_id_array": [ + 223 + ] + }, + "lose_tips_id": 0 + }, + { + "race_history": { + "turn": 44, + "program_id": 168, + "weather": 1, + "ground_condition": 1, + "running_style": 1, + "result_rank": 1, + "frame_order": 11, + "npc_count": 0 + }, + "race_reward_info": { + "result_rank": 1, + "result_time": 0, + "race_reward": [ + { + "item_type": 11, + "item_id": 83, + "item_num": 2 + }, + { + "item_type": 91, + "item_id": 59, + "item_num": 800 + }, + { + "item_type": 11, + "item_id": 10, + "item_num": 2 + } + ], + "race_reward_bonus": [ + { + "item_type": 30, + "item_id": 110, + "item_num": 40 + } + ], + "race_reward_plus_bonus": [], + "race_reward_bonus_win": [], + "race_reward_limit": [], + "gained_fans": 23976, + "campaign_id_array": [ + 223 + ] + }, + "lose_tips_id": 0 + }, + { + "race_history": { + "turn": 48, + "program_id": 81, + "weather": 1, + "ground_condition": 1, + "running_style": 1, + "result_rank": 1, + "frame_order": 4, + "npc_count": 0 + }, + "race_reward_info": { + "result_rank": 1, + "result_time": 0, + "race_reward": [ + { + "item_type": 11, + "item_id": 91, + "item_num": 2 + }, + { + "item_type": 91, + "item_id": 59, + "item_num": 800 + }, + { + "item_type": 11, + "item_id": 10, + "item_num": 2 + } + ], + "race_reward_bonus": [ + { + "item_type": 91, + "item_id": 59, + "item_num": 800 + }, + { + "item_type": 30, + "item_id": 110, + "item_num": 40 + } + ], + "race_reward_plus_bonus": [], + "race_reward_bonus_win": [], + "race_reward_limit": [], + "gained_fans": 59940, + "campaign_id_array": [ + 223 + ] + }, + "lose_tips_id": 0 + }, + { + "race_history": { + "turn": 54, + "program_id": 12, + "weather": 2, + "ground_condition": 1, + "running_style": 1, + "result_rank": 1, + "frame_order": 7, + "npc_count": 0 + }, + "race_reward_info": { + "result_rank": 1, + "result_time": 0, + "race_reward": [ + { + "item_type": 91, + "item_id": 59, + "item_num": 800 + }, + { + "item_type": 11, + "item_id": 10, + "item_num": 2 + } + ], + "race_reward_bonus": [], + "race_reward_plus_bonus": [], + "race_reward_bonus_win": [], + "race_reward_limit": [], + "gained_fans": 13387, + "campaign_id_array": [ + 223 + ] + }, + "lose_tips_id": 0 + }, + { + "race_history": { + "turn": 56, + "program_id": 4, + "weather": 1, + "ground_condition": 1, + "running_style": 1, + "result_rank": 1, + "frame_order": 6, + "npc_count": 0 + }, + "race_reward_info": { + "result_rank": 1, + "result_time": 0, + "race_reward": [ + { + "item_type": 11, + "item_id": 74, + "item_num": 2 + }, + { + "item_type": 91, + "item_id": 59, + "item_num": 800 + }, + { + "item_type": 11, + "item_id": 10, + "item_num": 2 + } + ], + "race_reward_bonus": [ + { + "item_type": 91, + "item_id": 59, + "item_num": 800 + }, + { + "item_type": 30, + "item_id": 110, + "item_num": 40 + } + ], + "race_reward_plus_bonus": [], + "race_reward_bonus_win": [], + "race_reward_limit": [], + "gained_fans": 29970, + "campaign_id_array": [ + 223 + ] + }, + "lose_tips_id": 0 + }, + { + "race_history": { + "turn": 60, + "program_id": 74, + "weather": 2, + "ground_condition": 1, + "running_style": 1, + "result_rank": 1, + "frame_order": 8, + "npc_count": 0 + }, + "race_reward_info": { + "result_rank": 1, + "result_time": 0, + "race_reward": [ + { + "item_type": 11, + "item_id": 80, + "item_num": 2 + }, + { + "item_type": 91, + "item_id": 59, + "item_num": 800 + }, + { + "item_type": 11, + "item_id": 7, + "item_num": 2 + } + ], + "race_reward_bonus": [ + { + "item_type": 91, + "item_id": 59, + "item_num": 800 + } + ], + "race_reward_plus_bonus": [], + "race_reward_bonus_win": [], + "race_reward_limit": [], + "gained_fans": 29970, + "campaign_id_array": [ + 223 + ] + }, + "lose_tips_id": 0 + }, + { + "race_history": { + "turn": 68, + "program_id": 76, + "weather": 1, + "ground_condition": 1, + "running_style": 1, + "result_rank": 1, + "frame_order": 14, + "npc_count": 0 + }, + "race_reward_info": { + "result_rank": 1, + "result_time": 0, + "race_reward": [ + { + "item_type": 11, + "item_id": 84, + "item_num": 2 + }, + { + "item_type": 91, + "item_id": 59, + "item_num": 800 + }, + { + "item_type": 11, + "item_id": 7, + "item_num": 2 + } + ], + "race_reward_bonus": [ + { + "item_type": 91, + "item_id": 59, + "item_num": 800 + } + ], + "race_reward_plus_bonus": [], + "race_reward_bonus_win": [], + "race_reward_limit": [], + "gained_fans": 29970, + "campaign_id_array": [ + 223 + ] + }, + "lose_tips_id": 0 + }, + { + "race_history": { + "turn": 72, + "program_id": 81, + "weather": 2, + "ground_condition": 1, + "running_style": 1, + "result_rank": 1, + "frame_order": 6, + "npc_count": 0 + }, + "race_reward_info": { + "result_rank": 1, + "result_time": 0, + "race_reward": [ + { + "item_type": 11, + "item_id": 91, + "item_num": 2 + }, + { + "item_type": 91, + "item_id": 59, + "item_num": 800 + }, + { + "item_type": 11, + "item_id": 10, + "item_num": 2 + } + ], + "race_reward_bonus": [ + { + "item_type": 91, + "item_id": 59, + "item_num": 800 + }, + { + "item_type": 30, + "item_id": 110, + "item_num": 40 + } + ], + "race_reward_plus_bonus": [], + "race_reward_bonus_win": [], + "race_reward_limit": [], + "gained_fans": 59940, + "campaign_id_array": [ + 223 + ] + }, + "lose_tips_id": 0 + }, + { + "race_history": { + "turn": 74, + "program_id": 2031, + "weather": 2, + "ground_condition": 2, + "running_style": 1, + "result_rank": 1, + "frame_order": 10, + "npc_count": 0 + }, + "race_reward_info": { + "result_rank": 1, + "result_time": 0, + "race_reward": [ + { + "item_type": 91, + "item_id": 59, + "item_num": 1200 + }, + { + "item_type": 11, + "item_id": 10, + "item_num": 2 + } + ], + "race_reward_bonus": [], + "race_reward_plus_bonus": [], + "race_reward_bonus_win": [], + "race_reward_limit": [], + "gained_fans": 13986, + "campaign_id_array": [ + 223 + ] + }, + "lose_tips_id": 0 + }, + { + "race_history": { + "turn": 76, + "program_id": 2130, + "weather": 1, + "ground_condition": 1, + "running_style": 1, + "result_rank": 1, + "frame_order": 1, + "npc_count": 0 + }, + "race_reward_info": { + "result_rank": 1, + "result_time": 0, + "race_reward": [ + { + "item_type": 91, + "item_id": 59, + "item_num": 1200 + }, + { + "item_type": 11, + "item_id": 10, + "item_num": 2 + } + ], + "race_reward_bonus": [ + { + "item_type": 30, + "item_id": 110, + "item_num": 80 + } + ], + "race_reward_plus_bonus": [], + "race_reward_bonus_win": [], + "race_reward_limit": [], + "gained_fans": 19980, + "campaign_id_array": [ + 223 + ] + }, + "lose_tips_id": 0 + }, + { + "race_history": { + "turn": 78, + "program_id": 2228, + "weather": 2, + "ground_condition": 2, + "running_style": 1, + "result_rank": 1, + "frame_order": 4, + "npc_count": 0 + }, + "race_reward_info": { + "result_rank": 1, + "result_time": 0, + "race_reward": [ + { + "item_type": 91, + "item_id": 59, + "item_num": 1200 + }, + { + "item_type": 11, + "item_id": 10, + "item_num": 2 + } + ], + "race_reward_bonus": [ + { + "item_type": 91, + "item_id": 59, + "item_num": 1200 + }, + { + "item_type": 30, + "item_id": 110, + "item_num": 80 + } + ], + "race_reward_plus_bonus": [], + "race_reward_bonus_win": [], + "race_reward_limit": [], + "gained_fans": 59940, + "campaign_id_array": [ + 223 + ] + }, + "lose_tips_id": 0 + } + ], + "gainSkillIdArray": [], + "totalSkillPoint": 3904 + } +} \ No newline at end of file