Skip to content

Commit c78d261

Browse files
author
thinksyncs
committed
Use flag language toggle and show difficulty badges
1 parent a01ac65 commit c78d261

9 files changed

Lines changed: 200 additions & 38 deletions

education/quiz.css

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
--font-sans: system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,"Apple Color Emoji","Segoe UI Emoji";
33
--font-sans-ja: system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,"Hiragino Sans","Hiragino Kaku Gothic ProN","Yu Gothic","Meiryo","Apple Color Emoji","Segoe UI Emoji";
44
--font-mono: ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;
5-
--bg-gradient-top:#0b0f14;
6-
--bg-gradient-bottom:#0d141c;
5+
--bg-gradient-top:#12161a;
6+
--bg-gradient-bottom:#141b22;
77
--fg:#e7eef6;
88
--muted:#8aa0b5;
99
--accent:#4ea1ff;
@@ -36,6 +36,7 @@ h2{font-size:clamp(16px,2.6vw,22px);margin:0;color:var(--muted)}
3636
.badge{padding:.25rem .55rem;border:1px solid var(--border);border-radius:999px;background:rgba(255,255,255,.03);color:var(--muted);font-size:.85rem}
3737
.badge.clickable{cursor:pointer;user-select:none}
3838
.badge.clickable:focus{outline:2px solid var(--accent);outline-offset:2px}
39+
.difficulty-badge{display:inline-flex;align-items:center;justify-content:center;padding:.12rem .5rem;border:1px solid var(--border);border-radius:999px;background:rgba(255,255,255,.03);color:var(--muted);font-size:.75rem;line-height:1}
3940
.card{background:linear-gradient(180deg,var(--glass),var(--glass-2));border:1px solid rgba(255,255,255,0.03);border-radius:16px;box-shadow:var(--shadow);backdrop-filter:blur(6px)}
4041
.panel{display:grid;gap:12px;padding:16px;margin:16px 0}
4142
.row{display:flex;flex-wrap:wrap;gap:10px;align-items:center}

