- New app.ico (from the Cevolani favicon, background made transparent and cropped tighter to the logo so it stays legible at 16/24px), wired up via ApplicationIcon in the csproj and re-read at runtime for the window icon. - Named the product "Cevolani StepPrep" and set Version=0.1.0 in the csproj; shown in the window title. The CadSearchGui folder/namespace/csproj keep their technical name, only the product-facing name changed. - Updated CLAUDE.md, README.md and docs/architettura.md to reflect the product name/version, UiStile.cs, app.ico, and that this app is a pre-process step ahead of Creo Distributed Batch. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
10 KiB
Architettura di CadSearchGui (Cevolani StepPrep)
Panoramica di tutti i file sorgente e di come collaborano. CadSearchGui è il nome
tecnico del progetto; Cevolani StepPrep è il nome del programma per l'utente
finale (titolo finestra, icona, versione — vedi <Version>/<Product> in
CadSearchGui.csproj). 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 unPanelper fase, uno solo visibile alla volta (VaiAllaFase); si avanza con "Avanti" solo seAvantiConsentitoritorna vero per la fase corrente.Form1.Designer.cscontiene 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.ScanAsyncCrea/aggiorna cad_index.dbscansionando la share2 Importa Distinta Base selezione file → ImportaDistinta→DistintaBaseImporter.ConvertiInCsvXls/Xml gestionale → CSV componente;descrizione, scritto nella root del repo ( TrovaRadiceRepo)3 Crea cartella raw "Crea cartella raw" → CreaCartellaRawTrovaPercorsiCad+CopiaFileTrovati(parallela) →raw/4 Trova componenti referenziati "Trova componenti referenziati" → TrovaPrtReferenziati→RisolviAlberoComponentiLegge i .asminraw/conAssemblyComponentScanner, risolve ricorsivamente sotto-assiemi/parti nell'indice, li copia anch'essi inraw/5 Verifica completezza e STEP "Verifica completezza assiemi" → VerificaCompletezzaAssiemi; "Crea cartella step_finali" →GeneraReportStepCompletezza ricorsiva sui percorsi in indice; confronto con step/→step_finali/. All'ingresso nella fase,AggiornaAnteprimaAsmmostra le icone trascinabili dei.asmdella distinta già inraw/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 daAssemblyComponentScannerper validare i token generici).CopiaFileTrovati— copia (in parallelo, grado 6) i file trovati inraw/, saltando silenziosamente quelli irraggiungibili (share offline/permessi).PulisciRawEStep— svuotaraw/,step/,step_finali/(manutenzione, richiede conferma).InizializzaDatabase/ScegliDatabase/TrovaRadiceRepo— localizzazione del DB e della root del repo (quest'ultima risalendo daAppContext.BaseDirectoryfino alla cartella che contieneCLAUDE.md).
Indicizzazione
- Indexer.cs —
ScanAsynccammina tutte le cartelle di primo livello sotto la radice (scoperte dinamicamente, non un elenco fisso) con un walk manuale a stack (Walk, più veloce diEnumerateFiles(..., AllDirectories)su share con centinaia di migliaia di file), esclude le cartelletemp_*, estrae da ogni nome file il pattern Pro-E<codice>.<tipo>.<versione>(ParseFilename, regex), e fa un upsert incrementale riga per riga confrontandopercorso_completo+ dimensione + data modifica. Progresso riportato viaIProgress<ScanProgress>(marshalato sul thread UI). Contiene anche lo schema SQL: tabellafilese vistafiles_ultima_versione(ultima versione percodice+tipo_fileviaROW_NUMBER() OVER (...), non self-join+GROUP BYper 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 indocs/formato-asm.md.
Import distinta base
- DistintaBaseImporter.cs — converte l'export del gestionale (SpreadsheetML XML con
estensione
.xls/.xml, oppure.xls/.xlsxbinario vero, distinti dai primi byte del file) nelle sole colonne Componente/Descrizione, foglio"Distinta Base". Se il nome del file segue la convenzioneDBP_<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 daForm1(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
RisolviAlberoComponentiin fase 4.
Stile UI condiviso
- UiStile.cs —
Primario/Secondario: stile piatto per i bottoni (bordo sottile per i secondari, blu pieno per l'azione principale di ogni fase), entrambi conAutoSize+Padding+MinimumSizeinvece di unaSizefissa in pixel indovinata a mano (altrimenti il testo va a capo e si taglia in verticale se non ci sta nella larghezza scelta).Arrotondaapplica angoli arrotondati viaRegioncalcolata suSizeChanged(non una volta sola: conAutoSizela dimensione finale del bottone si conosce solo a layout avvenuto), usata sui bottoni "Avanti"/"Indietro" del wizard. - app.ico — icona dell'app, referenziata da
<ApplicationIcon>nel csproj (icona dell'exe in Esplora risorse/taskbar) e riletta esplicitamente inForm1.BuildUi()conIcon.ExtractAssociatedIcon(Application.ExecutablePath)per la titlebar, senza copiare il file.iconell'output. Sfondo trasparente (nessuna card bianca), 7 risoluzioni da 16 a 256px. - 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 tabellafiles/vistafiles_ultima_versionesopra. Percorso: cercato accanto all'eseguibile o nella working directory all'avvio; altrimenti selezionabile con "Apri DB...". Radice disco di scansione di defaultX:\(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
.asmrisolvendo ricorsivamente i sotto-assiemi controcad_index.db(stessa logica diAssiemeCompletoin 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.dbda riga di comando.
⚠️ Nota importante di sicurezza: se
dotnet runviene lanciato dentroCadSearchGui/(che contiene un.csprojdi tipoWinExe), 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 oscripts/stessa).
Test
- CadSearchGui.Tests/ (xUnit) — riferimento al progetto principale via
ProjectReferenceInternalsVisibleTo(inCadSearchGui.csproj), così i test chiamano direttamenteIndexer.ParseFilenameeAssemblyComponentScanner.EstraiCodiciReferenziatisenza esporli come API pubblica. File:IndexerParseFilenameTests.cs,AssemblyComponentScannerTests.cs,DistintaBaseImporterTests.cs,CaseInsensitiveLookupIntegrationTests.cs.