- tests/test.js: 148 -> 206 проверок (разделы 23 wrap/torus, 24 зоны, 25 бюджет, 26 размеры, 27 сейв v2/миграция, 28 рендер/resize 300x300, 29 HUD 381-400px); resetGlobals сбрасывает tool/reason/winner; sleep заменён на waitCond/settleViewport. - tools/old-ref/: независимый torus-эталон (nextStepCleanWrap, CLI --torus, gen-torus.js, reference-torus.json); diff-our.js сверяет stepN при setWrap(true). - index.html: медиазапрос HUD 380->400px (убрана микро-обрезка 381-388px); инлайн-комментарий про согласованность useWrap/setWrap. - AGENTS.md: полный список контракта дополнен; useWrap-заметка уточнена; покрытие приведено в соответствие. README: скорость — константа в коде, не UI. - .gitignore: tools/old-ref/.tmp-*.txt. - Прогоны: check: OK; суита 206/206 (3 повтора); паритет clean 273/273 + torus 273/273. - Ревью-гейт R2-3 (Oracle): PASS; minor/nit закрыты.
67 lines
2.9 KiB
JavaScript
67 lines
2.9 KiB
JavaScript
'use strict';
|
||
/* Генерация эталона ЧИСТОГО правила НА ТОРЕ (--torus) для всех кейсов reference.json.
|
||
Опция «Замкнутая карта» — новая (в прототипе old заворотов не было), поэтому
|
||
независимого прототипного эталона нет; эталон считает тот же harness
|
||
(nextStepCleanWrap) с заворотом через края.
|
||
|
||
Использует CLI-режим harness: ./old_ref <file.txt> <steps> --torus
|
||
Пишет reference-torus.json в структуре: [{name,w,h,steps:[ascii0..asciiN]}].
|
||
|
||
Запуск: node gen-torus.js (из tools/old-ref/)
|
||
*/
|
||
const { execFileSync } = require('child_process');
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
|
||
const DIR = __dirname;
|
||
const refPath = path.join(DIR, 'reference.json');
|
||
const outPath = path.join(DIR, 'reference-torus.json');
|
||
const tmpPath = path.join(DIR, '.tmp-torus-case.txt');
|
||
|
||
const ref = JSON.parse(fs.readFileSync(refPath, 'utf8'));
|
||
const out = [];
|
||
|
||
for (const c of ref) {
|
||
const init = c.steps[0]; // ASCII начального поля (строки\n)
|
||
fs.writeFileSync(tmpPath, init);
|
||
const n = c.steps.length - 1; // число шагов
|
||
const res = execFileSync(path.join(DIR, 'old_ref'), [tmpPath, String(n), '--torus'], {
|
||
encoding: 'utf8',
|
||
});
|
||
const parts = res.split(/--- step \d+ ---\n/);
|
||
if (parts.length !== n + 1) {
|
||
throw new Error(`case ${c.name}: ожидалось ${n + 1} полей, получено ${parts.length}`);
|
||
}
|
||
out.push({ name: c.name, w: c.w, h: c.h, steps: parts });
|
||
}
|
||
|
||
// Санити-проверка: шаг 0 совпадает с начальным полем reference.json.
|
||
for (let i = 0; i < ref.length; i++) {
|
||
if (ref[i].steps[0] !== out[i].steps[0]) {
|
||
throw new Error(`шаг 0 расходится для ${ref[i].name}`);
|
||
}
|
||
}
|
||
|
||
fs.writeFileSync(outPath, JSON.stringify(out, null, 1) + '\n');
|
||
try { fs.unlinkSync(tmpPath); } catch (e) {}
|
||
|
||
// Сводка: сколько (кейс×шаг) разошлось clean(жёсткие) vs torus.
|
||
const cleanPath = path.join(DIR, 'reference-clean.json');
|
||
let diff = 0, total = 0;
|
||
const diffCases = new Set();
|
||
if (fs.existsSync(cleanPath)) {
|
||
const clean = JSON.parse(fs.readFileSync(cleanPath, 'utf8'));
|
||
const cleanByName = new Map(clean.map(c => [c.name, c]));
|
||
for (const c of out) {
|
||
const cl = cleanByName.get(c.name);
|
||
if (!cl) continue;
|
||
for (let k = 1; k < c.steps.length; k++) {
|
||
total++;
|
||
if (cl.steps[k] !== c.steps[k]) { diff++; diffCases.add(c.name); }
|
||
}
|
||
}
|
||
}
|
||
console.log('reference-torus.json записан:', outPath);
|
||
console.log(`кейсов: ${out.length}, сравнений clean(жёстк.)-vs-torus: ${total}, расхождений: ${diff}`);
|
||
console.log('кейсы, где torus ≠ жёсткие границы:', [...diffCases].join(', ') || '(нет)');
|