let items=[],players=[],loot=[],selected=null; const fmt=n=>Number(n).toLocaleString(); async function loadDatabase(){ try{ const response=await fetch('items.json'); if(!response.ok) throw new Error('load'); const raw=await response.json(); items=raw.map(x=>{ const name=(x.LocalizedNames&&x.LocalizedNames["EN-US"])||""; const u=x.UniqueName||""; const ench=(u.match(/@(\d)/)||[])[1]||"0"; const tier=(u.match(/T(\d)/)||[])[1]||""; return {name,label:`${name} (T${tier}.${ench})`}; }).filter(i=>i.name); const s=document.getElementById('dbStatus')||document.getElementById('status'); if(s)s.textContent=''; search.disabled=false; }catch(e){ const s=document.getElementById('dbStatus')||document.getElementById('status'); if(s)s.textContent='Unable to load items.json'; } } loadDatabase(); function renderPlayers(){ playersDiv=playersEl=document.getElementById("players"); playersEl.innerHTML=""; players.forEach((p,i)=>{ const d=document.createElement("span"); d.className="player"; d.innerHTML=`${p} `; d.querySelector("button").onclick=()=>{players.splice(i,1);renderPlayers();}; playersEl.appendChild(d); }); updateSummary(); } function addPlayerFn(){ const n=playerName.value.trim(); if(!n)return; players.push(n); playerName.value=""; renderPlayers(); } addPlayer.onclick=addPlayerFn; playerName.addEventListener("keydown",e=>{if(e.key==="Enter"){e.preventDefault();addPlayerFn();}}); search.oninput=()=>{ const q=search.value.toLowerCase(); results.innerHTML=""; if(q.length<2)return; const groups={}; items.filter(i=>i.name.toLowerCase().includes(q)).slice(0,80).forEach(i=>(groups[i.name]??=[]).push(i)); Object.keys(groups).sort().forEach(name=>{ const g=document.createElement("div");g.className="group"; g.innerHTML=`
${name}
`; groups[name].forEach(it=>{ const c=document.createElement("div");c.className="child";c.textContent=it.label; c.onclick=()=>{selected=it;selectedSpan.textContent=it.label;search.value=it.name;results.innerHTML="";updatePriceInfo();qty.focus();}; g.appendChild(c); }); results.appendChild(g); }); updateSummary(); }; const priceHistory=JSON.parse(localStorage.getItem("priceHistory")||"{}"); function fmtAge(ts){if(!ts)return"Never";let m=Math.floor((Date.now()-ts)/60000);if(m<60)return m+"m ago";let h=Math.floor(m/60);if(h<24)return h+"h ago";let d=Math.floor(h/24);h%=24;return d+"d "+h+"h ago";} function updatePriceInfo(){if(!selected){lastUpdated.textContent="Never";return;}const p=priceHistory[selected.label];if(p){priceEach.value=p.price;updateTotal();lastUpdated.textContent=fmtAge(p.updated);}else lastUpdated.textContent="Never";} const selectedSpan=document.getElementById("selected"); function updateTotal(){totalValue.textContent=fmt((+qty.value||0)*(+priceEach.value||0));} qty.oninput=updateTotal;priceEach.oninput=updateTotal;updateTotal(); addLoot.onclick=()=>{ if(!selected)return alert("Select an item."); const q=+qty.value||1,e=+priceEach.value||0,total=q*e; const existing=loot.find(x=>x.item===selected.label&&x.each===e); if(existing){existing.qty+=q;existing.total=existing.qty*existing.each;} else loot.push({item:selected.label,qty:q,each:e,total,keep:keepTogether.checked}); priceHistory[selected.label]={price:e,updated:Date.now()};localStorage.setItem("priceHistory",JSON.stringify(priceHistory));renderLoot(); selected=null;selectedSpan.textContent="None";search.value="";qty.value=1;priceEach.value=0;updateTotal(); }; function updateSummary(){let stacks=loot.length,items=0,val=0;loot.forEach(l=>{items+=l.qty;val+=l.total;});sumStacks.textContent=stacks;sumItems.textContent=items;sumValue.textContent=fmt(val);targetShare.textContent=players.length?fmt(Math.round(val/players.length)):0;} function renderLoot(){ const tb=document.querySelector("#loot tbody");tb.innerHTML=""; loot.forEach((l,i)=>{ const r=tb.insertRow(); r.insertCell().textContent=l.item; r.insertCell().textContent=l.qty; r.insertCell().textContent=fmt(l.each); r.insertCell().textContent=fmt(l.total); r.insertCell().textContent=l.keep?'✓':''; const b=document.createElement("button");b.textContent="❌";b.onclick=()=>{loot.splice(i,1);renderLoot();}; r.insertCell().appendChild(b); }); updateSummary(); } distribute.onclick=()=>{ if(players.length===0)return alert("Add players first."); let best=null,bestSpread=Infinity; for(let t=0;t<300;t++){ let expanded=[];loot.forEach(l=>{if(l.keep){expanded.push({...l});}else{for(let i=0;iMath.random()-0.5).sort((a,b)=>b.total-a.total); let p=players.map(n=>({name:n,total:0,items:[]})); work.forEach(it=>{p.sort((a,b)=>a.total-b.total);p[0].items.push(it);p[0].total+=it.total;}); let vals=p.map(x=>x.total);let spread=Math.max(...vals)-Math.min(...vals); if(spread{ const merged={};pl.items.forEach(i=>{const k=i.item+'|'+i.each;if(!merged[k])merged[k]={...i};else{merged[k].qty+=i.qty;merged[k].total+=i.total;}}); const d=document.createElement("div"); d.innerHTML=`

${pl.name} — ${fmt(pl.total)} silver

`; distribution.appendChild(d); }); updateSummary(); };