education/quiz_finance_terms.html

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@
3232
<link rel="stylesheet" href="quiz.css" />
3333
<style>
3434
:root{
35-
--bg-gradient-top:#0b0f14;
36-
--bg-gradient-bottom:#0d141c;
35+
--bg-gradient-top:#12161a;
36+
--bg-gradient-bottom:#141b22;
3737
--fg:#e7eef6;
3838
--muted:#8aa0b5;
3939
--accent:#4ea1ff;
@@ -239,8 +239,8 @@ <h3 id="subtitle" data-i18n="subtitle">[SKILL_NAME] を「[GOAL_DESCRIPTION]」
239239
<span class="theme-label">ライトモード</span>
240240
</button>
241241
<div class="lang-toggle" role="tablist" aria-label="Language switcher">
242-
<a id="lang-ja" class="active" aria-current="page" href="quiz_finance_terms.html">日本語</a>
243-
<a id="lang-en" href="quiz_finance_terms_en.html">English</a>
242+
<a id="lang-en" href="quiz_finance_terms_en.html" aria-label="English" data-lang="en">🇺🇸</a>
243+
<a id="lang-ja" class="active" aria-current="page" href="quiz_finance_terms.html" aria-label="日本語" data-lang="ja">🇯🇵</a>
244244
</div>
245245
<button type="button" class="badge clickable" id="mode-badge" aria-live="polite" aria-pressed="true" title="クリックで学習/テスト切替">学習モード</button>
246246
<span id="score-badge" aria-live="polite" title="ライブスコア">0 / 0</span>
@@ -1507,6 +1507,31 @@ <h4 style="margin:0 0 8px">${langEn? 'Results (learning view)': '集計(学習
15071507
return {total,correct,answered,questionDetails};
15081508
}
15091509

1510+
function mapDifficulty(q){
1511+
const raw=(q.dataset.difficulty||'').trim();
1512+
if(/^L[1-5]$/.test(raw)) return raw;
1513+
const t=(q.dataset.type||'').toLowerCase();
1514+
if(t==='mc') return 'L2';
1515+
if(t==='ms') return 'L3';
1516+
if(t==='text') return 'L3';
1517+
return 'L3';
1518+
}
1519+
1520+
function injectDifficultyBadges(){
1521+
$$('#questions .q').forEach(q=>{
1522+
if(!(q instanceof HTMLElement)) return;
1523+
if(q.querySelector('.difficulty-badge')) return;
1524+
const type=q.querySelector('.type');
1525+
if(!(type instanceof HTMLElement)) return;
1526+
const badge=document.createElement('span');
1527+
badge.className='difficulty-badge';
1528+
badge.textContent=mapDifficulty(q);
1529+
badge.setAttribute('title','難易度');
1530+
type.append(' ');
1531+
type.appendChild(badge);
1532+
});
1533+
}
1534+
15101535
// Init
15111536
applyInitialTheme();
15121537
prefersDark.addEventListener?.('change', event=>{
@@ -1516,6 +1541,7 @@ <h4 style="margin:0 0 8px">${langEn? 'Results (learning view)': '集計(学習
15161541
setTheme(event.matches ? 'dark' : 'light', false);
15171542
});
15181543
applySettings();
1544+
injectDifficultyBadges();
15191545
injectAnswerButtons();
15201546
attachHandlers();
15211547
updateLiveScore();

education/quiz_finance_terms_en.html

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@
137137
body[data-theme="light"] .brand a{color:#1f2937}
138138
</style>
139139
</head>
140-
<body data-theme="dark">
141-
<script>
140+
--bg-gradient-top:#12161a;
141+
--bg-gradient-bottom:#141b22;
142142
window.DRILL_SETTINGS = {
143143
SKILL_NAME: "ECB/BIS Finance Terms",
144144
SKILL_SUBTITLE: "Beginner Keyword Quiz",
@@ -167,8 +167,8 @@ <h2 id="subtitle">A reading drill to reach: Explain key terms in your own words<
167167
<span class="theme-label">Light Mode</span>
168168
</button>
169169
<div class="lang-toggle" aria-label="Language switcher">
170-
<a href="quiz_finance_terms.html">日本語</a>
171-
<a href="quiz_finance_terms_en.html" class="active" aria-current="page">English</a>
170+
<a href="quiz_finance_terms.html" aria-label="日本語" data-lang="ja">🇯🇵</a>
171+
<a href="quiz_finance_terms_en.html" class="active" aria-current="page" aria-label="English" data-lang="en">🇺🇸</a>
172172
</div>
173173
<button type="button" class="badge clickable" id="mode-badge" aria-live="polite" aria-pressed="true" title="Click to toggle Learning/Test">Learning Mode</button>
174174
<span id="score-badge" aria-live="polite" title="Live score">0 / 0</span>
@@ -1155,13 +1155,39 @@ <h4>Q18: One-line definition of “Liquidity”.</h4>
11551155
return {total,correct,answered,questionDetails};
11561156
}
11571157

1158+
function mapDifficulty(q){
1159+
const raw=(q.dataset.difficulty||'').trim();
1160+
if(/^L[1-5]$/.test(raw)) return raw;
1161+
const t=(q.dataset.type||'').toLowerCase();
1162+
if(t==='mc') return 'L2';
1163+
if(t==='ms') return 'L3';
1164+
if(t==='text') return 'L3';
1165+
return 'L3';
1166+
}
1167+
1168+
function injectDifficultyBadges(){
1169+
$$('#questions .q').forEach(q=>{
1170+
if(!(q instanceof HTMLElement)) return;
1171+
if(q.querySelector('.difficulty-badge')) return;
1172+
const type=q.querySelector('.type');
1173+
if(!(type instanceof HTMLElement)) return;
1174+
const badge=document.createElement('span');
1175+
badge.className='difficulty-badge';
1176+
badge.textContent=mapDifficulty(q);
1177+
badge.setAttribute('title','Difficulty');
1178+
type.append(' ');
1179+
type.appendChild(badge);
1180+
});
1181+
}
1182+
11581183
applyInitialTheme();
11591184
prefersDark.addEventListener?.('change',event=>{
11601185
let stored=null;
11611186
try{ stored = localStorage.getItem(THEME_KEY); }catch(e){ stored=null; }
11621187
if(stored) return;
11631188
setTheme(event.matches?'dark':'light',false);
11641189
});
1190+
injectDifficultyBadges();
11651191
updateModeBadge();
11661192
injectAnswerButtons();
11671193
updateLiveScore();

education/quiz_k_terms.html

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ <h2 id="subtitle">Practice mapping from K# markers to formal definitions & intui
6060
<div style="display:flex;gap:10px;align-items:center;flex-wrap:wrap">
6161
<button type="button" class="theme-toggle" id="themeToggle" aria-pressed="false">🌞 Light</button>
6262
<div class="lang-toggle" aria-label="Language switcher">
63-
<a href="quiz_k_terms.html" class="active" aria-current="page">English</a>
64-
<a href="quiz_k_terms_ja.html">日本語</a>
63+
<a href="quiz_k_terms.html" class="active" aria-current="page" aria-label="English" data-lang="en">🇺🇸</a>
64+
<a href="quiz_k_terms_ja.html" aria-label="日本語" data-lang="ja">🇯🇵</a>
6565
</div>
6666
<button type="button" class="badge clickable" id="mode-badge" aria-live="polite" aria-pressed="true" title="Toggle learning/test mode">Learning Mode</button>
6767
<span id="score-badge" aria-live="polite" title="Live Score">0 / 0</span>
@@ -372,6 +372,21 @@ <h3 id="scope-h">Scope</h3>
372372
function applyInitialTheme(){let s=null; try{s=localStorage.getItem(THEME_KEY);}catch(e){} const init=s||(prefersDark.matches?'dark':'light'); setTheme(init,false);}
373373
function toggleTheme(){const c=document.body.getAttribute('data-theme')==='light'?'light':'dark'; setTheme(c==='light'?'dark':'light',true);}
374374
function applySettings(){const S=window.DRILL_SETTINGS||{}; const name=S.SKILL_NAME; const sub=S.SKILL_SUBTITLE; const goal=S.GOAL_DESCRIPTION; $('#title').textContent=`${name} Drill: ${sub}`; $('#subtitle').textContent=`Practice mapping from K# markers to definitions`; $('#footer-skill').textContent=name; $('#footer-goal').textContent=goal; const img=$('#brand-logo'); if(img&&S.BRAND_LOGO){img.src=S.BRAND_LOGO; img.style.display='inline-block'; img.alt=S.BRAND_NAME;} $('#brand-name').textContent=S.BRAND_NAME; $('#brand-link').href=S.BRAND_URL; $('#footer-brand').innerHTML=`<strong>${S.BRAND_NAME}</strong>`;}
375+
function mapDifficulty(q){const raw=(q.dataset.difficulty||'').trim(); if(/^L[1-5]$/.test(raw)) return raw; const t=(q.dataset.type||'').toLowerCase(); if(t==='mc') return 'L2'; if(t==='ms') return 'L3'; if(t==='text') return 'L3'; return 'L3';}
376+
function injectDifficultyBadges(){
377+
$$('#questions .q').forEach(q=>{
378+
if(!(q instanceof HTMLElement)) return;
379+
if(q.querySelector('.difficulty-badge')) return;
380+
const type=q.querySelector('.type');
381+
if(!(type instanceof HTMLElement)) return;
382+
const badge=document.createElement('span');
383+
badge.className='difficulty-badge';
384+
badge.textContent=mapDifficulty(q);
385+
badge.setAttribute('title','Difficulty');
386+
type.append(' ');
387+
type.appendChild(badge);
388+
});
389+
}
375390
function updateModeBadge(){const on=$('#learningMode')?.checked; const mb=$('#mode-badge'); if(!mb) return; mb.textContent=on?'Learning Mode':'Test Mode'; mb.setAttribute('aria-pressed',on?'true':'false'); renderLearningMarkers();}
376391
function renderLearningMarkers(){const on=$('#learningMode')?.checked; $$('#questions .q').forEach(q=>{const type=q.dataset.type; const ans=(q.dataset.answer||'').trim(); let gold=[]; if(type==='mc'){gold=[ans];} else if(type==='ms'){gold=ans.split(',').map(s=>s.trim());} q.querySelectorAll('.choices label.choice').forEach(l=>{const input=l.querySelector('input'); if(!input) return; const v=input.value; let m=l.querySelector('.correct-marker'); if(on && gold.includes(v)){ if(!m){ m=document.createElement('span'); m.className='correct-marker'; m.style.marginLeft='6px'; m.style.fontSize='11px'; m.style.color='var(--accent,#5aa7ff)'; m.textContent='✓'; l.appendChild(m);} } else { if(m) m.remove(); } }); }); }
377392
function showExplain(q,show=true){const exp=q.querySelector('.explain'); if(!exp) return; exp.classList.toggle('show',!!show);}
@@ -550,7 +565,7 @@ <h3 id="scope-h">Scope</h3>
550565
});
551566
}
552567
$$('#questions .q').forEach(q=>{const t=q.dataset.type; if(t==='mc'){q.querySelectorAll('input[type=radio]').forEach(r=>r.addEventListener('change',()=>{evaluateQuestion(q); if($('#learningMode')?.checked){showExplain(q,true);} updateLiveScore();}));} else if(t==='ms'){q.querySelectorAll('input[type=checkbox]').forEach(r=>r.addEventListener('change',()=>{evaluateQuestion(q); if($('#learningMode')?.checked){showExplain(q,true);} updateLiveScore();}));} else if(t==='text'){const i=q.querySelector('input[type=text]'); i?.addEventListener('input',()=>{evaluateQuestion(q); if($('#learningMode')?.checked && i.value.trim().length){showExplain(q,true);} updateLiveScore();});}});
553-
applyInitialTheme(); prefersDark.addEventListener?.('change',e=>{let s=null; try{s=localStorage.getItem(THEME_KEY);}catch(_){s=null;} if(s) return; setTheme(e.matches?'dark':'light',false);}); applySettings(); if(!$('#learningMode')){const lm=document.createElement('input'); lm.type='checkbox'; lm.id='learningMode'; lm.checked=true; lm.style.display='none'; document.body.appendChild(lm);} updateModeBadge(); updateLiveScore();
568+
applyInitialTheme(); prefersDark.addEventListener?.('change',e=>{let s=null; try{s=localStorage.getItem(THEME_KEY);}catch(_){s=null;} if(s) return; setTheme(e.matches?'dark':'light',false);}); applySettings(); injectDifficultyBadges(); if(!$('#learningMode')){const lm=document.createElement('input'); lm.type='checkbox'; lm.id='learningMode'; lm.checked=true; lm.style.display='none'; document.body.appendChild(lm);} updateModeBadge(); updateLiveScore();
554569
})();
555570
</script>
556571
</body>

