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
194 lines
10 KiB
Python
194 lines
10 KiB
Python
"""Cele două scheme din summaries/06_MODUL_5/07_workshop_6_abundenta.md.
|
||
|
||
Workshop de psihologie: nu există preț, deci nu există candele. Schemele sunt
|
||
structuri — lanțul a fi / a face / a avea, și schema logică a unei strategii,
|
||
cea pe care autorul spune că o desenează cu romb de pe vremea Turbo Pascal.
|
||
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_6_abundenta.py
|
||
"""
|
||
import re
|
||
from pathlib import Path
|
||
|
||
MD = Path("/workspace/atm-curs-dl/summaries/06_MODUL_5/07_workshop_6_abundenta.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. a fi -> a face -> a avea
|
||
# (eticheta, ce e, cele două rânduri de detaliu din transcriere)
|
||
VERBE = [
|
||
("a FI", "abilitățile + starea emoțională",
|
||
["„20% strategie, 80% psihologie — puse", "la pachet ca să obții 100%”"]),
|
||
("a FACE", "procesul: execuția strategiei",
|
||
["„acțiunea sau procesul care", "înseamnă creștere și dezvoltare\u201d"]),
|
||
("a AVEA", "rezultatul: banii",
|
||
["„a avea ce este? rezultatul, frate —", "rezultatul e consecința procesului”"]),
|
||
]
|
||
BOX_W, BOX_H, GAP_X, X0, Y0 = 200, 104, 32, 18, 44
|
||
|
||
|
||
def a_fi_a_face_a_avea() -> str:
|
||
w = X0 * 2 + 3 * BOX_W + 2 * GAP_X
|
||
p = [f'<svg viewBox="0 0 {w} 250" xmlns="http://www.w3.org/2000/svg"'
|
||
' style="width:100%;height:auto;font:12px sans-serif">',
|
||
f'<text x="{X0}" y="24" fill="{INK}" style="font-weight:bold">'
|
||
f'{fits("Ordinea dată de curs: a fi, a face, a avea — și scurtcircuitul pe care îl ia majoritatea", w - 2 * X0)}</text>']
|
||
for i, (verb, ce, detail) in enumerate(VERBE):
|
||
x = X0 + i * (BOX_W + GAP_X)
|
||
col = GREEN if i < 2 else ORANGE
|
||
p += [f'<rect x="{x}" y="{Y0}" width="{BOX_W}" height="{BOX_H}" fill="{col}"'
|
||
f' fill-opacity="0.07" stroke="{col}" stroke-width="1.5" rx="4"/>',
|
||
f'<text x="{x + 12}" y="{Y0 + 24}" fill="{col}" style="font-weight:bold">'
|
||
f'{fits(verb, BOX_W - 24)}</text>',
|
||
f'<text x="{x + 12}" y="{Y0 + 44}" fill="{INK}" font-size="11">'
|
||
f'{fits(ce, BOX_W - 24, 11)}</text>']
|
||
for k, d in enumerate(detail):
|
||
p += [f'<text x="{x + 12}" y="{Y0 + 66 + k * 14}" fill="{MUTED}" font-size="10">'
|
||
f'{fits(d, BOX_W - 20, 10)}</text>']
|
||
if i < len(VERBE) - 1:
|
||
xa = x + BOX_W
|
||
p += [f'<line x1="{xa + 4}" y1="{Y0 + BOX_H / 2}" x2="{xa + GAP_X - 6}"'
|
||
f' y2="{Y0 + BOX_H / 2}" stroke="{LINE}" stroke-width="1.5"/>',
|
||
f'<path d="M {xa + GAP_X - 12} {Y0 + BOX_H / 2 - 4} L {xa + GAP_X - 4}'
|
||
f' {Y0 + BOX_H / 2} L {xa + GAP_X - 12} {Y0 + BOX_H / 2 + 4} Z" fill="{LINE}"/>']
|
||
# scurtcircuitul: de la stânga primei casete direct la a treia, pe dedesubt
|
||
y_sc = Y0 + BOX_H + 34
|
||
x_end = X0 + 2 * (BOX_W + GAP_X) + BOX_W / 2
|
||
p += [f'<path d="M {X0 + 14} {Y0 + BOX_H + 6} L {X0 + 14} {y_sc} L {x_end} {y_sc}'
|
||
f' L {x_end} {Y0 + BOX_H + 8}" fill="none" stroke="{RED}" stroke-width="1.5"'
|
||
' stroke-dasharray="5 4"/>',
|
||
f'<path d="M {x_end - 4} {Y0 + BOX_H + 16} L {x_end} {Y0 + BOX_H + 6}'
|
||
f' L {x_end + 4} {Y0 + BOX_H + 16} Z" fill="{RED}"/>',
|
||
f'<text x="{X0 + 24}" y="{y_sc - 8}" fill="{RED}" font-size="11">'
|
||
f'{fits("scurtcircuitul: pui obiectivul direct pe rezultat, în bani", 400, 11)}</text>',
|
||
f'<text x="{X0}" y="{y_sc + 24}" fill="{RED}" font-size="11">'
|
||
f'{fits("Motivul pe care îl dă autorul: „oamenii nu-și asumă responsabilitatea transformării. Stau în a avea pentru", w - 2 * X0, 11)}</text>',
|
||
f'<text x="{X0}" y="{y_sc + 40}" fill="{RED}" font-size="11">'
|
||
f'{fits("că nu-și asumă responsabilitatea transformării.” Transformarea sunt exact cele două casete sărite.", w - 2 * X0, 11)}</text>',
|
||
'</svg>']
|
||
return "\n ".join(p)
|
||
|
||
|
||
# ------------------------------------------------ 2. schema logică a strategiei
|
||
# (eticheta nodului, tipul) — tipul contează pentru assert-uri
|
||
NODURI = [
|
||
("A — condiția de intrare din strategie", "start"),
|
||
("s-a format A, exact ca în reguli?", "romb"),
|
||
("B — intri, cu stopul pus în același ordin", "pas"),
|
||
("prețul face D: se duce la stop?", "romb"),
|
||
("E — stopul te scoate: pierdere planificată", "iesire-plan"),
|
||
("C — duci poziția la ieșirea din plan", "iesire-bun"),
|
||
("nu faci nimic, aștepți următoarea alertă", "iesire-bun"),
|
||
]
|
||
|
||
|
||
def schema_logica() -> str:
|
||
w, h = 700, 382
|
||
p = [f'<svg viewBox="0 0 {w} {h}" xmlns="http://www.w3.org/2000/svg"'
|
||
' style="width:100%;height:auto;font:12px sans-serif">',
|
||
f'<text x="16" y="24" fill="{INK}" style="font-weight:bold">'
|
||
f'{fits("Strategia ca schemă logică — forma pe care autorul spune că o desenează cu romb, din liceu", w - 32)}</text>']
|
||
|
||
def box(x, y, bw, bh, txt, col, bold=False, fs=11):
|
||
wt = "font-weight:bold" if bold else ""
|
||
return [f'<rect x="{x}" y="{y}" width="{bw}" height="{bh}" fill="{col}"'
|
||
f' fill-opacity="0.07" stroke="{col}" stroke-width="1.5" rx="4"/>',
|
||
f'<text x="{x + 10}" y="{y + bh / 2 + 4}" fill="{col}" font-size="{fs}"'
|
||
f' style="{wt}">{fits(txt, bw - 20, fs)}</text>']
|
||
|
||
def diamond(cx, cy, dw, dh, lines):
|
||
"""Romb cu text centrat; textul stă în banda din mijloc, unde rombul e lat."""
|
||
out = [f'<path d="M {cx} {cy - dh / 2} L {cx + dw / 2} {cy} L {cx} {cy + dh / 2}'
|
||
f' L {cx - dw / 2} {cy} Z" fill="{BLUE}" fill-opacity="0.07"'
|
||
f' stroke="{BLUE}" stroke-width="1.5"/>']
|
||
y0 = cy - 4 if len(lines) == 2 else cy + 3
|
||
for k, t in enumerate(lines):
|
||
dy = abs(y0 + k * 13 - cy) + 5 # cât de departe de mijloc e rândul
|
||
half = dw / 2 * (1 - dy / (dh / 2)) # semi-lățimea rombului acolo
|
||
out += [f'<text x="{cx}" y="{y0 + k * 13}" fill="{BLUE}" font-size="10"'
|
||
f' text-anchor="middle">{fits(t, 2 * half - 16, 10)}</text>']
|
||
return out
|
||
|
||
def arrow(x1, y1, x2, y2, col=LINE):
|
||
d = 4
|
||
head = (f'M {x2 - d} {y2 - 9} L {x2} {y2} L {x2 + d} {y2 - 9} Z' if y2 > y1
|
||
else f'M {x2 - 9} {y2 - d} L {x2} {y2} L {x2 - 9} {y2 + d} Z')
|
||
return [f'<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" stroke="{col}" stroke-width="1.5"/>',
|
||
f'<path d="{head}" fill="{col}"/>']
|
||
|
||
# coloana centrală: start -> romb 1 -> B -> romb 2 -> C
|
||
p += box(200, 40, 300, 34, NODURI[0][0], GRAY, bold=True)
|
||
p += arrow(350, 74, 350, 92)
|
||
p += diamond(350, 130, 300, 76, ["s-a format A, exact ca în reguli?",
|
||
"(fără „dar aici e un bull flag”)"])
|
||
p += arrow(350, 168, 350, 182)
|
||
p += box(200, 182, 300, 34, NODURI[2][0], GREEN)
|
||
p += arrow(350, 216, 350, 230)
|
||
p += diamond(350, 268, 300, 76, ["prețul se duce înspre stop (D)?"])
|
||
p += arrow(350, 306, 350, 320)
|
||
p += box(200, 320, 300, 34, NODURI[5][0], GREEN)
|
||
# ramura NU a primului romb -> aștepți
|
||
p += arrow(500, 130, 536, 130)
|
||
p += box(536, 113, 150, 34, "aștepți alerta", GRAY)
|
||
p += [f'<text x="506" y="124" fill="{MUTED}" font-size="10">NU</text>',
|
||
f'<text x="356" y="180" fill="{MUTED}" font-size="10">DA</text>']
|
||
# ramura DA a celui de-al doilea romb -> stopul
|
||
p += arrow(500, 268, 536, 268)
|
||
p += box(536, 251, 150, 34, "E — stopul te scoate", RED)
|
||
p += [f'<text x="506" y="262" fill="{MUTED}" font-size="10">DA</text>',
|
||
f'<text x="356" y="318" fill="{MUTED}" font-size="10">NU</text>',
|
||
f'<text x="536" y="300" fill="{RED}" font-size="10">'
|
||
f'{fits("pierdere planificată", 150, 10)}</text>']
|
||
p += [f'<text x="16" y="{h - 8}" fill="{MUTED}" font-size="10">'
|
||
f'{fits("Trei capete de drum, o singură pierdere — și e planificată. Literele A, B, C, D, E sunt ale autorului.", w - 32, 10)}</text>',
|
||
'</svg>']
|
||
return "\n ".join(p)
|
||
|
||
|
||
svgs["a_fi_a_face_a_avea"] = a_fi_a_face_a_avea()
|
||
svgs["schema_logica"] = schema_logica()
|
||
|
||
# ------------------------------------------------------------------- assert-uri
|
||
# 1. textul vorbește despre trei verbe, în ordinea a fi -> a face -> a avea
|
||
assert [v[0] for v in VERBE] == ["a FI", "a FACE", "a AVEA"], "ordinea verbelor"
|
||
# 2. scurtcircuitul roșu sare exact două casete (de la prima direct la a treia)
|
||
assert len(VERBE) == 3, "scurtcircuitul e desenat ca sărind peste exact 2 casete"
|
||
# 3. schema logică: exact două rombi (autorul descrie o ramificație de intrare și
|
||
# una de ieșire) și exact o singură ieșire etichetată ca pierdere
|
||
assert sum(1 for _, t in NODURI if t == "romb") == 2, "textul spune două ramificații"
|
||
assert sum(1 for _, t in NODURI if t == "iesire-plan") == 1, \
|
||
"legenda spune «o singură pierdere»"
|
||
# 4. legenda spune „trei capete de drum" — exact nodurile din care nu mai pleacă
|
||
# nicio săgeată (E, C, aștepți)
|
||
assert sum(1 for _, t in NODURI if t.startswith("iesire")) == 3, \
|
||
"legenda spune trei capete de drum"
|
||
# 5. literele din schemă sunt exact cele rostite în transcriere
|
||
litere = {s[0] for s, _ in NODURI if s[0].isupper() and s[1] == " "}
|
||
assert litere == {"A", "B", "C", "E"}, f"litere desenate: {litere}"
|
||
# 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)
|