From 338a7327a02838db0bc90b4cd5c2734c21cee4c2 Mon Sep 17 00:00:00 2001 From: Davide Grilli Date: Thu, 17 Sep 2026 12:26:31 +0200 Subject: [PATCH] Resolve UNI family-table hardware (screws/nuts/washers) as components These appear in the .asm binary as a family-table instance name (e.g. "R6--_-_U6592"), not a separate file on disk - only the generic "uni6592.prt" is actually indexed. Extract just the "" content instead of the full instance name, in both the standalone script and the production scanner, so standard hardware stops being silently dropped as "not found in index". Co-Authored-By: Claude Sonnet 5 --- .../AssemblyComponentScannerTests.cs | 16 ++++++++++++ CadSearchGui/AssemblyComponentScanner.cs | 7 +++++- docs/formato-asm.md | 25 +++++++++++++++++++ scripts/ExtractCreoStrings.cs | 9 ++++++- 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/CadSearchGui.Tests/AssemblyComponentScannerTests.cs b/CadSearchGui.Tests/AssemblyComponentScannerTests.cs index 4d292ac..ba32bf1 100644 --- a/CadSearchGui.Tests/AssemblyComponentScannerTests.cs +++ b/CadSearchGui.Tests/AssemblyComponentScannerTests.cs @@ -67,6 +67,22 @@ public class AssemblyComponentScannerTests finally { File.Delete(percorso); } } + [Fact] + public void Estrae_il_codice_generico_da_istanze_di_family_table_UNI() + { + // Visto su 9244228576.asm: le viti normalizzate compaiono come istanza di family + // table "R12--_-_U6592", ma il file reale indicizzato è "uni6592.prt". + string percorso = ScriviAsmFinto( + "Componente ID 1 (R12--_-_U6592.PRT) x Componente ID 2 (R12--_-_U6592.PRT)"); + try + { + var codici = AssemblyComponentScanner.EstraiCodiciReferenziati(percorso); + Assert.Contains("UNI6592", codici); + Assert.DoesNotContain("R12--_-_U6592", codici); + } + finally { File.Delete(percorso); } + } + [Fact] public void File_inesistente_lancia_eccezione_IO() => Assert.Throws(() => diff --git a/CadSearchGui/AssemblyComponentScanner.cs b/CadSearchGui/AssemblyComponentScanner.cs index 696a7f5..793b30c 100644 --- a/CadSearchGui/AssemblyComponentScanner.cs +++ b/CadSearchGui/AssemblyComponentScanner.cs @@ -20,11 +20,16 @@ namespace CadSearchGui; /// Falso positivo noto ed escluso: gli ID interni di viste salvate, nel formato /// "ModelView#<numero>", hanno la stessa forma di un codice (8-12 cifre) e /// compaiono più volte come un riferimento vero. Vedi docs/formato-asm.md. +/// +/// Viti/dadi/rosette normalizzati UNI sono family table Creo: il nome che compare nel +/// binario (es. "R6--_-_U6592<UNI6592>") è la singola istanza, non un file separato +/// su disco - il file reale indicizzato è il generico "uni6592.prt.<versione>", quindi +/// va estratto solo il contenuto tra "<" e ">". Vedi docs/formato-asm.md. /// static class AssemblyComponentScanner { private static readonly Regex CodiceRegex = new( - @"(?)", RegexOptions.Compiled); private const int OccorrenzeMinime = 2; public static HashSet EstraiCodiciReferenziati(string percorsoAsm) diff --git a/docs/formato-asm.md b/docs/formato-asm.md index 8038d62..70cd7ae 100644 --- a/docs/formato-asm.md +++ b/docs/formato-asm.md @@ -70,6 +70,31 @@ riesce a discriminarlo in modo affidabile senza rischiare di scartare componenti veri con pattern simili altrove. Se ricompare, l'unica verifica sicura resta l'apertura manuale in Creo del sotto-assieme sospetto. +## Viti/dadi/rosette normalizzati (family table UNI) + +I componenti di minuteria standard (viti, dadi, rosette UNI) sono definiti in +Creo come **family table**: un file generico (es. `uni6592.prt`) con tante +righe/istanze quante sono le varianti dimensionali. Nel binario dell'assieme +compaiono così: + +``` +Componente ID 28755 (R6--_-_U6592.PRT) +``` + +`R6--_-_U6592` è il nome della singola istanza (riga della family table), **non +un file separato su disco** — sulla share esiste solo `uni6592.prt.` +(verificato in `Unificati/`). Cercare l'istanza intera nell'indice fallisce +sempre; va estratto solo il contenuto tra `<` e `>` (`UNI6592`), che coincide +col nome del file generico realmente indicizzato: + +``` +regex aggiuntiva: (?<=<)UNI\d+(?=>) +``` + +Implementata sia in [`scripts/ExtractCreoStrings.cs`](../scripts/ExtractCreoStrings.cs) sia in +[`AssemblyComponentScanner.cs`](../CadSearchGui/AssemblyComponentScanner.cs) (fase "Trova componenti +referenziati" dell'app). + ## Risoluzione ricorsiva dell'albero Un `.asm` referenzia solo i propri sotto-componenti diretti, non l'intero diff --git a/scripts/ExtractCreoStrings.cs b/scripts/ExtractCreoStrings.cs index e154380..db93aa9 100644 --- a/scripts/ExtractCreoStrings.cs +++ b/scripts/ExtractCreoStrings.cs @@ -22,7 +22,14 @@ string asmIniziale = args[0]; string dbPath = args.Length > 1 ? args[1] : "cad_index.db"; string outPath = args.Length > 2 ? args[2] : "BOM.txt"; -var codiceRegex = new Regex(@"(?.PRT)": "R12--_-_U6592" è +// il nome della singola istanza (riga della family table, non un file separato su disco), +// il file reale indicizzato è il generico "uni6592.prt." - va quindi estratto +// solo il contenuto tra "<" e ">". +var codiceRegex = new Regex( + @"(?)", + RegexOptions.Compiled); const int occorrenzeMinime = 2; HashSet EstraiCodiciReferenziati(string percorsoAsm)