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<UNI6592>"), not a separate file on disk - only the generic
"uni6592.prt" is actually indexed. Extract just the "<UNI...>" 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 <noreply@anthropic.com>
This commit is contained in:
davideandClaude Sonnet 5 committed 2026-09-17 12:26:31 +02:00
1 parent 52d126372d
commit 338a7327a0
4 files changed
+55 -2

No files matched your search

@@ -67,6 +67,22 @@ public class AssemblyComponentScannerTests
finally { File.Delete(percorso); } 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<UNI6592>", ma il file reale indicizzato è "uni6592.prt".
string percorso = ScriviAsmFinto(
"Componente ID 1 (R12--_-_U6592<UNI6592>.PRT) x Componente ID 2 (R12--_-_U6592<UNI6592>.PRT)");
try
{
var codici = AssemblyComponentScanner.EstraiCodiciReferenziati(percorso);
Assert.Contains("UNI6592", codici);
Assert.DoesNotContain("R12--_-_U6592<UNI6592>", codici);
}
finally { File.Delete(percorso); }
}
[Fact] [Fact]
public void File_inesistente_lancia_eccezione_IO() => public void File_inesistente_lancia_eccezione_IO() =>
Assert.Throws<DirectoryNotFoundException>(() => Assert.Throws<DirectoryNotFoundException>(() =>
+6 -1
View File
@@ -20,11 +20,16 @@ namespace CadSearchGui;
/// Falso positivo noto ed escluso: gli ID interni di viste salvate, nel formato /// Falso positivo noto ed escluso: gli ID interni di viste salvate, nel formato
/// "ModelView#&lt;numero&gt;", hanno la stessa forma di un codice (8-12 cifre) e /// "ModelView#&lt;numero&gt;", hanno la stessa forma di un codice (8-12 cifre) e
/// compaiono più volte come un riferimento vero. Vedi docs/formato-asm.md. /// 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&lt;UNI6592&gt;") è la singola istanza, non un file separato
/// su disco - il file reale indicizzato è il generico "uni6592.prt.&lt;versione&gt;", quindi
/// va estratto solo il contenuto tra "&lt;" e "&gt;". Vedi docs/formato-asm.md.
/// </summary> /// </summary>
static class AssemblyComponentScanner static class AssemblyComponentScanner
{ {
private static readonly Regex CodiceRegex = new( private static readonly Regex CodiceRegex = new(
@"(?<!ModelView#)\b\d{8,12}(?:_[A-Za-z]\d{2,4}|[A-Za-z]{0,2})\b", RegexOptions.Compiled); @"(?<!ModelView#)\b\d{8,12}(?:_[A-Za-z]\d{2,4}|[A-Za-z]{0,2})\b|(?<=<)UNI\d+(?=>)", RegexOptions.Compiled);
private const int OccorrenzeMinime = 2; private const int OccorrenzeMinime = 2;
public static HashSet<string> EstraiCodiciReferenziati(string percorsoAsm) public static HashSet<string> EstraiCodiciReferenziati(string percorsoAsm)
+25
View File
@@ -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 componenti veri con pattern simili altrove. Se ricompare, l'unica verifica
sicura resta l'apertura manuale in Creo del sotto-assieme sospetto. 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<UNI6592>.PRT)
```
`R6--_-_U6592` è il nome della singola istanza (riga della family table), **non
un file separato su disco** — sulla share esiste solo `uni6592.prt.<versione>`
(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 ## Risoluzione ricorsiva dell'albero
Un `.asm` referenzia solo i propri sotto-componenti diretti, non l'intero Un `.asm` referenzia solo i propri sotto-componenti diretti, non l'intero
+8 -1
View File
@@ -22,7 +22,14 @@ string asmIniziale = args[0];
string dbPath = args.Length > 1 ? args[1] : "cad_index.db"; string dbPath = args.Length > 1 ? args[1] : "cad_index.db";
string outPath = args.Length > 2 ? args[2] : "BOM.txt"; string outPath = args.Length > 2 ? args[2] : "BOM.txt";
var codiceRegex = new Regex(@"(?<!ModelView#)\b\d{8,12}(?:_[A-Za-z]\d{2,4}|[A-Za-z]{0,2})\b", RegexOptions.Compiled); // Seconda alternativa: viti/dadi/rosette normalizzati UNI, definiti come family table in
// Creo. Compaiono come "Componente ID N (R12--_-_U6592<UNI6592>.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.<versione>" - va quindi estratto
// solo il contenuto tra "<" e ">".
var codiceRegex = new Regex(
@"(?<!ModelView#)\b\d{8,12}(?:_[A-Za-z]\d{2,4}|[A-Za-z]{0,2})\b|(?<=<)UNI\d+(?=>)",
RegexOptions.Compiled);
const int occorrenzeMinime = 2; const int occorrenzeMinime = 2;
HashSet<string> EstraiCodiciReferenziati(string percorsoAsm) HashSet<string> EstraiCodiciReferenziati(string percorsoAsm)