# -*- coding: utf-8 -*- """ Fetch final submission code per (student, problem) for CSP04 lesson 01 (基础回顾). Targets both CSP04 sections (0830 & 1400). Saves to JSON. """ import io, sys, json, re, httpx from collections import defaultdict from pathlib import Path sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace') sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace') PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent.parent env = {} for line in (PROJECT_ROOT / '.env').read_text(encoding='utf-8').split('\n'): line = line.strip() if line and not line.startswith('#') and '=' in line: k, v = line.split('=', 1) env[k] = v base = env.get('OJ_BASE_URL', 'https://oj.qonnwolf.com') TID = '6a8c6a8b8499477a04169f85' # CSP04 lesson 01 基础回顾 (A包) # 数字题目 -> 展示名(参考课件 OJ ID) PID_MAP = { 6775: 'S0401P1 小杨的回文串', 6776: 'S0401P2 小杨有序去重', 6777: 'S0401P3 小杨的进制数位', 6968: 'S0401P4 小杨的幸运数字', 6969: 'S0401P5 小杨的报数游戏', } CLASSES = { '0830': ['欧俊宇', '汪子杰', '谢明泓', '王佳琳', '魏铭轩', '张立坤'], '1400': ['郑子煜', '张雨禾', '苏俊宇', '卢华琛', '鲍佳音'], } ALL_TARGETS = sorted({n for lst in CLASSES.values() for n in lst}) STATUS_NAMES = {1: 'AC', 2: 'WA', 3: 'CE', 4: 'RE', 5: 'TLE', 6: 'MLE', 7: 'PE', 8: 'OLE'} client = httpx.Client(base_url=base, follow_redirects=True, timeout=30) r = client.post('/login', json={'uname': env.get('OJ_USERNAME'), 'password': env.get('OJ_PASSWORD')}) ok = any(c.name == 'sid' for c in client.cookies.jar) print('LOGIN:', 'OK' if ok else 'FAIL') if not ok: raise SystemExit('login failed') # 1. fetch all records for the homework records = [] seen = set() for page in range(1, 40): r = client.get(f'/d/system/record?tid={TID}&page={page}', headers={'Accept': 'application/json'}) if r.status_code != 200: break try: rdocs = r.json().get('rdocs', []) except Exception: break if not rdocs: break for rec in rdocs: rid = rec.get('_id') if rid in seen: continue seen.add(rid) records.append({ 'rid': rid, 'uid': rec.get('uid'), 'pid': rec.get('pid'), 'status': rec.get('status'), 'score': rec.get('score', 0), 'judgeAt': rec.get('judgeAt', ''), 'lang': rec.get('lang'), }) if len(rdocs) < 100: break print('TOTAL RECORDS:', len(records)) # 2. build uid -> name uids = {rec['uid'] for rec in records} uid_name = {} for uid in sorted(uids): try: rr = client.get(f'/user/{uid}') m = re.search(r'