From bd5c4850da54d08ff7a931c548c8ff37c383ffb2 Mon Sep 17 00:00:00 2001 From: heaven Date: Fri, 14 Aug 2026 17:15:23 +0300 Subject: [PATCH] Parameterize the judging harness by axis so the en panel gets its own work dir, blind keys, arm list and contrast family --- eval/dovodka/sud.py | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/eval/dovodka/sud.py b/eval/dovodka/sud.py index bb384077..bc6bf139 100644 --- a/eval/dovodka/sud.py +++ b/eval/dovodka/sud.py @@ -67,11 +67,19 @@ import absjudge as AJ # noqa: E402 # ⚠ РАБОЧИЙ КАТАЛОГ СУДЬИ — ВНЕ `~/books/dovodka`. Рядом с заданиями не должно лежать ни ключа # слепых меток, ни сырья с полем `arm`, ни кода. Ключи живут ОТДЕЛЬНО и судье не выдаются. -WORK = Path.home() / "sud-d4" +# ⚠ ОСЬ — ПАРАМЕТР. Каталоги, ключи, состав панели и семейство контрастов у английской оси свои, +# и класть её пачки рядом с китайскими нельзя: судья, увидевший обе, перестаёт быть слепым к +# паре, а ключи разных осей в одном каталоге — прямая дорога к разбору чужой приманки (класс, +# уже пойманный дважды: `itog_d4.py:53` и селфтест этого файла). +AXIS = next((a.split("=", 1)[1] for a in sys.argv if a.startswith("--axis=")), "d4") +if AXIS not in ("d4", "d3"): + raise SystemExit(f"⛔ ось {AXIS} харнессу неизвестна") + +WORK = Path.home() / f"sud-{AXIS}" TASKS1, TASKS2 = WORK / "p1-tasks", WORK / "p2-tasks" ANSW1, ANSW2 = WORK / "p1-answers", WORK / "p2-answers" VOTES = WORK / "votes" -KEYS = Path.home() / "books" / "dovodka" / "blind-keys-d4" # НЕ в WORK: судья туда не ходит +KEYS = Path.home() / "books" / "dovodka" / f"blind-keys-{AXIS}" # НЕ в WORK: судья туда не ходит # ⚠ ПЕРЕВОДИМ РИГ НА КЛЮЧИ ФАЗЫ СРАЗУ, а не только внутри `emit`. Селфтест зовёт `AJ._plant` # напрямую и при дефолтном `AJ.KEYS` строил приманку ПОСАДКАМИ ЧУЖОГО ПАКА (7 против 6, правила # разные) — то есть гейт «грубый декой грубее маржевого» сертифицировал не тот текст, который @@ -82,6 +90,13 @@ AJ.KEYS = KEYS ARMS_D4 = ("A0", "A1B", "A2", "A3", "A4", "A1") ARMS_OLD = ("A6", "A6F") # есть только у 16 старых единиц +# Панель английской оси. `D0` — черновик: он ЧЛЕН панели, потому что первичный контраст оси +# именно `E0/D0` (H-3 «покупает ли редактор поверх черновика»), а не контраст контуров. +ARMS_D3 = ("D0", "E0", "E1", "E2", "E4") +FAMILY_D3 = [ + ("E0", "D0", "боевой редактор поверх черновика (H-3, несущая оси)"), +] + # ⚠ ПЕРВИЧНОЕ СЕМЕЙСТВО — по одному контрасту на гипотезу владельца, Холм по трём. Объявлено в # пре-реге Д0.5 и `power.py`; здесь оно ПОВТОРЕНО, а не переопределено, и впечатывается в ключ # до первого ответа судьи. @@ -113,6 +128,30 @@ MARGIN_PLANTS = [ MARGIN_MIN = 2 # клетка, где посадить удалось меньше, в маржевый декой не идёт +ARMS = ARMS_D3 if AXIS == "d3" else ARMS_D4 +FAMILY = FAMILY_D3 if AXIS == "d3" else FAMILY_D4 +BASE_ARM = "E0" if AXIS == "d3" else "A0" # эталон, против которого строится декой и пол + + +def _wire_axis() -> None: + """Включить пару оси. Для d4 — no-op (китайская пара и так умолчание).""" + if AXIS == "d3": + import importlib.util # noqa: PLC0415 + sp = importlib.util.spec_from_file_location( + "en_axis_sud", Path(__file__).resolve().parent / "en_axis.py") + ax = importlib.util.module_from_spec(sp) + sys.modules["en_axis_sud"] = ax + sp.loader.exec_module(ax) + # ⚠ НЕ `ax.wire()`: драйвер держит СВОЙ экземпляр контура, и его настройка нашего не + # касается — судейство осталось бы на китайской паре с 31 единицей вместо 16. Ловушка + # та же, что с кассой (`money_d` настраивал свой экземпляр). Настраиваем СВОЙ. + C.configure(C.PARA.EN, units_provider=ax.units, + base_draft_hook=ax.base_draft, base_a0_hook=ax.base_e0) + + +_wire_axis() + + def units(): """Единицы, допустимые к судейству: без брака базы и без клеток finish=length.""" return C.units_ok()