orgbench-review / app.js
happy8825's picture
static mirror: client, seeds, results
ddb8e34 verified
Raw History Blame Contribute Delete
31.6 kB
'use strict';
const $=s=>document.querySelector(s), esc=s=>String(s??'').replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
const fmt=n=>Number(n).toLocaleString('en-US'), pct=(a,b)=>b?`${(100*a/b).toFixed(1)}%`:'โ€”';
const kindNames={chat:'Slack',tracker:'Notion ยท Tracker',claim:'Notion ยท Claim',decision:'Notion ยท Decision',meeting:'ํšŒ์˜ ๊ธฐ๋ก',email:'Email',doc:'๋ฌธ์„œ',image:'๊ทธ๋ฆผ'};
const modNames={text:'Text',image:'Image',multi:'Multi-image'};
const taskOrder=['Fact','Attribution','Computation','Selection','Interpretation','Discrepancy','Resolution','State','Change','Abstention'];
const taskNames={Fact:'Fact ยท ์‚ฌ์‹ค ์กฐํšŒ',Attribution:'Attribution ยท ์ถœ์ฒ˜ ์ถ”์ ',Computation:'Computation ยท ์ˆ˜๋Ÿ‰ ๊ณ„์‚ฐ',Selection:'Selection ยท ๋น„๊ตยท์„ ํƒ',Interpretation:'Interpretation ยท ํ•ด์„',Discrepancy:'Discrepancy ยท ๋ถˆ์ผ์น˜ ์‹๋ณ„',Resolution:'Resolution ยท ์œ ํšจ๊ฐ’ ๊ฒฐ์ •',State:'State ยท ์ƒํƒœ',Change:'Change ยท ๋ณ€๊ฒฝ'};
let INDEX,UNITS,unitMap,projectMap,recordUnits,questionMap,RANKS=null,rankError=false,renderGeneration=0;
taskNames.Abstention='Abstention ยท ๋‹ต๋ณ€ ์œ ๋ณด';
const qaCache=new Map();
let S={view:'qa',project:'',task:'',result:'',text:'',kind:'',id:'',page:1,tab:'retrieval',hitkind:'all',unit:''};
async function getJSON(path){const r=await fetch(path+'.gz');if(!r.ok)throw new Error(`${path} (${r.status})`);const b=new Uint8Array(await r.arrayBuffer());if(b[0]!==31||b[1]!==139)return JSON.parse(new TextDecoder().decode(b));if(typeof DecompressionStream==='undefined')throw new Error('์ตœ์‹  ๋ธŒ๋ผ์šฐ์ €์—์„œ ์—ด์–ด ์ฃผ์„ธ์š”. ๋ฌด์†์‹ค ์••์ถ• ๋ฐ์ดํ„ฐ ์ง€์›์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.');return new Response(new Blob([b]).stream().pipeThrough(new DecompressionStream('gzip'))).json();}
function url(view,params={}){const q=new URLSearchParams();for(const[k,v]of Object.entries(params))if(v!==''&&v!==null&&v!==undefined&&v!==false)q.set(k,v);return '#'+view+(q.size?'?'+q:'');}
function readState(){const raw=location.hash.slice(1),parts=raw.includes('?')?raw.split('?'):(raw.includes('=')?['clean',raw]:[raw,'']);const p=new URLSearchParams(parts[1]||''),aliases={capability:'group',family:'task',world:'project',evidence:'evidence_bucket'};let head=p.get('head')||'group';head=aliases[head]||head;let result=p.get('result')||p.get('verdict')||'';if(result==='wrong')result='incorrect';let project=p.get('project')||p.get('world')||p.get('f_world')||'';project=INDEX?.projects.find(x=>x.id===project||x.run===project)?.id||project;const requestedTask=p.get('task')||p.get('f_family')||'',requestedFacet=p.get('facet')||'';return {view:['clean','qa','world','results','stats'].includes(parts[0])?parts[0]:'clean',project,task:taskOrder.includes(requestedTask)?requestedTask:'',group:p.get('group')||p.get('f_capability')||'',result,model:p.get('model')||'luna',condition:p.get('condition')||'rag100',text:p.get('text')||'',kind:p.get('kind')||'',id:p.get('id')||'',page:Math.max(1,parseInt(p.get('page')||'1',10)||1),tab:p.get('tab')||'gold',hitkind:p.get('hitkind')||'all',unit:p.get('unit')||'',document:p.get('document')||'',head,facet:head==='task'&&!taskOrder.includes(requestedFacet)?'':requestedFacet,inclusion:p.get('inclusion')||'',interesting:p.get('interesting')||'',app:p.get('app')||'slack',room:p.get('room')||''};}
function go(patch,replace=false){const next={...S,...patch};const h=url(next.view,Object.fromEntries(Object.entries(next).filter(([k])=>k!=='view')));if(replace){history.replaceState(null,'',h);S=next;render();}else if(location.hash===h){S=next;render();}else location.hash=h;}
function projectLabel(id){return projectMap.get(id)?.label||id;}
function shortSource(u){const lines=u.text.split('\n').filter(Boolean);return lines[1]||lines[0]||u.record_id;}
function time(t){return (t||'').replace('T',' ');}
function imageSrc(path){if(!/^media\/[a-f0-9]{64}\.(?:png|jpe?g|webp|gif)$/i.test(path||''))return '';return typeof LAYOUT_IMAGE_PATHS!=='undefined'&&LAYOUT_IMAGE_PATHS.has(path)?'https://huggingface.co/datasets/MMOrgBench/MMOrgBench/resolve/'+LAYOUT_REFRESH.hf_commit+'/'+path:path;}
function badge(ok){return `<span class="chip ${ok?'good':'bad'}">${ok?'โœ“ ์ •๋‹ต':'ร— ์˜ค๋‹ต'}</span>`;}
function overview(){const d=INDEX.summary;$('#overview').innerHTML=`<div class="stat"><span class="stat-label">Luna ยท ์ „์—ญ RAG top100</span><strong>${pct(d.correct,d.questions)}</strong><small>${fmt(d.correct)} / ${fmt(d.questions)} ์ •๋‹ต ยท ์ฑ„์  ์™„๋ฃŒ</small></div><div class="stat"><span class="stat-label">ํ†ตํ•ฉ ํ”„๋กœ์ ํŠธ</span><strong>${d.projects}<small> ํ”„๋กœ์ ํŠธ</small></strong><small>${fmt(d.records)}๊ฐœ ์›๋ฌธ ๊ธฐ๋ก</small></div><div class="stat"><span class="stat-label">๊ฒ€์ƒ‰ ๋‹จ์œ„</span><strong>${fmt(d.units)}</strong><small>ํ…์ŠคํŠธ ${fmt(d.text_units)} ยท ์ด๋ฏธ์ง€ ${fmt(d.images)}</small></div><div class="stat"><span class="stat-label">์งˆ๋ฌธ ๊ด€์ </span><strong>Omni</strong><small>ํ”„๋กœ์ ํŠธ ์‚ฌ์ „ ํ•„ํ„ฐ ์—†์Œ</small></div>`;}
function projectOptions(){return '<option value="">์ „์ฒด 32๊ฐœ ํ”„๋กœ์ ํŠธ</option>'+INDEX.projects.map(p=>`<option value="${p.id}" ${S.project===p.id?'selected':''}>${esc(p.id.toUpperCase())} ยท ${esc(p.label)}</option>`).join('');}
function taskOptions(){return '<option value="">์ „์ฒด Task</option>'+taskOrder.map(t=>`<option value="${t}" ${S.task===t?'selected':''}>${esc(taskNames[t])}</option>`).join('');}
function filterControls(world=false){return `<div class="filters"><label>${world?'์›๋ฌธ ๊ฒ€์ƒ‰':'์งˆ๋ฌธ ๊ฒ€์ƒ‰'}<input type="search" id="search" placeholder="${world?'๋ณธ๋ฌธ, ์ธ๋ฌผ, ์ฑ„๋„, ํŒŒ์ผ๋ช…โ€ฆ':'์งˆ๋ฌธ ๋‚ด์šฉ ๋˜๋Š” Q / N / MU ๋ฌธํ•ญ IDโ€ฆ'}" value="${esc(S.text)}"></label><label>ํ”„๋กœ์ ํŠธ<select id="project-filter">${projectOptions()}</select></label>${world?`<label>๊ธฐ๋ก ์ข…๋ฅ˜<select id="kind-filter"><option value="">์ „์ฒด ๊ธฐ๋ก</option>${Object.entries(kindNames).map(([k,v])=>`<option value="${k}" ${S.kind===k?'selected':''}>${v}</option>`).join('')}<option value="pixels" ${S.kind==='pixels'?'selected':''}>์ด๋ฏธ์ง€ ์žˆ๋Š” ๊ธฐ๋ก๋งŒ</option></select></label>`:`<label>Task<select id="task-filter">${taskOptions()}</select></label>`}<label>${world?'ํ‘œ์‹œ':'Luna ํŒ์ •'}<select id="result-filter">${world?'<option value="">์‹œ๊ฐ„์ˆœ ยท ์˜ค๋ž˜๋œ ์ˆœ</option>':`<option value="">์ „์ฒด ๋ฌธํ•ญ</option><option value="correct" ${S.result==='correct'?'selected':''}>์ •๋‹ต๋งŒ</option><option value="incorrect" ${S.result==='incorrect'?'selected':''}>์˜ค๋‹ต๋งŒ</option><option value="no-image" ${S.result==='no-image'?'selected':''}>์ด๋ฏธ์ง€ ๋ฌธํ•ญ ยท ๊ฒ€์ƒ‰ ์ด๋ฏธ์ง€ 0</option>`}</select></label></div>`;}
function bindFilters(world=false){let timer;$('#search')?.addEventListener('input',e=>{const pos=e.target.selectionStart,value=e.target.value;clearTimeout(timer);timer=setTimeout(()=>{go({text:value,page:1,id:'',unit:''},true);setTimeout(()=>{const el=$('#search');el?.focus();if(el&&pos!==null)el.setSelectionRange(pos,pos);},0);},250);});$('#project-filter')?.addEventListener('change',e=>go({project:e.target.value,page:1,id:'',unit:''}));$('#task-filter')?.addEventListener('change',e=>go({task:e.target.value,page:1,id:''}));$('#kind-filter')?.addEventListener('change',e=>go({kind:e.target.value,page:1,unit:''}));if(!world)$('#result-filter')?.addEventListener('change',e=>go({result:e.target.value,page:1,id:''}));}
function pageControls(page,pages,extra=''){return `<div class="page-controls ${extra}"><button data-page="${page-1}" ${page<=1?'disabled':''}>โ† ์ด์ „</button><span>${page} / ${pages}</span><button data-page="${page+1}" ${page>=pages?'disabled':''}>๋‹ค์Œ โ†’</button></div>`;}
function bindPages(){$$('[data-page]').forEach(b=>b.addEventListener('click',()=>go({page:Number(b.dataset.page),id:'',unit:''})));}
function $$(s,base=document){return [...base.querySelectorAll(s)];}
function filteredQuestions(){const needle=S.text.trim().toLowerCase();return INDEX.questions.filter(q=>(!S.project||q.project===S.project)&&(!S.task||q.task===S.task)&&(!needle||[q.q,q.id,projectLabel(q.project)].join(' ').toLowerCase().includes(needle))&&(!S.result||S.result==='correct'&&q.correct||S.result==='incorrect'&&!q.correct||S.result==='no-image'&&q.modality!=='text'&&q.images===0));}
async function loadQuestion(id){const p=id.split('::')[0];if(!qaCache.has(p))qaCache.set(p,getJSON('data/qa/'+encodeURIComponent(p)+'.json').catch(e=>{qaCache.delete(p);throw e;}));const data=await qaCache.get(p);return data.items.find(q=>q.id===id);}
async function renderQA(generation){const all=filteredQuestions(),pageSize=25,pages=Math.max(1,Math.ceil(all.length/pageSize));let page=Math.min(S.page,pages);let active=all.find(q=>q.id===S.id);if(active){page=Math.floor(all.indexOf(active)/pageSize)+1;}else active=all[(page-1)*pageSize];const start=(page-1)*pageSize;const shown=all.slice(start,start+pageSize);const good=all.filter(q=>q.correct).length;
$('#workspace').innerHTML=filterControls()+`<div class="filter-foot"><span>ํ‘œ์‹œ ${fmt(all.length)}๋ฌธํ•ญ ยท ์ •๋‹ต ${fmt(good)} ยท ${pct(good,all.length)}</span><span>์ €์žฅ๋œ Luna ํŒ์ • ยท ์งˆ๋ฌธ ๋‹จ์œ„</span><button id="reset-filters">ํ•„ํ„ฐ ์ดˆ๊ธฐํ™”</button></div><div class="qa-layout"><aside class="qa-list" aria-label="๋ฌธํ•ญ ๋ชฉ๋ก"><div class="list-heading"><strong>๋ฌธํ•ญ</strong><span>${all.length?start+1:0}โ€“${Math.min(start+pageSize,all.length)}</span></div><div class="list-items">${shown.length?shown.map(q=>`<a class="question-link ${q.id===active?.id?'selected':''}" href="${esc(url('qa',{...S,view:undefined,id:q.id,page,unit:''}))}" ${q.id===active?.id?'aria-current="true"':''}><span class="q-id">${esc(q.project.toUpperCase())} ยท ${esc(q.item)}<span class="${q.correct?'good':'bad'}">${q.correct?'โœ“':'ร—'}</span></span><span class="q-title">${esc(q.q)}</span><span class="q-meta">${esc(projectLabel(q.project))} ยท ${esc(q.task)}</span></a>`).join(''):'<div class="empty">์กฐ๊ฑด์— ๋งž๋Š” ๋ฌธํ•ญ์ด ์—†์Šต๋‹ˆ๋‹ค.</div>'}</div>${pageControls(page,pages)}</aside><section id="question-detail" class="question-detail" aria-label="๋ฌธํ•ญ ์ƒ์„ธ">${active?'<div class="panel loading">๋‹ต๋ณ€๊ณผ ๊ฒ€์ƒ‰ ๊ธฐ๋ก์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘์ž…๋‹ˆ๋‹คโ€ฆ</div>':'<div class="panel empty">ํ•„ํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•ด ์ฃผ์„ธ์š”.</div>'}</section></div>`;
bindFilters();bindPages();const imageCounts=OrgBenchImageStats.summarize(all);$('.filter-foot').insertAdjacentHTML('beforeend',`<span>ํ˜„์žฌ ๋ฌธํ•ญ๋“ค์˜ ๊ฒ€์ƒ‰ ์ด๋ฏธ์ง€: ํ‰๊ท  ${imageCounts.mean===null?'โ€”':imageCounts.mean.toFixed(2)}์žฅ / 100๊ฐœ ยท <a href="#results">์ „์ฒด ๋ถ„ํฌ ๋ณด๊ธฐ</a></span>`);$$('.question-link .q-meta').forEach((el,i)=>el.insertAdjacentHTML('afterend',`<span class="q-image-count">๊ฒ€์ƒ‰ ์ด๋ฏธ์ง€ ${shown[i].images} / 100</span>`));if(!active)return;try{const q=await loadQuestion(active.id);if(generation!==renderGeneration)return;if(!q)throw new Error('๋ฌธํ•ญ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.');S.id=q.id;S.page=page;renderQuestion(q);}catch(e){if(generation===renderGeneration)$('#question-detail').innerHTML=`<div class="notice error">๋ฌธํ•ญ์„ ๋ถˆ๋Ÿฌ์˜ค์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ${esc(e.message)} <button onclick="location.reload()">๋‹ค์‹œ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ</button></div>`;}}
function renderQuestion(q){const projects=new Set(q.hits.map(h=>unitMap.get(h.id)?.project));$('#question-detail').innerHTML=`<article class="panel"><div class="question-top"><div class="eyebrow">${esc(q.project.toUpperCase())} ยท ${esc(projectLabel(q.project))} ยท ${esc(q.item)}</div><a class="subtle-link" href="${url('world',{project:q.project})}">์ด ํ”„๋กœ์ ํŠธ ์›๋ฌธ ๋ณด๊ธฐ โ†—</a></div><h1 class="question-text">${esc(q.q)}</h1><div class="chips"><span class="chip blue">${esc(q.group)} / ${esc(q.task)}</span><span class="chip">${esc(modNames[q.modality]||q.modality)} ๋ฌธํ•ญ</span><span class="chip">๊ฒ€์ƒ‰๋œ ์ด๋ฏธ์ง€ ${q.images}์žฅ</span><span class="chip">${projects.size}๊ฐœ ํ”„๋กœ์ ํŠธ์˜ ๊ธฐ๋ก</span>${badge(q.grade.answer_ok)}</div><div class="answers"><section class="answer-card"><div class="answer-label">Gold ยท Omni<span class="muted">๊ฒ€์ˆ˜์šฉ</span></div><div class="answer-body">${esc(q.gold)}</div></section><section class="answer-card"><div class="answer-label">Luna ๋‹ต๋ณ€${badge(q.grade.answer_ok)}</div><div class="answer-body">${esc(q.answer)}</div></section></div><details class="judge"><summary>Luna ํŒ์ • ์ด์œ </summary><p>${esc(q.grade.grader_reason||'์ €์žฅ๋œ ํŒ์ • ์ด์œ ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.')}</p></details><details class="plain-details"><summary>๋ชจ๋ธ ์›๋ฌธ ์ถœ๋ ฅ ยท ์‚ฌ์šฉ๋Ÿ‰</summary><pre>${esc(q.raw)}</pre><p class="caption">์ž…๋ ฅ ํ† ํฐ ${fmt(q.usage?.reader?.prompt_tokens||0)} ยท ์ถœ๋ ฅ ํ† ํฐ ${fmt(q.usage?.reader?.completion_tokens||0)} ยท ๋ณ„๋„์˜ ๋น„๊ณต๊ฐœ ์ถ”๋ก  ๋‚ด์šฉ์€ ์ œ๊ณตํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.</p></details></article><section class="panel evidence-panel"><div class="tabs" role="tablist" aria-label="๊ทผ๊ฑฐ ๋ฐ ๋ชจ๋ธ ์ž…๋ ฅ"><button role="tab" data-tab="retrieval" aria-selected="${S.tab==='retrieval'}" class="${S.tab==='retrieval'?'active':''}">๊ฒ€์ƒ‰ top100</button><button role="tab" data-tab="input" aria-selected="${S.tab==='input'}" class="${S.tab==='input'?'active':''}">Luna ์ „๋‹ฌ ์ˆœ์„œ</button><button role="tab" data-tab="gold" aria-selected="${S.tab==='gold'}" class="${S.tab==='gold'?'active':''}">Gold ํ’€์ด ยท ๊ทผ๊ฑฐ</button></div><div id="tab-body" class="tab-body"></div></section>`;$$('[data-tab]').forEach(b=>b.addEventListener('click',()=>go({tab:b.dataset.tab})));renderEvidence(q);}
function recordHTML(u,opts={}){const rank=opts.rank,selected=opts.selected,annotated=opts.annotated,originalRank=opts.originalRank,seq=opts.seq;const title=shortSource(u);const sourceTitle=title.length>165?title.slice(0,165)+'โ€ฆ':title;let marks=`<span class="chip">${esc(kindNames[u.kind]||u.kind)}</span>${u.image?'<span class="chip blue">์ด๋ฏธ์ง€</span>':''}`;if(annotated)marks+='<span class="chip warn">Gold ๊ทผ๊ฑฐ</span>';if(selected===false)marks+='<span class="chip warn">Luna์— ๋ฏธ์ „๋‹ฌ</span>';if(selected===true)marks+='<span class="chip good">top100 ํฌํ•จ</span>';const score=Number.isFinite(opts.score)?opts.score.toFixed(4):'';return `<details class="record" data-unit="${esc(u.id)}" ${opts.open?'open':''}><summary><span class="rank">${seq?'์ˆœ์„œ '+seq:rank?'#'+rank:'์›๋ฌธ'}</span><div><div class="record-topline">${marks}</div><div class="record-title">${esc(sourceTitle)}</div><div class="record-snippet">${esc(u.text.split('\n').slice(2).join('\n').slice(0,220))}</div><div class="record-meta">${esc(projectLabel(u.project))} ยท ${esc(time(u.timestamp))}<br>${esc(u.record_id)}${opts.imageRank?' ยท ์ด๋ฏธ์ง€ ์ค‘ '+fmt(opts.imageRank)+'์œ„':''}${seq&&originalRank?' ยท ๊ฒ€์ƒ‰ #'+originalRank:''}</div></div><div class="score">${score?'์œ ์‚ฌ๋„<br>'+score:''}<span class="expand">ํŽผ์น˜๊ธฐ</span></div></summary><div class="record-body"><div class="native-text">${esc(u.text)}</div>${u.image?`<img class="record-image" src="${esc(imageSrc(u.image))}" alt="${esc(u.record_id)} ์›๋ฌธ ์ด๋ฏธ์ง€" loading="lazy" decoding="async">`:''}<div class="image-tools"><button type="button" data-open-unit="${esc(u.id)}">${u.image?'์ด๋ฏธ์ง€ ํฌ๊ฒŒ ๋ณด๊ธฐ':'์›๋ฌธ ํฌ๊ฒŒ ๋ณด๊ธฐ'}</button><a href="${esc(url('world',{project:u.project,unit:u.id}))}">ํ†ตํ•ฉ ์›”๋“œ์—์„œ ์—ด๊ธฐ โ†—</a></div></div></details>`;}
function bindRecords(base=document){$$('[data-open-unit]',base).forEach(b=>b.addEventListener('click',()=>openUnit(b.dataset.openUnit)));$$('[data-record-ref]',base).forEach(b=>b.addEventListener('click',()=>{const units=recordUnits.get(b.dataset.recordRef)||[];if(units.length)openUnit(units[0].id);}));}
function renderEvidence(q,body=$('#tab-body'),local=null){const tab=local?.tab||S.tab,hitkind=local?.hitkind||S.hitkind;if(tab==='gold'){const known=RANKS?.[q.id]||[];const rankMap=new Map(known.map(r=>[r.id,r]));const ids=[...new Set(q.evidence.flatMap(r=>(recordUnits.get(r)||[]).map(u=>u.id)))];const hits=new Map(q.hits.map(h=>[h.id,h]));body.innerHTML=`<div class="gold-warning">์•„๋ž˜ ํ’€์ดยท๊ทผ๊ฑฐ๋Š” ๊ฒ€์ˆ˜์šฉ์ž…๋‹ˆ๋‹ค. ๊ฒ€์ƒ‰๋˜์ง€ ์•Š์€ ์›๋ฌธ๋„ ์—ฌ๊ธฐ์„œ๋Š” ์—ด ์ˆ˜ ์žˆ์ง€๋งŒ, ํ•ด๋‹น ๋ฌธํ•ญ์˜ Luna ์ž…๋ ฅ์—๋Š” ๋“ค์–ด๊ฐ€์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.</div>${q.solution?.length?`<details class="plain-details" open><summary>์ €์žฅ๋œ Gold solution</summary><ol class="solution">${q.solution.map(s=>`<li>${esc(s.step)}<div>${(s.record_ids||[]).map(id=>`<button class="record-ref" data-record-ref="${esc(id)}">${esc(id)}</button>`).join('')}</div></li>`).join('')}</ol></details>`:''}<p class="caption">์ฃผ์„์— ์—ฐ๊ฒฐ๋œ ${q.evidence.length}๊ฐœ ๊ทผ๊ฑฐ ๊ธฐ๋ก์ž…๋‹ˆ๋‹ค. ์œ ์ผํ•˜๊ฑฐ๋‚˜ ์ตœ์†Œ์ธ ๊ทผ๊ฑฐ ์ง‘ํ•ฉ์ด๋ผ๋Š” ๋œป์€ ์•„๋‹™๋‹ˆ๋‹ค.${rankError?' ์ „์ฒด ์ˆœ์œ„ ์ง„๋‹จ์„ ๋ถˆ๋Ÿฌ์˜ค์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.':''}</p><div class="hit-list">${ids.map(id=>{const u=unitMap.get(id),r=rankMap.get(id),h=hits.get(id);return recordHTML(u,{rank:r?.rank||h?.rank,score:r?.score??h?.score,imageRank:r?.image_rank,selected:hits.has(id),annotated:true});}).join('')||'<div class="empty">์—ฐ๊ฒฐ๋œ ๊ทผ๊ฑฐ ๊ธฐ๋ก์ด ์—†์Šต๋‹ˆ๋‹ค.</div>'}</div>`;bindRecords(body);return;}
const chronological=tab==='input';const hm=new Map(q.hits.map(h=>[h.id,h]));const ids=chronological?q.reader_order:q.hits.map(h=>h.id);const hitImages=ids.filter(id=>unitMap.get(id).image).length;const filtered=ids.filter(id=>hitkind==='image'?!!unitMap.get(id).image:hitkind==='text'?!unitMap.get(id).image:true);const projectCount=new Set(ids.map(id=>unitMap.get(id).project)).size;
body.innerHTML=`<p class="context-note">${chronological?'์œ ์‚ฌ๋„ ์ƒ์œ„ 100๊ฐœ๋ฅผ ๋จผ์ € ์„ ํƒํ•œ ๋’ค ์‹œ๊ฐ„์ˆœ์œผ๋กœ ๋ฐฐ์—ดํ•œ ์‹ค์ œ ๊ธฐ๋ก ์ˆœ์„œ์ž…๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์— ์งˆ๋ฌธ์„ ๋ถ™์—ฌ Luna์— ์ „๋‹ฌํ–ˆ์Šต๋‹ˆ๋‹ค.':'32๊ฐœ ํ”„๋กœ์ ํŠธ ์ „์ฒด์—์„œ ์งˆ๋ฌธ๊ณผ์˜ ์œ ์‚ฌ๋„๊ฐ€ ๋†’์€ ์ˆœ์„œ๋กœ ์„ ํƒํ•œ 100๊ฐœ์ž…๋‹ˆ๋‹ค. ํ…์ŠคํŠธ์™€ ์ด๋ฏธ์ง€๊ฐ€ ๊ฐ™์€ ์ˆœ์œ„์—์„œ ๊ฒฝ์Ÿํ•˜๋ฉฐ, ์ฒจ๋ถ€ ํŒŒ์ผ์€ ์ž๋™์œผ๋กœ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.'}</p><div class="chips"><span class="chip">100๊ฐœ ๊ฒ€์ƒ‰ ๋‹จ์œ„</span><span class="chip blue">์ด๋ฏธ์ง€ ${hitImages}์žฅ</span><span class="chip">ํ…์ŠคํŠธ ์ „์šฉ ${100-hitImages}๊ฐœ</span><span class="chip">${projectCount}๊ฐœ ํ”„๋กœ์ ํŠธ</span></div>${q.modality!=='text'&&!hitImages?'<p class="caption warn">์ด๋ฏธ์ง€ ๊ด€๋ จ ๋ฌธํ•ญ์ด์ง€๋งŒ ์ด ์š”์ฒญ์—๋Š” ์ด๋ฏธ์ง€๊ฐ€ ํ•œ ์žฅ๋„ ์ „๋‹ฌ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. Gold ๊ทผ๊ฑฐ ํƒญ์—์„œ ์ œ์™ธ๋œ ์ด๋ฏธ์ง€์˜ ์ˆœ์œ„๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.</p>':''}<div class="context-meter" aria-label="๊ฒ€์ƒ‰ ๋‹จ์œ„ 100๊ฐœ ์ค‘ ์ด๋ฏธ์ง€ ${hitImages}๊ฐœ">${ids.map(id=>`<span class="${unitMap.get(id).image?'visual':''}" title="${esc(id)}"></span>`).join('')}</div><div class="hit-toolbar"><strong>${chronological?'Luna ์ž…๋ ฅ์ˆœ':'๊ฒ€์ƒ‰ ์œ ์‚ฌ๋„์ˆœ'}</strong><label>ํ‘œ์‹œ<select data-hit-kind><option value="all" ${hitkind==='all'?'selected':''}>์ „์ฒด 100๊ฐœ</option><option value="image" ${hitkind==='image'?'selected':''}>์ด๋ฏธ์ง€ ์žˆ๋Š” ๊ธฐ๋ก๋งŒ</option><option value="text" ${hitkind==='text'?'selected':''}>ํ…์ŠคํŠธ ๊ธฐ๋ก๋งŒ</option></select></label></div><div class="hit-list">${filtered.map(id=>{const h=hm.get(id);return recordHTML(unitMap.get(id),{rank:h.rank,score:h.score,seq:chronological?ids.indexOf(id)+1:null,originalRank:h.rank,annotated:q.evidence.includes(unitMap.get(id).record_id)});}).join('')||'<div class="evidence-empty">์ด ์š”์ฒญ์—๋Š” ๊ฒ€์ƒ‰๋œ ์ด๋ฏธ์ง€๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ํ‘œ์‹œ๋ฅผ ๋ฐ”๊ฟ” ํ…์ŠคํŠธ ๊ธฐ๋ก์„ ํ™•์ธํ•ด ์ฃผ์„ธ์š”.</div>'}</div><p class="caption">์ฝ”์‚ฌ์ธ ์œ ์‚ฌ๋„๋Š” ๊ฒ€์ƒ‰ ์ˆœ์œ„ ์ ์ˆ˜์ด๋ฉฐ ์ •๋‹ต ํ™•๋ฅ ์ด ์•„๋‹™๋‹ˆ๋‹ค. ${chronological?'ํ™”๋ฉด์˜ Gold ํ‘œ์‹œ๋Š” ๊ฒ€์ˆ˜์šฉ์œผ๋กœ ๋ง๋ถ™์ธ ๊ฒƒ์ด๋ฉฐ ์‹ค์ œ ์ž…๋ ฅ์— ํฌํ•จ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.':''}</p>`;body.querySelector('[data-hit-kind]').addEventListener('change',e=>{if(local){local.hitkind=e.target.value;renderEvidence(q,body,local);}else go({hitkind:e.target.value});});bindRecords(body);}
function openUnit(id){if(S.view==='world'||String(id).startsWith('layout23_')){const current=worldUnit(id);if(current)return openCleanRecord(current.record_id);return;}const u=unitMap.get(id);if(!u)return;const d=$('#record-dialog');$('#dialog-title').textContent=`${u.record_id} ยท ${kindNames[u.kind]||u.kind}`;$('#dialog-body').innerHTML=`<p class="eyebrow">${esc(projectLabel(u.project))} ยท ${esc(time(u.timestamp))}</p><div class="native-text">${esc(u.text)}</div>${u.image?`<img class="record-image" src="${esc(imageSrc(u.image))}" alt="${esc(u.record_id)} ์›๋ฌธ ์ด๋ฏธ์ง€"><a href="${esc(imageSrc(u.image))}" target="_blank" rel="noopener">์ด๋ฏธ์ง€ ์›๋ณธ ํฌ๊ธฐ๋กœ ์—ด๊ธฐ โ†—</a>`:''}<p class="caption">์›๋ฌธ์— ์ ํžŒ ์‹œ๊ฐ์„ ๊ทธ๋Œ€๋กœ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ์‹œ๊ฐ„๋Œ€๋Š” ๋ณ„๋„๋กœ ์ •์˜๋˜์–ด ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.</p>`;if(!d.open)d.showModal();}
function projectIntro(){if(!S.project)return `<details class="panel world-intro"><summary>32๊ฐœ ํ”„๋กœ์ ํŠธ ๊ตฌ์„ฑ ยท ์ธ๋ฌผยท์ฑ„๋„ ๋ณด๊ธฐ</summary><div class="project-grid">${INDEX.projects.map(p=>`<a class="project-tile" href="${url('world',{project:p.id})}">${esc(p.id.toUpperCase())} ยท ${esc(p.label)}<small>${esc(p.run)}</small><small>${p.questions}๋ฌธํ•ญ ยท ์ธ๋ฌผ ${p.people.length}๋ช…</small></a>`).join('')}</div></details>`;const p=projectMap.get(S.project);if(!p)return '';return `<details class="panel world-intro"><summary>${esc(p.label)} ยท ์ธ๋ฌผ ${p.people.length}๋ช… / ์ฑ„๋„ ${p.channels.length}๊ฐœ</summary><p class="caption">${esc(p.run)} ยท Project CEO์˜ ๊ถŒํ•œ์€ ํ•ด๋‹น ํ”„๋กœ์ ํŠธ ์•ˆ์—์„œ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.</p><div class="people">${p.people.map(n=>`<div class="person">${esc(n.new_name)}<small>${esc(n.new_role)}</small></div>`).join('')}</div><div class="channels">${p.channels.map(c=>`<span class="chip">${esc(c.new_name)}</span>`).join('')}</div>${p.clients?.length?`<p class="caption">๊ณ ๊ฐ ๋‹ด๋‹น์ž: ${p.clients.map(c=>esc(c.new_name)+' ยท '+esc(c.company_name)).join(' / ')}</p>`:''}</details>`;}
function renderWorld(){const needle=S.text.trim().toLowerCase();const all=UNITS.filter(u=>(!S.project||u.project===S.project)&&(!S.kind||(S.kind==='pixels'?!!u.image:u.kind===S.kind))&&(!needle||[u.text,u.record_id,projectLabel(u.project)].join(' ').toLowerCase().includes(needle)));const size=24,pages=Math.max(1,Math.ceil(all.length/size)),page=Math.min(S.page,pages),shown=all.slice((page-1)*size,page*size);$('#workspace').innerHTML=`<div class="section-head"><h1>ํ†ตํ•ฉ ์›”๋“œ ์›๋ฌธ</h1><span class="muted">32๊ฐœ ํ”„๋กœ์ ํŠธ ยท ๊ฒ€์ƒ‰์— ์‚ฌ์šฉํ•œ ์›๋ฌธ๊ณผ ํŽ˜์ด์ง€ ์ด๋ฏธ์ง€</span></div>${filterControls(true)}<div class="filter-foot"><span>${fmt(all.length)}๊ฐœ ๊ฒ€์ƒ‰ ๋‹จ์œ„ ยท ${fmt(new Set(all.map(u=>u.record_id)).size)}๊ฐœ ๋…ผ๋ฆฌ ๊ธฐ๋ก</span><button id="reset-filters">ํ•„ํ„ฐ ์ดˆ๊ธฐํ™”</button></div>${projectIntro()}<div class="world-records">${shown.map(u=>recordHTML(u)).join('')||'<div class="panel empty">์กฐ๊ฑด์— ๋งž๋Š” ๊ธฐ๋ก์ด ์—†์Šต๋‹ˆ๋‹ค.</div>'}</div>${pageControls(page,pages,'bottom-pages')}`;bindFilters(true);bindPages();bindRecords();if(S.unit&&unitMap.has(S.unit))openUnit(S.unit);}
function groupStats(field,order){return order.map(k=>{const qs=INDEX.questions.filter(q=>q[field]===k);return {key:k,n:qs.length,ok:qs.filter(q=>q.correct).length};});}
function statsTable(rows,label,href){return `<div class="table-wrap"><table><thead><tr><th>${label}</th><th>๋ฌธํ•ญ</th><th>์ •๋‹ต</th><th>์ •ํ™•๋„</th></tr></thead><tbody>${rows.map(r=>`<tr><td>${href?`<a href="${esc(href(r.key))}">${esc(r.label||r.key)}</a>`:esc(r.label||r.key)}</td><td>${fmt(r.n)}</td><td>${fmt(r.ok)}</td><td>${pct(r.ok,r.n)}</td></tr>`).join('')}</tbody></table></div>`;}
function renderResults(){const s=INDEX.summary;const mod=groupStats('modality',['text','image','multi']).map(r=>({...r,label:modNames[r.key]}));const groups=groupStats('group',['Retrieval','Synthesis','Alignment']);const tasks=groupStats('task',taskOrder).map(r=>({...r,label:taskNames[r.key]}));const im=INDEX.questions.filter(q=>q.modality!=='text');const buckets=[{key:'with',label:'์ด๋ฏธ์ง€๊ฐ€ 1์žฅ ์ด์ƒ ๊ฒ€์ƒ‰๋จ',rows:im.filter(q=>q.images>0)},{key:'without',label:'๊ฒ€์ƒ‰๋œ ์ด๋ฏธ์ง€ 0์žฅ',rows:im.filter(q=>!q.images)}].map(r=>({...r,n:r.rows.length,ok:r.rows.filter(q=>q.correct).length}));$('#workspace').innerHTML=`<div class="section-head"><h1>์ตœ์ข… ํ‰๊ฐ€ ๊ฒฐ๊ณผ</h1><span class="chip good">${fmt(s.questions)} / ${fmt(s.questions)} ์ฑ„์  ์™„๋ฃŒ</span></div><div class="result-banner">GPT-5.6 Luna ยท Qwen3-VL-Embedding-2B ์ „์—ญ top100 ยท <strong>${pct(s.correct,s.questions)}</strong> (${fmt(s.correct)} / ${fmt(s.questions)})</div><div class="results-grid"><section class="panel"><h2>Task ์ƒ์œ„ ๊ทธ๋ฃน</h2>${statsTable(groups,'๊ทธ๋ฃน')}<p class="caption">๋ชจ๋‘ Luna ๋‹ต๋ณ€ ์ •ํ™•๋„์ž…๋‹ˆ๋‹ค. ๊ฒ€์ƒ‰๊ธฐ์˜ Recall@100 ์ง€ํ‘œ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.</p></section><section class="panel"><h2>๊ทผ๊ฑฐ ๋ชจ๋‹ฌ๋ฆฌํ‹ฐ</h2>${statsTable(mod,'๋ฌธํ•ญ ๋ผ๋ฒจ')}<p class="caption">๋ฌธํ•ญ์— ๋ถ€์—ฌ๋œ ๋ผ๋ฒจ ๊ธฐ์ค€์ž…๋‹ˆ๋‹ค. ์‹ค์ œ ๊ฒ€์ƒ‰๋œ ์ด๋ฏธ์ง€ ์ˆ˜์™€๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค.</p></section><section class="panel"><h2>์„ธ๋ถ€ Task</h2>${statsTable(tasks,'Task',k=>url('qa',{task:k}))}</section><section class="panel"><h2>์ด๋ฏธ์ง€ ๊ด€๋ จ ๋ฌธํ•ญ ยท ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ</h2>${statsTable(buckets,'๊ฒ€์ƒ‰๋œ ์ด๋ฏธ์ง€')}<p class="caption">์„œ๋กœ ๋‹ค๋ฅธ ๋ฌธํ•ญ ์ง‘๋‹จ์˜ ๋น„๊ต์ž…๋‹ˆ๋‹ค. ์ด๋ฏธ์ง€ ์ œ๊ณต ์—ฌ๋ถ€๋งŒ ๋ฐ”๊พผ ๋Œ€์กฐ ์‹คํ—˜์ด ์•„๋‹ˆ๋ฏ€๋กœ ์ธ๊ณผ์  ํšจ๊ณผ๋กœ ํ•ด์„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.</p><details class="plain-details" open><summary>๊ทธ๋ฆผ์ด ์žˆ์–ด๋„ Luna๊ฐ€ ๋ชป ๋ณธ ์‚ฌ๋ก€</summary><p>โ€˜child-in-redโ€™ ๊ทธ๋ฆผ์€ ์ด๋ฏธ์ง€๋ผ๋ฆฌ ๋น„๊ตํ•˜๋ฉด 1์œ„์ง€๋งŒ, ํ…์ŠคํŠธ๊นŒ์ง€ ํ•ฉ์นœ ์ „์ฒด ์ˆœ์œ„๋Š” 191์œ„์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ top100์— ํฌํ•จ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.</p><a href="${url('qa',{id:'p01::N260917_23',tab:'gold'})}">ํ•ด๋‹น ๋ฌธํ•ญ ยท ์ „์ฒด 191์œ„ ๊ทธ๋ฆผ ํ™•์ธ โ†’</a></details></section></div><section class="panel"><h2>ํ”„๋กœ์ ํŠธ๋ณ„ ์„ฑ๋Šฅ</h2>${statsTable(INDEX.projects.map(p=>({key:p.id,label:p.id.toUpperCase()+' ยท '+p.label,n:p.questions,ok:p.correct})),'ํ”„๋กœ์ ํŠธ',k=>url('qa',{project:k}))}</section><section class="panel"><h2>์‹คํ—˜ ์„ค์ •๊ณผ ํ•ด์„ ๋ฒ”์œ„</h2><div class="settings-grid"><div class="setting"><span>๊ฒ€์ƒ‰ ๋Œ€์ƒ</span>32๊ฐœ ํ”„๋กœ์ ํŠธ ยท ${fmt(s.units)}๊ฐœ ๋ ˆ์ฝ”๋“œ / ํŽ˜์ด์ง€ ๋‹จ์œ„</div><div class="setting"><span>๊ฒ€์ƒ‰ ๋ชจ๋ธ</span>Qwen3-VL-Embedding-2B ยท 2,048์ฐจ์› ยท ์ฝ”์‚ฌ์ธ ์œ ์‚ฌ๋„</div><div class="setting"><span>์งˆ๋ฌธ ์ž…๋ ฅ</span>์งˆ๋ฌธ ํ…์ŠคํŠธ๋งŒ ยท ํƒ€๊นƒ ํ”„๋กœ์ ํŠธ ์‚ฌ์ „ ํ•„ํ„ฐ ์—†์Œ</div><div class="setting"><span>์ด๋ฏธ์ง€ ์ž…๋ ฅ</span>PDFยทPPT ํŽ˜์ด์ง€์™€ ๋ณ„๋„ ๊ทธ๋ฆผ์˜ ์‹ค์ œ ํ”ฝ์…€ ยท OCR / ์ƒ์„ฑ ์„ค๋ช… ์ถ”๊ฐ€ ์—†์Œ</div><div class="setting"><span>Luna ์ปจํ…์ŠคํŠธ</span>์ „์—ญ top100 ์„ ํƒ ํ›„ ์‹œ๊ฐ„์ˆœ ๋ฐฐ์—ด ยท ์ฒจ๋ถ€ / ๋ฌธ์„œ ์ „์ฒด ์ž๋™ ํ™•์žฅ ์—†์Œ</div><div class="setting"><span>์ฑ„์ </span>์งง์€ Luna ์˜๋ฏธ ํŒ์ • ยท ์งˆ๋ฌธ / ๊ด€์  / Gold / ๋ชจ๋ธ ๋‹ต ๋น„๊ต</div></div><p class="caption">์‘๋‹ต ๋ชจ๋ธ๊ณผ ์ฑ„์  ๋ชจ๋ธ์€ ๋ชจ๋‘ Luna์ž…๋‹ˆ๋‹ค. ํŒ์ •์€ ์‚ฌ๋žŒ์˜ ํ™•์ • ๊ฒ€์ˆ˜๊ฐ€ ์•„๋‹ˆ๋ฉฐ ์ด๊ฒฌ์ด ์ƒ๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์‚ฌ์ดํŠธ๋Š” ์ €์žฅ๋œ ๊ฒฐ๊ณผ๋ฅผ ์ฝ๊ธฐ๋งŒ ํ•˜๊ณ  ๋ชจ๋ธ์„ ์ƒˆ๋กœ ์‹คํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.</p></section>`;}
function imageStatisticsHTML(){
const summarize=OrgBenchImageStats.summarize,s=summarize(INDEX.questions),visual=summarize(INDEX.questions.filter(q=>q.modality!=='text'));
const rows=[{label:'์ „์ฒด ๋ฌธํ•ญ',s},...['text','image','multi'].map(m=>({label:modNames[m],s:summarize(INDEX.questions.filter(q=>q.modality===m))}))];
return `<section class="panel" id="image-count-statistics"><h2>Top100์— ํฌํ•จ๋œ ์ด๋ฏธ์ง€ ์ˆ˜</h2><p class="caption">๊ฐ ๋ฌธํ•ญ์˜ ์‹ค์ œ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ 100๊ฐœ ์ค‘ ์ด๋ฏธ์ง€๋กœ ์ „๋‹ฌ๋œ ํ•ญ๋ชฉ ์ˆ˜์ž…๋‹ˆ๋‹ค. ๋ฌธ์„œ์˜ ํŽ˜์ด์ง€ ์ด๋ฏธ์ง€์™€ ๋ณ„๋„ ๊ทธ๋ฆผ์„ ๋ชจ๋‘ ์…‰๋‹ˆ๋‹ค.</p><div class="image-count-summary"><div class="image-count-stat"><span>๋ฌธํ•ญ๋‹น ํ‰๊ท </span><strong>${s.mean.toFixed(2)}์žฅ / 100๊ฐœ</strong></div><div class="image-count-stat"><span>์ค‘์•™๊ฐ’</span><strong>${s.median}์žฅ</strong></div><div class="image-count-stat"><span>์ตœ์†Œโ€“์ตœ๋Œ€</span><strong>${s.min}โ€“${s.max}์žฅ</strong></div><div class="image-count-stat"><span>90๋ฐฑ๋ถ„์œ„์ˆ˜</span><strong>${s.p90.toFixed(1)}์žฅ</strong></div><div class="image-count-stat"><span>์ด๋ฏธ์ง€ 0์žฅ์ธ ๋ฌธํ•ญ</span><strong>${fmt(s.zero)}๊ฐœ ยท ${pct(s.zero,s.n)}</strong></div></div><div class="image-count-tables"><div><h3>์ด๋ฏธ์ง€ ์ˆ˜๋ณ„ ๋ฌธํ•ญ ๋ถ„ํฌ</h3><div class="table-wrap"><table><thead><tr><th>Top100์˜ ์ด๋ฏธ์ง€ ์ˆ˜</th><th>๋ฌธํ•ญ</th><th>๋น„์œจ</th></tr></thead><tbody>${s.bins.map(b=>`<tr><td>${b.label}</td><td>${fmt(b.n)}</td><td>${pct(b.n,s.n)}</td></tr>`).join('')}</tbody></table></div></div><div><h3>๋ฌธํ•ญ ๋ชจ๋‹ฌ๋ฆฌํ‹ฐ๋ณ„</h3><div class="table-wrap"><table><thead><tr><th>๋ฌธํ•ญ ๋ผ๋ฒจ</th><th>๋ฌธํ•ญ</th><th>ํ‰๊ท  ์ด๋ฏธ์ง€ ์ˆ˜</th><th>์ค‘์•™๊ฐ’</th><th>์ด๋ฏธ์ง€ 0์žฅ ๋ฌธํ•ญ</th></tr></thead><tbody>${rows.map(r=>`<tr><td>${r.label}</td><td>${fmt(r.s.n)}</td><td>${r.s.mean===null?'โ€”':r.s.mean.toFixed(2)}</td><td>${r.s.median??'โ€”'}</td><td>${fmt(r.s.zero)} ยท ${pct(r.s.zero,r.s.n)}</td></tr>`).join('')}</tbody></table></div></div></div><p class="caption">์ด๋ฏธ์ง€ ๊ด€๋ จ ๋ฌธํ•ญ(Image + Multi-image) ${fmt(visual.n)}๊ฐœ: ํ‰๊ท  ${visual.mean.toFixed(2)}์žฅ, ์ค‘์•™๊ฐ’ ${visual.median}์žฅ. ์ด ์ค‘ ${fmt(visual.zero)}๊ฐœ(${pct(visual.zero,visual.n)})์—๋Š” ์ด๋ฏธ์ง€๊ฐ€ ์ „๋‹ฌ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.</p><p class="caption">์ „์ฒด ${fmt(s.slots)}๊ฐœ ๊ฒ€์ƒ‰ ์Šฌ๋กฏ ์ค‘ ์ด๋ฏธ์ง€ ${fmt(s.total)}๊ฐœ(${pct(s.total,s.slots)}). ๋™์ผ ์ด๋ฏธ์ง€๊ฐ€ ์—ฌ๋Ÿฌ ๋ฌธํ•ญ์— ๊ฒ€์ƒ‰๋˜๋ฉด ๊ฐ๊ฐ ์ง‘๊ณ„ํ•˜๋ฏ€๋กœ, ๊ณ ์œ  ์ด๋ฏธ์ง€ ์ˆ˜์™€ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ์ด๋ฏธ์ง€๊ฐ€ ๊ฒ€์ƒ‰๋๋‹ค๋Š” ๊ฒƒ๋งŒ์œผ๋กœ ์ •๋‹ต์— ํ•„์š”ํ•œ ๊ทธ๋ฆผ์ด ํฌํ•จ๋๋‹ค๋Š” ๋œป์€ ์•„๋‹™๋‹ˆ๋‹ค.</p></section>`;
}
function render(){
if(['qa','results'].includes(S.view))S.view='clean';
const generation=++renderGeneration;document.body.classList.toggle('corpus-view',S.view==='stats');$('#notice').textContent='';$('#overview').innerHTML='';
$$('[data-nav]').forEach(a=>{a.classList.toggle('active',a.dataset.nav===S.view);if(a.dataset.nav===S.view)a.setAttribute('aria-current','page');else a.removeAttribute('aria-current');});
if(S.view==='stats'){BenchmarkStats.show(generation);return;}
if(S.view==='world'){renderWorldBrowser(generation);return;}
renderClean(generation);
}
async function init(){try{[INDEX,UNITS]=await Promise.all([getJSON('data/index.json'),getJSON('data/units.json')]);unitMap=new Map(UNITS.map(u=>[u.id,u]));projectMap=new Map(INDEX.projects.map(p=>[p.id,p]));questionMap=new Map(INDEX.questions.map(q=>[q.id,q]));recordUnits=new Map();for(const u of UNITS){if(!recordUnits.has(u.record_id))recordUnits.set(u.record_id,[]);recordUnits.get(u.record_id).push(u);}S=readState();overview();render();getJSON('data/rank_checks.json').then(r=>{RANKS=r;refreshOpenReviewEvidence();if(S.view==='qa'&&S.tab==='gold'&&S.id){const id=S.id;loadQuestion(id).then(q=>{if(q&&S.id===id&&S.view==='qa'&&S.tab==='gold'&&$('#tab-body'))renderEvidence(q);});}}).catch(()=>{rankError=true;});}catch(e){$('#notice').className='notice error';$('#notice').innerHTML=`๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ${esc(e.message)} <button onclick="location.reload()">๋‹ค์‹œ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ</button>`;}}
window.addEventListener('hashchange',()=>{if(!INDEX)return;S=readState();if($('#record-dialog').open)$('#record-dialog').close();render();});$('.skip').addEventListener('click',e=>{e.preventDefault();$('#main').focus();$('#main').scrollIntoView({block:'start'});});$('#close-dialog').addEventListener('click',()=>$('#record-dialog').close());$('#record-dialog').addEventListener('click',e=>{if(e.target===$('#record-dialog'))$('#record-dialog').close();});init();