package replay import ( "fmt" "strings" "sync" "git.sunturtle.xyz/zephyr/horse" ) type Race struct { RaceType RaceType `json:"raceType"` IsExistPlayerRace bool `json:"isExistPlayerRace"` IsExistGhostRace bool `json:"isExistGhostRace"` IsExistFollowRace bool `json:"isExistFollowRace"` IsMultiplePlayerRace bool `json:"isMultiplePlayerRace"` RandomSeed int32 `json:"randomSeed"` SingleRaceProgramID int32 `json:"singleRaceProgramId"` OpponentEvaluate int32 `json:"opponentEvaluate"` SelfEvaluate int32 `json:"selfEvaluate"` SupportCardScoreBonus int32 `json:"supportCardScoreBonus"` ScoreCalcTeamID int32 `json:"scoreCalcTeamId"` RaceNo int32 `json:"raceNo"` RaceCourseSet RaceCourseSet `json:"raceCourseSet"` FenceSet struct{} `json:"fenceSet"` RaceTrack struct{} `json:"raceTrack"` GoalGate int32 `json:"goalGate"` GoalGateFlower int32 `json:"goalGateFlower"` InitialLaneType InitialLaneType `json:"initialLaneType"` RotationCategory Rotation `json:"rotationCategory"` ResultBoardConditionType ResultBoardConditionType `json:"resultBoardConditionType"` CourseSectionDistance float32 `json:"courseSectionDistance"` CourseDistanceType CourseDistanceType `json:"courseDistanceType"` CourseFurlongNum int32 `json:"courseFurlongNum"` IsHalfGate bool `json:"isHalfGate"` IsHorseNumVariationGate bool `json:"isHorseNumVariationGate"` TurfVisionType TurfVisionType `json:"turfVisionType"` GroundCondition GroundCondition `json:"groundCondition"` Weather RaceWeather `json:"weather"` Season Season `json:"season"` Time RaceTime `json:"time"` BaseSpeed float32 `json:"baseSpeed"` BorderTimeScaled float32 `json:"borderTimeScaled"` ChallengeMatchDifficulty RaceDifficulty `json:"challengeMatchDifficulty"` NumRaceHorses int32 `json:"numRaceHorses"` PostNumberMax int32 `json:"postNumberMax"` PlayerHorseIndex int32 `json:"playerHorseIndex"` OverridePlayerHorseIndex int32 `json:"overridePlayerHorseIndex"` PlayerTeamMemberArray []RaceHorse `json:"playerTeamMemberArray"` PlayerTeamTopFinishOrderHorse RaceHorse `json:"playerTeamTopFinishOrderHorse"` IsGateInPopularityInitialized bool `json:"isGateInPopularityInitialized"` RaceHorse []RaceHorse `json:"raceHorse"` RaceBibMaster struct{} `json:"raceBibMaster"` RaceMaster struct{} `json:"raceMaster"` RaceInstanceMaster struct{} `json:"raceInstanceMaster"` SimDataBase64 string `json:"simDataBase64"` SimData struct{} `json:"simData"` SimReader struct{} `json:"simReader"` EpisodeRaceReplayID int32 `json:"episodeRaceReplayId"` IsNotSimulateExport bool `json:"isNotSimulateExport"` LaneDistanceMax float32 `json:"laneDistanceMax"` ReplayCheckInfo struct{} `json:"replayCheckInfo"` ReplayCheckInfoDaily struct{} `json:"replayCheckInfoDaily"` ReplayCheckInfoLegend struct{} `json:"replayCheckInfoLegend"` IsDailyLegendRace bool `json:"isDailyLegendRace"` ReplayCheckInfoChallengeMatch struct{} `json:"replayCheckInfoChallengeMatch"` RaceRewardSingle RaceRewardSingle `json:"raceRewardSingle"` ResultHorseIndex int32 `json:"resultHorseIndex"` PrevGradeType CharaGradeType `json:"prevGradeType"` MainStoryRaceGimmickType MainStoryRaceGimmickType `json:"mainStoryRaceGimmickType"` IsMainStoryRaceMatchGimmick bool `json:"isMainStoryRaceMatchGimmick"` UnlockFlags uint32 `json:"unlockFlags"` PhaseCalculator struct{} `json:"phaseCalculator"` HorseIndexByFinishOrder []int32 `json:"horseIndexByFinishOrder"` HorseIndexByPopularity []int32 `json:"horseIndexByPopularity"` } type RaceType int32 //go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type RaceType -linecomment -trimprefix RaceType const ( RaceTypeNone RaceType = iota // NONE RaceTypePvP RaceTypeTutorial RaceTypeStory RaceTypeStoryCondition RaceTypeChampions RaceTypeSingle RaceTypeSingleModeScenarioTeamRace RaceTypeRoomMatch RaceTypePractice RaceTypeDaily RaceTypeTeamBuilding RaceTypeLegend RaceTypeChallengeMatch RaceTypeTeamStadium // no value 15 RaceTypeHeroes RaceType = 16 raceTypeMaxInclusive ) func (r RaceType) AppendText(b []byte) ([]byte, error) { return append(b, r.String()...), nil } func (r RaceType) MarshalText() ([]byte, error) { return r.AppendText(nil) } var raceTypeNames = sync.OnceValue(func() map[string]RaceType { m := make(map[string]RaceType, raceTypeMaxInclusive) for r := RaceTypeNone; r <= raceTypeMaxInclusive; r++ { s := r.String() if strings.HasPrefix(s, "RaceType(") { continue } m[r.String()] = r } return m }) func (r *RaceType) UnmarshalText(b []byte) error { n, ok := raceTypeNames()[string(b)] *r = n if !ok { return fmt.Errorf("unknown race type %q", b) } return nil } type RaceCourseSet struct { ID horse.RacecourseID `json:"id"` RaceTrackID horse.RaceTrackID `json:"raceTrackId"` Distance int32 `json:"distance"` Ground int `json:"ground"` Inout int `json:"inout"` Turn int `json:"turn"` FenceSet int `json:"fenceSet"` FloatLaneMax int `json:"floatLaneMax"` CourseSetStatusID int `json:"courseSetStatusId"` FinishTimeMin int `json:"finishTimeMin"` FinishTimeMinRandomRange int `json:"finishTimeMinRandomRange"` FinishTimeMax int `json:"finishTimeMax"` FinishTimeMaxRandomRange int `json:"finishTimeMaxRandomRange"` } type InitialLaneType int8 //go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type InitialLaneType -trimprefix InitialLane const ( InitialLaneExtraSpaceAfter9 InitialLaneType = iota + 1 InitialLaneEquidistant InitialLaneExtraSpaceAfter14 InitialLaneExtraSpaceAfter8 initialLaneMax ) func (r InitialLaneType) AppendText(b []byte) ([]byte, error) { return append(b, r.String()...), nil } func (r InitialLaneType) MarshalText() ([]byte, error) { return r.AppendText(nil) } var initialLaneNames = sync.OnceValue(func() map[string]InitialLaneType { m := make(map[string]InitialLaneType, initialLaneMax) for r := InitialLaneExtraSpaceAfter9; r < initialLaneMax; r++ { s := r.String() if strings.HasPrefix(s, "InitialLaneType(") { continue } m[r.String()] = r } return m }) func (r *InitialLaneType) UnmarshalText(b []byte) error { n, ok := initialLaneNames()[string(b)] *r = n if !ok { return fmt.Errorf("unknown initial lane type type %q", b) } return nil } type Rotation int8 //go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type Rotation -trimprefix Rotation const ( RotationRight Rotation = iota + 1 RotationLeft RotationStraightRight RotationStraightLeft ) func (r Rotation) AppendText(b []byte) ([]byte, error) { return append(b, r.String()...), nil } func (r Rotation) MarshalText() ([]byte, error) { return r.AppendText(nil) } func (r *Rotation) UnmarshalText(b []byte) error { switch string(b) { case "Right": *r = RotationRight case "Left": *r = RotationLeft case "StraightRight": *r = RotationStraightRight case "StraightLeft": *r = RotationStraightLeft default: *r = 0 return fmt.Errorf("unknown rotation type %q", b) } return nil } type ResultBoardConditionType int8 //go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type ResultBoardConditionType -linecomment const ( ResultBoardTurfNone ResultBoardConditionType = iota + 1 // Turf_None ResultBoardTurfDirt // Turf_Dirt ResultBoardDirtNone // Dirt_None ResultBoardDirtTurf // Dirt_Turf ) func (r ResultBoardConditionType) AppendText(b []byte) ([]byte, error) { return append(b, r.String()...), nil } func (r ResultBoardConditionType) MarshalText() ([]byte, error) { return r.AppendText(nil) } func (r *ResultBoardConditionType) UnmarshalText(b []byte) error { switch string(b) { case "Turf_None": *r = ResultBoardTurfNone case "Turf_Dirt": *r = ResultBoardTurfDirt case "Dirt_None": *r = ResultBoardDirtNone case "Dirt_Turf": *r = ResultBoardDirtTurf default: *r = 0 return fmt.Errorf("unknown result board type %q", b) } return nil } type CourseDistanceType int8 //go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type CourseDistanceType -linecomment -trimprefix Distance const ( DistanceSprint CourseDistanceType = iota + 1 // Short DistanceMile DistanceMedium // Middle DistanceLong ) func (r CourseDistanceType) AppendText(b []byte) ([]byte, error) { return append(b, r.String()...), nil } func (r CourseDistanceType) MarshalText() ([]byte, error) { return r.AppendText(nil) } func (r *CourseDistanceType) UnmarshalText(b []byte) error { switch string(b) { case "Short": *r = DistanceSprint case "Mile": *r = DistanceMile case "Middle": *r = DistanceMedium case "Long": *r = DistanceLong default: *r = 0 return fmt.Errorf("unknown distance type %q", b) } return nil } type TurfVisionType int8 //go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type TurfVisionType -trimprefix TurfVision const ( TurfVisionURA TurfVisionType = iota + 1 TurfVisionNAU TurfVisionStand turfVisionMax ) func (r TurfVisionType) AppendText(b []byte) ([]byte, error) { return append(b, r.String()...), nil } func (r TurfVisionType) MarshalText() ([]byte, error) { return r.AppendText(nil) } var turfVisionNames = sync.OnceValue(func() map[string]TurfVisionType { m := make(map[string]TurfVisionType, turfVisionMax) for r := TurfVisionURA; r < turfVisionMax; r++ { s := r.String() if strings.HasPrefix(s, "TurfVisionType(") { continue } m[r.String()] = r } return m }) func (r *TurfVisionType) UnmarshalText(b []byte) error { n, ok := turfVisionNames()[string(b)] *r = n if !ok { return fmt.Errorf("unknown turf vision type %q", b) } return nil } type GroundCondition int8 //go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type GroundCondition -linecomment const ( GroundFirm GroundCondition = iota + 1 // Good GroundGood // Soft GroundSoft // Hard GroundHeavy // Bad ) func (r GroundCondition) AppendText(b []byte) ([]byte, error) { return append(b, r.String()...), nil } func (r GroundCondition) MarshalText() ([]byte, error) { return r.AppendText(nil) } func (r *GroundCondition) UnmarshalText(b []byte) error { switch string(b) { case "Good": *r = GroundFirm case "Soft": *r = GroundGood case "Hard": *r = GroundSoft case "Bad": *r = GroundHeavy default: *r = 0 return fmt.Errorf("unknown ground condition type %q", b) } return nil } type RaceWeather int8 //go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type RaceWeather -trimprefix Weather const ( WeatherMin RaceWeather = iota WeatherSunny WeatherCloudy WeatherRainy WeatherSnow WeatherMax ) func (r RaceWeather) AppendText(b []byte) ([]byte, error) { return append(b, r.String()...), nil } func (r RaceWeather) MarshalText() ([]byte, error) { return r.AppendText(nil) } func (r *RaceWeather) UnmarshalText(b []byte) error { switch string(b) { case "Min", "NONE": *r = WeatherMin case "Sunny": *r = WeatherSunny case "Cloudy": *r = WeatherCloudy case "Rainy": *r = WeatherRainy case "Snow": *r = WeatherSnow case "Max": *r = WeatherMax default: *r = 0 return fmt.Errorf("unknown race weather %q", b) } return nil } type Season int8 //go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type Season -trimprefix Season const ( SeasonMin Season = iota SeasonSpring SeasonSummer SeasonFall SeasonWinter SeasonCherryBlossom SeasonMax ) func (r Season) AppendText(b []byte) ([]byte, error) { return append(b, r.String()...), nil } func (r Season) MarshalText() ([]byte, error) { return r.AppendText(nil) } func (r *Season) UnmarshalText(b []byte) error { switch string(b) { case "Min", "NONE": *r = SeasonMin case "Spring": *r = SeasonSpring case "Summer": *r = SeasonSummer case "Fall": *r = SeasonFall case "Winter": *r = SeasonWinter case "CherryBlossom": *r = SeasonCherryBlossom case "Max": *r = SeasonMax default: *r = 0 return fmt.Errorf("unknown season %q", b) } return nil } type RaceTime int8 //go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type RaceTime -trimprefix Time const ( TimeMin RaceTime = iota TimeMorning TimeDaytime TimeEvening TimeNight TimeMax ) func (r RaceTime) AppendText(b []byte) ([]byte, error) { return append(b, r.String()...), nil } func (r RaceTime) MarshalText() ([]byte, error) { return r.AppendText(nil) } func (r *RaceTime) UnmarshalText(b []byte) error { switch string(b) { case "Min": *r = TimeMin case "Morning": *r = TimeMorning case "Daytime": *r = TimeDaytime case "Evening": *r = TimeEvening case "Night": *r = TimeNight case "Max": *r = TimeMax default: *r = 0 return fmt.Errorf("unknown race time %q", b) } return nil } type RaceDifficulty int8 //go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type RaceDifficulty -trimprefix Difficulty const ( DifficultyEasy RaceDifficulty = iota + 1 DifficultyNormal DifficultyHard DifficultyVeryHard DifficultyExtreme difficultyMax ) func (r RaceDifficulty) AppendText(b []byte) ([]byte, error) { return append(b, r.String()...), nil } func (r RaceDifficulty) MarshalText() ([]byte, error) { return r.AppendText(nil) } var difficultyNames = sync.OnceValue(func() map[string]RaceDifficulty { m := make(map[string]RaceDifficulty, difficultyMax) for r := DifficultyEasy; r < difficultyMax; r++ { s := r.String() if strings.HasPrefix(s, "RaceDifficulty(") { continue } m[r.String()] = r } // extra one for pure pvp races m["UNKNOWN"] = 0 return m }) func (r *RaceDifficulty) UnmarshalText(b []byte) error { n, ok := difficultyNames()[string(b)] *r = n if !ok { return fmt.Errorf("unknown turf vision type %q", b) } return nil } type RaceParam struct { RawSpeed int `json:"rawSpeed"` RawStamina int `json:"rawStamina"` RawPow int `json:"rawPow"` RawGuts int `json:"rawGuts"` RawWiz int `json:"rawWiz"` BaseSpeed float32 `json:"baseSpeed"` BaseStamina float32 `json:"baseStamina"` BasePow float32 `json:"basePow"` BaseGuts float32 `json:"baseGuts"` BaseWiz float32 `json:"baseWiz"` Motivation string `json:"motivation"` MotivationCoef float32 `json:"motivationCoef"` } type SkillArray struct { SkillID int `json:"skill_id"` Level int `json:"level"` } type RaceResultArray struct { Turn int `json:"turn"` ProgramID int `json:"program_id"` Weather int `json:"weather"` GroundCondition int `json:"ground_condition"` RunningStyle int `json:"running_style"` Popularity int `json:"popularity"` ResultRank int `json:"result_rank"` ResultTime int `json:"result_time"` PrizeMoney int `json:"prize_money"` } type ResponseHorseData struct { FrameOrder int `json:"frame_order"` ViewerID int64 `json:"viewer_id"` TrainerName string `json:"trainer_name"` OwnerViewerID int `json:"owner_viewer_id"` OwnerTrainerName string `json:"owner_trainer_name"` SingleModeCharaID int `json:"single_mode_chara_id"` TrainedCharaID int `json:"trained_chara_id"` NicknameID int `json:"nickname_id"` CharaID int `json:"chara_id"` CardID int `json:"card_id"` MobID int `json:"mob_id"` Rarity int `json:"rarity"` TalentLevel int `json:"talent_level"` SkillArray []SkillArray `json:"skill_array"` Stamina int `json:"stamina"` Speed int `json:"speed"` Pow int `json:"pow"` Guts int `json:"guts"` Wiz int `json:"wiz"` RunningStyle int `json:"running_style"` RaceDressID int `json:"race_dress_id"` CharaColorType int `json:"chara_color_type"` NpcType int `json:"npc_type"` FinalGrade int `json:"final_grade"` Popularity int `json:"popularity"` PopularityMarkRankArray []int `json:"popularity_mark_rank_array"` ProperDistanceShort int `json:"proper_distance_short"` ProperDistanceMile int `json:"proper_distance_mile"` ProperDistanceMiddle int `json:"proper_distance_middle"` ProperDistanceLong int `json:"proper_distance_long"` ProperRunningStyleNige int `json:"proper_running_style_nige"` ProperRunningStyleSenko int `json:"proper_running_style_senko"` ProperRunningStyleSashi int `json:"proper_running_style_sashi"` ProperRunningStyleOikomi int `json:"proper_running_style_oikomi"` ProperGroundTurf int `json:"proper_ground_turf"` ProperGroundDirt int `json:"proper_ground_dirt"` Motivation int `json:"motivation"` WinSaddleIDArray []int `json:"win_saddle_id_array"` RaceResultArray []RaceResultArray `json:"race_result_array"` TeamID int `json:"team_id"` TeamMemberID int `json:"team_member_id"` TeamRank int `json:"team_rank"` SingleModeWinCount int `json:"single_mode_win_count"` ItemIDArray []any `json:"item_id_array"` MotivationChangeFlag int `json:"motivation_change_flag"` FrameOrderChangeFlag int `json:"frame_order_change_flag"` } type RaceRecord struct { } type FactorDataArray struct { FactorLv int `json:"factorLv"` FactorID int `json:"factorId"` BaseFactorID int `json:"baseFactorId"` UpgradeHistoryList []any `json:"upgradeHistoryList"` } type FavoriteData struct { } type SuccessionCharaList struct { PositionID int `json:"positionId"` CardID int `json:"cardId"` Rarity int `json:"rarity"` Level int `json:"level"` Rank int `json:"rank"` FactorDataArray []FactorDataArray `json:"factorDataArray"` SortedFactorList []any `json:"sortedFactorList"` SortedFactorListForProfileCard []any `json:"sortedFactorListForProfileCard"` OwnerViewerID int `json:"ownerViewerId"` IsPlayer bool `json:"isPlayer"` WinSaddleArray []any `json:"winSaddleArray"` WinSaddleIDArray []int `json:"winSaddleIdArray"` } type Master struct { } type AcquiredSkillArray struct { MasterID int `json:"masterId"` Level int `json:"level"` Master Master `json:"master"` } type SupportCardArray struct { Position int `json:"position"` SupportCardID int `json:"supportCardId"` LimitBreakCount int `json:"limitBreakCount"` Exp int `json:"exp"` } type SingleModeRaceResultArray struct { Turn int `json:"turn"` ProgramID int `json:"programId"` RaceInstanceID int `json:"raceInstanceId"` FrameOrder int `json:"frameOrder"` NpcCount int `json:"npcCount"` Weather int `json:"weather"` GroundCondition int `json:"groundCondition"` RunningStyle int `json:"runningStyle"` ResultRank int `json:"resultRank"` ScenarioID int `json:"scenarioId"` } type MasterCardData struct { } type MasterCharaData struct { } type MasterCardRarityData struct { } type TrainedCharaDataAccessor struct { } type TrainedCharaData struct { ID int `json:"id"` IsSaved bool `json:"isSaved"` ViewerID int64 `json:"viewerId"` OwnerViewerID int `json:"ownerViewerId"` OwnerTrainedCharaID int `json:"ownerTrainedCharaId"` UseType int `json:"useType"` CardID int `json:"cardId"` NickNameID int `json:"nickNameId"` NickNameIDArray []int `json:"nickNameIdArray"` Stamina int `json:"stamina"` Speed int `json:"speed"` Power int `json:"power"` Guts int `json:"guts"` Wiz int `json:"wiz"` Fans int `json:"fans"` Rank int `json:"rank"` RankScore int `json:"rankScore"` RunningStyle int `json:"runningStyle"` ProperGroundTurf int `json:"properGroundTurf"` ProperGroundDirt int `json:"properGroundDirt"` ProperDistanceShort int `json:"properDistanceShort"` ProperDistanceMile int `json:"properDistanceMile"` ProperDistanceMiddle int `json:"properDistanceMiddle"` ProperDistanceLong int `json:"properDistanceLong"` ProperRunningStyleNige int `json:"properRunningStyleNige"` ProperRunningStyleSenko int `json:"properRunningStyleSenko"` ProperRunningStyleSashi int `json:"properRunningStyleSashi"` ProperRunningStyleOikomi int `json:"properRunningStyleOikomi"` SuccessionCount int `json:"successionCount"` FactorDataArray []FactorDataArray `json:"factorDataArray"` CreateTime string `json:"createTime"` ScenarioID int `json:"scenarioId"` TalentLevel int `json:"talentLevel"` CharaGrade int `json:"charaGrade"` Rarity int `json:"rarity"` IsLock bool `json:"isLock"` FavoriteData FavoriteData `json:"favoriteData"` CachedCreateTimeTimeStamp int `json:"cachedCreateTimeTimeStamp"` SortedFactorList []any `json:"sortedFactorList"` SortedFactorProfileCardList []any `json:"sortedFactorProfileCardList"` FactorListIncludingSuccession []any `json:"factorListIncludingSuccession"` SuccessionCharaList []SuccessionCharaList `json:"successionCharaList"` IsSuccessionHistoryInitialized bool `json:"isSuccessionHistoryInitialized"` SuccessionHistoryList []any `json:"successionHistoryList"` AcquiredSkillArray []AcquiredSkillArray `json:"acquiredSkillArray"` SupportCardArray []SupportCardArray `json:"supportCardArray"` SingleModeRaceResultArray []SingleModeRaceResultArray `json:"singleModeRaceResultArray"` WinSaddleArray []any `json:"winSaddleArray"` WinSaddleIDArray []int `json:"winSaddleIdArray"` CacheCharaID int `json:"cacheCharaId"` MasterCardData MasterCardData `json:"masterCardData"` MasterCharaData MasterCharaData `json:"masterCharaData"` MasterCardRarityData MasterCardRarityData `json:"masterCardRarityData"` SingleTotalRaceNum int `json:"singleTotalRaceNum"` SingleWinNum int `json:"singleWinNum"` TrainedCharaDataAccessor TrainedCharaDataAccessor `json:"trainedCharaDataAccessor"` } type PlayerTeamMember struct { HorseIndex int `json:"horseIndex"` PostNumber int `json:"postNumber"` CharaID int `json:"charaId"` CharaName string `json:"charaName"` FinishOrder int `json:"finishOrder"` FinishTimeRaw float32 `json:"finishTimeRaw"` FinishTimeScaled float32 `json:"finishTimeScaled"` FinishDiffTimeFromPrev float32 `json:"finishDiffTimeFromPrev"` RaceParam RaceParam `json:"raceParam"` ResponseHorseData ResponseHorseData `json:"responseHorseData"` Popularity int `json:"popularity"` PopularityRankLeft int `json:"popularityRankLeft"` PopularityRankCenter int `json:"popularityRankCenter"` PopularityRankRight int `json:"popularityRankRight"` GateInPopularity int `json:"gateInPopularity"` Rarity string `json:"rarity"` TrainerName string `json:"trainerName"` IsGhost bool `json:"isGhost"` IsRunningStyleExInitialized bool `json:"isRunningStyleExInitialized"` RunningStyleEx string `json:"runningStyleEx"` Defeat string `json:"defeat"` RaceDressID int `json:"raceDressId"` RaceDressIDWithOption int `json:"raceDressIdWithOption"` RunningType string `json:"runningType"` ActiveProperDistance string `json:"activeProperDistance"` ActiveProperGroundType string `json:"activeProperGroundType"` MobID int `json:"mobId"` RaceRecord RaceRecord `json:"raceRecord"` FinishOrderRawScore int `json:"finishOrderRawScore"` TrainedCharaData TrainedCharaData `json:"trainedCharaData"` } type PlayerTeamTopFinishOrderHorse struct { HorseIndex int `json:"horseIndex"` PostNumber int `json:"postNumber"` CharaID int `json:"charaId"` CharaName string `json:"charaName"` FinishOrder int `json:"finishOrder"` FinishTimeRaw float32 `json:"finishTimeRaw"` FinishTimeScaled float32 `json:"finishTimeScaled"` FinishDiffTimeFromPrev float32 `json:"finishDiffTimeFromPrev"` RaceParam RaceParam `json:"raceParam"` ResponseHorseData ResponseHorseData `json:"responseHorseData"` Popularity int `json:"popularity"` PopularityRankLeft int `json:"popularityRankLeft"` PopularityRankCenter int `json:"popularityRankCenter"` PopularityRankRight int `json:"popularityRankRight"` GateInPopularity int `json:"gateInPopularity"` Rarity string `json:"rarity"` TrainerName string `json:"trainerName"` IsGhost bool `json:"isGhost"` IsRunningStyleExInitialized bool `json:"isRunningStyleExInitialized"` RunningStyleEx string `json:"runningStyleEx"` Defeat string `json:"defeat"` RaceDressID int `json:"raceDressId"` RaceDressIDWithOption int `json:"raceDressIdWithOption"` RunningType string `json:"runningType"` ActiveProperDistance string `json:"activeProperDistance"` ActiveProperGroundType string `json:"activeProperGroundType"` MobID int `json:"mobId"` RaceRecord RaceRecord `json:"raceRecord"` FinishOrderRawScore int `json:"finishOrderRawScore"` TrainedCharaData TrainedCharaData `json:"trainedCharaData"` } type RaceHorse struct { HorseIndex int `json:"horseIndex"` PostNumber int `json:"postNumber"` CharaID int `json:"charaId"` CharaName string `json:"charaName"` FinishOrder int `json:"finishOrder"` FinishTimeRaw float32 `json:"finishTimeRaw"` FinishTimeScaled float32 `json:"finishTimeScaled"` FinishDiffTimeFromPrev float32 `json:"finishDiffTimeFromPrev"` RaceParam RaceParam `json:"raceParam"` ResponseHorseData ResponseHorseData `json:"responseHorseData"` Popularity int `json:"popularity"` PopularityRankLeft int `json:"popularityRankLeft"` PopularityRankCenter int `json:"popularityRankCenter"` PopularityRankRight int `json:"popularityRankRight"` GateInPopularity int `json:"gateInPopularity"` Rarity string `json:"rarity"` TrainerName string `json:"trainerName"` IsGhost bool `json:"isGhost"` IsRunningStyleExInitialized bool `json:"isRunningStyleExInitialized"` RunningStyleEx string `json:"runningStyleEx"` Defeat string `json:"defeat"` RaceDressID int `json:"raceDressId"` RaceDressIDWithOption int `json:"raceDressIdWithOption"` RunningType string `json:"runningType"` ActiveProperDistance string `json:"activeProperDistance"` ActiveProperGroundType string `json:"activeProperGroundType"` MobID int `json:"mobId"` RaceRecord RaceRecord `json:"raceRecord"` FinishOrderRawScore int `json:"finishOrderRawScore"` TrainedCharaData TrainedCharaData `json:"trainedCharaData,omitempty"` } type RaceRewardSingle struct { // TODO(zeph): this } type CharaGradeType int8 //go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type CharaGradeType -linecomment -trimprefix CharaGrade const ( CharaGradeNone CharaGradeType = iota // NONE CharaGradeDebut CharaGradeNoWin CharaGradeOpen CharaGradeG3Silver CharaGradeG3Gold CharaGradeG2Silver CharaGradeG2Gold CharaGradeG1Bronze CharaGradeG1Silver CharaGradeG1Gold charaGradeMax ) func (r CharaGradeType) AppendText(b []byte) ([]byte, error) { return append(b, r.String()...), nil } func (r CharaGradeType) MarshalText() ([]byte, error) { return r.AppendText(nil) } var charaGradeNames = sync.OnceValue(func() map[string]CharaGradeType { m := make(map[string]CharaGradeType, raceTypeMaxInclusive) for r := CharaGradeNone; r < charaGradeMax; r++ { s := r.String() if strings.HasPrefix(s, "CharaGradeType(") { continue } m[r.String()] = r } return m }) func (r *CharaGradeType) UnmarshalText(b []byte) error { n, ok := charaGradeNames()[string(b)] *r = n if !ok { return fmt.Errorf("unknown chara grade type %q", b) } return nil } type MainStoryRaceGimmickType int8 //go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type MainStoryRaceGimmickType -linecomment const ( GimmickNone MainStoryRaceGimmickType = iota // NONE GimmickSpecial00 // Special_00 gimmickMax ) func (r MainStoryRaceGimmickType) AppendText(b []byte) ([]byte, error) { return append(b, r.String()...), nil } func (r MainStoryRaceGimmickType) MarshalText() ([]byte, error) { return r.AppendText(nil) } var mainStoryGimmickNames = sync.OnceValue(func() map[string]MainStoryRaceGimmickType { m := make(map[string]MainStoryRaceGimmickType, raceTypeMaxInclusive) for r := GimmickNone; r < gimmickMax; r++ { s := r.String() if strings.HasPrefix(s, "MainStoryRaceGimmickType(") { continue } m[r.String()] = r } return m }) func (r *MainStoryRaceGimmickType) UnmarshalText(b []byte) error { n, ok := mainStoryGimmickNames()[string(b)] *r = n if !ok { return fmt.Errorf("unknown main story race gimmick type %q", b) } return nil }