"""Teaching example: simulated baseline, not a production quality decision."""
from statistics import mean
from pathlib import Path
from math import isfinite
BASELINE = [10.00,10.02,9.99,10.01,10.03,10.00,9.98,10.01,10.00,10.02,9.99,10.01,9.97,10.00,10.02,9.99,10.01,10.00,9.98,10.02]
OBSERVATION = 10.15
assert len(BASELINE) > 1 and all(isfinite(x) for x in BASELINE)
center = mean(BASELINE)
mr = mean(abs(b-a) for a,b in zip(BASELINE,BASELINE[1:]))
lower, upper = center-3*mr/1.128, center+3*mr/1.128
print(f'CL={center:.5f} LCL={lower:.5f} UCL={upper:.5f}')
print(f'new={OBSERVATION:.5f} outside_limits={not lower <= OBSERVATION <= upper}')
values=BASELINE+[OBSERVATION]
x=lambda i: 80+i*32
y=lambda v: 295-(v-9.9)/0.3*240
svg=['<svg xmlns="http://www.w3.org/2000/svg" width="800" height="360" viewBox="0 0 800 360" role="img" aria-labelledby="title desc">','<title id="title">Simulated individuals control chart</title><desc id="desc">20 baseline values and a new observation above the upper control limit. Not production data.</desc>','<rect width="800" height="360" fill="#f7faff"/>','<g font-family="sans-serif" font-size="13" fill="#10233f">','<text x="30" y="28">Simulated measurements (mm) / baseline = 20 points</text>']
for label,value,color in [('UCL',upper,'#b45309'),('CL',center,'#64748b'),('LCL',lower,'#b45309')]:
 svg += [f'<line x1="75" y1="{y(value)}" x2="750" y2="{y(value)}" stroke="{color}" stroke-dasharray="6 4"/>',f'<text x="8" y="{y(value)-5}">{label}</text>']
svg += ['<polyline fill="none" stroke="#0b5cff" stroke-width="2" points="'+' '.join(f'{x(i)},{y(v)}' for i,v in enumerate(values))+'"/>']
for i,v in enumerate(values):
 color='#dc2626' if v<lower or v>upper else '#0b5cff'
 svg.append(f'<circle cx="{x(i)}" cy="{y(v)}" r="4" fill="{color}"/>')
svg += ['<text x="80" y="330">1</text><text x="390" y="330">Time order</text><text x="710" y="330">21</text>','</g></svg>']
Path('control-chart.svg').write_text('\n'.join(svg),encoding='utf-8')
