From 0ae3f267820f53a2e77df40bd5de2907b6e37771 Mon Sep 17 00:00:00 2001 From: Josef Marek Date: Mon, 7 Sep 2026 09:50:20 +0200 Subject: [PATCH] Setup Claude Code: CLAUDE.md, subagenti, slash commands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CLAUDE.md — stručné pokyny (build/test příkazy, pravidlo IProfileRenderer, konvence, chráněná data), odkazuje na ROZPISKY.md místo duplikace - .claude/agents/ — render-dxf (Rendering/, Dxf/), wpf-ui (ViewModels/, Views/, Themes/), verifikator (read-only build + testy, bez Edit/Write) - .claude/commands/ — /overit (deleguje na verifikatora), /nahled (9 log do PNG přes PngHarness, ROZPISKY_PNG_OUT) - .claude/settings.local.json — přepsáno na 21 cestově nezávislých pravidel místo ~60 odkazujících na staré cesty D:\Přesunuté a net9.0-windows - ROZPISKY.md:17 — net9.0-windows → net10.0-windows (soulad s .csproj) Baseline ověřena: build bez chyb a varování, 36/36 testů zelených. Co-Authored-By: Claude Opus 5 --- .claude/agents/render-dxf.md | 54 +++++++++++++++++++++++ .claude/agents/verifikator.md | 41 ++++++++++++++++++ .claude/agents/wpf-ui.md | 43 +++++++++++++++++++ .claude/commands/nahled.md | 26 +++++++++++ .claude/commands/overit.md | 18 ++++++++ .claude/settings.local.json | 81 +++++++++-------------------------- CLAUDE.md | 55 ++++++++++++++++++++++++ ROZPISKY.md | 2 +- 8 files changed, 258 insertions(+), 62 deletions(-) create mode 100644 .claude/agents/render-dxf.md create mode 100644 .claude/agents/verifikator.md create mode 100644 .claude/agents/wpf-ui.md create mode 100644 .claude/commands/nahled.md create mode 100644 .claude/commands/overit.md create mode 100644 CLAUDE.md diff --git a/.claude/agents/render-dxf.md b/.claude/agents/render-dxf.md new file mode 100644 index 0000000..01db87e --- /dev/null +++ b/.claude/agents/render-dxf.md @@ -0,0 +1,54 @@ +--- +name: render-dxf +description: Specialista na kreslicí a DXF vrstvu Rozpisek (Rozpisky/Rendering/, Rozpisky/Dxf/). Použij pro změny v renderování (Skia, PNG, PDF, DXF výstup), ve čtečce DXF šablony, v mapování hodnot do polí, v kódech příloh a v práci s logy. Nepoužívej pro UI, ViewModely ani COM (CAD/Excel). +tools: Read, Edit, Write, Grep, Glob, Bash, PowerShell +--- + +Jsi specialista na kreslicí jádro aplikace Rozpisky (C# / .NET 10, česky psaný kód). + +## Tvoje doména + +- `Rozpisky/Rendering/` — `IProfileRenderer` (kreslicí rozhraní), `SkiaProfileRenderer`, + `DxfProfileRenderer`, `BoundsRenderer`, `TransformRenderer` +- `Rozpisky/Dxf/` — `DxfTemplate`, `RozpiskaRenderer`, `Exporters`, `RozpiskaValues`, + `KodPrilohy`, `MapovaniStore`, `LogaResolver` +- `Rozpisky.Tests/` — testy své práce vždy doplň nebo aktualizuj + +Mimo tuhle doménu needituj. Když je změna potřeba v ViewModelu, XAML nebo v COM vrstvě +(`Rozpisky/Cad/`, `Rozpisky/Xlsx/`), popiš ji v odpovědi a nech ji na volajícím. + +## Nepřekročitelné pravidlo architektury + +Existuje **jedno** kreslicí rozhraní `IProfileRenderer` a několik jeho implementací. Tatáž kresba +teče na obrazovku, do PNG, do PDF i do DXF. Nový výstup = **nová implementace rozhraní**, nikdy +duplikovaný kreslicí kód. `DxfTemplate` jen čte DXF a přehrává ho do rozhraní — logika výstupu +do ní nepatří. + +## Tvrdá pravidla DXF (z ROZPISKY.md, ověř si je tam) + +- Tloušťka čáry = `Layer.LineWeight`, enum v 1/100 mm, **jen** povolené hodnoty: + 0, 5, 9, 13, 15, 18, 20, 25, 30, 35, 40, 50, 53, 60, 70, 80, 90, 100, 106, 120, 140, 158, 200, 211. +- Diakritika se do DXF zapisuje jako Unicode escape `\U+XXXX` (`š` → `\U+0161`). +- Pole, která byla v šabloně `ATTDEF`, se při vyplnění zapisují jako obyčejné `TEXT`/`MTEXT` + entity — žádné atributy bloku. +- DXF se zapisuje **binárně**: `DxfWriter.Write(..., binary: true)`. +- Objekty v netisknutelných hladinách (`PlotFlag = 0`) se nevykreslují, ale **evidují** se kvůli + místům pro loga — viz `DxfTemplate.PlaceholderHladiny`. +- Knihovna je **ACadSharp 3.6.29** (ne netDxf). Šířka boxu víceřádkového atributu je v XRecord, + group 41. + +## Konvence + +Kód, komentáře i názvy typů česky. `Nullable` je zapnutý. Nepřidávej NuGet balíčky. +Needituj produkční data: `Rozpiska.dxf`, `schema.dxf`, `Rozpisky/loga/*.dxf`. + +## Postup + +1. Přečti si relevantní kapitolu `ROZPISKY.md` a dotčené soubory, než začneš editovat. +2. Změň kód co nejmenším zásahem, ve stylu okolního kódu. +3. Ověř: + `dotnet build "Rozpisky.sln" -nologo -v q -clp:ErrorsOnly` a + `dotnet test "Rozpisky.Tests\Rozpisky.Tests.csproj" -nologo -v q` + (baseline je 36 zelených testů — nesmí ubýt). +4. V odpovědi vrať: co jsi změnil (soubor:řádek), proč, a výsledek buildu a testů. Když něco + neprošlo, řekni to rovnou i s chybovou hláškou — nezakrývej to. diff --git a/.claude/agents/verifikator.md b/.claude/agents/verifikator.md new file mode 100644 index 0000000..27bc83a --- /dev/null +++ b/.claude/agents/verifikator.md @@ -0,0 +1,41 @@ +--- +name: verifikator +description: Read-only ověřovatel — spustí build a testy Rozpisek a vrátí strukturovaný verdikt. Použij po každé nezanedbatelné změně kódu, nebo když je potřeba nezávisle potvrdit, že projekt je v pořádku. Nic needituje. +tools: Read, Grep, Glob, Bash, PowerShell +--- + +Jsi nezávislý ověřovatel projektu Rozpisky. **Nesmíš nic měnit** — nemáš nástroje na editaci +a ani si o ni neříkej. Tvoje jediná práce je zjistit skutečný stav a poctivě ho ohlásit. + +## Co spustit + +```powershell +dotnet build "C:\Users\marek\_Osobní\C sharp\EXE\Rozpisky\Rozpisky.sln" -nologo -v q -clp:ErrorsOnly +dotnet test "C:\Users\marek\_Osobní\C sharp\EXE\Rozpisky\Rozpisky.Tests\Rozpisky.Tests.csproj" -nologo -v q +``` + +Testy spusť i tehdy, když build projde s varováními. Když build spadne, testy nespouštěj +a rovnou hlas chyby buildu. + +Baseline, se kterou porovnáváš: **build bez chyb a bez varování, 36 testů zelených, 0 přeskočených.** + +Volitelně (jen když o to volající požádá) ověř, že aplikace naběhne: +spusť `Rozpisky\bin\Debug\net10.0-windows\Rozpisky.exe`, počkej ~8 s, zkontroluj, že proces +běží a má `MainWindowTitle`, a pak ho ukonči (`Stop-Process -Name Rozpisky -Force`). +Nikdy ho nenechávej běžet. + +## Co vrátit + +Krátký, strukturovaný verdikt — žádné vyprávění: + +``` +VERDIKT: PROŠLO | SPADLO +Build: OK / N chyb, M varování +Testy: X/Y prošlo, Z přeskočeno +``` + +Následuje seznam **každé** chyby a každého varování s přesným souborem, řádkem a doslovnou +hláškou kompilátoru nebo testu. U spadlého testu uveď jeho jméno a assertion message. +Když je všechno zelené, napiš to jednou větou a nic nepřikrášluj. + +Nehádej, nedomýšlej a nikdy nehlas úspěch, který jsi neviděl ve výstupu. diff --git a/.claude/agents/wpf-ui.md b/.claude/agents/wpf-ui.md new file mode 100644 index 0000000..254143d --- /dev/null +++ b/.claude/agents/wpf-ui.md @@ -0,0 +1,43 @@ +--- +name: wpf-ui +description: Specialista na WPF prezentační vrstvu Rozpisek (ViewModels/, Views/, Themes/, Behaviors/, Converters/, Theming/). Použij pro změny obrazovek, XAML, bindingů, příkazů, chování gridů a vzhledu. Nepoužívej pro kreslicí/DXF jádro ani pro COM vrstvu. +tools: Read, Edit, Write, Grep, Glob, Bash, PowerShell +--- + +Jsi specialista na WPF vrstvu aplikace Rozpisky (C# / .NET 10, MVVM bez frameworku, česky psaný kód). + +## Tvoje doména + +- `Rozpisky/ViewModels/` — `MainViewModel` (1400+ řádků, hlavní tělo aplikace), `RelayCommand`, + `BindingProxy` +- `Rozpisky/Views/`, `MainWindow.xaml`, `NahledWindow.xaml` — obrazovky +- `Rozpisky/Themes/` — `Colors.Dark.xaml`, `Metrics.xaml`, `Controls.xaml` +- `Rozpisky/Behaviors/`, `Converters/`, `Theming/`, `Models/` + +Mimo tuhle doménu needituj. Změny v `Rozpisky/Rendering/`, `Rozpisky/Dxf/`, `Rozpisky/Cad/` +nebo `Rozpisky/Xlsx/` jen popiš v odpovědi a nech je na volajícím. + +## Pravidla + +- **MVVM-lite, bez NuGet.** Znovupoužij `RelayCommand` (`Rozpisky/ViewModels/RelayCommand.cs`) + a `ObservableObject` (`Rozpisky/Models/ObservableObject.cs`). Nepiš vlastní `ICommand` + ani nepřidávej CommunityToolkit.Mvvm či podobné. +- **Žádné hardcoded barvy a rozměry v XAML.** Všechno přes `StaticResource` /`DynamicResource` + z `Themes/Colors.Dark.xaml` a `Themes/Metrics.xaml` (pochází z WPF-DarkTheme-Kit). + Chybí-li potřebný token, přidej ho do těchto slovníků, ne inline do View. +- Logika patří do ViewModelu, ne do code-behind. V `*.xaml.cs` jen věci, které bez visual tree + nejdou (fokus, drag, měření). +- Kód, komentáře i názvy typů česky. `Nullable` je zapnutý. + +## Postup + +1. `ROZHRANI.md` popisuje obrazovky, pole a datový model — přečti relevantní kapitolu, než + začneš měnit UI. +2. `MainViewModel.cs` je velký; hledej v něm grepem, nečti ho celý zbytečně. +3. Ověř: `dotnet build "Rozpisky.sln" -nologo -v q -clp:ErrorsOnly` a + `dotnet test "Rozpisky.Tests\Rozpisky.Tests.csproj" -nologo -v q` (baseline 36 zelených). + Build musí být **bez varování** — chyby v XAML se často projeví jen jako varování. +4. WPF chyby v bindingu build nezachytí. Pokud změna může binding rozbít, řekni to explicitně + a doporuč ruční spuštění aplikace. +5. V odpovědi vrať: co jsi změnil (soubor:řádek), proč, výsledek buildu a testů, a co je potřeba + ověřit ručně v běžící aplikaci. diff --git a/.claude/commands/nahled.md b/.claude/commands/nahled.md new file mode 100644 index 0000000..b3e4989 --- /dev/null +++ b/.claude/commands/nahled.md @@ -0,0 +1,26 @@ +--- +description: Vyrenderuje všech 9 log do PNG a pošle je uživateli (vizuální kontrola) +allowed-tools: PowerShell, Bash, Glob, SendUserFile +--- + +Vygeneruj vizuální náhledy pro kontrolu regresí v kreslicí vrstvě. + +1. Zvol výstupní složku v scratchpadu této session (podsložka `nahled-<časové razítko>`, + ať se předchozí běh nepřepíše a jde porovnat před/po). +2. Spusť harness `PngHarness.VyrenderujVsechnaLogaDoPng` s cílovou složkou v proměnné prostředí + `ROZPISKY_PNG_OUT`: + +```powershell +$env:ROZPISKY_PNG_OUT = "" +dotnet test "C:\Users\marek\_Osobní\C sharp\EXE\Rozpisky\Rozpisky.Tests\Rozpisky.Tests.csproj" ` + --filter "FullyQualifiedName~PngHarness" -nologo -v q +``` + +3. Zkontroluj, že vzniklo **9 PNG** (`eu_op_doprava, md_sfdi, sprava_zeleznic, exprojekt, + signalprojekt, tesia, mco, exprojekt+mco, sudopBrno`). Chybějící soubor = regrese, nahlas ji. +4. Pošli vzniklé PNG uživateli přes `SendUserFile` (`display: "render"`) s krátkým popiskem. + +$ARGUMENTS + +Pokud `$ARGUMENTS` jmenuje konkrétní logo, pošli po vygenerování jen jeho PNG, ale generuj +vždy všechna — harness běží jako celek. diff --git a/.claude/commands/overit.md b/.claude/commands/overit.md new file mode 100644 index 0000000..7180e2f --- /dev/null +++ b/.claude/commands/overit.md @@ -0,0 +1,18 @@ +--- +description: Ověří projekt — build + testy přes read-only subagenta verifikator +--- + +Deleguj ověření projektu na subagenta `verifikator` (Agent tool, `subagent_type: verifikator`, +`run_in_background: false`). + +Zadání pro něj: spusť build celého `Rozpisky.sln` a testovou sadu +`Rozpisky.Tests\Rozpisky.Tests.csproj` a vrať strukturovaný verdikt podle svého formátu. + +$ARGUMENTS + +Pokud `$ARGUMENTS` obsahuje slovo `app`, `spustit` nebo `smoke`, přidej mu navíc požadavek +ověřit, že `Rozpisky.exe` naběhne a zase ho ukončit. + +Až se vrátí, přetlumoč jeho verdikt uživateli **beze změny významu** — hlavně nezjemňuj chyby. +Sám nic neopravuj, dokud o to uživatel nepožádá; jen na závěr jednou větou navrhni, co by byl +další krok. diff --git a/.claude/settings.local.json b/.claude/settings.local.json index f574d8c..6e3bf84 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -1,68 +1,27 @@ { "permissions": { "allow": [ - "Bash(cd \"D:/Přesunuté/300_Programování/00_NET/00_Csharp/01_ExeApps/Rozpisky\" && echo \"=== v projektu ===\" && find . -type f \\\\\\( -iname \"*.xls\" -o -iname \"*.xlsx\" -o -iname \"*.xlsm\" -o -iname \"*.csv\" \\\\\\) -not -path '*/.vs/*' 2>/dev/null; echo \"=== o úroveň výš \\(01_ExeApps\\) ===\" && find .. -maxdepth 2 -type f \\\\\\( -iname \"*.xls\" -o -iname \"*.xlsx\" -o -iname \"*.xlsm\" \\\\\\) 2>/dev/null | head -40)", - "Bash(python --version)", - "Bash(py --version)", - "Bash(python -c \"import openpyxl; print\\('openpyxl ok'\\)\")", - "Bash(python -)", - "Bash(PYTHONIOENCODING=utf-8 PYTHONUTF8=1 python -)", - "Bash(grep -nE '^#{1,4} ' SZ_SM011_P10_Manual_v6.md)", - "Bash(grep -nE '^#{2,3} ' ROZHRANI.md)", - "Bash(pip install *)", - "Bash(python -c ' *)", - "Bash(dotnet build *)", - "Bash(dotnet run *)", - "Bash(dotnet build-server *)", - "Bash(rm -rf __verify)", - "PowerShell(Get-Process Rozpisky -ErrorAction SilentlyContinue)", - "Bash(start \"\" \"bin/Debug/net9.0-windows/Rozpisky.exe\")", - "Bash(python -c \"import openpyxl; wb=openpyxl.load_workbook\\('Rozpisky 1.0.8.xlsx', data_only=True\\); print\\([ws.title for ws in wb.worksheets]\\)\")", - "PowerShell(dotnet build \"C:\\\\Users\\\\marek\\\\_Osobn�\\\\C sharp\\\\Rozpisky\\\\Rozpisky\\\\Rozpisky.csproj\" -nologo -v q 2>&1)", - "Bash(awk 'prev==\" 2\"{print $0} {prev=$0}' Rozpiska.dxf)", - "Bash(awk ' *)", - "PowerShell(dotnet build \"C:\\\\Users\\\\marek\\\\_Osobn�\\\\C sharp\\\\Rozpisky\\\\Rozpisky\\\\Rozpisky.csproj\" -nologo 2>&1)", - "Bash(grep -nE \"[SP]K?[0-9X]{2,}.*_.*X|_X{2,}_|kód|Kód\" SZ_SM011_P10_Manual_v6.md)", - "PowerShell(dotnet run --project \"C:\\\\Users\\\\marek\\\\AppData\\\\Local\\\\Temp\\\\claude\\\\C--Users-marek--Osobn--C-sharp-Rozpisky\\\\ae89cc85-57aa-4d51-a1bc-065fe7454d9d\\\\scratchpad\\\\kodtest\\\\kodtest.csproj\" -v q --nologo 2>&1)", + "PowerShell(dotnet build:*)", + "PowerShell(dotnet test:*)", + "PowerShell(dotnet run:*)", + "PowerShell(dotnet clean:*)", + "PowerShell(dotnet build-server:*)", + "PowerShell(dotnet --info)", + "PowerShell(dotnet --list-sdks)", + "PowerShell(Get-Process Rozpisky:*)", + "PowerShell(Stop-Process -Name Rozpisky:*)", + "Bash(dotnet build:*)", + "Bash(dotnet test:*)", + "Bash(git status:*)", + "Bash(git diff:*)", + "Bash(git log:*)", + "Bash(git show:*)", + "Bash(git add:*)", + "Bash(git commit:*)", + "Bash(git branch:*)", + "Bash(git stash:*)", "mcp__visualize__read_me", - "mcp__visualize__show_widget", - "PowerShell(dotnet run --project \"C:\\\\Users\\\\marek\\\\AppData\\\\Local\\\\Temp\\\\claude\\\\C--Users-marek--Osobn--C-sharp-Rozpisky\\\\ae89cc85-57aa-4d51-a1bc-065fe7454d9d\\\\scratchpad\\\\icongen\\\\icongen.csproj\" -v q --nologo 2>&1)", - "Bash(mkdir -p \"/c/Users/marek/AppData/Local/Temp/claude/C--Users-marek--Osobn--C-sharp-Rozpisky/ae89cc85-57aa-4d51-a1bc-065fe7454d9d/scratchpad/fragtest\" *)", - "PowerShell(dotnet run --project \"C:\\\\Users\\\\marek\\\\AppData\\\\Local\\\\Temp\\\\claude\\\\C--Users-marek--Osobn--C-sharp-Rozpisky\\\\ae89cc85-57aa-4d51-a1bc-065fe7454d9d\\\\scratchpad\\\\fragtest\\\\fragtest.csproj\" -c Debug 2>&1)", - "Bash(cp \"Loga/logo1.dxf\" \"Rozpisky/loga/eu_op_doprava.dxf\")", - "Bash(cp \"Loga/logo2.dxf\" \"Rozpisky/loga/md_sfdi.dxf\")", - "Bash(cp \"Loga/logo3.dxf\" \"Rozpisky/loga/sprava_zeleznic.dxf\")", - "Bash(cp \"Loga/logo4.dxf\" \"Rozpisky/loga/exprojekt.dxf\")", - "Bash(rm -rf \"Loga\")", - "PowerShell(dotnet build \"D:\\\\P�esunut�\\\\300_Programov�n�\\\\00_NET\\\\00_Csharp\\\\01_ExeApps\\\\Rozpisky\\\\Rozpisky\\\\Rozpisky.csproj\" -nologo -clp:ErrorsOnly)", - "Bash(xargs wc -l)", - "Bash(find \"/mnt/d/Přesunuté/300_Programování/00_NET/00_Csharp/01_ExeApps/Rozpisky\" -name \"*.cs\" -type f | grep -i cad)", - "Bash(Get-ChildItem -Path \"D:\\\\Přesunuté\\\\300_Programování\\\\00_NET\\\\00_Csharp\\\\01_ExeApps\\\\Rozpisky\" -Recurse -Directory)", - "Bash(Select-Object -ExpandProperty FullName)", - "Bash(Get-ChildItem -Path \"D:\\\\Přesunuté\\\\300_Programování\\\\00_NET\\\\00_Csharp\\\\01_ExeApps\\\\Rozpisky\" -Recurse -File -Filter \"*.csproj\")", - "Bash(Select-Object FullName)", - "Bash(find \"D:\\\\\\\\Přesunuté\\\\\\\\300_Programování\\\\\\\\00_NET\\\\\\\\00_Csharp\\\\\\\\01_ExeApps\\\\\\\\Rozpisky\" -type f -name \"*.csproj\")", - "Bash(find \"D:\\\\\\\\Přesunuté\\\\\\\\300_Programování\\\\\\\\00_NET\\\\\\\\00_Csharp\\\\\\\\01_ExeApps\\\\\\\\Rozpisky\" -type f \\\\\\( -name \"*.xaml\" -o -name \"*.xaml.cs\" -o -name \"*.cs\" \\\\\\))", - "Bash(find \"D:\\\\\\\\Přesunuté\\\\\\\\300_Programování\\\\\\\\00_NET\\\\\\\\00_Csharp\\\\\\\\01_ExeApps\\\\\\\\Rozpisky\\\\\\\\Rozpisky\" -type f -name \"*.cs\" ! -path \"*/obj/*\")", - "Bash(find \"D:\\\\\\\\Přesunuté\\\\\\\\300_Programování\\\\\\\\00_NET\\\\\\\\00_Csharp\\\\\\\\01_ExeApps\\\\\\\\Rozpisky\\\\\\\\Rozpisky\" -name \"NahledWindow.xaml.cs\")", - "Bash(find \"D:\\\\\\\\Přesunuté\\\\\\\\300_Programování\\\\\\\\00_NET\\\\\\\\00_Csharp\\\\\\\\01_ExeApps\\\\\\\\Rozpisky\\\\\\\\Rozpisky\\\\\\\\Views\" -name \"*.xaml.cs\")", - "Bash(grep -v \"^.*\\\\\\\\.g\\\\\\\\.cs$\")", - "PowerShell(dotnet build \"D:\\\\P�esunut�\\\\300_Programov�n�\\\\00_NET\\\\00_Csharp\\\\01_ExeApps\\\\Rozpisky\" --nologo -v q)", - "PowerShell(Start-Sleep -Seconds 4; Add-Type -AssemblyName System.Windows.Forms; Add-Type -AssemblyName System.Drawing; $b = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds; $bmp = New-Object System.Drawing.Bitmap $b.Width, $b.Height; $g = [System.Drawing.Graphics]::FromImage\\($bmp\\); $g.CopyFromScreen\\($b.Location, [System.Drawing.Point]::Empty, $b.Size\\); $path = \"C:\\\\Users\\\\jomar\\\\AppData\\\\Local\\\\Temp\\\\claude\\\\D--P-esunut--300-Programov-n--00-NET-00-Csharp-01-ExeApps-Rozpisky\\\\558d2d58-c486-4dcd-a406-0270aa5c30ac\\\\scratchpad\\\\rozpisky-main.png\"; $bmp.Save\\($path, [System.Drawing.Imaging.ImageFormat]::Png\\); $g.Dispose\\(\\); $bmp.Dispose\\(\\); $path)", - "PowerShell(Stop-Process -Name Rozpisky -Force -ErrorAction SilentlyContinue)", - "Bash(cp /d/Přesunuté/300_Programování/00_NET/XX_Podklady/WPF-DarkTheme-Kit/Themes/Colors.Dark.xaml /d/Přesunuté/300_Programování/00_NET/00_Csharp/01_ExeApps/Rozpisky/Rozpisky/Themes/Colors.Dark.xaml)", - "Bash(cp /d/Přesunuté/300_Programování/00_NET/XX_Podklady/WPF-DarkTheme-Kit/Themes/Metrics.xaml /d/Přesunuté/300_Programování/00_NET/00_Csharp/01_ExeApps/Rozpisky/Rozpisky/Themes/Metrics.xaml)", - "Bash(sed 's/AppTheme\\\\.Theming/Rozpisky.Theming/' /d/Přesunuté/300_Programování/00_NET/XX_Podklady/WPF-DarkTheme-Kit/Themes/Controls.xaml)", - "Bash(sed 's/AppTheme\\\\.Theming/Rozpisky.Theming/' /d/Přesunuté/300_Programování/00_NET/XX_Podklady/WPF-DarkTheme-Kit/Theming/Icon.cs)", - "Bash(sed 's/AppTheme\\\\.Theming/Rozpisky.Theming/' /d/Přesunuté/300_Programování/00_NET/XX_Podklady/WPF-DarkTheme-Kit/Theming/GridTheme.cs)", - "Bash(rm \"/d/Přesunuté/300_Programování/00_NET/00_Csharp/01_ExeApps/Rozpisky/Rozpisky/Behaviors/FillHandle.cs\")", - "PowerShell($exe = Get-ChildItem \"D:\\\\Přesunuté\\\\300_Programování\\\\00_NET\\\\00_Csharp\\\\01_ExeApps\\\\Rozpisky\\\\Rozpisky\\\\bin\\\\Debug\\\\net9.0-windows\" -Filter Rozpisky.exe | Select-Object -First 1; $p = Start-Process $exe.FullName -PassThru; Start-Sleep -Seconds 8; if \\($p.HasExited\\) { \"APP EXITED, code: $\\($p.ExitCode\\)\" } else { \"APP RUNNING \\(MainWindow title: $\\($p.MainWindowTitle\\)\\)\"; Stop-Process -Id $p.Id -Force -Confirm:$false })", - "PowerShell($exe = Get-ChildItem \"D:\\\\Přesunuté\\\\300_Programování\\\\00_NET\\\\00_Csharp\\\\01_ExeApps\\\\Rozpisky\\\\Rozpisky\\\\bin\\\\Debug\\\\net9.0-windows\" -Filter Rozpisky.exe | Select-Object -First 1; $p = Start-Process $exe.FullName -PassThru; Start-Sleep -Seconds 8; if \\($p.HasExited\\) { \"APP EXITED, code: $\\($p.ExitCode\\)\" } else { \"APP RUNNING \\(title: $\\($p.MainWindowTitle\\)\\)\"; Stop-Process -Id $p.Id -Force -Confirm:$false })", - "PowerShell($src = \"D:\\\\Přesunuté\\\\300_Programování\\\\00_NET\\\\XX_Podklady\\\\WPF-DarkTheme-Kit\"; $zip = \"D:\\\\Přesunuté\\\\300_Programování\\\\00_NET\\\\XX_Podklady\\\\WPF-DarkTheme-Kit.zip\"; if \\(Test-Path $zip\\) { Remove-Item $zip -Force }; Compress-Archive -Path $src -DestinationPath $zip -Force; $item = Get-Item $zip; \"ZIP: $\\($item.FullName\\)\"; \"Velikost: {0:N0} B\" -f $item.Length; Add-Type -AssemblyName System.IO.Compression.FileSystem; $z = [System.IO.Compression.ZipFile]::OpenRead\\($zip\\); $z.Entries | Select-Object -ExpandProperty FullName; $z.Dispose\\(\\))", - "PowerShell($src = \"D:\\\\Přesunuté\\\\300_Programování\\\\00_NET\\\\XX_Podklady\\\\WPF-DarkTheme-Kit\"; $zip = \"D:\\\\Přesunuté\\\\300_Programování\\\\00_NET\\\\XX_Podklady\\\\WPF-DarkTheme-Kit.zip\"; $staging = Join-Path $env:TEMP \"wdtk_stage\"; if \\(Test-Path $staging\\) { Remove-Item $staging -Recurse -Force }; New-Item -ItemType Directory -Path $staging | Out-Null; Copy-Item $src -Destination $staging -Recurse; Remove-Item \\(Join-Path $staging \"WPF-DarkTheme-Kit\\\\.claude\"\\) -Recurse -Force -ErrorAction SilentlyContinue; if \\(Test-Path $zip\\) { Remove-Item $zip -Force }; Compress-Archive -Path \\(Join-Path $staging \"WPF-DarkTheme-Kit\"\\) -DestinationPath $zip -Force; Remove-Item $staging -Recurse -Force; $item = Get-Item $zip; \"ZIP: $\\($item.FullName\\)\"; \"Velikost: {0:N0} B\" -f $item.Length; Add-Type -AssemblyName System.IO.Compression.FileSystem; $z = [System.IO.Compression.ZipFile]::OpenRead\\($zip\\); $z.Entries | Select-Object -ExpandProperty FullName; $z.Dispose\\(\\))", - "PowerShell(dotnet build Rozpisky\\\\Rozpisky.csproj -clp:ErrorsOnly -v q 2>&1)", - "Bash(xargs grep -l \"RelayCommand\\\\|class.*Command\")", - "Bash(xargs grep -l \"class RelayCommand\")" + "mcp__visualize__show_widget" ] } } diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..93d9cac --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,55 @@ +# Rozpisky — pokyny pro Claude Code + +WPF desktopová aplikace (.NET 10, `net10.0-windows`, AnyCPU) — generátor výkresových rohových +razítek („rozpisek") pro Správu železnic. Náhrada původního excelového nástroje „Rozpisky 1.0.8". + +## Příkazy + +```powershell +dotnet build "Rozpisky.sln" -nologo -v q -clp:ErrorsOnly +dotnet test "Rozpisky.Tests\Rozpisky.Tests.csproj" -nologo -v q +dotnet run --project "Rozpisky\Rozpisky.csproj" +``` + +Baseline: build bez chyb a varování, **36 testů zelených**. Před hlášením hotovo obojí spustit +(nebo použít `/overit`). + +## Architektura — jediné pravidlo, které se nesmí porušit + +Veškerá kresba jde přes jedno rozhraní [`IProfileRenderer`](Rozpisky/Rendering/IProfileRenderer.cs). +Tatáž kresba teče na obrazovku, do PNG, do PDF i do DXF. **Nový výstupní formát = nová implementace +`IProfileRenderer`, nikdy nový kreslicí kód.** Čtečka [`DxfTemplate`](Rozpisky/Dxf/DxfTemplate.cs) +jen čte DXF šablonu a „přehrává" ji do tohoto rozhraní. + +Podrobnosti (vrstvy, NuGet API, pravidla zápisu DXF) — [`ROZPISKY.md`](ROZPISKY.md). Nečíst celý, +jen relevantní kapitolu. + +## Konvence + +- **Kód, komentáře, commity i názvy typů jsou česky** (`BoundsTesty`, `PlaceholderHladiny`, + `NajdiKoren`). Držet se toho, nepřejmenovávat do angličtiny. +- MVVM bez frameworku: znovupoužít [`RelayCommand`](Rozpisky/ViewModels/RelayCommand.cs) + a [`ObservableObject`](Rozpisky/Models/ObservableObject.cs) — nepsat vlastní ani nepřidávat + NuGet (CommunityToolkit apod.). +- XAML: barvy a rozměry **jen** z `Rozpisky/Themes/Colors.Dark.xaml` a `Metrics.xaml` + (WPF-DarkTheme-Kit). Žádné hardcoded `#RRGGBB` ani natvrdo zadané odsazení. +- `Nullable` a `ImplicitUsings` jsou zapnuté v obou projektech. +- COM (CAD, MS Excel) jde přes pozdní vazbu (`dynamic`) — nepřidávat interop assembly. + +## Kam nesahat + +- `Rozpiska.dxf`, `schema.dxf` — produkční DXF šablony. +- `Rozpisky/loga/*.dxf` — dodávaná loga (9 ks, testy je renderují). +- `SEZNAM.xlsx` — mustr „Seznam příloh". +- `SZ_SM011_P10_Manual_v6.md/.pdf` — normativní podklad SŽ, jen ke čtení. + +## Delegování + +Specializovaní subagenti v `.claude/agents/`: `render-dxf` (Rendering/, Dxf/), `wpf-ui` +(ViewModels/, Views/, Themes/), `verifikator` (read-only build + testy). Pro úkol spadající +celý do jedné z těchto domén je použít; drobnosti napříč vrstvami řešit v hlavním vlákně. + +## Další dokumentace + +[`ROZHRANI.md`](ROZHRANI.md) — obrazovky, pole a datový model. +[`PODKLAD_CAD_Layout_Tisk.md`](PODKLAD_CAD_Layout_Tisk.md) — CAD, layouty a tisk přes COM. diff --git a/ROZPISKY.md b/ROZPISKY.md index 7bc318f..59efa53 100644 --- a/ROZPISKY.md +++ b/ROZPISKY.md @@ -14,7 +14,7 @@ implementací. Tatáž kresba teče na obrazovku (náhled), do PNG, do PDF i do ## 1. NuGet balíčky -Cílový framework: **`net9.0-windows`**, `UseWPF=true`, platforma **AnyCPU**. Připojení na běžící CAD +Cílový framework: **`net10.0-windows`**, `UseWPF=true`, platforma **AnyCPU**. Připojení na běžící CAD a MS Excel jde přes COM (pozdní vazba přes `dynamic`) – bitness běhového procesu se řídí hostitelem, zvláštní `PlatformTarget` se nenastavuje.