Files
prep-step/docs/architettura.md
T
davideandClaude Sonnet 5 6511d58b01 Parallelize raw/ copy and document overall architecture
CopiaFileTrovati now copies with Parallel.ForEach (degree 6) instead of
sequentially: the bottleneck is network latency to the share, not CPU,
so overlapping copies gives a large speedup (~5x in a synthetic
benchmark with simulated SMB latency, documented in
docs/copia-raw-parallela.md).

Also adds docs/architettura.md, a full architecture overview of every
source file, the wizard's 5 phases, dialogs, persistence and standalone
scripts.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 10:07:46 +02:00

9.1 KiB

Architettura di CadSearchGui

Panoramica di tutti i file sorgente e di come collaborano. Per il "come si usa" vedi il README.md in root; per il formato binario .asm vedi docs/formato-asm.md; per la parallelizzazione della copia in raw/ vedi docs/copia-raw-parallela.md.

Vista d'insieme

Un solo eseguibile WinForms (nessuna CLI, nessun processo esterno): indicizza i file CAD di una share di rete in un DB SQLite locale, poi guida l'utente in un wizard a 5 fasi che, a partire da una distinta base esportata dal gestionale, raccoglie in locale (raw/) tutti i file CAD dei componenti e dei loro sotto-assiemi, e verifica/raccoglie gli STEP corrispondenti (step_finali/).

