Gasite de un verificator care nu scrisese documentele, aplicate de un corector separat de amandoi. Tiparul dominant, patru din zece: inferenta autorului pusa in coloana „rostit de curs" a diagramei rani_masti. Cuvantul „stop" nu apare deloc in transcrierea workshop-ului 5 (singura ocurenta e „Recording stopped"), dar „muti stopul" statea in negru, ca si cum l-ar fi spus cursul. Mutate in albastru, ca derivatii. Cea mai utila: emendarea „o sa va [im]bolnaviti" era gresita. Transcrierea spune „o sa va vindecati in timp de chestia asta", iar asta e sensul corect - „a se vindeca DE ceva" = o sa va treaca. Workshop 1 o confirma: „o sa va plictisiti si nu o sa mai vreti sa faceti day trading". Citatul e pus la loc neatins. Restul: titlu de carte inventat, „un minut" care nu e in sursa, ordinea grupelor data ca a cursului, o enumerare de trei acolo unde sursa numara doua, si o sageata de diagrama care cadea pe „comportament" desi eticheta spunea „gand" (acum legata prin assert de caseta tinta). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ThN7ixZrowca8aTGrK1MUJ
269 lines
14 KiB
Python
269 lines
14 KiB
Python
"""Cele trei scheme din summaries/06_MODUL_5/06_workshop_5_copilul_interior.md.
|
||
|
||
Workshop de psihologie: nu există preț, deci nu există candele. Schemele sunt
|
||
doar structuri (lanțul de decizie, maparea rană -> mască -> greșeală de
|
||
execuție, axa de vârstă a etapelor). Se generează de aici ca să existe un
|
||
singur loc unde se schimbă o etichetă și ca să treacă prin assert-urile de
|
||
lățime — nu se editează SVG-ul din .md.
|
||
|
||
Rulează: .venv/bin/python gen/workshop_5_copilul_interior.py
|
||
"""
|
||
import re
|
||
from pathlib import Path
|
||
|
||
MD = Path("/workspace/atm-curs-dl/summaries/06_MODUL_5/06_workshop_5_copilul_interior.md")
|
||
GRAY, RED, GREEN, BLUE, ORANGE = "#777", "#c00", "#188a3e", "#1a5fb4", "#b06000"
|
||
INK, MUTED, LINE, FILL = "#333", "#666", "#9bb0c7", "#f7f9fb"
|
||
CHAR_W = 5.7 # px/caracter la 12px sans-serif, calibrat ca în audit_diagrams.py
|
||
svgs = {}
|
||
|
||
|
||
def fits(txt: str, box_w: float, fs: float = 12.0) -> str:
|
||
"""Text care intră în lățimea dată la font-size-ul dat, altfel assert."""
|
||
w = len(txt) * CHAR_W * fs / 12.0
|
||
assert w <= box_w, f"text de {w:.0f}px în {box_w:.0f}px: {txt!r}"
|
||
return txt
|
||
|
||
|
||
# --------------------------------------------------------------- 1. lanțul de decizie
|
||
FILTRE = ["filtrele VAKOG — vizual, auditiv, kinestezic",
|
||
"valorile și credințele (unele limitative)",
|
||
"experiențele, cu rănile emoționale din ele"]
|
||
LANT2 = [("gând", '„iar m-a trădat piața"'),
|
||
("emoție", "furie"),
|
||
("comportament", "intri în revanșă"),
|
||
("rezultat", "a doua pierdere")]
|
||
BOX2_X = [14 + 172 * k for k in range(len(LANT2))]
|
||
BOX2_W = 152
|
||
# caseta în care intră săgeata care coboară din „reprezentare mentală"
|
||
ARROW_TARGET = 0
|
||
X_ARR = BOX2_X[ARROW_TARGET] + BOX2_W / 2
|
||
|
||
|
||
def lant_rana() -> str:
|
||
p = ['<svg viewBox="0 0 700 330" xmlns="http://www.w3.org/2000/svg"'
|
||
' style="width:100%;height:auto;font:12px sans-serif">',
|
||
f'<text x="14" y="22" fill="{INK}" style="font-weight:bold">Formula de'
|
||
' funcționare reluată la începutul workshopului — rana stă în a doua'
|
||
' casetă</text>']
|
||
# stimul extern
|
||
p += [f'<rect x="14" y="40" width="150" height="56" fill="{FILL}"'
|
||
f' stroke="{LINE}" stroke-width="1"/>',
|
||
f'<text x="24" y="60" fill="{INK}" style="font-weight:bold">'
|
||
f'{fits("stimul extern", 130)}</text>',
|
||
f'<text x="24" y="78" fill="{MUTED}" font-size="10">'
|
||
f'{fits("tot ce e în afara pielii", 130, 10)}</text>',
|
||
f'<text x="24" y="90" fill="{MUTED}" font-size="10">'
|
||
f'{fits("ex: piața îți ia stopul", 130, 10)}</text>']
|
||
p += [f'<line x1="166" y1="68" x2="196" y2="68" stroke="{LINE}" stroke-width="1.5"/>',
|
||
f'<path d="M 190 64 L 198 68 L 190 72 Z" fill="{LINE}"/>']
|
||
# reprezentare mentală, cu filtrele
|
||
p += [f'<rect x="200" y="40" width="330" height="96" fill="{BLUE}"'
|
||
f' fill-opacity="0.07" stroke="{BLUE}" stroke-width="1.5"/>',
|
||
f'<text x="210" y="60" fill="{BLUE}" style="font-weight:bold">'
|
||
f'{fits("reprezentare mentală — lentila prin care vezi", 310)}</text>']
|
||
for k, t in enumerate(FILTRE):
|
||
y = 78 + 18 * k
|
||
p += [f'<circle cx="216" cy="{y - 4}" r="3" fill="{BLUE}"/>',
|
||
f'<text x="226" y="{y}" fill="{INK}" font-size="11">'
|
||
f'{fits(t, 296, 11)}</text>']
|
||
p += [f'<text x="546" y="64" fill="{RED}" font-size="11">'
|
||
f'{fits("rana nu schimbă", 140, 11)}</text>',
|
||
f'<text x="546" y="80" fill="{RED}" font-size="11">'
|
||
f'{fits("evenimentul —", 140, 11)}</text>',
|
||
f'<text x="546" y="96" fill="{RED}" font-size="11">'
|
||
f'{fits("schimbă lentila", 140, 11)}</text>',
|
||
f'<line x1="534" y1="88" x2="542" y2="88" stroke="{RED}" stroke-width="1.5"/>']
|
||
# coborârea pe rândul doi
|
||
p += [f'<path d="M 210 138 L 210 152 L {X_ARR} 152 L {X_ARR} 162"'
|
||
f' fill="none" stroke="{LINE}" stroke-width="1.5"/>',
|
||
f'<path d="M {X_ARR - 4} 156 L {X_ARR} 164 L {X_ARR + 4} 156 Z" fill="{LINE}"/>']
|
||
for k, (nume, ex) in enumerate(LANT2):
|
||
x = BOX2_X[k]
|
||
p += [f'<rect x="{x}" y="170" width="{BOX2_W}" height="54" fill="{FILL}"'
|
||
f' stroke="{LINE}" stroke-width="1"/>',
|
||
f'<text x="{x + 10}" y="190" fill="{INK}" style="font-weight:bold">'
|
||
f'{fits(nume, BOX2_W - 20)}</text>',
|
||
f'<text x="{x + 10}" y="212" fill={chr(34)}{ORANGE}{chr(34)}'
|
||
f' font-size="11">{fits(ex, 132, 11)}</text>']
|
||
if k < len(LANT2) - 1:
|
||
p += [f'<line x1="{x + BOX2_W + 2}" y1="197" x2="{x + 170}" y2="197"'
|
||
f' stroke="{LINE}" stroke-width="1.5"/>',
|
||
f'<path d="M {x + 164} 193 L {x + 172} 197 L {x + 164} 201 Z"'
|
||
f' fill="{LINE}"/>']
|
||
p += [f'<rect x="14" y="240" width="672" height="74" fill="{RED}"'
|
||
f' fill-opacity="0.06" stroke="{RED}" stroke-width="1"/>',
|
||
f'<text x="24" y="260" fill="{RED}" style="font-weight:bold">'
|
||
f'{fits("De ce te interesează la execuție", 652)}</text>',
|
||
f'<text x="24" y="280" fill="{INK}" font-size="11">'
|
||
f'{fits("Doi traderi cu același stop luat, pe același grafic, scriu două reprezentări diferite — deci două", 652, 11)}</text>',
|
||
f'<text x="24" y="296" fill="{INK}" font-size="11">'
|
||
f'{fits("comportamente diferite. Regula scrisă dinainte acționează în caseta a doua, nu în ultima.", 652, 11)}</text>',
|
||
'</svg>']
|
||
return "\n ".join(p)
|
||
|
||
|
||
# ------------------------------------------------- 2. rană -> mască -> greșeală
|
||
# col. 4 = ce e rostit în transcriere (negru); col. 5 = derivația mea pe execuție
|
||
# (albastru). Oricare poate fi "" — la abandon cursul nu spune nimic pe cont.
|
||
RANI = [("respingere", "fugarul", "de obicei tatăl",
|
||
"închizi tranzacția mai devreme; fugi de reguli", ""),
|
||
("abandon", "dependentul", "de obicei mama",
|
||
"", "nu intri până nu confirmă altcineva setup-ul"),
|
||
("umilire", "masochistul", "de obicei mama",
|
||
"te autosabotezi", "suporți pierderea mai mult decât trebuie"),
|
||
("trădare", "dominatorul", "părintele de sex opus",
|
||
"nu ai încredere în nicio strategie; o serie proastă = trădare",
|
||
"de aici schimbatul strategiei după o serie proastă"),
|
||
("nedreptate", "rigidul", "părintele mai autoritar",
|
||
"vrei să ai dreptate; overtrading „ca să meriți”",
|
||
"de aici mutatul stopului ca să nu greșești")]
|
||
ROW_H = 40
|
||
|
||
|
||
def rani_masti() -> str:
|
||
h = 76 + ROW_H * len(RANI) + 58
|
||
p = [f'<svg viewBox="0 0 700 {h}" xmlns="http://www.w3.org/2000/svg"'
|
||
' style="width:100%;height:auto;font:12px sans-serif">',
|
||
f'<text x="14" y="22" fill="{INK}" style="font-weight:bold">Cele cinci'
|
||
' răni: masca fiecăreia și greșeala de execuție pe care o produce</text>',
|
||
f'<text x="20" y="46" fill="#44576e" font-size="10">RANA</text>',
|
||
f'<text x="118" y="46" fill="#44576e" font-size="10">MASCA</text>',
|
||
f'<text x="212" y="46" fill="#44576e" font-size="10">PĂRINTE ASOCIAT</text>',
|
||
f'<text x="344" y="46" fill="#44576e" font-size="10">CE FACE PE CONT</text>',
|
||
f'<line x1="14" y1="52" x2="686" y2="52" stroke="{LINE}" stroke-width="1"/>']
|
||
for k, (rana, masca, par, negru, albastru) in enumerate(RANI):
|
||
y = 74 + ROW_H * k
|
||
p += [f'<text x="20" y="{y}" fill="{INK}" font-size="11"'
|
||
f' style="font-weight:bold">{fits(rana, 92, 11)}</text>',
|
||
f'<text x="118" y="{y}" fill="{ORANGE}" font-size="11">'
|
||
f'{fits(masca, 88, 11)}</text>',
|
||
f'<text x="212" y="{y}" fill="{MUTED}" font-size="10">'
|
||
f'{fits(par, 126, 10)}</text>']
|
||
randuri = [(t, c) for t, c in ((negru, INK), (albastru, BLUE)) if t]
|
||
for j, (txt, col) in enumerate(randuri):
|
||
p.append(f'<text x="344" y="{y + 14 * j}" fill="{col}"'
|
||
f' font-size="11">{fits(txt, 340, 11)}</text>')
|
||
if k < len(RANI) - 1:
|
||
p.append(f'<line x1="14" y1="{y + 21}" x2="686" y2="{y + 21}"'
|
||
f' stroke="{LINE}" stroke-width="0.5" stroke-opacity="0.6"/>')
|
||
yb = 76 + ROW_H * len(RANI) + 18
|
||
p += [f'<text x="14" y="{yb}" fill="{INK}" font-size="11">'
|
||
f'{fits("În coloana a patra, rândul negru e rostit în transcriere; rândul albastru de sub el e derivația mea pe execuție.", 672, 11)}</text>',
|
||
f'<text x="14" y="{yb + 16}" fill="{MUTED}" font-size="11">'
|
||
f'{fits("La abandon cursul vorbește doar de relații și dependențe, nu de cont. Poți fi în mai multe răni, cu una dominantă.", 672, 11)}</text>',
|
||
'</svg>']
|
||
return "\n ".join(p)
|
||
|
||
|
||
# ----------------------------------------------------- 3. etapele copiilor interiori
|
||
# (start_ani, stop_ani, nume, linia 1, linia 2)
|
||
ETAPE = [(0.0, 1.5, "sinele infantil",
|
||
"nevoi de bază: hrană, somn, atingere, siguranță.",
|
||
"Fără amintiri — cursul le pune în „memoria celulară”."),
|
||
(1.5, 3.0, "sinele copilului mic",
|
||
"autonomie și testarea limitelor.",
|
||
"Mediu restrictiv aici duce în rușine, vinovăție, îndoială."),
|
||
(3.0, 6.0, "copilul interior tânăr",
|
||
"imaginație, creativitate, stimă de sine.",
|
||
"Aici se formează, spune cursul, umilirea și respingerea."),
|
||
(6.0, 12.0, "copilul interior școlar",
|
||
"identitate și valoare de sine, prin grup.",
|
||
"Critica produce aici „nu sunt suficient de bun”."),
|
||
(12.0, 15.0, "adolescentul interior",
|
||
"rebeliune, căutare de identitate, apartenență.",
|
||
"De aici vine, spune cursul, încălcarea regulilor."),
|
||
(16.0, 22.0, "tânărul adult interior",
|
||
"asumarea responsabilității, primele decizii mari.",
|
||
"De aici vine indecizia, inclusiv în trading.")]
|
||
AX0, AXW, YEARS, ROW = 20.0, 250.0, 22.0, 54
|
||
|
||
|
||
def eti(a: float, b: float) -> str:
|
||
"""Eticheta de vârstă: luni sub doi ani, altfel ani, cu virgulă zecimală."""
|
||
if b <= 1.6:
|
||
return f"{int(a * 12)}–{int(b * 12)} luni"
|
||
lo = "18 luni" if a == 1.5 else f"{a:g}".replace(".", ",")
|
||
return f"{lo}–{b:g} ani".replace(".", ",")
|
||
|
||
|
||
def _x(an: float) -> float:
|
||
return AX0 + AXW * an / YEARS
|
||
|
||
|
||
def etape_copii() -> str:
|
||
h = 74 + ROW * len(ETAPE) + 44
|
||
p = [f'<svg viewBox="0 0 700 {h}" xmlns="http://www.w3.org/2000/svg"'
|
||
' style="width:100%;height:auto;font:12px sans-serif">',
|
||
f'<text x="14" y="22" fill="{INK}" style="font-weight:bold">Nu un copil'
|
||
' interior, ci șase — barele sunt la scară pe axa de vârstă</text>']
|
||
# axa de vârstă, sus
|
||
p += [f'<line x1="{AX0}" y1="52" x2="{_x(YEARS)}" y2="52" stroke="{LINE}"'
|
||
' stroke-width="1"/>']
|
||
for an in (0, 3, 6, 12, 22):
|
||
p += [f'<line x1="{_x(an)}" y1="48" x2="{_x(an)}" y2="56"'
|
||
f' stroke="{LINE}" stroke-width="1"/>',
|
||
f'<text x="{_x(an) - 4}" y="45" fill="{MUTED}" font-size="10">{an}</text>']
|
||
p.append(f'<text x="{_x(YEARS) + 8}" y="56" fill="{MUTED}" font-size="10">ani</text>')
|
||
y_last = 74 + ROW * (len(ETAPE) - 1) + 18
|
||
p += [f'<line x1="{_x(3)}" y1="58" x2="{_x(3)}" y2="{y_last}" stroke="{RED}"'
|
||
' stroke-width="1" stroke-dasharray="4 3"/>']
|
||
for k, (a, b, nume, l1, l2) in enumerate(ETAPE):
|
||
y = 74 + ROW * k
|
||
col = RED if b <= 3 else INK
|
||
p += [f'<rect x="{_x(a)}" y="{y}" width="{_x(b) - _x(a)}" height="18"'
|
||
f' fill="{col}" fill-opacity="0.16" stroke="{col}" stroke-width="1"/>',
|
||
f'<text x="298" y="{y + 12}" fill="{col}" font-size="11"'
|
||
f' style="font-weight:bold">{fits(f"{nume} · {eti(a, b)}", 388, 11)}</text>',
|
||
f'<text x="298" y="{y + 28}" fill="{INK}" font-size="11">'
|
||
f'{fits(l1, 388, 11)}</text>',
|
||
f'<text x="298" y="{y + 43}" fill="{MUTED}" font-size="10">'
|
||
f'{fits(l2, 388, 10)}</text>']
|
||
yb = 74 + ROW * len(ETAPE) + 16
|
||
p += [f'<text x="14" y="{yb}" fill="{RED}" font-size="11">'
|
||
f'{fits("Linia punctată de la 3 ani: sub ea nu ai amintiri (neocortexul nu e dezvoltat), deci informația vine", 672, 11)}</text>',
|
||
f'<text x="14" y="{yb + 16}" fill="{RED}" font-size="11">'
|
||
f'{fits("de la părinți sau din corp, nu din memorie. Între 15 și 16 ani cursul nu numește o etapă separată.", 672, 11)}</text>',
|
||
'</svg>']
|
||
return "\n ".join(p)
|
||
|
||
|
||
svgs["lant_rana"] = lant_rana()
|
||
svgs["rani_masti"] = rani_masti()
|
||
svgs["etape_copii"] = etape_copii()
|
||
|
||
# ---------------------------------------------------------------------- assert-uri
|
||
# 1. nicio bară nu iese din axă și barele sunt în ordine crescătoare de vârstă
|
||
assert all(0 <= a < b <= YEARS for a, b, *_ in ETAPE), "interval de vârstă invalid"
|
||
assert [a for a, *_ in ETAPE] == sorted(a for a, *_ in ETAPE), "etape neordonate"
|
||
# 2. eticheta „sub 3 ani nu ai amintiri" trebuie să acopere exact primele două etape
|
||
sub3 = [e for e in ETAPE if e[1] <= 3.0]
|
||
assert len(sub3) == 2, f"linia de 3 ani nu mai taie 2 etape, ci {len(sub3)}"
|
||
# 3. textul spune „șase" copii interiori
|
||
assert len(ETAPE) == 6, "titlul spune șase etape"
|
||
# 4. textul spune „cinci răni", fiecare cu exact o mască
|
||
assert len(RANI) == 5 and len({r[1] for r in RANI}) == 5, "5 răni, 5 măști distincte"
|
||
# 5. fiecare rană spune ceva pe cont, din curs sau de la mine; „muți stopul" nu
|
||
# poate sta în negru (cuvântul „stop" nu apare în transcrierea workshopului)
|
||
assert all(r[3] or r[4] for r in RANI), "o rană fără nimic pe coloana de cont"
|
||
assert not any("stop" in r[3] for r in RANI), "«stop» nu e rostit în transcriere"
|
||
# 5b. săgeata care coboară din reprezentarea mentală cade pe caseta „gând"
|
||
_i = [n for n, _ in LANT2].index("gând")
|
||
assert _i == ARROW_TARGET and BOX2_X[_i] < X_ARR < BOX2_X[_i] + BOX2_W, \
|
||
f"săgeata la x={X_ARR} nu cade pe caseta „gând” ({BOX2_X[_i]}…{BOX2_X[_i] + BOX2_W})"
|
||
# 6. niciun SVG nu are linie goală (python-markdown ar rupe blocul)
|
||
for name, svg in svgs.items():
|
||
assert "\n\n" not in svg, f"linie goală în {name}"
|
||
assert svg.count("<svg") == 1 and svg.rstrip().endswith("</svg>"), name
|
||
|
||
if MD.exists():
|
||
md = MD.read_text(encoding="utf-8")
|
||
for name, svg in svgs.items():
|
||
pat = re.compile(rf"<!--SVG:{name}-->.*?<!--/SVG-->", re.S)
|
||
assert pat.search(md), f"marcatorul {name} lipsește din .md"
|
||
md = pat.sub(lambda _m: f"<!--SVG:{name}-->\n{svg}\n<!--/SVG-->", md)
|
||
MD.write_text(md, encoding="utf-8")
|
||
print("scris", MD)
|
||
else:
|
||
print("nu există încă", MD)
|