"""Deterministic virtual-time telemetry pipeline; standard library only."""
from collections import deque
from dataclasses import dataclass
from math import floor, pi, sin


@dataclass(frozen=True)
class Record:
    sequence: int
    sampled_at: int
    code: int
    filtered_volts: float


def simulate(outage=None, upload_period=20, capacity=8):
    queue = deque()
    window = deque(maxlen=5)
    sent = []
    dropped = 0
    peak = 0
    max_age = 0
    produced = 0

    def deliver(now, limit=2):
        nonlocal max_age
        for _ in range(min(limit, len(queue))):
            record = queue.popleft()
            max_age = max(max_age, now - record.sampled_at)
            sent.append(record)

    for now in range(0, 1000, 10):
        volts = 1.65 + 0.05 * sin(2 * pi * 5 * now / 1000)
        code = min(4095, max(0, floor(volts / 3.3 * 4096)))
        window.append((code + 0.5) * 3.3 / 4096)
        record = Record(produced, now, code, sum(window) / len(window))
        produced += 1
        if len(queue) == capacity:
            queue.popleft()
            dropped += 1
        queue.append(record)
        peak = max(peak, len(queue))
        online = outage is None or not (outage[0] <= now < outage[1])
        if online and now % upload_period == 0:
            deliver(now)
    # Stop acquisition and drain bounded backlog after connectivity is restored.
    now = 1000
    while queue:
        deliver(now)
        now += upload_period
    sequences = [item.sequence for item in sent]
    assert all(a < b for a, b in zip(sequences, sequences[1:]))
    assert all(0 <= item.code <= 4095 for item in sent)
    assert produced == len(sent) + dropped + len(queue)
    assert peak <= capacity
    return dict(produced=produced, delivered=len(sent), dropped=dropped,
                queued=len(queue), peak=peak, max_age_ms=max_age)


def main():
    normal = simulate()
    offline = simulate(outage=(300, 600))
    slow = simulate(upload_period=40)
    assert normal["dropped"] == 0 and normal["delivered"] == 100
    assert offline["dropped"] > 0 and slow["dropped"] > 0
    for name, result in (("normal", normal), ("offline", offline), ("slow", slow)):
        print(name, result)
    print("PASS")


if __name__ == "__main__":
    main()
