Compare commits

...

2 Commits

Author SHA1 Message Date
zephyr 8b315680b3 add readme 2026-07-28 01:45:20 -04:00
zephyr a2337732ee include scenario and character 2026-07-28 01:45:03 -04:00
3 changed files with 48 additions and 26 deletions
+15
View File
@@ -0,0 +1,15 @@
# ismdata
Reduce [Umadump](https://github.com/Werseter/umadump/releases)'s idle single mode (Independent Training) outputs to CSV for analysis.
Open Umadump's idle_single_mode folder, select all files with Ctrl+A, and drag and drop the files onto ismdata.exe to create idle_single_mode.csv.
Alternatively, run ismdata in the command line with the filenames to process as arguments.
When using it this way, `-o <output.csv>` can be provided to change the output file.
Stdout is not supported.
## CSV Contents
The output CSV has a header row followed by eight rows per input career dump.
Each row gives the stat gains from one respective source, along with distinctive information per career: scenario, full deck, race count and wins, and negative and positive conditions.
The `GainSource` column is `Events`, `Inspiration`, or a support card ID.
+1 -1
View File
@@ -53,7 +53,7 @@ func dofile(w *csv.Writer, name string) {
return return
} }
for row := range ismRows(name, ism.ProgressLog) { for row := range ismRows(name, ism) {
if err := w.Write(row.csv()); err != nil { if err := w.Write(row.csv()); err != nil {
log.Error("write row", slog.Any("err", err)) log.Error("write row", slog.Any("err", err))
} }
+32 -25
View File
@@ -17,6 +17,8 @@ type Row struct {
Wit int Wit int
SP int SP int
NumSkills int NumSkills int
Scenario int
Character int
Deck1 int Deck1 int
Deck2 int Deck2 int
Deck3 int Deck3 int
@@ -47,17 +49,18 @@ func init() {
} }
} }
func ismRows(key string, ism IdleSingleModeProgressLog) iter.Seq[Row] { func ismRows(key string, ism WorkIdleSingleMode) iter.Seq[Row] {
return func(yield func(Row) bool) { return func(yield func(Row) bool) {
races := len(ism.RaceHistory) pl := ism.ProgressLog
races := len(pl.RaceHistory)
var wins int var wins int
for _, r := range ism.RaceHistory { for _, r := range pl.RaceHistory {
if r.RaceHistory.ResultRank == 1 { if r.RaceHistory.ResultRank == 1 {
wins++ wins++
} }
} }
var conditions [11]bool var conditions [11]bool
for _, v := range ism.CharaEffectLog { for _, v := range pl.CharaEffectLog {
if v.CharaEffectID < 1 || v.CharaEffectID > 11 { if v.CharaEffectID < 1 || v.CharaEffectID > 11 {
slog.Warn("skipping unknown charaEffectID", slog.Int("id", int(v.CharaEffectID)), slog.Bool("active", v.IsActive)) slog.Warn("skipping unknown charaEffectID", slog.Int("id", int(v.CharaEffectID)), slog.Bool("active", v.IsActive))
continue continue
@@ -66,12 +69,14 @@ func ismRows(key string, ism IdleSingleModeProgressLog) iter.Seq[Row] {
} }
row := Row{ row := Row{
File: key, File: key,
Deck1: int(ism.SupportCardGains[0].SupportCardID), Scenario: int(ism.Chara.ScenarioID),
Deck2: int(ism.SupportCardGains[1].SupportCardID), Character: int(ism.Chara.CardID),
Deck3: int(ism.SupportCardGains[2].SupportCardID), Deck1: int(pl.SupportCardGains[0].SupportCardID),
Deck4: int(ism.SupportCardGains[3].SupportCardID), Deck2: int(pl.SupportCardGains[1].SupportCardID),
Deck5: int(ism.SupportCardGains[4].SupportCardID), Deck3: int(pl.SupportCardGains[2].SupportCardID),
Deck6: int(ism.SupportCardGains[5].SupportCardID), Deck4: int(pl.SupportCardGains[3].SupportCardID),
Deck5: int(pl.SupportCardGains[4].SupportCardID),
Deck6: int(pl.SupportCardGains[5].SupportCardID),
Races: races, Races: races,
Wins: wins, Wins: wins,
NightOwl: conditions[0], NightOwl: conditions[0],
@@ -88,30 +93,30 @@ func ismRows(key string, ism IdleSingleModeProgressLog) iter.Seq[Row] {
} }
row.GainSource = "Events" row.GainSource = "Events"
row.Speed = int(ism.EventGain.Speed.Value) row.Speed = int(pl.EventGain.Speed.Value)
row.Stamina = int(ism.EventGain.Stamina.Value) row.Stamina = int(pl.EventGain.Stamina.Value)
row.Power = int(ism.EventGain.Power.Value) row.Power = int(pl.EventGain.Power.Value)
row.Guts = int(ism.EventGain.Guts.Value) row.Guts = int(pl.EventGain.Guts.Value)
row.Wit = int(ism.EventGain.Wiz.Value) row.Wit = int(pl.EventGain.Wiz.Value)
row.SP = int(ism.EventGain.SkillPoint) row.SP = int(pl.EventGain.SkillPoint)
row.NumSkills = len(ism.EventGain.SkillTips) row.NumSkills = len(pl.EventGain.SkillTips)
if !yield(row) { if !yield(row) {
return return
} }
row.GainSource = "Inspiration" row.GainSource = "Inspiration"
row.Speed = int(ism.SuccessionGain.Speed.Value) row.Speed = int(pl.SuccessionGain.Speed.Value)
row.Stamina = int(ism.SuccessionGain.Stamina.Value) row.Stamina = int(pl.SuccessionGain.Stamina.Value)
row.Power = int(ism.SuccessionGain.Power.Value) row.Power = int(pl.SuccessionGain.Power.Value)
row.Guts = int(ism.SuccessionGain.Guts.Value) row.Guts = int(pl.SuccessionGain.Guts.Value)
row.Wit = int(ism.SuccessionGain.Wiz.Value) row.Wit = int(pl.SuccessionGain.Wiz.Value)
row.SP = int(ism.SuccessionGain.SkillPoint) row.SP = int(pl.SuccessionGain.SkillPoint)
row.NumSkills = len(ism.SuccessionGain.SkillTips) row.NumSkills = len(pl.SuccessionGain.SkillTips)
if !yield(row) { if !yield(row) {
return return
} }
for _, sup := range ism.SupportCardGains { for _, sup := range pl.SupportCardGains {
row.GainSource = strconv.Itoa(int(sup.SupportCardID)) row.GainSource = strconv.Itoa(int(sup.SupportCardID))
row.Speed = int(sup.GainInfo.Speed.Value) row.Speed = int(sup.GainInfo.Speed.Value)
row.Stamina = int(sup.GainInfo.Stamina.Value) row.Stamina = int(sup.GainInfo.Stamina.Value)
@@ -138,6 +143,8 @@ func (r Row) csv() []string {
strconv.Itoa(r.Wit), strconv.Itoa(r.Wit),
strconv.Itoa(r.SP), strconv.Itoa(r.SP),
strconv.Itoa(r.NumSkills), strconv.Itoa(r.NumSkills),
strconv.Itoa(r.Scenario),
strconv.Itoa(r.Character),
strconv.Itoa(r.Deck1), strconv.Itoa(r.Deck1),
strconv.Itoa(r.Deck2), strconv.Itoa(r.Deck2),
strconv.Itoa(r.Deck3), strconv.Itoa(r.Deck3),