Parts-Based Manifest Publishing

This commit is contained in:
2026-04-09 21:22:26 +02:00
parent 94ffcc5868
commit 8f0b8a5d66
8 changed files with 596 additions and 89 deletions
+59 -10
View File
@@ -9,6 +9,8 @@ import (
"slices"
"strconv"
"strings"
"gitea.westgate.pw/ShadowsOverWestgate/sow-tools/internal/project"
)
// supportedPartCategories defines the part types that should be auto-discovered
@@ -189,13 +191,25 @@ func DiscoverPartModels(assetsDir string, category string) (map[int]*DiscoveredP
return result, nil
}
// CreateDefaultPartRow creates a default row for a discovered part model
// CreateDefaultPartRow creates a default row for a discovered part model.
// Base defaults are COSTMODIFIER=0 and ACBONUS=0.00. Any robe HIDE* columns
// present in the dataset columns default to 0 as well.
func CreateDefaultPartRow(rowID int) map[string]any {
return map[string]any{
return CreateDefaultPartRowForColumns(rowID, nil)
}
func CreateDefaultPartRowForColumns(rowID int, columns []string) map[string]any {
row := map[string]any{
"id": rowID,
"COSTMODIFIER": "0",
"ACBONUS": "0.00",
}
for _, column := range columns {
if strings.HasPrefix(column, "HIDE") {
row[column] = "0"
}
}
return row
}
func isUnsetPartValue(value any) bool {
@@ -208,6 +222,23 @@ func isUnsetPartValue(value any) bool {
return false
}
func applyDiscoveredPartDefaults(row map[string]any, columns []string) {
if isUnsetPartValue(row["COSTMODIFIER"]) {
row["COSTMODIFIER"] = "0"
}
if isUnsetPartValue(row["ACBONUS"]) {
row["ACBONUS"] = "0.00"
}
for _, column := range columns {
if !strings.HasPrefix(column, "HIDE") {
continue
}
if isUnsetPartValue(row[column]) {
row[column] = "0"
}
}
}
func resolvePartsRoot(root string) (string, error) {
if strings.TrimSpace(root) == "" {
return "", nil
@@ -256,6 +287,29 @@ func scanAutogeneratedParts(assetsDir string) (map[string]map[int]struct{}, erro
return result, nil
}
func resolveAutogeneratedPartsInventory(p *project.Project, progress func(string)) (map[string]map[int]struct{}, error) {
overrideDir, err := resolvePartsAssetsOverrideDir(p)
if err != nil {
return nil, err
}
if overrideDir != "" {
if progress != nil {
progress(fmt.Sprintf("Scanning part models from local topdata.assets override %s...", overrideDir))
}
return scanAutogeneratedParts(overrideDir)
}
return resolveReleasedPartsManifest(p, progress)
}
func hasCollectedPartsDatasets(collected []nativeCollectedDataset) bool {
for _, dataset := range collected {
if isPartsDataset(dataset.Dataset.Name) {
return true
}
}
return false
}
func loadPartOverrides(path string) ([]map[string]any, error) {
if _, err := os.Stat(path); err != nil {
if os.IsNotExist(err) {
@@ -327,7 +381,7 @@ func applyPartOverrides(sourceDir string, collected []nativeCollectedDataset) ([
}
row, ok := rowByID[rowID]
if !ok {
row = CreateDefaultPartRow(rowID)
row = CreateDefaultPartRowForColumns(rowID, dataset.Columns)
rows = append(rows, row)
rowByID[rowID] = row
}
@@ -400,16 +454,11 @@ func augmentWithAutogeneratedParts(collected []nativeCollectedDataset, autogener
for rowID := range ids {
if row, exists := existingRows[rowID]; exists {
if isUnsetPartValue(row["COSTMODIFIER"]) {
row["COSTMODIFIER"] = "0"
}
if isUnsetPartValue(row["ACBONUS"]) {
row["ACBONUS"] = "0.00"
}
applyDiscoveredPartDefaults(row, dataset.Columns)
continue
}
if _, exists := existingRows[rowID]; !exists {
newRow := CreateDefaultPartRow(rowID)
newRow := CreateDefaultPartRowForColumns(rowID, dataset.Columns)
newRows = append(newRows, newRow)
}
}