From d5b630a7930d981b51747e082e1bbce7e61962d4 Mon Sep 17 00:00:00 2001 From: "vladimir.buzalka" Date: Mon, 18 May 2026 11:21:13 +0200 Subject: [PATCH] z230 --- CLAUDE.md | 18 ++++++++++ RozkladScanu/NOTES.md | 23 +++++++++++- RozkladScanu/navrh_pojmenovani.py | 50 +++++++++++++++++++++++--- RozkladScanu/pojmenovani_historie.json | 14 ++++++++ RozkladScanu/rozloz_brozuru.py | 32 +++++++++++++---- 5 files changed, 125 insertions(+), 12 deletions(-) create mode 100644 RozkladScanu/pojmenovani_historie.json diff --git a/CLAUDE.md b/CLAUDE.md index 7af7779..df386df 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -11,6 +11,24 @@ Worktree (`.claude/worktrees/*`) slouží jen pro interní práci Claude, ne jak Každý adresář se skriptem má vlastní `NOTES.md` s technickými detaily. Přečti relevantní NOTES.md podle toho, čeho se konverzace týká. +## Anthropic API klíč + +Uložen v `Medevio/.env` jako `ANTHROPIC_API_KEY=sk-ant-...`. +Skripty, které volají Claude API, si ho načítají samy — vzor: + +```python +def _load_env(): + env_path = Path(__file__).resolve().parent.parent / "Medevio" / ".env" + if env_path.exists(): + for line in env_path.read_text(encoding="utf-8").splitlines(): + line = line.strip() + if "=" in line and not line.startswith("#"): + k, v = line.split("=", 1) + os.environ[k.strip()] = v.strip() + +_load_env() +``` + ## Sdílené knihovny (`Knihovny/`) Před psaním nového kódu vždy zkontroluj, zda existuje vhodná sdílená funkce. diff --git a/RozkladScanu/NOTES.md b/RozkladScanu/NOTES.md index 5591338..1f78bf2 100644 --- a/RozkladScanu/NOTES.md +++ b/RozkladScanu/NOTES.md @@ -4,11 +4,32 @@ Univerzální skript pro oba druhy skenování níže. Vše se odvodí automaticky z PDF. +**Dávkový režim (bez argumentů)** — zpracuje všechna PDF ve `vstup/`: +``` +python rozloz_brozuru.py +``` +- Výstup jde do `vystup/_serazena.pdf` +- Po úspěchu se vstupní soubor přejmenuje: ` [ZPRACOVANO].pdf` +- Soubory s `[ZPRACOVANO]` v názvu jsou přeskočeny +- Chyba u jednoho souboru nezastaví zpracování ostatních + +**Explicitní argumenty** (zachována zpětná kompatibilita): ``` python rozloz_brozuru.py vstup/ vystup/ ``` -Pokud není zadán výstup, pojmenuje se `_serazena.pdf` ve stejném adresáři jako vstup. +## Skript: `navrh_pojmenovani.py` + +Vezme prvních 5 stránek PDF, pošle je Claude API jako obrázky, navrhne název souboru. + +``` +python navrh_pojmenovani.py +``` +- Bez argumentu otevře dialog pro výběr souboru (výchozí adresář: `vystup/`) +- Název vždy začíná `YYYY-MM-DD_` +- Dialog umožní opravit návrh; historie se ukládá do `pojmenovani_historie.json` +- Pokud Claude navrhne stejné jméno jako posledně, dialog se předvyplní předchozí uživatelovou volbou +- API klíč se načítá z `../Medevio/.env` --- diff --git a/RozkladScanu/navrh_pojmenovani.py b/RozkladScanu/navrh_pojmenovani.py index 09752c9..e4fefb8 100644 --- a/RozkladScanu/navrh_pojmenovani.py +++ b/RozkladScanu/navrh_pojmenovani.py @@ -11,16 +11,30 @@ Pouziti: """ import sys +import os import json import base64 import io import copy import tkinter as tk +from tkinter import filedialog from pathlib import Path from datetime import date import fitz # pymupdf import anthropic + +def _load_env(): + env_path = Path(__file__).resolve().parent.parent / "Medevio" / ".env" + if env_path.exists(): + for line in env_path.read_text(encoding="utf-8").splitlines(): + line = line.strip() + if "=" in line and not line.startswith("#"): + k, v = line.split("=", 1) + os.environ[k.strip()] = v.strip() + +_load_env() + HISTORY_FILE = Path(__file__).parent / "pojmenovani_historie.json" N_PAGES = 5 DPI = 120 # dostatecne pro cteni obsahu, nizke naklady na tokeny @@ -151,12 +165,29 @@ def dialog(claude_suggestion: str) -> dict: # ---------- hlavni logika ---------- +def pick_file() -> Path | None: + """Otevre dialog pro vyber PDF souboru.""" + root = tk.Tk() + root.withdraw() + root.attributes("-topmost", True) + chosen = filedialog.askopenfilename( + title="Vyber PDF k pojmenovani", + filetypes=[("PDF soubory", "*.pdf"), ("Vsechny soubory", "*.*")], + initialdir=Path(__file__).parent / "vystup", + ) + root.destroy() + return Path(chosen) if chosen else None + + def main(): if len(sys.argv) < 2: - print(__doc__) - sys.exit(1) + pdf_path = pick_file() + if pdf_path is None: + print("Zadny soubor nebyl vybran.") + sys.exit(0) + else: + pdf_path = Path(sys.argv[1]) - pdf_path = Path(sys.argv[1]) if not pdf_path.exists(): print(f"Soubor nenalezen: {pdf_path}") sys.exit(1) @@ -177,13 +208,22 @@ def main(): claude_name = ask_claude(images, history) print(f" Claude navrhuje: {claude_name}") - res = dialog(claude_name) + # Pokud uz jsme tento soubor pojmenovavali (Claude navrhl stejne jmeno), + # predvyplnime dialog predchozi volbou uzivatele. + prefill = claude_name + for item in reversed(history): + if item["claude"] == claude_name: + prefill = item["user"] + print(f" Znamy dokument — predvyplnuji predchozi nazev: {prefill}") + break + + res = dialog(prefill) if res["cancelled"] or not res["name"]: print("Zruseno — soubor nebyl prejmenovan.") return - user_name = res["name"] + user_name = res["name"].replace("/", "-").replace("\\", "-").strip() # uloz do historie history.append({"claude": claude_name, "user": user_name}) diff --git a/RozkladScanu/pojmenovani_historie.json b/RozkladScanu/pojmenovani_historie.json new file mode 100644 index 0000000..b51925b --- /dev/null +++ b/RozkladScanu/pojmenovani_historie.json @@ -0,0 +1,14 @@ +[ + { + "claude": "2026-05-18_bulletin-spl-cr-2-2026", + "user": "2026-05-18 Bulletin SPL ČR 02/2026 36. ročník" + }, + { + "claude": "2026-05-18_bulletin-spl-cr-2-2026", + "user": "2026-05-18 Bulletin SPL ČR 02-2026 36. ročník" + }, + { + "claude": "2026-05-18_navimow-i-series-quick-start-guide", + "user": "2026-05-18 Navimow i-series quick start guide" + } +] \ No newline at end of file diff --git a/RozkladScanu/rozloz_brozuru.py b/RozkladScanu/rozloz_brozuru.py index c4a4aca..4aa44c0 100644 --- a/RozkladScanu/rozloz_brozuru.py +++ b/RozkladScanu/rozloz_brozuru.py @@ -12,6 +12,7 @@ Pouziti: import sys import copy +from pathlib import Path from pypdf import PdfReader, PdfWriter from pypdf.generic import RectangleObject @@ -67,10 +68,29 @@ def rozloz(input_path, output_path): if __name__ == "__main__": - if len(sys.argv) < 2: - print("Pouziti: python rozloz_brozuru.py [vystup.pdf]") - sys.exit(1) + BASE = Path(__file__).parent + VSTUP = BASE / "vstup" + VYSTUP = BASE / "vystup" + VYSTUP.mkdir(exist_ok=True) - inp = sys.argv[1] - out = sys.argv[2] if len(sys.argv) > 2 else inp.replace(".pdf", "_serazena.pdf") - rozloz(inp, out) + if len(sys.argv) >= 2: + # explicitni argumenty zachovany pro zpetnou kompatibilitu + inp = sys.argv[1] + out = sys.argv[2] if len(sys.argv) > 2 else inp.replace(".pdf", "_serazena.pdf") + rozloz(inp, out) + else: + pdfs = [f for f in VSTUP.glob("*.pdf") if "[ZPRACOVANO]" not in f.name] + if not pdfs: + print("Zadne PDF soubory ke zpracovani ve vstup/") + sys.exit(0) + + for pdf in pdfs: + out = VYSTUP / (pdf.stem + "_serazena.pdf") + print(f"\n=== {pdf.name} ===") + try: + rozloz(str(pdf), str(out)) + done = pdf.with_name(pdf.stem + " [ZPRACOVANO]" + pdf.suffix) + pdf.rename(done) + print(f"Vstupni soubor oznacen: {done.name}") + except Exception as e: + print(f"CHYBA: {e}")