horsegen: generate data per region

This commit is contained in:
2026-01-15 13:43:54 -05:00
parent 5b5e008b5e
commit d6fb4b6caf
16 changed files with 1287 additions and 2261 deletions

File diff suppressed because one or more lines are too long

264
go/global/character.go Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +1,9 @@
package horse package global
// Automatically generated with horsegen; DO NOT EDIT // Automatically generated with horsegen; DO NOT EDIT
//go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type SkillID -trimprefix Skill -linecomment import . "git.sunturtle.xyz/zephyr/horse/go"
const ( const (
SkillWarningShot SkillID = 10071 // Warning Shot! SkillWarningShot SkillID = 10071 // Warning Shot!
SkillXceleration SkillID = 10081 // Xceleration SkillXceleration SkillID = 10081 // Xceleration

View File

@@ -7,12 +7,13 @@ import (
"sync" "sync"
"testing" "testing"
"git.sunturtle.xyz/zephyr/horse" horse "git.sunturtle.xyz/zephyr/horse/go"
"git.sunturtle.xyz/zephyr/horse/go/global"
) )
var SortedSkills = sync.OnceValue(func() []horse.Skill { var SortedSkills = sync.OnceValue(func() []horse.Skill {
skills := make([]horse.Skill, 0, len(horse.AllSkills)) skills := make([]horse.Skill, 0, len(global.AllSkills))
for _, v := range horse.AllSkills { for _, v := range global.AllSkills {
skills = append(skills, v) skills = append(skills, v)
} }
slices.SortFunc(skills, func(a, b horse.Skill) int { return cmp.Compare(a.ID, b.ID) }) slices.SortFunc(skills, func(a, b horse.Skill) int { return cmp.Compare(a.ID, b.ID) })
@@ -22,9 +23,6 @@ var SortedSkills = sync.OnceValue(func() []horse.Skill {
func TestSkillStrings(t *testing.T) { func TestSkillStrings(t *testing.T) {
t.Parallel() t.Parallel()
for _, s := range SortedSkills() { for _, s := range SortedSkills() {
if n := s.ID.String(); strings.HasPrefix(n, "SkillID(") {
t.Error(n)
}
// We could check that s.ID.String() matches s.Name, // We could check that s.ID.String() matches s.Name,
// but that may be awkward for inherited skills. // but that may be awkward for inherited skills.
for _, a := range s.Activations { for _, a := range s.Activations {

View File

@@ -1,6 +1,6 @@
module horse/character module horse/global/character
// Automatically generated with the horsegen tool; DO NOT EDIT // Automatically generated with horsegen; DO NOT EDIT
import std/core/vector import std/core/vector
import std/core-extras import std/core-extras

View File

@@ -1,4 +1,4 @@
module horse/skill-group module horse/global/skill-group
// Automatically generated with horsegen; DO NOT EDIT // Automatically generated with horsegen; DO NOT EDIT

View File

@@ -1,4 +1,6 @@
module horse/skill module horse/global/skill
// Automatically generated with horsegen; DO NOT EDIT
import std/num/decimal import std/num/decimal
pub import horse/skill-group pub import horse/skill-group

View File

@@ -1,5 +1,5 @@
{{ define "go-character" -}} {{ define "go-character" -}}
package horse package {{ $.Region }}
// Automatically generated with horsegen; DO NOT EDIT // Automatically generated with horsegen; DO NOT EDIT

View File

@@ -1,7 +1,7 @@
{{ define "koka-character" -}} {{ define "koka-character" -}}
module horse/character module horse/{{ $.Region }}/character
// Automatically generated with the horsegen tool; DO NOT EDIT // Automatically generated with horsegen; DO NOT EDIT
import std/core/vector import std/core/vector
import std/core-extras import std/core-extras

View File

@@ -26,7 +26,7 @@ func LoadTemplates() (*template.Template, error) {
// ExecCharacter renders the Koka character module to kk and the Go character file to g. // ExecCharacter renders the Koka character module to kk and the Go character file to g.
// If either is nil, it is skipped. // If either is nil, it is skipped.
func ExecCharacter(t *template.Template, kk, g io.Writer, c []NamedID[Character], pairs, trios []AffinityRelation) error { func ExecCharacter(t *template.Template, region string, kk, g io.Writer, c []NamedID[Character], pairs, trios []AffinityRelation) error {
if len(pairs) != len(c)*len(c) { if len(pairs) != len(c)*len(c) {
return fmt.Errorf("there are %d pairs but there must be %d for %d characters", len(pairs), len(c)*len(c), len(c)) return fmt.Errorf("there are %d pairs but there must be %d for %d characters", len(pairs), len(c)*len(c), len(c))
} }
@@ -53,6 +53,7 @@ func ExecCharacter(t *template.Template, kk, g io.Writer, c []NamedID[Character]
} }
data := struct { data := struct {
Region string
Characters []NamedID[Character] Characters []NamedID[Character]
Pairs []AffinityRelation Pairs []AffinityRelation
Trios []AffinityRelation Trios []AffinityRelation
@@ -60,7 +61,7 @@ func ExecCharacter(t *template.Template, kk, g io.Writer, c []NamedID[Character]
TrioMaps map[int]map[int]map[int]int TrioMaps map[int]map[int]map[int]int
Count int Count int
MaxID int MaxID int
}{c, pairs, trios, pm, tm, len(c), maxid} }{region, c, pairs, trios, pm, tm, len(c), maxid}
var err error var err error
if kk != nil { if kk != nil {
err = errors.Join(t.ExecuteTemplate(kk, "koka-character", &data)) err = errors.Join(t.ExecuteTemplate(kk, "koka-character", &data))
@@ -71,7 +72,7 @@ func ExecCharacter(t *template.Template, kk, g io.Writer, c []NamedID[Character]
return err return err
} }
func ExecSkill(t *template.Template, kk, g io.Writer, groups []NamedID[SkillGroup], skills []Skill) error { func ExecSkill(t *template.Template, region string, kk, g io.Writer, groups []NamedID[SkillGroup], skills []Skill) error {
m := make(map[int][]Skill, len(groups)) m := make(map[int][]Skill, len(groups))
u := make(map[int]int, len(groups)) u := make(map[int]int, len(groups))
for _, t := range skills { for _, t := range skills {
@@ -88,10 +89,11 @@ func ExecSkill(t *template.Template, kk, g io.Writer, groups []NamedID[SkillGrou
} }
} }
data := struct { data := struct {
Region string
Groups []NamedID[SkillGroup] Groups []NamedID[SkillGroup]
Skills []Skill Skills []Skill
Related map[int][]Skill Related map[int][]Skill
}{groups, skills, m} }{region, groups, skills, m}
var err error var err error
if kk != nil { if kk != nil {
err = errors.Join(t.ExecuteTemplate(kk, "koka-skill", &data)) err = errors.Join(t.ExecuteTemplate(kk, "koka-skill", &data))
@@ -102,11 +104,12 @@ func ExecSkill(t *template.Template, kk, g io.Writer, groups []NamedID[SkillGrou
return err return err
} }
func ExecSkillGroupKK(t *template.Template, w io.Writer, g []NamedID[SkillGroup], s []Skill) error { func ExecSkillGroupKK(t *template.Template, region string, w io.Writer, g []NamedID[SkillGroup], s []Skill) error {
data := struct { data := struct {
Region string
Groups []NamedID[SkillGroup] Groups []NamedID[SkillGroup]
Skills []Skill Skills []Skill
}{g, s} }{region, g, s}
return t.ExecuteTemplate(w, "koka-skill-group", &data) return t.ExecuteTemplate(w, "koka-skill-group", &data)
} }

View File

@@ -16,11 +16,12 @@ import (
func main() { func main() {
var ( var (
mdb string mdb string
kkOut, goOut string out string
region string
) )
flag.StringVar(&mdb, "mdb", os.ExpandEnv(`$USERPROFILE\AppData\LocalLow\Cygames\Umamusume\master\master.mdb`), "`path` to Umamusume master.mdb") flag.StringVar(&mdb, "mdb", os.ExpandEnv(`$USERPROFILE\AppData\LocalLow\Cygames\Umamusume\master\master.mdb`), "`path` to Umamusume master.mdb")
flag.StringVar(&kkOut, "kk", `.\horse`, "existing `dir`ectory for output Koka files") flag.StringVar(&out, "o", `.`, "root `dir`ectory for output files")
flag.StringVar(&goOut, "go", `.`, "existing `dir`ectory for output Go files") flag.StringVar(&region, "region", "global", "region the database is for (global, jp)")
flag.Parse() flag.Parse()
pctx, stop := signal.NotifyContext(context.Background(), os.Interrupt) pctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
@@ -85,35 +86,44 @@ func main() {
os.Exit(1) os.Exit(1)
} }
if err := os.MkdirAll(filepath.Join(out, "horse", region), 0775); err != nil {
slog.Error("create koka output dir", slog.Any("err", err))
os.Exit(1)
}
if err := os.MkdirAll(filepath.Join(out, "go", region), 0775); err != nil {
slog.Error("create go output dir", slog.Any("err", err))
os.Exit(1)
}
eg, ctx = errgroup.WithContext(pctx) eg, ctx = errgroup.WithContext(pctx)
eg.Go(func() error { eg.Go(func() error {
cf, err := os.Create(filepath.Join(kkOut, "character.kk")) cf, err := os.Create(filepath.Join(out, "horse", region, "character.kk"))
if err != nil { if err != nil {
return err return err
} }
gf, err := os.Create(filepath.Join(goOut, "character.go")) gf, err := os.Create(filepath.Join(out, "go", region, "character.go"))
if err != nil { if err != nil {
return err return err
} }
slog.Info("write characters") slog.Info("write characters")
return ExecCharacter(t, cf, gf, charas, pairs, trios) return ExecCharacter(t, region, cf, gf, charas, pairs, trios)
}) })
eg.Go(func() error { eg.Go(func() error {
sf, err := os.Create(filepath.Join(kkOut, "skill.kk")) sf, err := os.Create(filepath.Join(out, "horse", region, "skill.kk"))
if err != nil { if err != nil {
return err return err
} }
gf, err := os.Create(filepath.Join(goOut, "skill_data.go")) gf, err := os.Create(filepath.Join(out, "go", region, "skill.go"))
slog.Info("write skills") slog.Info("write skills")
return ExecSkill(t, sf, gf, sg, skills) return ExecSkill(t, region, sf, gf, sg, skills)
}) })
eg.Go(func() error { eg.Go(func() error {
sf, err := os.Create(filepath.Join(kkOut, "skill-group.kk")) sf, err := os.Create(filepath.Join(out, "horse", region, "skill-group.kk"))
if err != nil { if err != nil {
return err return err
} }
slog.Info("write skill groups") slog.Info("write skill groups")
return ExecSkillGroupKK(t, sf, sg, skills) return ExecSkillGroupKK(t, region, sf, sg, skills)
}) })
if err := eg.Wait(); err != nil { if err := eg.Wait(); err != nil {
slog.Error("generate", slog.Any("err", err)) slog.Error("generate", slog.Any("err", err))

View File

@@ -1,9 +1,13 @@
{{- define "go-skill-data" -}} {{- define "go-skill-data" -}}
package horse package {{ $.Region }}
// Automatically generated with horsegen; DO NOT EDIT // Automatically generated with horsegen; DO NOT EDIT
import . "git.sunturtle.xyz/zephyr/horse/go"
{{/*
//go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type SkillID -trimprefix Skill -linecomment //go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type SkillID -trimprefix Skill -linecomment
*/ -}}
const ( const (
{{- range $s := $.Skills }} {{- range $s := $.Skills }}
Skill{{ goenum $s.Name }}{{ if ne $s.InheritID 0 }}Inherit{{ end }} SkillID = {{ $s.ID }} // {{ $s.Name }} Skill{{ goenum $s.Name }}{{ if ne $s.InheritID 0 }}Inherit{{ end }} SkillID = {{ $s.ID }} // {{ $s.Name }}

View File

@@ -1,5 +1,5 @@
{{- define "koka-skill-group" -}} {{- define "koka-skill-group" -}}
module horse/skill-group module horse/{{ $.Region }}/skill-group
// Automatically generated with horsegen; DO NOT EDIT // Automatically generated with horsegen; DO NOT EDIT
@@ -48,7 +48,9 @@ pub fun skill-group/(==)(a: skill-group, b: skill-group): bool
{{- end -}} {{- end -}}
{{- define "koka-skill" -}} {{- define "koka-skill" -}}
module horse/skill module horse/{{ $.Region }}/skill
// Automatically generated with horsegen; DO NOT EDIT
import std/num/decimal import std/num/decimal
pub import horse/skill-group pub import horse/skill-group

File diff suppressed because one or more lines are too long