topdata: stop hardcoding the skills dataset location
The skills dataset moved into a tree (skills/core, skills/specs, ...).
Resolve it data-driven instead of by name:
- The required-family check no longer pins skill focus families to
dataset "skills"; the family spec's child_source names the dataset.
- Affinity generation and display names use the skill_focus spec's
child_source dataset.
- Child slugs derive from the row key's own namespace (text after the
first colon) instead of assuming namespace == dataset path.
- The wiki loader accepts both layouts ("skills", then "skills/core").
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -2317,6 +2317,18 @@ func (c *featGeneratedContext) familyHasExistingRows(familyKey string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// skillsDatasetName returns the dataset the skill_focus family sources its
|
||||||
|
// children from. The skills dataset location is data-driven via that spec;
|
||||||
|
// "skills" is only the fallback when no spec is loaded.
|
||||||
|
func (c *featGeneratedContext) skillsDatasetName() string {
|
||||||
|
for key, spec := range c.familySpecs {
|
||||||
|
if normalizeKeyIdentity(key) == "skillfocus" && spec.ChildSource.Dataset != "" {
|
||||||
|
return spec.ChildSource.Dataset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "skills"
|
||||||
|
}
|
||||||
|
|
||||||
func (c *featGeneratedContext) datasetRows(name string) (map[string]map[string]any, error) {
|
func (c *featGeneratedContext) datasetRows(name string) (map[string]map[string]any, error) {
|
||||||
if rows, ok := c.rowsByDataset[name]; ok {
|
if rows, ok := c.rowsByDataset[name]; ok {
|
||||||
return rows, nil
|
return rows, nil
|
||||||
@@ -2555,7 +2567,10 @@ func buildFamilyExpansionGeneratedModule(path string, obj map[string]any, ctx *f
|
|||||||
if !include {
|
if !include {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
slug := strings.TrimPrefix(sourceKey, spec.ChildSource.Dataset+":")
|
slug := sourceKey
|
||||||
|
if idx := strings.Index(slug, ":"); idx >= 0 {
|
||||||
|
slug = slug[idx+1:]
|
||||||
|
}
|
||||||
featKey, rowID, hasID, err := ctx.resolveGeneratedFeatIdentity(spec, slug, row)
|
featKey, rowID, hasID, err := ctx.resolveGeneratedFeatIdentity(spec, slug, row)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("generated feat file %s: %w", path, err)
|
return nil, fmt.Errorf("generated feat file %s: %w", path, err)
|
||||||
@@ -2655,7 +2670,7 @@ func buildRacialtypesSkillAffinityModule(ctx *featGeneratedContext) (map[string]
|
|||||||
if len(grants) == 0 {
|
if len(grants) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
skillRows, err := ctx.datasetRows("skills")
|
skillRows, err := ctx.datasetRows(ctx.skillsDatasetName())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -2854,7 +2869,7 @@ func (c *featGeneratedContext) displayNameForGeneratedSource(dataset string, row
|
|||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
switch dataset {
|
switch dataset {
|
||||||
case "skills":
|
case c.skillsDatasetName():
|
||||||
return displayNameForSkill(row)
|
return displayNameForSkill(row)
|
||||||
case "baseitems":
|
case "baseitems":
|
||||||
return displayNameForBaseitem(row)
|
return displayNameForBaseitem(row)
|
||||||
|
|||||||
@@ -1867,8 +1867,10 @@ func validateGeneratedFeatFamilies(dataDir string, report *ValidationReport) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
required := []requiredFeatFamily{
|
required := []requiredFeatFamily{
|
||||||
{FamilyKey: "skillfocus", Dataset: "skills", Predicate: "accessible"},
|
// skill families: the source dataset is data-driven (family spec), only
|
||||||
{FamilyKey: "greaterskillfocus", Dataset: "skills", Predicate: "accessible"},
|
// the accessibility predicate is required
|
||||||
|
{FamilyKey: "skillfocus", Predicate: "accessible"},
|
||||||
|
{FamilyKey: "greaterskillfocus", Predicate: "accessible"},
|
||||||
{FamilyKey: "weaponfocus", Dataset: "baseitems", Column: "WeaponFocusFeat"},
|
{FamilyKey: "weaponfocus", Dataset: "baseitems", Column: "WeaponFocusFeat"},
|
||||||
{FamilyKey: "weaponspecialization", Dataset: "baseitems", Column: "WeaponSpecializationFeat"},
|
{FamilyKey: "weaponspecialization", Dataset: "baseitems", Column: "WeaponSpecializationFeat"},
|
||||||
{FamilyKey: "improvedcritical", Dataset: "baseitems", Column: "WeaponImprovedCriticalFeat"},
|
{FamilyKey: "improvedcritical", Dataset: "baseitems", Column: "WeaponImprovedCriticalFeat"},
|
||||||
@@ -1882,7 +1884,7 @@ func validateGeneratedFeatFamilies(dataDir string, report *ValidationReport) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if spec.ChildSource.Dataset != requirement.Dataset ||
|
if (requirement.Dataset != "" && spec.ChildSource.Dataset != requirement.Dataset) ||
|
||||||
spec.ChildSource.Column != requirement.Column ||
|
spec.ChildSource.Column != requirement.Column ||
|
||||||
spec.ChildSource.Predicate != requirement.Predicate {
|
spec.ChildSource.Predicate != requirement.Predicate {
|
||||||
report.Diagnostics = append(report.Diagnostics, Diagnostic{
|
report.Diagnostics = append(report.Diagnostics, Diagnostic{
|
||||||
@@ -2081,7 +2083,10 @@ func validateGeneratedFeatFamilyCompleteness(path string, spec familyExpansionSp
|
|||||||
}
|
}
|
||||||
if include {
|
if include {
|
||||||
if familyAllowlist {
|
if familyAllowlist {
|
||||||
slug := strings.TrimPrefix(sourceKey, spec.ChildSource.Dataset+":")
|
slug := sourceKey
|
||||||
|
if idx := strings.Index(slug, ":"); idx >= 0 {
|
||||||
|
slug = slug[idx+1:]
|
||||||
|
}
|
||||||
featKey, _, _, err := ctx.resolveGeneratedFeatIdentity(spec, slug, row)
|
featKey, _, _, err := ctx.resolveGeneratedFeatIdentity(spec, slug, row)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
report.Diagnostics = append(report.Diagnostics, Diagnostic{
|
report.Diagnostics = append(report.Diagnostics, Diagnostic{
|
||||||
|
|||||||
@@ -569,13 +569,15 @@ func loadWikiContext(dataDir, sourceDir string) (*wikiContext, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
loadBase := func(name string) (nativeCollectedDataset, bool, error) {
|
loadBase := func(names ...string) (nativeCollectedDataset, bool, error) {
|
||||||
|
for _, name := range names {
|
||||||
for _, dataset := range datasets {
|
for _, dataset := range datasets {
|
||||||
if dataset.Name == name {
|
if dataset.Name == name {
|
||||||
collected, err := collectNativeDataset(dataset)
|
collected, err := collectNativeDataset(dataset)
|
||||||
return collected, true, err
|
return collected, true, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return nativeCollectedDataset{}, false, nil
|
return nativeCollectedDataset{}, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -583,7 +585,7 @@ func loadWikiContext(dataDir, sourceDir string) (*wikiContext, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
skillDataset, skillOK, err := loadBase("skills")
|
skillDataset, skillOK, err := loadBase("skills", "skills/core")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user