73 lines
3.7 KiB
Python
73 lines
3.7 KiB
Python
#!/usr/bin/env python3
|
||
"""РАСКЛАДКА СУДЕЙСКИХ ПАЧЕК ПО СЕССИЯМ и печать готовых промтов. $0.
|
||
|
||
Зачем скриптом, а не руками. Состав сессии — часть прибора, а не оформление: от него зависит,
|
||
(1) не попадут ли обе половины одной пары шумового пола к ОДНОМУ судье — тогда пол не поймает
|
||
межсессионную компоненту, и порог будет занижен, как в паке 23 на 19%; (2) одинаково ли
|
||
нагружены семейства — если Sol судит по 10 пачек за сессию, а Claude по 4, разница усталости
|
||
станет разницей семейств; (3) воспроизводима ли раскладка при пере-прогоне.
|
||
|
||
Обвязка берётся из `judge-prompts/{claude,sol}.md`, которые собраны из ОДНОГО ядра и сверяются
|
||
гейтом `paritet.py` (норма Д0.13 П-4). Здесь подставляется только список файлов.
|
||
|
||
⚠ Наборы `p1` и `p2` НИКОГДА не попадают в одну сессию: это разные половины пары пола.
|
||
|
||
Запуск: sessii.py план раскладки
|
||
sessii.py --write записать готовые промты файлами
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
ZONE = Path(__file__).resolve().parent
|
||
PROMPTS = ZONE / "judge-prompts"
|
||
FAM = {
|
||
"claude": dict(root=Path.home() / "sud-d4", tpl=PROMPTS / "claude.md"),
|
||
"sol": dict(root=Path.home() / "sol-d4-work", tpl=PROMPTS / "sol.md"),
|
||
}
|
||
PER_SESSION = 4 # как у харнесса Sol в паке 23; одинаково для обоих семейств
|
||
|
||
|
||
def batches(root: Path, half: str) -> list[list[str]]:
|
||
"""Пачки набора, разложенные по сессиям. Порядок — от имени файла, значит воспроизводим."""
|
||
toks = sorted(p.stem for p in (root / f"{half}-tasks").glob("*.txt"))
|
||
return [toks[i:i + PER_SESSION] for i in range(0, len(toks), PER_SESSION)]
|
||
|
||
|
||
def render(fam: str, half: str, toks: list[str]) -> str:
|
||
m = FAM[fam]
|
||
body = m["tpl"].read_text(encoding="utf-8")
|
||
lst = "\n".join(f" ~/{m['root'].name}/{half}-tasks/{t}.txt" for t in toks)
|
||
return body.replace("{СПИСОК ФАЙЛОВ}", lst)
|
||
|
||
|
||
def main() -> int:
|
||
write = "--write" in sys.argv
|
||
total = 0
|
||
for fam, m in FAM.items():
|
||
root = m["root"]
|
||
if not root.exists():
|
||
print(f"{fam}: каталога {root} нет — пропуск")
|
||
continue
|
||
out = root / "prompts"
|
||
if write:
|
||
out.mkdir(exist_ok=True)
|
||
print(f"\n=== {fam.upper()} ({root}) ===")
|
||
n = 0
|
||
for half in ("p1", "p2"):
|
||
for i, toks in enumerate(batches(root, half), 1):
|
||
n += 1
|
||
name = f"{half}-session-{i:02d}.md"
|
||
print(f" {name:22s} пачек {len(toks)}: {' '.join(toks)}")
|
||
if write:
|
||
(out / name).write_text(render(fam, half, toks), encoding="utf-8")
|
||
total += n
|
||
print(f" сессий у семейства: {n}" + (f" · записано в {out}" if write else ""))
|
||
print(f"\nвсего сессий: {total} · по {PER_SESSION} пачки · кап агент-сессий 80")
|
||
print("⚠ наборы p1 и p2 — разные половины пары пола, одному судье их отдавать НЕЛЬЗЯ")
|
||
return 0
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(main())
|