65 lines
2.7 KiB
Python
65 lines
2.7 KiB
Python
# -*- coding: utf-8 -*-
|
|
import re, json, io, sys
|
|
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
|
|
slides = json.load(open(r"C:\GUARDiA\workspace\kintex\_workspace\proposal\_qa_slides.json", encoding="utf-8"))
|
|
|
|
# Full REQ universe
|
|
UNIV = {}
|
|
for pfx, cnt in [("F", 81), ("A", 20), ("N", 21), ("S", 20)]:
|
|
for i in range(1, cnt + 1):
|
|
UNIV[f"{pfx}-{i:03d}"] = None # slide where covered
|
|
|
|
# Parse each text line for badge tokens with prefix-context + range + continuation.
|
|
# Grammar we support in a run:
|
|
# REQ-<P>-<n> single
|
|
# REQ-<P>-<n>~<m> range (same prefix)
|
|
# ...·<P>-<n> new prefix single continuation
|
|
# ...·<P>-<n>~<m> new prefix range continuation
|
|
# ...·<n> bare number continues LAST prefix (e.g. A-011·012)
|
|
# ...·<n>~<m> bare range continues last prefix (e.g. 067~069)
|
|
cover = {} # req -> list of slides
|
|
|
|
def add(pfx, a, b, sn):
|
|
for i in range(a, b + 1):
|
|
key = f"{pfx}-{i:03d}"
|
|
cover.setdefault(key, set()).add(sn)
|
|
|
|
# token: optional prefix letter, number, optional ~ number
|
|
tok = re.compile(r"(?:REQ-)?(?:([FANS])-)?(\d{2,3})(?:\s*~\s*(?:[FANS]-)?(\d{2,3}))?")
|
|
|
|
for s in slides:
|
|
sn = s["n"]
|
|
for t in s["texts"]:
|
|
# only scan segments that look like badge context (contain REQ- or letter-number dot chains)
|
|
for m in re.finditer(r"REQ-[FANS]-\d{2,3}(?:\s*~\s*\d{2,3})?(?:[·,\s]+(?:[FANS]-)?\d{2,3}(?:\s*~\s*\d{2,3})?)*", t):
|
|
seg = m.group(0)
|
|
last_pfx = None
|
|
for mm in tok.finditer(seg):
|
|
p, a, b = mm.group(1), mm.group(2), mm.group(3)
|
|
if p:
|
|
last_pfx = p
|
|
if last_pfx is None:
|
|
continue
|
|
ai = int(a)
|
|
bi = int(b) if b else ai
|
|
# sanity: within universe range
|
|
add(last_pfx, ai, bi, sn)
|
|
|
|
missing = sorted(k for k in UNIV if k not in cover)
|
|
print("=== RANGE-EXPANDED BADGE COVERAGE ===")
|
|
print("COVERED (badge):", len(cover), "/ 142")
|
|
print("NOT badge-covered (", len(missing), "):", ", ".join(missing))
|
|
|
|
# priority 7
|
|
prio = ["F-008", "F-010", "F-026", "F-032", "A-003", "A-005", "A-008"]
|
|
print("\n=== PRIORITY 7 BADGE STATUS ===")
|
|
for r in prio:
|
|
print(f"{r}: badge slides = {sorted(cover.get(r, []))}")
|
|
|
|
# dump per-covered for the previously-flagged 18
|
|
flagged = ["F-005","F-008","F-010","F-026","F-032","F-034","F-036","F-038","F-039","F-054","F-074","F-075","F-076","A-003","A-005","A-008","S-005","S-006"]
|
|
print("\n=== PREVIOUSLY-FLAGGED 18: badge coverage after range expansion ===")
|
|
for r in flagged:
|
|
sl = sorted(cover.get(r, []))
|
|
print(f"{r}: {'BADGE ' + str(sl) if sl else 'NO BADGE'}")
|