From 4931c55338ed61c6bbd26d33fa37c0821d2b50ac Mon Sep 17 00:00:00 2001 From: Jacek Pyziak Date: Fri, 24 Apr 2026 18:55:13 +0200 Subject: [PATCH] update --- .paul/governance/governance_2026-04-24.jsonl | 17 ++ .vscode/ftp-kr.sync.cache.json | 25 +++ .../akrylowa_statuetka_chrzest_wzor1.py | 165 ++++++++++++++++++ 3 files changed, 207 insertions(+) create mode 100644 .paul/governance/governance_2026-04-24.jsonl create mode 100644 tools/generowanie/akrylowa_statuetka_chrzest_wzor1.py diff --git a/.paul/governance/governance_2026-04-24.jsonl b/.paul/governance/governance_2026-04-24.jsonl new file mode 100644 index 0000000..42690ff --- /dev/null +++ b/.paul/governance/governance_2026-04-24.jsonl @@ -0,0 +1,17 @@ +{"ts":"2026-04-24T09:37:28Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\_explore_tmp.py","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-24T09:51:45Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\_rename_tmp.py","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-24T09:52:24Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\akrylowa_statuetka_chrzest_wzor1.py","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-24T09:52:41Z","tool":"Bash","cmd":"rm \"C:/visual studio code/projekty/orderPRO/tools/generowanie/_explore_tmp.py\" \"C:/visual studio code/projekty/orderPRO/tools/generowanie/_rename_tmp.py\" && echo OK\",\"description\":\"Remove temp","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-24T09:57:47Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\_inspect_tmp.py","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-24T10:04:17Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\_convert_tmp.py","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-24T10:05:00Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\akrylowa_statuetka_chrzest_wzor1.py","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-24T10:05:57Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\_fix_mapping.sql","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-24T10:07:56Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\_q_tmp.sql","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-24T10:08:23Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\_q_tmp.sql","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-24T10:08:41Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\_q_tmp.sql","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-24T10:08:55Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\_q_tmp.sql","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-24T10:11:44Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\_q_tmp.sql","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-24T10:21:21Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\_q_tmp.sql","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-24T10:22:13Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\_fetch_all_tmp.py","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-24T10:22:30Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\_fetch_all_tmp.py","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-24T10:24:19Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\_q_tmp.sql","cwd":"/c/visual studio code/projekty/orderPRO"} diff --git a/.vscode/ftp-kr.sync.cache.json b/.vscode/ftp-kr.sync.cache.json index d00d404..347fcbe 100644 --- a/.vscode/ftp-kr.sync.cache.json +++ b/.vscode/ftp-kr.sync.cache.json @@ -5829,6 +5829,12 @@ "lmtime": 1776018627219, "modified": false }, + "_explore_biblia.py": { + "type": "-", + "size": 1006, + "lmtime": 1776930569643, + "modified": false + }, "_explore_psd.py": { "type": "-", "size": 1571, @@ -5895,6 +5901,12 @@ "lmtime": 1776029385458, "modified": false }, + "magnes_wieczor_panienski_szpilka_z_kwiatami.py": { + "type": "-", + "size": 3296, + "lmtime": 0, + "modified": false + }, "prosba_chrzestny_zlota_plexi_uv.py": { "type": "-", "size": 4220, @@ -5949,6 +5961,12 @@ "lmtime": 1776763857067, "modified": false }, + "pudelko_komunia_biblia.py": { + "type": "-", + "size": 996, + "lmtime": 1776930538074, + "modified": false + }, "pudelko_komunia_chlopiec.py": { "type": "-", "size": 1020, @@ -6029,6 +6047,7 @@ "lmtime": 0, "modified": false }, + "_tmp": {}, "_tmp_diag_wzor3.py": { "type": "-", "size": 1890, @@ -6078,6 +6097,12 @@ "size": 5328, "lmtime": 1776032317220, "modified": false + }, + "_rename_biblia.py": { + "type": "-", + "size": 1329, + "lmtime": 1776930598673, + "modified": false } } }, diff --git a/tools/generowanie/akrylowa_statuetka_chrzest_wzor1.py b/tools/generowanie/akrylowa_statuetka_chrzest_wzor1.py new file mode 100644 index 0000000..316f15e --- /dev/null +++ b/tools/generowanie/akrylowa_statuetka_chrzest_wzor1.py @@ -0,0 +1,165 @@ +""" +Generator PSD — Akrylowa statuetka na Chrzest ze zdjeciem (Wzor 1). + +Plaska struktura PSD: w grupie "Projekt" znajduja sie: +- warstwy tekstowe: imie, data, zyczenia +- Smart Object "zdjecie" (placeholder na zdjecie dziecka) + +Podmiana zdjecia: +- jesli --zdjecie wskazuje na istniejacy plik graficzny -> zostaje wstawione, + przeskalowane "cover" do oryginalnych boundsow placeholdera i wycentrowane +- jesli zdjecie nie zostalo podane lub plik nie istnieje -> wstawiamy + zielony prostokat (#00FF00) jako sygnal, ze klient nie przeslal foto + +Wymaga: uruchomiony Adobe Photoshop, photoshop-python-api, Pillow. +""" + +import argparse +import os +import photoshop.api as ps + + +PROJEKT_DIR = os.path.join( + r"d:\pomysloweprezenty.pl\projekty\chrzest - pamiątki", + "Akrylowa statuetka na Chrzest - Wzór 1", +) +SZABLON_PATH = os.path.join(PROJEKT_DIR, "Akrylowa statuetka na Chrzest - Wzór 1.psd") +GOTOWE_DIR = os.path.join(PROJEKT_DIR, "_gotowe") + +ASSETS_DIR = os.path.join(os.path.dirname(__file__), "_assets") +GREEN_PLACEHOLDER_PATH = os.path.join(ASSETS_DIR, "green_placeholder.png") + +GRUPA_NAME = "Projekt" +PHOTO_SLOT = "zdjecie" + + +def ensure_green_placeholder(): + if os.path.exists(GREEN_PLACEHOLDER_PATH): + return GREEN_PLACEHOLDER_PATH + os.makedirs(ASSETS_DIR, exist_ok=True) + from PIL import Image + Image.new("RGB", (1000, 1000), (0, 255, 0)).save(GREEN_PLACEHOLDER_PATH) + return GREEN_PLACEHOLDER_PATH + + +def set_text(layer, new_text): + """Zmienia tekst zachowujac srodek bounding boxa (centrowane warstwy).""" + b = [float(x) for x in layer.bounds] + cx, cy = (b[0] + b[2]) / 2, (b[1] + b[3]) / 2 + layer.textItem.contents = new_text + b2 = [float(x) for x in layer.bounds] + cx2, cy2 = (b2[0] + b2[2]) / 2, (b2[1] + b2[3]) / 2 + dx, dy = cx - cx2, cy - cy2 + if dx or dy: + layer.translate(dx, dy) + + +def set_layer_text(container, layer_name, new_text): + if new_text is None: + return + layer = container.artLayers[layer_name] + old = layer.textItem.contents + set_text(layer, new_text) + print(f' {layer_name}: "{old}" -> "{new_text}"') + + +def replace_smart_object_contents(app, file_path): + desc = ps.ActionDescriptor() + desc.putPath(app.charIDToTypeID("null"), file_path) + desc.putInteger(app.charIDToTypeID("PgNm"), 1) + app.executeAction(app.stringIDToTypeID("placedLayerReplaceContents"), desc) + + +def replace_photo_cover(app, so_layer, photo_path): + """Podmienia zawartosc Smart Object i skaluje 'cover' do oryginalnych boundsow.""" + target = [float(x) for x in so_layer.bounds] + target_w = target[2] - target[0] + target_h = target[3] - target[1] + target_cx = (target[0] + target[2]) / 2 + target_cy = (target[1] + target[3]) / 2 + + app.activeDocument.activeLayer = so_layer + replace_smart_object_contents(app, photo_path) + + new_b = [float(x) for x in so_layer.bounds] + new_w = new_b[2] - new_b[0] + new_h = new_b[3] - new_b[1] + if new_w <= 0 or new_h <= 0: + return + + scale = max(target_w / new_w, target_h / new_h) * 100.0 + so_layer.resize(scale, scale, ps.AnchorPosition.MiddleCenter) + + cur = [float(x) for x in so_layer.bounds] + cur_cx = (cur[0] + cur[2]) / 2 + cur_cy = (cur[1] + cur[3]) / 2 + so_layer.translate(target_cx - cur_cx, target_cy - cur_cy) + + +def swap_photo(app, container, photo_path): + so_layer = container.artLayers[PHOTO_SLOT] + if photo_path and os.path.isfile(photo_path): + print(f" zdjecie: {photo_path}") + replace_photo_cover(app, so_layer, photo_path) + else: + if photo_path: + print(f" zdjecie: UWAGA plik nie istnieje ({photo_path}) - zielony placeholder") + else: + print(" zdjecie: brak - zielony placeholder") + replace_photo_cover(app, so_layer, ensure_green_placeholder()) + + +def generate(klient, imie, data, zyczenia=None, zdjecie=None): + os.makedirs(GOTOWE_DIR, exist_ok=True) + output_path = os.path.join(GOTOWE_DIR, f"{klient}.psd") + + app = ps.Application() + doc = app.open(SZABLON_PATH) + print(f"Otwarto szablon: {doc.name}") + + try: + grupa = doc.layerSets[GRUPA_NAME] + + print(" Podmiana tekstow:") + set_layer_text(grupa, "imie", imie) + set_layer_text(grupa, "data", data) + set_layer_text(grupa, "zyczenia", zyczenia) + + print(" Podmiana zdjecia:") + swap_photo(app, grupa, zdjecie) + + psd_opts = ps.PhotoshopSaveOptions() + doc.saveAs(output_path, psd_opts, True) + print(f"Zapisano: {output_path}") + finally: + try: + doc.close(ps.SaveOptions.DoNotSaveChanges) + except Exception: + pass + + print("Gotowe!") + return output_path + + +def main(): + parser = argparse.ArgumentParser( + description="Generator PSD - Akrylowa statuetka na Chrzest ze zdjeciem Wzor 1" + ) + parser.add_argument("--klient", required=True, help="Nazwa pliku wyjsciowego (bez rozszerzenia)") + parser.add_argument("--imie", required=True, help="Imie dziecka (np. 'Antosia')") + parser.add_argument("--data", required=True, help="Data chrztu (w formacie przeslanym przez klienta)") + parser.add_argument("--zyczenia", default=None, help="Tresc zyczen (opcjonalnie)") + parser.add_argument("--zdjecie", default=None, help="Sciezka do zdjecia (opcjonalnie; brak = zielony placeholder)") + + args = parser.parse_args() + generate( + klient=args.klient, + imie=args.imie, + data=args.data, + zyczenia=args.zyczenia, + zdjecie=args.zdjecie, + ) + + +if __name__ == "__main__": + main()