Wiki Template-First Rendering (#9)
Reviewed-on: https://gitea.westgate.pw/ShadowsOverWestgate/sow-tools/pulls/9 Co-authored-by: vickydotbat <vickydotbat@tutamail.com> Co-committed-by: vickydotbat <vickydotbat@tutamail.com>
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
package topdata
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type wikiDataProvidersDocument struct {
|
||||
Providers map[string]wikiDataProviderDefinition `json:"providers" yaml:"providers"`
|
||||
}
|
||||
|
||||
type wikiDataProviderDefinition struct {
|
||||
Source string `json:"source" yaml:"source"`
|
||||
Levels string `json:"levels" yaml:"levels"`
|
||||
}
|
||||
|
||||
func loadWikiDataProviders(path string) (map[string]wikiDataProviderDefinition, error) {
|
||||
raw, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return map[string]wikiDataProviderDefinition{}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("read wiki data providers %s: %w", path, err)
|
||||
}
|
||||
var doc wikiDataProvidersDocument
|
||||
if err := yaml.Unmarshal(raw, &doc); err != nil {
|
||||
return nil, fmt.Errorf("parse wiki data providers %s: %w", path, err)
|
||||
}
|
||||
for name, def := range doc.Providers {
|
||||
if strings.TrimSpace(name) == "" {
|
||||
return nil, fmt.Errorf("wiki data providers %s: provider name must not be empty", path)
|
||||
}
|
||||
if strings.TrimSpace(def.Source) == "" {
|
||||
return nil, fmt.Errorf("wiki data providers %s: provider %s missing source", path, name)
|
||||
}
|
||||
switch strings.TrimSpace(def.Source) {
|
||||
case "class_progression", "class_feats", "class_summary", "race_feats", "race_name_forms":
|
||||
default:
|
||||
return nil, fmt.Errorf("wiki data providers %s: provider %s has unknown source %q", path, name, def.Source)
|
||||
}
|
||||
}
|
||||
if doc.Providers == nil {
|
||||
return map[string]wikiDataProviderDefinition{}, nil
|
||||
}
|
||||
return doc.Providers, nil
|
||||
}
|
||||
|
||||
func (ctx *wikiContext) wikiDataProviderRows(name string, page wikiTemplatePage) ([]map[string]any, error) {
|
||||
def, ok := ctx.wikiDataProviders[name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("missing wiki data provider %q in %s", name, ctx.wikiDataPath)
|
||||
}
|
||||
switch strings.TrimSpace(def.Source) {
|
||||
case "class_progression":
|
||||
if page.Category != "classes" {
|
||||
return nil, nil
|
||||
}
|
||||
return ctx.classProgressionRows(wikiTableDefinition{Rows: wikiTableRowsConfig{Levels: def.Levels}}, page.Row)
|
||||
case "class_feats":
|
||||
if page.Category != "classes" {
|
||||
return nil, nil
|
||||
}
|
||||
return ctx.classFeatRows(page.Row), nil
|
||||
case "class_summary":
|
||||
if page.Category != "classes" {
|
||||
return nil, nil
|
||||
}
|
||||
return ctx.classSummaryRows(page.Row), nil
|
||||
case "race_feats":
|
||||
if page.Category != "racialtypes" {
|
||||
return nil, nil
|
||||
}
|
||||
return ctx.raceFeatRows(page.Row), nil
|
||||
case "race_name_forms":
|
||||
if page.Category != "racialtypes" {
|
||||
return nil, nil
|
||||
}
|
||||
return ctx.raceNameFormRows(page.Row), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown wiki data provider source %q", def.Source)
|
||||
}
|
||||
}
|
||||
|
||||
func (ctx *wikiContext) raceFeatRows(raceRow map[string]any) []map[string]any {
|
||||
values := []any{}
|
||||
switch typed := fieldValue(raceRow, "FeatsTable").(type) {
|
||||
case []any:
|
||||
values = append(values, typed...)
|
||||
case []string:
|
||||
for _, value := range typed {
|
||||
values = append(values, value)
|
||||
}
|
||||
default:
|
||||
if table := ctx.tableForValue(typed, ctx.raceFeatTables); table != nil {
|
||||
for _, row := range table.Rows {
|
||||
values = append(values, fieldValue(row, "FeatIndex"))
|
||||
}
|
||||
}
|
||||
}
|
||||
rows := []map[string]any{}
|
||||
for _, value := range values {
|
||||
key := resolveReferenceKey(value, ctx.featIDToKey)
|
||||
if key == "" {
|
||||
key = resolveReferenceKey(value, nil)
|
||||
}
|
||||
if key == "" || !ctx.canReferenceWikiKey(key) {
|
||||
continue
|
||||
}
|
||||
rows = append(rows, map[string]any{
|
||||
"FeatKey": key,
|
||||
"FeatName": ctx.resolveFeatName(key),
|
||||
})
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
func (ctx *wikiContext) raceNameFormRows(raceRow map[string]any) []map[string]any {
|
||||
candidates := []struct {
|
||||
label string
|
||||
field string
|
||||
}{
|
||||
{"Plural", "NamePlural"},
|
||||
{"Converted Name", "ConverName"},
|
||||
{"Lower Name", "ConverNameLower"},
|
||||
}
|
||||
rows := []map[string]any{}
|
||||
for _, candidate := range candidates {
|
||||
if value := ctx.resolveTextValue(fieldValue(raceRow, candidate.field), nil); value != "" {
|
||||
rows = append(rows, map[string]any{"Label": candidate.label, "Value": value})
|
||||
}
|
||||
}
|
||||
return rows
|
||||
}
|
||||
Reference in New Issue
Block a user