"""
radar_svg.py — генерация SVG паутинной диаграммы для сохранения на устройство.
Не требует сторонних зависимостей (чистый Python).
SVG содержит корректные шрифты и цвета, может быть открыт/сохранён в браузере.
"""
import math
import base64
def generate_radar_svg(items: list[dict], max_val: float = 14.0, size: int = 520) -> str:
"""
Возвращает SVG-строку паутинной диаграммы.
items — список осей (dimension_name, dimension_color, value)
max_val — максимум шкалы
size — размер холста в пикселях
"""
n = len(items)
if n < 3:
return f''
cx = cy = size / 2
R = size * 0.27 # радиус внешнего кольца
lbl_r = R + size * 0.12 # расстояние до подписей от центра
safe_max = max_val if max_val > 0 else 1.0
def axis_xy(i: int, frac: float = 1.0) -> tuple[float, float]:
a = math.radians(-90.0 + 360.0 * i / n)
return cx + R * frac * math.cos(a), cy + R * frac * math.sin(a)
def poly_pts(pts: list[tuple]) -> str:
return " ".join(f"{x:.2f},{y:.2f}" for x, y in pts)
lines: list[str] = [
f'")
return "\n".join(lines)
def _xml_escape(s: str) -> str:
return s.replace("&", "&").replace("<", "<").replace(">", ">")
def get_radar_data_uri(items: list[dict], max_val: float = 14.0) -> str:
"""
Возвращает data URI вида «data:image/svg+xml;base64,…».
Передайте в page.launch_url(...) чтобы открыть/сохранить изображение.
"""
svg = generate_radar_svg(items, max_val)
b64 = base64.b64encode(svg.encode("utf-8")).decode()
return f"data:image/svg+xml;base64,{b64}"