Add explicit working folder; rename project from CadSearchGui to PrepStep

Working folder (phase 1): CSV/raw/step/step_finali all used to live split
across two different implicit locations (CSV in the "repo root" found by
walking up for CLAUDE.md, raw/step next to the input distinta file) with
neither shown to the user. That repo-root lookup also silently breaks once
the app runs as a standalone published exe on a machine with no repo/
CLAUDE.md at all. Replaced both with one explicit "cartella di lavoro",
auto-suggested (last used, remembered the same way as the DB path) and
changeable from phase 1, with no dependency on any repo marker file.

Rename: CadSearchGui was the working name from before the app had a
product identity; renamed folders, csproj files, namespace and the
AppData settings folder to PrepStep throughout, matching the exe name
already in use. Product-facing name stays "Cevolani StepPrep".

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
davideandClaude Sonnet 5 committed 2026-09-21 11:18:43 +02:00
1 parent 6726dd2216
commit 13798ad47c
24 files changed
+211 -129

No files matched your search

+26 -20
View File
@@ -4,10 +4,10 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Cos'è questo progetto ## Cos'è questo progetto
`CadSearchGui` è il nome tecnico del progetto (cartella, namespace, csproj); il nome del `PrepStep` è il nome tecnico del progetto (cartella, namespace, csproj, eseguibile
programma per l'utente finale è **Cevolani StepPrep** (versione in `<Version>` dentro `PrepStep.exe`); il nome mostrato all'utente finale è **Cevolani StepPrep** (`<Product>`/
`CadSearchGui/CadSearchGui.csproj`, attualmente `0.1.0` — mostrata anche nel titolo della `<AssemblyTitle>` in `PrepStep/PrepStep.csproj`, usato nel titolo della finestra insieme
finestra). È un'app Windows Forms (.NET 10, WinForms) che indicizza e permette di alla versione, `<Version>`, attualmente `0.1.0`). È un'app Windows Forms (.NET 10, WinForms) che indicizza e permette di
cercare i file CAD Pro-ENGINEER/Creo contenuti in tutte le cartelle di primo livello cercare i file CAD Pro-ENGINEER/Creo contenuti in tutte le cartelle di primo livello
di un disco/share di rete (radice di default `X:\`), salvando i metadati in un DB di un disco/share di rete (radice di default `X:\`), salvando i metadati in un DB
SQLite locale (`cad_index.db`). Il flusso a valle (fasi 2-5, vedi sotto) prepara i file SQLite locale (`cad_index.db`). Il flusso a valle (fasi 2-5, vedi sotto) prepara i file
@@ -16,7 +16,7 @@ pre-processo per quel passaggio, non lo sostituisce.
## Comandi ## Comandi
Tutti da eseguire dentro `CadSearchGui/`. Tutti da eseguire dentro `PrepStep/`.
```powershell ```powershell
dotnet build -c Release dotnet build -c Release
@@ -29,16 +29,16 @@ Pubblicazione come eseguibile standalone (single-file, self-contained, Windows x
dotnet publish -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true -o publish dotnet publish -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true -o publish
``` ```
`CadSearchGui.Tests/` (xUnit) contiene unit e integration test — vedi `PrepStep.Tests/` (xUnit) contiene unit e integration test — vedi
`dotnet test` da dentro quella cartella. Riferimento al progetto principale `dotnet test` da dentro quella cartella. Riferimento al progetto principale
via `ProjectReference` + `InternalsVisibleTo` (in `CadSearchGui.csproj`), così via `ProjectReference` + `InternalsVisibleTo` (in `PrepStep.csproj`), così
i test possono chiamare direttamente `Indexer.ParseFilename` e i test possono chiamare direttamente `Indexer.ParseFilename` e
`AssemblyComponentScanner.EstraiCodiciReferenziati` senza esporli come API `AssemblyComponentScanner.EstraiCodiciReferenziati` senza esporli come API
pubblica. pubblica.
## Architettura ## Architettura
Il programma è tutto in `CadSearchGui/` (nessun altro progetto nella solution — in Il programma è tutto in `PrepStep/` (nessun altro progetto nella solution — in
passato esisteva anche una CLI separata e uno script Python di indicizzazione, passato esisteva anche una CLI separata e uno script Python di indicizzazione,
entrambi rimossi: ora l'unico programma è questo, con GUI e indicizzazione integrate). entrambi rimossi: ora l'unico programma è questo, con GUI e indicizzazione integrate).
@@ -50,19 +50,25 @@ entrambi rimossi: ora l'unico programma è questo, con GUI e indicizzazione inte
`Form1.Designer.cs` contiene solo lo scheletro minimo (`InitializeComponent`/`Dispose`) `Form1.Designer.cs` contiene solo lo scheletro minimo (`InitializeComponent`/`Dispose`)
generato dal template. Le fasi, in ordine: generato dal template. Le fasi, in ordine:
1. **Database** — carica/aggiorna l'indice, mostra data ultimo aggiornamento; qui vive 1. **Database** — carica/aggiorna l'indice, mostra data ultimo aggiornamento; qui vive
anche "Pulisci raw e step" (manutenzione, non fa parte del flusso a valle). anche la **cartella di lavoro** (`_cartellaLavoro`, mostrata in `_lblCartellaLavoro`,
cambiabile con "Cambia cartella..." → `ScegliCartellaLavoro`): destinazione di CSV,
`raw/`, `step/`, `step_finali/` per tutte le fasi successive. All'avvio
`InizializzaCartellaLavoro` propone l'ultima usata (ricordata in
`%AppData%/PrepStep/ultima_cartella_lavoro.txt`, stesso pattern di
`ultimo_db.txt` per il DB) se esiste ancora, altrimenti `AppContext.BaseDirectory`
— non dipende da un marker di repo (niente più `CLAUDE.md`/`TrovaRadiceRepo`),
quindi funziona identica anche sull'exe pubblicato standalone (`PrepStep.exe`)
copiato su un'altra macchina. Qui vive anche "Pulisci raw e step" (manutenzione,
non fa parte del flusso a valle).
2. **Importa Distinta Base** — `DistintaBaseImporter.ConvertiInCsv` genera il CSV dei 2. **Importa Distinta Base** — `DistintaBaseImporter.ConvertiInCsv` genera il CSV dei
componenti; se il nome del file segue la convenzione del gestionale componenti nella cartella di lavoro; se il nome del file segue la convenzione del
(`DBP_<codice>_<timestamp>`), l'assieme generale viene aggiunto come riga in più nel gestionale (`DBP_<codice>_<timestamp>`), l'assieme generale viene aggiunto come riga
CSV stesso (il foglio elenca solo i componenti sotto l'assieme, non l'assieme in sé). in più nel CSV stesso (il foglio elenca solo i componenti sotto l'assieme, non
Da qui in avanti l'assieme generale è un componente come tutti gli altri, nessun l'assieme in sé). Da qui in avanti l'assieme generale è un componente come tutti
caso speciale nel resto del codice. Il CSV viene sempre scritto nella root del repo gli altri, nessun caso speciale nel resto del codice.
(`Form1.TrovaRadiceRepo`, che risale da `AppContext.BaseDirectory` fino alla cartella
che contiene `CLAUDE.md`), indipendentemente da dove si trova il file `.xls`/`.xml`
di input scelto dall'utente.
3. **Crea cartella raw** — cerca nell'indice il percorso CAD di ogni componente del CSV 3. **Crea cartella raw** — cerca nell'indice il percorso CAD di ogni componente del CSV
(`TrovaPercorsiCad`) e lo copia in `raw/` (`CopiaFileTrovati`, parallela — vedi (`TrovaPercorsiCad`) e lo copia in `raw/` dentro la cartella di lavoro
`docs/copia-raw-parallela.md`). (`CopiaFileTrovati`, parallela — vedi `docs/copia-raw-parallela.md`).
4. **Trova componenti referenziati** — legge euristicamente i metadati binari dei `.asm` 4. **Trova componenti referenziati** — legge euristicamente i metadati binari dei `.asm`
già in `raw/` (`AssemblyComponentScanner`) per risolvere ricorsivamente i già in `raw/` (`AssemblyComponentScanner`) per risolvere ricorsivamente i
sotto-assiemi/parti che contengono (`RisolviAlberoComponenti`), copiandoli anch'essi sotto-assiemi/parti che contengono (`RisolviAlberoComponenti`), copiandoli anch'essi
@@ -100,7 +106,7 @@ entrambi rimossi: ora l'unico programma è questo, con GUI e indicizzazione inte
in pixel, per evitare che il testo vada a capo e si tagli quando non ci sta) e in pixel, per evitare che il testo vada a capo e si tagli quando non ci sta) e
`Arrotonda` per gli angoli dei bottoni "Avanti"/"Indietro" del wizard. `Arrotonda` per gli angoli dei bottoni "Avanti"/"Indietro" del wizard.
- **app.ico** — icona dell'app (logo Cevolani + pezzo + STEP, sfondo trasparente), - **app.ico** — icona dell'app (logo Cevolani + pezzo + STEP, sfondo trasparente),
referenziata da `<ApplicationIcon>` in `CadSearchGui.csproj` e riletta a runtime in referenziata da `<ApplicationIcon>` in `PrepStep.csproj` e riletta a runtime in
`Form1.BuildUi()` via `Icon.ExtractAssociatedIcon(Application.ExecutablePath)` per `Form1.BuildUi()` via `Icon.ExtractAssociatedIcon(Application.ExecutablePath)` per
la titlebar (stessa icona dell'exe, nessun file duplicato nell'output). la titlebar (stessa icona dell'exe, nessun file duplicato nell'output).
@@ -1,6 +1,6 @@
using CadSearchGui; using PrepStep;
namespace CadSearchGui.Tests; namespace PrepStep.Tests;
public class AssemblyComponentScannerTests public class AssemblyComponentScannerTests
{ {
@@ -1,7 +1,7 @@
using CadSearchGui; using PrepStep;
using Microsoft.Data.Sqlite; using Microsoft.Data.Sqlite;
namespace CadSearchGui.Tests; namespace PrepStep.Tests;
/// <summary>Ricrea lo schema reale del DB (stessa costante SQL usata da Indexer.ScanAsync) e /// <summary>Ricrea lo schema reale del DB (stessa costante SQL usata da Indexer.ScanAsync) e
/// verifica, con dati inseriti a mano, i due comportamenti che in passato hanno causato bug /// verifica, con dati inseriti a mano, i due comportamenti che in passato hanno causato bug
@@ -1,6 +1,6 @@
using CadSearchGui; using PrepStep;
namespace CadSearchGui.Tests; namespace PrepStep.Tests;
public class DistintaBaseImporterTests public class DistintaBaseImporterTests
{ {
@@ -1,6 +1,6 @@
using CadSearchGui; using PrepStep;
namespace CadSearchGui.Tests; namespace PrepStep.Tests;
public class IndexerParseFilenameTests public class IndexerParseFilenameTests
{ {
@@ -16,7 +16,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\CadSearchGui\CadSearchGui.csproj" /> <ProjectReference Include="..\PrepStep\PrepStep.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -1,7 +1,7 @@
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
namespace CadSearchGui; namespace PrepStep;
/// <summary> /// <summary>
/// Estrae i codici componente referenziati dentro un file .asm Pro-E/Creo. /// Estrae i codici componente referenziati dentro un file .asm Pro-E/Creo.
@@ -2,7 +2,7 @@ using System.Text;
using System.Xml.Linq; using System.Xml.Linq;
using ExcelDataReader; using ExcelDataReader;
namespace CadSearchGui; namespace PrepStep;
/// <summary> /// <summary>
/// Converte il file "Distinta Base" esportato dal gestionale (SpreadsheetML /// Converte il file "Distinta Base" esportato dal gestionale (SpreadsheetML
@@ -1,6 +1,6 @@
#nullable enable #nullable enable
namespace CadSearchGui; namespace PrepStep;
partial class Form1 partial class Form1
{ {
+105 -45
View File
@@ -1,7 +1,7 @@
using System.Diagnostics; using System.Diagnostics;
using Microsoft.Data.Sqlite; using Microsoft.Data.Sqlite;
namespace CadSearchGui; namespace PrepStep;
public partial class Form1 : Form public partial class Form1 : Form
{ {
@@ -17,6 +17,8 @@ public partial class Form1 : Form
private readonly Label _lblStatus = new(); private readonly Label _lblStatus = new();
private readonly Label _lblDb = new(); private readonly Label _lblDb = new();
private readonly Label _lblUltimoAggiornamento = new(); private readonly Label _lblUltimoAggiornamento = new();
private readonly Label _lblCartellaLavoro = new();
private readonly Button _btnCambiaCartella = new();
private readonly DataGridView _gridImport = new(); private readonly DataGridView _gridImport = new();
private readonly DataGridView _gridRaw = new(); private readonly DataGridView _gridRaw = new();
private readonly Label _lblImportStatus = new(); private readonly Label _lblImportStatus = new();
@@ -42,20 +44,8 @@ public partial class Form1 : Form
private static readonly string[] TipiPredefiniti = { "prt", "asm" }; private static readonly string[] TipiPredefiniti = { "prt", "asm" };
private const string RadiceDiscoDefault = @"X:\"; private const string RadiceDiscoDefault = @"X:\";
/// <summary>Risale da AppContext.BaseDirectory (variabile tra Debug/Release/publish) fino
/// alla cartella che contiene CLAUDE.md, cioè la root del repo; se non la trova (es. exe
/// pubblicato e spostato altrove) ripiega su AppContext.BaseDirectory.</summary>
private static string TrovaRadiceRepo()
{
for (var dir = new DirectoryInfo(AppContext.BaseDirectory); dir is not null; dir = dir.Parent)
{
if (File.Exists(Path.Combine(dir.FullName, "CLAUDE.md")))
return dir.FullName;
}
return AppContext.BaseDirectory;
}
private string? _dbPath; private string? _dbPath;
private string? _cartellaLavoro;
private string? _percorsoInputCorrente; private string? _percorsoInputCorrente;
private List<(string Componente, string Descrizione)>? _righeCorrenti; private List<(string Componente, string Descrizione)>? _righeCorrenti;
private Dictionary<string, List<string>>? _ultimaVerifica; private Dictionary<string, List<string>>? _ultimaVerifica;
@@ -65,7 +55,11 @@ public partial class Form1 : Form
{ {
InitializeComponent(); InitializeComponent();
BuildUi(); BuildUi();
Load += (_, _) => InizializzaDatabase(); Load += (_, _) =>
{
InizializzaCartellaLavoro();
InizializzaDatabase();
};
} }
// Palette: blu primario per l'azione principale del flusso ("Crea cartella raw"), // Palette: blu primario per l'azione principale del flusso ("Crea cartella raw"),
@@ -77,7 +71,7 @@ public partial class Form1 : Form
AllowDrop = true; AllowDrop = true;
// Versione letta dall'assembly (<Version> nel csproj) invece che duplicata qui a mano. // Versione letta dall'assembly (<Version> nel csproj) invece che duplicata qui a mano.
var versione = typeof(Form1).Assembly.GetName().Version; var versione = typeof(Form1).Assembly.GetName().Version;
Text = $"Cevolani StepPrep {versione?.ToString(3)} — Distinta Base -> CSV con percorsi CAD"; Text = $"Cevolani StepPrep {versione?.ToString(3)}";
MinimumSize = new Size(760, 480); MinimumSize = new Size(760, 480);
Font = new Font("Segoe UI", 9.5f); Font = new Font("Segoe UI", 9.5f);
// Stessa icona di ApplicationIcon nel csproj: la si rilegge dall'exe compilato invece // Stessa icona di ApplicationIcon nel csproj: la si rilegge dall'exe compilato invece
@@ -221,7 +215,7 @@ public partial class Form1 : Form
/// <summary>Condizione per cui la fase indicata è "conclusa" e si può passare alla successiva.</summary> /// <summary>Condizione per cui la fase indicata è "conclusa" e si può passare alla successiva.</summary>
private bool AvantiConsentito(int fase) => fase switch private bool AvantiConsentito(int fase) => fase switch
{ {
0 => _dbPath is not null, 0 => _dbPath is not null && _cartellaLavoro is not null,
1 => _righeCorrenti is { Count: > 0 }, 1 => _righeCorrenti is { Count: > 0 },
2 => _ultimaCartellaRaw is not null, 2 => _ultimaCartellaRaw is not null,
3 => true, // risoluzione ricorsiva opzionale: non tutti gli assiemi hanno sotto-componenti 3 => true, // risoluzione ricorsiva opzionale: non tutti gli assiemi hanno sotto-componenti
@@ -282,14 +276,37 @@ public partial class Form1 : Form
contenuto.Controls.Add(bottoni); contenuto.Controls.Add(bottoni);
var lblIstruzioniCartella = new Label
{
Dock = DockStyle.Top,
AutoSize = true,
ForeColor = SystemColors.GrayText,
Margin = new Padding(0, 20, 0, 4),
Text = "Cartella di lavoro: qui vengono scritti il CSV della distinta e le "
+ "cartelle 'raw', 'step' e 'step_finali'. Proposta automaticamente "
+ "(ricordata da un avvio all'altro), modificabile con 'Cambia cartella...'.",
};
contenuto.Controls.Add(lblIstruzioniCartella);
_lblCartellaLavoro.Dock = DockStyle.Top;
_lblCartellaLavoro.AutoSize = true;
_lblCartellaLavoro.ForeColor = SystemColors.GrayText;
_lblCartellaLavoro.Margin = new Padding(0, 0, 0, 4);
contenuto.Controls.Add(_lblCartellaLavoro);
_btnCambiaCartella.Text = "Cambia cartella...";
UiStile.Secondario(_btnCambiaCartella);
_btnCambiaCartella.Click += (_, _) => ScegliCartellaLavoro();
contenuto.Controls.Add(_btnCambiaCartella);
var lblManutenzione = new Label var lblManutenzione = new Label
{ {
Dock = DockStyle.Top, Dock = DockStyle.Top,
AutoSize = true, AutoSize = true,
ForeColor = SystemColors.GrayText, ForeColor = SystemColors.GrayText,
Margin = new Padding(0, 20, 0, 8), Margin = new Padding(0, 20, 0, 8),
Text = "Manutenzione: svuota le cartelle 'raw' e 'step' nella root prima di un " Text = "Manutenzione: svuota le cartelle 'raw' e 'step' nella cartella di lavoro "
+ "nuovo giro (non tocca l'indice, solo le copie locali).", + "prima di un nuovo giro (non tocca l'indice, solo le copie locali).",
}; };
contenuto.Controls.Add(lblManutenzione); contenuto.Controls.Add(lblManutenzione);
@@ -397,7 +414,7 @@ public partial class Form1 : Form
ForeColor = SystemColors.GrayText, ForeColor = SystemColors.GrayText,
Margin = new Padding(0, 0, 0, 8), Margin = new Padding(0, 0, 0, 8),
Text = "Cerca nell'indice il percorso CAD di ogni componente importato e copia i " Text = "Cerca nell'indice il percorso CAD di ogni componente importato e copia i "
+ "file trovati in una cartella 'raw' accanto al file di distinta originale.", + "file trovati in una cartella 'raw' dentro la cartella di lavoro (fase 1).",
}; };
contenuto.Controls.Add(lblIstruzioni); contenuto.Controls.Add(lblIstruzioni);
@@ -578,7 +595,7 @@ public partial class Form1 : Form
{ {
try try
{ {
var (csv, righe) = DistintaBaseImporter.ConvertiInCsv(percorso, TrovaRadiceRepo()); var (csv, righe) = DistintaBaseImporter.ConvertiInCsv(percorso, _cartellaLavoro!);
_percorsoInputCorrente = percorso; _percorsoInputCorrente = percorso;
_righeCorrenti = righe; _righeCorrenti = righe;
@@ -647,7 +664,7 @@ public partial class Form1 : Form
_gridRaw.Rows.Add(componente, percorsoCad); _gridRaw.Rows.Add(componente, percorsoCad);
} }
var cartellaRaw = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(_percorsoInputCorrente))!, "raw"); var cartellaRaw = Path.Combine(_cartellaLavoro!, "raw");
int copiati = CopiaFileTrovati(percorsiTrovati.Values.SelectMany(p => p).Distinct(), cartellaRaw); int copiati = CopiaFileTrovati(percorsiTrovati.Values.SelectMany(p => p).Distinct(), cartellaRaw);
_ultimaCartellaRaw = cartellaRaw; _ultimaCartellaRaw = cartellaRaw;
@@ -663,10 +680,10 @@ public partial class Form1 : Form
/// già stati realizzati e quali mancano ancora.</summary> /// già stati realizzati e quali mancano ancora.</summary>
private void GeneraReportStep() private void GeneraReportStep()
{ {
if (_percorsoInputCorrente is null || _righeCorrenti is null) if (_righeCorrenti is null)
return; return;
string radice = Path.GetDirectoryName(Path.GetFullPath(_percorsoInputCorrente))!; string radice = _cartellaLavoro!;
var cartellaStep = Path.Combine(radice, "step"); var cartellaStep = Path.Combine(radice, "step");
if (!Directory.Exists(cartellaStep)) if (!Directory.Exists(cartellaStep))
{ {
@@ -722,26 +739,12 @@ public partial class Form1 : Form
dialog.ShowDialog(this); dialog.ShowDialog(this);
} }
/// <summary>Svuota in un colpo solo le cartelle "raw", "step" e "step_finali" nella root /// <summary>Svuota in un colpo solo le cartelle "raw", "step" e "step_finali" nella cartella
/// (stessa cartella base del file distinta importato), previa un'unica conferma. Non tocca /// di lavoro, previa un'unica conferma. Non tocca l'indice CAD: solo le copie locali
/// l'indice CAD: solo le copie locali generate dalla pipeline.</summary> /// generate dalla pipeline.</summary>
private void PulisciRawEStep() private void PulisciRawEStep()
{ {
string radice; string radice = _cartellaLavoro!;
if (_ultimaCartellaRaw is not null)
{
radice = Path.GetDirectoryName(_ultimaCartellaRaw)!;
}
else
{
// Non abbiamo ancora una cartella nota in questa sessione (es. app appena riaperta):
// si chiede all'utente di indicare la root invece di tenere il pulsante disabilitato.
using var dialog = new FolderBrowserDialog { Description = "Seleziona la cartella root (contiene 'raw' e 'step')" };
if (dialog.ShowDialog(this) != DialogResult.OK)
return;
radice = dialog.SelectedPath;
}
var cartelle = new[] { Path.Combine(radice, "raw"), Path.Combine(radice, "step"), Path.Combine(radice, "step_finali") } var cartelle = new[] { Path.Combine(radice, "raw"), Path.Combine(radice, "step"), Path.Combine(radice, "step_finali") }
.Where(Directory.Exists) .Where(Directory.Exists)
.ToList(); .ToList();
@@ -1058,8 +1061,65 @@ public partial class Form1 : Form
return risultato; return risultato;
} }
private static readonly string PercorsoImpostazioni = Path.Combine( private static readonly string CartellaImpostazioni = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "CadSearchGui", "ultimo_db.txt"); Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "PrepStep");
private static readonly string PercorsoImpostazioni = Path.Combine(CartellaImpostazioni, "ultimo_db.txt");
private static readonly string PercorsoImpostazioniCartella = Path.Combine(CartellaImpostazioni, "ultima_cartella_lavoro.txt");
/// <summary>Propone l'ultima cartella di lavoro usata (se ancora esiste su disco) o, la prima
/// volta, la cartella dell'eseguibile: non richiede mai un CLAUDE.md/repo (a differenza del
/// vecchio TrovaRadiceRepo), quindi funziona identica anche sull'exe pubblicato standalone
/// copiato su un'altra macchina. Sempre modificabile con "Cambia cartella..." in fase 1.</summary>
private void InizializzaCartellaLavoro()
{
var ultima = LeggiUltimaCartellaLavoro();
_cartellaLavoro = ultima is not null && Directory.Exists(ultima) ? ultima : AppContext.BaseDirectory;
AggiornaLabelCartellaLavoro();
}
private void ScegliCartellaLavoro()
{
using var dialog = new FolderBrowserDialog
{
Description = "Seleziona la cartella di lavoro (CSV, raw, step, step_finali)",
SelectedPath = _cartellaLavoro ?? string.Empty,
};
if (dialog.ShowDialog(this) != DialogResult.OK)
return;
string percorso = dialog.SelectedPath;
_cartellaLavoro = percorso;
AggiornaLabelCartellaLavoro();
SalvaUltimaCartellaLavoro(percorso);
AggiornaStatoAvanti();
}
private void AggiornaLabelCartellaLavoro() => _lblCartellaLavoro.Text = $"Cartella di lavoro: {_cartellaLavoro}";
private static string? LeggiUltimaCartellaLavoro()
{
try
{
return File.Exists(PercorsoImpostazioniCartella) ? File.ReadAllText(PercorsoImpostazioniCartella).Trim() : null;
}
catch (IOException)
{
return null;
}
}
private static void SalvaUltimaCartellaLavoro(string path)
{
try
{
Directory.CreateDirectory(CartellaImpostazioni);
File.WriteAllText(PercorsoImpostazioniCartella, path);
}
catch (IOException)
{
// ponytail: non critico se non si riesce a salvare, si ripropone il default al prossimo avvio
}
}
private void InizializzaDatabase() private void InizializzaDatabase()
{ {
@@ -1141,7 +1201,7 @@ public partial class Form1 : Form
{ {
try try
{ {
Directory.CreateDirectory(Path.GetDirectoryName(PercorsoImpostazioni)!); Directory.CreateDirectory(CartellaImpostazioni);
File.WriteAllText(PercorsoImpostazioni, path); File.WriteAllText(PercorsoImpostazioni, path);
} }
catch (IOException) catch (IOException)
@@ -2,7 +2,7 @@ using System.Diagnostics;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Microsoft.Data.Sqlite; using Microsoft.Data.Sqlite;
namespace CadSearchGui; namespace PrepStep;
public sealed record ScanProgress( public sealed record ScanProgress(
string Cartella, string Cartella,
@@ -8,6 +8,8 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<ApplicationHighDpiMode>PerMonitorV2</ApplicationHighDpiMode> <ApplicationHighDpiMode>PerMonitorV2</ApplicationHighDpiMode>
<ApplicationIcon>app.ico</ApplicationIcon> <ApplicationIcon>app.ico</ApplicationIcon>
<!-- Nome tecnico (cartella/csproj/namespace) e nome del file .exe pubblicato: PrepStep.
Il nome prodotto mostrato all'utente ("Cevolani StepPrep") resta separato, sotto. -->
<AssemblyTitle>Cevolani StepPrep</AssemblyTitle> <AssemblyTitle>Cevolani StepPrep</AssemblyTitle>
<Product>Cevolani StepPrep</Product> <Product>Cevolani StepPrep</Product>
<Company>Cevolani</Company> <Company>Cevolani</Company>
@@ -22,7 +24,7 @@
<ItemGroup> <ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute"> <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
<_Parameter1>CadSearchGui.Tests</_Parameter1> <_Parameter1>PrepStep.Tests</_Parameter1>
</AssemblyAttribute> </AssemblyAttribute>
</ItemGroup> </ItemGroup>
@@ -1,4 +1,4 @@
namespace CadSearchGui; namespace PrepStep;
static class Program static class Program
{ {
@@ -1,4 +1,4 @@
namespace CadSearchGui; namespace PrepStep;
public sealed class ProgressForm : Form public sealed class ProgressForm : Form
{ {
@@ -1,4 +1,4 @@
namespace CadSearchGui; namespace PrepStep;
public sealed class ProgressoComponentiForm : Form public sealed class ProgressoComponentiForm : Form
{ {
@@ -1,6 +1,6 @@
using System.Diagnostics; using System.Diagnostics;
namespace CadSearchGui; namespace PrepStep;
/// <summary>Mostra l'esito della risoluzione ricorsiva dell'albero componenti: i PRT e i /// <summary>Mostra l'esito della risoluzione ricorsiva dell'albero componenti: i PRT e i
/// sotto-assiemi trovati nell'indice e già copiati in "raw" a partire dagli assiemi iniziali.</summary> /// sotto-assiemi trovati nell'indice e già copiati in "raw" a partire dagli assiemi iniziali.</summary>
@@ -1,4 +1,4 @@
namespace CadSearchGui; namespace PrepStep;
/// <summary>Mostra, per ogni assieme della distinta base, se tutti i suoi componenti /// <summary>Mostra, per ogni assieme della distinta base, se tutti i suoi componenti
/// (ricorsivamente fino ai PRT) sono presenti nell'indice (v) o mancano (x).</summary> /// (ricorsivamente fino ai PRT) sono presenti nell'indice (v) o mancano (x).</summary>
@@ -1,6 +1,6 @@
using System.Diagnostics; using System.Diagnostics;
namespace CadSearchGui; namespace PrepStep;
public enum EsitoStep public enum EsitoStep
{ {
@@ -1,6 +1,6 @@
using System.Drawing.Drawing2D; using System.Drawing.Drawing2D;
namespace CadSearchGui; namespace PrepStep;
/// <summary>Stile bottoni condiviso tra la form principale e i dialog secondari: piatto con /// <summary>Stile bottoni condiviso tra la form principale e i dialog secondari: piatto con
/// bordo sottile e hover, per un aspetto coerente sia per l'azione primaria di ogni fase /// bordo sottile e hover, per un aspetto coerente sia per l'azione primaria di ogni fase
File renamed without changes.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

+22 -17
View File
@@ -1,6 +1,6 @@
# Cevolani StepPrep # Cevolani StepPrep
App Windows Forms (.NET 10, progetto `CadSearchGui`) per indicizzare, cercare e App Windows Forms (.NET 10, progetto `PrepStep`) per indicizzare, cercare e
recuperare i file CAD Pro-ENGINEER/Creo di un disco/share di rete, e per trasformare recuperare i file CAD Pro-ENGINEER/Creo di un disco/share di rete, e per trasformare
l'estrazione "Distinta Base" del gestionale (file `.xls`/`.xml`) in un CSV con il l'estrazione "Distinta Base" del gestionale (file `.xls`/`.xml`) in un CSV con il
percorso CAD di ogni componente, fino a raccogliere in `raw/` tutto il necessario per percorso CAD di ogni componente, fino a raccogliere in `raw/` tutto il necessario per
@@ -13,17 +13,20 @@ passaggio, non lo sostituisce.
presente accanto all'eseguibile). Se manca, si può selezionare un DB presente accanto all'eseguibile). Se manca, si può selezionare un DB
esistente con **Apri DB...** o generarne uno nuovo con **Aggiorna esistente con **Apri DB...** o generarne uno nuovo con **Aggiorna
indice**, che scansiona il disco (di default `X:\`, tutte le cartelle di primo indice**, che scansiona il disco (di default `X:\`, tutte le cartelle di primo
livello che trova) e indicizza tutti i file. livello che trova) e indicizza tutti i file. In questa fase si vede/cambia anche
la **cartella di lavoro**: dove finiscono il CSV e le cartelle `raw/`, `step/`,
`step_finali/`. Proposta automaticamente (ricordata da un avvio all'altro),
modificabile con **Cambia cartella...**.
2. **Importa Distinta Base** — trascina (o scegli da file) l'estrazione 2. **Importa Distinta Base** — trascina (o scegli da file) l'estrazione
`.xls`/`.xml` del gestionale (foglio "Distinta Base", colonne `.xls`/`.xml` del gestionale (foglio "Distinta Base", colonne
Componente/Descrizione): viene generato un CSV con anteprima in griglia. Componente/Descrizione): viene generato un CSV nella cartella di lavoro, con
Se il file segue la convenzione di nome `DBP_<codice>_<timestamp>` del anteprima in griglia. Se il file segue la convenzione di nome
gestionale, l'assieme generale dell'estrazione viene aggiunto come riga `DBP_<codice>_<timestamp>` del gestionale, l'assieme generale dell'estrazione
in più nel CSV (il foglio elenca solo i componenti sotto l'assieme, non viene aggiunto come riga in più nel CSV (il foglio elenca solo i componenti
l'assieme stesso). sotto l'assieme, non l'assieme stesso).
3. **Crea cartella raw** — cerca nell'indice il percorso CAD di ogni 3. **Crea cartella raw** — cerca nell'indice il percorso CAD di ogni
componente importato (assieme generale incluso) e copia i file trovati componente importato (assieme generale incluso) e copia i file trovati
in una cartella `raw/` accanto al file di distinta originale. in una cartella `raw/` dentro la cartella di lavoro.
4. **Trova componenti referenziati** — legge i metadati dei file `.asm` in 4. **Trova componenti referenziati** — legge i metadati dei file `.asm` in
`raw/` per trovare ricorsivamente i sotto-assiemi/parti che li `raw/` per trovare ricorsivamente i sotto-assiemi/parti che li
compongono, copiandoli a loro volta in `raw/`. compongono, copiandoli a loro volta in `raw/`.
@@ -42,7 +45,7 @@ passaggio, non lo sostituisce.
## Build ## Build
```powershell ```powershell
cd CadSearchGui cd PrepStep
dotnet build -c Release dotnet build -c Release
``` ```
@@ -51,15 +54,15 @@ dotnet build -c Release
Da sorgente: Da sorgente:
```powershell ```powershell
cd CadSearchGui cd PrepStep
dotnet run -c Release dotnet run -c Release
``` ```
Oppure l'eseguibile già compilato: Oppure l'eseguibile già compilato:
```powershell ```powershell
cd CadSearchGui\bin\Release\net10.0-windows cd PrepStep\bin\Release\net10.0-windows
.\CadSearchGui.exe .\PrepStep.exe
``` ```
## Pubblicazione (eseguibile standalone) ## Pubblicazione (eseguibile standalone)
@@ -68,15 +71,17 @@ Genera un `.exe` self-contained per Windows x64, senza bisogno del runtime
.NET installato sulla macchina di destinazione: .NET installato sulla macchina di destinazione:
```powershell ```powershell
cd CadSearchGui cd PrepStep
dotnet publish -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true -o publish dotnet publish -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true -o publish
``` ```
L'eseguibile risultante è in `CadSearchGui\publish\CadSearchGui.exe`. L'eseguibile risultante è in `PrepStep\publish\PrepStep.exe` — un unico
file, si copia e si lancia su un'altra macchina Windows senza bisogno di .NET
installato.
## Struttura del progetto ## Struttura del progetto
Tutto il codice è in `CadSearchGui/` (unico progetto nella solution, GUI e Tutto il codice è in `PrepStep/` (unico progetto nella solution, GUI e
indicizzazione integrate): indicizzazione integrate):
- `Program.cs` — entry point. - `Program.cs` — entry point.
@@ -93,12 +98,12 @@ sono tracciati in git (vedi `.gitignore`).
## Test ## Test
`CadSearchGui.Tests/` contiene unit test (regex di estrazione dei componenti `PrepStep.Tests/` contiene unit test (regex di estrazione dei componenti
dai `.asm`, parsing del nome file Pro-E) e integration test (schema/vista SQL dai `.asm`, parsing del nome file Pro-E) e integration test (schema/vista SQL
reale, con focus sui bug di case-sensitivity/duplicati già risolti). Da reale, con focus sui bug di case-sensitivity/duplicati già risolti). Da
eseguire: eseguire:
```powershell ```powershell
cd CadSearchGui.Tests cd PrepStep.Tests
dotnet test dotnet test
``` ```
+31 -22
View File
@@ -1,9 +1,9 @@
# Architettura di CadSearchGui (Cevolani StepPrep) # Architettura di PrepStep (Cevolani StepPrep)
Panoramica di tutti i file sorgente e di come collaborano. `CadSearchGui` è il nome Panoramica di tutti i file sorgente e di come collaborano. `PrepStep` è il nome
tecnico del progetto; **Cevolani StepPrep** è il nome del programma per l'utente tecnico del progetto (cartella, namespace, csproj, eseguibile `PrepStep.exe`);
finale (titolo finestra, icona, versione — vedi `<Version>`/`<Product>` in **Cevolani StepPrep** è il nome mostrato all'utente finale (titolo finestra, icona,
`CadSearchGui.csproj`). Per il "come si usa" vedi il `README.md` in root; per il versione — vedi `<Version>`/`<Product>` in `PrepStep.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 formato binario `.asm` vedi `docs/formato-asm.md`; per la parallelizzazione della
copia in `raw/` vedi `docs/copia-raw-parallela.md`. copia in `raw/` vedi `docs/copia-raw-parallela.md`.
@@ -40,14 +40,15 @@ Distinta (.xls/.xml) → CSV (componente;descrizione) → raw/ (CAD copiati
| # | Fase | Bottone → metodo | Cosa fa | | # | Fase | Bottone → metodo | Cosa fa |
|---|---|---|---| |---|---|---|---|
| 1 | Database | "Aggiorna indice" → `Indexer.ScanAsync` | Crea/aggiorna `cad_index.db` scansionando la share | | 1 | Database | "Aggiorna indice" → `Indexer.ScanAsync`; "Cambia cartella..." → `ScegliCartellaLavoro` | Crea/aggiorna `cad_index.db` scansionando la share; sceglie/mostra la cartella di lavoro |
| 2 | Importa Distinta Base | selezione file → `ImportaDistinta` → `DistintaBaseImporter.ConvertiInCsv` | Xls/Xml gestionale → CSV componente;descrizione, scritto nella root del repo (`TrovaRadiceRepo`) | | 2 | Importa Distinta Base | selezione file → `ImportaDistinta` → `DistintaBaseImporter.ConvertiInCsv` | Xls/Xml gestionale → CSV componente;descrizione, scritto nella cartella di lavoro |
| 3 | Crea cartella raw | "Crea cartella raw" → `CreaCartellaRaw` | `TrovaPercorsiCad` + `CopiaFileTrovati` (parallela) → `raw/` | | 3 | Crea cartella raw | "Crea cartella raw" → `CreaCartellaRaw` | `TrovaPercorsiCad` + `CopiaFileTrovati` (parallela) → `raw/` dentro la cartella di lavoro |
| 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/` | | 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/` | | 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/` (entrambe dentro la cartella di lavoro). 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`, Stato condiviso tra le fasi (campi privati di `Form1`): `_dbPath`, `_cartellaLavoro`,
`_righeCorrenti` (righe del CSV), `_ultimaVerifica` (cache percorsi CAD), `_ultimaCartellaRaw`. `_percorsoInputCorrente`, `_righeCorrenti` (righe del CSV), `_ultimaVerifica` (cache percorsi
CAD), `_ultimaCartellaRaw`.
Altre responsabilità in Form1.cs: Altre responsabilità in Form1.cs:
- `TrovaPercorsiCad` / `CaricaCodiciNoti` — query sul DB (`files_ultima_versione`), la - `TrovaPercorsiCad` / `CaricaCodiciNoti` — query sul DB (`files_ultima_versione`), la
@@ -55,10 +56,14 @@ Distinta (.xls/.xml) → CSV (componente;descrizione) → raw/ (CAD copiati
componenti sia da `AssemblyComponentScanner` per validare i token generici). componenti sia da `AssemblyComponentScanner` per validare i token generici).
- `CopiaFileTrovati` — copia (in parallelo, grado 6) i file trovati in `raw/`, saltando - `CopiaFileTrovati` — copia (in parallelo, grado 6) i file trovati in `raw/`, saltando
silenziosamente quelli irraggiungibili (share offline/permessi). silenziosamente quelli irraggiungibili (share offline/permessi).
- `PulisciRawEStep` — svuota `raw/`, `step/`, `step_finali/` (manutenzione, richiede conferma). - `PulisciRawEStep` — svuota `raw/`, `step/`, `step_finali/` nella cartella di lavoro
- `InizializzaDatabase` / `ScegliDatabase` / `TrovaRadiceRepo` — localizzazione del DB e (manutenzione, richiede conferma).
della root del repo (quest'ultima risalendo da `AppContext.BaseDirectory` fino alla - `InizializzaDatabase` / `ScegliDatabase` — localizzazione del DB (ultimo usato, salvato in
cartella che contiene `CLAUDE.md`). `%AppData%/PrepStep/ultimo_db.txt`, o `cad_index.db` accanto all'eseguibile).
- `InizializzaCartellaLavoro` / `ScegliCartellaLavoro` — stesso pattern per la cartella di
lavoro (`ultima_cartella_lavoro.txt`), fallback `AppContext.BaseDirectory` se non c'è
ancora nulla di salvato: nessuna dipendenza da un marker di repo, funziona identica
sull'exe pubblicato standalone spostato su un'altra macchina.
## Indicizzazione ## Indicizzazione
@@ -89,7 +94,8 @@ Distinta (.xls/.xml) → CSV (componente;descrizione) → raw/ (CAD copiati
file) nelle sole colonne Componente/Descrizione, foglio `"Distinta Base"`. Se il nome 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 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 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. passata da `Form1` (la cartella di lavoro scelta in fase 1), non necessariamente accanto al
file di input.
## Finestre di dialogo (modali, mostrate a fine step) ## Finestre di dialogo (modali, mostrate a fine step)
@@ -130,9 +136,12 @@ Distinta (.xls/.xml) → CSV (componente;descrizione) → raw/ (CAD copiati
Percorso: cercato accanto all'eseguibile o nella working directory all'avvio; altrimenti Percorso: cercato accanto all'eseguibile o nella working directory all'avvio; altrimenti
selezionabile con "Apri DB...". Radice disco di scansione di default `X:\` selezionabile con "Apri DB...". Radice disco di scansione di default `X:\`
(`Form1.RadiceDiscoDefault`, hardcoded). (`Form1.RadiceDiscoDefault`, hardcoded).
- **File su disco**, tutti nella root del repo (non nella cartella dell'eseguibile): il CSV - **Cartella di lavoro** — salvata in `%AppData%/PrepStep/ultima_cartella_lavoro.txt`
della distinta, `raw/` (CAD dei componenti e sotto-componenti), `step/` (STEP esportati a (stesso meccanismo del DB sopra), proposta di default `AppContext.BaseDirectory` la prima
mano da Creo, input), `step_finali/` (STEP dei soli codici della distinta, output). volta; selezionabile/cambiabile con "Cambia cartella..." in fase 1. Tutti i file generati a
valle ci finiscono dentro: 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/`) ## Script standalone (`scripts/`)
@@ -149,15 +158,15 @@ dipendenze extra con `#:package Nome@versione` in testa al file):
`AssemblyComponentScanner`. `AssemblyComponentScanner`.
- **Query.cs** — query SQL ad-hoc contro `cad_index.db` da riga di comando. - **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/` > ⚠️ Nota importante di sicurezza: se `dotnet run` viene lanciato dentro `PrepStep/`
> (che contiene un `.csproj` di tipo `WinExe`), esegue l'app GUI vera invece dello script > (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 > 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). > una cartella senza `.csproj` (es. la root del repo o `scripts/` stessa).
## Test ## Test
- **CadSearchGui.Tests/** (xUnit) — riferimento al progetto principale via `ProjectReference` - **PrepStep.Tests/** (xUnit) — riferimento al progetto principale via `ProjectReference`
+ `InternalsVisibleTo` (in `CadSearchGui.csproj`), così i test chiamano direttamente + `InternalsVisibleTo` (in `PrepStep.csproj`), così i test chiamano direttamente
`Indexer.ParseFilename` e `AssemblyComponentScanner.EstraiCodiciReferenziati` senza esporli `Indexer.ParseFilename` e `AssemblyComponentScanner.EstraiCodiciReferenziati` senza esporli
come API pubblica. File: `IndexerParseFilenameTests.cs`, come API pubblica. File: `IndexerParseFilenameTests.cs`,
`AssemblyComponentScannerTests.cs`, `DistintaBaseImporterTests.cs`, `AssemblyComponentScannerTests.cs`, `DistintaBaseImporterTests.cs`,
+3 -3
View File
@@ -33,7 +33,7 @@ ASCII leggibili in diversi campi ricorrenti:
Un codice reale compare **più volte** nel file (una per feature/placement Un codice reale compare **più volte** nel file (una per feature/placement
diverso); rumore binario che assomiglia casualmente a un codice compare quasi diverso); rumore binario che assomiglia casualmente a un codice compare quasi
sempre una sola volta. Questa è la base del filtro in sempre una sola volta. Questa è la base del filtro in
[`AssemblyComponentScanner.cs`](../CadSearchGui/AssemblyComponentScanner.cs) [`AssemblyComponentScanner.cs`](../PrepStep/AssemblyComponentScanner.cs)
e in [`scripts/ExtractCreoStrings.cs`](../scripts/ExtractCreoStrings.cs): e in [`scripts/ExtractCreoStrings.cs`](../scripts/ExtractCreoStrings.cs):
``` ```
@@ -249,7 +249,7 @@ regex aggiuntiva: (?<=<)(?:UNI\d+|CUSCI_[A-Za-z0-9]+)(?=>)
``` ```
Implementata sia in [`scripts/ExtractCreoStrings.cs`](../scripts/ExtractCreoStrings.cs) sia in Implementata sia in [`scripts/ExtractCreoStrings.cs`](../scripts/ExtractCreoStrings.cs) sia in
[`AssemblyComponentScanner.cs`](../CadSearchGui/AssemblyComponentScanner.cs) (fase "Trova componenti [`AssemblyComponentScanner.cs`](../PrepStep/AssemblyComponentScanner.cs) (fase "Trova componenti
referenziati" dell'app). Il prefisso family table non è garantito essere solo `UNI`/`CUSCI`: referenziati" dell'app). Il prefisso family table non è garantito essere solo `UNI`/`CUSCI`:
se ricompaiono famiglie diverse (altri componenti normalizzati), vanno aggiunte allo stesso modo, se ricompaiono famiglie diverse (altri componenti normalizzati), vanno aggiunte allo stesso modo,
verificando prima con `scripts/Analyze.cs` che il contenuto tra `<` e `>` corrisponda a un codice verificando prima con `scripts/Analyze.cs` che il contenuto tra `<` e `>` corrisponda a un codice
@@ -271,7 +271,7 @@ livello) serve una BFS:
Stessa logica di estrazione candidati ed euristica del codice radice (sopra), Stessa logica di estrazione candidati ed euristica del codice radice (sopra),
duplicata in due punti del codice per scopi diversi: duplicata in due punti del codice per scopi diversi:
- [`AssemblyComponentScanner.EstraiCodiciReferenziati`](../CadSearchGui/AssemblyComponentScanner.cs) + `CodiceRadice` — estrazione dei candidati da un file, usata dalla BFS in [`Form1.RisolviAlberoComponenti`](../CadSearchGui/Form1.cs) (fase "Trova componenti referenziati") e [`Form1.AssiemeCompleto`](../CadSearchGui/Form1.cs) (fase "Verifica completezza"). Entrambe seminano l'insieme dei codici visitati con codice + radice di ogni file di partenza, e caricano una volta sola tutti i codici noti all'indice (`Form1.CaricaCodiciNoti`) sia per validare i token generici delle parti commerciali sia per risolvere i percorsi dei componenti trovati, senza una query SQL per candidato. - [`AssemblyComponentScanner.EstraiCodiciReferenziati`](../PrepStep/AssemblyComponentScanner.cs) + `CodiceRadice` — estrazione dei candidati da un file, usata dalla BFS in [`Form1.RisolviAlberoComponenti`](../PrepStep/Form1.cs) (fase "Trova componenti referenziati") e [`Form1.AssiemeCompleto`](../PrepStep/Form1.cs) (fase "Verifica completezza"). Entrambe seminano l'insieme dei codici visitati con codice + radice di ogni file di partenza, e caricano una volta sola tutti i codici noti all'indice (`Form1.CaricaCodiciNoti`) sia per validare i token generici delle parti commerciali sia per risolvere i percorsi dei componenti trovati, senza una query SQL per candidato.
- [`scripts/ExtractCreoStrings.cs`](../scripts/ExtractCreoStrings.cs) e [`scripts/BomViaDb.cs`](../scripts/BomViaDb.cs) — stessa BFS ricorsiva standalone da riga di comando (copia indipendente della stessa euristica, nessun `ProjectReference` verso la GUI). Usati per confrontare l'euristica contro l'albero Creo di un singolo file durante il reverse engineering, senza dover passare dalla UI/dal DB `raw`. - [`scripts/ExtractCreoStrings.cs`](../scripts/ExtractCreoStrings.cs) e [`scripts/BomViaDb.cs`](../scripts/BomViaDb.cs) — stessa BFS ricorsiva standalone da riga di comando (copia indipendente della stessa euristica, nessun `ProjectReference` verso la GUI). Usati per confrontare l'euristica contro l'albero Creo di un singolo file durante il reverse engineering, senza dover passare dalla UI/dal DB `raw`.
Nota: le query contro `files_ultima_versione` filtrano solo per Nota: le query contro `files_ultima_versione` filtrano solo per
+1 -1
View File
@@ -3,7 +3,7 @@
// //
// Estrae dal file .asm i codici dei componenti referenziati, espandendo ricorsivamente // Estrae dal file .asm i codici dei componenti referenziati, espandendo ricorsivamente
// ogni sotto-assieme (.asm) trovato nell'indice, finché non restano solo PRT (foglie) o // ogni sotto-assieme (.asm) trovato nell'indice, finché non restano solo PRT (foglie) o
// codici non presenti nell'indice. Stessa euristica di CadSearchGui/AssemblyComponentScanner.cs: // codici non presenti nell'indice. Stessa euristica di PrepStep/AssemblyComponentScanner.cs:
// i codici veri compaiono più volte nel file, il rumore binario quasi sempre una sola volta; // i codici veri compaiono più volte nel file, il rumore binario quasi sempre una sola volta;
// gli ID interni "ModelView#<numero>" sono esclusi via lookbehind - vedi scripts/Analyze.cs. // gli ID interni "ModelView#<numero>" sono esclusi via lookbehind - vedi scripts/Analyze.cs.
// Ogni codice trovato viene validato contro l'indice cad_index.db. // Ogni codice trovato viene validato contro l'indice cad_index.db.