feat(go-services): inventory-go search — name/material/set enrichment (exact)

enrichRows now applies the material-name prefix to name (material is already a
translated string in the DB), sets material_name + original_name, and resolves
item_set_name via the AttributeSetInfo enum (fallback "Set {id}").

Validated vs Python position-by-position: 0 mismatches across 60 armor + 60
jewelry rows for name, material_name, item_set_name, original_name, value,
object_class. Sample names match exactly (e.g. "Gold Alduressa Coat").

Remaining enrichment slices: object_class_name (gem context), spells/spell_names
(needs the spells enum map), slot_name (sophisticated), weapon damage/speed/mana,
rating gear-total fallbacks.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-06-24 12:02:17 +02:00
parent c04cfaf2c6
commit 50360f72c4

View file

@ -325,10 +325,7 @@ func (s *Server) handleSearchItems(w http.ResponseWriter, r *http.Request) {
return return
} }
items := make([]map[string]any, 0, len(rows)) items := s.enrichRows(rows)
for _, row := range row2items(rows) {
items = append(items, row)
}
writeJSON(w, http.StatusOK, map[string]any{ writeJSON(w, http.StatusOK, map[string]any{
"items": items, "items": items,
@ -340,13 +337,14 @@ func (s *Server) handleSearchItems(w http.ResponseWriter, r *http.Request) {
}) })
} }
// row2items applies the direct-column transforms (computed booleans, condition, // enrichRows applies the direct-column transforms (computed booleans, condition,
// timestamp formatting) and strips internal columns. Deep enrichment is a later // timestamp), the material-name prefix, and the item_set name, then strips
// slice. // internal columns. Deeper enrichment (spells, slot_name, weapon damage/mana,
func row2items(rows []map[string]any) []map[string]any { // rating fallbacks) is a later slice.
func (s *Server) enrichRows(rows []map[string]any) []map[string]any {
out := make([]map[string]any, 0, len(rows))
for _, row := range rows { for _, row := range rows {
cw := toInt64(row["current_wielded_location"]) row["is_equipped"] = toInt64(row["current_wielded_location"]) > 0
row["is_equipped"] = cw > 0
row["is_bonded"] = toInt64(row["bonded"]) > 0 row["is_bonded"] = toInt64(row["bonded"]) > 0
row["is_attuned"] = toInt64(row["attuned"]) > 0 row["is_attuned"] = toInt64(row["attuned"]) > 0
row["is_rare"] = toInt64(row["rare_id"]) > 0 row["is_rare"] = toInt64(row["rare_id"]) > 0
@ -359,9 +357,30 @@ func row2items(rows []map[string]any) []map[string]any {
if t, ok := row["last_updated"].(time.Time); ok { if t, ok := row["last_updated"].(time.Time); ok {
row["last_updated"] = pyISO(t) row["last_updated"] = pyISO(t)
} }
// material_name + material prefix on name (material is already a
// translated string in the DB; enrich_db_item:2371-2602).
if mat := toStr(row["material"]); mat != "" {
row["material_name"] = mat
if name := toStr(row["name"]); name != "" &&
!strings.HasPrefix(strings.ToLower(name), strings.ToLower(mat)) {
row["original_name"] = name
row["name"] = mat + " " + name
}
}
// item_set_name (enrich_db_item:2551-2562).
if iset := strings.TrimSpace(toStr(row["item_set"])); iset != "" {
if n, ok := s.attributeSets[iset]; ok {
row["item_set_name"] = n
} else {
row["item_set_name"] = "Set " + iset
}
}
delete(row, "db_item_id") delete(row, "db_item_id")
out = append(out, row)
} }
return rows return out
} }
// translateSetID mirrors translate_equipment_set_id (AttributeSetInfo lookup, // translateSetID mirrors translate_equipment_set_id (AttributeSetInfo lookup,