audit: pragul de rand derivat din font-size; si cele doua diagrame chiar stricate
Al doilea defect al uneltei: inaltimea de rand era constanta LINE_H=13, calibrata pe 12 px, deci la etichetele de 10 px cu pas de 12 px credea ca randurile se ating. Acum e LINE_H_RATIO x font-size-ul efectiv, mostenit corect de pe <g>. Factorul e 1.07, nu 1.15: agentul a incercat valorile mari, a masurat cu metrice reale de glif si a aratat ca scot cinci fantome noi. Cele doua probleme reale pe care unealta reparata le-a scos la iveala: atmi_ansamblu avea un caption de 792 px intr-un viewBox de 720, deci se taia la margine; la selectia_proximitate se calcau eticheta sagetii si titlul. Ambele reparate si privite la 1:1. Cele 92 de diagrame: 0 probleme. Selftest-ul trece, si prinde in continuare o suprapunere fabricata deliberat - unealta tace pentru ca e curat, nu pentru ca a orbit. Ramane, raportat si nereparat: CHAR_W = 5.7 e tot calibrat pe 12 px, deci latimea textelor mici e supraestimata. Aceeasi clasa de bug, n-a produs inca raportari gresite. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ThN7ixZrowca8aTGrK1MUJ
This commit is contained in:
@@ -13,6 +13,7 @@ Rulează:
|
||||
python3 gen/strategii/atmi_ansamblu.py
|
||||
Scrie lângă el `atmi_ansamblu.svg`.
|
||||
"""
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
@@ -84,11 +85,13 @@ marks = [
|
||||
Mark(LAST, "ieși cu tot", BLUE, "below", dy=22),
|
||||
]
|
||||
|
||||
caption = ("100.00 / 96.00 / 105.60 sunt cifrele exemplului din curs; PPQ 95.80 e calculat "
|
||||
"în diagrama pasului 1 (cursul nu dă valorile pivoților).")
|
||||
|
||||
ch = Chart(candles=cds, levels=levels, marks=marks,
|
||||
scale=22.0, gap=17, body_w=9, left=44, width=720, vol_h=70, vol_gap=72, top=88,
|
||||
vol_label="volum",
|
||||
caption="100.00 / 96.00 / 105.60 sunt cifrele exemplului din curs; PPQ 95.80 e calculat "
|
||||
"în diagrama pasului 1 (cursul nu dă valorile pivoților).")
|
||||
caption=caption)
|
||||
|
||||
svg = ch.render()
|
||||
|
||||
@@ -125,6 +128,46 @@ titlu = ('<text x="24" y="26" fill="#333" style="font-weight:bold">'
|
||||
i = svg.index(">") + 1
|
||||
svg = svg[:i] + "\n " + "\n ".join([ppq, no_sl, titlu]) + svg[i:]
|
||||
|
||||
# ---------------------------------------------------------------- caption pe două rânduri
|
||||
# Captionul are 135 de caractere, adică ~794 px de la x=24 într-o pânză lată de
|
||||
# 720: se rupe pe două rânduri, ca în selectia_ansamblu.py.
|
||||
def _wrap(text: str, max_chars: int) -> list[str]:
|
||||
lines, cur = [], ""
|
||||
for w in text.split():
|
||||
if cur and len(cur) + 1 + len(w) > max_chars:
|
||||
lines.append(cur)
|
||||
cur = w
|
||||
else:
|
||||
cur = f"{cur} {w}".strip()
|
||||
if cur:
|
||||
lines.append(cur)
|
||||
return lines
|
||||
|
||||
|
||||
cap_lines = _wrap(caption, 80)
|
||||
assert len(cap_lines) == 2, cap_lines
|
||||
m = re.search(r'<text x="24" y="(\d+)" fill="#555">' + re.escape(caption) + r"</text>", svg)
|
||||
assert m, "caption-ul nu a fost găsit în SVG"
|
||||
y0 = int(m.group(1))
|
||||
wrapped = "\n ".join(f'<text x="24" y="{y0 + 17 * i}" fill="#555">{ln}</text>'
|
||||
for i, ln in enumerate(cap_lines))
|
||||
svg = svg[:m.start()] + wrapped + svg[m.end():]
|
||||
vm = re.search(r'viewBox="0 0 (\d+) (\d+)"', svg)
|
||||
assert vm, "nu găsesc viewBox-ul"
|
||||
svg = svg.replace(vm.group(0),
|
||||
f'viewBox="0 0 {vm.group(1)} {int(vm.group(2)) + 17 * (len(cap_lines) - 1)}"', 1)
|
||||
|
||||
# fiecare rând de caption CHIAR DESENAT trebuie să încapă în lățimea pânzei.
|
||||
# CHAR_W = 5.7 e lățimea medie per caracter calibrată de audit_diagrams.py;
|
||||
# assertul prinde exact defectul vechi, când captionul era un singur text de
|
||||
# 135 de caractere: 24 + 135 × 5.7 = 794 > 720.
|
||||
CHAR_W = 5.7
|
||||
vw = int(vm.group(1))
|
||||
for m_cap in re.finditer(r'<text x="24" y="[\d.]+" fill="#555">([^<]*)</text>', svg):
|
||||
ln = m_cap.group(1)
|
||||
x1 = 24 + len(ln) * CHAR_W
|
||||
assert x1 <= vw, f"rând de caption tăiat la marginea dreaptă ({x1:.0f} > {vw}): {ln!r}"
|
||||
|
||||
assert svg.count("\n\n") == 0, "linie goală în SVG rupe blocul din markdown"
|
||||
assert ".md:" not in svg, "trimitere fișier:linie în SVG"
|
||||
OUT.write_text(svg)
|
||||
|
||||
Reference in New Issue
Block a user