Automated parts sorting

This commit is contained in:
2026-05-17 14:21:05 +02:00
parent d7704c5f68
commit 574349b929
7 changed files with 414 additions and 8 deletions
+126 -3
View File
@@ -212,11 +212,24 @@ func CreateDefaultPartRow(rowID int) map[string]any {
}
func CreateDefaultPartRowForColumns(rowID int, columns []string) map[string]any {
return createDefaultPartRowForDataset(rowID, "", columns, project.PartsRowsConfig{})
}
func createDefaultPartRowForDataset(rowID int, datasetName string, columns []string, cfg project.PartsRowsConfig) map[string]any {
row := map[string]any{
"id": rowID,
"COSTMODIFIER": "0",
"ACBONUS": "0.00",
}
for field, value := range cfg.RowDefaults {
if strings.TrimSpace(field) == "" {
continue
}
row[field] = value
}
if value, ok := configuredPartsRowsACBonusValue(rowID, datasetName, cfg); ok {
row["ACBONUS"] = value
}
for _, column := range columns {
if strings.HasPrefix(column, "HIDE") {
row[column] = "0"
@@ -236,12 +249,27 @@ func isUnsetPartValue(value any) bool {
}
func applyDiscoveredPartDefaults(row map[string]any, columns []string) {
applyDiscoveredPartDefaultsWithConfig(row, "", columns, project.PartsRowsConfig{})
}
func applyDiscoveredPartDefaultsWithConfig(row map[string]any, datasetName string, columns []string, cfg project.PartsRowsConfig) {
if isUnsetPartValue(row["COSTMODIFIER"]) {
row["COSTMODIFIER"] = "0"
}
for field, value := range cfg.RowDefaults {
if strings.TrimSpace(field) == "" {
continue
}
if isUnsetPartValue(row[field]) {
row[field] = value
}
}
if isUnsetPartValue(row["ACBONUS"]) {
row["ACBONUS"] = "0.00"
}
if value, ok := configuredPartsRowsACBonusValue(rowIDFromPartRow(row), datasetName, cfg); ok {
row["ACBONUS"] = value
}
for _, column := range columns {
if !strings.HasPrefix(column, "HIDE") {
continue
@@ -252,6 +280,11 @@ func applyDiscoveredPartDefaults(row map[string]any, columns []string) {
}
}
func rowIDFromPartRow(row map[string]any) int {
rowID, _ := row["id"].(int)
return rowID
}
func resolvePartsRoot(root string) (string, error) {
if strings.TrimSpace(root) == "" {
return "", nil
@@ -354,6 +387,10 @@ func loadPartOverrides(path string) ([]map[string]any, error) {
}
func applyPartOverrides(sourceDir string, collected []nativeCollectedDataset) ([]nativeCollectedDataset, error) {
return applyPartOverridesWithConfig(sourceDir, collected, project.PartsRowsConfig{})
}
func applyPartOverridesWithConfig(sourceDir string, collected []nativeCollectedDataset, cfg project.PartsRowsConfig) ([]nativeCollectedDataset, error) {
result := make([]nativeCollectedDataset, len(collected))
copy(result, collected)
for i, dataset := range result {
@@ -393,7 +430,7 @@ func applyPartOverrides(sourceDir string, collected []nativeCollectedDataset) ([
}
row, ok := rowByID[rowID]
if !ok {
row = CreateDefaultPartRowForColumns(rowID, dataset.Columns)
row = createDefaultPartRowForDataset(rowID, dataset.Dataset.Name, dataset.Columns, cfg)
rows = append(rows, row)
rowByID[rowID] = row
}
@@ -415,6 +452,88 @@ func applyPartOverrides(sourceDir string, collected []nativeCollectedDataset) ([
return result, nil
}
func normalizePartsRowsACBonus(collected []nativeCollectedDataset, cfg project.PartsRowsConfig) ([]nativeCollectedDataset, error) {
if !partsRowsACBonusConfigured(cfg) && len(cfg.RowDefaults) == 0 {
return collected, nil
}
result := make([]nativeCollectedDataset, len(collected))
copy(result, collected)
for i, dataset := range result {
if !strings.HasPrefix(dataset.Dataset.Name, "parts/") {
continue
}
rows := make([]map[string]any, len(dataset.Rows))
for index, row := range dataset.Rows {
cloned := cloneRowMap(row)
for field, value := range cfg.RowDefaults {
if strings.TrimSpace(field) == "" {
continue
}
if isUnsetPartValue(cloned[field]) {
cloned[field] = value
}
}
rowID, ok := cloned["id"].(int)
if ok {
if value, configured := configuredPartsRowsACBonusValue(rowID, dataset.Dataset.Name, cfg); configured {
cloned["ACBONUS"] = value
}
}
rows[index] = cloned
}
result[i].Rows = rows
}
return result, nil
}
func partsRowsACBonusConfigured(cfg project.PartsRowsConfig) bool {
if strings.TrimSpace(cfg.ACBonus.Default.Strategy) != "" {
return true
}
if len(cfg.ACBonus.Datasets) > 0 {
return true
}
for _, dataset := range cfg.Datasets {
if strings.TrimSpace(dataset.ACBonus.Strategy) != "" {
return true
}
}
return false
}
func configuredPartsRowsACBonusValue(rowID int, datasetName string, cfg project.PartsRowsConfig) (string, bool) {
policy, ok := partsRowsACBonusPolicyForDataset(datasetName, cfg)
if !ok {
return "", false
}
switch strings.TrimSpace(policy.Strategy) {
case "descending_row_id_sort_key":
format := strings.TrimSpace(policy.Format)
if format == "" {
format = "%.2f"
}
return fmt.Sprintf(format, float64(policy.MaxRowID-rowID)/float64(policy.Divisor)), true
case "fixed":
return policy.Value, true
default:
return "", false
}
}
func partsRowsACBonusPolicyForDataset(datasetName string, cfg project.PartsRowsConfig) (project.PartsRowsACBonusPolicy, bool) {
category := extractPartCategory(datasetName)
if policy, ok := cfg.ACBonus.Datasets[category]; ok && strings.TrimSpace(policy.Strategy) != "" {
return policy, true
}
if dataset, ok := cfg.Datasets[category]; ok && strings.TrimSpace(dataset.ACBonus.Strategy) != "" {
return dataset.ACBonus, true
}
if strings.TrimSpace(cfg.ACBonus.Default.Strategy) != "" {
return cfg.ACBonus.Default, true
}
return project.PartsRowsACBonusPolicy{}, false
}
func loadPartOverridesForCategory(sourceDir, category string) ([]map[string]any, error) {
overrides := []map[string]any{}
@@ -503,6 +622,10 @@ func normalizePartOverrideValue(value any) any {
// retain authored values unless they still use placeholder values, in which case
// discovery activates them with engine-visible defaults.
func augmentWithAutogeneratedParts(collected []nativeCollectedDataset, autogenerated map[string]map[int]struct{}) []nativeCollectedDataset {
return augmentWithAutogeneratedPartsWithConfig(collected, autogenerated, project.PartsRowsConfig{})
}
func augmentWithAutogeneratedPartsWithConfig(collected []nativeCollectedDataset, autogenerated map[string]map[int]struct{}, cfg project.PartsRowsConfig) []nativeCollectedDataset {
if len(autogenerated) == 0 {
return collected
}
@@ -538,11 +661,11 @@ func augmentWithAutogeneratedParts(collected []nativeCollectedDataset, autogener
for rowID := range ids {
if row, exists := existingRows[rowID]; exists {
applyDiscoveredPartDefaults(row, dataset.Columns)
applyDiscoveredPartDefaultsWithConfig(row, dataset.Dataset.Name, dataset.Columns, cfg)
continue
}
if _, exists := existingRows[rowID]; !exists {
newRow := CreateDefaultPartRowForColumns(rowID, dataset.Columns)
newRow := createDefaultPartRowForDataset(rowID, dataset.Dataset.Name, dataset.Columns, cfg)
newRows = append(newRows, newRow)
}
}