feat: implement Research Project PageView (v1.8) with static SSG pre-render and E2E gates
This commit is contained in:
@@ -443,6 +443,77 @@ def parse_standards():
|
||||
|
||||
return bodies
|
||||
|
||||
def parse_projects():
|
||||
bodies = parse_standards()
|
||||
body_map = {b["org"]: b for b in bodies}
|
||||
|
||||
# Extract deliverables for CCIS (IEC TC100)
|
||||
ccis_docs = []
|
||||
if "IEC TC100" in body_map:
|
||||
for p in body_map["IEC TC100"]["projects"]:
|
||||
for d in p["documents"]:
|
||||
ccis_docs.append({
|
||||
"title": d["title"],
|
||||
"ref": d["ref"],
|
||||
"status": d["status"]
|
||||
})
|
||||
|
||||
# Extract deliverables for VLC-IoT (ITU-T SG20)
|
||||
vlc_docs = []
|
||||
if "ITU-T SG20" in body_map:
|
||||
for p in body_map["ITU-T SG20"]["projects"]:
|
||||
for d in p["documents"]:
|
||||
vlc_docs.append({
|
||||
"title": d["title"],
|
||||
"ref": d["ref"],
|
||||
"status": d["status"]
|
||||
})
|
||||
|
||||
# Extract deliverables for IoT Standards (ISO/IEC JTC1/SC41)
|
||||
iot_docs = []
|
||||
if "ISO/IEC JTC1/SC41" in body_map:
|
||||
for p in body_map["ISO/IEC JTC1/SC41"]["projects"]:
|
||||
for d in p["documents"]:
|
||||
iot_docs.append({
|
||||
"title": d["title"],
|
||||
"ref": d["ref"],
|
||||
"status": d["status"]
|
||||
})
|
||||
|
||||
projects = [
|
||||
{
|
||||
"slug": "iot-standards",
|
||||
"title": "IoT Standards",
|
||||
"abstract": "Internet of Things covers a huge range of industries and use cases that scale from a single constrained device up to massive cross-platform deployments of embedded technologies and cloud systems connecting in real-time.",
|
||||
"keywords": ["Internet of Things", "embedded technologies", "cloud systems", "real-time"],
|
||||
"standardsOrg": "ISO/IEC JTC1/SC41",
|
||||
"period": body_map.get("ISO/IEC JTC1/SC41", {}).get("period", "2020 ~ Present"),
|
||||
"deliverables": iot_docs,
|
||||
},
|
||||
{
|
||||
"slug": "ccis",
|
||||
"title": "CCIS",
|
||||
"abstract": "In-Vehicle Infotainment (IVI) refers to vehicle systems that combine entertainment and information delivery to drivers and passengers. Configurable Car Infotainment Service (CCIS) is a service that helps users to more easily manage and control In-Vehicle infotainment devices and content.",
|
||||
"keywords": ["In-Vehicle Infotainment", "CCIS", "infotainment devices"],
|
||||
"standardsTrack": "IEC/TC 100/TA 17",
|
||||
"standardsOrg": "IEC TC100",
|
||||
"period": body_map.get("IEC TC100", {}).get("period", "2018 ~ Present"),
|
||||
"deliverables": ccis_docs,
|
||||
},
|
||||
{
|
||||
"slug": "vlc-iot",
|
||||
"title": "VLC-IoT",
|
||||
"abstract": "Visible-light communication (VLC) transmits data by intensity modulating optical sources, such as light-emitting diodes (LEDs) and laser diodes (LDs), faster than the persistence of the human eye. The goal of IoT-VLC is to design a framework of IoT services based on VLC.",
|
||||
"keywords": ["Visible-light communication", "VLC", "light-emitting diodes", "laser diodes", "IoT services"],
|
||||
"standardsTrack": "ITU-T SG20",
|
||||
"standardsOrg": "ITU-T SG20",
|
||||
"period": body_map.get("ITU-T SG20", {}).get("period", "2018 ~ 2020"),
|
||||
"deliverables": vlc_docs,
|
||||
}
|
||||
]
|
||||
|
||||
return projects
|
||||
|
||||
def clean_dict(obj):
|
||||
if isinstance(obj, dict):
|
||||
return {k: clean_dict(v) for k, v in obj.items() if v is not None}
|
||||
@@ -455,6 +526,7 @@ def main():
|
||||
intl_p, dom_p, pat_p = parse_publications()
|
||||
semesters = parse_lectures()
|
||||
bodies = parse_standards()
|
||||
projects = parse_projects()
|
||||
|
||||
os.makedirs(CONTENT_DIR, exist_ok=True)
|
||||
|
||||
@@ -481,5 +553,10 @@ def main():
|
||||
f.write('import { StandardsBody } from "./types";\n\n')
|
||||
f.write(f'export const standardsBodies: StandardsBody[] = {json.dumps(clean_dict(bodies), ensure_ascii=False, indent=2)};\n')
|
||||
|
||||
with open(os.path.join(CONTENT_DIR, "projects.ts"), "w", encoding="utf-8") as f:
|
||||
f.write('// AUTO-GENERATED by scripts/extract/generate_all.py — DO NOT EDIT BY HAND\n')
|
||||
f.write('import { ResearchProject } from "./types";\n\n')
|
||||
f.write(f'export const researchProjects: ResearchProject[] = {json.dumps(clean_dict(projects), ensure_ascii=False, indent=2)};\n')
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -14,17 +14,18 @@ MONTH_MAP = {
|
||||
}
|
||||
|
||||
def verify():
|
||||
from generate_all import parse_members, parse_publications, parse_lectures, parse_standards
|
||||
from generate_all import parse_members, parse_publications, parse_lectures, parse_standards, parse_projects
|
||||
|
||||
active_m, alumni_m = parse_members()
|
||||
intl_p, dom_p, pat_p = parse_publications()
|
||||
semesters = parse_lectures()
|
||||
bodies = parse_standards()
|
||||
projects = parse_projects()
|
||||
|
||||
total_pubs = len(intl_p) + len(dom_p) + len(pat_p)
|
||||
std_docs_count = sum(len(p["documents"]) for b in bodies for p in b["projects"])
|
||||
|
||||
print("=== DATA VERIFICATION GATE (AC-07 / AC-08 / AC-10 / AC-11 / VOLUME CROSS-CHECK) ===")
|
||||
print("=== DATA VERIFICATION GATE (AC-07 / AC-08 / AC-10 / AC-11 / AC-30 / VOLUME CROSS-CHECK) ===")
|
||||
print(f"Active Members: {len(active_m)} (Expected: 16)")
|
||||
print(f"Alumni: {len(alumni_m)} (Expected: 60)")
|
||||
print(f"International Papers: {len(intl_p)} (Expected: 68)")
|
||||
@@ -34,9 +35,20 @@ def verify():
|
||||
print(f"Lectures Semesters: {len(semesters)} (Expected: 45)")
|
||||
print(f"Standard Bodies: {len(bodies)} (Expected: 6)")
|
||||
print(f"Standard Documents: {std_docs_count} (Expected: 44)")
|
||||
print(f"Research Projects: {len(projects)} (Expected: 3)")
|
||||
|
||||
errors = []
|
||||
|
||||
if len(projects) != 3:
|
||||
errors.append(f"Research Projects count mismatch: got {len(projects)}, expected 3")
|
||||
|
||||
# AC-30: Keyword Substring Verification (Ensures zero hallucinated/created keywords)
|
||||
for proj in projects:
|
||||
abstract = proj.get("abstract", "")
|
||||
for kw in proj.get("keywords", []):
|
||||
if kw not in abstract:
|
||||
errors.append(f"AC-30 Keyword Violation in project '{proj.get('slug')}': keyword '{kw}' not in abstract")
|
||||
|
||||
# 1. Count checks
|
||||
if len(active_m) != 16:
|
||||
errors.append(f"Active Members count mismatch: got {len(active_m)}, expected 16")
|
||||
|
||||
Reference in New Issue
Block a user