1 Commits
Author SHA1 Message Date
zephyr 55aa03aa41 umadump/replay: start of race replay json decoding 2026-09-20 11:44:09 -04:00
44 changed files with 840 additions and 19620 deletions
-325
View File
@@ -1,325 +0,0 @@
package main
import (
"cmp"
"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/replay"
)
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, race *replay.Race, simdata *replay.RaceSimulateData) (err error) {
conn, err := db.Take(ctx)
if err != nil {
return err
}
defer db.Put(conn)
defer sqlitex.Transaction(conn)(&err)
log.DebugContext(ctx, "horses",
slog.Int("num", int(race.NumRaceHorses)),
slog.Int("actual", len(race.RaceHorse)),
)
var trainedCharas [18]int64
for i := range race.RaceHorse {
c := &race.RaceHorse[i]
id, err := insertTrainedChara(conn, c)
if err != nil {
return err
}
trainedCharas[i] = id
if err := insertTrainedCharaSkill(conn, c, id); err != nil {
return err
}
log.DebugContext(ctx, "horse",
slog.String("trainer", c.TrainerName),
slog.Int("trained", int(c.ResponseHorseData.TrainedCharaID)),
slog.Int("card", int(c.ResponseHorseData.CardID)),
slog.Int64("id", id),
)
}
if err = insertRaceCourseSet(conn, race); err != nil {
return err
}
log.DebugContext(ctx, "course", slog.Int("id", int(race.RaceCourseSet.ID)))
configID, err := insertRaceConfig(conn, race)
if err != nil {
return err
}
log.DebugContext(ctx, "config", slog.Int64("id", configID))
raceID, err := insertRace(conn, race, simdata, &trainedCharas, configID)
if err != nil {
code := sqlite.ErrCode(err)
if code == sqlite.ResultConstraintUnique {
log.InfoContext(ctx, "already loaded")
return nil
}
return err
}
log.DebugContext(ctx, "race", slog.Int64("id", raceID))
err = errors.Join(
insertRaceHorses(ctx, log, conn, race, simdata, &trainedCharas, raceID),
insertRaceFrames(ctx, log, conn, simdata, raceID),
insertRaceEvents(ctx, log, conn, simdata, raceID),
)
return err
}
//go:embed insert-trained_chara.sql
var insertTrainedCharaSQL string
func insertTrainedChara(conn *sqlite.Conn, c *replay.HorseData) (int64, error) {
stmt := conn.Prep(insertTrainedCharaSQL)
trainer := cmp.Or(c.ResponseHorseData.ViewerID, c.ResponseHorseData.OwnerViewerID)
stmt.SetText("$trainer", c.TrainerName)
stmt.SetInt64("$trainer_id", trainer)
stmt.SetInt64("$trained_chara_id", int64(c.ResponseHorseData.TrainedCharaID))
stmt.SetInt64("$chara_id", int64(c.CharaID))
stmt.SetText("$chara_name", c.CharaName)
stmt.SetInt64("$card_id", int64(c.ResponseHorseData.CardID))
stmt.SetInt64("$rarity", int64(c.Rarity))
stmt.SetInt64("$mob_id", int64(c.MobID))
stmt.SetInt64("$raw_speed", int64(c.ResponseHorseData.Speed))
stmt.SetInt64("$raw_stamina", int64(c.ResponseHorseData.Stamina))
stmt.SetInt64("$raw_power", int64(c.ResponseHorseData.Pow))
stmt.SetInt64("$raw_guts", int64(c.ResponseHorseData.Guts))
stmt.SetInt64("$raw_wit", int64(c.ResponseHorseData.Wiz))
stmt.SetInt64("$turf", int64(c.ResponseHorseData.ProperGroundTurf))
stmt.SetInt64("$dirt", int64(c.ResponseHorseData.ProperGroundDirt))
stmt.SetInt64("$sprint", int64(c.ResponseHorseData.ProperDistanceShort))
stmt.SetInt64("$mile", int64(c.ResponseHorseData.ProperDistanceMile))
stmt.SetInt64("$medium", int64(c.ResponseHorseData.ProperDistanceMiddle))
stmt.SetInt64("$long", int64(c.ResponseHorseData.ProperDistanceLong))
stmt.SetInt64("$front_runner", int64(c.ResponseHorseData.ProperRunningStyleNige))
stmt.SetInt64("$pace_chaser", int64(c.ResponseHorseData.ProperRunningStyleSenko))
stmt.SetInt64("$late_surger", int64(c.ResponseHorseData.ProperRunningStyleSashi))
stmt.SetInt64("$end_closer", int64(c.ResponseHorseData.ProperRunningStyleOikomi))
stmt.SetInt64("$fans", int64(c.TrainedCharaData.Fans))
stmt.SetInt64("$rank", int64(c.TrainedCharaData.Rank))
stmt.SetInt64("$rank_score", int64(c.TrainedCharaData.RankScore))
r, err := sqlitex.ResultInt64(stmt)
err = errors.Join(err, stmt.Reset())
if err != nil {
err = fmt.Errorf("inserting trained chara: %w", err)
}
return r, err
}
func insertTrainedCharaSkill(conn *sqlite.Conn, c *replay.HorseData, id int64) error {
const sql = `INSERT OR IGNORE INTO trained_chara_skill VALUES (?, ?, ?)`
stmt := conn.Prep(sql)
stmt.BindInt64(1, id)
for _, sk := range c.ResponseHorseData.SkillArray {
stmt.BindInt64(2, int64(sk.SkillID))
stmt.BindInt64(3, int64(sk.Level))
_, err := stmt.Step()
err = errors.Join(err, stmt.Reset())
if err != nil {
return fmt.Errorf("inserting trained chara id %d skill %d: %w", id, sk.SkillID, err)
}
}
return nil
}
func insertRaceCourseSet(conn *sqlite.Conn, race *replay.Race) error {
const sql = `INSERT OR IGNORE INTO race_course_set VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
stmt := conn.Prep(sql)
stmt.BindInt64(1, int64(race.RaceCourseSet.ID))
stmt.BindInt64(2, int64(race.RaceCourseSet.RaceTrackID))
stmt.BindInt64(3, int64(race.RaceCourseSet.Distance))
stmt.BindInt64(4, int64(race.RaceCourseSet.Ground))
stmt.BindInt64(5, int64(race.RaceCourseSet.Inout))
stmt.BindInt64(6, int64(race.RaceCourseSet.Turn))
stmt.BindInt64(7, int64(race.RaceCourseSet.FenceSet))
stmt.BindInt64(8, int64(race.RaceCourseSet.FloatLaneMax))
stmt.BindInt64(9, int64(race.RaceCourseSet.CourseSetStatusID))
stmt.BindInt64(10, int64(race.RaceCourseSet.FinishTimeMin))
stmt.BindInt64(11, int64(race.RaceCourseSet.FinishTimeMinRandomRange))
stmt.BindInt64(12, int64(race.RaceCourseSet.FinishTimeMax))
stmt.BindInt64(13, int64(race.RaceCourseSet.FinishTimeMaxRandomRange))
stmt.BindFloat(14, float64(race.CourseSectionDistance))
stmt.BindInt64(15, int64(race.CourseDistanceType))
stmt.BindInt64(16, int64(race.CourseFurlongNum))
stmt.BindFloat(17, float64(race.BaseSpeed))
_, err := stmt.Step()
err = errors.Join(err, stmt.Reset())
if err != nil {
return fmt.Errorf("inserting race course: %w", err)
}
return nil
}
//go:embed insert-race_config.sql
var insertRaceConfigSQL string
func insertRaceConfig(conn *sqlite.Conn, race *replay.Race) (int64, error) {
stmt := conn.Prep(insertRaceConfigSQL)
stmt.SetInt64("$type", int64(race.RaceType))
stmt.SetInt64("$course_set_id", int64(race.RaceCourseSet.ID))
stmt.SetInt64("$ground_condition", int64(race.GroundCondition))
stmt.SetInt64("$weather", int64(race.Weather))
stmt.SetInt64("$season", int64(race.Season))
stmt.SetInt64("$time", int64(race.Time))
stmt.SetInt64("$num_horse", int64(race.NumRaceHorses))
r, err := sqlitex.ResultInt64(stmt)
err = errors.Join(err, stmt.Reset())
if err != nil {
err = fmt.Errorf("inserting race config: %w", err)
}
return r, err
}
//go:embed insert-race.sql
var insertRaceSQL string
func insertRace(conn *sqlite.Conn, race *replay.Race, simdata *replay.RaceSimulateData, trainedCharas *[18]int64, configID int64) (int64, error) {
stmt := conn.Prep(insertRaceSQL)
stmt.SetInt64("$config_id", configID)
stmt.SetInt64("$seed", int64(race.RandomSeed))
stmt.SetFloat("$distance_diff_max", float64(simdata.DistanceDiffMax))
stmt.SetInt64("$frame_count", int64(simdata.FrameCount))
// zombiezen/sqlite doesn't seem to expose an API to find the index of a
// named parameter, so even though we were using names before, we switch
// to indices for trained chara IDs.
for i, id := range trainedCharas {
stmt.BindInt64(5+i, id)
}
r, err := sqlitex.ResultInt64(stmt)
err = errors.Join(err, stmt.Reset())
if err != nil {
err = fmt.Errorf("inserting race: %w", err)
}
return r, err
}
//go:embed insert-race_horse.sql
var insertRaceHorseSQL string
func insertRaceHorses(ctx context.Context, log *slog.Logger, conn *sqlite.Conn, race *replay.Race, simdata *replay.RaceSimulateData, trainedCharas *[18]int64, raceID int64) error {
stmt := conn.Prep(insertRaceHorseSQL)
stmt.SetInt64("$race", raceID)
for i, c := range race.RaceHorse {
log.DebugContext(ctx, "race horse", slog.Int64("trained", trainedCharas[i]), slog.Int("index", int(c.HorseIndex)))
stmt.SetInt64("$horse", trainedCharas[i])
stmt.SetInt64("$horse_index", int64(c.HorseIndex))
stmt.SetInt64("$post", int64(c.PostNumber))
stmt.SetInt64("$finish_order", int64(c.FinishOrder))
stmt.SetFloat("$finish_time_raw", float64(c.FinishTimeRaw))
stmt.SetFloat("$finish_time_scaled", float64(c.FinishTimeScaled))
stmt.SetFloat("$finish_diff_time_from_prev", float64(c.FinishDiffTimeFromPrev))
stmt.SetInt64("$running_style", int64(c.ResponseHorseData.RunningStyle))
stmt.SetInt64("$running_style_ex", int64(c.RunningStyleEx))
stmt.SetInt64("$active_distance_aptitude", int64(c.ActiveProperDistance))
stmt.SetInt64("$active_surface_aptitude", int64(c.ActiveProperGroundType))
stmt.SetInt64("$mood", int64(c.RaceParam.Motivation))
stmt.SetFloat("$mood_coef", float64(c.RaceParam.MotivationCoef))
stmt.SetFloat("$base_speed", float64(c.RaceParam.BaseSpeed))
stmt.SetFloat("$base_stamina", float64(c.RaceParam.BaseStamina))
stmt.SetFloat("$base_power", float64(c.RaceParam.BasePow))
stmt.SetFloat("$base_guts", float64(c.RaceParam.BaseGuts))
stmt.SetFloat("$base_wit", float64(c.RaceParam.BaseWiz))
stmt.SetInt64("$popularity", int64(c.Popularity))
stmt.SetInt64("$popularity_rank_left", int64(c.PopularityRankLeft))
stmt.SetInt64("$popularity_rank_center", int64(c.PopularityRankCenter))
stmt.SetInt64("$popularity_rank_right", int64(c.PopularityRankRight))
stmt.SetFloat("$start_delay", float64(simdata.HorseResult[i].StartDelayTime))
stmt.SetFloat("$spurt_start_distance", float64(simdata.HorseResult[i].LastSpurtStartDistance))
_, err := stmt.Step()
err = errors.Join(err, stmt.Reset())
if err != nil {
return fmt.Errorf("inserting race horses: %w", err)
}
}
return nil
}
func insertRaceFrames(ctx context.Context, log *slog.Logger, conn *sqlite.Conn, simdata *replay.RaceSimulateData, raceID int64) error {
const sql = `INSERT INTO race_frame VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`
stmt := conn.Prep(sql)
stmt.BindInt64(1, raceID)
for _, f := range simdata.Frame {
log.DebugContext(ctx, "frame", slog.Float64("time", float64(f.Time)))
stmt.BindFloat(2, float64(f.Time))
for i, h := range f.HorseFrame {
stmt.BindInt64(3, int64(i))
stmt.BindFloat(4, float64(h.Distance))
stmt.BindInt64(5, int64(h.LanePosition))
stmt.BindInt64(6, int64(h.Speed))
stmt.BindInt64(7, int64(h.HP))
stmt.BindInt64(8, int64(h.TemptationMode))
stmt.BindInt64(9, int64(h.BlockFrontHorseIndex))
_, err := stmt.Step()
err = errors.Join(err, stmt.Reset())
if err != nil {
return fmt.Errorf("inserting race frames: %w", err)
}
}
}
return nil
}
func insertRaceEvents(ctx context.Context, log *slog.Logger, conn *sqlite.Conn, simdata *replay.RaceSimulateData, raceID int64) error {
const sql = `INSERT INTO race_event VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`
stmt := conn.Prep(sql)
for _, e := range simdata.Event {
log.DebugContext(ctx, "event", slog.Float64("time", float64(e.Event.FrameTime)), slog.Int("type", int(e.Event.Type)))
// Easier to clear all bindings every time now
// than to bind nulls to all the parameters that need them below.
stmt.ClearBindings()
stmt.BindInt64(1, raceID)
stmt.BindFloat(2, float64(e.Event.FrameTime))
stmt.BindInt64(3, int64(e.Event.Type))
for i, p := range e.Event.Param {
stmt.BindInt64(4+i, int64(p))
}
_, err := stmt.Step()
err = errors.Join(err, stmt.Reset())
if err != nil {
return fmt.Errorf("inserting race events: %w", err)
}
}
return nil
}
-49
View File
@@ -1,49 +0,0 @@
INSERT OR ROLLBACK INTO race (
config_id,
seed,
distance_diff_max,
frame_count,
horse_1,
horse_2,
horse_3,
horse_4,
horse_5,
horse_6,
horse_7,
horse_8,
horse_9,
horse_10,
horse_11,
horse_12,
horse_13,
horse_14,
horse_15,
horse_16,
horse_17,
horse_18
)
VALUES (
$config_id,
$seed,
$distance_diff_max,
$frame_count,
$horse_1,
$horse_2,
$horse_3,
$horse_4,
$horse_5,
$horse_6,
$horse_7,
$horse_8,
$horse_9,
$horse_10,
$horse_11,
$horse_12,
$horse_13,
$horse_14,
$horse_15,
$horse_16,
$horse_17,
$horse_18
)
RETURNING id
-4
View File
@@ -1,4 +0,0 @@
INSERT INTO race_config (type, course_set_id, ground_condition, weather, season, time, num_horse)
VALUES ($type, $course_set_id, $ground_condition, $weather, $season, $time, $num_horse)
ON CONFLICT DO UPDATE SET id=id
RETURNING id
-12
View File
@@ -1,12 +0,0 @@
INSERT INTO race_horse
VALUES (
$race, $horse,
$horse_index, $post,
$finish_order, $finish_time_raw, $finish_time_scaled, $finish_diff_time_from_prev,
$running_style, $running_style_ex,
$active_distance_aptitude, $active_surface_aptitude,
$mood, $mood_coef,
$base_speed, $base_stamina, $base_power, $base_guts, $base_wit,
$popularity, $popularity_rank_left, $popularity_rank_center, $popularity_rank_right,
$start_delay, $spurt_start_distance
)
-19
View File
@@ -1,19 +0,0 @@
INSERT INTO trained_chara (
trainer, trainer_id, trained_chara_id,
chara_id, chara_name, card_id, rarity, mob_id,
raw_speed, raw_stamina, raw_power, raw_guts, raw_wit,
turf, dirt,
sprint, mile, medium, long,
front_runner, pace_chaser, late_surger, end_closer,
fans, rank, rank_score
) VALUES (
$trainer, $trainer_id, $trained_chara_id,
$chara_id, $chara_name, $card_id, $rarity, $mob_id,
$raw_speed, $raw_stamina, $raw_power, $raw_guts, $raw_wit,
$turf, $dirt,
$sprint, $mile, $medium, $long,
$front_runner, $pace_chaser, $late_surger, $end_closer,
$fans, $rank, $rank_score
)
ON CONFLICT DO UPDATE SET id=id
RETURNING id
-74
View File
@@ -1,74 +0,0 @@
package main
import (
"context"
"encoding/json"
"flag"
"log/slog"
"os"
"os/signal"
"path/filepath"
"git.sunturtle.xyz/zephyr/horse/umadump/replay"
)
func main() {
var (
uri, journalMode string
fs []string
)
flag.StringVar(&uri, "db", "race.sqlite3", "output database `URI` or filename")
flag.StringVar(&journalMode, "journal", "memory", "journal `mode` to apply to database connections")
flag.Func("d", "`dir`ectory containing race dumps to load (repeatable)", func(s string) error {
es, err := os.ReadDir(s)
for _, e := range es {
if e.IsDir() {
continue
}
fs = append(fs, filepath.Join(s, e.Name()))
}
return err
})
flag.Parse()
fs = append(fs, flag.Args()...)
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
go func() {
<-ctx.Done()
stop()
}()
db := opendb(uri, journalMode)
ok := 0
for _, n := range fs {
log := slog.With(slog.String("file", n))
log.Info("begin")
f, err := os.Open(n)
if err != nil {
log.Error("open", slog.Any("err", err))
continue
}
var race replay.Race
d := json.NewDecoder(f)
d.DisallowUnknownFields()
log.Debug("decode")
if err := d.Decode(&race); err != nil {
log.Error("load", slog.Any("err", err))
continue
}
log.Debug("simdata")
simdata, err := replay.DecodeSim(race.SimDataBase64)
if err != nil {
log.Error("simdata", slog.Any("err", err))
continue
}
log.Debug("insert")
err = insert(ctx, db, log, &race, simdata)
if err != nil {
log.Error("insert", slog.Any("err", err))
continue
}
ok++
}
slog.Info("done", slog.Int("races", ok))
}
-234
View File
@@ -1,234 +0,0 @@
-- trained_chara lists horses who appear in races.
CREATE TABLE IF NOT EXISTS trained_chara (
-- id is the DB-internal ID of the Uma.
-- It does not come from the game and should not be supplied in DDL.
id INTEGER PRIMARY KEY,
trainer TEXT NOT NULL,
trainer_id INTEGER NOT NULL, -- 0 for NPC umas e.g. in practice races
trained_chara_id INTEGER NOT NULL,
chara_id INTEGER NOT NULL,
chara_name TEXT NOT NULL,
-- card_id is the Uma herself, e.g. 100201 for [Innocent Silence] Silence Suzuka.
card_id INTEGER NOT NULL,
rarity INTEGER NOT NULL,
mob_id INTEGER NOT NULL, -- 0 for Umas that are not mobs
-- Raw stats.
raw_speed INTEGER NOT NULL,
raw_stamina INTEGER NOT NULL,
raw_power INTEGER NOT NULL,
raw_guts INTEGER NOT NULL,
raw_wit INTEGER NOT NULL,
-- Aptitudes.
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,
-- Other data.
fans INTEGER NOT NULL,
rank INTEGER NOT NULL,
rank_score INTEGER NOT NULL,
UNIQUE (trainer_id, trained_chara_id)
) STRICT;
-- Insert trained chara ID 0 to represent no Uma.
INSERT OR IGNORE INTO trained_chara (
id,
trainer,
trainer_id,
trained_chara_id,
chara_id, chara_name,
card_id,
mob_id,
raw_speed, raw_stamina, raw_power, raw_guts, raw_wit,
turf, dirt,
sprint, mile, medium, long,
front_runner, pace_chaser, late_surger, end_closer,
fans,
rank, rank_score
)
VALUES (0, '', 0, 0, 0, '', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
-- trained_chara_skill lists the skills each observed horse owns.
CREATE TABLE IF NOT EXISTS trained_chara_skill (
trained_chara INTEGER NOT NULL REFERENCES trained_chara (id) ON DELETE CASCADE,
skill_id INTEGER NOT NULL,
level INTEGER NOT NULL,
UNIQUE (trained_chara, skill_id)
) STRICT;
CREATE INDEX IF NOT EXISTS trained_chara_skill_by_trained_chara ON trained_chara_skill (trained_chara);
-- race_course_set is the accumulated information of observed race courses.
CREATE TABLE IF NOT EXISTS race_course_set (
id INTEGER PRIMARY KEY,
race_track_id INTEGER NOT NULL,
distance INTEGER NOT NULL,
ground INTEGER NOT NULL,
inout INTEGER NOT NULL,
turn INTEGER NOT NULL,
fence_set INTEGER NOT NULL,
float_lane_max INTEGER NOT NULL,
course_set_status_id INTEGER NOT NULL,
finish_time_min INTEGER NOT NULL,
finish_time_min_random_range INTEGER NOT NULL,
finish_time_max INTEGER NOT NULL,
finish_time_max_random_range INTEGER NOT NULL,
section_distance REAL NOT NULL,
distance_type INTEGER NOT NULL,
furlong_number INTEGER NOT NULL,
base_speed REAL NOT NULL
) STRICT;
-- race_config is observed configurations of races including the race type.
CREATE TABLE IF NOT EXISTS race_config (
-- id is the DB-internal ID of the race config.
id INTEGER PRIMARY KEY,
type INTEGER NOT NULL,
course_set_id INTEGER NOT NULL REFERENCES race_course_set (id) ON DELETE RESTRICT,
ground_condition INTEGER NOT NULL,
weather INTEGER NOT NULL,
season INTEGER NOT NULL,
time INTEGER NOT NULL,
num_horse INTEGER NOT NULL,
UNIQUE (type, course_set_id, ground_condition, weather, season, time, num_horse)
) STRICT;
CREATE INDEX IF NOT EXISTS race_config_by_type ON race_config (type);
-- race is all observed races.
CREATE TABLE IF NOT EXISTS race (
-- id is the DB-internal ID of the race.
id INTEGER PRIMARY KEY,
config_id INTEGER NOT NULL REFERENCES race_config (id),
seed INTEGER NOT NULL,
distance_diff_max REAL NOT NULL,
frame_count INTEGER NOT NULL,
-- There is no consistent ID for races, and even race seeds have been found
-- to collide well above the expected rate for a uniform distribution.
-- In order to prevent adding duplicates of races each time the tool is run,
-- we include the list of all horse IDs present in the race.
-- Analysis on the horses in the race should instead use the race_horse table.
-- Horse entries here are 0 where there is actually no horse at that gate.
horse_1 INTEGER NOT NULL REFERENCES trained_chara (id) ON DELETE CASCADE,
horse_2 INTEGER NOT NULL REFERENCES trained_chara (id) ON DELETE CASCADE,
horse_3 INTEGER NOT NULL REFERENCES trained_chara (id) ON DELETE CASCADE,
horse_4 INTEGER NOT NULL REFERENCES trained_chara (id) ON DELETE CASCADE,
horse_5 INTEGER NOT NULL REFERENCES trained_chara (id) ON DELETE CASCADE,
horse_6 INTEGER NOT NULL REFERENCES trained_chara (id) ON DELETE CASCADE,
horse_7 INTEGER NOT NULL REFERENCES trained_chara (id) ON DELETE CASCADE,
horse_8 INTEGER NOT NULL REFERENCES trained_chara (id) ON DELETE CASCADE,
horse_9 INTEGER NOT NULL REFERENCES trained_chara (id) ON DELETE CASCADE,
horse_10 INTEGER NOT NULL REFERENCES trained_chara (id) ON DELETE CASCADE,
horse_11 INTEGER NOT NULL REFERENCES trained_chara (id) ON DELETE CASCADE,
horse_12 INTEGER NOT NULL REFERENCES trained_chara (id) ON DELETE CASCADE,
horse_13 INTEGER NOT NULL REFERENCES trained_chara (id) ON DELETE CASCADE,
horse_14 INTEGER NOT NULL REFERENCES trained_chara (id) ON DELETE CASCADE,
horse_15 INTEGER NOT NULL REFERENCES trained_chara (id) ON DELETE CASCADE,
horse_16 INTEGER NOT NULL REFERENCES trained_chara (id) ON DELETE CASCADE,
horse_17 INTEGER NOT NULL REFERENCES trained_chara (id) ON DELETE CASCADE,
horse_18 INTEGER NOT NULL REFERENCES trained_chara (id) ON DELETE CASCADE,
UNIQUE (
config_id,
seed,
horse_1,
horse_2,
horse_3,
horse_4,
horse_5,
horse_6,
horse_7,
horse_8,
horse_9,
horse_10,
horse_11,
horse_12,
horse_13,
horse_14,
horse_15,
horse_16,
horse_17,
horse_18
)
) STRICT;
CREATE INDEX IF NOT EXISTS race_by_config ON race (config_id);
-- race_horse pairs each instance of a horse with its condition and performance
-- in a given race.
CREATE TABLE IF NOT EXISTS race_horse (
race INTEGER NOT NULL REFERENCES race (id) ON DELETE CASCADE,
horse INTEGER NOT NULL REFERENCES trained_chara (id) ON DELETE CASCADE,
horse_index INTEGER NOT NULL,
post INTEGER NOT NULL,
finish_order INTEGER NOT NULL,
finish_time_raw REAL NOT NULL,
finish_time_scaled REAL NOT NULL,
finish_diff_time_from_prev REAL NOT NULL,
running_style INTEGER NOT NULL,
running_style_ex INTEGER NOT NULL,
active_distance_aptitude INTEGER NOT NULL,
active_surface_aptitude INTEGER NOT NULL,
mood INTEGER NOT NULL,
mood_coef REAL NOT NULL,
base_speed REAL NOT NULL,
base_stamina REAL NOT NULL,
base_power REAL NOT NULL,
base_guts REAL NOT NULL,
base_wit REAL NOT NULL,
popularity INTEGER NOT NULL,
popularity_rank_left INTEGER NOT NULL,
popularity_rank_center INTEGER NOT NULL,
popularity_rank_right INTEGER NOT NULL,
start_delay REAL NOT NULL,
spurt_start_distance REAL NOT NULL,
PRIMARY KEY (race, horse),
UNIQUE (race, horse_index),
CHECK (horse != 0)
) STRICT;
-- race_frame holds the actual received frames.
CREATE TABLE IF NOT EXISTS race_frame (
race INTEGER NOT NULL REFERENCES race (id) ON DELETE CASCADE,
frame_time REAL NOT NULL,
horse_index INTEGER NOT NULL,
distance REAL NOT NULL,
lane INTEGER NOT NULL, -- scale -4
speed INTEGER NOT NULL, -- scale -2
hp INTEGER NOT NULL,
temptation INTEGER NOT NULL,
block_front_horse_index INTEGER NOT NULL,
PRIMARY KEY (race, frame_time, horse_index)
) STRICT;
-- race_event holds raw received race events.
-- Views such as race_event_skill_activate, race_event_spot_struggle_activate, &c.
-- interpret events per type.
CREATE TABLE IF NOT EXISTS race_event (
race INTEGER NOT NULL REFERENCES race (id) ON DELETE CASCADE,
frame_time REAL NOT NULL,
type INTEGER NOT NULL,
param_0 INTEGER,
param_1 INTEGER,
param_2 INTEGER,
param_3 INTEGER,
param_4 INTEGER,
param_5 INTEGER
) STRICT;
CREATE INDEX IF NOT EXISTS race_event_by_race ON race_event (race);
CREATE INDEX IF NOT EXISTS race_event_by_type ON race_event (type);
-36
View File
@@ -1,36 +0,0 @@
DROP VIEW IF EXISTS race_event_skill_activate;
DROP VIEW IF EXISTS race_event_spot_struggle_activate;
DROP VIEW IF EXISTS race_event_duel_activate;
DROP VIEW IF EXISTS race_event_release_conserve_power;
CREATE VIEW race_event_skill_activate AS
SELECT
race,
frame_time,
param_0 AS user_index,
param_1 AS skill,
param_2 * 0.0001 AS duration,
param_3 AS branch,
param_4 AS hit_bitmask
FROM race_event WHERE type = 3;
CREATE VIEW race_event_spot_struggle_activate AS
SELECT
race,
frame_time,
param_0 AS user_index
FROM race_event WHERE type = 4;
CREATE VIEW race_event_duel_activate AS
SELECT
race,
frame_time,
param_0 AS user_index
FROM race_event WHERE type = 5;
CREATE VIEW race_event_release_conserve_power AS
SELECT
race,
frame_time,
param_0 AS user_index
FROM race_event WHERE type = 6;
+4 -3
View File
@@ -139,8 +139,9 @@ func spansslopes(id horse.RacecourseID, evts []courseEvent, length float32) ([]h
}
// Start of the straight.
span = horse.RacecourseSpan{
Start: evt.Distance,
Straight: int8(evt.Values[1]),
Start: evt.Distance,
Straight: true,
FarStraight: evt.Values[1] == 2,
}
// Continue out of the switch.
}
@@ -153,7 +154,7 @@ func spansslopes(id horse.RacecourseID, evts []courseEvent, length float32) ([]h
// Longchamp 1000 (which doesn't appear to actually be used but w/e)
// defines straights by their start positions only, so check for the
// previous event being a straight with no end.
if prev.Straight != 0 && prev.End == 0 {
if prev.Straight && prev.End == 0 {
spans[len(spans)-1].End = span.Start
} else {
// Otherwise, insert a new span which is neither straight nor corner.
+66 -20
View File
@@ -35,7 +35,7 @@ func TestRacecourses(t *testing.T) {
{
Start: 0,
End: 649.9000244140625,
Straight: 1,
Straight: true,
},
{
Start: 649.9000244140625,
@@ -44,7 +44,7 @@ func TestRacecourses(t *testing.T) {
{
Start: 650,
End: 1000,
Straight: 1,
Straight: true,
},
},
Slopes: []horse.Slope{},
@@ -64,9 +64,10 @@ func TestRacecourses(t *testing.T) {
LaneStart: [18]horse.TenThousandths{0, 555, 1111, 1666, 2222, 2777, 3333, 3888, 4444, 5333, 5888, 6444, 7000, 7555, 8111, 8666, 9222, 9777},
Spans: []horse.RacecourseSpan{
{
Start: 0,
End: 458,
Straight: 2,
Start: 0,
End: 458,
Straight: true,
FarStraight: true,
},
{
Start: 458,
@@ -81,7 +82,7 @@ func TestRacecourses(t *testing.T) {
{
Start: 958,
End: 1450,
Straight: 1,
Straight: true,
},
{
Start: 1450,
@@ -94,9 +95,10 @@ func TestRacecourses(t *testing.T) {
Corner: 2,
},
{
Start: 1850,
End: 2300,
Straight: 2,
Start: 1850,
End: 2300,
Straight: true,
FarStraight: true,
},
{
Start: 2300,
@@ -111,7 +113,7 @@ func TestRacecourses(t *testing.T) {
{
Start: 2797,
End: 3200,
Straight: 1,
Straight: true,
},
},
Slopes: []horse.Slope{
@@ -164,7 +166,7 @@ func TestRacecourses(t *testing.T) {
{
Start: 0,
End: 500,
Straight: 1,
Straight: true,
},
{
Start: 500,
@@ -177,9 +179,10 @@ func TestRacecourses(t *testing.T) {
Corner: 2,
},
{
Start: 800,
End: 1300,
Straight: 2,
Start: 800,
End: 1300,
Straight: true,
FarStraight: true,
},
{
Start: 1300,
@@ -194,12 +197,54 @@ func TestRacecourses(t *testing.T) {
{
Start: 1614,
End: 2000,
Straight: 1,
Straight: true,
},
},
Slopes: []horse.Slope{},
MoveLanePoint: 500,
},
{
ID: 11203,
TrackID: 10201,
TrackName: "Longchamp",
Distance: 2400,
Ground: 1,
InOut: 1,
Turn: 1,
LaneMax: 12000,
Threshold1: 3,
Threshold2: 0,
LaneStart: [18]horse.TenThousandths{0, 555, 1111, 1666, 2222, 2777, 3333, 3888, 4444, 5000, 5555, 6111, 6666, 7222, 8811, 9366, 9922, 10477},
Spans: []horse.RacecourseSpan{
{
Start: 0,
End: 798,
Straight: true,
FarStraight: true,
},
{
Start: 798,
End: 800,
},
{
Start: 800,
End: 1200,
Corner: 3,
},
{
Start: 1200,
End: 1600,
Corner: 4,
},
{
Start: 1600,
End: 2400,
Straight: true,
},
},
Slopes: []horse.Slope{},
MoveLanePoint: 800,
},
{
ID: 11504,
TrackID: 10105,
@@ -220,7 +265,7 @@ func TestRacecourses(t *testing.T) {
{
Start: 100,
End: 500,
Straight: 1,
Straight: true,
},
{
Start: 500,
@@ -233,9 +278,10 @@ func TestRacecourses(t *testing.T) {
Corner: 2,
},
{
Start: 900,
End: 1300,
Straight: 2,
Start: 900,
End: 1300,
Straight: true,
FarStraight: true,
},
{
Start: 1300,
@@ -250,7 +296,7 @@ func TestRacecourses(t *testing.T) {
{
Start: 1700,
End: 2000,
Straight: 1,
Straight: true,
},
},
Slopes: []horse.Slope{
+2 -3
View File
@@ -17,7 +17,6 @@ FROM race_course_set c
JOIN track ON c.race_track_id = track.id
JOIN race_track t ON c.race_track_id = t.id
LEFT JOIN race_course_set_status ss ON c.course_set_status_id = ss.course_set_status_id
-- Only include courses that can be selected for room matches.
-- Some other courses exist in the game files but have busted data.
WHERE c.id IN (SELECT course_set FROM race WHERE "group" = 12)
-- Exclude unused Longchamp courses with busted data.
WHERE c.id NOT IN (11201, 11202)
ORDER BY c.id
+1 -1
View File
@@ -6,7 +6,7 @@ WITH skill_names AS (
FROM text_data n
JOIN text_data d ON n."index" = d."index" AND n."category" = 47 AND d."category" = 48
), skill_groups AS (
SELECT DISTINCT
SELECT
group_id,
name
FROM skill_data d
-61
View File
@@ -40,64 +40,3 @@ INSERT INTO race_track (id, initial_lane_type, enable_half_gate, horse_num_gate_
INSERT INTO race_track (id, initial_lane_type, enable_half_gate, horse_num_gate_variation, turf_vision_type, footsmoke_color_type, area, flag_type, gate_panel_type, gate_lamp_type, board_condition_type, result_board_type) VALUES (10101, 2, 0, 1, 2, 2, 2, 1, 1, 1, 3, 0);
INSERT INTO race_track (id, initial_lane_type, enable_half_gate, horse_num_gate_variation, turf_vision_type, footsmoke_color_type, area, flag_type, gate_panel_type, gate_lamp_type, board_condition_type, result_board_type) VALUES (10105, 4, 1, 0, 2, 2, 1, 1, 1, 1, 4, 0);
INSERT INTO race_track (id, initial_lane_type, enable_half_gate, horse_num_gate_variation, turf_vision_type, footsmoke_color_type, area, flag_type, gate_panel_type, gate_lamp_type, board_condition_type, result_board_type) VALUES (10201, 3, 1, 0, 1, 1, 5, 0, 2, 2, 1, 0);
CREATE TABLE IF NOT EXISTS 'race' ('id' INTEGER NOT NULL, 'group' INTEGER NOT NULL, 'grade' INTEGER NOT NULL, 'course_set' INTEGER NOT NULL, 'thumbnail_id' INTEGER NOT NULL, 'ff_cue_name' TEXT NOT NULL, 'ff_cuesheet_name' TEXT NOT NULL, 'real_ff_cue_name' TEXT NOT NULL, 'real_ff_cuesheet_name' TEXT NOT NULL, 'ff_anim' INTEGER NOT NULL, 'ff_camera' INTEGER NOT NULL, 'ff_camera_sub' INTEGER NOT NULL, 'ff_sub' INTEGER NOT NULL, 'start_gate' INTEGER NOT NULL, 'start_gate_panel' INTEGER NOT NULL, 'goal_gate' INTEGER NOT NULL, 'goal_flower' INTEGER NOT NULL, 'result_podium' INTEGER NOT NULL, 'audience_group_id' INTEGER NOT NULL, 'paddock_bg_id' INTEGER NOT NULL, 'audience' INTEGER NOT NULL, 'entry_num' INTEGER NOT NULL, 'change_full_gate' INTEGER NOT NULL, 'is_dirtgrade' INTEGER NOT NULL, 'start_date' INTEGER NOT NULL, PRIMARY KEY('id'));
-- SELECT * FROM race WHERE course_set IN (10301, 10811, 11103, 11203, 11504);
INSERT INTO race VALUES(3042,1,300,10301,3042,'snd_mfx_1007_CL','snd_mfx_1007_CL','snd_mfx_r_1007_CL','snd_mfx_r_1007_CL',3042,207,0,0,0,0,0,0,-1,0,0,0,18,0,0,1498870800);
INSERT INTO race VALUES(4055,1,400,10301,4055,'snd_mfx_1012_CL','snd_mfx_1012_CL','snd_mfx_r_1012_CL','snd_mfx_r_1012_CL',4055,312,0,0,0,0,0,0,-1,0,0,0,18,0,0,1498870800);
INSERT INTO race VALUES(4101,1,400,10301,4101,'snd_mfx_1012_CL','snd_mfx_1012_CL','snd_mfx_r_1012_CL','snd_mfx_r_1012_CL',4101,312,0,0,0,0,0,0,-1,0,0,0,18,0,0,1498870800);
INSERT INTO race VALUES(5032,6,900,10301,5002,'snd_mfx_2009_CL','snd_mfx_2009_CL','','',5002,312,0,0,0,0,0,0,-1,0,0,1,18,0,0,1636977600);
INSERT INTO race VALUES(5226,12,999,10301,5200,'snd_mfx_2008_CL','snd_mfx_2008_CL','','',5200,121,0,0,0,0,0,0,-1,0,0,0,18,0,0,1627560000);
INSERT INTO race VALUES(6136,9,100,10301,6100,'snd_mfx_2004_CL','snd_mfx_2004_CL','','',6100,121,0,0,0,0,0,0,-1,0,0,0,12,0,0,1498870800);
INSERT INTO race VALUES(6137,9,100,10301,6101,'snd_mfx_2004_CL','snd_mfx_2004_CL','','',6101,121,0,0,0,0,0,0,-1,0,0,0,12,0,0,1498870800);
INSERT INTO race VALUES(6138,9,100,10301,6102,'snd_mfx_2004_CL','snd_mfx_2004_CL','','',6102,121,0,0,0,0,0,0,-1,0,0,0,12,0,0,1498870800);
INSERT INTO race VALUES(9307,7,800,10301,9005,'snd_mfx_1012_CL','snd_mfx_1012_CL','snd_mfx_r_1012_CL','snd_mfx_r_1012_CL',9005,312,0,0,0,0,0,0,-1,0,0,0,9,0,0,1498870800);
INSERT INTO race VALUES(9323,7,800,10301,9003,'snd_mfx_1012_CL','snd_mfx_1012_CL','snd_mfx_r_1012_CL','snd_mfx_r_1012_CL',9003,312,0,0,0,0,0,0,-1,0,0,0,9,0,0,1498870800);
INSERT INTO race VALUES(1006,1,100,10811,1006,'snd_mfx_1002_CL','snd_mfx_1002_CL','snd_mfx_r_1002_CL','snd_mfx_r_1002_CL',1006,102,0,0,0,0,1,1,-1,0,0,0,18,0,0,1498870800);
INSERT INTO race VALUES(4905,61,100,10811,1006,'snd_mfx_1002_CL','snd_mfx_1002_CL','','',1006,102,0,0,0,0,1,1,-1,0,0,0,18,0,0,1498870800);
INSERT INTO race VALUES(5070,6,900,10811,5002,'snd_mfx_2009_CL','snd_mfx_2009_CL','','',5002,313,0,0,0,0,0,0,-1,0,0,1,18,0,0,1636977600);
INSERT INTO race VALUES(5113,6,100,10811,1006,'snd_mfx_2009_CL','snd_mfx_2009_CL','','',1006,313,0,0,0,0,1,1,-1,0,0,1,18,0,0,1636977600);
INSERT INTO race VALUES(5257,12,999,10811,5200,'snd_mfx_2008_CL','snd_mfx_2008_CL','','',5200,121,0,0,0,0,0,0,-1,0,0,0,18,0,0,1627560000);
INSERT INTO race VALUES(5930,8,100,10811,5930,'snd_mfx_2003_CL','snd_mfx_2003_CL','','',5930,102,0,0,0,0,1,1,-1,0,0,0,18,0,0,1623931200);
INSERT INTO race VALUES(5931,8,100,10811,5930,'snd_mfx_2003_CL','snd_mfx_2003_CL','','',5930,102,0,0,0,0,1,1,-1,0,0,0,18,0,0,1623931200);
INSERT INTO race VALUES(5932,8,100,10811,5930,'snd_mfx_2003_CL','snd_mfx_2003_CL','','',5930,102,0,0,0,0,1,1,-1,0,0,0,18,0,0,1623931200);
INSERT INTO race VALUES(5933,8,100,10811,5930,'snd_mfx_2003_CL','snd_mfx_2003_CL','','',5930,102,0,0,0,0,1,1,-1,0,0,0,18,0,0,1623931200);
INSERT INTO race VALUES(6006,11,100,10811,6006,'snd_mfx_2005_CL','snd_mfx_2005_CL','','',6006,122,0,0,0,0,0,0,-1,0,0,0,9,0,0,1623326400);
INSERT INTO race VALUES(6018,11,100,10811,6006,'snd_mfx_2006_CL','snd_mfx_2006_CL','','',6006,123,0,0,0,0,0,0,-1,0,0,0,9,0,0,1623326400);
INSERT INTO race VALUES(6283,9,100,10811,6100,'snd_mfx_2004_CL','snd_mfx_2004_CL','','',6100,121,0,0,0,0,0,0,-1,0,0,0,12,0,0,1498870800);
INSERT INTO race VALUES(6284,9,100,10811,6101,'snd_mfx_2004_CL','snd_mfx_2004_CL','','',6101,121,0,0,0,0,0,0,-1,0,0,0,12,0,0,1498870800);
INSERT INTO race VALUES(6285,9,100,10811,6102,'snd_mfx_2004_CL','snd_mfx_2004_CL','','',6102,121,0,0,0,0,0,0,-1,0,0,0,12,0,0,1498870800);
INSERT INTO race VALUES(7004,4,0,10811,7004,'snd_mfx_1013_CL','snd_mfx_1013_CL','','',7004,313,0,0,0,0,0,0,-1,0,0,0,18,0,0,1498870800);
INSERT INTO race VALUES(7018,4,0,10811,7018,'snd_mfx_1013_CL','snd_mfx_1013_CL','','',7018,313,0,0,0,0,0,0,-1,0,0,0,12,0,0,1647777600);
INSERT INTO race VALUES(9530,7,100,10811,9020,'snd_mfx_3002_CL','snd_mfx_3002_CL','','',9020,208,0,0,0,0,302,0,-1,0,0,0,18,0,0,1498870800);
INSERT INTO race VALUES(9630,7,100,10811,9010,'snd_mfx_3002_CL','snd_mfx_3002_CL','','',9010,208,0,0,0,0,303,0,-1,0,0,0,18,0,0,1498870800);
INSERT INTO race VALUES(9730,7,100,10811,9001,'snd_mfx_3001_CL','snd_mfx_3001_CL','','',9001,119,0,0,0,0,301,0,-1,0,0,0,18,0,0,1498870800);
INSERT INTO race VALUES(9826,7,100,10811,9031,'snd_mfx_3005_CL','snd_mfx_3005_CL','','',9030,119,0,0,0,0,304,0,-1,0,0,0,16,0,0,1645704000);
INSERT INTO race VALUES(9867,7,100,10811,9032,'snd_mfx_3005_CL','snd_mfx_3005_CL','','',9030,119,0,0,0,0,304,0,-1,0,0,0,16,0,0,1645704000);
INSERT INTO race VALUES(9908,7,100,10811,9033,'snd_mfx_3005_CL','snd_mfx_3005_CL','','',9030,119,0,0,0,0,304,0,-1,0,0,0,16,0,0,1645704000);
INSERT INTO race VALUES(10165,12,100,10811,1006,'snd_mfx_1002_CL','snd_mfx_1002_CL','snd_mfx_r_1002_CL','snd_mfx_r_1002_CL',1006,102,0,0,0,0,1,1,-1,0,0,0,18,0,0,1623326400);
INSERT INTO race VALUES(12000,8,100,10811,5930,'snd_mfx_2003_CL','snd_mfx_2003_CL','','',5930,102,0,0,0,0,1,1,-1,0,0,0,18,0,0,1652184000);
INSERT INTO race VALUES(16305,10,1000,10811,6101,'snd_mfx_3003_CL','snd_mfx_3003_CL','','',6100,121,0,0,0,0,0,0,-1,0,0,3,12,0,0,1783029600);
INSERT INTO race VALUES(1101,1,100,11103,1101,'snd_mfx_1015_CL','snd_mfx_1015_CL','snd_mfx_r_1015_CL','snd_mfx_r_1015_CL',1101,313,0,0,100,0,1,0,-1,0,0,0,16,0,1,1498870800);
INSERT INTO race VALUES(1102,1,100,11103,1102,'snd_mfx_1015_CL','snd_mfx_1015_CL','snd_mfx_r_1015_CL','snd_mfx_r_1015_CL',1102,313,0,0,100,0,2,0,-1,0,0,0,16,0,1,1498870800);
INSERT INTO race VALUES(1105,1,100,11103,1105,'snd_mfx_1015_CL','snd_mfx_1015_CL','snd_mfx_r_1015_CL','snd_mfx_r_1015_CL',1105,313,0,0,100,0,5,0,-1,0,0,0,16,0,1,1498870800);
INSERT INTO race VALUES(1106,1,100,11103,1106,'snd_mfx_1014_CL','snd_mfx_1014_CL','snd_mfx_r_1014_CL','snd_mfx_r_1014_CL',1106,313,0,0,100,0,6,0,-1,0,0,0,16,0,1,1498870800);
INSERT INTO race VALUES(4924,61,100,11103,1101,'snd_mfx_1015_CL','snd_mfx_1015_CL','','',1101,313,0,0,100,0,1,0,-1,0,0,0,16,0,1,1498870800);
INSERT INTO race VALUES(4925,61,100,11103,1102,'snd_mfx_1015_CL','snd_mfx_1015_CL','','',1102,313,0,0,100,0,2,0,-1,0,0,0,16,0,1,1498870800);
INSERT INTO race VALUES(4928,61,100,11103,1105,'snd_mfx_1015_CL','snd_mfx_1015_CL','','',1105,313,0,0,100,0,5,0,-1,0,0,0,16,0,1,1498870800);
INSERT INTO race VALUES(4929,61,100,11103,1106,'snd_mfx_1014_CL','snd_mfx_1014_CL','','',1106,313,0,0,100,0,6,0,-1,0,0,0,16,0,1,1498870800);
INSERT INTO race VALUES(5105,6,900,11103,5002,'snd_mfx_2009_CL','snd_mfx_2009_CL','','',5002,315,0,0,100,0,0,0,-1,0,0,1,16,0,1,1636977600);
INSERT INTO race VALUES(5132,6,100,11103,1101,'snd_mfx_2009_CL','snd_mfx_2009_CL','','',1101,315,0,0,100,0,1,0,-1,0,0,1,16,0,1,1636977600);
INSERT INTO race VALUES(5133,6,100,11103,1102,'snd_mfx_2009_CL','snd_mfx_2009_CL','','',1102,315,0,0,100,0,2,0,-1,0,0,1,16,0,1,1636977600);
INSERT INTO race VALUES(5136,6,100,11103,1105,'snd_mfx_2009_CL','snd_mfx_2009_CL','','',1105,315,0,0,100,0,5,0,-1,0,0,1,16,0,1,1636977600);
INSERT INTO race VALUES(5137,6,100,11103,1106,'snd_mfx_2009_CL','snd_mfx_2009_CL','','',1106,315,0,0,100,0,6,0,-1,0,0,1,16,0,1,1636977600);
INSERT INTO race VALUES(5290,12,999,11103,5200,'snd_mfx_2008_CL','snd_mfx_2008_CL','','',5200,121,0,0,100,0,0,0,-1,0,0,0,16,0,1,1627560000);
INSERT INTO race VALUES(10184,12,100,11103,1101,'snd_mfx_1015_CL','snd_mfx_1015_CL','snd_mfx_r_1015_CL','snd_mfx_r_1015_CL',1101,313,0,0,100,0,1,0,-1,0,0,0,16,0,1,1623326400);
INSERT INTO race VALUES(10185,12,100,11103,1102,'snd_mfx_1015_CL','snd_mfx_1015_CL','snd_mfx_r_1015_CL','snd_mfx_r_1015_CL',1102,313,0,0,100,0,2,0,-1,0,0,0,16,0,1,1623326400);
INSERT INTO race VALUES(10188,12,100,11103,1105,'snd_mfx_1015_CL','snd_mfx_1015_CL','snd_mfx_r_1015_CL','snd_mfx_r_1015_CL',1105,313,0,0,100,0,5,0,-1,0,0,0,16,0,1,1623326400);
INSERT INTO race VALUES(10189,12,100,11103,1106,'snd_mfx_1014_CL','snd_mfx_1014_CL','snd_mfx_r_1014_CL','snd_mfx_r_1014_CL',1106,313,0,0,100,0,6,0,-1,0,0,0,16,0,1,1623326400);
INSERT INTO race VALUES(1201,1,100,11203,1023,'snd_mfx_1001_CL','snd_mfx_1001_CL','','',1023,101,0,0,201,101,1,1,-1,0,0,0,18,0,0,1498870800);
INSERT INTO race VALUES(1119,1,100,11504,1105,'snd_mfx_1018_CL','snd_mfx_1018_CL','snd_mfx_r_1018_CL','snd_mfx_r_1018_CL',1119,133,0,0,105,0,2,0,-1,0,0,0,16,0,1,1660910400);
INSERT INTO race VALUES(3076,1,300,11504,3076,'snd_mfx_1019_CL','snd_mfx_1019_CL','snd_mfx_r_1019_CL','snd_mfx_r_1019_CL',3076,234,0,0,105,0,0,0,-1,0,0,0,14,0,1,1660910400);
INSERT INTO race VALUES(5149,6,900,11504,5002,'snd_mfx_2009_CL','snd_mfx_2009_CL','','',5002,234,0,0,105,0,0,0,-1,0,0,1,16,0,1,1660910400);
INSERT INTO race VALUES(5300,12,999,11504,5200,'snd_mfx_2008_CL','snd_mfx_2008_CL','','',5200,121,0,0,105,0,0,0,-1,0,0,0,16,0,1,1660910400);
+5 -3
View File
@@ -46,9 +46,11 @@ type RacecourseSpan struct {
Start float32 `json:"start"`
// End is the distance in meters along the track at which the span ends.
End float32 `json:"end"`
// Straight is the straight type if the span is formally a straight.
// 1 indicates the front stretch and 2 the backstretch.
Straight int8 `json:"straight,omitzero"`
// Straight is whether the span is formally a straight.
Straight bool `json:"straight,omitzero"`
// FarStraight is whether the span is the backstretch.
// If true, then Straight is also true.
FarStraight bool `json:"far_straight,omitzero"`
// Corner is the corner number of the span, or zero if not a corner.
Corner int8 `json:"corner,omitzero"`
}
+4 -100
View File
@@ -1,9 +1,6 @@
package ism
import (
"git.sunturtle.xyz/zephyr/horse"
"git.sunturtle.xyz/zephyr/horse/umadump"
)
import "git.sunturtle.xyz/zephyr/horse"
type Skill struct {
ID horse.SkillID `json:"skill_id"`
@@ -228,106 +225,13 @@ type AddItem struct {
Number int32 `json:"number"`
}
type PieceData struct {
PieceID int32 `json:"piece_id"`
PieceNum int32 `json:"piece_num"`
}
type UserCard struct {
CardID horse.UmaID `json:"card_id"`
Rarity int8 `json:"rarity"`
TalentLevel int8 `json:"talent_level"`
Skills []Skill `json:"skill_data_array"`
CreateTime string `json:"create_time"`
}
type UserSupportCard struct {
ViewerID int64 `json:"viewer_id"`
SupportCardID horse.SupportCardID `json:"support_card_id"`
Exp int32 `json:"exp"`
LimitBreak int32 `json:"limit_break_count"`
FavoriteFlag int32 `json:"favorite_flag"`
Stock int32 `json:"stock"`
PossessTime string `json:"possess_time"`
}
type RewardAddSupportCardNum struct {
SupportCardID horse.SupportCardID `json:"support_card_id"`
Number int32 `json:"number"`
ItemType int32 `json:"item_type"`
}
type HonorData struct {
HonorID int32 `json:"honor_id"`
Step int32 `json:"step"`
CreateTime string `json:"create_time"`
}
type UserChara struct {
CharaID horse.CharacterID `json:"chara_id"`
TrainingNum int32 `json:"training_num"`
LovePoint int32 `json:"love_point"`
LovePointPool int32 `json:"love_point_pool"`
Fan uint64 `json:"fan"`
}
type UserCloth struct {
ClothID int32 `json:"cloth_id"`
}
type UserMusic struct {
MusicID int32 `json:"music_id"`
AcquisitionTime string `json:"acquisition_time"`
}
type CharaProfileData struct {
CharaID horse.CharacterID `json:"chara_id"`
DataID int32 `json:"data_id"`
NewFlag int32 `json:"new_flag"`
}
type RewardSummary struct {
AddItem []AddItem `json:"add_item_list"`
AddPiece []PieceData `json:"add_piece_list"`
AddCard []UserCard `json:"add_card_list"`
AddCardBonus *RewardSummary `json:"add_card_bonus_info"`
AddSupportCard []UserSupportCard `json:"add_support_card_list"`
AddSupportCardNum []RewardAddSupportCardNum `json:"add_support_card_num_array"`
AddHonor []HonorData `json:"add_honor_list"`
AddChara []UserChara `json:"add_chara_list"`
AddCloth []UserCloth `json:"add_cloth_list"`
AddMusic []UserMusic `json:"add_music_list"`
AddStoryIDs []umadump.Never `json:"add_story_id_array"` // not in my disassembly
AddFCoin int32 `json:"add_fcoin"` // carats
AddPresents int32 `json:"add_present_num"`
AddTotalFan int32 `json:"add_total_fan"`
NewCharaProfiles []CharaProfileData `json:"new_chara_profile_array"`
ForceUpdateHonorID int32 `json:"force_update_honor_id"`
AddItem []AddItem `json:"add_item_list"`
}
type End struct {
Chara SingleModeChara `json:"chara_info"`
RaceConditions []umadump.Never `json:"race_condition_array"`
UncheckedEvents []umadump.Never `json:"unchecked_event_array"`
HomeInfo *umadump.Never `json:"home_info"`
WinSaddleIDs []umadump.Never `json:"win_saddle_id_array"`
EffectedFactors []umadump.Never `json:"effected_factor_array"`
RaceStartInfo *umadump.Never `json:"race_start_info"`
RaceScenario *umadump.Never `json:"race_scenario"`
AddTrophyInfo *umadump.Never `json:"add_trophy_info"`
TrophyRewardInfo *umadump.Never `json:"trophy_reward_info"`
PrevCharaGrade *umadump.Never `json:"prev_chara_grade"`
RaceAddRewardInfo []umadump.Never `json:"race_add_reward_info"`
Missions []umadump.Never `json:"mission_list"`
StoryEventMissions []umadump.Never `json:"story_event_mission_list"`
StoryEventCharaBonuses []umadump.Never `json:"story_event_chara_bonus_list"`
StartDressInfo []umadump.Never `json:"start_dress_info"`
ResumeFactorSelect *umadump.Never `json:"resume_factor_select"`
RaceRandomPrograms []umadump.Never `json:"race_random_program_array"`
RaceRewardLimitMore []umadump.Never `json:"race_reward_limit_more_list"`
SkillFilterSettings []umadump.Never `json:"skill_filter_setting_array"`
RewardSummary RewardSummary `json:"reward_summary_info"`
IsUmaplan bool `json:"is_umaplan"`
Chara SingleModeChara `json:"chara_info"`
RewardSummary RewardSummary `json:"reward_summary_info"`
}
type ProgressInfo struct {
-13
View File
@@ -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
-29
View File
@@ -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]]
}
-29
View File
@@ -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]]
}
-32
View File
@@ -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 -356
View File
@@ -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,335 +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"`
FanCount int32 `json:"fan_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"`
@@ -878,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
-182
View File
@@ -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))
}
}
-25
View File
@@ -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
-20
View File
@@ -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>
-1
View File
@@ -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,
-5
View File
@@ -106,11 +106,6 @@ export const PAGES = {
name: 'Tagged Skills Explorer',
description: 'View skills matching the tags internal to the game.',
},
{
route: resolve('/doc/fans'),
name: 'Career Fan Gain Is Solved',
description: 'The exact formula for fan gain from career races – nothing "random" about it.'
},
] satisfies Page[],
} as const;
File diff suppressed because it is too large Load Diff
+23 -23
View File
@@ -76,36 +76,36 @@ export interface SectionInfo {
section: number;
phase: Phase;
endRate: number;
posKeep?: boolean;
rush?: boolean;
spotStruggleEnter?: boolean;
posKeep: boolean;
rush: boolean;
spotStruggleEnter: boolean;
}
export const SECTIONS: ReadonlyArray<SectionInfo> = [
{ section: 1, phase: Phase.EarlyRace, endRate: 1 / 24, posKeep: true },
{ section: 1, phase: Phase.EarlyRace, endRate: 1 / 24, posKeep: true, rush: false, spotStruggleEnter: false },
{ section: 2, phase: Phase.EarlyRace, endRate: 2 / 24, posKeep: true, rush: true, spotStruggleEnter: true },
{ section: 3, phase: Phase.EarlyRace, endRate: 3 / 24, posKeep: true, rush: true, spotStruggleEnter: true },
{ section: 4, phase: Phase.EarlyRace, endRate: 4 / 24, posKeep: true, rush: true, spotStruggleEnter: true },
{ section: 5, phase: Phase.MidRace, endRate: 5 / 24, posKeep: true, rush: true, spotStruggleEnter: true },
{ section: 6, phase: Phase.MidRace, endRate: 6 / 24, posKeep: true, rush: true },
{ section: 7, phase: Phase.MidRace, endRate: 7 / 24, posKeep: true, rush: true },
{ section: 8, phase: Phase.MidRace, endRate: 8 / 24, posKeep: true, rush: true },
{ section: 9, phase: Phase.MidRace, endRate: 9 / 24, posKeep: true, rush: true },
{ section: 10, phase: Phase.MidRace, endRate: 10 / 24, posKeep: true },
{ section: 11, phase: Phase.MidRace, endRate: 11 / 24 },
{ section: 12, phase: Phase.MidRace, endRate: 12 / 24 },
{ section: 13, phase: Phase.MidRace, endRate: 13 / 24 },
{ section: 14, phase: Phase.MidRace, endRate: 14 / 24 },
{ section: 15, phase: Phase.MidRace, endRate: 15 / 24 },
{ section: 16, phase: Phase.MidRace, endRate: 16 / 24 },
{ section: 17, phase: Phase.LateRace, endRate: 17 / 24 },
{ section: 18, phase: Phase.LateRace, endRate: 18 / 24 },
{ section: 19, phase: Phase.LateRace, endRate: 19 / 24 },
{ section: 20, phase: Phase.LateRace, endRate: 20 / 24 },
{ section: 21, phase: Phase.LastSpurt, endRate: 21 / 24 },
{ section: 22, phase: Phase.LastSpurt, endRate: 22 / 24 },
{ section: 23, phase: Phase.LastSpurt, endRate: 23 / 24 },
{ section: 24, phase: Phase.LastSpurt, endRate: 24 / 24 },
{ section: 6, phase: Phase.MidRace, endRate: 6 / 24, posKeep: true, rush: true, spotStruggleEnter: false },
{ section: 7, phase: Phase.MidRace, endRate: 7 / 24, posKeep: true, rush: true, spotStruggleEnter: false },
{ section: 8, phase: Phase.MidRace, endRate: 8 / 24, posKeep: true, rush: true, spotStruggleEnter: false },
{ section: 9, phase: Phase.MidRace, endRate: 9 / 24, posKeep: true, rush: true, spotStruggleEnter: false },
{ section: 10, phase: Phase.MidRace, endRate: 10 / 24, posKeep: true, rush: false, spotStruggleEnter: false },
{ section: 11, phase: Phase.MidRace, endRate: 11 / 24, posKeep: false, rush: false, spotStruggleEnter: false },
{ section: 12, phase: Phase.MidRace, endRate: 12 / 24, posKeep: false, rush: false, spotStruggleEnter: false },
{ section: 13, phase: Phase.MidRace, endRate: 13 / 24, posKeep: false, rush: false, spotStruggleEnter: false },
{ section: 14, phase: Phase.MidRace, endRate: 14 / 24, posKeep: false, rush: false, spotStruggleEnter: false },
{ section: 15, phase: Phase.MidRace, endRate: 15 / 24, posKeep: false, rush: false, spotStruggleEnter: false },
{ section: 16, phase: Phase.MidRace, endRate: 16 / 24, posKeep: false, rush: false, spotStruggleEnter: false },
{ section: 17, phase: Phase.LateRace, endRate: 17 / 24, posKeep: false, rush: false, spotStruggleEnter: false },
{ section: 18, phase: Phase.LateRace, endRate: 18 / 24, posKeep: false, rush: false, spotStruggleEnter: false },
{ section: 19, phase: Phase.LateRace, endRate: 19 / 24, posKeep: false, rush: false, spotStruggleEnter: false },
{ section: 20, phase: Phase.LateRace, endRate: 20 / 24, posKeep: false, rush: false, spotStruggleEnter: false },
{ section: 21, phase: Phase.LateRace, endRate: 21 / 24, posKeep: false, rush: false, spotStruggleEnter: false },
{ section: 22, phase: Phase.LateRace, endRate: 22 / 24, posKeep: false, rush: false, spotStruggleEnter: false },
{ section: 23, phase: Phase.LateRace, endRate: 23 / 24, posKeep: false, rush: false, spotStruggleEnter: false },
{ section: 24, phase: Phase.LateRace, endRate: 24 / 24, posKeep: false, rush: false, spotStruggleEnter: false },
];
export interface SectionSlopeSegment extends SectionInfo {
-4
View File
@@ -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.
*/
-16
View File
@@ -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,
+40 -45
View File
@@ -8,11 +8,11 @@ import { binomPMF } from './prob';
* Fundamental stats of umas.
*/
export enum Stat {
Speed = 1,
Stamina = 2,
Power = 3,
Guts = 4,
Wit = 5,
Speed,
Stamina,
Power,
Guts,
Wit,
}
/**
@@ -118,15 +118,14 @@ export function distance(raceLen: number): Distance {
/**
* Get the distances at which each phase of a race ends.
* @param raceLen Length of the race in meters
* @returns Ends of each phase in meters, including separate late and spurt phases
* @returns Ends of each phase in meters
*/
export function phases(raceLen: number) {
const sixth = raceLen / 6;
return {
[Phase.EarlyRace]: sixth,
[Phase.MidRace]: 4 * sixth,
[Phase.LateRace]: 5 * sixth,
[Phase.LastSpurt]: raceLen,
[Phase.LateRace]: raceLen,
};
}
@@ -134,18 +133,18 @@ export function phases(raceLen: number) {
* Race surfaces.
*/
export enum Surface {
Turf = 1,
Dirt = 2,
Turf,
Dirt,
}
/**
* Race ground condition types.
*/
export enum GroundConditions {
Firm = 1,
Good = 2,
Soft = 3,
Heavy = 4,
Firm,
Good,
Soft,
Heavy,
}
/**
@@ -328,12 +327,12 @@ export const RUNNING_STYLES = [
/**
* Race phases.
* While last spurt phase is also a phase, it is not distinguished here.
*/
export enum Phase {
EarlyRace = 0,
MidRace = 1,
LateRace = 2,
LastSpurt = 3,
EarlyRace,
MidRace,
LateRace,
}
const hpStrategyCoeff = {
@@ -408,7 +407,7 @@ export function hpPerSecond(
const pdmMod = pdm ? 0.6 : 1;
const damMod = dam ? 0.4 : 1;
const groundMod = groundHPRateMod[surface][conditions];
const gutsMod = phase >= Phase.LateRace ? 1 + 200 / (math.sqrt(600 * gutsStat) as number) : 1;
const gutsMod = phase === Phase.LateRace ? 1 + 200 / (math.sqrt(600 * gutsStat) as number) : 1;
const sp = currentSpeed - baseSpeed(raceLen) + 12;
return (20 / 144) * sp * sp * rushedMod * pdmMod * damMod * groundMod * gutsMod;
}
@@ -448,11 +447,11 @@ export function baseSpeed(raceLen: number): number {
}
const speedStrategyPhaseCoeff = [
[1.0, 0.98, 0.962, 0.962],
[0.978, 0.991, 0.975, 0.975],
[0.938, 0.998, 0.994, 0.994],
[0.931, 1.0, 1.0, 1.0],
[1.063, 0.962, 0.95, 0.95],
[1.0, 0.98, 0.962],
[0.978, 0.991, 0.975],
[0.938, 0.998, 0.994],
[0.931, 1.0, 1.0],
[1.063, 0.962, 0.95],
] as const;
const distanceProficiencyMod: Readonly<Record<AptitudeLevel, number>> = {
@@ -472,11 +471,7 @@ const distanceProficiencyMod: Readonly<Record<AptitudeLevel, number>> = {
* @param style Horse's running style
* @param phase Phase to calculate for
*/
export function baseTargetSpeed(
raceLen: number,
style: RunningStyle,
phase: Exclude<Phase, Phase.LateRace | Phase.LastSpurt>,
): number;
export function baseTargetSpeed(raceLen: number, style: RunningStyle, phase: Exclude<Phase, Phase.LateRace>): number;
/**
* Get a horse's base target speed when not spurting during late race.
* @param raceLen Length of the race in meters
@@ -488,7 +483,7 @@ export function baseTargetSpeed(
export function baseTargetSpeed(
raceLen: number,
style: RunningStyle,
phase: Phase.LateRace | Phase.LastSpurt,
phase: Phase.LateRace,
speedStat: number,
distanceApt: AptitudeLevel,
): number;
@@ -502,7 +497,7 @@ export function baseTargetSpeed(
const base = baseSpeed(raceLen);
const baseTarget = base * speedStrategyPhaseCoeff[style][phase];
const late =
phase >= Phase.LateRace ? (math.sqrt(500 * speedStat!) as number) * distanceProficiencyMod[distanceApt!] * 0.002 : 0;
phase === Phase.LateRace ? (math.sqrt(500 * speedStat!) as number) * distanceProficiencyMod[distanceApt!] * 0.002 : 0;
return baseTarget + late;
}
@@ -517,7 +512,7 @@ export function sectionSpeed(
raceLen: number,
witStat: number,
style: RunningStyle,
phase: Exclude<Phase, Phase.LateRace | Phase.LastSpurt>,
phase: Exclude<Phase, Phase.LateRace>,
): [number, number];
/**
* Calculate the range of section speed values for a horse not spurting during late race.
@@ -534,7 +529,7 @@ export function sectionSpeed(
witStat: number,
style: RunningStyle,
distance: AptitudeLevel,
phase: Phase.LateRace | Phase.LastSpurt,
phase: Phase.LateRace,
): [number, number];
export function sectionSpeed(
raceLen: number,
@@ -542,7 +537,7 @@ export function sectionSpeed(
witStatOrStyle: number | RunningStyle,
styleOrPhase: RunningStyle | Phase,
distance?: AptitudeLevel,
lateRace?: Phase.LateRace | Phase.LastSpurt,
lateRace?: Phase.LateRace,
): [number, number] {
const speedStat = lateRace !== undefined ? speedStatOrWitStat : 0;
const witStat = lateRace !== undefined ? witStatOrStyle : speedStatOrWitStat;
@@ -551,7 +546,7 @@ export function sectionSpeed(
const base = baseSpeed(raceLen);
const baseTarget = base * speedStrategyPhaseCoeff[style][phase];
const late =
phase >= Phase.LateRace
phase === Phase.LateRace
? (math.sqrt(500 * speedStat) as number) * distanceProficiencyMod[distance ?? AptitudeLevel.A] * 0.002
: 0;
const u = (witStat / 550000) * math.log10(witStat * 0.1);
@@ -625,11 +620,11 @@ export const COURSE_WIDTH = 11.25;
export const LANE_WIDTH = COURSE_WIDTH / 18;
const accelStrategyPhaseCoeff = {
[RunningStyle.FrontRunner]: [1.0, 1.0, 0.996, 0.996],
[RunningStyle.PaceChaser]: [0.985, 1.0, 0.996, 0.996],
[RunningStyle.LateSurger]: [0.975, 1.0, 1.0, 1.0],
[RunningStyle.EndCloser]: [0.945, 1.0, 0.997, 0.997],
[RunningStyle.Runaway]: [1.17, 0.94, 0.956, 0.956],
[RunningStyle.FrontRunner]: [1.0, 1.0, 0.996],
[RunningStyle.PaceChaser]: [0.985, 1.0, 0.996],
[RunningStyle.LateSurger]: [0.975, 1.0, 1.0],
[RunningStyle.EndCloser]: [0.945, 1.0, 0.997],
[RunningStyle.Runaway]: [1.17, 0.94, 0.956],
} as const;
const surfaceProficiencyMod: Readonly<Record<AptitudeLevel, number>> = {
@@ -686,7 +681,6 @@ const phaseDecel = {
[Phase.EarlyRace]: -1.2,
[Phase.MidRace]: -0.8,
[Phase.LateRace]: -1.0,
[Phase.LastSpurt]: -1.0,
} as const;
/**
@@ -701,7 +695,9 @@ export function deceleration(phase: Phase, pdm?: boolean, dead?: boolean): numbe
return -1.2;
}
if (pdm) {
return -0.5;
// This isn't until 1.5anni.
// return -0.5;
return phaseDecel[phase];
}
return phaseDecel[phase];
}
@@ -775,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;
}
-14
View File
@@ -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>;
+8 -57
View File
@@ -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">
-223
View File
@@ -1,223 +0,0 @@
<script lang="ts">
import { asset, resolve } from '$app/paths';
import CalcInfo from '../../race/CalcInfo.svelte';
import Article from '../Article.svelte';
import Sec from '../Sec.svelte';
import * as fans from './fans';
let baseFans = $state(700);
let fanBonus = $state(0);
let finishOrder = $state(1);
let margin = $state(0);
let skills = $state(0);
let glowsticks = $state(false);
const marginFans = $derived(fans.marginFans(baseFans, finishOrder, margin));
const skillFans = $derived(fans.skillFans(baseFans, skills));
const glowstickBonus = $derived(glowsticks ? 50 : 0);
const gainedFans = $derived(fans.gained(baseFans, marginFans, skillFans, fanBonus, glowstickBonus));
const marginType = $derived(finishOrder === 1 ? 'Win Margin' : 'Margin vs. Winner');
const orderPct = [
[1, 100],
[2, 40],
[3, 25],
[4, 15],
[5, 10],
[6, 9],
[7, 8],
[8, 7],
[9, 6],
[10, 5],
[11, 4],
[12, 3],
[13, 2.5],
[14, 2],
[15, 1.5],
[16, 1],
[17, 1],
[18, 1],
] as const;
const marginBonus = [
['Nose – 3/4 L', 0, 9],
['1 L – 2.5 L', 2, 6],
['3 L – 4 L', 4, 4],
['5 L – 6 L', 6, 2],
['7L – distance', 9, 0],
] as const;
const skillBonus = [
['0', 0],
['1-3', 2],
['4-6', 3],
['7-9', 5],
['10+', 8],
] as const;
</script>
<Article>
{#snippet head()}
<Sec h={1} id="top" class="text-center pointer-coarse:mb-8">Career Fan Gain Is Solved</Sec>
<p>
Thanks to work by Moxa and Werseter on the Hakuraku Discord, a precise formula for fans gained from career races has been
found.
</p>
<p>
There is no random component to fan gain, except insofar as the race itself is random. It is now known to be entirely
determined by five factors:
</p>
<ul class="mb-4 list-disc pl-4">
<li>Base fans, according to the race and finish placement.</li>
<li>Fan bonus from support cards.</li>
<li>Margin of the win, or margin behind the winner if the player's trainee did not win.</li>
<li>Number of skills the trainee activated during the race.</li>
<li>In Trackblazer/MANT, use of glowsticks.</li>
</ul>
<p>
The identified formula perfectly fits hundreds of recorded career race gains, including losses. Some questions remain, but
the results so far have important implications both for fan runs and for low fan bonus decks for which debut can fall short
of fan requirements for early career goals.
</p>
{/snippet}
<Sec h={2} id="calc-fans">Calculate Fans</Sec>
<p>This tool will calculate your exact fan gain from a race.</p>
<form class="mx-auto mb-4 grid grid-cols-1 gap-2 rounded-md p-4 text-center shadow-md ring md:max-w-2xl md:grid-cols-3">
<div>
<label for="calc-base-fans">Base Fans</label>
<input id="calc-base-fans" class="max-w-32" type="number" min="0" max="30000" step="100" bind:value={baseFans} />
</div>
<div>
<label for="calc-fan-bonus">Fan Bonus</label>
<input id="calc-fan-bonus" class="max-w-32" type="number" min="0" max="150" step="5" bind:value={fanBonus} />
</div>
<div>
<label for="calc-finish-order">Finish Order</label>
<input id="calc-finish-order" class="max-w-32" type="number" min="1" max="18" step="1" bind:value={finishOrder} />
</div>
<div>
<label for="calc-margin">{marginType} (L)</label>
<input id="calc-margin" class="max-w-32" type="number" min="0" step="0.25" bind:value={margin} />
</div>
<div>
<label for="calc-skills">Activated Skills</label>
<input id="calc-skills" class="max-w-32" type="number" min="0" step="1" bind:value={skills} />
</div>
<div class="my-auto">
<input id="calc-glowsticks" class="min-h-6 min-w-6 align-middle" type="checkbox" bind:checked={glowsticks} />
<label for="calc-glowsticks">Glowsticks</label>
</div>
</form>
<div class="grid grid-cols-1 md:grid-cols-12">
<CalcInfo title="Fans from Margin" class="md:col-span-4 md:col-start-3">{marginFans}</CalcInfo>
<CalcInfo title="Fans from Skills" class="md:col-span-4">{skillFans}</CalcInfo>
<CalcInfo title="Fans Gained" class="md:col-span-4 md:col-start-5">{gainedFans}</CalcInfo>
</div>
<Sec h={2} id="base-fans">Base Fans</Sec>
<p>
Base fans is a parameter per race and finish placement, defined in <a href={resolve('/doc/mdb')}>master data</a>. The number
shown in the career race selection menu is the base fans for first place. While it is defined separately for each race and
finish order, every race currently follows the same curve for all placements.
</p>
<table class="mx-auto mb-4 border text-center">
<thead>
<tr>
<th scope="col" class="px-2">Placement</th>
<th scope="col" class="px-2">Fan Ratio</th>
</tr>
</thead>
<tbody>
{#each orderPct as [o, p] (o)}
<tr class="even:bg-mist-300 dark:even:bg-mist-900">
<td>{o}</td>
<td>{p}%</td>
</tr>
{/each}
</tbody>
</table>
<Sec h={2} id="margin">Fans from Margin</Sec>
<p>
When the trainee places in the top three (top five?), she receives a bonus percentage of base fans according to the finish
margin.
</p>
<p>
The bonus depends on whether the trainee won the race. If so, it is calculated by her margin versus second place. Otherwise,
her total margin behind the winner is used. If she did not place in the top three (top five?), then she gains no fans from
margin.
</p>
<table class="mx-auto mb-4 border text-center">
<thead>
<tr>
<th scope="col" class="px-2">Actual<br />Margin Within</th>
<th scope="col" class="px-2">Bonus for Winner</th>
<th scope="col" class="px-2">Bonus for Podium</th>
</tr>
</thead>
<tbody>
{#each marginBonus as [m, w, l] (m)}
<tr class="even:bg-mist-300 dark:even:bg-mist-900">
<td>{m}</td>
<td>{w}%</td>
<td>{l}%</td>
</tr>
{/each}
</tbody>
</table>
<Sec h={2} id="skills">Fans from Skill Activations</Sec>
<p>The trainee receives a bonus percentage of base fans according to the number of skills she activated during the race.</p>
<table class="mx-auto mb-4 border text-center">
<thead>
<tr>
<th scope="col" class="px-2">Activated Skills</th>
<th scope="col" class="px-2">Bonus</th>
</tr>
</thead>
<tbody>
{#each skillBonus as [n, b] (n)}
<tr class="even:bg-mist-300 dark:even:bg-mist-900">
<td>{n}</td>
<td>{b}%</td>
</tr>
{/each}
</tbody>
</table>
<Sec h={2} id="rounding">Calculation Order and Rounding</Sec>
<p>The calculation is perfomed as if in the following order.</p>
<ol class="mb-4 list-decimal pl-4">
<li>Calculate fans from win margin and round down.</li>
<li>Calculate fans from skill activation count and round down.</li>
<li>Calculate the sum of base fans, win margin fans, and skill activation fans.</li>
<li>Apply fan bonus to the sum and round to the nearest integer with halfway cases away from zero.</li>
<li>(Trackblazer/MANT) If glowsticks were used for the race, apply their multiplier and round down.</li>
</ol>
<Sec h={2} id="data">Data and Limitations</Sec>
<p>
The data for this research comes from 193 races and fan results dumped using <a
href="https://werseter.github.io/umadump/"
target="_blank"
rel="noopener noreferrer">Umadump</a
>. The races come from sixteen careers run between 19 Aug and 11 Oct 2026. These careers include five different values of race
bonus ranging from 55 to 105. The identified formula predicts the actual fan gain perfectly for all of the races. You can
<a
href="https://docs.google.com/spreadsheets/d/1_jtOv6qk9dP4jJTagJqG53Pvj48IVd6gl2zKpyT6Kvs/edit?gid=463816108#gid=463816108"
target="_blank"
rel="noopener noreferrer">view the data</a
>.
</p>
<p>
There are some gaps in the data. No collected race had a finish placement of 4th or 5th, nor lower than 6th, so the exact
details of the win margin fan bonus remain open. Similarly, no race featured a trainee who activated more than ten skills, so
it is unknown whether there are further tiers of skill activation count fan bonus.
</p>
<p>
Once these edge cases are covered, this article will be updated. If you'd like to contribute, please contact me
(@zephyrtronium) via Discord on the Hakuraku, uma.moe, GameTora, or EoG servers.
</p>
</Article>
-58
View File
@@ -1,58 +0,0 @@
const margins = [
[0.75, 0.0, 0.09],
[2.5, 0.02, 0.06],
[4, 0.04, 0.04],
[6, 0.06, 0.02],
[Infinity, 0.09, 0.0],
] as const;
/**
* Calculate fans gained from a career race due to the margin of the finish.
* @param baseFans Base fans from the race and finish order
* @param finishOrder Placement of the trainee
* @param margin Margin in lengths between the trainee and second if a win, or the winner and trainee if a loss
* @returns Fans gained due to finish margin
*/
export function marginFans(baseFans: number, finishOrder: number, margin: number): number {
if (finishOrder > 3) {
return 0;
}
const [, wb, lb] = margins.find(([m]) => margin < m)!;
const b = finishOrder === 1 ? wb : lb;
return Math.floor(baseFans * b);
}
const skills = [
[0, 0.0],
[3, 0.02],
[6, 0.03],
[9, 0.05],
[Infinity, 0.08],
] as const;
/**
* Calculate the fans gained from a career race due to skills activated.
* @param baseFans Base fans from the race and finish order
* @param skillsActivated Number of skills the trainee activated during the race
* @returns Fans gained due to skill activations
*/
export function skillFans(baseFans: number, skillsActivated: number): number {
const [, b] = skills.find(([n]) => skillsActivated <= n)!;
return Math.floor(baseFans * b);
}
/**
* Calculate fan gain from a career race.
* @param baseFans Base fans from the race and finish order
* @param marginFans Fans gained due to finish margin
* @param skillFans Fans gained due to skill activations
* @param fanBonus Total fan bonus from support cards
* @param itemBonus Fan bonus from items (MANT glowsticks)
* @returns Total fans gained
*/
export function gained(baseFans: number, marginFans: number, skillFans: number, fanBonus: number, itemBonus?: number): number {
const f = baseFans + marginFans + skillFans;
const d = Math.round(f * (1 + fanBonus / 100));
const b = itemBonus ?? 0;
return Math.floor(d * (1 + b / 100));
}
+29 -11
View File
@@ -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)}
+16 -15
View File
@@ -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>
+12 -6
View File
@@ -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);
@@ -99,8 +98,8 @@
const distance = $derived([last(seggs[0]).end.x, last(seggs[1]).end.x] as const);
const time = $derived([last(seggs[0]).end.t, last(seggs[1]).end.t] as const);
const finishTime = $derived([
time[0] + (raceLen - distance[0]) / spurtSpeed,
time[1] + (raceLen - distance[1]) / spurtSpeed,
time[0] + (phases[race.Phase.LateRace] - distance[0]) / spurtSpeed,
time[1] + (phases[race.Phase.LateRace] - distance[1]) / spurtSpeed,
] as const);
function gainLengths(fast: accel.Instant, slow: accel.Instant): number {
const m = fast.v * (slow.t - fast.t) + fast.x - slow.x;
@@ -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>
+10 -4
View File
@@ -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>
+2 -2
View File
@@ -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>
+2 -2
View File
@@ -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>
+10 -6
View File
@@ -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';
@@ -103,10 +102,6 @@
race.spurtSpeed(stats[race.Stat.Speed], stats[race.Stat.Guts], style, distanceApt, raceLen),
race.spurtSpeed(stats[race.Stat.Speed], stats[race.Stat.Guts], style, distanceApt, raceLen),
] as [number, number],
[race.Phase.LastSpurt]: [
race.spurtSpeed(stats[race.Stat.Speed], stats[race.Stat.Guts], style, distanceApt, raceLen),
race.spurtSpeed(stats[race.Stat.Speed], stats[race.Stat.Guts], style, distanceApt, raceLen),
] as [number, number],
});
// const isFront = $derived(style === race.RunningStyle.FrontRunner || style === race.RunningStyle.Runaway);
@@ -282,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>
@@ -1,194 +0,0 @@
career,turn,scenario,character,race,program_id,place,base_fans,deck_bonus_pct,margin_lengths,skill_activations,margin_bonus_pct,skill_bonus_pct,item_bonus_pct,deck_only_fans,actual_fans,extra_fans,extra_pct,predicted_fans,residual_fans
2026-08-19 20:37:27,12,3,[Ashen Miracle] Oguri Cap,Junior Make Debut,1070,1,700,55,4.4727,0,6,0,0,1085.0,1150,65.0,5.9908,1150,0
2026-08-19 20:37:27,23,3,[Ashen Miracle] Oguri Cap,Hanshin Juvenile Fillies,623,6,585,55,1.2941,0,0,0,0,906.75,906,-0.75,-0.0827,906,0
2026-08-19 20:37:27,24,3,[Ashen Miracle] Oguri Cap,Hopeful Stakes,625,1,7000,55,1.1495,0,2,0,0,10850.0,11067,217.0,2.0,11067,0
2026-08-19 20:37:27,33,3,[Ashen Miracle] Oguri Cap,NHK Mile Cup,164,1,10500,55,1.6165,0,2,0,0,16275.0,16601,326.0,2.0031,16601,0
2026-08-19 20:37:27,46,3,[Ashen Miracle] Oguri Cap,Mile Championship,78,1,11000,55,5.3966,5,6,3,0,17050.0,18585,1535.0,9.0029,18585,0
2026-08-19 20:37:27,48,3,[Ashen Miracle] Oguri Cap,Arima Kinen,81,1,30000,55,8.8065,6,9,3,0,46500.0,52080,5580.0,12.0,52080,0
2026-08-19 20:37:27,54,3,[Ashen Miracle] Oguri Cap,Osaka Hai,3,1,13500,55,3.3853,4,4,3,0,20925.0,22390,1465.0,7.0012,22390,0
2026-08-19 20:37:27,57,3,[Ashen Miracle] Oguri Cap,Victoria Mile,5,1,10500,55,4.8613,2,6,2,0,16275.0,17577,1302.0,8.0,17577,0
2026-08-19 20:37:27,68,3,[Ashen Miracle] Oguri Cap,Tenno Sho (Autumn),76,1,15000,55,14.0515,6,9,3,0,23250.0,26040,2790.0,12.0,26040,0
2026-08-19 20:37:27,72,3,[Ashen Miracle] Oguri Cap,Arima Kinen,81,1,30000,55,10.5066,7,9,5,0,46500.0,53010,6510.0,14.0,53010,0
2026-08-19 20:37:27,74,3,[Ashen Miracle] Oguri Cap,URA Finale Qualifier,2015,1,7000,55,6.1557,6,9,3,0,10850.0,12152,1302.0,12.0,12152,0
2026-08-19 20:37:27,76,3,[Ashen Miracle] Oguri Cap,URA Finale Semifinal,2112,1,10000,55,6.906,7,9,5,0,15500.0,17670,2170.0,14.0,17670,0
2026-08-19 20:37:27,78,3,[Ashen Miracle] Oguri Cap,URA Finale Finals,2213,1,30000,55,7.8077,8,9,5,0,46500.0,53010,6510.0,14.0,53010,0
2026-09-08 21:05:53,12,3,[Ashen Miracle] Oguri Cap,Junior Make Debut,1070,1,700,70,2.4747,0,2,0,0,1190.0,1213,23.0,1.9328,1213,0
2026-09-08 21:05:53,23,3,[Ashen Miracle] Oguri Cap,Hanshin Juvenile Fillies,623,3,1625,70,2.5458,0,4,0,0,2762.5,2873,110.5,4.0,2873,0
2026-09-08 21:05:53,32,3,[Ashen Miracle] Oguri Cap,Flora Stakes,173,1,5200,70,0.166,0,0,0,0,8840.0,8840,0.0,0.0,8840,0
2026-09-08 21:05:53,33,3,[Ashen Miracle] Oguri Cap,NHK Mile Cup,164,1,10500,70,0.6636,0,0,0,0,17850.0,17850,0.0,0.0,17850,0
2026-09-08 21:05:53,46,3,[Ashen Miracle] Oguri Cap,Mile Championship,78,1,11000,70,0.3634,0,0,0,0,18700.0,18700,0.0,0.0,18700,0
2026-09-08 21:05:53,48,3,[Ashen Miracle] Oguri Cap,Arima Kinen,81,1,30000,70,3.9924,0,4,0,0,51000.0,53040,2040.0,4.0,53040,0
2026-09-08 21:05:53,54,3,[Ashen Miracle] Oguri Cap,Osaka Hai,3,1,13500,70,3.7863,0,4,0,0,22950.0,23868,918.0,4.0,23868,0
2026-09-08 21:05:53,57,3,[Ashen Miracle] Oguri Cap,Victoria Mile,5,1,10500,70,1.4385,0,2,0,0,17850.0,18207,357.0,2.0,18207,0
2026-09-08 21:05:53,68,3,[Ashen Miracle] Oguri Cap,Tenno Sho (Autumn),76,1,15000,70,3.9784,0,4,0,0,25500.0,26520,1020.0,4.0,26520,0
2026-09-08 21:05:53,72,3,[Ashen Miracle] Oguri Cap,Arima Kinen,81,1,30000,70,7.8092,0,9,0,0,51000.0,55590,4590.0,9.0,55590,0
2026-09-08 21:05:53,74,3,[Ashen Miracle] Oguri Cap,URA Finale Qualifier,2011,1,7000,70,4.2694,0,6,0,0,11900.0,12614,714.0,6.0,12614,0
2026-09-08 21:05:53,76,3,[Ashen Miracle] Oguri Cap,URA Finale Semifinal,2108,1,10000,70,1.7312,0,2,0,0,17000.0,17340,340.0,2.0,17340,0
2026-09-08 21:05:53,78,3,[Ashen Miracle] Oguri Cap,URA Finale Finals,2209,1,30000,70,2.9177,0,4,0,0,51000.0,53040,2040.0,4.0,53040,0
2026-09-16 13:24:41,12,3,[Ashen Miracle] Oguri Cap,Junior Make Debut,1070,1,700,70,6.3564,0,9,0,0,1190.0,1297,107.0,8.9916,1297,0
2026-09-16 13:24:41,23,3,[Ashen Miracle] Oguri Cap,Hanshin Juvenile Fillies,623,1,6500,70,0.5447,0,0,0,0,11050.0,11050,0.0,0.0,11050,0
2026-09-16 13:24:41,33,3,[Ashen Miracle] Oguri Cap,NHK Mile Cup,164,1,10500,70,1.2208,0,2,0,0,17850.0,18207,357.0,2.0,18207,0
2026-09-16 13:24:41,46,3,[Ashen Miracle] Oguri Cap,Mile Championship,78,1,11000,70,1.8764,0,2,0,0,18700.0,19074,374.0,2.0,19074,0
2026-09-16 13:24:41,48,3,[Ashen Miracle] Oguri Cap,Arima Kinen,81,1,30000,70,7.2065,0,9,0,0,51000.0,55590,4590.0,9.0,55590,0
2026-09-16 13:24:41,54,3,[Ashen Miracle] Oguri Cap,Osaka Hai,3,1,13500,70,9.1057,0,9,0,0,22950.0,25016,2066.0,9.0022,25016,0
2026-09-16 13:24:41,59,3,[Ashen Miracle] Oguri Cap,Yasuda Kinen,73,1,13000,70,4.3705,0,6,0,0,22100.0,23426,1326.0,6.0,23426,0
2026-09-16 13:24:41,68,3,[Ashen Miracle] Oguri Cap,Tenno Sho (Autumn),76,1,15000,70,7.933,0,9,0,0,25500.0,27795,2295.0,9.0,27795,0
2026-09-16 13:24:41,72,3,[Ashen Miracle] Oguri Cap,Arima Kinen,81,1,30000,70,5.7931,0,6,0,0,51000.0,54060,3060.0,6.0,54060,0
2026-09-16 13:24:41,74,3,[Ashen Miracle] Oguri Cap,URA Finale Qualifier,2010,1,7000,70,5.7824,0,6,0,0,11900.0,12614,714.0,6.0,12614,0
2026-09-16 13:24:41,76,3,[Ashen Miracle] Oguri Cap,URA Finale Semifinal,2112,1,10000,70,2.7856,0,4,0,0,17000.0,17680,680.0,4.0,17680,0
2026-09-16 13:24:41,78,3,[Ashen Miracle] Oguri Cap,URA Finale Finals,2208,1,30000,70,5.4409,0,6,0,0,51000.0,54060,3060.0,6.0,54060,0
2026-09-17 20:23:11,12,3,[Ashen Miracle] Oguri Cap,Junior Make Debut,1070,1,700,70,5.3797,0,6,0,0,1190.0,1261,71.0,5.9664,1261,0
2026-09-17 20:23:11,24,3,[Ashen Miracle] Oguri Cap,Hopeful Stakes,625,1,7000,70,4.8411,2,6,2,0,11900.0,12852,952.0,8.0,12852,0
2026-09-17 20:23:11,33,3,[Ashen Miracle] Oguri Cap,NHK Mile Cup,164,1,10500,70,3.0921,1,4,2,0,17850.0,18921,1071.0,6.0,18921,0
2026-09-17 20:23:11,46,3,[Ashen Miracle] Oguri Cap,Mile Championship,78,1,11000,70,3.4861,1,4,2,0,18700.0,19822,1122.0,6.0,19822,0
2026-09-17 20:23:11,48,3,[Ashen Miracle] Oguri Cap,Arima Kinen,81,1,30000,70,8.0058,1,9,2,0,51000.0,56610,5610.0,11.0,56610,0
2026-09-17 20:23:11,51,3,[Ashen Miracle] Oguri Cap,Kawasaki Kinen,1106,1,6000,70,5.6972,1,6,2,0,10200.0,11016,816.0,8.0,11016,0
2026-09-17 20:23:11,52,3,[Ashen Miracle] Oguri Cap,February Stakes,1,1,10000,70,0.5589,1,0,2,0,17000.0,17340,340.0,2.0,17340,0
2026-09-17 20:23:11,68,3,[Ashen Miracle] Oguri Cap,Tenno Sho (Autumn),76,1,15000,70,4.6895,2,6,2,0,25500.0,27540,2040.0,8.0,27540,0
2026-09-17 20:23:11,72,3,[Ashen Miracle] Oguri Cap,Arima Kinen,81,1,30000,70,9.0895,1,9,2,0,51000.0,56610,5610.0,11.0,56610,0
2026-09-17 20:23:11,74,3,[Ashen Miracle] Oguri Cap,URA Finale Qualifier,2014,1,7000,70,6.1828,1,9,2,0,11900.0,13209,1309.0,11.0,13209,0
2026-09-17 20:23:11,76,3,[Ashen Miracle] Oguri Cap,URA Finale Semifinal,2111,1,10000,70,2.8136,1,4,2,0,17000.0,18020,1020.0,6.0,18020,0
2026-09-17 20:23:11,78,3,[Ashen Miracle] Oguri Cap,URA Finale Finals,2212,1,30000,70,1.061,1,2,2,0,51000.0,53040,2040.0,4.0,53040,0
2026-09-17 22:45:31,12,3,[Ashen Miracle] Oguri Cap,Junior Make Debut,1070,1,700,70,2.2776,1,2,2,0,1190.0,1237,47.0,3.9496,1237,0
2026-09-17 22:45:31,23,3,[Ashen Miracle] Oguri Cap,Hanshin Juvenile Fillies,623,2,2600,70,0.0231,0,9,0,0,4420.0,4817,397.0,8.9819,4817,0
2026-09-17 22:45:31,33,3,[Ashen Miracle] Oguri Cap,NHK Mile Cup,164,1,10500,70,2.7073,2,4,2,0,17850.0,18921,1071.0,6.0,18921,0
2026-09-17 22:45:31,46,3,[Ashen Miracle] Oguri Cap,Mile Championship,78,1,11000,70,1.9154,2,2,2,0,18700.0,19448,748.0,4.0,19448,0
2026-09-17 22:45:31,48,3,[Ashen Miracle] Oguri Cap,Arima Kinen,81,1,30000,70,4.8206,2,6,2,0,51000.0,55080,4080.0,8.0,55080,0
2026-09-17 22:45:31,56,3,[Ashen Miracle] Oguri Cap,Tenno Sho (Spring),4,1,15000,70,14.398,5,9,3,0,25500.0,28560,3060.0,12.0,28560,0
2026-09-17 22:45:31,57,3,[Ashen Miracle] Oguri Cap,Victoria Mile,5,1,10500,70,2.1273,3,2,2,0,17850.0,18564,714.0,4.0,18564,0
2026-09-17 22:45:31,68,3,[Ashen Miracle] Oguri Cap,Tenno Sho (Autumn),76,1,15000,70,7.6906,5,9,3,0,25500.0,28560,3060.0,12.0,28560,0
2026-09-17 22:45:31,72,3,[Ashen Miracle] Oguri Cap,Arima Kinen,81,1,30000,70,7.549,6,9,3,0,51000.0,57120,6120.0,12.0,57120,0
2026-09-17 22:45:31,74,3,[Ashen Miracle] Oguri Cap,URA Finale Qualifier,2014,1,7000,70,6.4801,3,9,2,0,11900.0,13209,1309.0,11.0,13209,0
2026-09-17 22:45:31,76,3,[Ashen Miracle] Oguri Cap,URA Finale Semifinal,2109,1,10000,70,5.9469,7,6,5,0,17000.0,18870,1870.0,11.0,18870,0
2026-09-17 22:45:31,78,3,[Ashen Miracle] Oguri Cap,URA Finale Finals,2212,1,30000,70,7.2892,5,9,3,0,51000.0,57120,6120.0,12.0,57120,0
2026-09-19 20:01:05,12,3,[Ashen Miracle] Oguri Cap,Junior Make Debut,1070,1,700,70,6.6525,0,9,0,0,1190.0,1297,107.0,8.9916,1297,0
2026-09-19 20:01:05,23,3,[Ashen Miracle] Oguri Cap,Asahi Hai Futurity Stakes,624,3,1750,70,1.5022,0,6,0,0,2975.0,3153,178.0,5.9832,3153,0
2026-09-19 20:01:05,24,3,[Ashen Miracle] Oguri Cap,Hopeful Stakes,625,1,7000,70,5.6931,0,6,0,0,11900.0,12614,714.0,6.0,12614,0
2026-09-19 20:01:05,33,3,[Ashen Miracle] Oguri Cap,NHK Mile Cup,164,1,10500,70,1.488,0,2,0,0,17850.0,18207,357.0,2.0,18207,0
2026-09-19 20:01:05,46,3,[Ashen Miracle] Oguri Cap,Mile Championship,78,1,11000,70,3.8134,0,4,0,0,18700.0,19448,748.0,4.0,19448,0
2026-09-19 20:01:05,48,3,[Ashen Miracle] Oguri Cap,Arima Kinen,81,1,30000,70,2.6633,0,4,0,0,51000.0,53040,2040.0,4.0,53040,0
2026-09-19 20:01:05,52,3,[Ashen Miracle] Oguri Cap,February Stakes,1,1,10000,70,0.6637,0,0,0,0,17000.0,17000,0.0,0.0,17000,0
2026-09-19 20:01:05,59,3,[Ashen Miracle] Oguri Cap,Yasuda Kinen,73,1,13000,70,5.9364,0,6,0,0,22100.0,23426,1326.0,6.0,23426,0
2026-09-19 20:01:05,68,3,[Ashen Miracle] Oguri Cap,Tenno Sho (Autumn),76,1,15000,70,6.0564,0,9,0,0,25500.0,27795,2295.0,9.0,27795,0
2026-09-19 20:01:05,72,3,[Ashen Miracle] Oguri Cap,Arima Kinen,81,1,30000,70,7.8703,0,9,0,0,51000.0,55590,4590.0,9.0,55590,0
2026-09-19 20:01:05,74,3,[Ashen Miracle] Oguri Cap,URA Finale Qualifier,2015,1,7000,70,5.8192,0,6,0,0,11900.0,12614,714.0,6.0,12614,0
2026-09-19 20:01:05,76,3,[Ashen Miracle] Oguri Cap,URA Finale Semifinal,2111,1,10000,70,5.2726,0,6,0,0,17000.0,18020,1020.0,6.0,18020,0
2026-09-19 20:01:05,78,3,[Ashen Miracle] Oguri Cap,URA Finale Finals,2213,1,30000,70,5.6513,0,6,0,0,51000.0,54060,3060.0,6.0,54060,0
2026-09-19 21:45:59,12,2,[Blossom in Learning] Sakura Bakushin O,Junior Make Debut,676,1,700,65,1.7631,0,2,0,0,1155.0,1178,23.0,1.9913,1178,0
2026-09-19 21:45:59,21,2,[Blossom in Learning] Sakura Bakushin O,Keio Hai Junior Stakes,626,1,3800,65,0.917,0,2,0,0,6270.0,6395,125.0,1.9936,6395,0
2026-09-19 21:45:59,30,2,[Blossom in Learning] Sakura Bakushin O,Spring Stakes,171,2,2160,65,0.7907,1,6,2,0,3564.0,3847,283.0,7.9405,3847,0
2026-09-19 21:45:59,34,2,[Blossom in Learning] Sakura Bakushin O,Aoi Stakes,210,2,1520,65,1.5851,0,6,0,0,2508.0,2658,150.0,5.9809,2658,0
2026-09-19 21:45:59,35,2,[Blossom in Learning] Sakura Bakushin O,Epsom Cup,95,1,4100,65,1.3364,1,2,2,0,6765.0,7035,270.0,3.9911,7035,0
2026-09-19 21:45:59,42,2,[Blossom in Learning] Sakura Bakushin O,Sprinters Stakes,75,3,3250,65,0.8705,0,6,0,0,5362.5,5684,321.5,5.9953,5684,0
2026-09-19 21:45:59,54,2,[Blossom in Learning] Sakura Bakushin O,Takamatsunomiya Kinen,2,2,5200,65,0.451,0,9,0,0,8580.0,9352,772.0,8.9977,9352,0
2026-09-19 21:45:59,60,2,[Blossom in Learning] Sakura Bakushin O,Hakodate Sprint Stakes,96,1,3900,65,0.9971,0,2,0,0,6435.0,6563,128.0,1.9891,6563,0
2026-09-19 21:45:59,61,2,[Blossom in Learning] Sakura Bakushin O,CBC Sho,97,1,3900,65,2.3483,0,2,0,0,6435.0,6563,128.0,1.9891,6563,0
2026-09-19 21:45:59,65,2,[Blossom in Learning] Sakura Bakushin O,Centaur Stakes,83,1,5900,65,1.5096,0,2,0,0,9735.0,9929,194.0,1.9928,9929,0
2026-09-19 21:45:59,66,2,[Blossom in Learning] Sakura Bakushin O,Sprinters Stakes,75,6,1170,65,2.5098,1,0,2,0,1930.5,1968,37.5,1.9425,1968,0
2026-09-23 23:41:07,12,1,[Blossom in Learning] Sakura Bakushin O,Junior Make Debut,676,1,700,65,2.7319,0,4,0,0,1155.0,1201,46.0,3.9827,1201,0
2026-09-23 23:41:07,21,1,[Blossom in Learning] Sakura Bakushin O,Keio Hai Junior Stakes,626,1,3800,65,0.5164,0,0,0,0,6270.0,6270,0.0,0.0,6270,0
2026-09-23 23:41:07,30,1,[Blossom in Learning] Sakura Bakushin O,Spring Stakes,171,1,5400,65,2.4521,1,2,2,0,8910.0,9266,356.0,3.9955,9266,0
2026-09-23 23:41:07,34,1,[Blossom in Learning] Sakura Bakushin O,Aoi Stakes,210,1,3800,65,0.4297,0,0,0,0,6270.0,6270,0.0,0.0,6270,0
2026-09-23 23:41:07,42,1,[Blossom in Learning] Sakura Bakushin O,Sprinters Stakes,75,6,1170,65,3.8513,0,0,0,0,1930.5,1930,-0.5,-0.0259,1930,0
2026-09-28 14:22:08,12,1,[Hot☆Summer Night] Maruzensky,Junior Make Debut,676,1,700,65,0.2547,0,0,0,0,1155.0,1155,0.0,0.0,1155,0
2026-10-01 09:39:24,12,2,[Wild Frontier] Taiki Shuttle,Junior Make Debut,846,1,700,80,2.9274,1,4,2,0,1260.0,1335,75.0,5.9524,1335,0
2026-10-01 09:39:24,25,2,[Wild Frontier] Taiki Shuttle,Shinzan Kinen,178,1,3800,80,3.297,0,4,0,0,6840.0,7113,273.0,3.9912,7113,0
2026-10-01 09:39:24,33,2,[Wild Frontier] Taiki Shuttle,NHK Mile Cup,164,1,10500,80,1.5041,0,2,0,0,18900.0,19278,378.0,2.0,19278,0
2026-10-01 09:39:24,36,2,[Wild Frontier] Taiki Shuttle,Unicorn Stakes,189,1,3500,80,0.0829,0,0,0,0,6300.0,6300,0.0,0.0,6300,0
2026-10-01 09:39:24,46,2,[Wild Frontier] Taiki Shuttle,Mile Championship,78,1,11000,80,1.3511,1,2,2,0,19800.0,20592,792.0,4.0,20592,0
2026-10-01 09:39:24,59,2,[Wild Frontier] Taiki Shuttle,Yasuda Kinen,73,1,13000,80,4.4812,0,6,0,0,23400.0,24804,1404.0,6.0,24804,0
2026-10-01 09:39:24,66,2,[Wild Frontier] Taiki Shuttle,Sprinters Stakes,75,1,13000,80,3.6966,1,4,2,0,23400.0,24804,1404.0,6.0,24804,0
2026-10-01 09:39:24,70,2,[Wild Frontier] Taiki Shuttle,Mile Championship,78,1,11000,80,3.6774,0,4,0,0,19800.0,20592,792.0,4.0,20592,0
2026-10-01 09:39:24,74,2,[Wild Frontier] Taiki Shuttle,URA Finale Qualifier,2013,1,7000,80,4.0671,0,6,0,0,12600.0,13356,756.0,6.0,13356,0
2026-10-01 09:39:24,76,2,[Wild Frontier] Taiki Shuttle,URA Finale Semifinal,2109,1,10000,80,4.9632,1,6,2,0,18000.0,19440,1440.0,8.0,19440,0
2026-10-01 09:39:24,78,2,[Wild Frontier] Taiki Shuttle,URA Finale Finals,2214,1,30000,80,1.1329,0,2,0,0,54000.0,55080,1080.0,2.0,55080,0
2026-10-04 14:36:48,12,4,[Wild Frontier] Taiki Shuttle,Junior Make Debut,846,1,700,105,2.6127,1,4,2,0,1435.0,1521,86.0,5.993,1521,0
2026-10-04 14:36:48,14,4,[Wild Frontier] Taiki Shuttle,Hakodate Junior Stakes,628,1,3100,105,4.3676,0,6,0,0,6355.0,6736,381.0,5.9953,6736,0
2026-10-04 14:36:48,16,4,[Wild Frontier] Taiki Shuttle,Niigata Junior Stakes,629,1,3100,105,2.8947,0,4,0,0,6355.0,6609,254.0,3.9969,6609,0
2026-10-04 14:36:48,17,4,[Wild Frontier] Taiki Shuttle,Sapporo Junior Stakes,630,1,3100,105,2.2675,1,2,2,0,6355.0,6609,254.0,3.9969,6609,0
2026-10-04 14:36:48,21,4,[Wild Frontier] Taiki Shuttle,Keio Hai Junior Stakes,626,1,3800,105,1.8215,1,2,2,0,7790.0,8101,311.0,3.9923,8101,0
2026-10-04 14:36:48,22,4,[Wild Frontier] Taiki Shuttle,Tokyo Sports Hai Junior Stakes,635,1,3300,105,4.1972,0,6,0,0,6765.0,7170,405.0,5.9867,7170,0
2026-10-04 14:36:48,23,4,[Wild Frontier] Taiki Shuttle,Hanshin Juvenile Fillies,623,1,6500,105,4.4133,1,6,2,0,13325.0,14391,1066.0,8.0,14391,0
2026-10-04 14:36:48,24,4,[Wild Frontier] Taiki Shuttle,Zen-Nippon Junior Yushun,1107,2,1680,105,0.6647,1,9,2,0,3444.0,3821,377.0,10.9466,3821,0
2026-10-04 14:36:48,27,4,[Wild Frontier] Taiki Shuttle,Kyodo News Hai,183,1,3800,105,3.9819,1,4,2,0,7790.0,8257,467.0,5.9949,8257,0
2026-10-04 14:36:48,29,4,[Wild Frontier] Taiki Shuttle,Fillies' Revue,170,2,2080,105,0.056,1,9,2,0,4264.0,4731,467.0,10.9522,4731,0
2026-10-04 14:36:48,30,4,[Wild Frontier] Taiki Shuttle,Spring Stakes,171,1,5400,105,1.5715,1,2,2,0,11070.0,11513,443.0,4.0018,11513,0
2026-10-04 14:36:48,31,4,[Wild Frontier] Taiki Shuttle,Oka Sho,162,1,10500,105,2.0067,0,2,0,0,21525.0,21956,431.0,2.0023,21956,0
2026-10-04 14:36:48,33,4,[Wild Frontier] Taiki Shuttle,NHK Mile Cup,164,1,10500,105,1.3928,0,2,0,0,21525.0,21956,431.0,2.0023,21956,0
2026-10-04 14:36:48,35,4,[Wild Frontier] Taiki Shuttle,Yasuda Kinen,73,1,13000,105,1.2662,1,2,2,0,26650.0,27716,1066.0,4.0,27716,0
2026-10-04 14:36:48,39,4,[Wild Frontier] Taiki Shuttle,Sekiya Kinen,105,1,3900,105,3.8619,0,4,0,0,7995.0,8314,319.0,3.99,8314,0
2026-10-04 14:36:48,41,4,[Wild Frontier] Taiki Shuttle,Rose Stakes,176,1,5200,105,3.3191,1,4,2,0,10660.0,11300,640.0,6.0038,11300,0
2026-10-04 14:36:48,42,4,[Wild Frontier] Taiki Shuttle,Sprinters Stakes,75,1,13000,105,3.2007,1,4,2,0,26650.0,28249,1599.0,6.0,28249,0
2026-10-04 14:36:48,43,4,[Wild Frontier] Taiki Shuttle,M.C. Nambu Hai,1109,1,6000,105,2.7546,0,4,0,0,12300.0,12792,492.0,4.0,12792,0
2026-10-04 14:36:48,45,4,[Wild Frontier] Taiki Shuttle,JBC Sprint,1111,1,6000,105,1.5294,1,2,2,0,12300.0,12792,492.0,4.0,12792,0
2026-10-04 14:36:48,46,4,[Wild Frontier] Taiki Shuttle,Mile Championship,78,1,11000,105,2.2484,0,2,0,0,22550.0,23001,451.0,2.0,23001,0
2026-10-04 14:36:48,47,4,[Wild Frontier] Taiki Shuttle,Champions Cup,80,1,10000,105,2.5859,0,4,0,0,20500.0,21320,820.0,4.0,21320,0
2026-10-04 14:36:48,50,4,[Wild Frontier] Taiki Shuttle,Negishi Stakes,22,2,1520,105,1.4117,0,6,0,0,3116.0,3302,186.0,5.9692,3302,0
2026-10-04 14:36:48,52,4,[Wild Frontier] Taiki Shuttle,February Stakes,1,1,10000,105,0.0968,0,0,0,0,20500.0,20500,0.0,0.0,20500,0
2026-10-04 14:36:48,54,4,[Wild Frontier] Taiki Shuttle,Takamatsunomiya Kinen,2,1,13000,105,3.2402,0,4,0,0,26650.0,27716,1066.0,4.0,27716,0
2026-10-04 14:36:48,55,4,[Wild Frontier] Taiki Shuttle,Marine Cup,1128,1,2500,105,2.6992,0,4,0,0,5125.0,5330,205.0,4.0,5330,0
2026-10-04 14:36:48,57,4,[Wild Frontier] Taiki Shuttle,Victoria Mile,5,1,10500,105,1.5024,0,2,0,0,21525.0,21956,431.0,2.0023,21956,0
2026-10-04 14:36:48,58,4,[Wild Frontier] Taiki Shuttle,Keyaki Stakes,71,1,2200,105,3.8244,1,4,2,0,4510.0,4780,270.0,5.9867,4780,0
2026-10-04 14:36:48,59,4,[Wild Frontier] Taiki Shuttle,Yasuda Kinen,73,1,13000,105,1.4361,1,2,2,0,26650.0,27716,1066.0,4.0,27716,0
2026-10-04 14:36:48,62,4,[Wild Frontier] Taiki Shuttle,Queen Stakes,103,1,3600,105,5.0515,0,6,0,0,7380.0,7822,442.0,5.9892,7822,0
2026-10-04 14:36:48,65,4,[Wild Frontier] Taiki Shuttle,Keisei Hai Autumn Handicap,110,1,3900,105,5.633,0,6,0,0,7995.0,8474,479.0,5.9912,8474,0
2026-10-04 14:36:48,66,4,[Wild Frontier] Taiki Shuttle,Sprinters Stakes,75,1,13000,105,2.6328,0,4,0,0,26650.0,27716,1066.0,4.0,27716,0
2026-10-04 14:36:48,67,4,[Wild Frontier] Taiki Shuttle,M.C. Nambu Hai,1109,1,6000,105,4.184,0,6,0,0,12300.0,13038,738.0,6.0,13038,0
2026-10-04 14:36:48,69,4,[Wild Frontier] Taiki Shuttle,JBC Sprint,1025,1,6000,105,2.1263,1,2,2,0,12300.0,12792,492.0,4.0,12792,0
2026-10-04 14:36:48,70,4,[Wild Frontier] Taiki Shuttle,Mile Championship,78,1,11000,105,2.1798,0,2,0,0,22550.0,23001,451.0,2.0,23001,0
2026-10-04 14:36:48,71,4,[Wild Frontier] Taiki Shuttle,Champions Cup,80,1,10000,105,0.8076,1,2,2,0,20500.0,21320,820.0,4.0,21320,0
2026-10-04 14:36:48,74,4,[Wild Frontier] Taiki Shuttle,Twinkle Star Climax Race 1,2313,1,7000,105,4.0466,1,6,2,0,14350.0,15498,1148.0,8.0,15498,0
2026-10-04 14:36:48,76,4,[Wild Frontier] Taiki Shuttle,Twinkle Star Climax Race 2,2410,1,10000,105,1.8345,1,2,2,0,20500.0,21320,820.0,4.0,21320,0
2026-10-04 14:36:48,78,4,[Wild Frontier] Taiki Shuttle,Twinkle Star Climax Race 3,2515,1,30000,105,5.1406,1,6,2,50,61500.0,99630,38130.0,62.0,99630,0
2026-10-08 10:00:27,12,3,[CODE: ICING] Mihono Bourbon,Junior Make Debut,1075,1,700,70,3.126,1,4,2,0,1190.0,1261,71.0,5.9664,1261,0
2026-10-08 10:00:27,23,3,[CODE: ICING] Mihono Bourbon,Asahi Hai Futurity Stakes,624,1,7000,70,3.0099,2,4,2,0,11900.0,12614,714.0,6.0,12614,0
2026-10-08 10:00:27,30,3,[CODE: ICING] Mihono Bourbon,Spring Stakes,171,1,5400,70,1.4594,1,2,2,0,9180.0,9547,367.0,3.9978,9547,0
2026-10-08 10:00:27,31,3,[CODE: ICING] Mihono Bourbon,Satsuki Sho,163,1,11000,70,6.1843,2,9,2,0,18700.0,20757,2057.0,11.0,20757,0
2026-10-08 10:00:27,34,3,[CODE: ICING] Mihono Bourbon,Tokyo Yushun (Japanese Derby),166,1,20000,70,4.682,2,6,2,0,34000.0,36720,2720.0,8.0,36720,0
2026-10-08 10:00:27,44,3,[CODE: ICING] Mihono Bourbon,Kikuka Sho,168,1,12000,70,3.5273,1,4,2,0,20400.0,21624,1224.0,6.0,21624,0
2026-10-08 10:00:27,56,3,[CODE: ICING] Mihono Bourbon,Tenno Sho (Spring),4,1,15000,70,10.0374,2,9,2,0,25500.0,28305,2805.0,11.0,28305,0
2026-10-08 10:00:27,70,3,[CODE: ICING] Mihono Bourbon,Japan Cup,79,1,30000,70,10.1623,2,9,2,0,51000.0,56610,5610.0,11.0,56610,0
2026-10-08 10:00:27,72,3,[CODE: ICING] Mihono Bourbon,Arima Kinen,81,1,30000,70,10.4669,3,9,2,0,51000.0,56610,5610.0,11.0,56610,0
2026-10-08 10:00:27,74,3,[CODE: ICING] Mihono Bourbon,URA Finale Qualifier,2010,1,7000,70,5.7274,3,6,2,0,11900.0,12852,952.0,8.0,12852,0
2026-10-08 10:00:27,76,3,[CODE: ICING] Mihono Bourbon,URA Finale Semifinal,2113,1,10000,70,3.7223,3,4,2,0,17000.0,18020,1020.0,6.0,18020,0
2026-10-08 10:00:27,78,3,[CODE: ICING] Mihono Bourbon,URA Finale Finals,2209,1,30000,70,3.873,3,4,2,0,51000.0,54060,3060.0,6.0,54060,0
2026-10-10 03:12:29,12,3,[Soirée des Chatons] Seiun Sky,Junior Make Debut,689,1,700,70,3.0303,1,4,2,0,1190.0,1261,71.0,5.9664,1261,0
2026-10-10 03:12:29,24,3,[Soirée des Chatons] Seiun Sky,Hopeful Stakes,625,1,7000,70,2.1576,1,2,2,0,11900.0,12376,476.0,4.0,12376,0
2026-10-10 03:12:29,31,3,[Soirée des Chatons] Seiun Sky,Satsuki Sho,163,1,11000,70,2.5681,2,4,2,0,18700.0,19822,1122.0,6.0,19822,0
2026-10-10 03:12:29,34,3,[Soirée des Chatons] Seiun Sky,Tokyo Yushun (Japanese Derby),166,1,20000,70,2.4678,2,2,2,0,34000.0,35360,1360.0,4.0,35360,0
2026-10-10 03:12:29,44,3,[Soirée des Chatons] Seiun Sky,Kikuka Sho,168,1,12000,70,0.6938,2,0,2,0,20400.0,20808,408.0,2.0,20808,0
2026-10-10 03:12:29,48,3,[Soirée des Chatons] Seiun Sky,Arima Kinen,81,1,30000,70,3.3828,2,4,2,0,51000.0,54060,3060.0,6.0,54060,0
2026-10-10 03:12:29,56,3,[Soirée des Chatons] Seiun Sky,Tenno Sho (Spring),4,1,15000,70,20.5803,10,9,8,0,25500.0,29835,4335.0,17.0,29835,0
2026-10-10 03:12:29,60,3,[Soirée des Chatons] Seiun Sky,Takarazuka Kinen,74,1,15000,70,6.4095,10,9,8,0,25500.0,29835,4335.0,17.0,29835,0
2026-10-10 03:12:29,68,3,[Soirée des Chatons] Seiun Sky,Tenno Sho (Autumn),76,1,15000,70,9.3985,9,9,5,0,25500.0,29070,3570.0,14.0,29070,0
2026-10-10 03:12:29,72,3,[Soirée des Chatons] Seiun Sky,Arima Kinen,81,1,30000,70,11.7606,10,9,8,0,51000.0,59670,8670.0,17.0,59670,0
2026-10-10 03:12:29,74,3,[Soirée des Chatons] Seiun Sky,URA Finale Qualifier,2018,1,7000,70,11.2054,9,9,5,0,11900.0,13566,1666.0,14.0,13566,0
2026-10-10 03:12:29,76,3,[Soirée des Chatons] Seiun Sky,URA Finale Semifinal,2123,1,10000,70,8.0601,7,9,5,0,17000.0,19380,2380.0,14.0,19380,0
2026-10-10 03:12:29,78,3,[Soirée des Chatons] Seiun Sky,URA Finale Finals,2222,1,30000,70,5.7947,8,6,5,0,51000.0,56610,5610.0,11.0,56610,0
2026-10-10 15:53:30,12,3,[Soirée des Chatons] Seiun Sky,Junior Make Debut,689,1,700,70,3.7946,2,4,2,0,1190.0,1261,71.0,5.9664,1261,0
2026-10-10 15:53:30,24,3,[Soirée des Chatons] Seiun Sky,Hopeful Stakes,625,1,7000,70,5.3394,1,6,2,0,11900.0,12852,952.0,8.0,12852,0
2026-10-10 15:53:30,31,3,[Soirée des Chatons] Seiun Sky,Satsuki Sho,163,1,11000,70,7.5947,2,9,2,0,18700.0,20757,2057.0,11.0,20757,0
2026-10-10 15:53:30,34,3,[Soirée des Chatons] Seiun Sky,Tokyo Yushun (Japanese Derby),166,1,20000,70,2.1677,4,2,3,0,34000.0,35700,1700.0,5.0,35700,0
2026-10-10 15:53:30,44,3,[Soirée des Chatons] Seiun Sky,Kikuka Sho,168,3,3000,70,3.8191,4,4,3,0,5100.0,5457,357.0,7.0,5457,0
2026-10-10 15:53:30,48,3,[Soirée des Chatons] Seiun Sky,Arima Kinen,81,1,30000,70,12.6422,3,9,2,0,51000.0,56610,5610.0,11.0,56610,0
2026-10-10 15:53:30,56,3,[Soirée des Chatons] Seiun Sky,Tenno Sho (Spring),4,1,15000,70,1.11,7,2,5,0,25500.0,27285,1785.0,7.0,27285,0
2026-10-10 15:53:30,60,3,[Soirée des Chatons] Seiun Sky,Takarazuka Kinen,74,1,15000,70,13.7279,7,9,5,0,25500.0,29070,3570.0,14.0,29070,0
2026-10-10 15:53:30,68,3,[Soirée des Chatons] Seiun Sky,Tenno Sho (Autumn),76,1,15000,70,3.6698,6,4,3,0,25500.0,27285,1785.0,7.0,27285,0
2026-10-10 15:53:30,72,3,[Soirée des Chatons] Seiun Sky,Arima Kinen,81,1,30000,70,13.5919,8,9,5,0,51000.0,58140,7140.0,14.0,58140,0
2026-10-10 15:53:30,74,3,[Soirée des Chatons] Seiun Sky,URA Finale Qualifier,2025,1,7000,70,13.045,7,9,5,0,11900.0,13566,1666.0,14.0,13566,0
2026-10-10 15:53:30,76,3,[Soirée des Chatons] Seiun Sky,URA Finale Semifinal,2122,1,10000,70,12.4002,7,9,5,0,17000.0,19380,2380.0,14.0,19380,0
2026-10-10 15:53:30,78,3,[Soirée des Chatons] Seiun Sky,URA Finale Finals,2217,1,30000,70,12.3247,7,9,5,0,51000.0,58140,7140.0,14.0,58140,0
2026-10-11 18:47:03,12,3,[Soirée des Chatons] Seiun Sky,Junior Make Debut,689,1,700,80,3.2149,2,4,2,0,1260.0,1335,75.0,5.9524,1335,0
2026-10-11 18:47:03,24,3,[Soirée des Chatons] Seiun Sky,Hopeful Stakes,625,1,7000,80,2.4816,2,2,2,0,12600.0,13104,504.0,4.0,13104,0
2026-10-11 19:13:35,12,3,[Soirée des Chatons] Seiun Sky,Junior Make Debut,689,1,700,80,4.1512,1,6,2,0,1260.0,1360,100.0,7.9365,1360,0
2026-10-11 19:13:35,24,3,[Soirée des Chatons] Seiun Sky,Hopeful Stakes,625,1,7000,80,2.8651,2,4,2,0,12600.0,13356,756.0,6.0,13356,0
2026-10-11 19:13:35,31,3,[Soirée des Chatons] Seiun Sky,Satsuki Sho,163,1,11000,80,4.6012,2,6,2,0,19800.0,21384,1584.0,8.0,21384,0
2026-10-11 19:13:35,34,3,[Soirée des Chatons] Seiun Sky,Tokyo Yushun (Japanese Derby),166,1,20000,80,4.1483,2,6,2,0,36000.0,38880,2880.0,8.0,38880,0
2026-10-11 19:13:35,44,3,[Soirée des Chatons] Seiun Sky,Kikuka Sho,168,2,4800,80,4.218,2,2,2,0,8640.0,8985,345.0,3.9931,8985,0
2026-10-11 19:13:35,48,3,[Soirée des Chatons] Seiun Sky,Arima Kinen,81,1,30000,80,10.0709,3,9,2,0,54000.0,59940,5940.0,11.0,59940,0
2026-10-11 19:13:35,56,3,[Soirée des Chatons] Seiun Sky,Tenno Sho (Spring),4,1,15000,80,6.5113,8,9,5,0,27000.0,30780,3780.0,14.0,30780,0
2026-10-11 19:13:35,60,3,[Soirée des Chatons] Seiun Sky,Takarazuka Kinen,74,1,15000,80,6.7601,6,9,3,0,27000.0,30240,3240.0,12.0,30240,0
2026-10-11 19:13:35,72,3,[Soirée des Chatons] Seiun Sky,Arima Kinen,81,1,30000,80,14.0565,7,9,5,0,54000.0,61560,7560.0,14.0,61560,0
2026-10-11 19:13:35,74,3,[Soirée des Chatons] Seiun Sky,URA Finale Qualifier,2018,1,7000,80,10.2344,7,9,5,0,12600.0,14364,1764.0,14.0,14364,0
2026-10-11 19:13:35,76,3,[Soirée des Chatons] Seiun Sky,URA Finale Semifinal,2121,1,10000,80,5.3797,5,6,3,0,18000.0,19620,1620.0,9.0,19620,0
2026-10-11 19:13:35,78,3,[Soirée des Chatons] Seiun Sky,URA Finale Finals,2222,1,30000,80,7.7281,7,9,5,0,54000.0,61560,7560.0,14.0,61560,0
1 career turn scenario character race program_id place base_fans deck_bonus_pct margin_lengths skill_activations margin_bonus_pct skill_bonus_pct item_bonus_pct deck_only_fans actual_fans extra_fans extra_pct predicted_fans residual_fans
2 2026-08-19 20:37:27 12 3 [Ashen Miracle] Oguri Cap Junior Make Debut 1070 1 700 55 4.4727 0 6 0 0 1085.0 1150 65.0 5.9908 1150 0
3 2026-08-19 20:37:27 23 3 [Ashen Miracle] Oguri Cap Hanshin Juvenile Fillies 623 6 585 55 1.2941 0 0 0 0 906.75 906 -0.75 -0.0827 906 0
4 2026-08-19 20:37:27 24 3 [Ashen Miracle] Oguri Cap Hopeful Stakes 625 1 7000 55 1.1495 0 2 0 0 10850.0 11067 217.0 2.0 11067 0
5 2026-08-19 20:37:27 33 3 [Ashen Miracle] Oguri Cap NHK Mile Cup 164 1 10500 55 1.6165 0 2 0 0 16275.0 16601 326.0 2.0031 16601 0
6 2026-08-19 20:37:27 46 3 [Ashen Miracle] Oguri Cap Mile Championship 78 1 11000 55 5.3966 5 6 3 0 17050.0 18585 1535.0 9.0029 18585 0
7 2026-08-19 20:37:27 48 3 [Ashen Miracle] Oguri Cap Arima Kinen 81 1 30000 55 8.8065 6 9 3 0 46500.0 52080 5580.0 12.0 52080 0
8 2026-08-19 20:37:27 54 3 [Ashen Miracle] Oguri Cap Osaka Hai 3 1 13500 55 3.3853 4 4 3 0 20925.0 22390 1465.0 7.0012 22390 0
9 2026-08-19 20:37:27 57 3 [Ashen Miracle] Oguri Cap Victoria Mile 5 1 10500 55 4.8613 2 6 2 0 16275.0 17577 1302.0 8.0 17577 0
10 2026-08-19 20:37:27 68 3 [Ashen Miracle] Oguri Cap Tenno Sho (Autumn) 76 1 15000 55 14.0515 6 9 3 0 23250.0 26040 2790.0 12.0 26040 0
11 2026-08-19 20:37:27 72 3 [Ashen Miracle] Oguri Cap Arima Kinen 81 1 30000 55 10.5066 7 9 5 0 46500.0 53010 6510.0 14.0 53010 0
12 2026-08-19 20:37:27 74 3 [Ashen Miracle] Oguri Cap URA Finale Qualifier 2015 1 7000 55 6.1557 6 9 3 0 10850.0 12152 1302.0 12.0 12152 0
13 2026-08-19 20:37:27 76 3 [Ashen Miracle] Oguri Cap URA Finale Semifinal 2112 1 10000 55 6.906 7 9 5 0 15500.0 17670 2170.0 14.0 17670 0
14 2026-08-19 20:37:27 78 3 [Ashen Miracle] Oguri Cap URA Finale Finals 2213 1 30000 55 7.8077 8 9 5 0 46500.0 53010 6510.0 14.0 53010 0
15 2026-09-08 21:05:53 12 3 [Ashen Miracle] Oguri Cap Junior Make Debut 1070 1 700 70 2.4747 0 2 0 0 1190.0 1213 23.0 1.9328 1213 0
16 2026-09-08 21:05:53 23 3 [Ashen Miracle] Oguri Cap Hanshin Juvenile Fillies 623 3 1625 70 2.5458 0 4 0 0 2762.5 2873 110.5 4.0 2873 0
17 2026-09-08 21:05:53 32 3 [Ashen Miracle] Oguri Cap Flora Stakes 173 1 5200 70 0.166 0 0 0 0 8840.0 8840 0.0 0.0 8840 0
18 2026-09-08 21:05:53 33 3 [Ashen Miracle] Oguri Cap NHK Mile Cup 164 1 10500 70 0.6636 0 0 0 0 17850.0 17850 0.0 0.0 17850 0
19 2026-09-08 21:05:53 46 3 [Ashen Miracle] Oguri Cap Mile Championship 78 1 11000 70 0.3634 0 0 0 0 18700.0 18700 0.0 0.0 18700 0
20 2026-09-08 21:05:53 48 3 [Ashen Miracle] Oguri Cap Arima Kinen 81 1 30000 70 3.9924 0 4 0 0 51000.0 53040 2040.0 4.0 53040 0
21 2026-09-08 21:05:53 54 3 [Ashen Miracle] Oguri Cap Osaka Hai 3 1 13500 70 3.7863 0 4 0 0 22950.0 23868 918.0 4.0 23868 0
22 2026-09-08 21:05:53 57 3 [Ashen Miracle] Oguri Cap Victoria Mile 5 1 10500 70 1.4385 0 2 0 0 17850.0 18207 357.0 2.0 18207 0
23 2026-09-08 21:05:53 68 3 [Ashen Miracle] Oguri Cap Tenno Sho (Autumn) 76 1 15000 70 3.9784 0 4 0 0 25500.0 26520 1020.0 4.0 26520 0
24 2026-09-08 21:05:53 72 3 [Ashen Miracle] Oguri Cap Arima Kinen 81 1 30000 70 7.8092 0 9 0 0 51000.0 55590 4590.0 9.0 55590 0
25 2026-09-08 21:05:53 74 3 [Ashen Miracle] Oguri Cap URA Finale Qualifier 2011 1 7000 70 4.2694 0 6 0 0 11900.0 12614 714.0 6.0 12614 0
26 2026-09-08 21:05:53 76 3 [Ashen Miracle] Oguri Cap URA Finale Semifinal 2108 1 10000 70 1.7312 0 2 0 0 17000.0 17340 340.0 2.0 17340 0
27 2026-09-08 21:05:53 78 3 [Ashen Miracle] Oguri Cap URA Finale Finals 2209 1 30000 70 2.9177 0 4 0 0 51000.0 53040 2040.0 4.0 53040 0
28 2026-09-16 13:24:41 12 3 [Ashen Miracle] Oguri Cap Junior Make Debut 1070 1 700 70 6.3564 0 9 0 0 1190.0 1297 107.0 8.9916 1297 0
29 2026-09-16 13:24:41 23 3 [Ashen Miracle] Oguri Cap Hanshin Juvenile Fillies 623 1 6500 70 0.5447 0 0 0 0 11050.0 11050 0.0 0.0 11050 0
30 2026-09-16 13:24:41 33 3 [Ashen Miracle] Oguri Cap NHK Mile Cup 164 1 10500 70 1.2208 0 2 0 0 17850.0 18207 357.0 2.0 18207 0
31 2026-09-16 13:24:41 46 3 [Ashen Miracle] Oguri Cap Mile Championship 78 1 11000 70 1.8764 0 2 0 0 18700.0 19074 374.0 2.0 19074 0
32 2026-09-16 13:24:41 48 3 [Ashen Miracle] Oguri Cap Arima Kinen 81 1 30000 70 7.2065 0 9 0 0 51000.0 55590 4590.0 9.0 55590 0
33 2026-09-16 13:24:41 54 3 [Ashen Miracle] Oguri Cap Osaka Hai 3 1 13500 70 9.1057 0 9 0 0 22950.0 25016 2066.0 9.0022 25016 0
34 2026-09-16 13:24:41 59 3 [Ashen Miracle] Oguri Cap Yasuda Kinen 73 1 13000 70 4.3705 0 6 0 0 22100.0 23426 1326.0 6.0 23426 0
35 2026-09-16 13:24:41 68 3 [Ashen Miracle] Oguri Cap Tenno Sho (Autumn) 76 1 15000 70 7.933 0 9 0 0 25500.0 27795 2295.0 9.0 27795 0
36 2026-09-16 13:24:41 72 3 [Ashen Miracle] Oguri Cap Arima Kinen 81 1 30000 70 5.7931 0 6 0 0 51000.0 54060 3060.0 6.0 54060 0
37 2026-09-16 13:24:41 74 3 [Ashen Miracle] Oguri Cap URA Finale Qualifier 2010 1 7000 70 5.7824 0 6 0 0 11900.0 12614 714.0 6.0 12614 0
38 2026-09-16 13:24:41 76 3 [Ashen Miracle] Oguri Cap URA Finale Semifinal 2112 1 10000 70 2.7856 0 4 0 0 17000.0 17680 680.0 4.0 17680 0
39 2026-09-16 13:24:41 78 3 [Ashen Miracle] Oguri Cap URA Finale Finals 2208 1 30000 70 5.4409 0 6 0 0 51000.0 54060 3060.0 6.0 54060 0
40 2026-09-17 20:23:11 12 3 [Ashen Miracle] Oguri Cap Junior Make Debut 1070 1 700 70 5.3797 0 6 0 0 1190.0 1261 71.0 5.9664 1261 0
41 2026-09-17 20:23:11 24 3 [Ashen Miracle] Oguri Cap Hopeful Stakes 625 1 7000 70 4.8411 2 6 2 0 11900.0 12852 952.0 8.0 12852 0
42 2026-09-17 20:23:11 33 3 [Ashen Miracle] Oguri Cap NHK Mile Cup 164 1 10500 70 3.0921 1 4 2 0 17850.0 18921 1071.0 6.0 18921 0
43 2026-09-17 20:23:11 46 3 [Ashen Miracle] Oguri Cap Mile Championship 78 1 11000 70 3.4861 1 4 2 0 18700.0 19822 1122.0 6.0 19822 0
44 2026-09-17 20:23:11 48 3 [Ashen Miracle] Oguri Cap Arima Kinen 81 1 30000 70 8.0058 1 9 2 0 51000.0 56610 5610.0 11.0 56610 0
45 2026-09-17 20:23:11 51 3 [Ashen Miracle] Oguri Cap Kawasaki Kinen 1106 1 6000 70 5.6972 1 6 2 0 10200.0 11016 816.0 8.0 11016 0
46 2026-09-17 20:23:11 52 3 [Ashen Miracle] Oguri Cap February Stakes 1 1 10000 70 0.5589 1 0 2 0 17000.0 17340 340.0 2.0 17340 0
47 2026-09-17 20:23:11 68 3 [Ashen Miracle] Oguri Cap Tenno Sho (Autumn) 76 1 15000 70 4.6895 2 6 2 0 25500.0 27540 2040.0 8.0 27540 0
48 2026-09-17 20:23:11 72 3 [Ashen Miracle] Oguri Cap Arima Kinen 81 1 30000 70 9.0895 1 9 2 0 51000.0 56610 5610.0 11.0 56610 0
49 2026-09-17 20:23:11 74 3 [Ashen Miracle] Oguri Cap URA Finale Qualifier 2014 1 7000 70 6.1828 1 9 2 0 11900.0 13209 1309.0 11.0 13209 0
50 2026-09-17 20:23:11 76 3 [Ashen Miracle] Oguri Cap URA Finale Semifinal 2111 1 10000 70 2.8136 1 4 2 0 17000.0 18020 1020.0 6.0 18020 0
51 2026-09-17 20:23:11 78 3 [Ashen Miracle] Oguri Cap URA Finale Finals 2212 1 30000 70 1.061 1 2 2 0 51000.0 53040 2040.0 4.0 53040 0
52 2026-09-17 22:45:31 12 3 [Ashen Miracle] Oguri Cap Junior Make Debut 1070 1 700 70 2.2776 1 2 2 0 1190.0 1237 47.0 3.9496 1237 0
53 2026-09-17 22:45:31 23 3 [Ashen Miracle] Oguri Cap Hanshin Juvenile Fillies 623 2 2600 70 0.0231 0 9 0 0 4420.0 4817 397.0 8.9819 4817 0
54 2026-09-17 22:45:31 33 3 [Ashen Miracle] Oguri Cap NHK Mile Cup 164 1 10500 70 2.7073 2 4 2 0 17850.0 18921 1071.0 6.0 18921 0
55 2026-09-17 22:45:31 46 3 [Ashen Miracle] Oguri Cap Mile Championship 78 1 11000 70 1.9154 2 2 2 0 18700.0 19448 748.0 4.0 19448 0
56 2026-09-17 22:45:31 48 3 [Ashen Miracle] Oguri Cap Arima Kinen 81 1 30000 70 4.8206 2 6 2 0 51000.0 55080 4080.0 8.0 55080 0
57 2026-09-17 22:45:31 56 3 [Ashen Miracle] Oguri Cap Tenno Sho (Spring) 4 1 15000 70 14.398 5 9 3 0 25500.0 28560 3060.0 12.0 28560 0
58 2026-09-17 22:45:31 57 3 [Ashen Miracle] Oguri Cap Victoria Mile 5 1 10500 70 2.1273 3 2 2 0 17850.0 18564 714.0 4.0 18564 0
59 2026-09-17 22:45:31 68 3 [Ashen Miracle] Oguri Cap Tenno Sho (Autumn) 76 1 15000 70 7.6906 5 9 3 0 25500.0 28560 3060.0 12.0 28560 0
60 2026-09-17 22:45:31 72 3 [Ashen Miracle] Oguri Cap Arima Kinen 81 1 30000 70 7.549 6 9 3 0 51000.0 57120 6120.0 12.0 57120 0
61 2026-09-17 22:45:31 74 3 [Ashen Miracle] Oguri Cap URA Finale Qualifier 2014 1 7000 70 6.4801 3 9 2 0 11900.0 13209 1309.0 11.0 13209 0
62 2026-09-17 22:45:31 76 3 [Ashen Miracle] Oguri Cap URA Finale Semifinal 2109 1 10000 70 5.9469 7 6 5 0 17000.0 18870 1870.0 11.0 18870 0
63 2026-09-17 22:45:31 78 3 [Ashen Miracle] Oguri Cap URA Finale Finals 2212 1 30000 70 7.2892 5 9 3 0 51000.0 57120 6120.0 12.0 57120 0
64 2026-09-19 20:01:05 12 3 [Ashen Miracle] Oguri Cap Junior Make Debut 1070 1 700 70 6.6525 0 9 0 0 1190.0 1297 107.0 8.9916 1297 0
65 2026-09-19 20:01:05 23 3 [Ashen Miracle] Oguri Cap Asahi Hai Futurity Stakes 624 3 1750 70 1.5022 0 6 0 0 2975.0 3153 178.0 5.9832 3153 0
66 2026-09-19 20:01:05 24 3 [Ashen Miracle] Oguri Cap Hopeful Stakes 625 1 7000 70 5.6931 0 6 0 0 11900.0 12614 714.0 6.0 12614 0
67 2026-09-19 20:01:05 33 3 [Ashen Miracle] Oguri Cap NHK Mile Cup 164 1 10500 70 1.488 0 2 0 0 17850.0 18207 357.0 2.0 18207 0
68 2026-09-19 20:01:05 46 3 [Ashen Miracle] Oguri Cap Mile Championship 78 1 11000 70 3.8134 0 4 0 0 18700.0 19448 748.0 4.0 19448 0
69 2026-09-19 20:01:05 48 3 [Ashen Miracle] Oguri Cap Arima Kinen 81 1 30000 70 2.6633 0 4 0 0 51000.0 53040 2040.0 4.0 53040 0
70 2026-09-19 20:01:05 52 3 [Ashen Miracle] Oguri Cap February Stakes 1 1 10000 70 0.6637 0 0 0 0 17000.0 17000 0.0 0.0 17000 0
71 2026-09-19 20:01:05 59 3 [Ashen Miracle] Oguri Cap Yasuda Kinen 73 1 13000 70 5.9364 0 6 0 0 22100.0 23426 1326.0 6.0 23426 0
72 2026-09-19 20:01:05 68 3 [Ashen Miracle] Oguri Cap Tenno Sho (Autumn) 76 1 15000 70 6.0564 0 9 0 0 25500.0 27795 2295.0 9.0 27795 0
73 2026-09-19 20:01:05 72 3 [Ashen Miracle] Oguri Cap Arima Kinen 81 1 30000 70 7.8703 0 9 0 0 51000.0 55590 4590.0 9.0 55590 0
74 2026-09-19 20:01:05 74 3 [Ashen Miracle] Oguri Cap URA Finale Qualifier 2015 1 7000 70 5.8192 0 6 0 0 11900.0 12614 714.0 6.0 12614 0
75 2026-09-19 20:01:05 76 3 [Ashen Miracle] Oguri Cap URA Finale Semifinal 2111 1 10000 70 5.2726 0 6 0 0 17000.0 18020 1020.0 6.0 18020 0
76 2026-09-19 20:01:05 78 3 [Ashen Miracle] Oguri Cap URA Finale Finals 2213 1 30000 70 5.6513 0 6 0 0 51000.0 54060 3060.0 6.0 54060 0
77 2026-09-19 21:45:59 12 2 [Blossom in Learning] Sakura Bakushin O Junior Make Debut 676 1 700 65 1.7631 0 2 0 0 1155.0 1178 23.0 1.9913 1178 0
78 2026-09-19 21:45:59 21 2 [Blossom in Learning] Sakura Bakushin O Keio Hai Junior Stakes 626 1 3800 65 0.917 0 2 0 0 6270.0 6395 125.0 1.9936 6395 0
79 2026-09-19 21:45:59 30 2 [Blossom in Learning] Sakura Bakushin O Spring Stakes 171 2 2160 65 0.7907 1 6 2 0 3564.0 3847 283.0 7.9405 3847 0
80 2026-09-19 21:45:59 34 2 [Blossom in Learning] Sakura Bakushin O Aoi Stakes 210 2 1520 65 1.5851 0 6 0 0 2508.0 2658 150.0 5.9809 2658 0
81 2026-09-19 21:45:59 35 2 [Blossom in Learning] Sakura Bakushin O Epsom Cup 95 1 4100 65 1.3364 1 2 2 0 6765.0 7035 270.0 3.9911 7035 0
82 2026-09-19 21:45:59 42 2 [Blossom in Learning] Sakura Bakushin O Sprinters Stakes 75 3 3250 65 0.8705 0 6 0 0 5362.5 5684 321.5 5.9953 5684 0
83 2026-09-19 21:45:59 54 2 [Blossom in Learning] Sakura Bakushin O Takamatsunomiya Kinen 2 2 5200 65 0.451 0 9 0 0 8580.0 9352 772.0 8.9977 9352 0
84 2026-09-19 21:45:59 60 2 [Blossom in Learning] Sakura Bakushin O Hakodate Sprint Stakes 96 1 3900 65 0.9971 0 2 0 0 6435.0 6563 128.0 1.9891 6563 0
85 2026-09-19 21:45:59 61 2 [Blossom in Learning] Sakura Bakushin O CBC Sho 97 1 3900 65 2.3483 0 2 0 0 6435.0 6563 128.0 1.9891 6563 0
86 2026-09-19 21:45:59 65 2 [Blossom in Learning] Sakura Bakushin O Centaur Stakes 83 1 5900 65 1.5096 0 2 0 0 9735.0 9929 194.0 1.9928 9929 0
87 2026-09-19 21:45:59 66 2 [Blossom in Learning] Sakura Bakushin O Sprinters Stakes 75 6 1170 65 2.5098 1 0 2 0 1930.5 1968 37.5 1.9425 1968 0
88 2026-09-23 23:41:07 12 1 [Blossom in Learning] Sakura Bakushin O Junior Make Debut 676 1 700 65 2.7319 0 4 0 0 1155.0 1201 46.0 3.9827 1201 0
89 2026-09-23 23:41:07 21 1 [Blossom in Learning] Sakura Bakushin O Keio Hai Junior Stakes 626 1 3800 65 0.5164 0 0 0 0 6270.0 6270 0.0 0.0 6270 0
90 2026-09-23 23:41:07 30 1 [Blossom in Learning] Sakura Bakushin O Spring Stakes 171 1 5400 65 2.4521 1 2 2 0 8910.0 9266 356.0 3.9955 9266 0
91 2026-09-23 23:41:07 34 1 [Blossom in Learning] Sakura Bakushin O Aoi Stakes 210 1 3800 65 0.4297 0 0 0 0 6270.0 6270 0.0 0.0 6270 0
92 2026-09-23 23:41:07 42 1 [Blossom in Learning] Sakura Bakushin O Sprinters Stakes 75 6 1170 65 3.8513 0 0 0 0 1930.5 1930 -0.5 -0.0259 1930 0
93 2026-09-28 14:22:08 12 1 [Hot☆Summer Night] Maruzensky Junior Make Debut 676 1 700 65 0.2547 0 0 0 0 1155.0 1155 0.0 0.0 1155 0
94 2026-10-01 09:39:24 12 2 [Wild Frontier] Taiki Shuttle Junior Make Debut 846 1 700 80 2.9274 1 4 2 0 1260.0 1335 75.0 5.9524 1335 0
95 2026-10-01 09:39:24 25 2 [Wild Frontier] Taiki Shuttle Shinzan Kinen 178 1 3800 80 3.297 0 4 0 0 6840.0 7113 273.0 3.9912 7113 0
96 2026-10-01 09:39:24 33 2 [Wild Frontier] Taiki Shuttle NHK Mile Cup 164 1 10500 80 1.5041 0 2 0 0 18900.0 19278 378.0 2.0 19278 0
97 2026-10-01 09:39:24 36 2 [Wild Frontier] Taiki Shuttle Unicorn Stakes 189 1 3500 80 0.0829 0 0 0 0 6300.0 6300 0.0 0.0 6300 0
98 2026-10-01 09:39:24 46 2 [Wild Frontier] Taiki Shuttle Mile Championship 78 1 11000 80 1.3511 1 2 2 0 19800.0 20592 792.0 4.0 20592 0
99 2026-10-01 09:39:24 59 2 [Wild Frontier] Taiki Shuttle Yasuda Kinen 73 1 13000 80 4.4812 0 6 0 0 23400.0 24804 1404.0 6.0 24804 0
100 2026-10-01 09:39:24 66 2 [Wild Frontier] Taiki Shuttle Sprinters Stakes 75 1 13000 80 3.6966 1 4 2 0 23400.0 24804 1404.0 6.0 24804 0
101 2026-10-01 09:39:24 70 2 [Wild Frontier] Taiki Shuttle Mile Championship 78 1 11000 80 3.6774 0 4 0 0 19800.0 20592 792.0 4.0 20592 0
102 2026-10-01 09:39:24 74 2 [Wild Frontier] Taiki Shuttle URA Finale Qualifier 2013 1 7000 80 4.0671 0 6 0 0 12600.0 13356 756.0 6.0 13356 0
103 2026-10-01 09:39:24 76 2 [Wild Frontier] Taiki Shuttle URA Finale Semifinal 2109 1 10000 80 4.9632 1 6 2 0 18000.0 19440 1440.0 8.0 19440 0
104 2026-10-01 09:39:24 78 2 [Wild Frontier] Taiki Shuttle URA Finale Finals 2214 1 30000 80 1.1329 0 2 0 0 54000.0 55080 1080.0 2.0 55080 0
105 2026-10-04 14:36:48 12 4 [Wild Frontier] Taiki Shuttle Junior Make Debut 846 1 700 105 2.6127 1 4 2 0 1435.0 1521 86.0 5.993 1521 0
106 2026-10-04 14:36:48 14 4 [Wild Frontier] Taiki Shuttle Hakodate Junior Stakes 628 1 3100 105 4.3676 0 6 0 0 6355.0 6736 381.0 5.9953 6736 0
107 2026-10-04 14:36:48 16 4 [Wild Frontier] Taiki Shuttle Niigata Junior Stakes 629 1 3100 105 2.8947 0 4 0 0 6355.0 6609 254.0 3.9969 6609 0
108 2026-10-04 14:36:48 17 4 [Wild Frontier] Taiki Shuttle Sapporo Junior Stakes 630 1 3100 105 2.2675 1 2 2 0 6355.0 6609 254.0 3.9969 6609 0
109 2026-10-04 14:36:48 21 4 [Wild Frontier] Taiki Shuttle Keio Hai Junior Stakes 626 1 3800 105 1.8215 1 2 2 0 7790.0 8101 311.0 3.9923 8101 0
110 2026-10-04 14:36:48 22 4 [Wild Frontier] Taiki Shuttle Tokyo Sports Hai Junior Stakes 635 1 3300 105 4.1972 0 6 0 0 6765.0 7170 405.0 5.9867 7170 0
111 2026-10-04 14:36:48 23 4 [Wild Frontier] Taiki Shuttle Hanshin Juvenile Fillies 623 1 6500 105 4.4133 1 6 2 0 13325.0 14391 1066.0 8.0 14391 0
112 2026-10-04 14:36:48 24 4 [Wild Frontier] Taiki Shuttle Zen-Nippon Junior Yushun 1107 2 1680 105 0.6647 1 9 2 0 3444.0 3821 377.0 10.9466 3821 0
113 2026-10-04 14:36:48 27 4 [Wild Frontier] Taiki Shuttle Kyodo News Hai 183 1 3800 105 3.9819 1 4 2 0 7790.0 8257 467.0 5.9949 8257 0
114 2026-10-04 14:36:48 29 4 [Wild Frontier] Taiki Shuttle Fillies' Revue 170 2 2080 105 0.056 1 9 2 0 4264.0 4731 467.0 10.9522 4731 0
115 2026-10-04 14:36:48 30 4 [Wild Frontier] Taiki Shuttle Spring Stakes 171 1 5400 105 1.5715 1 2 2 0 11070.0 11513 443.0 4.0018 11513 0
116 2026-10-04 14:36:48 31 4 [Wild Frontier] Taiki Shuttle Oka Sho 162 1 10500 105 2.0067 0 2 0 0 21525.0 21956 431.0 2.0023 21956 0
117 2026-10-04 14:36:48 33 4 [Wild Frontier] Taiki Shuttle NHK Mile Cup 164 1 10500 105 1.3928 0 2 0 0 21525.0 21956 431.0 2.0023 21956 0
118 2026-10-04 14:36:48 35 4 [Wild Frontier] Taiki Shuttle Yasuda Kinen 73 1 13000 105 1.2662 1 2 2 0 26650.0 27716 1066.0 4.0 27716 0
119 2026-10-04 14:36:48 39 4 [Wild Frontier] Taiki Shuttle Sekiya Kinen 105 1 3900 105 3.8619 0 4 0 0 7995.0 8314 319.0 3.99 8314 0
120 2026-10-04 14:36:48 41 4 [Wild Frontier] Taiki Shuttle Rose Stakes 176 1 5200 105 3.3191 1 4 2 0 10660.0 11300 640.0 6.0038 11300 0
121 2026-10-04 14:36:48 42 4 [Wild Frontier] Taiki Shuttle Sprinters Stakes 75 1 13000 105 3.2007 1 4 2 0 26650.0 28249 1599.0 6.0 28249 0
122 2026-10-04 14:36:48 43 4 [Wild Frontier] Taiki Shuttle M.C. Nambu Hai 1109 1 6000 105 2.7546 0 4 0 0 12300.0 12792 492.0 4.0 12792 0
123 2026-10-04 14:36:48 45 4 [Wild Frontier] Taiki Shuttle JBC Sprint 1111 1 6000 105 1.5294 1 2 2 0 12300.0 12792 492.0 4.0 12792 0
124 2026-10-04 14:36:48 46 4 [Wild Frontier] Taiki Shuttle Mile Championship 78 1 11000 105 2.2484 0 2 0 0 22550.0 23001 451.0 2.0 23001 0
125 2026-10-04 14:36:48 47 4 [Wild Frontier] Taiki Shuttle Champions Cup 80 1 10000 105 2.5859 0 4 0 0 20500.0 21320 820.0 4.0 21320 0
126 2026-10-04 14:36:48 50 4 [Wild Frontier] Taiki Shuttle Negishi Stakes 22 2 1520 105 1.4117 0 6 0 0 3116.0 3302 186.0 5.9692 3302 0
127 2026-10-04 14:36:48 52 4 [Wild Frontier] Taiki Shuttle February Stakes 1 1 10000 105 0.0968 0 0 0 0 20500.0 20500 0.0 0.0 20500 0
128 2026-10-04 14:36:48 54 4 [Wild Frontier] Taiki Shuttle Takamatsunomiya Kinen 2 1 13000 105 3.2402 0 4 0 0 26650.0 27716 1066.0 4.0 27716 0
129 2026-10-04 14:36:48 55 4 [Wild Frontier] Taiki Shuttle Marine Cup 1128 1 2500 105 2.6992 0 4 0 0 5125.0 5330 205.0 4.0 5330 0
130 2026-10-04 14:36:48 57 4 [Wild Frontier] Taiki Shuttle Victoria Mile 5 1 10500 105 1.5024 0 2 0 0 21525.0 21956 431.0 2.0023 21956 0
131 2026-10-04 14:36:48 58 4 [Wild Frontier] Taiki Shuttle Keyaki Stakes 71 1 2200 105 3.8244 1 4 2 0 4510.0 4780 270.0 5.9867 4780 0
132 2026-10-04 14:36:48 59 4 [Wild Frontier] Taiki Shuttle Yasuda Kinen 73 1 13000 105 1.4361 1 2 2 0 26650.0 27716 1066.0 4.0 27716 0
133 2026-10-04 14:36:48 62 4 [Wild Frontier] Taiki Shuttle Queen Stakes 103 1 3600 105 5.0515 0 6 0 0 7380.0 7822 442.0 5.9892 7822 0
134 2026-10-04 14:36:48 65 4 [Wild Frontier] Taiki Shuttle Keisei Hai Autumn Handicap 110 1 3900 105 5.633 0 6 0 0 7995.0 8474 479.0 5.9912 8474 0
135 2026-10-04 14:36:48 66 4 [Wild Frontier] Taiki Shuttle Sprinters Stakes 75 1 13000 105 2.6328 0 4 0 0 26650.0 27716 1066.0 4.0 27716 0
136 2026-10-04 14:36:48 67 4 [Wild Frontier] Taiki Shuttle M.C. Nambu Hai 1109 1 6000 105 4.184 0 6 0 0 12300.0 13038 738.0 6.0 13038 0
137 2026-10-04 14:36:48 69 4 [Wild Frontier] Taiki Shuttle JBC Sprint 1025 1 6000 105 2.1263 1 2 2 0 12300.0 12792 492.0 4.0 12792 0
138 2026-10-04 14:36:48 70 4 [Wild Frontier] Taiki Shuttle Mile Championship 78 1 11000 105 2.1798 0 2 0 0 22550.0 23001 451.0 2.0 23001 0
139 2026-10-04 14:36:48 71 4 [Wild Frontier] Taiki Shuttle Champions Cup 80 1 10000 105 0.8076 1 2 2 0 20500.0 21320 820.0 4.0 21320 0
140 2026-10-04 14:36:48 74 4 [Wild Frontier] Taiki Shuttle Twinkle Star Climax Race 1 2313 1 7000 105 4.0466 1 6 2 0 14350.0 15498 1148.0 8.0 15498 0
141 2026-10-04 14:36:48 76 4 [Wild Frontier] Taiki Shuttle Twinkle Star Climax Race 2 2410 1 10000 105 1.8345 1 2 2 0 20500.0 21320 820.0 4.0 21320 0
142 2026-10-04 14:36:48 78 4 [Wild Frontier] Taiki Shuttle Twinkle Star Climax Race 3 2515 1 30000 105 5.1406 1 6 2 50 61500.0 99630 38130.0 62.0 99630 0
143 2026-10-08 10:00:27 12 3 [CODE: ICING] Mihono Bourbon Junior Make Debut 1075 1 700 70 3.126 1 4 2 0 1190.0 1261 71.0 5.9664 1261 0
144 2026-10-08 10:00:27 23 3 [CODE: ICING] Mihono Bourbon Asahi Hai Futurity Stakes 624 1 7000 70 3.0099 2 4 2 0 11900.0 12614 714.0 6.0 12614 0
145 2026-10-08 10:00:27 30 3 [CODE: ICING] Mihono Bourbon Spring Stakes 171 1 5400 70 1.4594 1 2 2 0 9180.0 9547 367.0 3.9978 9547 0
146 2026-10-08 10:00:27 31 3 [CODE: ICING] Mihono Bourbon Satsuki Sho 163 1 11000 70 6.1843 2 9 2 0 18700.0 20757 2057.0 11.0 20757 0
147 2026-10-08 10:00:27 34 3 [CODE: ICING] Mihono Bourbon Tokyo Yushun (Japanese Derby) 166 1 20000 70 4.682 2 6 2 0 34000.0 36720 2720.0 8.0 36720 0
148 2026-10-08 10:00:27 44 3 [CODE: ICING] Mihono Bourbon Kikuka Sho 168 1 12000 70 3.5273 1 4 2 0 20400.0 21624 1224.0 6.0 21624 0
149 2026-10-08 10:00:27 56 3 [CODE: ICING] Mihono Bourbon Tenno Sho (Spring) 4 1 15000 70 10.0374 2 9 2 0 25500.0 28305 2805.0 11.0 28305 0
150 2026-10-08 10:00:27 70 3 [CODE: ICING] Mihono Bourbon Japan Cup 79 1 30000 70 10.1623 2 9 2 0 51000.0 56610 5610.0 11.0 56610 0
151 2026-10-08 10:00:27 72 3 [CODE: ICING] Mihono Bourbon Arima Kinen 81 1 30000 70 10.4669 3 9 2 0 51000.0 56610 5610.0 11.0 56610 0
152 2026-10-08 10:00:27 74 3 [CODE: ICING] Mihono Bourbon URA Finale Qualifier 2010 1 7000 70 5.7274 3 6 2 0 11900.0 12852 952.0 8.0 12852 0
153 2026-10-08 10:00:27 76 3 [CODE: ICING] Mihono Bourbon URA Finale Semifinal 2113 1 10000 70 3.7223 3 4 2 0 17000.0 18020 1020.0 6.0 18020 0
154 2026-10-08 10:00:27 78 3 [CODE: ICING] Mihono Bourbon URA Finale Finals 2209 1 30000 70 3.873 3 4 2 0 51000.0 54060 3060.0 6.0 54060 0
155 2026-10-10 03:12:29 12 3 [Soirée des Chatons] Seiun Sky Junior Make Debut 689 1 700 70 3.0303 1 4 2 0 1190.0 1261 71.0 5.9664 1261 0
156 2026-10-10 03:12:29 24 3 [Soirée des Chatons] Seiun Sky Hopeful Stakes 625 1 7000 70 2.1576 1 2 2 0 11900.0 12376 476.0 4.0 12376 0
157 2026-10-10 03:12:29 31 3 [Soirée des Chatons] Seiun Sky Satsuki Sho 163 1 11000 70 2.5681 2 4 2 0 18700.0 19822 1122.0 6.0 19822 0
158 2026-10-10 03:12:29 34 3 [Soirée des Chatons] Seiun Sky Tokyo Yushun (Japanese Derby) 166 1 20000 70 2.4678 2 2 2 0 34000.0 35360 1360.0 4.0 35360 0
159 2026-10-10 03:12:29 44 3 [Soirée des Chatons] Seiun Sky Kikuka Sho 168 1 12000 70 0.6938 2 0 2 0 20400.0 20808 408.0 2.0 20808 0
160 2026-10-10 03:12:29 48 3 [Soirée des Chatons] Seiun Sky Arima Kinen 81 1 30000 70 3.3828 2 4 2 0 51000.0 54060 3060.0 6.0 54060 0
161 2026-10-10 03:12:29 56 3 [Soirée des Chatons] Seiun Sky Tenno Sho (Spring) 4 1 15000 70 20.5803 10 9 8 0 25500.0 29835 4335.0 17.0 29835 0
162 2026-10-10 03:12:29 60 3 [Soirée des Chatons] Seiun Sky Takarazuka Kinen 74 1 15000 70 6.4095 10 9 8 0 25500.0 29835 4335.0 17.0 29835 0
163 2026-10-10 03:12:29 68 3 [Soirée des Chatons] Seiun Sky Tenno Sho (Autumn) 76 1 15000 70 9.3985 9 9 5 0 25500.0 29070 3570.0 14.0 29070 0
164 2026-10-10 03:12:29 72 3 [Soirée des Chatons] Seiun Sky Arima Kinen 81 1 30000 70 11.7606 10 9 8 0 51000.0 59670 8670.0 17.0 59670 0
165 2026-10-10 03:12:29 74 3 [Soirée des Chatons] Seiun Sky URA Finale Qualifier 2018 1 7000 70 11.2054 9 9 5 0 11900.0 13566 1666.0 14.0 13566 0
166 2026-10-10 03:12:29 76 3 [Soirée des Chatons] Seiun Sky URA Finale Semifinal 2123 1 10000 70 8.0601 7 9 5 0 17000.0 19380 2380.0 14.0 19380 0
167 2026-10-10 03:12:29 78 3 [Soirée des Chatons] Seiun Sky URA Finale Finals 2222 1 30000 70 5.7947 8 6 5 0 51000.0 56610 5610.0 11.0 56610 0
168 2026-10-10 15:53:30 12 3 [Soirée des Chatons] Seiun Sky Junior Make Debut 689 1 700 70 3.7946 2 4 2 0 1190.0 1261 71.0 5.9664 1261 0
169 2026-10-10 15:53:30 24 3 [Soirée des Chatons] Seiun Sky Hopeful Stakes 625 1 7000 70 5.3394 1 6 2 0 11900.0 12852 952.0 8.0 12852 0
170 2026-10-10 15:53:30 31 3 [Soirée des Chatons] Seiun Sky Satsuki Sho 163 1 11000 70 7.5947 2 9 2 0 18700.0 20757 2057.0 11.0 20757 0
171 2026-10-10 15:53:30 34 3 [Soirée des Chatons] Seiun Sky Tokyo Yushun (Japanese Derby) 166 1 20000 70 2.1677 4 2 3 0 34000.0 35700 1700.0 5.0 35700 0
172 2026-10-10 15:53:30 44 3 [Soirée des Chatons] Seiun Sky Kikuka Sho 168 3 3000 70 3.8191 4 4 3 0 5100.0 5457 357.0 7.0 5457 0
173 2026-10-10 15:53:30 48 3 [Soirée des Chatons] Seiun Sky Arima Kinen 81 1 30000 70 12.6422 3 9 2 0 51000.0 56610 5610.0 11.0 56610 0
174 2026-10-10 15:53:30 56 3 [Soirée des Chatons] Seiun Sky Tenno Sho (Spring) 4 1 15000 70 1.11 7 2 5 0 25500.0 27285 1785.0 7.0 27285 0
175 2026-10-10 15:53:30 60 3 [Soirée des Chatons] Seiun Sky Takarazuka Kinen 74 1 15000 70 13.7279 7 9 5 0 25500.0 29070 3570.0 14.0 29070 0
176 2026-10-10 15:53:30 68 3 [Soirée des Chatons] Seiun Sky Tenno Sho (Autumn) 76 1 15000 70 3.6698 6 4 3 0 25500.0 27285 1785.0 7.0 27285 0
177 2026-10-10 15:53:30 72 3 [Soirée des Chatons] Seiun Sky Arima Kinen 81 1 30000 70 13.5919 8 9 5 0 51000.0 58140 7140.0 14.0 58140 0
178 2026-10-10 15:53:30 74 3 [Soirée des Chatons] Seiun Sky URA Finale Qualifier 2025 1 7000 70 13.045 7 9 5 0 11900.0 13566 1666.0 14.0 13566 0
179 2026-10-10 15:53:30 76 3 [Soirée des Chatons] Seiun Sky URA Finale Semifinal 2122 1 10000 70 12.4002 7 9 5 0 17000.0 19380 2380.0 14.0 19380 0
180 2026-10-10 15:53:30 78 3 [Soirée des Chatons] Seiun Sky URA Finale Finals 2217 1 30000 70 12.3247 7 9 5 0 51000.0 58140 7140.0 14.0 58140 0
181 2026-10-11 18:47:03 12 3 [Soirée des Chatons] Seiun Sky Junior Make Debut 689 1 700 80 3.2149 2 4 2 0 1260.0 1335 75.0 5.9524 1335 0
182 2026-10-11 18:47:03 24 3 [Soirée des Chatons] Seiun Sky Hopeful Stakes 625 1 7000 80 2.4816 2 2 2 0 12600.0 13104 504.0 4.0 13104 0
183 2026-10-11 19:13:35 12 3 [Soirée des Chatons] Seiun Sky Junior Make Debut 689 1 700 80 4.1512 1 6 2 0 1260.0 1360 100.0 7.9365 1360 0
184 2026-10-11 19:13:35 24 3 [Soirée des Chatons] Seiun Sky Hopeful Stakes 625 1 7000 80 2.8651 2 4 2 0 12600.0 13356 756.0 6.0 13356 0
185 2026-10-11 19:13:35 31 3 [Soirée des Chatons] Seiun Sky Satsuki Sho 163 1 11000 80 4.6012 2 6 2 0 19800.0 21384 1584.0 8.0 21384 0
186 2026-10-11 19:13:35 34 3 [Soirée des Chatons] Seiun Sky Tokyo Yushun (Japanese Derby) 166 1 20000 80 4.1483 2 6 2 0 36000.0 38880 2880.0 8.0 38880 0
187 2026-10-11 19:13:35 44 3 [Soirée des Chatons] Seiun Sky Kikuka Sho 168 2 4800 80 4.218 2 2 2 0 8640.0 8985 345.0 3.9931 8985 0
188 2026-10-11 19:13:35 48 3 [Soirée des Chatons] Seiun Sky Arima Kinen 81 1 30000 80 10.0709 3 9 2 0 54000.0 59940 5940.0 11.0 59940 0
189 2026-10-11 19:13:35 56 3 [Soirée des Chatons] Seiun Sky Tenno Sho (Spring) 4 1 15000 80 6.5113 8 9 5 0 27000.0 30780 3780.0 14.0 30780 0
190 2026-10-11 19:13:35 60 3 [Soirée des Chatons] Seiun Sky Takarazuka Kinen 74 1 15000 80 6.7601 6 9 3 0 27000.0 30240 3240.0 12.0 30240 0
191 2026-10-11 19:13:35 72 3 [Soirée des Chatons] Seiun Sky Arima Kinen 81 1 30000 80 14.0565 7 9 5 0 54000.0 61560 7560.0 14.0 61560 0
192 2026-10-11 19:13:35 74 3 [Soirée des Chatons] Seiun Sky URA Finale Qualifier 2018 1 7000 80 10.2344 7 9 5 0 12600.0 14364 1764.0 14.0 14364 0
193 2026-10-11 19:13:35 76 3 [Soirée des Chatons] Seiun Sky URA Finale Semifinal 2121 1 10000 80 5.3797 5 6 3 0 18000.0 19620 1620.0 9.0 19620 0
194 2026-10-11 19:13:35 78 3 [Soirée des Chatons] Seiun Sky URA Finale Finals 2222 1 30000 80 7.7281 7 9 5 0 54000.0 61560 7560.0 14.0 61560 0