package replay import ( "fmt" "strings" "sync" "git.sunturtle.xyz/zephyr/horse" "git.sunturtle.xyz/zephyr/horse/umadump" ) 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 []HorseData `json:"playerTeamMemberArray"` PlayerTeamTopFinishOrderHorse HorseData `json:"playerTeamTopFinishOrderHorse"` IsGateInPopularityInitialized bool `json:"isGateInPopularityInitialized"` RaceHorse []HorseData `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 struct{} `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 Motivation `json:"motivation"` MotivationCoef float32 `json:"motivationCoef"` } type Motivation int32 //go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type Motivation -linecomment const ( MotivationNone Motivation = iota // None MotivationAwful // Min MotivationBad // Low MotivationNormal // Middle MotivationGood // High MotivationGreat // Max ) func (r Motivation) AppendText(b []byte) ([]byte, error) { return append(b, r.String()...), nil } func (r Motivation) MarshalText() ([]byte, error) { return r.AppendText(nil) } func (r *Motivation) UnmarshalText(b []byte) error { switch string(b) { case "Min": *r = MotivationAwful case "Low": *r = MotivationBad case "Middle": *r = MotivationNormal case "High": *r = MotivationGood case "Max": *r = MotivationGreat case "None": *r = MotivationNone default: *r = 0 return fmt.Errorf("unknown motivation %q", b) } return nil } type SkillArray struct { SkillID horse.SkillID `json:"skill_id"` Level int32 `json:"level"` } type RaceResult struct { Turn int32 `json:"turn"` ProgramID int32 `json:"program_id"` Weather int32 `json:"weather"` GroundCondition int32 `json:"ground_condition"` RunningStyle int32 `json:"running_style"` Popularity int32 `json:"popularity"` ResultRank int32 `json:"result_rank"` ResultTime int32 `json:"result_time"` PrizeMoney int32 `json:"prize_money"` } type RaceHorseData struct { FrameOrder int32 `json:"frame_order"` ViewerID int64 `json:"viewer_id"` TrainerName string `json:"trainer_name"` OwnerViewerID int64 `json:"owner_viewer_id"` OwnerTrainerName string `json:"owner_trainer_name"` SingleModeCharaID int32 `json:"single_mode_chara_id"` TrainedCharaID int32 `json:"trained_chara_id"` NicknameID int32 `json:"nickname_id"` CharaID int32 `json:"chara_id"` CardID int32 `json:"card_id"` MobID int32 `json:"mob_id"` Rarity int32 `json:"rarity"` TalentLevel int32 `json:"talent_level"` SkillArray []SkillArray `json:"skill_array"` Stamina int32 `json:"stamina"` Speed int32 `json:"speed"` Pow int32 `json:"pow"` Guts int32 `json:"guts"` Wiz int32 `json:"wiz"` RunningStyle int32 `json:"running_style"` RaceDressID int32 `json:"race_dress_id"` CharaColorType int32 `json:"chara_color_type"` NpcType int32 `json:"npc_type"` FinalGrade int32 `json:"final_grade"` Popularity int32 `json:"popularity"` PopularityMarkRankArray []int32 `json:"popularity_mark_rank_array"` ProperDistanceShort int32 `json:"proper_distance_short"` ProperDistanceMile int32 `json:"proper_distance_mile"` ProperDistanceMiddle int32 `json:"proper_distance_middle"` ProperDistanceLong int32 `json:"proper_distance_long"` ProperRunningStyleNige int32 `json:"proper_running_style_nige"` ProperRunningStyleSenko int32 `json:"proper_running_style_senko"` ProperRunningStyleSashi int32 `json:"proper_running_style_sashi"` ProperRunningStyleOikomi int32 `json:"proper_running_style_oikomi"` ProperGroundTurf int32 `json:"proper_ground_turf"` ProperGroundDirt int32 `json:"proper_ground_dirt"` Motivation int32 `json:"motivation"` WinSaddleIDArray []int32 `json:"win_saddle_id_array"` RaceResultArray []RaceResult `json:"race_result_array"` TeamID int32 `json:"team_id"` TeamMemberID int32 `json:"team_member_id"` TeamRank int32 `json:"team_rank"` SingleModeWinCount int32 `json:"single_mode_win_count"` ItemIDArray []int32 `json:"item_id_array"` MotivationChangeFlag int32 `json:"motivation_change_flag"` FrameOrderChangeFlag int32 `json:"frame_order_change_flag"` } type HorseData struct { HorseIndex int32 `json:"horseIndex"` PostNumber int32 `json:"postNumber"` CharaID horse.CharacterID `json:"charaId"` CharaName string `json:"charaName"` FinishOrder int32 `json:"finishOrder"` FinishTimeRaw float32 `json:"finishTimeRaw"` FinishTimeScaled float32 `json:"finishTimeScaled"` FinishDiffTimeFromPrev float32 `json:"finishDiffTimeFromPrev"` RaceParam RaceParam `json:"raceParam"` ResponseHorseData RaceHorseData `json:"responseHorseData"` Popularity int32 `json:"popularity"` PopularityRankLeft int8 `json:"popularityRankLeft"` PopularityRankCenter int8 `json:"popularityRankCenter"` PopularityRankRight int8 `json:"popularityRankRight"` GateInPopularity int8 `json:"gateInPopularity"` Rarity CardRarity `json:"rarity"` TrainerName string `json:"trainerName"` IsGhost bool `json:"isGhost"` IsRunningStyleExInitialized bool `json:"isRunningStyleExInitialized"` RunningStyleEx RunningStyleEx `json:"runningStyleEx"` Defeat string `json:"defeat"` // this is an enum, but not worth the effort RaceDressID int32 `json:"raceDressId"` RaceDressIDWithOption int32 `json:"raceDressIdWithOption"` RunningType string `json:"runningType"` // enum not worth ActiveProperDistance ProperGrade `json:"activeProperDistance"` ActiveProperGroundType ProperGrade `json:"activeProperGroundType"` MobID int32 `json:"mobId"` RaceRecord struct{} `json:"raceRecord"` FinishOrderRawScore int32 `json:"finishOrderRawScore"` TrainedCharaData TrainedCharaData `json:"trainedCharaData"` } type RunningStyleEx int8 //go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type RunningStyleEx -linecomment const ( StyleExNone RunningStyleEx = iota // NONE StyleExRunaway // Oonige ) func (r RunningStyleEx) AppendText(b []byte) ([]byte, error) { return append(b, r.String()...), nil } func (r RunningStyleEx) MarshalText() ([]byte, error) { return r.AppendText(nil) } func (r *RunningStyleEx) UnmarshalText(b []byte) error { switch string(b) { case "NONE": *r = StyleExNone case "Oonige": *r = StyleExRunaway default: *r = 0 return fmt.Errorf("unknown extra running style %q", b) } return nil } type ProperGrade int8 //go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type ProperGrade -trimprefix Aptitude const ( AptitudeNull ProperGrade = iota AptitudeG AptitudeF AptitudeE AptitudeD AptitudeC AptitudeB AptitudeA AptitudeS ) func (r ProperGrade) AppendText(b []byte) ([]byte, error) { return append(b, r.String()...), nil } func (r ProperGrade) MarshalText() ([]byte, error) { return r.AppendText(nil) } func (r *ProperGrade) UnmarshalText(b []byte) error { switch string(b) { case "Null": *r = AptitudeNull case "G": *r = AptitudeG case "F": *r = AptitudeF case "E": *r = AptitudeE case "D": *r = AptitudeD case "C": *r = AptitudeC case "B": *r = AptitudeB case "A": *r = AptitudeA case "S": *r = AptitudeS default: *r = 0 return fmt.Errorf("unknown motivation %q", b) } return nil } type TrainedCharaData struct { ID int32 `json:"id"` IsSaved bool `json:"isSaved"` ViewerID int64 `json:"viewerId"` OwnerViewerID int64 `json:"ownerViewerId"` OwnerTrainedCharaID int32 `json:"ownerTrainedCharaId"` UseType int32 `json:"useType"` CardID horse.UmaID `json:"cardId"` NickNameID int32 `json:"nickNameId"` NickNameIDArray []int32 `json:"nickNameIdArray"` Stamina int32 `json:"stamina"` Speed int32 `json:"speed"` Power int32 `json:"power"` Guts int32 `json:"guts"` Wiz int32 `json:"wiz"` Fans int32 `json:"fans"` Rank int32 `json:"rank"` RankScore int32 `json:"rankScore"` RunningStyle int32 `json:"runningStyle"` ProperGroundTurf int32 `json:"properGroundTurf"` ProperGroundDirt int32 `json:"properGroundDirt"` ProperDistanceShort int32 `json:"properDistanceShort"` ProperDistanceMile int32 `json:"properDistanceMile"` ProperDistanceMiddle int32 `json:"properDistanceMiddle"` ProperDistanceLong int32 `json:"properDistanceLong"` ProperRunningStyleNige int32 `json:"properRunningStyleNige"` ProperRunningStyleSenko int32 `json:"properRunningStyleSenko"` ProperRunningStyleSashi int32 `json:"properRunningStyleSashi"` ProperRunningStyleOikomi int32 `json:"properRunningStyleOikomi"` SuccessionCount int32 `json:"successionCount"` FactorDataArray []FactorData `json:"factorDataArray"` CreateTime string `json:"createTime"` ScenarioID horse.ScenarioID `json:"scenarioId"` TalentLevel int32 `json:"talentLevel"` CharaGrade int32 `json:"charaGrade"` Rarity int32 `json:"rarity"` IsLock bool `json:"isLock"` FavoriteData struct{} `json:"favoriteData"` CachedCreateTimeTimeStamp int64 `json:"cachedCreateTimeTimeStamp"` SortedFactorList []umadump.Never `json:"sortedFactorList"` SortedFactorProfileCardList []umadump.Never `json:"sortedFactorProfileCardList"` FactorListIncludingSuccession []umadump.Never `json:"factorListIncludingSuccession"` SuccessionCharaList []SuccessionCharaList `json:"successionCharaList"` IsSuccessionHistoryInitialized bool `json:"isSuccessionHistoryInitialized"` SuccessionHistoryList []umadump.Never `json:"successionHistoryList"` AcquiredSkillArray []AcquiredSkill `json:"acquiredSkillArray"` SupportCardArray []SupportCard `json:"supportCardArray"` SingleModeRaceResultArray []SingleModeRaceResult `json:"singleModeRaceResultArray"` WinSaddleArray []umadump.Never `json:"winSaddleArray"` WinSaddleIDArray []horse.SaddleID `json:"winSaddleIdArray"` CacheCharaID int32 `json:"cacheCharaId"` MasterCardData struct{} `json:"masterCardData"` MasterCharaData struct{} `json:"masterCharaData"` MasterCardRarityData struct{} `json:"masterCardRarityData"` SingleTotalRaceNum int32 `json:"singleTotalRaceNum"` SingleWinNum int32 `json:"singleWinNum"` TrainedCharaDataAccessor struct{} `json:"trainedCharaDataAccessor"` } type FactorData struct { FactorLv int32 `json:"factorLv"` FactorID horse.SparkID `json:"factorId"` BaseFactorID horse.SparkID `json:"baseFactorId"` UpgradeHistoryList []umadump.Never `json:"upgradeHistoryList"` } type SuccessionCharaList struct { PositionID int32 `json:"positionId"` CardID int32 `json:"cardId"` Rarity int32 `json:"rarity"` Level int32 `json:"level"` Rank int32 `json:"rank"` FactorDataArray []FactorData `json:"factorDataArray"` SortedFactorList []umadump.Never `json:"sortedFactorList"` SortedFactorListForProfileCard []umadump.Never `json:"sortedFactorListForProfileCard"` OwnerViewerID int64 `json:"ownerViewerId"` IsPlayer bool `json:"isPlayer"` WinSaddleArray []umadump.Never `json:"winSaddleArray"` WinSaddleIDArray []int32 `json:"winSaddleIdArray"` } type AcquiredSkill struct { MasterID horse.SkillID `json:"masterId"` Level int `json:"level"` Master struct{} `json:"master"` } type SupportCard struct { Position int32 `json:"position"` SupportCardID horse.SupportCardID `json:"supportCardId"` LimitBreakCount int32 `json:"limitBreakCount"` Exp int32 `json:"exp"` } type SingleModeRaceResult 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 CardRarity int8 //go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type CardRarity -linecomment -trimprefix Card const ( CardNone CardRarity = iota // NONE CardRare1 CardRare2 CardRare3 CardRare4 CardRare5 ) func (r CardRarity) AppendText(b []byte) ([]byte, error) { return append(b, r.String()...), nil } func (r CardRarity) MarshalText() ([]byte, error) { return r.AppendText(nil) } func (r *CardRarity) UnmarshalText(b []byte) error { switch string(b) { case "NONE": *r = CardNone case "Rare1": *r = CardRare1 case "Rare2": *r = CardRare2 case "Rare3": *r = CardRare3 case "Rare4": *r = CardRare4 case "Rare5": *r = CardRare5 default: *r = 0 return fmt.Errorf("unknown card rarity %q", b) } return nil } 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 }