#!/usr/bin/env python3
"""Rank one-triangle runtime-scheduler epochs by 640x480 pixel coverage.

Usage: rank_sched_triangle_coverage.py TAG [--top N]

The generated feeder format stores an eight-word header followed by three
{RGBAQ, ST, XYZ2} vertex triplets.  This is a capacity preflight: it uses the
same center-sample inside test as the fixture reference and reports epochs
whose unthrottled fragment burst may exceed the production request FIFO.
"""
import os
import sys

ROOT = os.path.normpath(os.path.join(os.path.dirname(__file__), ".."))
DATA = os.path.join(ROOT, "sim", "data", "top_psmct32_raster_demo")


def edge(ax, ay, bx, by, px, py):
    return (px - ax) * (by - ay) - (py - ay) * (bx - ax)


def coverage(vertices, width=640, height=480):
    (x0, y0), (x1, y1), (x2, y2) = vertices
    area = edge(x0, y0, x1, y1, x2, y2)
    if not area:
        return 0
    inv = 1.0 / area
    minx = max(0, int(min(x0, x1, x2)))
    maxx = min(width - 1, int(max(x0, x1, x2)) + 1)
    miny = max(0, int(min(y0, y1, y2)))
    maxy = min(height - 1, int(max(y0, y1, y2)) + 1)
    count = 0
    for py in range(miny, maxy + 1):
        cy = py + 0.5
        for px in range(minx, maxx + 1):
            cx = px + 0.5
            w0 = edge(x1, y1, x2, y2, cx, cy) * inv
            w1 = edge(x2, y2, x0, y0, cx, cy) * inv
            w2 = 1.0 - w0 - w1
            if w0 >= -0.001 and w1 >= -0.001 and w2 >= -0.001:
                count += 1
    return count


def main(argv):
    if len(argv) < 2:
        print(__doc__.strip())
        return 2
    tag = argv[1]
    top = int(argv[argv.index("--top") + 1]) if "--top" in argv else 12
    rows = []
    table = os.path.join(DATA, f"sh3_{tag}_epochs.txt")
    with open(table) as source:
        for line in source:
            fields = line.split()
            if not fields or not fields[0].isdigit():
                continue
            epoch, list_name, ntris = int(fields[0]), fields[8], int(fields[10])
            words = []
            with open(os.path.join(DATA, list_name)) as feeder:
                for text in feeder:
                    text = text.strip()
                    if text and not text.startswith("//"):
                        words.append(int(text, 16))
            total = 0
            peak = 0
            peak_vertices = None
            for ti in range(ntris):
                base = 8 + ti * 9
                xyz = [words[base + 2], words[base + 5], words[base + 8]]
                vertices = [((word >> 4) & 0xFFF, (word >> 20) & 0xFFF) for word in xyz]
                count = coverage(vertices)
                total += count
                if count > peak:
                    peak = count
                    peak_vertices = vertices
            rows.append((total, epoch, ntris, peak, peak_vertices))
    rows.sort(reverse=True)
    print(f"[coverage] tag={tag} epochs={len(rows)}")
    for count, epoch, ntris, peak, vertices in rows[:top]:
        print(f"[coverage] epoch={epoch:4d} pixels={count:6d} tris={ntris:3d} peak_tri={peak:6d} vertices={vertices}")
    return 0


if __name__ == "__main__":
    raise SystemExit(main(sys.argv))
