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:
Claude Agent
2026-09-22 20:45:50 +00:00
parent 5b157116d3
commit 43e6fbcd32
9 changed files with 488 additions and 378 deletions

View File

@@ -90,7 +90,7 @@ arrows = [
Arrow(DEPARTE, f"close {cds[DEPARTE].c:.2f} = {pct_departe:.2f} % peste suport\n"
f"prea departe: până acolo prețul mai are de căzut,\n"
f"deci nivelul nu-l poate opri acum",
where="above", color=RED, dx=-60, dy=-4),
where="above", color=RED, dx=-60, dy=-20),
Arrow(APROAPE, f"close {cds[APROAPE].c:.2f} = {pct_aproape:.2f} % peste suport\n"
f"la nivel: dacă mai scade puțin, dă de ordinele\n"
f"de cumpărare care au mai întors prețul de acolo",
@@ -165,6 +165,36 @@ svg = svg[:m.start()] + wrapped + svg[m.end():]
svg = svg.replace(m_vb.group(0),
f'viewBox="0 0 {m_vb.group(1)} {h_svg + 17 * (len(cap_lines) - 1)}"', 1)
def _text_boxes(fill: str) -> list[tuple[float, float, float, float, str]]:
"""Bbox-urile (x0, x1, ytop, ybot) ale textelor cu un anumit fill."""
out = []
for mm in re.finditer(r"<text ([^>]*)>([^<]*)</text>", svg):
attrs, txt = mm.group(1), mm.group(2)
if f'fill="{fill}"' not in attrs:
continue
x = float(re.search(r'\bx="([-\d.]+)"', attrs).group(1))
y = float(re.search(r'\by="([-\d.]+)"', attrs).group(1))
anchor = (re.search(r'text-anchor="(\w+)"', attrs) or [None, "start"])[1]
w = len(txt) * 5.7 # 12px bold, ca în audit_diagrams.py
x0 = x - w if anchor == "end" else (x - w / 2 if anchor == "middle" else x)
out.append((x0, x0 + w, y - 9, y + 3, txt))
return out
def _se_suprapun(a, b) -> bool:
return a[0] < b[1] and b[0] < a[1] and a[2] < b[3] and b[2] < a[3]
# defectul inițial: ultimul rând al etichetei săgeții de sus (y=75) și titlul
# (y=84) aveau 9 px între baseline-uri și se călcau pe orizontală. Titlul nu
# are voie să se suprapună peste nicio etichetă de săgeată.
titluri = _text_boxes("#333")
assert len(titluri) == 1, f"titluri #333 găsite: {len(titluri)}"
for b in _text_boxes(RED):
assert not _se_suprapun(titluri[0], b), \
f"titlul se suprapune peste eticheta săgeții: {b[4]!r}"
assert "<svg" in svg and "\n\n" not in svg, "linie goală în SVG"
OUT.write_text(svg)
print(f"scris {OUT.name}: 32 candele, suport {SUPORT:.2f}, banda până la {BANDA_SUS:.2f}, "