更新技术美术明亮教具室版:字体、指路、教学与庆祝效果
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
import {readFileSync,writeFileSync} from 'node:fs';
|
||||
import {createHash} from 'node:crypto';
|
||||
const local=p=>new URL(p,import.meta.url);
|
||||
const tokens=JSON.parse(readFileSync(local('tokens.json'),'utf8'));
|
||||
function luminance(hex){
|
||||
if(!/^#[0-9a-f]{6}$/i.test(hex))throw Error('Expected opaque sRGB: '+hex);
|
||||
const c=[1,3,5].map(i=>parseInt(hex.slice(i,i+2),16)/255).map(v=>v<=.04045?v/12.92:((v+.055)/1.055)**2.4);
|
||||
return c[0]*.2126+c[1]*.7152+c[2]*.0722;
|
||||
}
|
||||
const resolve=k=>tokens.color[k]??k;
|
||||
const rows=tokens.contrastPairs.map(p=>{const foreground=resolve(p.fg),background=resolve(p.bg),a=luminance(foreground),b=luminance(background),ratio=(Math.max(a,b)+.05)/(Math.min(a,b)+.05);return {...p,foreground,background,ratio,pass:p.minimum===null?null:ratio>=p.minimum};});
|
||||
writeFileSync(local('contrast-audit.json'),JSON.stringify({method:'WCAG relative luminance; opaque sRGB; unrounded thresholds; static token pairs only, not complete UI compliance',rows},null,2)+'\n');
|
||||
console.table(rows.map(p=>({pair:p.name,ratio:p.ratio.toFixed(3),minimum:p.minimum,result:p.pass===null?'diagnostic':p.pass?'pass':'FAIL'})));
|
||||
const tracked=[
|
||||
'../../../README.md',
|
||||
'../../../wechat-campaign-200-r2/README.md',
|
||||
'../../../wechat-campaign-200-r2/src/upstream/levels.json',
|
||||
'../../../wechat-campaign-200-r2/src/upstream/rules.mjs',
|
||||
'../../../wechat-campaign-200-r2/src/main.mjs',
|
||||
'../../../wechat-campaign-200-r2/src/hints.mjs',
|
||||
'../../../modes/01-number-stroke/src/board.ts',
|
||||
'../../../modes/01-number-stroke/src/game.ts',
|
||||
'../../../modes/03-hex-walls/src/board.ts'
|
||||
];
|
||||
// Paths above resolve from docs/design/bright-classroom/ to repository root.
|
||||
const sources=tracked.map(path=>{const bytes=readFileSync(local(path));return {path,sha256:createHash('sha256').update(bytes).digest('hex')};});
|
||||
const p=JSON.parse(readFileSync(local('../../../wechat-campaign-200-r2/src/upstream/levels.json'),'utf8'));
|
||||
const countBy=fn=>p.levels.reduce((out,l)=>{const k=fn(l);out[k]=(out[k]??0)+1;return out;},{});
|
||||
const extent=l=>{if(l.geometry==='hex')return null;const points=l.cells.flatMap(c=>c.shape?c.shape.map(([x,y])=>[c.x+x,c.y+y]):Array.from({length:(c.w??1)*(c.h??1)},(_,i)=>[c.x+i%(c.w??1),c.y+Math.floor(i/(c.w??1))]));return {cols:Math.max(...points.map(p=>p[0]))-Math.min(...points.map(p=>p[0]))+1,rows:Math.max(...points.map(p=>p[1]))-Math.min(...points.map(p=>p[1]))+1};};
|
||||
const examples=p.levels.map(l=>({id:l.id,chapter:l.chapter,geometry:l.geometry,features:l.features,cells:l.cells.length,...extent(l)}));
|
||||
const audit={date:'2026-10-21',scope:'Read-only design inventory; not solver validation',sources,campaign:{levels:p.levels.length,chapters:p.chapters.length,playOrder:p.playOrder.length,geometry:countBy(l=>l.geometry),featureCounts:Object.fromEntries([...new Set(p.levels.flatMap(l=>l.features))].map(f=>[f,p.levels.filter(l=>l.features.includes(f)).length])),minCells:Math.min(...p.levels.map(l=>l.cells.length)),maxCells:Math.max(...p.levels.map(l=>l.cells.length)),nonemptyConstraintCounts:Object.fromEntries(['relations','orderChains','windows','walls','doors','gates'].map(k=>[k,p.levels.filter(l=>l[k]?.length).length]))},examples};
|
||||
writeFileSync(local('project-audit.json'),JSON.stringify(audit,null,2)+'\n');
|
||||
console.log(JSON.stringify(audit.campaign,null,2));
|
||||
if(rows.some(p=>p.pass===false))process.exitCode=1;
|
||||
@@ -0,0 +1,305 @@
|
||||
{
|
||||
"method": "WCAG relative luminance; opaque sRGB; unrounded thresholds; static token pairs only, not complete UI compliance",
|
||||
"rows": [
|
||||
{
|
||||
"name": "标题/黄底",
|
||||
"fg": "ink",
|
||||
"bg": "background",
|
||||
"minimum": 4.5,
|
||||
"foreground": "#43382F",
|
||||
"background": "#FFE69A",
|
||||
"ratio": 9.232457114035482,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "辅助文字/黄底",
|
||||
"fg": "inkSecondary",
|
||||
"bg": "background",
|
||||
"minimum": 4.5,
|
||||
"foreground": "#71604F",
|
||||
"background": "#FFE69A",
|
||||
"ratio": 4.884289301747754,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "正文/舞台",
|
||||
"fg": "ink",
|
||||
"bg": "stage",
|
||||
"minimum": 4.5,
|
||||
"foreground": "#43382F",
|
||||
"background": "#FFF6DF",
|
||||
"ratio": 10.566877010581722,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "辅助文字/舞台",
|
||||
"fg": "inkSecondary",
|
||||
"bg": "stage",
|
||||
"minimum": 4.5,
|
||||
"foreground": "#71604F",
|
||||
"background": "#FFF6DF",
|
||||
"ratio": 5.590243604512046,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "数字/未走块",
|
||||
"fg": "ink",
|
||||
"bg": "cellFace",
|
||||
"minimum": 4.5,
|
||||
"foreground": "#43382F",
|
||||
"background": "#FFF8EA",
|
||||
"ratio": 10.765868439756863,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "白数字/路径",
|
||||
"fg": "onPrimary",
|
||||
"bg": "primary",
|
||||
"minimum": 4.5,
|
||||
"foreground": "#FFFFFF",
|
||||
"background": "#6552D9",
|
||||
"ratio": 5.581827872446398,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "白字/按压紫",
|
||||
"fg": "onPrimary",
|
||||
"bg": "primaryPressed",
|
||||
"minimum": 4.5,
|
||||
"foreground": "#FFFFFF",
|
||||
"background": "#5140B7",
|
||||
"ratio": 7.589436402107891,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "白数字/错误",
|
||||
"fg": "onPrimary",
|
||||
"bg": "danger",
|
||||
"minimum": 4.5,
|
||||
"foreground": "#FFFFFF",
|
||||
"background": "#B93B46",
|
||||
"ratio": 5.56014089796343,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "错误说明/淡红",
|
||||
"fg": "dangerInk",
|
||||
"bg": "dangerSoft",
|
||||
"minimum": 4.5,
|
||||
"foreground": "#862735",
|
||||
"background": "#FBE4E5",
|
||||
"ratio": 7.358198572071083,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "珊瑚标签文字",
|
||||
"fg": "coralInk",
|
||||
"bg": "coral",
|
||||
"minimum": 4.5,
|
||||
"foreground": "#4F2418",
|
||||
"background": "#F57950",
|
||||
"ratio": 4.839371438999691,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "淡紫选中文字",
|
||||
"fg": "primaryPressed",
|
||||
"bg": "primarySoft",
|
||||
"minimum": 4.5,
|
||||
"foreground": "#5140B7",
|
||||
"background": "#ECE7FF",
|
||||
"ratio": 6.303185573751691,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "提示文字/淡黄",
|
||||
"fg": "hint",
|
||||
"bg": "hintSoft",
|
||||
"minimum": 4.5,
|
||||
"foreground": "#8B5E00",
|
||||
"background": "#FFF0B8",
|
||||
"ratio": 4.976695326004001,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "成功文字/淡绿",
|
||||
"fg": "success",
|
||||
"bg": "successSoft",
|
||||
"minimum": 4.5,
|
||||
"foreground": "#2E6B52",
|
||||
"background": "#DEEFDC",
|
||||
"ratio": 5.233622489592483,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "蓝类别标记",
|
||||
"fg": "categoryBlueInk",
|
||||
"bg": "categoryBlueFace",
|
||||
"minimum": 4.5,
|
||||
"foreground": "#245A92",
|
||||
"background": "#CEE4FF",
|
||||
"ratio": 5.4751847239513065,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "橙类别标记",
|
||||
"fg": "categoryOrangeInk",
|
||||
"bg": "categoryOrangeFace",
|
||||
"minimum": 4.5,
|
||||
"foreground": "#8A470E",
|
||||
"background": "#FFE0B2",
|
||||
"ratio": 5.54066890035091,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "数字/蓝类别面",
|
||||
"fg": "ink",
|
||||
"bg": "categoryBlueFace",
|
||||
"minimum": 4.5,
|
||||
"foreground": "#43382F",
|
||||
"background": "#CEE4FF",
|
||||
"ratio": 8.760129662894578,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "数字/橙类别面",
|
||||
"fg": "ink",
|
||||
"bg": "categoryOrangeFace",
|
||||
"minimum": 4.5,
|
||||
"foreground": "#43382F",
|
||||
"background": "#FFE0B2",
|
||||
"ratio": 8.972232377643234,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "格边/格面",
|
||||
"fg": "cellBoundary",
|
||||
"bg": "cellFace",
|
||||
"minimum": 3,
|
||||
"foreground": "#8A7660",
|
||||
"background": "#FFF8EA",
|
||||
"ratio": 4.10397343242954,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "格边/舞台",
|
||||
"fg": "cellBoundary",
|
||||
"bg": "stage",
|
||||
"minimum": 3,
|
||||
"foreground": "#8A7660",
|
||||
"background": "#FFF6DF",
|
||||
"ratio": 4.0281174489400735,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "路径/未走格",
|
||||
"fg": "primary",
|
||||
"bg": "cellFace",
|
||||
"minimum": 3,
|
||||
"foreground": "#6552D9",
|
||||
"background": "#FFF8EA",
|
||||
"ratio": 5.280691791017535,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "提示描边/舞台",
|
||||
"fg": "hintCasing",
|
||||
"bg": "stage",
|
||||
"minimum": 3,
|
||||
"foreground": "#43382F",
|
||||
"background": "#FFF6DF",
|
||||
"ratio": 10.566877010581722,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "提示白芯/描边",
|
||||
"fg": "hintCore",
|
||||
"bg": "hintCasing",
|
||||
"minimum": 3,
|
||||
"foreground": "#FFFFFF",
|
||||
"background": "#43382F",
|
||||
"ratio": 11.379801530993449,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "墙/黄色条纹",
|
||||
"fg": "wallInk",
|
||||
"bg": "wallStripe",
|
||||
"minimum": 3,
|
||||
"foreground": "#43382F",
|
||||
"background": "#F7C74D",
|
||||
"ratio": 7.1700148267761294,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "墙/舞台",
|
||||
"fg": "wallInk",
|
||||
"bg": "stage",
|
||||
"minimum": 3,
|
||||
"foreground": "#43382F",
|
||||
"background": "#FFF6DF",
|
||||
"ratio": 10.566877010581722,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "开门标记/舞台",
|
||||
"fg": "doorOpen",
|
||||
"bg": "stage",
|
||||
"minimum": 3,
|
||||
"foreground": "#2E6B52",
|
||||
"background": "#FFF6DF",
|
||||
"ratio": 5.836381119577005,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "关门标记/舞台",
|
||||
"fg": "doorClosed",
|
||||
"bg": "stage",
|
||||
"minimum": 3,
|
||||
"foreground": "#8B4B29",
|
||||
"background": "#FFF6DF",
|
||||
"ratio": 6.217581699869901,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "焦点/黄底",
|
||||
"fg": "focus",
|
||||
"bg": "background",
|
||||
"minimum": 3,
|
||||
"foreground": "#5140B7",
|
||||
"background": "#FFE69A",
|
||||
"ratio": 6.15732584714453,
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "白字/珊瑚(仅诊断,不采用)",
|
||||
"fg": "onPrimary",
|
||||
"bg": "coral",
|
||||
"minimum": null,
|
||||
"foreground": "#FFFFFF",
|
||||
"background": "#F57950",
|
||||
"ratio": 2.715535351933964,
|
||||
"pass": null
|
||||
},
|
||||
{
|
||||
"name": "格面/舞台(仅诊断,格边承担识别)",
|
||||
"fg": "cellFace",
|
||||
"bg": "stage",
|
||||
"minimum": null,
|
||||
"foreground": "#FFF8EA",
|
||||
"background": "#FFF6DF",
|
||||
"ratio": 1.0188316215827884,
|
||||
"pass": null
|
||||
},
|
||||
{
|
||||
"name": "蓝类别面/橙类别面(仅诊断,另配形状)",
|
||||
"fg": "categoryBlueFace",
|
||||
"bg": "categoryOrangeFace",
|
||||
"minimum": null,
|
||||
"foreground": "#CEE4FF",
|
||||
"background": "#FFE0B2",
|
||||
"ratio": 1.0242122802870215,
|
||||
"pass": null
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"meta":{"name":"NumberSwipe 明亮教具室","version":"1.0-proposal","date":"2026-10-21","status":"Design specification; not applied to runtime","unit":"logical layout unit, not physical pixel","reference":[375,812]},
|
||||
"color":{
|
||||
"background":"#FFE69A","backgroundBottom":"#FFDE79","pattern":"#E8BE54","stage":"#FFF6DF","surface":"#FFFBF2","surfaceMuted":"#F1E6D0","cellFace":"#FFF8EA","cellDepth":"#D8C4A0","cellBoundary":"#8A7660","cellBevel":"#FFFFFF",
|
||||
"ink":"#43382F","inkSecondary":"#71604F","primary":"#6552D9","primaryPressed":"#5140B7","primaryDepth":"#49379E","primarySoft":"#ECE7FF","primaryEdge":"#ADA0F1","onPrimary":"#FFFFFF",
|
||||
"coral":"#F57950","coralInk":"#4F2418","coralSoft":"#FFE0CF","danger":"#B93B46","dangerDepth":"#8D2934","dangerSoft":"#FBE4E5","dangerInk":"#862735",
|
||||
"hint":"#8B5E00","hintSoft":"#FFF0B8","hintCore":"#FFFFFF","hintCasing":"#43382F","hintRibbon":"#F49B75","hintRibbonDepth":"#C96E48","hintRibbonLight":"#FFF5DD","hintSpark":"#FFFDF0","success":"#2E6B52","successSoft":"#DEEFDC",
|
||||
"categoryBlueFace":"#CEE4FF","categoryBlueInk":"#245A92","categoryOrangeFace":"#FFE0B2","categoryOrangeInk":"#8A470E","wallInk":"#43382F","wallStripe":"#F7C74D","doorClosed":"#8B4B29","doorOpen":"#2E6B52","disabledFace":"#E9E1D3","disabledInk":"#7A7064","focus":"#5140B7","overlay":"#43382F"
|
||||
},
|
||||
"referenceMatch":{
|
||||
"version":"2-reference-cushion","authority":"User-supplied reference image; overrides earlier flat production proposal",
|
||||
"color":{"background":"#FFE383","backgroundBottom":"#FFDA68","pattern":"#EFBF4D","stage":"#FAEED6","surface":"#FBEFD9","cellFace":"#F9EDD5","cellDepth":"#CDB590","ink":"#51452E","inkSecondary":"#796644","primary":"#8178F4","primaryPressed":"#7369DF","primaryDepth":"#5750BA","primaryEdge":"#B7AAFF","coral":"#FF7946"},
|
||||
"pitchMax":104,"bridgeRatio":0.25,"cellDepthRatio":0.085,"cellDepthMax":7,"bevelRatio":0.085,"stageMargin":12,"buttonRadiusRatio":0.32,
|
||||
"conditionFrames":false,"endpointCorners":false,"categoryVisitedFrames":false
|
||||
},
|
||||
"font":{"numeric":"Nunito","cjk":"Noto Sans SC","fallback":"system-ui, -apple-system, Segoe UI, Microsoft YaHei, sans-serif","numericWeight":800,"bodyWeight":500,"labelWeight":600,"headingWeight":700},
|
||||
"type":{"display":{"size":32,"line":40,"weight":800},"pageTitle":{"size":24,"line":32,"weight":700},"section":{"size":18,"line":26,"weight":700},"body":{"size":16,"line":24,"weight":500},"button":{"size":16,"line":22,"weight":700},"label":{"size":14,"line":20,"weight":600},"caption":{"size":13,"line":18,"weight":500},"micro":{"size":12,"line":16,"weight":500}},
|
||||
"spacing":[4,8,12,16,20,24,32,40,48],
|
||||
"layout":{"referenceWidth":375,"referenceHeight":812,"margin":20,"compactMargin":16,"topbarHeight":48,"headerHeight":40,"statusHeight":28,"playfieldHeight":464,"feedbackHeight":40,"actionHeight":64,"actionGap":10,"tapTarget":48,"pitchPreferred":56,"pitchTargetMin":44,"pitchReviewBelow":44,"tileInsetRatio":0.045,"bridgeThicknessRatio":0.42,"stagePadding":16},
|
||||
"radius":{"small":8,"label":12,"button":18,"stage":28,"card":24,"sheet":28,"dialog":24,"cellRatio":0.18,"cellMin":6,"cellMax":12,"concaveMaxRatio":0.06,"hexMaxRatio":0.11},
|
||||
"material":{"light":"upper-left","cellDepthRatio":0.055,"cellDepthMin":2,"cellDepthMax":4,"pressedDepth":1,"cellBoundary":1.25,"bevelWidth":1,"gradientChannelDeltaMax":6,"cellShadow":{"x":0,"y":3,"blur":5,"alpha":0.10},"stageShadow":{"x":0,"y":4,"blur":10,"alpha":0.08},"buttonShadow":{"x":0,"y":3,"blur":5,"alpha":0.12},"dialogShadow":{"x":0,"y":12,"blur":28,"alpha":0.16}},
|
||||
"motionMs":{"fast":120,"base":200,"slow":320,"hold":500,"buttonPress":80,"buttonRelease":120,"step":140,"bridge":120,"undo":100,"conflict":200,"hintAttention":2400,"hintSegmentCycleMin":1200,"door":160,"spinner":160,"clearSweep":320,"clearHold":500,"entryStagger":12,"entryStaggerCap":120},
|
||||
"motion":{"easeOut":[0.22,1,0.36,1],"stepPeak":1.015,"stepPressed":0.985,"buttonPressed":0.98,"conflictTravelMax":1.5,"spinnerDegrees":120,"ambientAnimation":false,"reducedMotionHint":"static dashed path; keep all hint information"},
|
||||
"contrastPairs":[
|
||||
{"name":"标题/黄底","fg":"ink","bg":"background","minimum":4.5},
|
||||
{"name":"辅助文字/黄底","fg":"inkSecondary","bg":"background","minimum":4.5},
|
||||
{"name":"正文/舞台","fg":"ink","bg":"stage","minimum":4.5},
|
||||
{"name":"辅助文字/舞台","fg":"inkSecondary","bg":"stage","minimum":4.5},
|
||||
{"name":"数字/未走块","fg":"ink","bg":"cellFace","minimum":4.5},
|
||||
{"name":"白数字/路径","fg":"onPrimary","bg":"primary","minimum":4.5},
|
||||
{"name":"白字/按压紫","fg":"onPrimary","bg":"primaryPressed","minimum":4.5},
|
||||
{"name":"白数字/错误","fg":"onPrimary","bg":"danger","minimum":4.5},
|
||||
{"name":"错误说明/淡红","fg":"dangerInk","bg":"dangerSoft","minimum":4.5},
|
||||
{"name":"珊瑚标签文字","fg":"coralInk","bg":"coral","minimum":4.5},
|
||||
{"name":"淡紫选中文字","fg":"primaryPressed","bg":"primarySoft","minimum":4.5},
|
||||
{"name":"提示文字/淡黄","fg":"hint","bg":"hintSoft","minimum":4.5},
|
||||
{"name":"成功文字/淡绿","fg":"success","bg":"successSoft","minimum":4.5},
|
||||
{"name":"蓝类别标记","fg":"categoryBlueInk","bg":"categoryBlueFace","minimum":4.5},
|
||||
{"name":"橙类别标记","fg":"categoryOrangeInk","bg":"categoryOrangeFace","minimum":4.5},
|
||||
{"name":"数字/蓝类别面","fg":"ink","bg":"categoryBlueFace","minimum":4.5},
|
||||
{"name":"数字/橙类别面","fg":"ink","bg":"categoryOrangeFace","minimum":4.5},
|
||||
{"name":"格边/格面","fg":"cellBoundary","bg":"cellFace","minimum":3},
|
||||
{"name":"格边/舞台","fg":"cellBoundary","bg":"stage","minimum":3},
|
||||
{"name":"路径/未走格","fg":"primary","bg":"cellFace","minimum":3},
|
||||
{"name":"提示描边/舞台","fg":"hintCasing","bg":"stage","minimum":3},
|
||||
{"name":"提示白芯/描边","fg":"hintCore","bg":"hintCasing","minimum":3},
|
||||
{"name":"墙/黄色条纹","fg":"wallInk","bg":"wallStripe","minimum":3},
|
||||
{"name":"墙/舞台","fg":"wallInk","bg":"stage","minimum":3},
|
||||
{"name":"开门标记/舞台","fg":"doorOpen","bg":"stage","minimum":3},
|
||||
{"name":"关门标记/舞台","fg":"doorClosed","bg":"stage","minimum":3},
|
||||
{"name":"焦点/黄底","fg":"focus","bg":"background","minimum":3},
|
||||
{"name":"白字/珊瑚(仅诊断,不采用)","fg":"onPrimary","bg":"coral","minimum":null},
|
||||
{"name":"格面/舞台(仅诊断,格边承担识别)","fg":"cellFace","bg":"stage","minimum":null},
|
||||
{"name":"蓝类别面/橙类别面(仅诊断,另配形状)","fg":"categoryBlueFace","bg":"categoryOrangeFace","minimum":null}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user