Align dashboard next-in-line with the rotation queue

The chain-only BFS pick could promote structurally-next but inactive
positions (#21's dashboard said #38 — not in the queue, likely inactive —
while the team rotation was working #36). Next-in-line now prefers the
active rotation sponsor when they're in the member's leg and unqualified,
then the first chain-order queue participant, falling back to the pure
structural pick for legs outside the queue.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-08-14 10:34:17 -05:00
parent 62ad2da2fa
commit 3a93fda3eb
+17
View File
@@ -311,6 +311,23 @@ async function handleApi(req,res,pathname){
try{ try{
const r=await Promise.race([chain.memberPublic(id),new Promise((_,rej)=>setTimeout(()=>rej(new Error('Blockchain lookup timed out — try again.')),20000))]); const r=await Promise.race([chain.memberPublic(id),new Promise((_,rej)=>setTimeout(()=>rej(new Error('Blockchain lookup timed out — try again.')),20000))]);
if(r.registered)r.referralUrl=`${getConfig().dappReferralBaseUrl}${encodeURIComponent(id)}`; if(r.registered)r.referralUrl=`${getConfig().dappReferralBaseUrl}${encodeURIComponent(id)}`;
// align next-in-line with the human-curated rotation: prefer the ACTIVE
// rotation sponsor when they sit in this member's leg and need directs;
// else the first chain-order position that's a queue participant; else
// keep the chain's pure structural pick (covers legs outside the queue).
if(r.registered&&r.subtree){
try{
const sponsors=getSponsors();
const act=activeSponsor(sponsors);
const participants=new Set(sponsors.filter(s=>s.status!=='qualified').map(s=>String(s.id)));
const bfs=[];const q=[r.subtree.left,r.subtree.right].filter(Boolean);
while(q.length){const n=q.shift();bfs.push(n);if(n.left)q.push(n.left);if(n.right)q.push(n.right);}
let pick=null;
if(act)pick=bfs.find(n=>String(n.id)===String(act.id)&&(n.directCount||0)<2);
if(!pick)pick=bfs.find(n=>participants.has(String(n.id))&&(n.directCount||0)<2);
if(pick)r.nextInLine={id:pick.id,directCount:pick.directCount||0,levelName:pick.levelName};
}catch(e){}
}
if(r.nextInLine)r.nextInLine.referralUrl=`${getConfig().dappReferralBaseUrl}${encodeURIComponent(r.nextInLine.id)}`; if(r.nextInLine)r.nextInLine.referralUrl=`${getConfig().dappReferralBaseUrl}${encodeURIComponent(r.nextInLine.id)}`;
memberCache.set(id,{data:r,ts:Date.now()}); memberCache.set(id,{data:r,ts:Date.now()});
if(memberCache.size>500)memberCache.delete(memberCache.keys().next().value); if(memberCache.size>500)memberCache.delete(memberCache.keys().next().value);