1 Commits
Author SHA1 Message Date
zephyr 6262e3c430 cmd/factorfactor: initial work 2026-09-23 09:17:27 -04:00
49 changed files with 708 additions and 20506 deletions
+77
View File
@@ -0,0 +1,77 @@
package main
import (
"log/slog"
"git.sunturtle.xyz/zephyr/horse"
"git.sunturtle.xyz/zephyr/horse/umadump/ism"
)
// For each gain type from inspiration (stats, caps, aptitudes, skills):
// find all activated sparks that can give that gain type.
// Then, find all subsets of effect groups among those sparks
// that have effects summing to those observed
// (or more if the .end_info result is maxed),
// with the restriction that one comes from each spark.
// Deduplicate permutations.
// Lastly, find the intersection of possible effects from sparks that appear
// multiple times.
//
// To some extent, we rely on there being no sparks with the random stats effect type,
// although we also don't know the distribution of stats from overcapped skill hints.
type target struct {
spark *horse.Spark
group int
effect horse.SparkEffect
}
func skilltargets(sparks []horse.Spark) map[horse.SkillID]map[horse.SparkID][]target {
r := make(map[horse.SkillID]map[horse.SparkID][]target)
for i, sp := range sparks {
for j, g := range sp.Effects {
for _, e := range g {
if e.Target != horse.SparkSkillHint {
continue
}
if r[horse.SkillID(e.Value1)] == nil {
r[horse.SkillID(e.Value1)] = make(map[horse.SparkID][]target)
}
r[horse.SkillID(e.Value1)][sp.ID] = append(r[horse.SkillID(e.Value1)][sp.ID], target{&sparks[i], j, e})
}
}
}
return r
}
func resolveSkills(tab tables, career *ism.WorkIdleSingleMode)
// skillsparks appends all activated sparks that can yield a given skill to r.
// It assumes that no spark can give multiple skills.
func skillsparks(tab tables, sparks []ism.Factor, id horse.SkillID, r []*horse.Spark) []*horse.Spark {
for _, f := range sparks {
sp := tab.sparks[f.FactorID]
if sp == nil {
// ATM we do generally exclude Carnival Bonus from spark info.
// Better to check.
slog.Warn("skipped spark", slog.Int("id", int(f.FactorID)))
continue
}
if sparkHasSkill(sp, id) {
r = append(r, sp)
}
}
return r
}
func sparkHasSkill(sp *horse.Spark, id horse.SkillID) bool {
for _, g := range sp.Effects {
for _, e := range g {
if e.Target != horse.SparkSkillHint {
continue
}
return id == horse.SkillID(e.Value1)
}
}
return false
}
+111
View File
@@ -0,0 +1,111 @@
package main
import (
"context"
"encoding/json"
"flag"
"fmt"
"log/slog"
"os"
"os/signal"
"path/filepath"
"slices"
"git.sunturtle.xyz/zephyr/horse/mdb"
"git.sunturtle.xyz/zephyr/horse/umadump/ism"
"golang.org/x/sync/errgroup"
"zombiezen.com/go/sqlite"
"zombiezen.com/go/sqlite/sqlitex"
)
func main() {
var (
mdbf string
dirs []string
files []string
)
flag.StringVar(&mdbf, "-mdb", "", "`path` to master.mdb")
flag.Func("d", "idle_single_mode `dir`ectory (may be specified multiple times)", func(s string) error {
dirs = append(dirs, s)
return nil
})
flag.Parse()
files = slices.Clone(flag.Args())
for _, dir := range dirs {
ds, err := os.ReadDir(dir)
if err != nil {
slog.Error("getting files in directory", slog.String("dir", dir), slog.Any("err", err))
os.Exit(1)
}
for _, d := range ds {
if d.IsDir() {
continue
}
files = append(files, filepath.Join(dir, d.Name()))
}
}
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
go func() {
<-ctx.Done()
stop()
}()
db, err := sqlitex.NewPool(mdbf, sqlitex.PoolOptions{Flags: sqlite.OpenReadOnly})
if err != nil {
slog.Error("mdb", slog.Any("err", err))
os.Exit(1)
}
slog.Info("load skills")
skills, err := mdb.Skills(ctx, db)
if err != nil {
slog.Error("skills", slog.Any("err", err))
os.Exit(1)
}
slog.Info("load sparks")
sparks, err := mdb.Sparks(ctx, db)
if err != nil {
slog.Error("sparks", slog.Any("err", err))
os.Exit(1)
}
slog.Info("load umas")
umas, err := mdb.Umas(ctx, db)
if err != nil {
slog.Error("umas", slog.Any("err", err))
os.Exit(1)
}
slog.Info("mdb",
slog.Int("sparks", len(sparks)),
slog.Int("skills", len(skills)),
slog.Int("umas", len(umas)),
)
tab := makeTables(skills, sparks, umas)
g, ctx := errgroup.WithContext(ctx)
g.SetLimit(64)
for _, file := range files {
g.Go(func() error {
return dofile(ctx, file)
})
}
if err := g.Wait(); err != nil {
slog.Error("process", slog.Any("err", err))
os.Exit(1)
}
}
func dofile(ctx context.Context, file string) error {
f, err := os.Open(file)
if err != nil {
return err
}
var career ism.WorkIdleSingleMode
d := json.NewDecoder(f)
d.DisallowUnknownFields()
if err := d.Decode(&career); err != nil {
return fmt.Errorf("%s: %w", file, err)
}
}
+37
View File
@@ -0,0 +1,37 @@
package main
import "git.sunturtle.xyz/zephyr/horse"
type tables struct {
skills map[horse.SkillID]*horse.Skill
groups map[horse.SkillGroupID]map[int8]*horse.Skill
sparks map[horse.SparkID]*horse.Spark
umas map[horse.UmaID]*horse.Uma
}
func makeTables(skills []horse.Skill, sparks []horse.Spark, umas []horse.Uma) tables {
tab := tables{
skills: make(map[horse.SkillID]*horse.Skill, len(skills)),
groups: make(map[horse.SkillGroupID]map[int8]*horse.Skill, len(skills)/2),
sparks: make(map[horse.SparkID]*horse.Spark, len(sparks)),
umas: make(map[horse.UmaID]*horse.Uma, len(umas)),
}
for i, sk := range skills {
tab.skills[sk.ID] = &skills[i]
if tab.groups[sk.Group] == nil {
tab.groups[sk.Group] = make(map[int8]*horse.Skill, 4)
}
// Only add the skill to the groups table if they're rare, the base
// version of the common skill, or there isn't anything else there.
if sk.Rarity == 2 || sk.GroupRate == 1 || tab.groups[sk.Group][sk.Rarity] == nil {
tab.groups[sk.Group][sk.Rarity] = &skills[i]
}
}
for i, sp := range sparks {
tab.sparks[sp.ID] = &sparks[i]
}
for i, u := range umas {
tab.umas[u.ID] = &umas[i]
}
return tab
}
-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]]
}
-35
View File
@@ -1,35 +0,0 @@
// Code generated by "stringer -type CharaGradeType -linecomment -trimprefix CharaGrade"; 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[CharaGradeNone-0]
_ = x[CharaGradeDebut-1]
_ = x[CharaGradeNoWin-2]
_ = x[CharaGradeOpen-3]
_ = x[CharaGradeG3Silver-4]
_ = x[CharaGradeG3Gold-5]
_ = x[CharaGradeG2Silver-6]
_ = x[CharaGradeG2Gold-7]
_ = x[CharaGradeG1Bronze-8]
_ = x[CharaGradeG1Silver-9]
_ = x[CharaGradeG1Gold-10]
_ = x[charaGradeMax-11]
}
const _CharaGradeType_name = "NONEDebutNoWinOpenG3SilverG3GoldG2SilverG2GoldG1BronzeG1SilverG1GoldcharaGradeMax"
var _CharaGradeType_index = [...]uint8{0, 4, 9, 14, 18, 26, 32, 40, 46, 54, 62, 68, 81}
func (i CharaGradeType) String() string {
idx := int(i) - 0
if i < 0 || idx >= len(_CharaGradeType_index)-1 {
return "CharaGradeType(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _CharaGradeType_name[_CharaGradeType_index[idx]:_CharaGradeType_index[idx+1]]
}
@@ -1,27 +0,0 @@
// Code generated by "stringer -type CourseDistanceType -linecomment -trimprefix Distance"; 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[DistanceSprint-1]
_ = x[DistanceMile-2]
_ = x[DistanceMedium-3]
_ = x[DistanceLong-4]
}
const _CourseDistanceType_name = "ShortMileMiddleLong"
var _CourseDistanceType_index = [...]uint8{0, 5, 9, 15, 19}
func (i CourseDistanceType) String() string {
idx := int(i) - 1
if i < 1 || idx >= len(_CourseDistanceType_index)-1 {
return "CourseDistanceType(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _CourseDistanceType_name[_CourseDistanceType_index[idx]:_CourseDistanceType_index[idx+1]]
}
-27
View File
@@ -1,27 +0,0 @@
// Code generated by "stringer -type GroundCondition -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[GroundFirm-1]
_ = x[GroundGood-2]
_ = x[GroundSoft-3]
_ = x[GroundHeavy-4]
}
const _GroundCondition_name = "GoodSoftHardBad"
var _GroundCondition_index = [...]uint8{0, 4, 8, 12, 15}
func (i GroundCondition) String() string {
idx := int(i) - 1
if i < 1 || idx >= len(_GroundCondition_index)-1 {
return "GroundCondition(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _GroundCondition_name[_GroundCondition_index[idx]:_GroundCondition_index[idx+1]]
}
-28
View File
@@ -1,28 +0,0 @@
// Code generated by "stringer -type InitialLaneType -trimprefix InitialLane"; 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[InitialLaneExtraSpaceAfter9-1]
_ = x[InitialLaneEquidistant-2]
_ = x[InitialLaneExtraSpaceAfter14-3]
_ = x[InitialLaneExtraSpaceAfter8-4]
_ = x[initialLaneMax-5]
}
const _InitialLaneType_name = "ExtraSpaceAfter9EquidistantExtraSpaceAfter14ExtraSpaceAfter8initialLaneMax"
var _InitialLaneType_index = [...]uint8{0, 16, 27, 44, 60, 74}
func (i InitialLaneType) String() string {
idx := int(i) - 1
if i < 1 || idx >= len(_InitialLaneType_index)-1 {
return "InitialLaneType(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _InitialLaneType_name[_InitialLaneType_index[idx]:_InitialLaneType_index[idx+1]]
}
@@ -1,26 +0,0 @@
// Code generated by "stringer -type MainStoryRaceGimmickType -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[GimmickNone-0]
_ = x[GimmickSpecial00-1]
_ = x[gimmickMax-2]
}
const _MainStoryRaceGimmickType_name = "NONESpecial_00gimmickMax"
var _MainStoryRaceGimmickType_index = [...]uint8{0, 4, 14, 24}
func (i MainStoryRaceGimmickType) String() string {
idx := int(i) - 0
if i < 0 || idx >= len(_MainStoryRaceGimmickType_index)-1 {
return "MainStoryRaceGimmickType(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _MainStoryRaceGimmickType_name[_MainStoryRaceGimmickType_index[idx]:_MainStoryRaceGimmickType_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]]
}
-29
View File
@@ -1,29 +0,0 @@
// Code generated by "stringer -type RaceDifficulty -trimprefix Difficulty"; 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[DifficultyEasy-1]
_ = x[DifficultyNormal-2]
_ = x[DifficultyHard-3]
_ = x[DifficultyVeryHard-4]
_ = x[DifficultyExtreme-5]
_ = x[difficultyMax-6]
}
const _RaceDifficulty_name = "EasyNormalHardVeryHardExtremedifficultyMax"
var _RaceDifficulty_index = [...]uint8{0, 4, 10, 14, 22, 29, 42}
func (i RaceDifficulty) String() string {
idx := int(i) - 1
if i < 1 || idx >= len(_RaceDifficulty_index)-1 {
return "RaceDifficulty(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _RaceDifficulty_name[_RaceDifficulty_index[idx]:_RaceDifficulty_index[idx+1]]
}
-29
View File
@@ -1,29 +0,0 @@
// Code generated by "stringer -type RaceTime -trimprefix Time"; 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[TimeMin-0]
_ = x[TimeMorning-1]
_ = x[TimeDaytime-2]
_ = x[TimeEvening-3]
_ = x[TimeNight-4]
_ = x[TimeMax-5]
}
const _RaceTime_name = "MinMorningDaytimeEveningNightMax"
var _RaceTime_index = [...]uint8{0, 3, 10, 17, 24, 29, 32}
func (i RaceTime) String() string {
idx := int(i) - 0
if i < 0 || idx >= len(_RaceTime_index)-1 {
return "RaceTime(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _RaceTime_name[_RaceTime_index[idx]:_RaceTime_index[idx+1]]
}
-48
View File
@@ -1,48 +0,0 @@
// Code generated by "stringer -type RaceType -linecomment -trimprefix RaceType"; 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[RaceTypeNone-0]
_ = x[RaceTypePvP-1]
_ = x[RaceTypeTutorial-2]
_ = x[RaceTypeStory-3]
_ = x[RaceTypeStoryCondition-4]
_ = x[RaceTypeChampions-5]
_ = x[RaceTypeSingle-6]
_ = x[RaceTypeSingleModeScenarioTeamRace-7]
_ = x[RaceTypeRoomMatch-8]
_ = x[RaceTypePractice-9]
_ = x[RaceTypeDaily-10]
_ = x[RaceTypeTeamBuilding-11]
_ = x[RaceTypeLegend-12]
_ = x[RaceTypeChallengeMatch-13]
_ = x[RaceTypeTeamStadium-14]
_ = x[RaceTypeHeroes-16]
_ = x[raceTypeMaxInclusive-16]
}
const (
_RaceType_name_0 = "NONEPvPTutorialStoryStoryConditionChampionsSingleSingleModeScenarioTeamRaceRoomMatchPracticeDailyTeamBuildingLegendChallengeMatchTeamStadium"
_RaceType_name_1 = "Heroes"
)
var (
_RaceType_index_0 = [...]uint8{0, 4, 7, 15, 20, 34, 43, 49, 75, 84, 92, 97, 109, 115, 129, 140}
)
func (i RaceType) String() string {
switch {
case 0 <= i && i <= 14:
return _RaceType_name_0[_RaceType_index_0[i]:_RaceType_index_0[i+1]]
case i == 16:
return _RaceType_name_1
default:
return "RaceType(" + strconv.FormatInt(int64(i), 10) + ")"
}
}
-29
View File
@@ -1,29 +0,0 @@
// Code generated by "stringer -type RaceWeather -trimprefix Weather"; 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[WeatherMin-0]
_ = x[WeatherSunny-1]
_ = x[WeatherCloudy-2]
_ = x[WeatherRainy-3]
_ = x[WeatherSnow-4]
_ = x[WeatherMax-5]
}
const _RaceWeather_name = "MinSunnyCloudyRainySnowMax"
var _RaceWeather_index = [...]uint8{0, 3, 8, 14, 19, 23, 26}
func (i RaceWeather) String() string {
idx := int(i) - 0
if i < 0 || idx >= len(_RaceWeather_index)-1 {
return "RaceWeather(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _RaceWeather_name[_RaceWeather_index[idx]:_RaceWeather_index[idx+1]]
}
File diff suppressed because it is too large Load Diff
-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))
}
}
@@ -1,27 +0,0 @@
// Code generated by "stringer -type ResultBoardConditionType -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[ResultBoardTurfNone-1]
_ = x[ResultBoardTurfDirt-2]
_ = x[ResultBoardDirtNone-3]
_ = x[ResultBoardDirtTurf-4]
}
const _ResultBoardConditionType_name = "Turf_NoneTurf_DirtDirt_NoneDirt_Turf"
var _ResultBoardConditionType_index = [...]uint8{0, 9, 18, 27, 36}
func (i ResultBoardConditionType) String() string {
idx := int(i) - 1
if i < 1 || idx >= len(_ResultBoardConditionType_index)-1 {
return "ResultBoardConditionType(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _ResultBoardConditionType_name[_ResultBoardConditionType_index[idx]:_ResultBoardConditionType_index[idx+1]]
}
-27
View File
@@ -1,27 +0,0 @@
// Code generated by "stringer -type Rotation -trimprefix Rotation"; 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[RotationRight-1]
_ = x[RotationLeft-2]
_ = x[RotationStraightRight-3]
_ = x[RotationStraightLeft-4]
}
const _Rotation_name = "RightLeftStraightRightStraightLeft"
var _Rotation_index = [...]uint8{0, 5, 9, 22, 34}
func (i Rotation) String() string {
idx := int(i) - 1
if i < 1 || idx >= len(_Rotation_index)-1 {
return "Rotation(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _Rotation_name[_Rotation_index[idx]:_Rotation_index[idx+1]]
}
-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]]
}
-30
View File
@@ -1,30 +0,0 @@
// Code generated by "stringer -type Season -trimprefix Season"; 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[SeasonMin-0]
_ = x[SeasonSpring-1]
_ = x[SeasonSummer-2]
_ = x[SeasonFall-3]
_ = x[SeasonWinter-4]
_ = x[SeasonCherryBlossom-5]
_ = x[SeasonMax-6]
}
const _Season_name = "MinSpringSummerFallWinterCherryBlossomMax"
var _Season_index = [...]uint8{0, 3, 9, 15, 19, 25, 38, 41}
func (i Season) String() string {
idx := int(i) - 0
if i < 0 || idx >= len(_Season_index)-1 {
return "Season(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _Season_name[_Season_index[idx]:_Season_index[idx+1]]
}
File diff suppressed because one or more lines are too long
-27
View File
@@ -1,27 +0,0 @@
// Code generated by "stringer -type TurfVisionType -trimprefix TurfVision"; 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[TurfVisionURA-1]
_ = x[TurfVisionNAU-2]
_ = x[TurfVisionStand-3]
_ = x[turfVisionMax-4]
}
const _TurfVisionType_name = "URANAUStandturfVisionMax"
var _TurfVisionType_index = [...]uint8{0, 3, 6, 11, 24}
func (i TurfVisionType) String() string {
idx := int(i) - 1
if i < 1 || idx >= len(_TurfVisionType_index)-1 {
return "TurfVisionType(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _TurfVisionType_name[_TurfVisionType_index[idx]:_TurfVisionType_index[idx+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 {
+38 -42
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];
}
-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));
}
+2 -2
View File
@@ -99,8 +99,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;
-4
View File
@@ -103,10 +103,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);
@@ -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