import html
from decimal import Decimal, ROUND_HALF_UP
INK, MUTED, TEAL, RUST = '#20282b', '#58646a', '#10777e', '#a44623'
PAPER, GRID = '#f6f7f4', '#dce1e0'
FONT = 'Arial, Helvetica, sans-serif'
def one(value):
    return str(Decimal(value).quantize(Decimal('.1'), rounding=ROUND_HALF_UP))
def signed(value):
    return ('+' if Decimal(value)>0 else '−' if Decimal(value)<0 else '') + one(abs(Decimal(value)))
class SVG:
    def __init__(self, width, height, title, desc):
        self.width, self.height = width, height
        self.parts = [f'<svg xmlns="http://www.w3.org/2000/svg" width="{width}" height="{height}" viewBox="0 0 {width} {height}" role="img" aria-labelledby="title desc">',
                      f'<title id="title">{html.escape(title)}</title>', f'<desc id="desc">{html.escape(desc)}</desc>',
                      f'<rect width="{width}" height="{height}" fill="{PAPER}"/>',
                      f'<g font-family="{FONT}" fill="{INK}">']
    def text(self, x, y, value, size=22, color=INK, weight=400, anchor='start', extra=''):
        self.parts.append(f'<text x="{x:.3f}" y="{y:.3f}" font-size="{size}" fill="{color}" font-weight="{weight}" text-anchor="{anchor}" {extra}>{html.escape(str(value))}</text>')
    def lines(self, x, y, values, size=22, leading=30, **kw):
        for i, value in enumerate(values):
            self.text(x, y + i * leading, value, size, **kw)
    def line(self, x1, y1, x2, y2, color=GRID, width=1, extra=''):
        self.parts.append(f'<line x1="{x1:.3f}" y1="{y1:.3f}" x2="{x2:.3f}" y2="{y2:.3f}" stroke="{color}" stroke-width="{width}" {extra}/>')
    def rect(self, x, y, w, h, fill, radius=0):
        self.parts.append(f'<rect x="{x:.3f}" y="{y:.3f}" width="{w:.3f}" height="{h:.3f}" fill="{fill}" rx="{radius}"/>')
    def dot(self, x, y, color, r=5, shape='circle', extra=''):
        if shape == 'square':
            self.parts.append(f'<rect x="{x-r:.3f}" y="{y-r:.3f}" width="{r*2}" height="{r*2}" fill="{color}" stroke="{PAPER}" stroke-width="1.5" {extra}/>')
        else:
            self.parts.append(f'<circle cx="{x:.3f}" cy="{y:.3f}" r="{r}" fill="{color}" stroke="{PAPER}" stroke-width="1.5" {extra}/>')
    def path(self, points, color, width=4, extra=''):
        d = ' '.join(('M' if i == 0 else 'L') + f'{x:.4f},{y:.4f}' for i, (x, y) in enumerate(points))
        self.parts.append(f'<path d="{d}" fill="none" stroke="{color}" stroke-width="{width}" stroke-linejoin="round" stroke-linecap="round" {extra}/>')
    def save(self, path):
        path.write_text('\n'.join(self.parts + ['</g>', '</svg>']) + '\n')