Distinta (.xls/.xml)  →  CSV (componente;descrizione)  →  raw/ (CAD copiati dall'indice)
                                                              │
                                          scansione .asm ─────┘  (sotto-assiemi/parti mancanti)
                                                              │
                              step/ (esportati a mano da Creo) → step_finali/ (solo i codici distinta)

Entry point

  • Program.cs — Main() standard WinForms: Application.Run(new Form1()). Nessuna logica.

Finestra principale (wizard)

  • Form1.cs — tutta la UI è costruita in codice (BuildUi/BuildFase*), non con il designer visuale. È un wizard: _panelFasi[] contiene un Panel per fase, uno solo visibile alla volta (VaiAllaFase); si avanza con "Avanti" solo se AvantiConsentito ritorna vero per la fase corrente. Form1.Designer.cs contiene solo lo scheletro minimo generato dal template (InitializeComponent/Dispose), non è usato per costruire i controlli.

    Le 5 fasi e i metodi principali dietro ciascuna:

    # Fase Bottone → metodo Cosa fa
    1 Database "Aggiorna indice" → Indexer.ScanAsync Crea/aggiorna cad_index.db scansionando la share
    2 Importa Distinta Base selezione file → ImportaDistinta → DistintaBaseImporter.ConvertiInCsv Xls/Xml gestionale → CSV componente;descrizione, scritto nella root del repo (TrovaRadiceRepo)
    3 Crea cartella raw "Crea cartella raw" → CreaCartellaRaw TrovaPercorsiCad + CopiaFileTrovati (parallela) → raw/
    4 Trova componenti referenziati "Trova componenti referenziati" → TrovaPrtReferenziati → RisolviAlberoComponenti Legge i .asm in raw/ con AssemblyComponentScanner, risolve ricorsivamente sotto-assiemi/parti nell'indice, li copia anch'essi in raw/
    5 Verifica completezza e STEP "Verifica completezza assiemi" → VerificaCompletezzaAssiemi; "Crea cartella step_finali" → GeneraReportStep Completezza ricorsiva sui percorsi in indice; confronto con step/ → step_finali/. All'ingresso nella fase, AggiornaAnteprimaAsm mostra le icone trascinabili dei .asm della distinta già in raw/

    Stato condiviso tra le fasi (campi privati di Form1): _dbPath, _percorsoInputCorrente, _righeCorrenti (righe del CSV), _ultimaVerifica (cache percorsi CAD), _ultimaCartellaRaw.

    Altre responsabilità in Form1.cs:

    • TrovaPercorsiCad / CaricaCodiciNoti — query sul DB (files_ultima_versione), la seconda carica tutti i codici prt/asm noti in un colpo solo (usata sia per risolvere i componenti sia da AssemblyComponentScanner per validare i token generici).
    • CopiaFileTrovati — copia (in parallelo, grado 6) i file trovati in raw/, saltando silenziosamente quelli irraggiungibili (share offline/permessi).
    • PulisciRawEStep — svuota raw/, step/, step_finali/ (manutenzione, richiede conferma).
    • InizializzaDatabase / ScegliDatabase / TrovaRadiceRepo — localizzazione del DB e della root del repo (quest'ultima risalendo da AppContext.BaseDirectory fino alla cartella che contiene CLAUDE.md).

Indicizzazione

  • Indexer.cs — ScanAsync cammina tutte le cartelle di primo livello sotto la radice (scoperte dinamicamente, non un elenco fisso) con un walk manuale a stack (Walk, più veloce di EnumerateFiles(..., AllDirectories) su share con centinaia di migliaia di file), esclude le cartelle temp_*, estrae da ogni nome file il pattern Pro-E <codice>.<tipo>.<versione> (ParseFilename, regex), e fa un upsert incrementale riga per riga confrontando percorso_completo + dimensione + data modifica. Progresso riportato via IProgress<ScanProgress> (marshalato sul thread UI). Contiene anche lo schema SQL: tabella files e vista files_ultima_versione (ultima versione per codice+tipo_file via ROW_NUMBER() OVER (...), non self-join+GROUP BY per evitare tempi quasi quadratici su ~200k righe).

Scansione binaria dei .asm

  • AssemblyComponentScanner.cs — estrae euristicamente i codici componente referenziati dentro un .asm (formato per lo più binario, codici come stringhe ASCII leggibili al suo interno). Due strategie: codici numerici Pro-E riconosciuti da soli via regex (come nei nomi file), e nomi alfabetici di parti commerciali tokenizzati genericamente e validati contro l'elenco di codici noti del DB (altrimenti il rumore binario sarebbe ingestibile). Dettagli sul formato, l'euristica e i falsi positivi noti in docs/formato-asm.md.

Import distinta base

  • DistintaBaseImporter.cs — converte l'export del gestionale (SpreadsheetML XML con estensione .xls/.xml, oppure .xls/.xlsx binario vero, distinti dai primi byte del file) nelle sole colonne Componente/Descrizione, foglio "Distinta Base". Se il nome del file segue la convenzione DBP_<codice>_<timestamp>, aggiunge l'assieme generale come riga in più (il foglio elenca solo i componenti sotto l'assieme). Scrive il CSV nella cartella passata da Form1 (root del repo), non necessariamente accanto al file di input.

Finestre di dialogo (modali, mostrate a fine step)

  • ProgressForm.cs — durante l'aggiornamento indice: barra di progresso, conteggi nuovi/aggiornati/invariati/rimossi, tempo trascorso e stima del tempo rimanente (dal ritmo file/secondo rispetto al totale atteso, preso dal conteggio della scansione precedente salvato nel DB).
  • ProgressoComponentiForm.cs — dialog minimale (etichetta + barra) durante RisolviAlberoComponenti in fase 4.
  • PrtMancantiForm.cs — esito della risoluzione ricorsiva dell'albero componenti: PRT e sotto-assiemi trovati e copiati in raw/, più i codici referenziati che non corrispondono a nessun file indicizzato (possono essere disegni, componenti davvero mancanti, o falsi positivi della scansione .asm).
  • ReportCompletezzaForm.cs — per ogni assieme della distinta, se tutti i suoi componenti (ricorsivamente fino ai PRT) sono nell'indice (✓/✗/? per "non trovato").
  • ReportStepForm.cs — per ogni componente della distinta, EsitoStep: Creato (STEP trovato e copiato), StepMancante (CAD in indice ma STEP non esportato), ComponenteNonTrovato (nemmeno il CAD è in indice).

Persistenza

  • DB (cad_index.db, SQLite) — vedi tabella files/vista files_ultima_versione sopra. Percorso: cercato accanto all'eseguibile o nella working directory all'avvio; altrimenti selezionabile con "Apri DB...". Radice disco di scansione di default X:\ (Form1.RadiceDiscoDefault, hardcoded).
  • File su disco, tutti nella root del repo (non nella cartella dell'eseguibile): il CSV della distinta, raw/ (CAD dei componenti e sotto-componenti), step/ (STEP esportati a mano da Creo, input), step_finali/ (STEP dei soli codici della distinta, output).

Script standalone (scripts/)

C# file-based apps (.NET 10, dotnet run scripts/Nome.cs -- arg1 arg2, nessun .csproj, dipendenze extra con #:package Nome@versione in testa al file):

  • ExtractCreoStrings.cs — BOM di un .asm risolvendo ricorsivamente i sotto-assiemi contro cad_index.db (stessa logica di AssiemeCompleto in Form1, solo codici numerici Pro-E).
  • BomViaDb.cs — come sopra ma con la tokenizzazione generica validata contro il DB, per intercettare anche i nomi alfabetici delle parti commerciali.
  • Analyze.cs — dump del contesto testo/hex attorno a un pattern in un file binario, per investigare a mano nuovi falsi positivi prima di toccare la regex di AssemblyComponentScanner.
  • Query.cs — query SQL ad-hoc contro cad_index.db da riga di comando.

⚠️ Nota importante di sicurezza: se dotnet run viene lanciato dentro CadSearchGui/ (che contiene un .csproj di tipo WinExe), esegue l'app GUI vera invece dello script standalone e resta bloccato in attesa che una finestra si chiuda. Lanciare gli script da una cartella senza .csproj (es. la root del repo o scripts/ stessa).

Test

  • CadSearchGui.Tests/ (xUnit) — riferimento al progetto principale via ProjectReference
    • InternalsVisibleTo (in CadSearchGui.csproj), così i test chiamano direttamente Indexer.ParseFilename e AssemblyComponentScanner.EstraiCodiciReferenziati senza esporli come API pubblica. File: IndexerParseFilenameTests.cs, AssemblyComponentScannerTests.cs, DistintaBaseImporterTests.cs, CaseInsensitiveLookupIntegrationTests.cs.