handle new umadump output shapes

This commit is contained in:
2026-07-29 15:19:17 -04:00
parent 6864472fdd
commit f5d102718d
7 changed files with 10685 additions and 805 deletions
+219 -22
View File
@@ -1,14 +1,35 @@
package main
import "git.sunturtle.xyz/zephyr/horse"
import (
"bytes"
"encoding/json"
"io"
"time"
"git.sunturtle.xyz/zephyr/horse"
)
type SupportCardID int32 // package horse doesn't have this yet
type OldWorkSingleIdleMode struct {
Chara SingleModeChara `json:"charaInfo"`
StartTime int64 `json:"startTime"`
EndTime int64 `json:"endTime"`
ProgressLog OldIdleSingleModeProgressLog `json:"progressLogInfo"`
}
type ProgressInfo struct {
Chara SingleModeChara `json:"chara_info"`
StartTime string `json:"start_time"`
EndTime string `json:"end_time"`
DressID int32 `json:"dress_id"`
}
type WorkIdleSingleMode struct {
Chara SingleModeChara `json:"charaInfo"`
StartTime int64 `json:"startTime"`
EndTime int64 `json:"endTime"`
ProgressLog IdleSingleModeProgressLog `json:"progressLogInfo"`
ProgressInfo ProgressInfo `json:"progress_info"`
ProgressLog IdleSingleModeProgressLog `json:"progress_log_info"`
End End `json:"end_info"`
OldChara *SingleModeChara `json:"chara_info"`
}
type Skill struct {
@@ -40,6 +61,7 @@ type GroupOuting struct {
type Evaluation struct {
TargetID int32 `json:"target_id"`
TrainingPartner int32 `json:"training_partner_id"`
Evaluation int32 `json:"evaluation"`
IsOuting int32 `json:"is_outing"`
StoryStep int32 `json:"story_step"`
@@ -126,17 +148,22 @@ type SingleModeChara struct {
SkillUpgrades []SingleModeSkillUpgrade `json:"skill_upgrade_info_array"`
}
type CharaEffectLog struct {
type OldCharaEffectLog struct {
CharaEffectID int32 `json:"charaEffectId"`
IsActive bool `json:"isActive"`
}
type CharaEffectLog struct {
CharaEffectID int32 `json:"chara_effect_id"`
IsActive bool `json:"is_active"`
}
type IdleSingleModeSignedInt struct {
Sign int32 `json:"sign"`
Value int32 `json:"value"`
}
type IdleSingleModeGainInfo struct {
type OldIdleSingleModeGainInfo struct {
Speed IdleSingleModeSignedInt `json:"speed"`
Stamina IdleSingleModeSignedInt `json:"stamina"`
Power IdleSingleModeSignedInt `json:"power"`
@@ -161,19 +188,59 @@ type IdleSingleModeGainInfo struct {
SkillTips []SkillTip `json:"skillTips"`
}
type IdleSingleModeSupportCardGain struct {
SupportCardID SupportCardID `json:"supportCardId"`
GainInfo IdleSingleModeGainInfo `json:"gainInfo"`
type IdleSingleModeGainInfo struct {
Speed IdleSingleModeSignedInt `json:"speed"`
Stamina IdleSingleModeSignedInt `json:"stamina"`
Power IdleSingleModeSignedInt `json:"power"`
Wiz IdleSingleModeSignedInt `json:"wiz"`
Guts IdleSingleModeSignedInt `json:"guts"`
MaxSpeed int32 `json:"max_speed"`
MaxStamina int32 `json:"max_stamina"`
MaxPower int32 `json:"max_power"`
MaxWiz int32 `json:"max_wiz"`
MaxGuts int32 `json:"max_guts"`
ProperDistanceShort horse.AptitudeLevel `json:"proper_distance_short"`
ProperDistanceMile horse.AptitudeLevel `json:"proper_distance_mile"`
ProperDistanceMiddle horse.AptitudeLevel `json:"proper_distance_middle"`
ProperDistanceLong horse.AptitudeLevel `json:"proper_distance_long"`
ProperRunningStyleNige horse.AptitudeLevel `json:"proper_running_style_nige"`
ProperRunningStyleSenko horse.AptitudeLevel `json:"proper_running_style_senko"`
ProperRunningStyleSashi horse.AptitudeLevel `json:"proper_running_style_sashi"`
ProperRunningStyleOikomi horse.AptitudeLevel `json:"proper_running_style_oikomi"`
ProperGroundTurf horse.AptitudeLevel `json:"proper_ground_turf"`
ProperGroundDirt horse.AptitudeLevel `json:"proper_ground_dirt"`
SkillPoint int32 `json:"skill_point"`
SkillTips []SkillTip `json:"skill_tips_array"`
}
type Factor struct {
type OldIdleSingleModeSupportCardGain struct {
SupportCardID SupportCardID `json:"supportCardId"`
GainInfo OldIdleSingleModeGainInfo `json:"gainInfo"`
}
type IdleSingleModeSupportCardGain struct {
SupportCardID SupportCardID `json:"support_card_id"`
GainInfo IdleSingleModeGainInfo `json:"gain_info"`
}
type OldFactor struct {
FactorID horse.SparkID `json:"factorId"`
Level int32 `json:"level"`
}
type Factor struct {
FactorID horse.SparkID `json:"factor_id"`
Level int32 `json:"level"`
}
type OldIdleSingleModeSuccessionFactorGain struct {
Year int32 `json:"year"`
GainFactorInfo []OldFactor `json:"gainFactorInfoArray"`
}
type IdleSingleModeSuccessionFactorGain struct {
Year int32 `json:"year"`
GainFactorInfo []Factor `json:"gainFactorInfoArray"`
GainFactorInfo []Factor `json:"gain_factor_info_array"`
}
type SingleRaceHistory struct {
@@ -184,7 +251,7 @@ type SingleRaceHistory struct {
RunningStyle int32 `json:"running_style"`
ResultRank int32 `json:"result_rank"`
FrameOrder int32 `json:"frame_order"`
NpcCount int32 `json:"npc_count"`
NPCCount int32 `json:"npc_count"`
}
type RaceReward struct {
@@ -219,13 +286,143 @@ type IdleSingleModeRaceHistory struct {
LoseTipsID int32 `json:"lose_tips_id"`
}
type IdleSingleModeProgressLog struct {
CharaEffectLog []CharaEffectLog `json:"charaEffectLog"`
SupportCardGains []IdleSingleModeSupportCardGain `json:"supportCardGainInfo"`
EventGain IdleSingleModeGainInfo `json:"eventGainInfo"`
SuccessionGain IdleSingleModeGainInfo `json:"successionGainInfo"`
SuccessionFactorGains []IdleSingleModeSuccessionFactorGain `json:"successionFactorGainArray"`
RaceHistory []IdleSingleModeRaceHistory `json:"raceHistoryArray"`
GainSkillIDs []horse.SkillID `json:"gainSkillIdArray"`
TotalSkillPoint int32 `json:"totalSkillPoint"`
type OldIdleSingleModeProgressLog struct {
CharaEffectLog []OldCharaEffectLog `json:"charaEffectLog"`
SupportCardGains []OldIdleSingleModeSupportCardGain `json:"supportCardGainInfo"`
EventGain OldIdleSingleModeGainInfo `json:"eventGainInfo"`
SuccessionGain OldIdleSingleModeGainInfo `json:"successionGainInfo"`
SuccessionFactorGains []OldIdleSingleModeSuccessionFactorGain `json:"successionFactorGainArray"`
RaceHistory []IdleSingleModeRaceHistory `json:"raceHistoryArray"`
GainSkillIDs []horse.SkillID `json:"gainSkillIdArray"`
TotalSkillPoint int32 `json:"totalSkillPoint"`
}
type IdleSingleModeProgressLog struct {
CharaEffectLog []CharaEffectLog `json:"chara_effect_log_array"`
SupportCardGains []IdleSingleModeSupportCardGain `json:"support_card_gain_info_array"`
EventGain IdleSingleModeGainInfo `json:"event_gain_info"`
SuccessionGain IdleSingleModeGainInfo `json:"succession_gain_info"`
SuccessionFactorGains []IdleSingleModeSuccessionFactorGain `json:"succession_factor_gain_array"`
RaceHistory []IdleSingleModeRaceHistory `json:"race_history_array"`
GainSkillIDs []horse.SkillID `json:"gain_skill_id_array"`
TotalSkillPoint int32 `json:"total_skill_point"`
}
type AddItem struct {
ItemID int32 `json:"item_id"`
Number int32 `json:"number"`
}
type RewardSummary struct {
AddItem []AddItem `json:"add_item_list"`
}
type End struct {
Chara SingleModeChara `json:"chara_info"`
CharaButWerseterIsOverworked *SingleModeChara `json:"chara_starting_info"`
RewardSummary RewardSummary `json:"reward_summary_info"`
}
func loadISM(r io.Reader) (WorkIdleSingleMode, error) {
// Since we have two potential types to read at the top level,
// decode one message and try it both ways.
var b json.RawMessage
var err error
if err = json.NewDecoder(r).Decode(&b); err != nil {
return WorkIdleSingleMode{}, err
}
{
var ism WorkIdleSingleMode
d := json.NewDecoder(bytes.NewReader(b))
d.DisallowUnknownFields()
err = d.Decode(&ism)
if err == nil {
// NOTE(zeph): this is for no error
// If old fields are populated, move them to the correct ones.
if ism.End.CharaButWerseterIsOverworked != nil {
ism.End.Chara = *ism.End.CharaButWerseterIsOverworked
ism.End.CharaButWerseterIsOverworked = nil
}
if ism.OldChara != nil {
ism.ProgressInfo.Chara = *ism.OldChara
ism.OldChara = nil
}
return ism, nil
}
}
{
var ism OldWorkSingleIdleMode
d := json.NewDecoder(bytes.NewReader(b))
d.DisallowUnknownFields()
// Use a new error variable here.
// If this fails, we want to return the reason we didn't use the API type instead.
if err := d.Decode(&ism); err == nil {
// NOTE(zeph): this is for no error
return unold(ism), nil
}
}
// NOTE(zeph): this is the error from decoding the API type, not the validation type.
return WorkIdleSingleMode{}, err
}
func unold(old OldWorkSingleIdleMode) WorkIdleSingleMode {
return WorkIdleSingleMode{
ProgressInfo: ProgressInfo{
Chara: old.Chara,
StartTime: time.Unix(old.StartTime, 0).Format(time.DateTime),
EndTime: time.Unix(old.EndTime, 0).Format(time.DateTime),
},
ProgressLog: IdleSingleModeProgressLog{
CharaEffectLog: unoldEffects(old.ProgressLog.CharaEffectLog),
SupportCardGains: unoldCardGains(old.ProgressLog.SupportCardGains),
EventGain: IdleSingleModeGainInfo(old.ProgressLog.EventGain),
SuccessionGain: IdleSingleModeGainInfo(old.ProgressLog.SuccessionGain),
SuccessionFactorGains: unoldFactorGains(old.ProgressLog.SuccessionFactorGains),
RaceHistory: old.ProgressLog.RaceHistory,
GainSkillIDs: old.ProgressLog.GainSkillIDs,
TotalSkillPoint: old.ProgressLog.TotalSkillPoint,
},
// We could try to roll up starting numbers plus gains,
// but only a few of these files exist anyway.
// Not worth the effort.
End: End{},
}
}
func unoldEffects(olds []OldCharaEffectLog) []CharaEffectLog {
new := make([]CharaEffectLog, len(olds))
for i, old := range olds {
new[i] = CharaEffectLog(old)
}
return new
}
func unoldCardGains(olds []OldIdleSingleModeSupportCardGain) []IdleSingleModeSupportCardGain {
new := make([]IdleSingleModeSupportCardGain, len(olds))
for i, old := range olds {
new[i] = IdleSingleModeSupportCardGain{
SupportCardID: old.SupportCardID,
GainInfo: IdleSingleModeGainInfo(old.GainInfo),
}
}
return new
}
func unoldFactorGains(olds []OldIdleSingleModeSuccessionFactorGain) []IdleSingleModeSuccessionFactorGain {
new := make([]IdleSingleModeSuccessionFactorGain, len(olds))
for i, old := range olds {
new[i] = IdleSingleModeSuccessionFactorGain{
Year: old.Year,
GainFactorInfo: unoldFactors(old.GainFactorInfo),
}
}
return new
}
func unoldFactors(olds []OldFactor) []Factor {
new := make([]Factor, len(olds))
for i, old := range olds {
new[i] = Factor(old)
}
return new
}
+4761 -776
View File
File diff suppressed because it is too large Load Diff
+2 -5
View File
@@ -3,7 +3,6 @@ package main
import (
"bufio"
"encoding/csv"
"encoding/json"
"flag"
"log/slog"
"os"
@@ -46,10 +45,8 @@ func dofile(w *csv.Writer, name string) {
}
defer f.Close()
var ism WorkIdleSingleMode
d := json.NewDecoder(f)
d.DisallowUnknownFields()
if err := d.Decode(&ism); err != nil {
ism, err := loadISM(f)
if err != nil {
log.Error("decode", slog.Any("err", err))
return
}
+2 -2
View File
@@ -69,8 +69,8 @@ func ismRows(key string, ism WorkIdleSingleMode) iter.Seq[Row] {
}
row := Row{
File: key,
Scenario: int(ism.Chara.ScenarioID),
Character: int(ism.Chara.CardID),
Scenario: int(ism.ProgressInfo.Chara.ScenarioID),
Character: int(ism.ProgressInfo.Chara.CardID),
Deck1: int(pl.SupportCardGains[0].SupportCardID),
Deck2: int(pl.SupportCardGains[1].SupportCardID),
Deck3: int(pl.SupportCardGains[2].SupportCardID),
View File
+2808
View File
File diff suppressed because it is too large Load Diff
+2893
View File
File diff suppressed because it is too large Load Diff