Compare commits
4 Commits
d13bc45d67
...
96c6273419
| Author | SHA1 | Date | |
|---|---|---|---|
| 96c6273419 | |||
| 7d8c6ae82e | |||
| 024742c053 | |||
| cdcd4b9b7f |
@@ -163,7 +163,7 @@ pub fun character/from-id(id: int): maybe<character>
|
|||||||
_ -> Nothing
|
_ -> Nothing
|
||||||
|
|
||||||
// Get the ID for a character.
|
// Get the ID for a character.
|
||||||
pub fun character/id(c: character): int
|
pub fun character/character-id(c: character): int
|
||||||
match c
|
match c
|
||||||
Special-Week -> 1001
|
Special-Week -> 1001
|
||||||
Silence-Suzuka -> 1002
|
Silence-Suzuka -> 1002
|
||||||
@@ -465,7 +465,7 @@ pub fun character/(==)(a: character, b: character): bool
|
|||||||
(King-Halo, King-Halo) -> True
|
(King-Halo, King-Halo) -> True
|
||||||
_ -> False
|
_ -> False
|
||||||
|
|
||||||
inline fip fun character/index(^c: character): int
|
fip fun character/index(^c: character): int
|
||||||
match c
|
match c
|
||||||
Special-Week -> 0
|
Special-Week -> 0
|
||||||
Silence-Suzuka -> 1
|
Silence-Suzuka -> 1
|
||||||
|
|||||||
1025
horse/skill.kk
Normal file
1025
horse/skill.kk
Normal file
File diff suppressed because it is too large
Load Diff
@@ -29,7 +29,7 @@ pub fun character/from-id(id: int): maybe<character>
|
|||||||
_ -> Nothing
|
_ -> Nothing
|
||||||
|
|
||||||
// Get the ID for a character.
|
// Get the ID for a character.
|
||||||
pub fun character/id(c: character): int
|
pub fun character/character-id(c: character): int
|
||||||
match c
|
match c
|
||||||
{{- range $uma := $.Characters }}
|
{{- range $uma := $.Characters }}
|
||||||
{{ kkenum $uma.Name }} -> {{ $uma.ID }}
|
{{ kkenum $uma.Name }} -> {{ $uma.ID }}
|
||||||
@@ -61,7 +61,7 @@ pub fun character/(==)(a: character, b: character): bool
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
_ -> False
|
_ -> False
|
||||||
|
|
||||||
inline fip fun character/index(^c: character): int
|
fip fun character/index(^c: character): int
|
||||||
match c
|
match c
|
||||||
{{- range $uma := $.Characters }}
|
{{- range $uma := $.Characters }}
|
||||||
{{ kkenum $uma.Name }} -> {{ $uma.Index }}
|
{{ kkenum $uma.Name }} -> {{ $uma.Index }}
|
||||||
@@ -70,8 +70,20 @@ inline fip fun character/index(^c: character): int
|
|||||||
// Create the table of all pair affinities.
|
// Create the table of all pair affinities.
|
||||||
// The affinity is the value at a.index*count + b.index.
|
// The affinity is the value at a.index*count + b.index.
|
||||||
extern global/create-pair-table(): vector<int>
|
extern global/create-pair-table(): vector<int>
|
||||||
c inline "kk_intx_t arr[] = { {{- range $a := $.Characters }}{{ range $b := $.Characters }}{{ index $.PairMaps $a.ID $b.ID }},{{ end }}{{ end -}} };\nkk_vector_from_cintarray(arr, (kk_ssize_t){{ $.Count }}*(kk_ssize_t){{ $.Count }}, kk_context())"
|
c inline "kk_intx_t arr[] = {
|
||||||
js inline "[ {{- range $a := $.Characters }}{{ range $b := $.Characters }}{{ index $.PairMaps $a.ID $b.ID }},{{ end }}{{ end -}} ]"
|
{{- range $a := $.Characters }}
|
||||||
|
{{- range $b := $.Characters }}
|
||||||
|
{{- index $.PairMaps $a.ID $b.ID }},
|
||||||
|
{{- end }}
|
||||||
|
{{- end -}}
|
||||||
|
};\nkk_vector_from_cintarray(arr, (kk_ssize_t){{ $.Count }} * (kk_ssize_t){{ $.Count }}, kk_context())"
|
||||||
|
js inline "[
|
||||||
|
{{- range $a := $.Characters }}
|
||||||
|
{{- range $b := $.Characters }}
|
||||||
|
{{- index $.PairMaps $a.ID $b.ID }},
|
||||||
|
{{- end }}
|
||||||
|
{{- end -}}
|
||||||
|
]"
|
||||||
val global/pair-table = global/create-pair-table()
|
val global/pair-table = global/create-pair-table()
|
||||||
|
|
||||||
// Base affinity between a pair using the global ruleset.
|
// Base affinity between a pair using the global ruleset.
|
||||||
@@ -81,8 +93,24 @@ pub fun global/pair-affinity(a: character, b: character): int
|
|||||||
// Create the table of all trio affinities.
|
// Create the table of all trio affinities.
|
||||||
// The affinity is the value at a.index*count*count + b.index*count + c.index.
|
// The affinity is the value at a.index*count*count + b.index*count + c.index.
|
||||||
extern global/create-trio-table(): vector<int>
|
extern global/create-trio-table(): vector<int>
|
||||||
c inline "kk_intx_t arr[] = { {{- range $a := $.Characters }}{{ range $b := $.Characters }}{{ range $c := $.Characters }}{{ index $.TrioMaps $a.ID $b.ID $c.ID }},{{ end }}{{ end }}{{ end -}} };\nkk_vector_from_cintarray(arr, (kk_ssize_t){{ $.Count }}*(kk_ssize_t){{ $.Count }}*(kk_ssize_t){{ $.Count }}, kk_context())"
|
c inline "kk_intx_t arr[] = {
|
||||||
js inline "[ {{- range $a := $.Characters }}{{ range $b := $.Characters }}{{ range $c := $.Characters }}{{ index $.TrioMaps $a.ID $b.ID $c.ID }},{{ end }}{{ end }}{{ end -}} ]"
|
{{- range $a := $.Characters }}
|
||||||
|
{{- range $b := $.Characters }}
|
||||||
|
{{- range $c := $.Characters }}
|
||||||
|
{{- index $.TrioMaps $a.ID $b.ID $c.ID }},
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end -}}
|
||||||
|
};\nkk_vector_from_cintarray(arr, (kk_ssize_t){{ $.Count }} * (kk_ssize_t){{ $.Count }} * (kk_ssize_t){{ $.Count }}, kk_context())"
|
||||||
|
js inline "[
|
||||||
|
{{- range $a := $.Characters }}
|
||||||
|
{{- range $b := $.Characters }}
|
||||||
|
{{- range $c := $.Characters }}
|
||||||
|
{{- index $.TrioMaps $a.ID $b.ID $c.ID }},
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end -}}
|
||||||
|
]"
|
||||||
val global/trio-table = global/create-trio-table()
|
val global/trio-table = global/create-trio-table()
|
||||||
|
|
||||||
// Base affinity for a trio using the global ruleset.
|
// Base affinity for a trio using the global ruleset.
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "embed"
|
"embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed character.kk.template
|
//go:embed character.kk.template skill.kk.template
|
||||||
var characterKK string
|
var templates embed.FS
|
||||||
|
|
||||||
// LoadTemplates sets up templates to render game data to source code.
|
// LoadTemplates sets up templates to render game data to source code.
|
||||||
func LoadTemplates() (*template.Template, error) {
|
func LoadTemplates() (*template.Template, error) {
|
||||||
@@ -17,15 +19,11 @@ func LoadTemplates() (*template.Template, error) {
|
|||||||
t.Funcs(template.FuncMap{
|
t.Funcs(template.FuncMap{
|
||||||
"kkenum": kkenum,
|
"kkenum": kkenum,
|
||||||
})
|
})
|
||||||
t, err := t.Parse(characterKK)
|
return t.ParseFS(templates, "*")
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("parsing characterKK: %w", err)
|
|
||||||
}
|
|
||||||
return t, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecCharacterKK renders the Koka character module to w.
|
// ExecCharacterKK renders the Koka character module to w.
|
||||||
func ExecCharacterKK(t *template.Template, w io.Writer, c []Character, pairs, trios []AffinityRelation) error {
|
func ExecCharacterKK(t *template.Template, w 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))
|
||||||
}
|
}
|
||||||
@@ -52,7 +50,7 @@ func ExecCharacterKK(t *template.Template, w io.Writer, c []Character, pairs, tr
|
|||||||
}
|
}
|
||||||
|
|
||||||
data := struct {
|
data := struct {
|
||||||
Characters []Character
|
Characters []NamedID[Character]
|
||||||
Pairs []AffinityRelation
|
Pairs []AffinityRelation
|
||||||
Trios []AffinityRelation
|
Trios []AffinityRelation
|
||||||
PairMaps map[int]map[int]int
|
PairMaps map[int]map[int]int
|
||||||
@@ -63,8 +61,56 @@ func ExecCharacterKK(t *template.Template, w io.Writer, c []Character, pairs, tr
|
|||||||
return t.ExecuteTemplate(w, "koka-character", &data)
|
return t.ExecuteTemplate(w, "koka-character", &data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExecSkillKK(t *template.Template, w io.Writer, g []NamedID[SkillGroup]) error {
|
||||||
|
data := struct {
|
||||||
|
Groups []NamedID[SkillGroup]
|
||||||
|
}{g}
|
||||||
|
return t.ExecuteTemplate(w, "koka-skill", &data)
|
||||||
|
}
|
||||||
|
|
||||||
|
const replaceDash = " ,!?/+();#○◎☆♡'&=♪∀゚∴"
|
||||||
|
|
||||||
|
var (
|
||||||
|
kkReplace = func() *strings.Replacer {
|
||||||
|
r := []string{
|
||||||
|
"Triple 7s", "Triple-Sevens", // hard to replace with the right thing automatically
|
||||||
|
"1,500,000 CC", "Million-CC",
|
||||||
|
"1st", "First",
|
||||||
|
".", "",
|
||||||
|
"'s", "s",
|
||||||
|
"ó", "o",
|
||||||
|
"∞", "Infinity",
|
||||||
|
}
|
||||||
|
for _, c := range replaceDash {
|
||||||
|
r = append(r, string(c), "-")
|
||||||
|
}
|
||||||
|
return strings.NewReplacer(r...)
|
||||||
|
}()
|
||||||
|
kkMultidash = regexp.MustCompile(`-+`)
|
||||||
|
kkDashNonletter = regexp.MustCompile(`-[^A-Za-z]`)
|
||||||
|
)
|
||||||
|
|
||||||
func kkenum(name string) string {
|
func kkenum(name string) string {
|
||||||
name = strings.ReplaceAll(name, ".", "")
|
orig := name
|
||||||
name = strings.ReplaceAll(name, " ", "-")
|
name = kkReplace.Replace(name)
|
||||||
|
name = kkMultidash.ReplaceAllLiteralString(name, "-")
|
||||||
|
name = strings.Trim(name, "-")
|
||||||
|
if len(name) == 0 {
|
||||||
|
panic(fmt.Errorf("%q became empty as Koka enum variant", orig))
|
||||||
|
}
|
||||||
|
name = strings.ToUpper(name[:1]) + name[1:]
|
||||||
|
if !unicode.IsLetter(rune(name[0])) {
|
||||||
|
panic(fmt.Errorf("Koka enum variant %q (from %q) starts with a non-letter", name, orig))
|
||||||
|
}
|
||||||
|
for _, c := range name {
|
||||||
|
if c > 127 {
|
||||||
|
// Koka does not allow non-ASCII characters in source code.
|
||||||
|
// Don't proceed if we've missed one.
|
||||||
|
panic(fmt.Errorf("non-ASCII character %q (%[1]U) in Koka enum variant %q (from %q)", c, name, orig))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if kkDashNonletter.MatchString(name) {
|
||||||
|
panic(fmt.Errorf("non-letter character after a dash in Koka enum variant %q (from %q)", name, orig))
|
||||||
|
}
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,15 +17,26 @@ var characterAffinity2SQL string
|
|||||||
//go:embed character.affinity3.sql
|
//go:embed character.affinity3.sql
|
||||||
var characterAffinity3SQL string
|
var characterAffinity3SQL string
|
||||||
|
|
||||||
type Character struct {
|
//go:embed skill-group.sql
|
||||||
|
var skillGroupSQL string
|
||||||
|
|
||||||
|
type (
|
||||||
|
Character struct{}
|
||||||
|
SkillGroup struct{}
|
||||||
|
)
|
||||||
|
|
||||||
|
type NamedID[T any] struct {
|
||||||
|
// Disallow conversions between NamedID types.
|
||||||
|
_ [0]*T
|
||||||
|
|
||||||
ID int
|
ID int
|
||||||
Name string
|
Name string
|
||||||
// For internal use, the index of the character.
|
// For internal use, the index of the identity, when it's needed.
|
||||||
// We don't show this in public API, but it lets us use vectors for lookups.
|
// We don't show this in public API, but it lets us use vectors for lookups.
|
||||||
Index int
|
Index int
|
||||||
}
|
}
|
||||||
|
|
||||||
func Characters(ctx context.Context, db *sqlitex.Pool) ([]Character, error) {
|
func Characters(ctx context.Context, db *sqlitex.Pool) ([]NamedID[Character], error) {
|
||||||
conn, err := db.Take(ctx)
|
conn, err := db.Take(ctx)
|
||||||
defer db.Put(conn)
|
defer db.Put(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -37,7 +48,7 @@ func Characters(ctx context.Context, db *sqlitex.Pool) ([]Character, error) {
|
|||||||
}
|
}
|
||||||
defer stmt.Finalize()
|
defer stmt.Finalize()
|
||||||
|
|
||||||
var r []Character
|
var r []NamedID[Character]
|
||||||
for {
|
for {
|
||||||
ok, err := stmt.Step()
|
ok, err := stmt.Step()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -46,7 +57,7 @@ func Characters(ctx context.Context, db *sqlitex.Pool) ([]Character, error) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
c := Character{
|
c := NamedID[Character]{
|
||||||
ID: stmt.ColumnInt(0),
|
ID: stmt.ColumnInt(0),
|
||||||
Name: stmt.ColumnText(1),
|
Name: stmt.ColumnText(1),
|
||||||
Index: stmt.ColumnInt(2),
|
Index: stmt.ColumnInt(2),
|
||||||
@@ -133,3 +144,33 @@ func CharacterTrios(ctx context.Context, db *sqlitex.Pool) ([]AffinityRelation,
|
|||||||
}
|
}
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SkillGroups(ctx context.Context, db *sqlitex.Pool) ([]NamedID[SkillGroup], error) {
|
||||||
|
conn, err := db.Take(ctx)
|
||||||
|
defer db.Put(conn)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("couldn't get connection for skill groups: %w", err)
|
||||||
|
}
|
||||||
|
stmt, _, err := conn.PrepareTransient(skillGroupSQL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("couldn't prepare statement for skill groups: %w", err)
|
||||||
|
}
|
||||||
|
defer stmt.Finalize()
|
||||||
|
|
||||||
|
var r []NamedID[SkillGroup]
|
||||||
|
for {
|
||||||
|
ok, err := stmt.Step()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error stepping skill groups: %w", err)
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
g := NamedID[SkillGroup]{
|
||||||
|
ID: stmt.ColumnInt(0),
|
||||||
|
Name: stmt.ColumnText(1),
|
||||||
|
}
|
||||||
|
r = append(r, g)
|
||||||
|
}
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -29,38 +29,60 @@ func main() {
|
|||||||
|
|
||||||
t, err := LoadTemplates()
|
t, err := LoadTemplates()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "loading templates: %s\n", err)
|
slog.Error("loading templates", slog.Any("err", err))
|
||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slog.Info("open", slog.String("mdb", mdb))
|
||||||
db, err := sqlitex.NewPool(mdb, sqlitex.PoolOptions{Flags: sqlite.OpenReadOnly})
|
db, err := sqlitex.NewPool(mdb, sqlitex.PoolOptions{Flags: sqlite.OpenReadOnly})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
slog.Error("opening mdb", slog.String("mdb", mdb), slog.Any("err", err))
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slog.Info("get characters")
|
||||||
charas, err := Characters(ctx, db)
|
charas, err := Characters(ctx, db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
slog.Error("getting characters", slog.Any("err", err))
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
slog.Info("get pairs")
|
||||||
pairs, err := CharacterPairs(ctx, db)
|
pairs, err := CharacterPairs(ctx, db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
slog.Error("getting pairs", slog.Any("err", err))
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
slog.Info("get trios")
|
||||||
trios, err := CharacterTrios(ctx, db)
|
trios, err := CharacterTrios(ctx, db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
slog.Error("getting trios", slog.Any("err", err))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
slog.Info("get skill groups")
|
||||||
|
sg, err := SkillGroups(ctx, db)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("getting skill groups", slog.Any("err", err))
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
cf, err := os.Create(filepath.Join(out, "character.kk"))
|
cf, err := os.Create(filepath.Join(out, "character.kk"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
slog.Error("creating character.kk", slog.Any("err", err))
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
slog.Info("write characters")
|
||||||
if err := ExecCharacterKK(t, cf, charas, pairs, trios); err != nil {
|
if err := ExecCharacterKK(t, cf, charas, pairs, trios); err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
slog.Error("writing character.kk", slog.Any("err", err))
|
||||||
|
// continue on
|
||||||
|
}
|
||||||
|
sf, err := os.Create(filepath.Join(out, "skill.kk"))
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("creating skill.kk", slog.Any("err", err))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
slog.Info("write skills")
|
||||||
|
if err := ExecSkillKK(t, sf, sg); err != nil {
|
||||||
|
slog.Error("writing skill.kk", slog.Any("err", err))
|
||||||
// continue on
|
// continue on
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
14
horsegen/skill-group.sql
Normal file
14
horsegen/skill-group.sql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
WITH skill_names AS (
|
||||||
|
SELECT
|
||||||
|
"index" AS "id",
|
||||||
|
"text" AS "name"
|
||||||
|
FROM text_data
|
||||||
|
WHERE category = 47
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
group_id,
|
||||||
|
name
|
||||||
|
FROM skill_data d
|
||||||
|
JOIN skill_names n ON d.id = n.id
|
||||||
|
WHERE d.group_rate = 1
|
||||||
|
ORDER BY group_id
|
||||||
48
horsegen/skill.kk.template
Normal file
48
horsegen/skill.kk.template
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
{{ define "koka-skill" -}}
|
||||||
|
module horse/skill
|
||||||
|
|
||||||
|
// Automatically generated with the horsegen tool; DO NOT EDIT
|
||||||
|
|
||||||
|
// Skill groups.
|
||||||
|
// A skill group may contain white, circle, double-circle, gold, and purple skills
|
||||||
|
// for the same effect.
|
||||||
|
// Sparks that grant skills refer to a skill group.
|
||||||
|
pub type skill-group
|
||||||
|
{{- range $g := $.Groups }}
|
||||||
|
{{ kkenum $g.Name }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
// Map a skill group to its ID.
|
||||||
|
pub fip fun skill-group/group-id(^sg: skill-group): int
|
||||||
|
match sg
|
||||||
|
{{- range $g := $.Groups }}
|
||||||
|
{{ kkenum $g.Name }} -> {{ $g.ID }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
// Get the skill group for an ID.
|
||||||
|
pub fip(1) fun skill-group/from-id(^id: int): maybe<skill-group>
|
||||||
|
match id
|
||||||
|
{{- range $g := $.Groups }}
|
||||||
|
{{ $g.ID }} -> Just( {{- kkenum $g.Name -}} )
|
||||||
|
{{- end }}
|
||||||
|
_ -> Nothing
|
||||||
|
|
||||||
|
// Get names for skill groups.
|
||||||
|
// Skill group names are the name of the base skill in the group.
|
||||||
|
pub fun skill-group/show(sg: skill-group): string
|
||||||
|
match sg
|
||||||
|
{{- range $g := $.Groups }}
|
||||||
|
{{ kkenum $g.Name }} -> {{ printf "%q" $g.Name }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
// Compare two skill groups by ID order.
|
||||||
|
pub fip fun skill-group/order2(a: skill-group, b: skill-group): order2<skill-group>
|
||||||
|
match cmp(a.group-id, b.group-id)
|
||||||
|
Lt -> Lt2(a, b)
|
||||||
|
Eq -> Eq2(a)
|
||||||
|
Gt -> Gt2(a, b)
|
||||||
|
|
||||||
|
pub fun skill-group/(==)(a: skill-group, b: skill-group): bool
|
||||||
|
a.group-id == b.group-id
|
||||||
|
|
||||||
|
{{- end }}
|
||||||
Reference in New Issue
Block a user