2 Commits
Author SHA1 Message Date
zephyr 9f758fcbe5 cmd/ismdb: start work 2026-10-21 22:33:43 -04:00
zephyr 7f1aa00be6 horse: update dependencies and go version
ci/woodpecker/push/zenno Pipeline failed
ci/woodpecker/push/horsebot Pipeline failed
2026-10-21 10:18:55 -04:00
7 changed files with 679 additions and 53 deletions
+188
View File
@@ -0,0 +1,188 @@
package main
import (
"context"
_ "embed"
"errors"
"fmt"
"log/slog"
"zombiezen.com/go/sqlite"
"zombiezen.com/go/sqlite/sqlitemigration"
"zombiezen.com/go/sqlite/sqlitex"
"git.sunturtle.xyz/zephyr/horse/umadump/ism"
)
const appID int32 = 0x4acedb
//go:embed schema-00.sql
var schema0 string
//go:embed schema-final.sql
var schemaFinal string
func opendb(uri, journalMode string) *sqlitemigration.Pool {
schema := sqlitemigration.Schema{
Migrations: []string{
schema0,
},
AppID: appID,
RepeatableMigration: schemaFinal,
}
j := "PRAGMA journal_mode=" + journalMode
opts := sqlitemigration.Options{
Flags: sqlite.OpenReadWrite | sqlite.OpenCreate | sqlite.OpenURI,
PrepareConn: func(conn *sqlite.Conn) error {
if journalMode == "" {
return nil
}
stmt, _, err := conn.PrepareTransient(j)
if err != nil {
return err
}
_, err = stmt.Step()
return errors.Join(err, stmt.Finalize())
},
}
db := sqlitemigration.NewPool(uri, schema, opts)
return db
}
func insert(ctx context.Context, db *sqlitemigration.Pool, log *slog.Logger, career *ism.WorkIdleSingleMode, trainerID int64) (err error) {
conn, err := db.Take(ctx)
if err != nil {
return err
}
defer db.Put(conn)
defer sqlitex.Transaction(conn)(&err)
}
//go:embed insert-career.sql
var insertCareerSQL string
func insertCareer(conn *sqlite.Conn, career *ism.WorkIdleSingleMode, trainerID int64) error {
stmt := conn.Prep(insertCareerSQL)
stmt.SetInt64("$trainer_id", trainerID)
stmt.SetInt64("$trained_chara_id", int64(career.End.Chara.SingleModeCharaID))
stmt.SetInt64("$card_id", int64(career.End.Chara.CardID))
stmt.SetInt64("$scenario_id", int64(career.End.Chara.ScenarioID))
stmt.SetInt64("$route_id", int64(career.End.Chara.RouteID))
stmt.SetText("$start_time", career.ProgressInfo.StartTime)
stmt.SetText("$end_time", career.ProgressInfo.EndTime)
stmt.SetInt64("$chara_grade", int64(career.End.Chara.CharaGrade))
stmt.SetInt64("$star_level", int64(career.End.Chara.Rarity))
stmt.SetInt64("$potential_level", int64(career.End.Chara.TalentLevel))
stmt.SetInt64("$speed", int64(career.End.Chara.Speed))
stmt.SetInt64("$stamina", int64(career.End.Chara.Stamina))
stmt.SetInt64("$power", int64(career.End.Chara.Power))
stmt.SetInt64("$guts", int64(career.End.Chara.Guts))
stmt.SetInt64("$wit", int64(career.End.Chara.Wiz))
stmt.SetInt64("$energy", int64(career.End.Chara.Vital))
stmt.SetInt64("$max_speed", int64(career.End.Chara.MaxSpeed))
stmt.SetInt64("$max_stamina", int64(career.End.Chara.MaxStamina))
stmt.SetInt64("$max_power", int64(career.End.Chara.MaxPower))
stmt.SetInt64("$max_guts", int64(career.End.Chara.MaxGuts))
stmt.SetInt64("$max_wit", int64(career.End.Chara.MaxWiz))
stmt.SetInt64("$max_energy", int64(career.End.Chara.MaxVital))
stmt.SetInt64("$skill_point", int64(career.ProgressLog.TotalSkillPoint))
stmt.SetInt64("$mood", int64(career.End.Chara.Motivation))
stmt.SetInt64("$turf", int64(career.End.Chara.ProperGroundTurf))
stmt.SetInt64("$dirt", int64(career.End.Chara.ProperGroundDirt))
stmt.SetInt64("$sprint", int64(career.End.Chara.ProperDistanceShort))
stmt.SetInt64("$mile", int64(career.End.Chara.ProperDistanceMile))
stmt.SetInt64("$medium", int64(career.End.Chara.ProperDistanceMiddle))
stmt.SetInt64("$long", int64(career.End.Chara.ProperDistanceLong))
stmt.SetInt64("$front_runner", int64(career.End.Chara.ProperRunningStyleNige))
stmt.SetInt64("$pace_chaser", int64(career.End.Chara.ProperRunningStyleSenko))
stmt.SetInt64("$late_surger", int64(career.End.Chara.ProperRunningStyleSashi))
stmt.SetInt64("$end_closer", int64(career.End.Chara.ProperRunningStyleOikomi))
stmt.SetInt64("$start_speed", int64(career.ProgressInfo.Chara.Speed))
stmt.SetInt64("$start_stamina", int64(career.ProgressInfo.Chara.Stamina))
stmt.SetInt64("$start_power", int64(career.ProgressInfo.Chara.Power))
stmt.SetInt64("$start_guts", int64(career.ProgressInfo.Chara.Guts))
stmt.SetInt64("$start_wit", int64(career.ProgressInfo.Chara.Wiz))
stmt.SetInt64("$start_max_speed", int64(career.ProgressInfo.Chara.MaxSpeed))
stmt.SetInt64("$start_max_stamina", int64(career.ProgressInfo.Chara.MaxStamina))
stmt.SetInt64("$start_max_power", int64(career.ProgressInfo.Chara.MaxPower))
stmt.SetInt64("$start_max_guts", int64(career.ProgressInfo.Chara.MaxGuts))
stmt.SetInt64("$start_max_wit", int64(career.ProgressInfo.Chara.MaxWiz))
stmt.SetInt64("$start_turf", int64(career.ProgressInfo.Chara.ProperGroundTurf))
stmt.SetInt64("$start_dirt", int64(career.ProgressInfo.Chara.ProperGroundDirt))
stmt.SetInt64("$start_sprint", int64(career.ProgressInfo.Chara.ProperDistanceShort))
stmt.SetInt64("$start_mile", int64(career.ProgressInfo.Chara.ProperDistanceMile))
stmt.SetInt64("$start_medium", int64(career.ProgressInfo.Chara.ProperDistanceMiddle))
stmt.SetInt64("$start_long", int64(career.ProgressInfo.Chara.ProperDistanceLong))
stmt.SetInt64("$start_front_runner", int64(career.ProgressInfo.Chara.ProperRunningStyleNige))
stmt.SetInt64("$start_pace_chaser", int64(career.ProgressInfo.Chara.ProperRunningStyleSenko))
stmt.SetInt64("$start_late_surger", int64(career.ProgressInfo.Chara.ProperRunningStyleSashi))
stmt.SetInt64("$start_end_closer", int64(career.ProgressInfo.Chara.ProperRunningStyleOikomi))
stmt.SetInt64("$fans", int64(career.End.Chara.Fans))
stmt.SetInt64("$race_program_id", int64(career.End.Chara.RaceProgramID))
stmt.SetInt64("$reserve_race_program_id", int64(career.End.Chara.ReserveRaceProgramID))
stmt.SetInt64("$race_running_style", int64(career.End.Chara.RaceRunningStyle))
stmt.SetInt64("$is_short_race", int64(career.End.Chara.IsShortRace))
stmt.SetInt64("$succession_trained_chara_id_1", int64(career.OldChara.SuccessionTrainedCharaID1))
stmt.SetInt64("$succession_trained_chara_id_2", int64(career.OldChara.SuccessionTrainedCharaID2))
_, err := stmt.Step()
err = errors.Join(err, stmt.Reset())
if err != nil {
return fmt.Errorf("inserting race course: %w", err)
}
return nil
}
func insertConditions(conn *sqlite.Conn, cs []ism.CharaEffectLog, trainerID int64, trainedChara int32) error {
const sql = `INSERT INTO condition VALUES (?, ?, ?, ?)`
stmt := conn.Prep(sql)
stmt.BindInt64(1, trainerID)
stmt.BindInt64(2, int64(trainedChara))
for _, c := range cs {
stmt.BindInt64(3, int64(c.CharaEffectID))
stmt.BindBool(4, c.IsActive)
_, err := stmt.Step()
err = errors.Join(err, stmt.Reset())
if err != nil {
return fmt.Errorf("inserting condition: %w", err)
}
}
return nil
}
//go:embed insert-gain.sql
var insertGainSQL string
func insertGain(conn *sqlite.Conn, gain *ism.IdleSingleModeGainInfo, trainerID int64, trainedChara int32, source int32) error {
stmt := conn.Prep(insertGainSQL)
stmt.SetInt64("$trainer_id", trainerID)
stmt.SetInt64("$trained_chara_id", int64(trainedChara))
stmt.SetInt64("$source", int64(source))
stmt.SetInt64("$gain_speed", int64(gain.Speed.Value))
stmt.SetInt64("$gain_stamina", int64(gain.Stamina.Value))
stmt.SetInt64("$gain_power", int64(gain.Power.Value))
stmt.SetInt64("$gain_guts", int64(gain.Guts.Value))
stmt.SetInt64("$gain_wit", int64(gain.Wiz.Value))
stmt.SetInt64("$gain_skill_point", int64(gain.SkillPoint))
stmt.SetInt64("$gain_max_speed", int64(gain.MaxSpeed))
stmt.SetInt64("$gain_max_stamina", int64(gain.MaxStamina))
stmt.SetInt64("$gain_max_power", int64(gain.MaxPower))
stmt.SetInt64("$gain_max_guts", int64(gain.MaxGuts))
stmt.SetInt64("$gain_max_wit", int64(gain.MaxWiz))
stmt.SetInt64("$gain_turf", int64(gain.ProperGroundTurf))
stmt.SetInt64("$gain_dirt", int64(gain.ProperGroundDirt))
stmt.SetInt64("$gain_sprint", int64(gain.ProperDistanceShort))
stmt.SetInt64("$gain_mile", int64(gain.ProperDistanceMile))
stmt.SetInt64("$gain_medium", int64(gain.ProperDistanceMiddle))
stmt.SetInt64("$gain_long", int64(gain.ProperDistanceLong))
stmt.SetInt64("$gain_front_runner", int64(gain.ProperRunningStyleNige))
stmt.SetInt64("$gain_pace_chaser", int64(gain.ProperRunningStyleSenko))
stmt.SetInt64("$gain_late_surger", int64(gain.ProperRunningStyleSashi))
stmt.SetInt64("$gain_end_closer", int64(gain.ProperRunningStyleOikomi))
_, err := stmt.Step()
err = errors.Join(err, stmt.Reset())
if err != nil {
return fmt.Errorf("inserting gain info: %w", err)
}
return nil
}
+69
View File
@@ -0,0 +1,69 @@
INSERT INTO career VALUES (
$trainer_id,
$trained_chara_id,
$card_id,
$scenario_id,
$route_id,
$start_time,
$end_time,
$chara_grade,
$star_level,
$potential_level,
$speed,
$stamina,
$power,
$guts,
$wit,
$energy,
$max_speed,
$max_stamina,
$max_power,
$max_guts,
$max_wit,
$max_energy,
$skill_point,
$mood,
$turf,
$dirt,
$sprint,
$mile,
$medium,
$long,
$front_runner,
$pace_chaser,
$late_surger,
$end_closer,
$start_speed,
$start_stamina,
$start_power,
$start_guts,
$start_wit,
$start_max_speed,
$start_max_stamina,
$start_max_power,
$start_max_guts,
$start_max_wit,
$start_turf,
$start_dirt,
$start_sprint,
$start_mile,
$start_medium,
$start_long,
$start_front_runner,
$start_pace_chaser,
$start_late_surger,
$start_end_closer,
$fans,
$race_program_id,
$reserve_race_program_id,
$race_running_style,
$is_short_race,
$succession_trained_chara_id_1,
$succession_trained_chara_id_2
)
+31
View File
@@ -0,0 +1,31 @@
INSERT INTO gain VALUES (
$trainer_id,
$trained_chara_id,
$source,
$gain_speed,
$gain_stamina,
$gain_power,
$gain_guts,
$gain_wit,
$gain_skill_point,
$gain_max_speed,
$gain_max_stamina,
$gain_max_power,
$gain_max_guts,
$gain_max_wit,
$gain_turf,
$gain_dirt,
$gain_sprint,
$gain_mile,
$gain_medium,
$gain_long,
$gain_front_runner,
$gain_pace_chaser,
$gain_late_surger,
$gain_end_closer
)
+251
View File
@@ -0,0 +1,251 @@
CREATE TABLE IF NOT EXISTS career (
trainer_id INTEGER NOT NULL DEFAULT 0,
trained_chara_id INTEGER NOT NULL,
card_id INTEGER NOT NULL,
scenario_id INTEGER NOT NULL,
route_id INTEGER NOT NULL,
start_time TEXT NOT NULL,
end_time TEXT NOT NULL,
chara_grade INTEGER NOT NULL,
star_level INTEGER NOT NULL,
potential_level INTEGER NOT NULL,
speed INTEGER NOT NULL,
stamina INTEGER NOT NULL,
power INTEGER NOT NULL,
guts INTEGER NOT NULL,
wit INTEGER NOT NULL,
energy INTEGER NOT NULL,
max_speed INTEGER NOT NULL,
max_stamina INTEGER NOT NULL,
max_power INTEGER NOT NULL,
max_guts INTEGER NOT NULL,
max_wit INTEGER NOT NULL,
max_energy INTEGER NOT NULL,
skill_point INTEGER NOT NULL,
mood INTEGER NOT NULL,
turf INTEGER NOT NULL,
dirt INTEGER NOT NULL,
sprint INTEGER NOT NULL,
mile INTEGER NOT NULL,
medium INTEGER NOT NULL,
long INTEGER NOT NULL,
front_runner INTEGER NOT NULL,
pace_chaser INTEGER NOT NULL,
late_surger INTEGER NOT NULL,
end_closer INTEGER NOT NULL,
-- These fields are 0 if the career finished while it was not actively
-- displayed on the client used to dump it.
start_speed INTEGER NOT NULL,
start_stamina INTEGER NOT NULL,
start_power INTEGER NOT NULL,
start_guts INTEGER NOT NULL,
start_wit INTEGER NOT NULL,
start_max_speed INTEGER NOT NULL,
start_max_stamina INTEGER NOT NULL,
start_max_power INTEGER NOT NULL,
start_max_guts INTEGER NOT NULL,
start_max_wit INTEGER NOT NULL,
start_turf INTEGER NOT NULL,
start_dirt INTEGER NOT NULL,
start_sprint INTEGER NOT NULL,
start_mile INTEGER NOT NULL,
start_medium INTEGER NOT NULL,
start_long INTEGER NOT NULL,
start_front_runner INTEGER NOT NULL,
start_pace_chaser INTEGER NOT NULL,
start_late_surger INTEGER NOT NULL,
start_end_closer INTEGER NOT NULL,
fans INTEGER NOT NULL,
race_program_id INTEGER NOT NULL,
reserve_race_program_id INTEGER NOT NULL,
race_running_style INTEGER NOT NULL,
is_short_race INTEGER NOT NULL,
succession_trained_chara_id_1 INTEGER NOT NULL,
succession_trained_chara_id_2 INTEGER NOT NULL,
PRIMARY KEY (trainer_id, trained_chara_id)
) STRICT;
CREATE INDEX IF NOT EXISTS career_by_scenario ON career (scenario_id);
CREATE INDEX IF NOT EXISTS career_by_start_time ON career (start_time);
CREATE TABLE IF NOT EXISTS condition (
trainer_id INTEGER NOT NULL DEFAULT 0,
trained_chara_id INTEGER NOT NULL,
condition INTEGER NOT NULL,
is_active INTEGER NOT NULL,
PRIMARY KEY (trainer_id, trained_chara_id, condition),
FOREIGN KEY (trainer_id, trained_chara_id) REFERENCES career ON DELETE CASCADE
) STRICT;
CREATE TABLE IF NOT EXISTS gain (
trainer_id INTEGER NOT NULL DEFAULT 0,
trained_chara_id INTEGER NOT NULL,
source INTEGER NOT NULL, -- 0 for events, 1 for inspiration, otherwise support card id
gain_speed INTEGER NOT NULL,
gain_stamina INTEGER NOT NULL,
gain_power INTEGER NOT NULL,
gain_guts INTEGER NOT NULL,
gain_wit INTEGER NOT NULL,
gain_skill_point INTEGER NOT NULL,
gain_max_speed INTEGER NOT NULL,
gain_max_stamina INTEGER NOT NULL,
gain_max_power INTEGER NOT NULL,
gain_max_guts INTEGER NOT NULL,
gain_max_wit INTEGER NOT NULL,
gain_turf INTEGER NOT NULL,
gain_dirt INTEGER NOT NULL,
gain_sprint INTEGER NOT NULL,
gain_mile INTEGER NOT NULL,
gain_medium INTEGER NOT NULL,
gain_long INTEGER NOT NULL,
gain_front_runner INTEGER NOT NULL,
gain_pace_chaser INTEGER NOT NULL,
gain_late_surger INTEGER NOT NULL,
gain_end_closer INTEGER NOT NULL,
PRIMARY KEY (trainer_id, trained_chara_id, source),
FOREIGN KEY (trainer_id, trained_chara_id) REFERENCES career ON DELETE CASCADE
) STRICT;
CREATE INDEX IF NOT EXISTS gain_by_source ON gain (source);
CREATE TABLE IF NOT EXISTS gain_skill_hint (
trainer_id INTEGER NOT NULL DEFAULT 0,
trained_chara_id INTEGER NOT NULL,
source INTEGER NOT NULL,
group_id INTEGER NOT NULL,
rarity INTEGER NOT NULL,
level INTEGER NOT NULL,
PRIMARY KEY (trainer_id, trained_chara_id, source, group_id, rarity),
FOREIGN KEY (trainer_id, trained_chara_id, source) REFERENCES gain ON DELETE CASCADE
) STRICT;
CREATE TABLE IF NOT EXISTS inspiration (
trainer_id INTEGER NOT NULL DEFAULT 0,
trained_chara_id INTEGER NOT NULL,
year INTEGER NOT NULL,
factor_id INTEGER NOT NULL,
level INTEGER NOT NULL, -- always 0 but just in case we get it in the future
FOREIGN KEY (trainer_id, trained_chara_id) REFERENCES career ON DELETE CASCADE
) STRICT;
CREATE INDEX IF NOT EXISTS inspiration_by_career ON inspiration (trainer_id, trained_chara_id);
CREATE INDEX IF NOT EXISTS inspiration_by_factor_id ON inspiration (factor_id);
CREATE TABLE IF NOT EXISTS race_history (
trainer_id INTEGER NOT NULL DEFAULT 0,
trained_chara_id INTEGER NOT NULL,
turn INTEGER NOT NULL,
program_id INTEGER NOT NULL,
weather INTEGER NOT NULL,
ground_condition INTEGER NOT NULL,
running_style INTEGER NOT NULL,
result_rank INTEGER NOT NULL,
frame_order INTEGER NOT NULL,
gained_fans INTEGER NOT NULL,
lose_tips_id INTEGER NOT NULL,
PRIMARY KEY (trainer_id, trained_chara_id, turn),
FOREIGN KEY (trainer_id, trained_chara_id) REFERENCES career ON DELETE CASCADE
) STRICT;
CREATE TABLE IF NOT EXISTS race_reward (
trainer_id INTEGER NOT NULL DEFAULT 0,
trained_chara_id INTEGER NOT NULL,
turn INTEGER NOT NULL,
item_type INTEGER NOT NULL,
item_id INTEGER NOT NULL,
item_num INTEGER NOT NULL,
is_bonus INTEGER NOT NULL,
is_plus_bonus INTEGER NOT NULL,
is_bonus_win INTEGER NOT NULL,
FOREIGN KEY (trainer_id, trained_chara_id, turn) REFERENCES race_history ON DELETE CASCADE
) STRICT;
CREATE INDEX IF NOT EXISTS race_reward_by_career_turn ON race_reward (trainer_id, trained_chara_id, turn);
CREATE INDEX IF NOT EXISTS race_reward_by_item ON race_reward (item_id);
CREATE TABLE IF NOT EXISTS gain_skill (
trainer_id INTEGER NOT NULL DEFAULT 0,
trained_chara_id INTEGER NOT NULL,
source INTEGER NOT NULL,
skill_id INTEGER NOT NULL,
PRIMARY KEY (trainer_id, trained_chara_id, source, skill_id),
FOREIGN KEY (trainer_id, trained_chara_id, source) REFERENCES gain ON DELETE CASCADE
) STRICT;
CREATE TABLE IF NOT EXISTS career_skill (
trainer_id INTEGER NOT NULL DEFAULT 0,
trained_chara_id INTEGER NOT NULL,
skill_id INTEGER NOT NULL,
level INTEGER NOT NULL,
PRIMARY KEY (trainer_id, trained_chara_id, skill_id),
FOREIGN KEY (trainer_id, trained_chara_id) REFERENCES career ON DELETE CASCADE
) STRICT;
CREATE TABLE IF NOT EXISTS career_skill_hint (
trainer_id INTEGER NOT NULL DEFAULT 0,
trained_chara_id INTEGER NOT NULL,
group_id INTEGER NOT NULL,
rarity INTEGER NOT NULL,
level INTEGER NOT NULL,
PRIMARY KEY (trainer_id, trained_chara_id, group_id, rarity),
FOREIGN KEY (trainer_id, trained_chara_id) REFERENCES career ON DELETE CASCADE
) STRICT;
CREATE TABLE IF NOT EXISTS career_support_card (
trainer_id INTEGER NOT NULL DEFAULT 0,
trained_chara_id INTEGER NOT NULL,
position INTEGER NOT NULL,
support_card_id INTEGER NOT NULL,
limit_break_count INTEGER NOT NULL,
exp INTEGER NOT NULL,
owner_viewer_id INTEGER NOT NULL,
PRIMARY KEY (trainer_id, trained_chara_id, position),
FOREIGN KEY (trainer_id, trained_chara_id) REFERENCES career ON DELETE CASCADE,
UNIQUE (trainer_id, trained_chara_id, support_card_id)
) STRICT;
CREATE INDEX IF NOT EXISTS career_support_card_by_card ON career_support_card (support_card_id, exp);
CREATE TABLE IF NOT EXISTS start_skill (
trainer_id INTEGER NOT NULL DEFAULT 0,
trained_chara_id INTEGER NOT NULL,
skill_id INTEGER NOT NULL,
level INTEGER NOT NULL,
PRIMARY KEY (trainer_id, trained_chara_id, skill_id),
FOREIGN KEY (trainer_id, trained_chara_id) REFERENCES career ON DELETE CASCADE
) STRICT;
CREATE TABLE IF NOT EXISTS start_skill_hint (
trainer_id INTEGER NOT NULL DEFAULT 0,
trained_chara_id INTEGER NOT NULL,
group_id INTEGER NOT NULL,
rarity INTEGER NOT NULL,
level INTEGER NOT NULL,
PRIMARY KEY (trainer_id, trained_chara_id, group_id, rarity),
FOREIGN KEY (trainer_id, trained_chara_id) REFERENCES career ON DELETE CASCADE
) STRICT;
+88
View File
@@ -0,0 +1,88 @@
DROP VIEW IF EXISTS gain_event;
DROP VIEW IF EXISTS gain_inspiration;
DROP VIEW IF EXISTS gain_support_card;
CREATE VIEW gain_event AS
SELECT
trainer_id,
trained_chara_id,
gain_speed,
gain_stamina,
gain_power,
gain_guts,
gain_wit,
gain_skill_point,
gain_max_speed,
gain_max_stamina,
gain_max_power,
gain_max_guts,
gain_max_wit,
gain_turf,
gain_dirt,
gain_sprint,
gain_mile,
gain_medium,
gain_long,
gain_front_runner,
gain_pace_chaser,
gain_late_surger,
gain_end_closer
FROM gain
WHERE source = 0;
CREATE VIEW gain_inspiration AS
SELECT
trainer_id,
trained_chara_id,
gain_speed,
gain_stamina,
gain_power,
gain_guts,
gain_wit,
gain_skill_point,
gain_max_speed,
gain_max_stamina,
gain_max_power,
gain_max_guts,
gain_max_wit,
gain_turf,
gain_dirt,
gain_sprint,
gain_mile,
gain_medium,
gain_long,
gain_front_runner,
gain_pace_chaser,
gain_late_surger,
gain_end_closer
FROM gain
WHERE source = 1;
CREATE VIEW gain_support_card AS
SELECT
trainer_id,
trained_chara_id,
source AS support_card_id,
gain_speed,
gain_stamina,
gain_power,
gain_guts,
gain_wit,
gain_skill_point,
gain_max_speed,
gain_max_stamina,
gain_max_power,
gain_max_guts,
gain_max_wit,
gain_turf,
gain_dirt,
gain_sprint,
gain_mile,
gain_medium,
gain_long,
gain_front_runner,
gain_pace_chaser,
gain_late_surger,
gain_end_closer
FROM gain
WHERE source > 1;
+14 -15
View File
@@ -1,15 +1,15 @@
module git.sunturtle.xyz/zephyr/horse
go 1.25.5
go 1.27.3
require (
github.com/disgoorg/disgo v0.19.6
github.com/gen2brain/avif v0.6.0
github.com/go-chi/chi/v5 v5.3.1
github.com/go-chi/chi/v5 v5.5.0
github.com/google/go-cmp v0.7.0
github.com/junegunn/fzf v0.74.1
golang.org/x/image v0.44.0
golang.org/x/sync v0.22.0
github.com/junegunn/fzf v0.74.5
golang.org/x/image v0.47.0
golang.org/x/sync v0.24.0
zombiezen.com/go/sqlite v1.4.2
)
@@ -18,23 +18,22 @@ require (
github.com/disgoorg/json/v2 v2.0.0 // indirect
github.com/disgoorg/omit v1.0.0 // indirect
github.com/disgoorg/snowflake/v2 v2.0.3 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/ebitengine/purego v0.10.2 // indirect
github.com/dustin/go-humanize v1.1.0 // indirect
github.com/ebitengine/purego v0.11.2 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/junegunn/go-shellwords v0.0.0-20250127100254-2aa3b3277741 // indirect
github.com/klauspost/compress v1.19.1 // indirect
github.com/klauspost/compress v1.20.3 // indirect
github.com/mattn/go-isatty v0.0.24 // indirect
github.com/ncruces/go-strftime v1.0.0 // indirect
github.com/ncruces/go-strftime v1.1.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/sasha-s/go-csync v0.0.0-20240107134140-fcbab37b09ad // indirect
github.com/tetratelabs/wazero v1.12.0 // indirect
golang.org/x/crypto v0.54.0 // indirect
golang.org/x/sys v0.47.0 // indirect
golang.org/x/tools v0.48.0 // indirect
modernc.org/libc v1.74.3 // indirect
golang.org/x/crypto v0.58.0 // indirect
golang.org/x/sys v0.49.0 // indirect
modernc.org/libc v1.79.0 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect
modernc.org/sqlite v1.54.0 // indirect
modernc.org/memory v1.12.1 // indirect
modernc.org/sqlite v1.61.0 // indirect
)
+38 -38
View File
@@ -10,14 +10,14 @@ github.com/disgoorg/omit v1.0.0 h1:y0LkVUOyUHT8ZlnhIAeOZEA22UYykeysK8bLJ0SfT78=
github.com/disgoorg/omit v1.0.0/go.mod h1:RTmSARkf6PWT/UckwI0bV8XgWkWQoPppaT01rYKLcFQ=
github.com/disgoorg/snowflake/v2 v2.0.3 h1:3B+PpFjr7j4ad7oeJu4RlQ+nYOTadsKapJIzgvSI2Ro=
github.com/disgoorg/snowflake/v2 v2.0.3/go.mod h1:W6r7NUA7DwfZLwr00km6G4UnZ0zcoLBRufhkFWgAc4c=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/ebitengine/purego v0.10.2 h1:W809HbnvzAxgdm+aOvlSekrM16wGCdT/e76+9tS7gzE=
github.com/ebitengine/purego v0.10.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/dustin/go-humanize v1.1.0 h1:dbKTrvD0klcbBV/h4AWJdMuZogJACoMlvWIWZ5b2xWg=
github.com/dustin/go-humanize v1.1.0/go.mod h1:hc1CvRkJMsgxqjmjMQF3QNRAZBwY8AXBAzKYoSX9sFI=
github.com/ebitengine/purego v0.11.2 h1:WWiTx8rD8zYdOwSj8O/NiNbsOvSAgJMTlyV1XlbUSeU=
github.com/ebitengine/purego v0.11.2/go.mod h1:DCHPP08djqhNSoTfImcnHYQRZmd0qhakvrozqaEYhGQ=
github.com/gen2brain/avif v0.6.0 h1:/8WSgcU+IEF0jhKYsUZ/mzlziFuTeJFpIKBj2siTQps=
github.com/gen2brain/avif v0.6.0/go.mod h1:QgrYqdVE9y40PCfArK9VakcMIpYeDYpZmCSLkW6C1n8=
github.com/go-chi/chi/v5 v5.3.1 h1:3j4HZLGZQ3JpMCrPJF/Jl3mYJfWLKBfNJ6quurUGCf8=
github.com/go-chi/chi/v5 v5.3.1/go.mod h1:R+tYY2hNuVUUjxoPtqUdgBqevM9s9njzkTLutVsOCto=
github.com/go-chi/chi/v5 v5.5.0 h1:xdKQ1dJmVJsmgahrXSKhUx8NyVPzpwdlyrrQFpMPJgg=
github.com/go-chi/chi/v5 v5.5.0/go.mod h1:d1IG7GtKPSjPyBP365PH8sAGVHk3qfB/IhjFNRH1wWM=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
@@ -26,16 +26,16 @@ github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aN
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/junegunn/fzf v0.74.1 h1:rCGVdCSoOkfcfTxtxCO/vG2yceDjRlKSlv7IfCGkc/Y=
github.com/junegunn/fzf v0.74.1/go.mod h1:hKDkO8orBWT5VLIZOL8oyhxn7mRLXdGyu+gz1Ss58pU=
github.com/junegunn/fzf v0.74.5 h1:mpJlCdgGuddKerHrdjvV3cnezEBgyjZAVn8KCo/4OMc=
github.com/junegunn/fzf v0.74.5/go.mod h1:TBRY54j3mGjAm4JcpDyiUIuDq38QlHvAzrB3GLKxQXM=
github.com/junegunn/go-shellwords v0.0.0-20250127100254-2aa3b3277741 h1:7dYDtfMDfKzjT+DVfIS4iqknSEKtZpEcXtu6vuaasHs=
github.com/junegunn/go-shellwords v0.0.0-20250127100254-2aa3b3277741/go.mod h1:6EILKtGpo5t+KLb85LNZLAF6P9LKp78hJI80PXMcn3c=
github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk=
github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
github.com/klauspost/compress v1.20.3 h1:zWNoFqq/lSuYQRim3dUXlXeA0IqwuZGicdG5ZTfY5j4=
github.com/klauspost/compress v1.20.3/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI=
github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI=
github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A=
github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/ncruces/go-strftime v1.1.0 h1:vtPmPWMkb539RGV9WpWT9EwJGvrOCKvMNI4obWL47Hk=
github.com/ncruces/go-strftime v1.1.0/go.mod h1:yVaq7iwCN09vHRrKBrrflXT0M9tTMG2KmZ9Fj7xeG/g=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
@@ -48,46 +48,46 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tetratelabs/wazero v1.12.0 h1:DuWcpNu/FzgEXgGBDp8J1Spc+CWOvvtvVyjKlaZopYU=
github.com/tetratelabs/wazero v1.12.0/go.mod h1:LvKtzl2RqO4gyF27BiXU+nKAjcV8f38U+kP/q2vgxh0=
golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
golang.org/x/image v0.44.0 h1:+tDekMZED9+LrtB3G5xzRggpVh9CARjZqROla3R3R+I=
golang.org/x/image v0.44.0/go.mod h1:V8K3KE9KKKE+pLpQDOeN18w9oacNSvy1tDOirTu4xtY=
golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk=
golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40=
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs=
golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY=
golang.org/x/tools v0.48.0 h1:3+hClM1aLL5mjMKm5ovokw9epgRXPuu2tILgismM6RE=
golang.org/x/tools v0.48.0/go.mod h1:08xX0orndb/F7jJxGDicx061tyd5pcMto75YMAXr6lk=
golang.org/x/crypto v0.58.0 h1:COkYLr4k7nDI4r6QtMML2AfzeIswWHAJthLS6K/M/54=
golang.org/x/crypto v0.58.0/go.mod h1:Xh+kl5A+M0gMiWDytH2Hhr5Z7WbNCpv/eB/EFgfSk+w=
golang.org/x/image v0.47.0 h1:za/8gVz++PPZqmZJBNSISICN5Rrj5zixP/8K++fgmqo=
golang.org/x/image v0.47.0/go.mod h1:IkN5o4A7vq55vXN8FWjjnhg9Rs2GOtffqsSi9mWAKYE=
golang.org/x/mod v0.42.0 h1:ICeL3t2L30ljSPHHxDnR4fqVcBt/zR2zJAb9juavmQg=
golang.org/x/mod v0.42.0/go.mod h1:u5fzIrRInkL8MaO1cbRkUHT64v303YIT5KEqpNr7jRs=
golang.org/x/sync v0.24.0 h1:iqiDrGoDgyuvAKrhLQthUEzU/R378N78gXbBjxed7oA=
golang.org/x/sync v0.24.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0=
golang.org/x/sys v0.49.0 h1:XbzkgYJHdqh/8m2Uu0W/dQv8nktxx4BFHp1M0gROTXA=
golang.org/x/sys v0.49.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og=
golang.org/x/text v0.43.0 h1:1QivrlhwAsnMOcqgOdl9my7s9OyZl8O5/UGUTJVXoWc=
golang.org/x/text v0.43.0/go.mod h1:hbSIYA/amXcRXTFSZqh8tWHEoqRvvbKPJ2uz/KU+a+s=
golang.org/x/tools v0.52.0 h1:ryxg4U63oaUYk7uOLTF37n43f4qgtGvqV4Ioit1BaEs=
golang.org/x/tools v0.52.0/go.mod h1:ItcP5UNaVGG+Yc4eIYmaFLNJ4soEopkx5Y2d4lcEurs=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
modernc.org/cc/v4 v4.29.1 h1:MKgdCV3WykTSPqpVrnxdEDS0HEd2FHpKZDzxzU5LyeI=
modernc.org/cc/v4 v4.29.1/go.mod h1:OnovgIhbbMXMu1aISnJ0wvVD1KnW+cAUJkIrAWh+kVI=
modernc.org/ccgo/v4 v4.34.6 h1:sBgfIwyN0TQ9C5hwIeuqyeAKyMWnbvj2fvpF4L11uzU=
modernc.org/ccgo/v4 v4.34.6/go.mod h1:SZ8YcN9NG7XVsQYdm6jYBvi8PQP1qi+kqB6OhjqI3Fk=
modernc.org/cc/v4 v4.30.3 h1:aDq8gIX1X7+VFgO/JYYji6pLWL2H4tv3g8WatT3KCys=
modernc.org/cc/v4 v4.30.3/go.mod h1:OnovgIhbbMXMu1aISnJ0wvVD1KnW+cAUJkIrAWh+kVI=
modernc.org/ccgo/v4 v4.37.0 h1:BAuJCUtIHIxFIYaFhqXIw5YaoMBlNCUlFovejHfMip4=
modernc.org/ccgo/v4 v4.37.0/go.mod h1:/8627VhwWtAbqUXmPORxFQU5SgLrAx2jl9seLw9GBhY=
modernc.org/fileutil v1.4.0 h1:j6ZzNTftVS054gi281TyLjHPp6CPHr2KCxEXjEbD6SM=
modernc.org/fileutil v1.4.0/go.mod h1:EqdKFDxiByqxLk8ozOxObDSfcVOv/54xDs/DUHdvCUU=
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/gc/v3 v3.1.4 h1:2g65LGVSmFQrXeITAw97x7hCRvZFcyE1uDP+7Vng7JI=
modernc.org/gc/v3 v3.1.4/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY=
modernc.org/gc/v3 v3.2.0 h1:/Y3LGDMQaoYf55PebP1qsZ5FDGgAZyG1RYKEHeQzh1o=
modernc.org/gc/v3 v3.2.0/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY=
modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
modernc.org/libc v1.74.3 h1:a4J+Z8aVaxPyjyxRAdJzw246PqpcFGvVPnfT/AuM5Ws=
modernc.org/libc v1.74.3/go.mod h1:4H7h/MJ8wnjL8RAbp9v3OXgnk22X7MouHIhDbvP3gj4=
modernc.org/libc v1.79.0 h1:9Dvvv++bAMSkSuBzuOFAatbTV5OIoq6Y6FohmD3e7q8=
modernc.org/libc v1.79.0/go.mod h1:uT3kR61NsbeKJSLqq83GJwSnZMVLlSjyAz4DfTaBy1M=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
modernc.org/memory v1.12.1 h1:nFMiWrpStgZczNl6XI9GnIk/rWhYIyHGUaR04pGbp9g=
modernc.org/memory v1.12.1/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
modernc.org/opt v0.2.0 h1:tGyef5ApycA7FSEOMraay9SaTk5zmbx7Tu+cJs4QKZg=
modernc.org/opt v0.2.0/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.54.0 h1:JCxR4qwkJvOaqAoYcgDoO25Nc+ROg6EJ2LfBVzdrgog=
modernc.org/sqlite v1.54.0/go.mod h1:4ntCLuNmnH8+GNqjka1wNg7KJd5/Hi5FYp8K+XQ7GZw=
modernc.org/sqlite v1.61.0 h1:sQi63oLQ9uquAUA4CzOisH35Q3pEszkPBuHM0tFL8CY=
modernc.org/sqlite v1.61.0/go.mod h1:f4gr5tbpx2umklaT/QVtbi/50hNdM+4ng+2zMo8KXJ0=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=