- index.html: реальная персистентность (loadSave/applySave/persist/freshSave, SAVE_VERSION=1, форма сейва v1, base64-поле, миграции), резюм незавершённой партии после reload, авто-пауза при visibilitychange без перезаписи сейва; полировка: modeForState вместо мёртвого mode, валидация FIELD_SIZES, setFieldSize игнорирует чужие значения, согласованный дефолт fieldH, сброс hoverCell на pointerup/cancel, актуализирован комментарий mode. - tests/test.js: расширена 65 -> 123 проверок (резюм R1/R2/R3, миграция/битый сейв, настройки, resize, клики DOM-кнопок, applyIntent, паритет сохранён). - tools/old-ref/: harness паритета перенесён в репозиторий (old_ref.cpp, reference*.json, генераторы, diff-our.js, ref-*.txt, ce1.txt, README). - AGENTS.md/README.md: форма сейва, миграции, резюм, harness, структура. - .gitignore: секрет .gitea_token и бинарники/логи harness. - Прогоны: check: OK; npm test — ИТОГ 123/123; паритет clean 273/273. - Ревью-гейт 4 (Oracle): PASS; minor/mit закрыты.
57 lines
2.3 KiB
JavaScript
57 lines
2.3 KiB
JavaScript
'use strict';
|
|
/* Генерация эталона ЧИСТОГО правила (--clean) для всех кейсов reference.json.
|
|
Использует CLI-режим harness: ./old_ref <file.txt> <steps> --clean
|
|
Пишет reference-clean.json в той же структуре: [{name,w,h,steps:[ascii0..asciiN]}].
|
|
|
|
Запуск: node gen-clean.js
|
|
*/
|
|
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-clean.json');
|
|
const tmpPath = path.join(DIR, '.tmp-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), '--clean'], {
|
|
encoding: 'utf8',
|
|
});
|
|
// res = ascii0 + ("--- step k ---\n" + asciiK)*
|
|
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 clean == шаг 0 proto (начальное поле одинаково).
|
|
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) {}
|
|
|
|
// Сводка: сколько (кейс×шаг) разошлось proto vs clean.
|
|
let diff = 0, total = 0;
|
|
const diffCases = new Set();
|
|
for (let i = 0; i < ref.length; i++) {
|
|
for (let k = 1; k < ref[i].steps.length; k++) {
|
|
total++;
|
|
if (ref[i].steps[k] !== out[i].steps[k]) { diff++; diffCases.add(ref[i].name); }
|
|
}
|
|
}
|
|
console.log('reference-clean.json записан:', outPath);
|
|
console.log(`кейсов: ${out.length}, сравнений proto-vs-clean: ${total}, расхождений: ${diff}`);
|
|
console.log('кейсы с расхождениями proto≠clean:', [...diffCases].join(', ') || '(нет)');
|