yangzijing's picture
Publish verified nine-source P3R3 browser and review reports
df02b06 verified
Raw History Blame Contribute Delete
2.27 kB
/* Pure deterministic sampling; sequence identities come only from the source index. */
(function(root) {
function rng(seed) {
let h=2166136261;
for(const c of String(seed)){h^=c.charCodeAt(0);h=Math.imul(h,16777619);}
return ()=>{h+=0x6D2B79F5;let t=Math.imul(h^(h>>>15),1|h);t^=t+Math.imul(t^(t>>>7),61|t);return ((t^(t>>>14))>>>0)/4294967296;};
}
function shuffle(a,random){a=[...a];for(let i=a.length-1;i>0;i--){const j=Math.floor(random()*(i+1));[a[i],a[j]]=[a[j],a[i]];}return a;}
function sequenceQueue(items,random){
const groups=new Map();
for(const item of [...items].sort((a,b)=>a.id.localeCompare(b.id))){const key=item.recording_id || 'unmapped:'+item.id;if(!groups.has(key))groups.set(key,[]);groups.get(key).push(item);}
const queues=shuffle([...groups.values()],random).map(g=>shuffle(g,random));const out=[];
while(queues.some(q=>q.length))for(const q of queues)if(q.length)out.push(q.shift());
return out;
}
function sample(items,options){
const random=rng(options.seed), n=Math.max(0,Math.floor(Number(options.n)||0));
const names=[...new Set(options.datasets)].sort();
const queues=names.map(ds=>sequenceQueue(items.filter(s=>s.dataset===ds),random));
const caps=queues.map(q=>q.length),take=caps.map(()=>0);
if(options.mode==='per_dataset')for(let i=0;i<caps.length;i++)take[i]=Math.min(n,caps[i]);
else {
const target=Math.min(n,caps.reduce((a,b)=>a+b,0));
const order=shuffle(caps.map((_,i)=>i),random);
if(options.balance==='proportional'){
const total=caps.reduce((a,b)=>a+b,0);
if(total){const ideals=caps.map(c=>target*c/total);for(let i=0;i<caps.length;i++)take[i]=Math.floor(ideals[i]);
order.sort((a,b)=>(ideals[b]-take[b])-(ideals[a]-take[a]));
let left=target-take.reduce((a,b)=>a+b,0);for(const i of order)if(left>0&&take[i]<caps[i]){take[i]++;left--;}}
}else{let left=target;while(left>0)for(const i of order)if(left>0&&take[i]<caps[i]){take[i]++;left--;}}
}
return shuffle(queues.flatMap((q,i)=>q.slice(0,take[i])),random);
}
const api={sample,rng,sequenceQueue};if(typeof module!=='undefined')module.exports=api;else root.ReviewSampling=api;
})(typeof window!=='undefined'?window:globalThis);