Add family_name and bracket-adjacent placement signals for .asm scanning
Two more real placement forms found by comparing against Creo BOM reports: - A sub-assembly can be referenced only through a "family_name\0<code>\0" metadata field instead of a textual "Componente ID" placement or the doubled-NUL pattern (case 9284202452 inside 9284208188_D400.asm, which contains 9284202452_C01/_C02/_C03 - previously dropped entirely, along with its three children). - A bare numeric code immediately followed by a family-table bracket (<code><GENERIC>, e.g. bearing instances like 2510060303<CUSCI_ACBB7>) is a real reference to that instance, even though only the generic file is indexed on disk. Previously the instance code silently vanished before ever reaching the DB lookup; now it survives placement filtering and ends up in the "scartati" (discarded) list instead, so it's traceable rather than invisible. docs/formato-asm.md documents both, bringing the total to four recognized placement forms. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a7e0df0247
commit
e7b5d85f6b
3 files changed
+61
-17
No files matched your search
@@ -36,12 +36,20 @@ namespace CadSearchGui;
|
|||||||
/// basta: può trattarsi del riferimento al nome di un altro assieme che lo contiene (non
|
/// basta: può trattarsi del riferimento al nome di un altro assieme che lo contiene (non
|
||||||
/// noto a priori, quindi non escludibile per confronto diretto come il proprio codice) o
|
/// noto a priori, quindi non escludibile per confronto diretto come il proprio codice) o
|
||||||
/// di un residuo di feature soppresse/superate (vedi docs/formato-asm.md). Per questi si
|
/// di un residuo di feature soppresse/superate (vedi docs/formato-asm.md). Per questi si
|
||||||
/// richiede anche un vero placement, in una delle due forme osservate nel binario:
|
/// richiede anche un vero placement, in una delle quattro forme osservate nel binario:
|
||||||
/// "Componente ID N (<codice>...)"/"Component id N (<codice>...)" (la stringa
|
/// "Componente ID N (<codice>...)"/"Component id N (<codice>...)" (la stringa
|
||||||
/// cambia con la localizzazione Creo del file), oppure il codice ripetuto due volte di
|
/// cambia con la localizzazione Creo del file); il codice ripetuto due volte di seguito
|
||||||
/// seguito separato da un singolo byte NUL ("<codice>\0<codice>\0", osservato per
|
/// separato da un singolo byte NUL ("<codice>\0<codice>\0", osservato per
|
||||||
/// componenti di family table non-UNI, es. cuscinetti "CUSCI_..."). Non si applica alle
|
/// componenti di family table non-UNI, es. cuscinetti "CUSCI_..."); il campo
|
||||||
/// varianti con suffisso o bracket UNI: in alcuni file il placement riporta solo il nome
|
/// "family_name\0<codice>\0" (osservato una sola volta per file, su un sotto-assieme
|
||||||
|
/// referenziato come family table generica invece che con un placement testuale esplicito);
|
||||||
|
/// oppure il codice seguito immediatamente da un bracket "<codice><GENERICO>" -
|
||||||
|
/// l'istanza di una family table non-UNI vista nel nome (es. "2510060303<CUSCI_ACBB7>",
|
||||||
|
/// un cuscinetto): il codice dell'istanza non è mai indicizzato a sé (solo il generico tra
|
||||||
|
/// "<" e ">" lo è), ma questo segnale lo fa comunque sopravvivere fino alla ricerca nel
|
||||||
|
/// DB invece di scomparire in silenzio come "nudo senza placement" - lì verrà comunque
|
||||||
|
/// scartato come "non in indice", ma in modo tracciabile. Non si applica alle varianti con
|
||||||
|
/// suffisso o bracket UNI: in alcuni file il placement riporta solo il nome
|
||||||
/// istanza/generico senza il dettaglio del suffisso o del bracket, che vive altrove nei
|
/// istanza/generico senza il dettaglio del suffisso o del bracket, che vive altrove nei
|
||||||
/// metadati - lì resta necessaria la sola euristica delle occorrenze ripetute.
|
/// metadati - lì resta necessaria la sola euristica delle occorrenze ripetute.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -74,7 +82,9 @@ static class AssemblyComponentScanner
|
|||||||
|
|
||||||
bool HaPlacement(string codice) =>
|
bool HaPlacement(string codice) =>
|
||||||
Regex.IsMatch(testo, $@"Component(?:e)? id \d+ \([^()]*{Regex.Escape(codice)}[^()]*\)", RegexOptions.IgnoreCase)
|
Regex.IsMatch(testo, $@"Component(?:e)? id \d+ \([^()]*{Regex.Escape(codice)}[^()]*\)", RegexOptions.IgnoreCase)
|
||||||
|| testo.Contains(codice + "\0" + codice + "\0");
|
|| testo.Contains(codice + "\0" + codice + "\0")
|
||||||
|
|| testo.Contains("family_name\0" + codice + "\0")
|
||||||
|
|| testo.Contains(codice + "<");
|
||||||
|
|
||||||
candidati.RemoveWhere(c => CodiceNudoRegex.IsMatch(c) && !HaPlacement(c));
|
candidati.RemoveWhere(c => CodiceNudoRegex.IsMatch(c) && !HaPlacement(c));
|
||||||
return candidati;
|
return candidati;
|
||||||
|
|||||||
+23
-4
@@ -73,7 +73,7 @@ non essendo un componente. A differenza del proprio codice, non è noto a
|
|||||||
priori: dipende da dove/come il file è stato aperto o da chi lo referenzia,
|
priori: dipende da dove/come il file è stato aperto o da chi lo referenzia,
|
||||||
quindi non si può escludere per confronto diretto come per il caso
|
quindi non si può escludere per confronto diretto come per il caso
|
||||||
precedente. La regola generale che discrimina questo caso: un componente
|
precedente. La regola generale che discrimina questo caso: un componente
|
||||||
vero compare **sempre** anche dentro un vero placement, in una delle due
|
vero compare **sempre** anche dentro un vero placement, in una delle quattro
|
||||||
forme osservate nel binario:
|
forme osservate nel binario:
|
||||||
|
|
||||||
- `Componente ID N (<codice>...)`/`Component id N (<codice>...)` (la stringa
|
- `Componente ID N (<codice>...)`/`Component id N (<codice>...)` (la stringa
|
||||||
@@ -82,13 +82,32 @@ forme osservate nel binario:
|
|||||||
- il codice ripetuto due volte di seguito separato da un singolo byte NUL,
|
- il codice ripetuto due volte di seguito separato da un singolo byte NUL,
|
||||||
`<codice>\0<codice>\0` (osservato per componenti di family table non-UNI,
|
`<codice>\0<codice>\0` (osservato per componenti di family table non-UNI,
|
||||||
es. cuscinetti `CUSCI_...` - vedi sotto; il placement testuale
|
es. cuscinetti `CUSCI_...` - vedi sotto; il placement testuale
|
||||||
"Componente ID" non li copre, ma questa coppia doppia sì).
|
"Componente ID" non li copre, ma questa coppia doppia sì);
|
||||||
|
- il campo `family_name\0<codice>\0` (con `name` e `family_name` uguali,
|
||||||
|
entrambi pari al codice). Osservato una sola volta per file, su un
|
||||||
|
sotto-assieme referenziato come family table generica invece che con un
|
||||||
|
placement testuale esplicito - caso `9284202452` dentro
|
||||||
|
`9284208188_D400.asm`: il sotto-assieme (che contiene a sua volta
|
||||||
|
`9284202452_C01/_C02/_C03`) non ha nessun `Componente ID (...)` né coppia
|
||||||
|
NUL, solo questo campo `family_name`. Verificato su 5 file diversi
|
||||||
|
(`9284208188_D400/D600/D610/D620/D630.asm`): l'unica occorrenza di
|
||||||
|
`family_name\0<codice>\0` in ciascuno corrisponde sempre a un componente
|
||||||
|
reale confermato dalla BOM Creo, mai al riferimento fantasma verso l'alto;
|
||||||
|
- il codice seguito immediatamente da un bracket, `<codice><GENERICO>`
|
||||||
|
(senza NUL né spazio in mezzo) - l'istanza di una family table non-UNI
|
||||||
|
(es. `2510060303<CUSCI_ACBB7>`, un cuscinetto, confermato aprendo l'assieme
|
||||||
|
in Creo: descrizione "CUSC.OBL.SFERE 2COR 17X40"). Il codice dell'istanza
|
||||||
|
non è mai indicizzato a sé sulla share (solo il generico tra `<` e `>` lo
|
||||||
|
è - stesso meccanismo di UNI, vedi sotto), quindi anche riconosciuto come
|
||||||
|
placement reale finisce comunque negli "scartati" alla ricerca nel DB - ma
|
||||||
|
in modo tracciabile, invece di sparire in silenzio prima ancora di essere
|
||||||
|
cercato.
|
||||||
|
|
||||||
Un riferimento incidentale al nome di un altro assieme, anche se ripetuto più
|
Un riferimento incidentale al nome di un altro assieme, anche se ripetuto più
|
||||||
volte, non compare mai in nessuna delle due forme. `scripts/ExtractCreoStrings.cs`
|
volte, non compare mai in nessuna delle quattro forme. `scripts/ExtractCreoStrings.cs`
|
||||||
e `AssemblyComponentScanner.cs` applicano questa regola ai codici "nudi" (senza
|
e `AssemblyComponentScanner.cs` applicano questa regola ai codici "nudi" (senza
|
||||||
suffisso `_...` e senza bracket family table - vedi sotto perché limitata a
|
suffisso `_...` e senza bracket family table - vedi sotto perché limitata a
|
||||||
questi): un codice ripetuto ma mai trovato dentro un placement/coppia NUL
|
questi): un codice ripetuto ma mai trovato dentro uno dei quattro segnali
|
||||||
viene scartato. Questo NON copre i casi fantasma/soppressi sotto, che hanno un
|
viene scartato. Questo NON copre i casi fantasma/soppressi sotto, che hanno un
|
||||||
placement sintatticamente identico a uno vero e restano quindi indistinguibili
|
placement sintatticamente identico a uno vero e restano quindi indistinguibili
|
||||||
a livello testuale.
|
a livello testuale.
|
||||||
|
|||||||
@@ -49,18 +49,28 @@ HashSet<string> EstraiCodiciReferenziati(string percorsoAsm)
|
|||||||
// riferimenti al proprio assieme padre (nome sessione/file) o a codici superati/
|
// riferimenti al proprio assieme padre (nome sessione/file) o a codici superati/
|
||||||
// rinominati (caso "fantasma", docs/formato-asm.md) ripetono comunque il codice più
|
// rinominati (caso "fantasma", docs/formato-asm.md) ripetono comunque il codice più
|
||||||
// volte pur non essendo mai un componente vero. Per questi si richiede un vero
|
// volte pur non essendo mai un componente vero. Per questi si richiede un vero
|
||||||
// placement, in una delle due forme osservate nel binario: "Componente ID N
|
// placement, in una delle quattro forme osservate nel binario: "Componente ID N
|
||||||
// (<codice>...)"/"Component id N (<codice>...)" (la stringa cambia con la
|
// (<codice>...)"/"Component id N (<codice>...)" (la stringa cambia con la
|
||||||
// localizzazione Creo del file), oppure il codice ripetuto due volte di seguito
|
// localizzazione Creo del file); il codice ripetuto due volte di seguito separato da
|
||||||
// separato da un singolo byte NUL ("<codice>\0<codice>\0", osservato per componenti di
|
// un singolo byte NUL ("<codice>\0<codice>\0", osservato per componenti di family
|
||||||
// family table non-UNI, es. cuscinetti "CUSCI_..."). Non si applica alle varianti con
|
// table non-UNI, es. cuscinetti "CUSCI_..."); il campo "family_name\0<codice>\0"
|
||||||
// suffisso "_..." né alle istanze family table UNI: in alcuni file il placement
|
// (osservato una sola volta per file, su un sotto-assieme referenziato come family
|
||||||
|
// table generica invece che con un placement testuale esplicito); oppure il codice
|
||||||
|
// seguito immediatamente da un bracket "<codice><GENERICO>" - l'istanza di una family
|
||||||
|
// table non-UNI vista nel nome (es. "2510060303<CUSCI_ACBB7>", un cuscinetto): il
|
||||||
|
// codice dell'istanza non è mai indicizzato a sé (solo il generico tra "<" e ">" lo è,
|
||||||
|
// vedi sotto), ma questo segnale lo fa comunque sopravvivere fino alla ricerca nel DB
|
||||||
|
// invece di scomparire in silenzio come "nudo senza placement" - lì verrà comunque
|
||||||
|
// scartato come "non in indice", ma in modo tracciabile. Non si applica alle varianti
|
||||||
|
// con suffisso "_..." né alle istanze family table UNI: in alcuni file il placement
|
||||||
// riporta solo il nome istanza/generico senza il dettaglio del suffisso o del bracket
|
// riporta solo il nome istanza/generico senza il dettaglio del suffisso o del bracket
|
||||||
// "<...>", che vive altrove nei metadati - lì l'occorrenza ripetuta resta l'unico
|
// "<...>", che vive altrove nei metadati - lì l'occorrenza ripetuta resta l'unico
|
||||||
// segnale disponibile.
|
// segnale disponibile.
|
||||||
bool HaPlacement(string codice) =>
|
bool HaPlacement(string codice) =>
|
||||||
Regex.IsMatch(testo, $@"Component(?:e)? id \d+ \([^()]*{Regex.Escape(codice)}[^()]*\)", RegexOptions.IgnoreCase)
|
Regex.IsMatch(testo, $@"Component(?:e)? id \d+ \([^()]*{Regex.Escape(codice)}[^()]*\)", RegexOptions.IgnoreCase)
|
||||||
|| testo.Contains(codice + "\0" + codice + "\0");
|
|| testo.Contains(codice + "\0" + codice + "\0")
|
||||||
|
|| testo.Contains("family_name\0" + codice + "\0")
|
||||||
|
|| testo.Contains(codice + "<");
|
||||||
|
|
||||||
candidati.RemoveWhere(c => Regex.IsMatch(c, @"^\d{8,12}[A-Za-z]{0,2}$") && !HaPlacement(c));
|
candidati.RemoveWhere(c => Regex.IsMatch(c, @"^\d{8,12}[A-Za-z]{0,2}$") && !HaPlacement(c));
|
||||||
return candidati;
|
return candidati;
|
||||||
@@ -84,8 +94,13 @@ Dictionary<string, List<(string Tipo, string Percorso)>> CercaComponenti(IReadOn
|
|||||||
|
|
||||||
using var command = connection.CreateCommand();
|
using var command = connection.CreateCommand();
|
||||||
var nomiParametri = codici.Select((_, i) => $"@c{i}").ToList();
|
var nomiParametri = codici.Select((_, i) => $"@c{i}").ToList();
|
||||||
|
// Lo stesso codice+tipo può esistere in più cartelle radice (duplicati/copie storiche
|
||||||
|
// sulla share, es. un generico family table ripetuto in 5 progetti scollegati): ordinato
|
||||||
|
// per data_modifica DESC, si tiene solo il più recente per codice+tipo (stessa regola di
|
||||||
|
// Form1.RisolviAlberoComponenti, vedi docs/formato-asm.md).
|
||||||
command.CommandText = "SELECT codice, tipo_file, percorso_completo FROM files_ultima_versione "
|
command.CommandText = "SELECT codice, tipo_file, percorso_completo FROM files_ultima_versione "
|
||||||
+ $"WHERE LOWER(codice) IN ({string.Join(",", nomiParametri)}) AND LOWER(tipo_file) IN ('prt', 'asm')";
|
+ $"WHERE LOWER(codice) IN ({string.Join(",", nomiParametri)}) AND LOWER(tipo_file) IN ('prt', 'asm') "
|
||||||
|
+ "ORDER BY codice, tipo_file, data_modifica DESC";
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var codice in codici)
|
foreach (var codice in codici)
|
||||||
command.Parameters.AddWithValue(nomiParametri[i++], codice.ToLowerInvariant());
|
command.Parameters.AddWithValue(nomiParametri[i++], codice.ToLowerInvariant());
|
||||||
|
|||||||
Reference in new issue
Block a user