Files
NumberSwipe_New/design/demo-50/build-h5.py
T

17 lines
14 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from pathlib import Path
import json,html
out=Path(r'G:\项目\NumberSwipe-Variants\design\demo-50');plan=json.loads((out/'demo-design.json').read_text(encoding='utf-8'));a=(out/'curve-a.svg').read_text(encoding='utf-8');b=(out/'curve-b.svg').read_text(encoding='utf-8');payload=json.dumps(plan,ensure_ascii=False).replace('<','\\u003c')
page=r'''<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>NumberSwipe · 50关DEMO设计与难度曲线</title><style>
:root{--bg:#0d1727;--panel:#15253c;--ink:#eaf0f7;--soft:#adc0d6;--line:#30455e;--mint:#76d6c3;--orange:#ffc781}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font:15px/1.7 system-ui,'Microsoft YaHei',sans-serif}main{max-width:1160px;margin:auto;padding:40px 24px 70px}header{padding:20px 0 24px}h1{font-size:clamp(28px,4vw,44px);line-height:1.3;margin:12px 0}h2{font-size:24px;margin:0 0 14px}h3{font-size:18px;margin:0 0 10px}p{color:var(--soft)}a{color:#9ec6ff}.eyebrow{color:var(--mint);font-size:12px;letter-spacing:.12em}.banner{border-left:4px solid var(--orange);padding:12px 16px;background:#332c32;margin:18px 0}.card{padding:20px;border:1px solid var(--line);background:var(--panel);border-radius:14px;margin:16px 0}.grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}.grid .card{margin:0}.number{font-size:32px;color:var(--mint);font-weight:750}.muted{font-size:12px;color:var(--soft)}section{margin:34px 0}button,select{font:inherit;color:var(--ink);background:#203752;border:1px solid #49617c;border-radius:8px;padding:8px 12px;min-height:42px}button{cursor:pointer}button.active{background:#2d635f;border-color:var(--mint)}button:focus-visible,select:focus-visible,a:focus-visible{outline:3px solid #f0d183}.controls{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:14px 0}.chart svg{width:100%;height:auto;display:block}.table-wrap{overflow:auto;border:1px solid var(--line);border-radius:12px}table{width:100%;border-collapse:collapse;min-width:850px;font-size:13px}th{background:#223650;text-align:left;white-space:nowrap}td,th{padding:11px 12px;border-bottom:1px solid var(--line);vertical-align:top}tr:nth-child(even){background:#15253c}tr.peak{background:#293f4c}td.score{font-weight:750;color:var(--mint)}.pill{display:inline-block;background:#274459;color:#bbdbe7;border-radius:20px;padding:2px 8px;font-size:12px;margin:2px}details{margin:15px 0;padding:18px;border:1px solid var(--line);border-radius:12px;background:var(--panel)}summary{cursor:pointer;font-weight:700}dl{display:grid;grid-template-columns:100px 1fr;gap:10px}dt{color:var(--mint)}dd{margin:0;color:var(--soft)}ul{color:var(--soft);padding-left:24px}li{margin:6px 0}.links{display:flex;gap:18px;flex-wrap:wrap}.callout{padding:14px;background:#173536;border-radius:10px}.two{display:grid;grid-template-columns:1fr 1fr;gap:16px}@media(max-width:740px){main{padding:20px 14px}.grid,.two{grid-template-columns:1fr}dl{grid-template-columns:1fr}dt{font-weight:700}}@media print{body{background:white;color:#111}p,dd,li{color:#333}.card,details{background:white}.controls,button{display:none}summary{font-size:16px}details{break-inside:avoid}table{min-width:0;font-size:10px}.chart svg{max-height:220px}}
</style></head><body><main><header><div class="eyebrow">NUMBERSWIPE · DEMO DESIGN · 2026-10-14</div><h1>50关DEMO<br>关卡设计与难度曲线</h1><p>外层缓慢成长,章内形成峰谷。前两关完成操作教学;以五关单元引入新机制,再通过结构与组合形成变化。</p><p class="callout"><strong>50关可玩版已制作:</strong><a href="../../campaign-50/index.html">打开50关DEMO →</a> 本页保留原始设计目标,制作验收见试玩目录报告。</p><div class="banner"><strong>制作任务规划 · 尚非可玩关卡包</strong><br>目标分、时间和推理层数是待测试假设。未生成50个具体盘面、未验证50关唯一解,也没有真人难度数据。</div><div class="links"><a href="DEMO_DESIGN.md">完整设计说明</a><a href="difficulty-curve.csv" download>下载曲线CSV</a><a href="VALIDATION_PLAN.md">制作与测试标准</a><a href="demo-design.json" download>设计任务JSON</a><a href="../../index.html">现有40关原型</a></div></header>
<div class="grid"><div class="card"><div class="number">50</div><strong>设计任务</strong><p class="muted">5章×10关;每关有推理意图和诱惑路线</p></div><div class="card"><div class="number">40 → 72</div><strong>阶段目标峰值</strong><p class="muted">策划标尺0–100,给长期扩展留出空间</p></div><div class="card"><div class="number">A / B</div><strong>同题库两种关序</strong><p class="muted">章节第8关峰值/章末峰值对照</p></div></div>
<section class="card"><h2>项目适配与边界</h2><div class="two"><div><h3>采用研究中的方法</h3><ul><li>难度看有效分叉、区域风险、错误发现延迟和推理依赖。</li><li>新技巧单独引入,再练习、变化、组合、巩固。</li><li>目标分、算法指标和真人表现分别保存。</li><li>章节峰谷与参数需测试,不能视为竞品内部标准。</li></ul></div><div><h3>坚持项目实际规则</h3><ul><li>数字是绝对访问步号;拼块整块一步,格数不等于面积。</li><li>方向通道只用于单位方格整盘;不继承到六边或大格。</li><li>奇偶优先用于大格/非双色六边,避免冗余。</li><li>门按落格切换,起点计入;单位方格不能靠随意绕圈补奇偶。</li></ul></div></div><p class="callout">现有Variants尚无奇偶判定,双色启用依赖玩法名称。组合主线需新增独立的features开关及奇偶支持;本次没有改动运行代码或手机体验。</p></section>
<section class="card"><h2>先验证六道桥接样题</h2><p>05异形共边、13拐角端口、18双色与墙、21单奇偶、24双奇偶协作、28大格与门位。均计入50关,不额外增加关数;对应规则先教会,再测试组合。</p><p>教学按课程顺序;难度校准先掌握规则,再交错代表题并隔开同盘形题。补充依据为原项目10月14日深度调研与45关结构审计,该审计不等于Variants的40关验证。</p></section><section><h2>目标难度曲线</h2><p>默认A的峰值在8、18、28、38、48关;末两关释放并顺畅收束。B使用同样50道题,把各章峰值移到章末。曲线不是通过概率。</p><div class="controls"><button id="a" class="active">A · 第8关峰值</button><button id="b">B · 章末峰值</button><button id="csv">导出当前关序CSV</button><span id="orderLabel" class="muted"></span></div><div class="chart" id="chartA">__SVG_A__</div><div class="chart" id="chartB" hidden>__SVG_B__</div></section>
<section><h2>五章节奏</h2><div class="table-wrap"><table><thead><tr><th>关卡</th><th>章节</th><th>新内容</th><th>主要任务</th><th>峰值</th></tr></thead><tbody id="chapters"></tbody></table></div></section>
<section><h2>50关逐关任务</h2><div class="controls"><label>章节 <select id="chapter"><option value="">全部</option></select></label><label>机制 <select id="feature"><option value="">全部</option></select></label><label>功能 <select id="role"><option value="">全部</option><option>章节峰值</option><option>释放</option><option>收束</option></select></label><span id="count" class="muted"></span></div><p class="muted">列表按当前A/B位置排列。点击“详细设计”查看布局、关键推理与排除依据;切换曲线不会更改关卡身份。</p><div class="table-wrap"><table><thead><tr><th>位置/设计号</th><th>标题/功能</th><th>几何/机制</th><th>节点目标</th><th>目标分</th><th>核心任务</th><th>思考P50目标</th></tr></thead><tbody id="tasks"></tbody></table></div><div id="details"></div></section>
<section class="card"><h2>制作与测试验收</h2><ul><li>每关先写推理,再做盘面:唯一解且所有新机制逐项必要,组合需有跨机制依赖。</li><li>几何邻接度、搜索节点数不能冒充有效分叉或真人难度;原型结构快照只作诊断。</li><li>先少量新玩家定性测试,再以足够样本比较A/B;分组固定,不在同一玩家中随机换曲线。</li><li>记录错误发现延迟、回退、提示、完成后下一关启动和后续返回;区分卡关、无聊和正常会话结束。</li><li>先验证关卡趣味和节奏,之后再调整手机触点、字号、反馈和动效。</li></ul></section>
<section class="card"><h2>51–100关与正式版</h2><p>优先用区域拓扑、对称破局、空洞、枢纽先后和线索位置开发变化,不要求第51关更难,也不要求新增机制。DEMO题目作为内容资产保留,正式首发前按测试筛选重排;上线后按章节与主题包扩展。</p><p>关卡ID、内容修订和显示顺序分开。重排不清空通关记录;实质重做的题有修订或新ID。过难好题可以进入挑战包。</p></section><footer class="muted">来源:用户提供的NumberSwipe_Research_H5.html+当前原型代码与40关数据只读核对。报告外部竞品统计未独立复算。详细一致性检查见plan-check.json。</footer></main>
<script>const PLAN=__PLAN__;const names={big:'大格/异形',walls:'墙',direction:'方向',alternation:'双色',parity:'奇偶','rhythm-door':'步进门'};const geo={square:'单位方格',blocks:'拼块',hex:'六边'};const $=id=>document.getElementById(id);let order='A';const lookup=new Map(PLAN.levels.map(l=>[l.levelId,l]));const esc=s=>String(s).replaceAll('&','&amp;').replaceAll('<','&lt;').replaceAll('>','&gt;').replaceAll('"','&quot;');function mechanism(l){return l.features.map(f=>names[f]).join('+')||'数字基础';}function option(el,v,text){const o=document.createElement('option');o.value=v;o.textContent=text;el.appendChild(o);}for(const c of PLAN.chapters)option($('chapter'),c.id,'第'+c.id+'章 · '+c.title);for(const [id,name]of Object.entries(names))option($('feature'),id,name);$('chapters').innerHTML=PLAN.chapters.map(c=>{const ls=PLAN.levels.filter(l=>l.chapter===c.id);return `<tr><td>${(c.id-1)*10+1}–${c.id*10}</td><td>${esc(c.title)}</td><td>${esc(c.introduced.map(k=>names[k]||({hex:'六边几何','unknown-start':'未知起点'})[k]).join('、')||'不新增规则')}</td><td>${esc(c.focus)}</td><td>${Math.max(...ls.map(l=>l.targetDifficulty))}</td></tr>`;}).join('');function render(){const ids=PLAN.orders[order].levelIds;const items=ids.map((id,i)=>({l:lookup.get(id),position:i+1})).filter(({l})=>(!$('chapter').value||l.chapter==$('chapter').value)&&(!$('feature').value||l.features.includes($('feature').value))&&(!$('role').value||l.role===$('role').value));$('count').textContent=`显示 ${items.length}/50关`;$('orderLabel').textContent=PLAN.orders[order].title;$('chartA').hidden=order!=='A';$('chartB').hidden=order!=='B';$('a').className=order==='A'?'active':'';$('b').className=order==='B'?'active':'';$('tasks').innerHTML=items.map(({l,position})=>`<tr class="${l.role==='章节峰值'?'peak':''}"><td>${position}<br><span class="muted">${esc(l.designKey)}</span></td><td><strong>${esc(l.title)}</strong><br>${esc(l.role)}${l.introduces?'<br><span class="pill">引入 '+esc(l.introduces)+'</span>':''}</td><td>${geo[l.geometry]}<br>${mechanism(l)}</td><td>${l.nodeCountTarget}</td><td class="score">${l.targetDifficulty}<br><span class="muted">${l.targetDifficultyBand.join('–')}</span></td><td>${esc(l.teachingGoal)}<br><a href="#detail-${l.designKey}">详细设计 ↓</a></td><td>${l.thinkingSecondsP50Target.join('–')}秒<br><span class="muted">待测目标</span></td></tr>`).join('');$('details').innerHTML=items.map(({l,position})=>`<details id="detail-${l.designKey}"><summary>${position} · ${esc(l.title)} · ${mechanism(l)} · 目标${l.targetDifficulty}</summary><dl><dt>盘面构造</dt><dd>${esc(l.layoutIntent)}</dd><dt>条件预算</dt><dd>${esc(l.constraintsBudget)}</dd><dt>关键顿悟</dt><dd>${esc(l.teachingGoal)}</dd><dt>诱惑路线</dt><dd>${esc(l.temptingRouteIntent)}</dd><dt>排除依据</dt><dd>${esc(l.rejectionReason)}</dd><dt>前置技能</dt><dd>${esc(l.prerequisiteSkills.join("、")||"无需前置")}</dd><dt>推理目标</dt><dd>有效选择${l.targetDecisionCount.join('–')}处;最长依赖约${l.targetDependencyDepth}层;${l.unknownStart?'起点未知':'给定起点'}。</dd><dt>项目落地</dt><dd>${esc(l.implementationNote)}</dd><dt>原型参考</dt><dd>${esc(l.sourceCandidates.join('、')||'新做基础题')};仅作构造参考。</dd><dt>当前状态</dt><dd>设计任务,尚无具体坐标/作者解/唯一性结果/真人测量。</dd></dl></details>`).join('');}for(const id of ['chapter','feature','role'])$(id).addEventListener('change',render);$('a').onclick=()=>{order='A';render();};$('b').onclick=()=>{order='B';render();};$('csv').onclick=()=>{const rows=PLAN.orders[order].levelIds.map((id,i)=>{const l=lookup.get(id);return [i+1,l.levelId,l.designKey,l.title,l.targetDifficulty,l.role];});const quote=x=>'"'+String(x).replaceAll('"','""')+'"';const text='\ufeffposition,level_id,design_key,title,target_difficulty,role\r\n'+rows.map(r=>r.map(quote).join(',')).join('\r\n');const u=URL.createObjectURL(new Blob([text],{type:'text/csv;charset=utf-8'}));const a=document.createElement('a');a.href=u;a.download='NumberSwipe_DEMO50_Order_'+order+'.csv';a.click();setTimeout(()=>URL.revokeObjectURL(u),1000);};render();</script></body></html>'''
page=page.replace('__SVG_A__',a).replace('__SVG_B__',b).replace('__PLAN__',payload);(out/'index.html').write_text(page,encoding='utf-8');print('Offline planning H5 written:',len(page),'characters')