Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55aa03aa41 |
@@ -1,13 +0,0 @@
|
||||
package umadump
|
||||
|
||||
type Never struct{}
|
||||
|
||||
func (Never) AppendText(b []byte) ([]byte, error) {
|
||||
panic("umadump: attempt to encode value that should never exist")
|
||||
}
|
||||
func (Never) MarshalText() ([]byte, error) {
|
||||
panic("umadump: attempt to encode value that should never exist")
|
||||
}
|
||||
func (Never) UnmarshalText(b []byte) error {
|
||||
panic("umadump: attempt to decode value that should never exist")
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,29 +0,0 @@
|
||||
// Code generated by "stringer -type CardRarity -linecomment -trimprefix Card"; DO NOT EDIT.
|
||||
|
||||
package replay
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[CardNone-0]
|
||||
_ = x[CardRare1-1]
|
||||
_ = x[CardRare2-2]
|
||||
_ = x[CardRare3-3]
|
||||
_ = x[CardRare4-4]
|
||||
_ = x[CardRare5-5]
|
||||
}
|
||||
|
||||
const _CardRarity_name = "NONERare1Rare2Rare3Rare4Rare5"
|
||||
|
||||
var _CardRarity_index = [...]uint8{0, 4, 9, 14, 19, 24, 29}
|
||||
|
||||
func (i CardRarity) String() string {
|
||||
idx := int(i) - 0
|
||||
if i < 0 || idx >= len(_CardRarity_index)-1 {
|
||||
return "CardRarity(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _CardRarity_name[_CardRarity_index[idx]:_CardRarity_index[idx+1]]
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
// Code generated by "stringer -type Motivation -linecomment"; DO NOT EDIT.
|
||||
|
||||
package replay
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[MotivationNone-0]
|
||||
_ = x[MotivationAwful-1]
|
||||
_ = x[MotivationBad-2]
|
||||
_ = x[MotivationNormal-3]
|
||||
_ = x[MotivationGood-4]
|
||||
_ = x[MotivationGreat-5]
|
||||
}
|
||||
|
||||
const _Motivation_name = "NoneMinLowMiddleHighMax"
|
||||
|
||||
var _Motivation_index = [...]uint8{0, 4, 7, 10, 16, 20, 23}
|
||||
|
||||
func (i Motivation) String() string {
|
||||
idx := int(i) - 0
|
||||
if i < 0 || idx >= len(_Motivation_index)-1 {
|
||||
return "Motivation(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _Motivation_name[_Motivation_index[idx]:_Motivation_index[idx+1]]
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
// Code generated by "stringer -type ProperGrade -trimprefix Aptitude"; DO NOT EDIT.
|
||||
|
||||
package replay
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[AptitudeNull-0]
|
||||
_ = x[AptitudeG-1]
|
||||
_ = x[AptitudeF-2]
|
||||
_ = x[AptitudeE-3]
|
||||
_ = x[AptitudeD-4]
|
||||
_ = x[AptitudeC-5]
|
||||
_ = x[AptitudeB-6]
|
||||
_ = x[AptitudeA-7]
|
||||
_ = x[AptitudeS-8]
|
||||
}
|
||||
|
||||
const _ProperGrade_name = "NullGFEDCBAS"
|
||||
|
||||
var _ProperGrade_index = [...]uint8{0, 4, 5, 6, 7, 8, 9, 10, 11, 12}
|
||||
|
||||
func (i ProperGrade) String() string {
|
||||
idx := int(i) - 0
|
||||
if i < 0 || idx >= len(_ProperGrade_index)-1 {
|
||||
return "ProperGrade(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _ProperGrade_name[_ProperGrade_index[idx]:_ProperGrade_index[idx+1]]
|
||||
}
|
||||
+268
-355
@@ -6,7 +6,6 @@ import (
|
||||
"sync"
|
||||
|
||||
"git.sunturtle.xyz/zephyr/horse"
|
||||
"git.sunturtle.xyz/zephyr/horse/umadump"
|
||||
)
|
||||
|
||||
type Race struct {
|
||||
@@ -47,10 +46,10 @@ type Race struct {
|
||||
PostNumberMax int32 `json:"postNumberMax"`
|
||||
PlayerHorseIndex int32 `json:"playerHorseIndex"`
|
||||
OverridePlayerHorseIndex int32 `json:"overridePlayerHorseIndex"`
|
||||
PlayerTeamMemberArray []HorseData `json:"playerTeamMemberArray"`
|
||||
PlayerTeamTopFinishOrderHorse HorseData `json:"playerTeamTopFinishOrderHorse"`
|
||||
PlayerTeamMemberArray []RaceHorse `json:"playerTeamMemberArray"`
|
||||
PlayerTeamTopFinishOrderHorse RaceHorse `json:"playerTeamTopFinishOrderHorse"`
|
||||
IsGateInPopularityInitialized bool `json:"isGateInPopularityInitialized"`
|
||||
RaceHorse []HorseData `json:"raceHorse"`
|
||||
RaceHorse []RaceHorse `json:"raceHorse"`
|
||||
RaceBibMaster struct{} `json:"raceBibMaster"`
|
||||
RaceMaster struct{} `json:"raceMaster"`
|
||||
RaceInstanceMaster struct{} `json:"raceInstanceMaster"`
|
||||
@@ -65,7 +64,7 @@ type Race struct {
|
||||
ReplayCheckInfoLegend struct{} `json:"replayCheckInfoLegend"`
|
||||
IsDailyLegendRace bool `json:"isDailyLegendRace"`
|
||||
ReplayCheckInfoChallengeMatch struct{} `json:"replayCheckInfoChallengeMatch"`
|
||||
RaceRewardSingle struct{} `json:"raceRewardSingle"`
|
||||
RaceRewardSingle RaceRewardSingle `json:"raceRewardSingle"`
|
||||
ResultHorseIndex int32 `json:"resultHorseIndex"`
|
||||
PrevGradeType CharaGradeType `json:"prevGradeType"`
|
||||
MainStoryRaceGimmickType MainStoryRaceGimmickType `json:"mainStoryRaceGimmickType"`
|
||||
@@ -538,334 +537,122 @@ func (r *RaceDifficulty) UnmarshalText(b []byte) error {
|
||||
}
|
||||
|
||||
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
|
||||
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 horse.SkillID `json:"skill_id"`
|
||||
Level int32 `json:"level"`
|
||||
SkillID int `json:"skill_id"`
|
||||
Level int `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 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 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 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 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 RaceRecord struct {
|
||||
}
|
||||
|
||||
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
|
||||
type FactorDataArray struct {
|
||||
FactorLv int `json:"factorLv"`
|
||||
FactorID int `json:"factorId"`
|
||||
BaseFactorID int `json:"baseFactorId"`
|
||||
UpgradeHistoryList []any `json:"upgradeHistoryList"`
|
||||
}
|
||||
|
||||
func (r RunningStyleEx) MarshalText() ([]byte, error) {
|
||||
return r.AppendText(nil)
|
||||
type FavoriteData struct {
|
||||
}
|
||||
|
||||
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"`
|
||||
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 AcquiredSkill struct {
|
||||
MasterID horse.SkillID `json:"masterId"`
|
||||
Level int `json:"level"`
|
||||
Master struct{} `json:"master"`
|
||||
type Master struct {
|
||||
}
|
||||
|
||||
type SupportCard struct {
|
||||
Position int32 `json:"position"`
|
||||
SupportCardID horse.SupportCardID `json:"supportCardId"`
|
||||
LimitBreakCount int32 `json:"limitBreakCount"`
|
||||
Exp int32 `json:"exp"`
|
||||
type AcquiredSkillArray struct {
|
||||
MasterID int `json:"masterId"`
|
||||
Level int `json:"level"`
|
||||
Master Master `json:"master"`
|
||||
}
|
||||
|
||||
type SingleModeRaceResult struct {
|
||||
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"`
|
||||
@@ -877,46 +664,172 @@ type SingleModeRaceResult struct {
|
||||
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
|
||||
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"`
|
||||
}
|
||||
|
||||
func (r CardRarity) MarshalText() ([]byte, error) {
|
||||
return r.AppendText(nil)
|
||||
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"`
|
||||
}
|
||||
|
||||
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 RaceRewardSingle struct {
|
||||
// TODO(zeph): this
|
||||
}
|
||||
|
||||
type CharaGradeType int8
|
||||
|
||||
@@ -1,182 +0,0 @@
|
||||
package replay_test
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.sunturtle.xyz/zephyr/horse/umadump/replay"
|
||||
)
|
||||
|
||||
//go:embed Mihono_Bourbon-74.2421s-20260829.json
|
||||
var testRace string
|
||||
|
||||
func TestRaceUnmarshal(t *testing.T) {
|
||||
// A replay is simply too large to bother converting by hand for a unit test.
|
||||
// Just test that we can unmarshal and certain important fields are populated.
|
||||
d := json.NewDecoder(strings.NewReader(testRace))
|
||||
d.DisallowUnknownFields()
|
||||
var got replay.Race
|
||||
if err := d.Decode(&got); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if got.RaceType != replay.RaceTypeChampions {
|
||||
t.Errorf("wrong race type: want %v, got %v", replay.RaceTypeChampions, got.RaceType)
|
||||
}
|
||||
if got.RandomSeed != 1667907263 {
|
||||
t.Errorf("wrong random seed: want 1667907263, got %d", got.RandomSeed)
|
||||
}
|
||||
if got.RaceCourseSet.ID != 10903 {
|
||||
t.Errorf("wrong race course: want 10903, got %d", got.RaceCourseSet.ID)
|
||||
}
|
||||
if got.GroundCondition != replay.GroundFirm {
|
||||
t.Errorf("wrong ground condition: want %v, got %v", replay.GroundFirm, got.GroundCondition)
|
||||
}
|
||||
if got.Weather != replay.WeatherCloudy {
|
||||
t.Errorf("wrong weather: want %v, got %v", replay.WeatherCloudy, got.Weather)
|
||||
}
|
||||
if got.NumRaceHorses != 9 {
|
||||
t.Errorf("wrong number of race horses: want 9, got %d", got.NumRaceHorses)
|
||||
}
|
||||
if len(got.PlayerTeamMemberArray) != 3 {
|
||||
t.Errorf("wrong number of team members: want 3, got %d", len(got.PlayerTeamMemberArray))
|
||||
}
|
||||
for _, m := range got.PlayerTeamMemberArray {
|
||||
if m.CharaID == 0 {
|
||||
t.Error("missing team member chara id")
|
||||
}
|
||||
if m.FinishTimeRaw == 0 {
|
||||
t.Error("missing team member finish time raw")
|
||||
}
|
||||
if m.RaceParam.RawSpeed == 0 {
|
||||
t.Error("missing team member race param raw speed")
|
||||
}
|
||||
if m.RaceParam.BaseSpeed == 0 {
|
||||
t.Error("missing team member race param base speed")
|
||||
}
|
||||
if m.ResponseHorseData.ViewerID == 0 {
|
||||
t.Error("missing team member response horse data viewer id")
|
||||
}
|
||||
if m.ResponseHorseData.TrainedCharaID == 0 {
|
||||
t.Error("missing team member response horse data trained chara id")
|
||||
}
|
||||
if m.ResponseHorseData.CardID == 0 {
|
||||
t.Error("missing team member response horse data card id")
|
||||
}
|
||||
if len(m.ResponseHorseData.SkillArray) == 0 {
|
||||
t.Error("missing team member response horse data skill array")
|
||||
}
|
||||
if m.ResponseHorseData.Speed == 0 {
|
||||
t.Error("missing team member response horse data speed")
|
||||
}
|
||||
if m.ResponseHorseData.RunningStyle == 0 {
|
||||
t.Error("missing team member response horse data running style")
|
||||
}
|
||||
if m.ActiveProperDistance == 0 {
|
||||
t.Error("missing team member active distance aptitude")
|
||||
}
|
||||
if m.ActiveProperGroundType == 0 {
|
||||
t.Error("missing team member active surface aptitude")
|
||||
}
|
||||
if m.TrainedCharaData.ID == 0 {
|
||||
t.Error("missing team member trained chara id")
|
||||
}
|
||||
if m.TrainedCharaData.CardID == 0 {
|
||||
t.Error("missing team member trained chara card id")
|
||||
}
|
||||
if m.TrainedCharaData.Speed == 0 {
|
||||
t.Error("missing team member trained chara speed")
|
||||
}
|
||||
if m.TrainedCharaData.RunningStyle == 0 {
|
||||
t.Error("missing team member trained chara running style")
|
||||
}
|
||||
if m.TrainedCharaData.CreateTime == "" {
|
||||
t.Error("missing team member trained chara create time")
|
||||
}
|
||||
if len(m.TrainedCharaData.AcquiredSkillArray) == 0 {
|
||||
t.Error("missing team member trained chara acquired skill array")
|
||||
}
|
||||
}
|
||||
if len(got.RaceHorse) != int(got.NumRaceHorses) {
|
||||
t.Errorf("wrong number of race horses: want %d, got %d", got.NumRaceHorses, len(got.RaceHorse))
|
||||
}
|
||||
zeroFinish, zeroDelta := 0, 0
|
||||
for _, m := range got.RaceHorse {
|
||||
if m.CharaID == 0 {
|
||||
t.Error("missing race horse chara id")
|
||||
}
|
||||
if m.FinishOrder == 0 {
|
||||
zeroFinish++
|
||||
}
|
||||
if m.FinishTimeRaw == 0 {
|
||||
t.Error("missing race horse finish time raw")
|
||||
}
|
||||
if m.FinishDiffTimeFromPrev == 0 {
|
||||
zeroDelta++
|
||||
}
|
||||
if m.RaceParam.RawSpeed == 0 {
|
||||
t.Error("missing race horse race param raw speed")
|
||||
}
|
||||
if m.RaceParam.BaseSpeed == 0 {
|
||||
t.Error("missing race horse race param base speed")
|
||||
}
|
||||
if m.ResponseHorseData.ViewerID == 0 {
|
||||
t.Error("missing race horse response horse data viewer id")
|
||||
}
|
||||
if m.ResponseHorseData.TrainedCharaID == 0 {
|
||||
t.Error("missing race horse response horse data trained chara id")
|
||||
}
|
||||
if m.ResponseHorseData.CardID == 0 {
|
||||
t.Error("missing race horse response horse data card id")
|
||||
}
|
||||
if len(m.ResponseHorseData.SkillArray) == 0 {
|
||||
t.Error("missing race horse response horse data skill array")
|
||||
}
|
||||
if m.ResponseHorseData.Speed == 0 {
|
||||
t.Error("missing race horse response horse data speed")
|
||||
}
|
||||
if m.ResponseHorseData.RunningStyle == 0 {
|
||||
t.Error("missing race horse response horse data running style")
|
||||
}
|
||||
if m.ActiveProperDistance == 0 {
|
||||
t.Error("missing race horse active distance aptitude")
|
||||
}
|
||||
if m.ActiveProperGroundType == 0 {
|
||||
t.Error("missing race horse active surface aptitude")
|
||||
}
|
||||
if m.TrainedCharaData.ID == 0 {
|
||||
t.Error("missing race horse trained chara id")
|
||||
}
|
||||
if m.TrainedCharaData.CardID == 0 {
|
||||
t.Error("missing race horse trained chara card id")
|
||||
}
|
||||
if m.TrainedCharaData.Speed == 0 {
|
||||
t.Error("missing race horse trained chara speed")
|
||||
}
|
||||
if m.TrainedCharaData.RunningStyle == 0 {
|
||||
t.Error("missing race horse trained chara running style")
|
||||
}
|
||||
if m.TrainedCharaData.CreateTime == "" {
|
||||
t.Error("missing race horse trained chara create time")
|
||||
}
|
||||
if len(m.TrainedCharaData.AcquiredSkillArray) == 0 {
|
||||
t.Error("missing race horse trained chara acquired skill array")
|
||||
}
|
||||
}
|
||||
if zeroFinish != 1 {
|
||||
t.Errorf("%d horses in index 0 finish", zeroFinish)
|
||||
}
|
||||
if zeroDelta != 1 {
|
||||
t.Errorf("%d horses with zero finish time delta", zeroDelta)
|
||||
}
|
||||
if got.SimDataBase64 != encodedSimdata {
|
||||
t.Errorf("wrong simdata:\nwant %s\n got %s", encodedSimdata, got.SimDataBase64)
|
||||
}
|
||||
if len(got.HorseIndexByFinishOrder) != len(got.RaceHorse) {
|
||||
t.Errorf("length of horseIndexByFinishOrder (%d) doesn't match length of raceHorse (%d)", len(got.HorseIndexByFinishOrder), len(got.RaceHorse))
|
||||
}
|
||||
if len(got.HorseIndexByPopularity) != len(got.RaceHorse) {
|
||||
t.Errorf("length of horseIndexByPopularity (%d) doesn't match length of raceHorse (%d)", len(got.HorseIndexByPopularity), len(got.RaceHorse))
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
// Code generated by "stringer -type RunningStyleEx -linecomment"; DO NOT EDIT.
|
||||
|
||||
package replay
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[StyleExNone-0]
|
||||
_ = x[StyleExRunaway-1]
|
||||
}
|
||||
|
||||
const _RunningStyleEx_name = "NONEOonige"
|
||||
|
||||
var _RunningStyleEx_index = [...]uint8{0, 4, 10}
|
||||
|
||||
func (i RunningStyleEx) String() string {
|
||||
idx := int(i) - 0
|
||||
if i < 0 || idx >= len(_RunningStyleEx_index)-1 {
|
||||
return "RunningStyleEx(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _RunningStyleEx_name[_RunningStyleEx_index[idx]:_RunningStyleEx_index[idx+1]]
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,20 +0,0 @@
|
||||
<script lang="ts">
|
||||
interface Props {
|
||||
value: number;
|
||||
}
|
||||
|
||||
let { value = $bindable() }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class="flex">
|
||||
<input
|
||||
class="my-auto w-full grow justify-self-center-safe"
|
||||
type="range"
|
||||
id="raceLen"
|
||||
min="1000"
|
||||
max="3600"
|
||||
step="100"
|
||||
bind:value
|
||||
/>
|
||||
<span class="my-auto flex-none pl-4 text-sm">{value}m</span>
|
||||
</div>
|
||||
@@ -20,7 +20,6 @@
|
||||
skill_id: 0,
|
||||
name: 'Skill data is loading...',
|
||||
description: 'Skill data is still loading, or else something went wrong.',
|
||||
group_skills: [],
|
||||
group: 0,
|
||||
rarity: 1,
|
||||
group_rate: 1,
|
||||
|
||||
@@ -4,10 +4,6 @@ import type { RegionalName } from '$lib/regional-name';
|
||||
* Lobby conversation data.
|
||||
*/
|
||||
export interface Conversation {
|
||||
/**
|
||||
* Gallery ID.
|
||||
*/
|
||||
id: number;
|
||||
/**
|
||||
* Character who owns the conversation as a gallery entry.
|
||||
*/
|
||||
|
||||
@@ -14,10 +14,6 @@ export interface Skill {
|
||||
* Regional skil description.
|
||||
*/
|
||||
description: string;
|
||||
/**
|
||||
* Other skills in the skill group.
|
||||
*/
|
||||
group_skills: GroupSkill[];
|
||||
/**
|
||||
* Skill group ID.
|
||||
*/
|
||||
@@ -62,18 +58,6 @@ export interface Skill {
|
||||
icon_id: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skill reference in a skill group.
|
||||
*/
|
||||
export interface GroupSkill {
|
||||
/** Skill ID. */
|
||||
skill_id: number;
|
||||
/** Group rate, as in `Skill`. */
|
||||
group_rate: Skill['group_rate'];
|
||||
/** Rarity, as in `Skill`. */
|
||||
rarity: Skill['rarity'];
|
||||
}
|
||||
|
||||
export enum DurationScale {
|
||||
Direct = 1,
|
||||
FrontDistance = 2,
|
||||
|
||||
@@ -771,17 +771,16 @@ export function conservePowerAccel(
|
||||
distanceType: Distance,
|
||||
style: RunningStyle,
|
||||
rawPower: number,
|
||||
basePower: number,
|
||||
powerSkillBonus?: number,
|
||||
spotStruggled?: boolean,
|
||||
rushed?: boolean,
|
||||
): number {
|
||||
const power = basePower + 0.5 * Math.max(rawPower - 1200, 0) + (powerSkillBonus ?? 0);
|
||||
const power = rawPower + (powerSkillBonus ?? 0);
|
||||
if (power <= 1200) {
|
||||
return 0;
|
||||
}
|
||||
const sdc = conserveStratDistCoef[style][distanceType];
|
||||
const activity = (rushed ? 0.8 : 1) * (spotStruggled ? 0.98 : 1);
|
||||
const activity = rushed ? 0.8 : spotStruggled ? 0.98 : 1;
|
||||
return Math.sqrt((power - 1200) * 130) * 0.001 * sdc * activity;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import * as z from 'zod';
|
||||
|
||||
const Entry = z.strictObject({
|
||||
home_story_trigger_id: z.int32(),
|
||||
new_flag: z.literal(0).or(z.literal(1)),
|
||||
});
|
||||
|
||||
export type Entry = z.infer<typeof Entry>;
|
||||
|
||||
export const Gallery = z.object({
|
||||
talk_gallery_list: z.array(Entry),
|
||||
});
|
||||
|
||||
export type Gallery = z.infer<typeof Gallery>;
|
||||
@@ -9,51 +9,25 @@
|
||||
requiredCharas,
|
||||
convoCharas,
|
||||
} from '$lib/data/convo';
|
||||
import * as talk from '$lib/umadump/talk';
|
||||
import CharaPick from '$lib/CharaPick.svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import CharaIcon from '$lib/CharaIcon.svelte';
|
||||
import { SvelteSet } from 'svelte/reactivity';
|
||||
|
||||
let allConvos: Conversation[] = $state([]);
|
||||
const popular = $derived(groupPopulars(allConvos));
|
||||
let conversations: Conversation[] = $state([]);
|
||||
const convoMap = $derived(byChara(conversations));
|
||||
const popular = $derived(groupPopulars(conversations));
|
||||
let characters: Character[] = $state([]);
|
||||
const selCharas = $derived(characters.filter((c) => convoMap.has(c.chara_id)));
|
||||
const names = $derived(charaNames(characters));
|
||||
const minSuggest = 8;
|
||||
|
||||
onMount(async () => {
|
||||
[allConvos, characters] = await Promise.all([conversation(), character()]);
|
||||
[conversations, characters] = await Promise.all([conversation(), character()]);
|
||||
});
|
||||
|
||||
let chara: Character | undefined = $state();
|
||||
let convo = $state(1);
|
||||
|
||||
let talkFiles: FileList | undefined = $state();
|
||||
let readIDs = new SvelteSet<number>();
|
||||
let talkFileInvalid = $state(false);
|
||||
async function setRead(f: FileList) {
|
||||
talkFiles = f;
|
||||
readIDs.clear();
|
||||
talkFileInvalid = false;
|
||||
if (talkFiles == null || talkFiles.length === 0) {
|
||||
return;
|
||||
}
|
||||
const t = await talkFiles[0].text();
|
||||
const d = JSON.parse(t);
|
||||
const g = talk.Gallery.safeDecode(d);
|
||||
if (!g.success) {
|
||||
talkFileInvalid = true;
|
||||
console.warn(g.error);
|
||||
return;
|
||||
}
|
||||
for (const e of g.data.talk_gallery_list) {
|
||||
readIDs.add(e.home_story_trigger_id);
|
||||
}
|
||||
}
|
||||
const conversations = $derived(allConvos.filter((c) => !readIDs.has(c.id)));
|
||||
const convoMap = $derived(byChara(conversations));
|
||||
const selCharas = $derived(characters.filter((c) => convoMap.has(c.chara_id)));
|
||||
|
||||
const options = $derived(convoMap.get(chara?.chara_id ?? 0) ?? []);
|
||||
const cur = $derived(options.find((c) => c.number === convo));
|
||||
const charaIDs = $derived(cur != null ? convoCharas(cur) : []);
|
||||
@@ -73,12 +47,12 @@
|
||||
</script>
|
||||
|
||||
<h1 class="text-4xl">Lobby Conversations</h1>
|
||||
<div class="mx-auto mt-8 grid grid-cols-1 gap-4 rounded-md p-4 text-center shadow-md ring md:max-w-xl md:grid-cols-6">
|
||||
<div class="md:col-span-3">
|
||||
<div class="mx-auto mt-8 flex flex-col rounded-md text-center shadow-md ring md:max-w-xl md:flex-row">
|
||||
<div class="m-4 flex-1 md:mt-3">
|
||||
<label for="chara" class="hidden md:inline">Character</label>
|
||||
<CharaPick id="chara" characters={selCharas} class="w-full" bind:value={chara} required />
|
||||
</div>
|
||||
<div class="md:col-span-3">
|
||||
<div class="m-4 flex-1 md:mt-3">
|
||||
<label for="convo" class="hidden md:inline">Conversation</label>
|
||||
<select id="convo" bind:value={convo} class="w-full">
|
||||
{#each options as opt (opt.number)}
|
||||
@@ -86,29 +60,6 @@
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-span-full">
|
||||
<label for="talkgallery" class="block">
|
||||
Select
|
||||
<a href="https://werseter.github.io/umadump/" target="_blank" rel="noopener noreferrer">
|
||||
<span class="inline-block font-mono">talk_gallery_data.json</span>
|
||||
</a>
|
||||
to hide read conversations.
|
||||
</label>
|
||||
<input
|
||||
type="file"
|
||||
class="rounded-full p-4"
|
||||
accept="application/json"
|
||||
id="talkgallery"
|
||||
bind:files={() => talkFiles ?? new DataTransfer().files, setRead}
|
||||
/>
|
||||
<button
|
||||
class="ml-4 rounded-full bg-mist-300 p-2 hover:cursor-pointer dark:bg-mist-900"
|
||||
onclick={() => setRead(new DataTransfer().files)}>Reset</button
|
||||
>
|
||||
</div>
|
||||
{#if talkFileInvalid}
|
||||
<div class="col-span-full">Invalid File</div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if cur}
|
||||
<div class="shadow-sm transition-shadow hover:shadow-md">
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
import Article from '../Article.svelte';
|
||||
import Sec from '../Sec.svelte';
|
||||
import * as skill from '$lib/data/skill';
|
||||
import RaceLenSlider from '$lib/RaceLenSlider.svelte';
|
||||
|
||||
let raceLen = $state(2000);
|
||||
let secSpeedStyle = $state(RunningStyle.FrontRunner);
|
||||
@@ -225,10 +224,10 @@
|
||||
},
|
||||
]);
|
||||
const fcSeries: ComputedSeries[] = $derived([
|
||||
{ label: 'Front Runner', y: (x, raw) => conservePowerAccel(distance(raceLen), RunningStyle.FrontRunner, raw, x) },
|
||||
{ label: 'Pace Chaser', y: (x, raw) => conservePowerAccel(distance(raceLen), RunningStyle.PaceChaser, raw, x) },
|
||||
{ label: 'Late Surger', y: (x, raw) => conservePowerAccel(distance(raceLen), RunningStyle.LateSurger, raw, x) },
|
||||
{ label: 'End Closer', y: (x, raw) => conservePowerAccel(distance(raceLen), RunningStyle.EndCloser, raw, x) },
|
||||
{ label: 'Front Runner', y: (x) => conservePowerAccel(distance(raceLen), RunningStyle.FrontRunner, x) },
|
||||
{ label: 'Pace Chaser', y: (x) => conservePowerAccel(distance(raceLen), RunningStyle.PaceChaser, x) },
|
||||
{ label: 'Late Surger', y: (x) => conservePowerAccel(distance(raceLen), RunningStyle.LateSurger, x) },
|
||||
{ label: 'End Closer', y: (x) => conservePowerAccel(distance(raceLen), RunningStyle.EndCloser, x) },
|
||||
]);
|
||||
</script>
|
||||
|
||||
@@ -515,13 +514,23 @@
|
||||
plotOptions={{ color: { legend: true } }}
|
||||
/>
|
||||
<div class="mx-auto flex w-full md:max-w-2xl">
|
||||
<label class="my-auto mr-2 hidden flex-none pr-2 text-right text-sm md:inline" for="secSpeedRaceLen">Race Length</label>
|
||||
<RaceLenSlider bind:value={raceLen} />
|
||||
<label class="my-auto hidden flex-none pr-2 text-right text-sm md:inline" for="secSpeedRaceLen">Race Length</label>
|
||||
<input
|
||||
class="my-auto max-w-40 flex-1 md:flex-2"
|
||||
type="range"
|
||||
id="secSpeedRaceLen"
|
||||
min="1000"
|
||||
max="3600"
|
||||
step="100"
|
||||
bind:value={raceLen}
|
||||
/>
|
||||
<span class="my-auto flex-none pl-2 text-sm">{raceLen}m</span>
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
Rushed and <a href="#spot-struggle">spot struggle</a> reduce both the duration and effectiveness of full charge, potentially to
|
||||
zero. In practice, this appears to be a concern primarily on sprints, which already have a -55% penalty to full charge duration.
|
||||
The exact mechanics of conserving power are unclear at this time. What has been confirmed is that rushed and <a
|
||||
href="#spot-struggle">spot struggle</a
|
||||
> both reduce the chance for it to fire.
|
||||
</p>
|
||||
|
||||
<Sec h={3} id="lane-combo">Lane Combo</Sec>
|
||||
@@ -661,8 +670,17 @@
|
||||
plotOptions={{ color: { legend: true } }}
|
||||
/>
|
||||
<div class="mx-auto flex w-full md:max-w-2xl">
|
||||
<label class="my-auto mr-2 hidden flex-1 pr-2 text-right text-sm md:inline" for="secSpeedRaceLen">Race Length</label>
|
||||
<RaceLenSlider bind:value={raceLen} />
|
||||
<label class="my-auto hidden flex-1 pr-2 text-right text-sm md:inline" for="secSpeedRaceLen">Race Length</label>
|
||||
<input
|
||||
class="my-auto max-w-40 flex-1 md:flex-2"
|
||||
type="range"
|
||||
id="secSpeedRaceLen"
|
||||
min="1000"
|
||||
max="3600"
|
||||
step="100"
|
||||
bind:value={raceLen}
|
||||
/>
|
||||
<span class="my-auto flex-1 pl-2 text-sm">{raceLen}m</span>
|
||||
<label class="my-auto hidden flex-1 pr-2 text-right text-sm md:inline" for="secSpeedStyle">Style</label>
|
||||
<select class="my-auto flex-1 text-sm" id="secSpeedStyle" bind:value={secSpeedStyle}>
|
||||
{#each RUNNING_STYLES as [name, style] (style)}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
import * as race from '$lib/race';
|
||||
import StatChart from '$lib/StatChart.svelte';
|
||||
import { resolve } from '$app/paths';
|
||||
import RaceLenSlider from '$lib/RaceLenSlider.svelte';
|
||||
|
||||
function modemean(x: number, bonus: number, p: number): number {
|
||||
return x * (1 - p) + x * bonus * p;
|
||||
@@ -59,10 +58,10 @@
|
||||
]);
|
||||
const laneChange: ComputedSeries[] = [{ label: 'Lane Change Target Speed', y: (x) => race.laneChangeSpeed(x) }];
|
||||
const conservePower: Array<ComputedSeries | null> = $derived([
|
||||
{ label: 'Conserved Power', y: (x, raw) => race.conservePowerAccel(distanceType, style, raw, x, 0, false, false) },
|
||||
{ label: 'Rushed', y: (x, raw) => race.conservePowerAccel(distanceType, style, raw, x, 0, false, true) },
|
||||
{ label: 'Conserved Power', y: (_raw, x) => race.conservePowerAccel(distanceType, style, x, 0, false, false) },
|
||||
{ label: 'Rushed', y: (_raw, x) => race.conservePowerAccel(distanceType, style, x, 0, false, true) },
|
||||
styleIsFront
|
||||
? { label: 'Spot Struggled', y: (x, raw) => race.conservePowerAccel(distanceType, style, raw, x, 0, true, false) }
|
||||
? { label: 'Spot Struggled', y: (_raw, x) => race.conservePowerAccel(distanceType, style, x, 0, true, false) }
|
||||
: null,
|
||||
]);
|
||||
const gutsSpurt: Array<ComputedSeries | null> = $derived([
|
||||
@@ -175,9 +174,16 @@
|
||||
/>
|
||||
<div class="mx-auto grid w-full grid-cols-3 gap-y-6 md:max-w-2xl md:grid-cols-7">
|
||||
{#if pick?.len}
|
||||
<div class="col-span-3 my-auto mr-4">
|
||||
<RaceLenSlider bind:value={raceLen} />
|
||||
</div>
|
||||
<input
|
||||
class="col-span-2 my-auto w-full justify-self-center-safe"
|
||||
type="range"
|
||||
id="raceLen"
|
||||
min="1000"
|
||||
max="3600"
|
||||
step="100"
|
||||
bind:value={raceLen}
|
||||
/>
|
||||
<span class="col-span-1 my-auto pl-2 text-sm">{raceLen}m</span>
|
||||
{/if}
|
||||
{#if pick?.style}
|
||||
<select class="col-span-1 my-auto text-sm md:col-span-2" id="stylePick" bind:value={style}>
|
||||
@@ -323,16 +329,11 @@
|
||||
Bonus acceleration at spurt start from the Charge Up/Fully Charged mechanic. Scales with base power plus passive skills, so
|
||||
modifiers for ground conditions and career mode do not apply.
|
||||
</p>
|
||||
{@render statChart(race.Stat.Power, conservePower, 'Acceleration (m/s²)', [0, 0.35], { len: true, style: true })}
|
||||
<p>
|
||||
The duration of Fully Charged does not depend directly on stats, but rather on a hidden <i>conserved power</i> value which
|
||||
increases per horse throughout the race. Conserved power does not increase while <a href="#spot-struggle">spot struggling</a>,
|
||||
so for front runners, the duration may scale negatively with guts. It also does not increase while running in any
|
||||
<a href="#poskeep">position keep mode</a>
|
||||
other than pace-down, so its duration may have a very slight negative correlation with wit.
|
||||
<a href="#rushed">Rushed</a> additionally prevents accumulating conserved power, so full charge duration may scale positively with
|
||||
wit amortized across races. Otherwise, power conservation rate depends on running style.
|
||||
This mechanic does not appear to be well understood, in particular how long the acceleration bonus lasts and how the rushed
|
||||
and spot struggle multipliers apply.
|
||||
</p>
|
||||
{@render statChart(race.Stat.Power, conservePower, 'Acceleration (m/s²)', [0, 0.35], { len: true, style: true })}
|
||||
|
||||
<Sec h={2} id="guts">Guts</Sec>
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
import * as accel from '$lib/racelib/accel';
|
||||
import type { Attachment } from 'svelte/attachments';
|
||||
import CalcInfo from '../CalcInfo.svelte';
|
||||
import RaceLenSlider from '$lib/RaceLenSlider.svelte';
|
||||
|
||||
let rawSpeed = $state(1200);
|
||||
let rawPower = $state(1200);
|
||||
@@ -232,9 +231,16 @@
|
||||
</div>
|
||||
|
||||
<div class="mb-auto grid max-w-4xl grid-cols-6 rounded-md text-center shadow-md ring md:col-span-6">
|
||||
<div class="col-span-full m-4">
|
||||
<RaceLenSlider bind:value={raceLen} />
|
||||
</div>
|
||||
<input
|
||||
class="col-span-4 m-4 w-full justify-self-center-safe"
|
||||
type="range"
|
||||
id="raceLen"
|
||||
min="1000"
|
||||
max="3600"
|
||||
step="100"
|
||||
bind:value={raceLen}
|
||||
/>
|
||||
<span class="col-span-2 my-auto mb-4 pl-2 text-sm">{raceLen}m</span>
|
||||
<select id="surface" bind:value={surface} class="col-span-2 mx-2 mb-4">
|
||||
<option value={race.Surface.Turf}>Turf</option>
|
||||
<option value={race.Surface.Dirt}>Dirt</option>
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
import * as accel from '$lib/racelib/accel';
|
||||
import type { Attachment } from 'svelte/attachments';
|
||||
import CalcInfo from '../CalcInfo.svelte';
|
||||
import RaceLenSlider from '$lib/RaceLenSlider.svelte';
|
||||
|
||||
let rawPower = $state(1200);
|
||||
let rawGuts = $state(1200);
|
||||
@@ -217,9 +216,16 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-auto grid max-w-4xl grid-cols-6 rounded-md text-center shadow-md ring md:col-span-3">
|
||||
<div class="col-span-6 mx-4 mt-4">
|
||||
<RaceLenSlider bind:value={raceLen} />
|
||||
</div>
|
||||
<input
|
||||
class="col-span-4 m-4 w-full justify-self-center-safe"
|
||||
type="range"
|
||||
id="raceLen"
|
||||
min="1000"
|
||||
max="3600"
|
||||
step="100"
|
||||
bind:value={raceLen}
|
||||
/>
|
||||
<span class="col-span-2 my-auto mb-4 pl-2 text-sm">{raceLen}m</span>
|
||||
<select id="surface" bind:value={surface} class="col-span-2 m-4">
|
||||
<option value={race.Surface.Turf}>Turf</option>
|
||||
<option value={race.Surface.Dirt}>Dirt</option>
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
import StatChart from '$lib/StatChart.svelte';
|
||||
import { resolve } from '$app/paths';
|
||||
import SpeedDur from './SpeedDur.svelte';
|
||||
import RaceLenSlider from '$lib/RaceLenSlider.svelte';
|
||||
|
||||
let rawPower = $state(1200);
|
||||
let rawGuts = $state(1200);
|
||||
@@ -113,7 +112,8 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="m-4 md:col-span-2 md:col-start-2">
|
||||
<RaceLenSlider bind:value={raceLen} />
|
||||
<label for="raceLen">Race Distance</label>
|
||||
<input type="number" id="raceLen" required min="1000" max="3600" step="100" bind:value={raceLen} class="w-full" />
|
||||
</div>
|
||||
<div class="m-4 self-center md:col-span-2">
|
||||
<label for="isRunaway" class="mr-1 align-middle">Runaway</label>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type { ComputedSeries } from '$lib/chart';
|
||||
import * as race from '$lib/race';
|
||||
import RaceLenSlider from '$lib/RaceLenSlider.svelte';
|
||||
import StatChart from '$lib/StatChart.svelte';
|
||||
import CalcInfo from '../CalcInfo.svelte';
|
||||
|
||||
@@ -99,7 +98,8 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="m-4 md:col-start-2">
|
||||
<RaceLenSlider bind:value={raceLen} />
|
||||
<label for="raceLen">Race Distance</label>
|
||||
<input type="number" id="raceLen" required min="1000" max="3600" step="100" bind:value={raceLen} class="w-full" />
|
||||
</div>
|
||||
<div class="m-4 self-center">
|
||||
<label for="isCareer" class="mr-1 align-middle">In Career</label>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import * as course from '$lib/course';
|
||||
import * as race from '$lib/race';
|
||||
import RaceLenSlider from '$lib/RaceLenSlider.svelte';
|
||||
import * as recovery from '$lib/racelib/recovery';
|
||||
import HPChart from './HPChart.svelte';
|
||||
import InfoPanels from './InfoPanels.svelte';
|
||||
@@ -278,7 +277,16 @@
|
||||
</div>
|
||||
<div class="mx-auto my-2 grid max-w-5xl grid-cols-1 gap-4 rounded-md text-center shadow-md ring md:grid-cols-6">
|
||||
<div class="m-4 flex md:col-span-2">
|
||||
<RaceLenSlider bind:value={raceLen} />
|
||||
<input
|
||||
class="col-span-2 my-auto w-full justify-self-center-safe"
|
||||
type="range"
|
||||
id="raceLen"
|
||||
min="1000"
|
||||
max="3600"
|
||||
step="100"
|
||||
bind:value={raceLen}
|
||||
/>
|
||||
<span class="my-auto pl-2 text-sm">{raceLen}m</span>
|
||||
</div>
|
||||
<select id="surface" class="m-4" bind:value={surface}>
|
||||
<option value={race.Surface.Turf}>Turf</option>
|
||||
|
||||
Reference in New Issue
Block a user