纠正仓库内容为衍生项目,标明 campaign-200-r2 最新版

This commit is contained in:
toshiocn
2026-10-19 16:56:31 +08:00
parent a492c5b80e
commit fdca4f67ea
1396 changed files with 392768 additions and 19530 deletions
+13
View File
@@ -0,0 +1,13 @@
import fs from 'node:fs';import path from 'node:path';import {fileURLToPath} from 'node:url';import {definitions} from './definitions.mjs';
const root=path.resolve(path.dirname(fileURLToPath(import.meta.url)),'..');
const css=`*{box-sizing:border-box}body{margin:0;background:#f6f5fb;color:#292a43;font-family:system-ui,'Microsoft YaHei',sans-serif}main{max-width:620px;margin:auto;padding:20px 18px 32px}a{color:#6650bf}header{display:flex;justify-content:space-between;align-items:center}h1{font-size:26px;margin:10px 0 4px}h2{font-size:18px;margin:14px 0 8px}p{line-height:1.6;margin:8px 0;color:#66677e}.eyebrow{font-size:12px;letter-spacing:.1em;color:#7e728f}button{font:inherit;min-height:44px;border:1px solid #d8d5e5;border-radius:12px;background:white;color:#47405f;padding:9px 15px;cursor:pointer}button:focus-visible,a:focus-visible,textarea:focus-visible{outline:3px solid #a586ed}button.active{background:#6c56c8;border-color:#6c56c8;color:white}button:disabled{opacity:.4}nav,.controls,#constraints{display:flex;gap:8px;flex-wrap:wrap;margin:10px 0}#difficulties{display:grid;grid-template-columns:repeat(4,1fr)}#levels{margin-bottom:18px}.card{padding:14px;border:1px solid #e4e0ef;border-radius:20px;background:white;box-shadow:0 6px 26px #41336508}.meta{display:flex;justify-content:space-between;align-items:center;font-size:13px;color:#767286}#remaining{background:#ece7ff;color:#6650bf;padding:6px 10px;border-radius:20px;font-weight:700}canvas{display:block;width:100%;height:470px;touch-action:none}#status{min-height:48px;font-size:14px;color:#554b70;line-height:1.7}#caption{font-size:13px}#constraints{margin-bottom:0}.constraint{font-size:13px;min-height:36px;padding:6px 10px;background:#f7f4ff}.controls button{flex:1;padding:10px 8px}.controls button.primary{background:#6c56c8;color:white}details{margin-top:16px;padding:12px;background:#eeebf6;border-radius:12px}summary{cursor:pointer;font-weight:600;min-height:28px}textarea{width:100%;min-height:80px;font:inherit;margin:8px 0;border:1px solid #d5cce6;border-radius:8px;padding:10px}.small{font-size:12px}.cards{display:grid;gap:14px}.cards a{display:block;text-decoration:none;color:inherit}.cards .card:hover{border-color:#8d78cf}.pill{font-size:12px;color:#7c659a}footer{margin-top:22px;font-size:12px;color:#857d93}@media(max-width:400px){main{padding:12px}canvas{height:420px}h1{font-size:23px}button{padding:8px 10px}}@media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}`;
const esc=s=>s.replaceAll('&','&amp;').replaceAll('<','&lt;').replaceAll('>','&gt;');
for(const def of definitions){const folder=path.join(root,'modes',def.id),pack=JSON.parse(fs.readFileSync(path.join(folder,'levels.json'),'utf8').replace(/^\uFEFF/,''));
fs.copyFileSync(path.join(root,'tools','ui-template.mjs'),path.join(folder,'ui.mjs'));
let engine=fs.readFileSync(path.join(folder,'rules.mjs'),'utf8').replaceAll('export ','');let ui=fs.readFileSync(path.join(folder,'ui.mjs'),'utf8').replace(/^import[^\n]+\n/,'');
const script=`const PACK=${JSON.stringify(pack).replaceAll('<','\\u003c')};\n${engine}\n${ui}`;
const html=`<!doctype html><html lang="zh-CN"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${def.title} · 衍生玩法验证</title><style>${css}</style><main><header><a href="../../index.html">← 全部玩法</a><span class="eyebrow">路径推理实验室</span></header><h1 id="title"></h1><p class="small">四个难度 · 每档两关 · 全部开放</p><nav id="difficulties" aria-label="难度"></nav><nav id="levels" aria-label="关卡"></nav><section class="card"><div class="meta"><span id="position"></span><span id="remaining" aria-live="polite"></span></div><h2 id="goal"></h2><p id="caption"></p><div id="constraints" aria-label="本关条件"></div><canvas id="board" aria-label="关卡盘面;拖动或点按相邻格画路"></canvas><div id="status" role="status" aria-live="polite"></div></section><div class="controls"><button id="undo">撤销</button><button id="restart">重开</button><button id="hint">指路</button><button id="next" class="primary" hidden>下一关</button></div><p class="small">点按或拖动相邻格 · 松手可继续 · 点已走格回退</p><details open><summary>玩法规则</summary><p id="rule-text"></p><p class="small">固定数字必须在对应步到达。所有格各走一次。永久墙、关闭的门和同色移动会阻止移动;其他条件画错可继续,错误处标红。</p></details><details><summary>记录本关体验</summary><p class="small">用自己的话说明关键分叉为什么只能这样走。导出记录含首次错误、回退和提示次数。</p><textarea id="reasoning" aria-label="推理与试玩反馈" placeholder="我先排除了哪条路线?依据是什么?"></textarea><button id="export">导出试玩记录</button></details><footer>原创候选关 · 难度等待真人试玩校准 · 离线可用</footer></main><script>${script}</script></html>`;
fs.writeFileSync(path.join(folder,'play.html'),html);
}
fs.writeFileSync(path.join(root,'index.html'),`<!doctype html><html lang="zh-CN"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>一笔路径 · 衍生玩法验证</title><style>${css}</style><main><span class="eyebrow">NUMBER SWIPE · VARIANT LAB</span><h1>一笔路径,五种推理</h1><p>每个玩法 8 关:入门、普通、进阶、难,各 2 关。先观察,再一笔完成。</p><div class="cards"><a href="campaign-50/index.html" class="card"><span class="pill">可玩DEMO · 50关</span><h2>50关统一主线</h2><p>五章渐进 · 奇偶与机制组合 · 全部关卡开放</p></a>${definitions.map((d,i)=>`<a href="modes/${d.id}/play.html" class="card"><span class="pill">0${i+1} · 8 关</span><h2>${d.title}</h2><p>${esc(d.rule)}</p></a>`).join('')}</div><details><summary>设计说明与答案图</summary>${definitions.map(d=>`<p><a href="modes/${d.id}/DESIGN.html">${d.title} · 设计评审</a></p>`).join('')}</details><footer>40 个机制验证候选关 · 无计时、体力、分数 · 所有玩法均可离线打开</footer></main></html>`);
console.log('Built 5 standalone pages + index.');