fix: 填空题智能匹配(空格/逗号/小数) + 即时显示解析, exam模式同步修复
This commit is contained in:
+55
-28
@@ -956,13 +956,14 @@ function examCli(j){
|
|||||||
if(kor)examScore++;examIdx++;setTimeout(showExamQ,400);
|
if(kor)examScore++;examIdx++;setTimeout(showExamQ,400);
|
||||||
}
|
}
|
||||||
function examCfil(){
|
function examCfil(){
|
||||||
let q=Q.find(x=>x.id===examQid[examIdx]);if(!q)return;
|
let q=Q.find(function(x){return x.id===examQid[examIdx];});if(!q)return;
|
||||||
let v=$('eip')?$('eip').value.trim():'';if(!v)return;
|
let v=$(('eip'))?$(('eip')).value.trim():'';if(!v)return;
|
||||||
let kor=v===q.ans;
|
function n(s){return s.replace(/[\s,,、;;。..]+/g,",").replace(/^,+|,+$/g,"").replace(/,+/g,",").replace(/\s+/g,"").toLowerCase();}
|
||||||
let inp=$('eip');inp.disabled=true;inp.className='inp '+(kor?'ok':'no');
|
var kor=n(v)===n(q.ans);
|
||||||
|
if(!kor){var nv=parseFloat(v);var na=parseFloat(q.ans);if(!isNaN(nv)&&!isNaN(na)&&Math.abs(nv-na)<0.001)kor=true;}
|
||||||
|
var inp=$(('eip'));inp.disabled=true;inp.className='inp '+(kor?'ok':'no');
|
||||||
if(kor)examScore++;examIdx++;setTimeout(showExamQ,600);
|
if(kor)examScore++;examIdx++;setTimeout(showExamQ,600);
|
||||||
}
|
}function finishExam(){
|
||||||
function finishExam(){
|
|
||||||
if(examTimer){clearInterval(examTimer);examTimer=null;}
|
if(examTimer){clearInterval(examTimer);examTimer=null;}
|
||||||
$('eh').className='exam-hdr';
|
$('eh').className='exam-hdr';
|
||||||
let pct=examQid.length?Math.round(examScore/examQid.length*100):0;
|
let pct=examQid.length?Math.round(examScore/examQid.length*100):0;
|
||||||
@@ -1103,42 +1104,68 @@ function showFullExp(id){
|
|||||||
cd.appendChild(fb);upd();
|
cd.appendChild(fb);upd();
|
||||||
}
|
}
|
||||||
function cfil(id){
|
function cfil(id){
|
||||||
let q=Q.find(x=>x.id===id);if(!q)return;
|
let q=Q.find(function(x){return x.id===id;});if(!q)return;
|
||||||
let v=$('ip'+id)?$('ip'+id).value.trim():'';if(!v)return;
|
let v=$('ip'+id)?$('ip'+id).value.trim():'';if(!v)return;
|
||||||
let kor=(v===q.ans);
|
// Normalize both input and answer for flexible comparison
|
||||||
|
function normalize(s){
|
||||||
|
return s.replace(/[\s,,、;;。..]+/g,",").replace(/^,+|,+$/g,"").replace(/,+/g,",").replace(/\s+/g,"").toLowerCase();
|
||||||
|
}
|
||||||
|
let userNorm=normalize(v);
|
||||||
|
let ansNorm=normalize(q.ans);
|
||||||
|
// Support partial match for comma-separated answers
|
||||||
|
let kor=(userNorm===ansNorm);
|
||||||
|
if(!kor&&ansNorm.indexOf(",")>0){
|
||||||
|
let userParts=userNorm.split(",").filter(function(p){return p.length>0;});
|
||||||
|
let ansParts=ansNorm.split(",").filter(function(p){return p.length>0;});
|
||||||
|
if(userParts.length===ansParts.length){
|
||||||
|
var allMatch=true;
|
||||||
|
for(var pi=0;pi<ansParts.length;pi++){
|
||||||
|
if(userParts[pi]!==ansParts[pi]){allMatch=false;break;}
|
||||||
|
}
|
||||||
|
kor=allMatch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Also support mathematical equivalence for fraction/decimal
|
||||||
|
if(!kor){
|
||||||
|
var numV=parseFloat(v);
|
||||||
|
var numAns=parseFloat(q.ans);
|
||||||
|
if(!isNaN(numV)&&!isNaN(numAns)&&Math.abs(numV-numAns)<0.001)kor=true;
|
||||||
|
}
|
||||||
conv[id]=kor?q.ans:'__w__';recAns(id,kor);if(kor)AUDIO.correct();else AUDIO.wrong();
|
conv[id]=kor?q.ans:'__w__';recAns(id,kor);if(kor)AUDIO.correct();else AUDIO.wrong();
|
||||||
let inp=$('ip'+id);inp.disabled=true;inp.className='inp '+(kor?'ok':'no');
|
let inp=$('ip'+id);inp.disabled=true;inp.className='inp '+(kor?'ok':'no');
|
||||||
let br=inp.parentElement.querySelector('.br');if(br)br.remove();
|
let br=inp.parentElement.querySelector('.br');if(br)br.remove();
|
||||||
if(!kor){
|
// Always show explanation immediately (remove hint-first flow)
|
||||||
let m=meta[id];
|
let cd=inp.closest('.cd');
|
||||||
if(m&&m.h===0){
|
let existingFB=cd?cd.querySelector('.fb'):null;
|
||||||
m.h=1;let cd=inp.closest('.cd');
|
if(existingFB)existingFB.remove();
|
||||||
let ht=document.createElement('div');ht.className='ht sh';
|
|
||||||
ht.innerHTML='💡 提示: '+getHintText(q)+'<br><span class="rt" onclick="retryFill(\''+id+'\')">🔄 再试一次</span><span style="margin-left:8px" class="rt" onclick="showFullExp(\''+id+'\')">👀 看解析</span>';
|
|
||||||
cd.appendChild(ht);return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let fb=document.createElement('div');
|
let fb=document.createElement('div');
|
||||||
fb.className='fb sh '+(kor?'go':'bd');
|
fb.className='fb sh '+(kor?'go':'bd');
|
||||||
fb.innerHTML=(kor?'✅ PERFECT! 完美通过!':'❌ MISS! 再练练!')+'<br><strong>🔧 维修站解析:</strong>'+q.exp;
|
if(kor){
|
||||||
if(!kor)fb.innerHTML+='<br><strong>正确赛道路线:</strong>'+q.ans;
|
fb.innerHTML='✅ PERFECT! 完美通过!<br><strong>🔧 维修站解析:</strong>'+q.exp;
|
||||||
inp.parentElement.appendChild(fb);
|
}else{
|
||||||
if(!kor){
|
fb.innerHTML='❌ MISS! 再练练!<br><strong>🔧 维修站解析:</strong>'+q.exp+'<br><strong>✅ 正确答案:</strong>'+q.ans;
|
||||||
let sims=getSimQuestions(q,3);
|
if(v!==q.ans)fb.innerHTML+='<br><small style="color:#888;">你的答案: '+v+'</small>';
|
||||||
|
// Show similar questions for practice
|
||||||
|
let sims=getSimQuestions(q,2);
|
||||||
if(sims.length){
|
if(sims.length){
|
||||||
let cd=inp.closest('.cd');let sdiv=document.createElement('div');sdiv.className='sim sh';
|
let sdiv=document.createElement('div');sdiv.className='sim sh';
|
||||||
let shtml='<span class="tp2">🏎 关联练习(同题型巩固)</span>';
|
let shtml='<span class="tp2">🏎 关联练习(同题型巩固)</span>';
|
||||||
sims.forEach((sq,si)=>{
|
sims.forEach(function(sq,si){
|
||||||
shtml+='<div class="st">'+(si+1)+'. '+sq.stem.replace(/\n/g,'<br>')+'</div>';
|
shtml+='<div class="st">'+(si+1)+'. '+sq.stem.replace(/\n/g,'<br>')+'</div>';
|
||||||
if(sq.type==='choice'){shtml+='<div class="opts">';sq.opts.forEach((o,j)=>{let c='op';shtml+='<button class="'+c+'" onclick="cli(\''+sq.id+'\','+j+')" id="oc'+sq.id+'_'+j+'">'+o+'</button>';});shtml+='</div>';}
|
if(sq.type==='choice'){
|
||||||
else{shtml+='<input class="inp" id="ip'+sq.id+'" placeholder="输入答案..."><div class="br"><button class="cf" onclick="cfil(\''+sq.id+'\')">🏎 确认</button><button class="sh" onclick="skip(\''+sq.id+'\')">👀 解析</button></div>';}
|
shtml+='<div class="opts">';
|
||||||
|
sq.opts.forEach(function(o,j2){shtml+='<button class="op" onclick="cli(\''+sq.id+'\','+j2+')" id="oc'+sq.id+'_'+j2+'">'+o+'</button>';});
|
||||||
|
shtml+='</div>';
|
||||||
|
}else{
|
||||||
|
shtml+='<input class="inp" id="ip'+sq.id+'" placeholder="输入答案..."><div class="br"><button class="cf" onclick="cfil(\''+sq.id+'\')">🏎 确认</button><button class="sh" onclick="skip(\''+sq.id+'\')">👀 解析</button></div>';
|
||||||
|
}
|
||||||
});
|
});
|
||||||
sdiv.innerHTML=shtml;cd.appendChild(sdiv);
|
sdiv.innerHTML=shtml;cd.appendChild(sdiv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(cd)cd.appendChild(fb);
|
||||||
upd();
|
upd();
|
||||||
}
|
}function retryFill(id){
|
||||||
function retryFill(id){
|
|
||||||
delete conv[id];let el=document.querySelector('.cd:has(.ht)');
|
delete conv[id];let el=document.querySelector('.cd:has(.ht)');
|
||||||
if(el){let q=Q.find(x=>x.id===id);if(q)el.outerHTML=renderCard(q,0,true);}
|
if(el){let q=Q.find(x=>x.id===id);if(q)el.outerHTML=renderCard(q,0,true);}
|
||||||
upd();
|
upd();
|
||||||
|
|||||||
Reference in New Issue
Block a user