Automatic spellknown/spellgain null-filling (#12)
Implemented on branches `feature/topdata-row-extensions` in both `toolkit` and `module`. **Scope Audited** - Toolkit native topdata collection/build path. - Project config/effective config validation. - Module `nwn-tool.yaml` topdata config and topdata README. **Changes Made** - Added `topdata.row_extensions` config with `repeat_last` support. - Added glob dataset matching and build-time row extension for plain native datasets in [native.go](/home/vicky/Projects/nwnee-shadowsoverwestgate/toolkit/internal/topdata/native.go:641). - Extension copies emitted columns from the highest authored `Level`, increments `Level`, and assigns sequential `id`s through target level. - Enabled rules for `classes/spellsgained/*` and `classes/spellsknown/*` to level 60 in [nwn-tool.yaml](/home/vicky/Projects/nwnee-shadowsoverwestgate/module/nwn-tool.yaml:90). - Updated toolkit/module docs. **Configuration / Compatibility** - New public config type: `TopDataRowExtensionConfig` in [project.go](/home/vicky/Projects/nwnee-shadowsoverwestgate/toolkit/internal/project/project.go:233). - Existing behavior is unchanged unless a repo opts into `topdata.row_extensions`. - Source JSON and lockfiles are not updated for generated extension rows. **Tests / Validation** - Added project config tests for loading and validation. - Added native topdata tests for extension behavior, glob application, preserving manually authored rows, unmatched datasets, and failure cases. - Ran: - `go test ./internal/project ./internal/topdata` - `go test ./internal/topdata -run TestBuildNativeKeepsGeneratedIDsStableAcrossRepeatedBuilds` - `/tmp/sow-toolkit-rowext config validate` in `module` - `/tmp/sow-toolkit-rowext validate-topdata` in `module` - `/tmp/sow-toolkit-rowext build-topdata --force`, then inspected generated rows: `cls_spgn_acolyte.2da` now reaches row `59` / level `60`. **Remaining Notes** - `validate-topdata` still reports the pre-existing portrait lock warnings for `cotbl/cotbl_` and `lantern/lantern_`. - `build-topdata --force` briefly rewrote three spellbook JSON files as a side effect; I reverted those, leaving only the intended YAML/docs changes in `module`. Reviewed-on: https://gitea.westgate.pw/ShadowsOverWestgate/sow-tools/pulls/12 Co-authored-by: vickydotbat <vickydotbat@tutamail.com> Co-committed-by: vickydotbat <vickydotbat@tutamail.com>
This commit is contained in:
@@ -220,6 +220,36 @@ topdata:
|
||||
}
|
||||
}
|
||||
|
||||
func TestEffectiveConfigIncludesTopDataRowExtensions(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
writeProjectFile(t, filepath.Join(root, ConfigFile), `
|
||||
module:
|
||||
name: Test Module
|
||||
resref: testmod
|
||||
topdata:
|
||||
source: topdata
|
||||
row_extensions:
|
||||
- dataset: classes/spellsgained/*
|
||||
mode: repeat_last
|
||||
level_column: Level
|
||||
target_level: 60
|
||||
`)
|
||||
|
||||
proj, err := Load(root)
|
||||
if err != nil {
|
||||
t.Fatalf("Load returned error: %v", err)
|
||||
}
|
||||
|
||||
rules := proj.EffectiveConfig().TopData.RowExtensions
|
||||
if len(rules) != 1 {
|
||||
t.Fatalf("expected one topdata row extension rule, got %#v", rules)
|
||||
}
|
||||
got := rules[0]
|
||||
if got.Dataset != "classes/spellsgained/*" || got.Mode != "repeat_last" || got.LevelColumn != "Level" || got.TargetLevel != 60 {
|
||||
t.Fatalf("unexpected topdata row extension rule: %#v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEffectiveConfigIncludesTopDataClassFeatInjections(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
writeProjectFile(t, filepath.Join(root, ConfigFile), `
|
||||
@@ -288,6 +318,11 @@ func TestValidateLayoutRejectsInvalidTopDataValueEncodings(t *testing.T) {
|
||||
{Mode: "first_null_row"},
|
||||
{Dataset: "classes", Mode: "first_null_row", MinimumRow: -1},
|
||||
},
|
||||
RowExtensions: []TopDataRowExtensionConfig{
|
||||
{Dataset: "classes/spellsgained/*", Mode: "repeat_last", LevelColumn: "Level", TargetLevel: 60},
|
||||
{Dataset: "classes/spellsgained/*", Mode: "repeat_last", LevelColumn: "Level", TargetLevel: 60},
|
||||
{Dataset: "", Mode: "unsupported", LevelColumn: "", TargetLevel: 0},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -311,6 +346,11 @@ func TestValidateLayoutRejectsInvalidTopDataValueEncodings(t *testing.T) {
|
||||
"topdata.row_generation[2].mode \"unsupported\" is not supported",
|
||||
"topdata.row_generation[3].dataset is required",
|
||||
"topdata.row_generation[4].minimum_row must be zero or greater",
|
||||
"topdata.row_extensions[1] duplicates an earlier dataset row extension rule",
|
||||
"topdata.row_extensions[2].dataset is required",
|
||||
"topdata.row_extensions[2].mode \"unsupported\" is not supported",
|
||||
"topdata.row_extensions[2].level_column is required",
|
||||
"topdata.row_extensions[2].target_level must be greater than zero",
|
||||
} {
|
||||
if !strings.Contains(text, want) {
|
||||
t.Fatalf("expected validation error %q, got %v", want, err)
|
||||
|
||||
Reference in New Issue
Block a user