education/quiz_k_terms_ja.html

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ <h2 id="subtitle">K# マーカーから定義と直感へ素早くマッピン
6060
<div style="display:flex;gap:10px;align-items:center;flex-wrap:wrap">
6161
<button type="button" class="theme-toggle" id="themeToggle" aria-pressed="false">🌞 ライト</button>
6262
<div class="lang-toggle" aria-label="言語切替">
63-
<a href="quiz_k_terms_ja.html" class="active" aria-current="page">日本語</a>
64-
<a href="quiz_k_terms.html">English</a>
63+
<a href="quiz_k_terms.html" aria-label="English" data-lang="en">🇺🇸</a>
64+
<a href="quiz_k_terms_ja.html" class="active" aria-current="page" aria-label="日本語" data-lang="ja">🇯🇵</a>
6565
</div>
6666
<button type="button" class="badge clickable" id="mode-badge" aria-live="polite" aria-pressed="true" title="学習/テスト切替">学習モード</button>
6767
<span id="score-badge" aria-live="polite" title="ライブスコア">0 / 0</span>
@@ -371,6 +371,21 @@ <h3 id="scope-h">範囲</h3>
371371
function applyInitialTheme(){let s=null; try{s=localStorage.getItem(THEME_KEY);}catch(e){} const init=s||(prefersDark.matches?'dark':'light'); setTheme(init,false);}
372372
function toggleTheme(){const c=document.body.getAttribute('data-theme')==='light'?'light':'dark'; setTheme(c==='light'?'dark':'light',true);}
373373
function applySettings(){const S=window.DRILL_SETTINGS||{}; const name=S.SKILL_NAME; const goal=S.GOAL_DESCRIPTION; $('#footer-skill').textContent=name; $('#footer-goal').textContent=goal; const img=$('#brand-logo'); if(img&&S.BRAND_LOGO){img.src=S.BRAND_LOGO; img.style.display='inline-block'; img.alt=S.BRAND_NAME;} $('#brand-name').textContent=S.BRAND_NAME; $('#brand-link').href=S.BRAND_URL; $('#footer-brand').innerHTML=`<strong>${S.BRAND_NAME}</strong>`;}
374+
function mapDifficulty(q){const raw=(q.dataset.difficulty||'').trim(); if(/^L[1-5]$/.test(raw)) return raw; const t=(q.dataset.type||'').toLowerCase(); if(t==='mc') return 'L2'; if(t==='ms') return 'L3'; if(t==='text') return 'L3'; return 'L3';}
375+
function injectDifficultyBadges(){
376+
$$('#questions .q').forEach(q=>{
377+
if(!(q instanceof HTMLElement)) return;
378+
if(q.querySelector('.difficulty-badge')) return;
379+
const type=q.querySelector('.type');
380+
if(!(type instanceof HTMLElement)) return;
381+
const badge=document.createElement('span');
382+
badge.className='difficulty-badge';
383+
badge.textContent=mapDifficulty(q);
384+
badge.setAttribute('title','難易度');
385+
type.append(' ');
386+
type.appendChild(badge);
387+
});
388+
}
374389
function showExplain(q,show=true){const exp=q.querySelector('.explain'); if(!exp) return; exp.classList.toggle('show',!!show);}
375390
function evaluateQuestion(q){const id=q.dataset.id; const type=q.dataset.type; const ans=(q.dataset.answer||'').trim(); let ok=null,user=null; if(type==='mc'){const p=q.querySelector('input[type=radio]:checked'); if(!p){ok=null;} else {user=p.value; ok=(user===ans);} } else if(type==='ms'){const picked=q.querySelectorAll('input[type=checkbox]:checked'); user=Array.from(picked).map(i=>i.value).sort(); if(!user.length){ok=null;} else {const gold=ans.split(',').map(s=>s.trim()).sort(); ok=JSON.stringify(user)===JSON.stringify(gold);} } else if(type==='text'){const t=q.querySelector('input[type=text]'); user=(t?.value||'').trim(); const mode=(q.dataset.eval||'exact').toLowerCase(); if(!user){ok=null;} else if(mode==='regex'){try{ok=new RegExp(ans,'i').test(user);}catch(e){ok=false;}} else {ok=(user===ans);} } const exp=q.querySelector('.explain'); const explainHtml=exp?exp.innerHTML.trim():''; return {id,type,ok,user,explainHtml};}
376391
function isAnswered(q){const t=q.dataset.type; if(t==='mc') return !!q.querySelector('input[type=radio]:checked'); if(t==='ms') return q.querySelectorAll('input[type=checkbox]:checked').length>0; if(t==='text'){const v=q.querySelector('input[type=text]')?.value.trim(); return !!v;} return false;}
@@ -562,7 +577,7 @@ <h3 id="scope-h">範囲</h3>
562577
});
563578
}
564579
$$('#questions .q').forEach(q=>{const t=q.dataset.type; if(t==='mc'){q.querySelectorAll('input[type=radio]').forEach(r=>r.addEventListener('change',()=>{evaluateQuestion(q); if($('#learningMode')?.checked){showExplain(q,true);} updateLiveScore();}));} else if(t==='ms'){q.querySelectorAll('input[type=checkbox]').forEach(r=>r.addEventListener('change',()=>{evaluateQuestion(q); if($('#learningMode')?.checked){showExplain(q,true);} updateLiveScore();}));} else if(t==='text'){const i=q.querySelector('input[type=text]'); i?.addEventListener('input',()=>{evaluateQuestion(q); if($('#learningMode')?.checked && i.value.trim().length){showExplain(q,true);} updateLiveScore();});}});
565-
applyInitialTheme(); prefersDark.addEventListener?.('change',e=>{let s=null; try{s=localStorage.getItem(THEME_KEY);}catch(_){s=null;} if(s) return; setTheme(e.matches?'dark':'light',false);}); applySettings(); if(!$('#learningMode')){const lm=document.createElement('input'); lm.type='checkbox'; lm.id='learningMode'; lm.checked=true; lm.style.display='none'; document.body.appendChild(lm);} updateModeBadge(); updateLiveScore();
580+
applyInitialTheme(); prefersDark.addEventListener?.('change',e=>{let s=null; try{s=localStorage.getItem(THEME_KEY);}catch(_){s=null;} if(s) return; setTheme(e.matches?'dark':'light',false);}); applySettings(); injectDifficultyBadges(); if(!$('#learningMode')){const lm=document.createElement('input'); lm.type='checkbox'; lm.id='learningMode'; lm.checked=true; lm.style.display='none'; document.body.appendChild(lm);} updateModeBadge(); updateLiveScore();
566581
})();
567582
</script>
568583
</body>

