export function applyLayeredFeedback(source){ const replace=(old,value)=>{if(!source.includes(old))throw Error('Layered feedback seam changed: '+old.slice(0,80));source=source.replace(old,value);}; source="import {feedback} from '../feedback.mjs';\nimport {inBacktrackCore} from '../backtrack.mjs';\n"+source; replace('const labels=new Map();',"feedback.attach(sound,wx,localStorage);\nconst labels=new Map();"); replace('function start(i,open=true){','function start(i,open=true){feedback.reset();'); replace("function markError(id,message){sound.play('error');","function markError(id,message){feedback.emit('error',level,id,path.at(-1)===id?path.length:path.length+1);"); replace("record.backtracks++;path.pop();sound.play('undo');","record.backtracks++;const removed=path.pop();feedback.emit('undo',level,removed,path.length,{from:path.at(-1)});"); replace("path.pop();sound.play('undo');record.backtracks++;","const removed=path.pop();feedback.emit('undo',level,removed,path.length,{from:path.at(-1)});record.backtracks++;"); const audio="if(path.length1?'checkpoint':'correct'):'move',0,path.length)"; replace(audio,"if(path.length1&&cell.clue===path.length)||cell.parity||cell.direction?'checkpoint':'move',level,id,path.length,{from:path.at(-2),ribbon:cell.clue>1&&cell.clue===path.length})"); replace("sound.play('complete',0)","feedback.emit('complete',level,id,path.length,{from:path.at(-2)})"); replace("sound.unlock();sound.play('restart');","feedback.reset();sound.unlock();sound.play('restart');"); replace('advance(hit(a[0]+(p[0]-a[0])*i/steps,a[1]+(p[1]-a[1])*i/steps))','advanceAt(a[0]+(p[0]-a[0])*i/steps,a[1]+(p[1]-a[1])*i/steps)'); source+=`\nfunction advanceAt(x,y){const id=hit(x,y);if(path.length>=2&&id===path.at(-2)&&!inBacktrackCore(polygons,id,x,y,unit))return;advance(id);}\n`; for(const event of ['pointerdown','pointermove']){ const line=source.split('\n').find(l=>l.startsWith(`canvas.addEventListener('${event}',e=>{`));if(!line)throw Error('Missing input batch '+event); const normalized=line.trimEnd(),at=normalized.indexOf('e=>{')+4;source=source.replace(line,normalized.slice(0,at)+'feedback.begin();try{'+normalized.slice(at,-3)+'}finally{feedback.end();}});'); } source=source.replace("$('btn-back').onclick=showSelect;","$('btn-back').onclick=()=>{feedback.reset();showSelect();};"); return source; }