education/quiz_rfc2119.html

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,10 @@ <h2 id="subtitle">Use MUST/SHOULD/MAY (BCP 14) precisely</h2>
5757
</div>
5858
<div style="display:flex;gap:10px;align-items:center;flex-wrap:wrap">
5959
<button type="button" class="theme-toggle" id="themeToggle" aria-pressed="false">🌞 Light</button>
60-
<label class="switch" for="langToggle" title="Switch language">
61-
<input type="checkbox" id="langToggle" data-en="quiz_rfc2119.html" data-ja="quiz_rfc2119_ja.html" />
62-
<span class="ui-toggle" aria-hidden="true"></span>
63-
<span class="switch-label">English / 日本語</span>
64-
</label>
60+
<div class="lang-toggle" aria-label="Language switcher">
61+
<a href="quiz_rfc2119.html" class="active" aria-current="page" aria-label="English" data-lang="en">🇺🇸</a>
62+
<a href="quiz_rfc2119_ja.html" aria-label="日本語" data-lang="ja">🇯🇵</a>
63+
</div>
6564
<button type="button" class="badge clickable" id="mode-badge" aria-live="polite" aria-pressed="true" title="Toggle learning/test mode">Learning Mode</button>
6665
<span id="score-badge" aria-live="polite" title="Live Score">0 / 0</span>
6766
</div>

0 commit comments

Comments
 (0)