xp-v0.2.0
Gameweek
4
updated 49m agoxp-v0.2.0

Iconka Stars

entry 7181076

Squad verified from official GW3 picks. Tap any player for the full picture.

Bench

Weak spots

Manager state provenance

bankRECONSTRUCTED
0.5

from last finished GW; ignores transfers made since

free transfersRECONSTRUCTED
4

chronological replay of 3 finished gameweek(s) under carry rules (cap 5)

selling pricesAPPROXIMATED
current prices

partial or missing map; plans default sale value to current price

(function(){ function esc(s){return String(s==null?'':s).replace(/[&<>"]/g,function(c){ return {'&':'&','<':'<','>':'>','"':'"'}[c];});} window.fplEsc=esc; var data=window.FPL_DRAWER||[]; var drawer=document.getElementById('pdrawer'); if(!drawer)return; var panel=document.getElementById('pd-panel'); var lastFocus=null; function fmt(v,suffix,dp){if(v===null||v===undefined)return'–'; return (typeof v==='number'?v.toFixed(dp||1):v)+suffix;} function stat(k,v){return '
'+v+'
'+k+'
';} function kvh(t){return '
'+t+'
';} function open(id){var p=data.find(function(r){return String(r.id)===String(id)}); if(!p)return; lastFocus=document.activeElement; var prov=p.is_c?'CAPTAIN':(p.is_v?'VICE-CAPTAIN':''); var range=(p.lo===null||p.lo===undefined)?'–':(p.lo.toFixed(1)+'\u2013'+p.hi.toFixed(1)); var press=(p.plvl?p.plvl:'')+(p.pdir&&p.pdir!=='FLAT'?' '+(p.pdir==='UP'?'\u2191':(p.pdir==='DOWN'?'\u2193':'')):''); var avail=(p.news?''+esc(p.status)+' ':'') +(p.chance!==null&&p.chance!==undefined?''+p.chance+'% to play':''); panel.innerHTML= '' +'

'+esc(p.name)+'

' +(prov?''+prov+' ':'') +''+esc(p.team)+'' +''+esc(p.fixture||'fixture n/a')+'' +avail +kvh('Projection (modelled)') +'
' +stat('xP',fmt(p.xp,'',2)) +stat('xMins',fmt(p.mins,'',0)) +stat('Range',range) +stat('Risk',fmt(p.risk,'',2)) +'
' +kvh('Availability') +'
' +stat('Status',esc((p.status==='a'?'available':(p.status||'-')))) +stat('News',p.news?esc(String(p.news).slice(0,26)):'none') +'
' +kvh('Market (observed)') +'
' +stat('Price','\u00a3'+fmt(p.price,'m')) +stat('24h move',(p.d24===null||p.d24===undefined)?'\u2013':(p.d24>0?'+':'')+p.d24.toFixed(1)+'m') +stat('Owned',fmt(p.ownership,'%')) +stat('Net GW',fmt(p.net_gw,'',0)) +stat('Vel 6h',(p.v6===null||p.v6===undefined)?'\u2013':fmt(p.v6,'/h',0)) +stat('Pressure',press||'\u2013') +'
' +'
Why: '+window.fplWhyText(p.components)+'
' +'

Model '+esc(p.model) +' · projections are model estimates; market figures are observed.

'; drawer.classList.add('open'); var closeBtn=panel.querySelector('[data-close]'); if(closeBtn)closeBtn.addEventListener('click',close); panel.tabIndex=-1;panel.focus();} function close(){drawer.classList.remove('open'); if(lastFocus&&lastFocus.focus)lastFocus.focus();} function stat2(k,v){return stat(k,v);} window.fplWhyText=function(components){ var c=components||{};var labels={appearance:'secure minutes outlook',goals:'goal threat', assists:'chance creation',clean_sheet:'clean-sheet outlook',bonus:'bonus potential', saves:'shot-stopping volume',goals_conceded:'expected defensive concessions', cards:'discipline risk',defensive_contribution:'defensive-contribution scoring'}; var pos=Object.keys(c).filter(function(k){return c[k]>=0.15}) .sort(function(a,b){return c[b]-c[a];}).slice(0,2) .map(function(k){return labels[k]||k;}); var neg=Object.keys(c).filter(function(k){return c[k]<=-0.1}) .sort(function(a,b){return c[a]-c[b];}).map(function(k){return labels[k]||k;})[0]; var s=pos.length?('Most of the projection comes from '+pos.join(' together with ')) :'The projection is modest across every component'; if(neg)s+=', partly offset by '+neg; return esc(s+'. Component values are model estimates.');}; document.querySelectorAll('.pcard[data-player-id]').forEach(function(el){ el.addEventListener('click',function(){open(el.getAttribute('data-player-id'));});}); drawer.addEventListener('click',function(e){ if(e.target.hasAttribute('data-close'))close();}); document.addEventListener('keydown',function(e){ if(e.key==='Escape'){close(); var sh=document.getElementById('moresheet');if(sh)sh.classList.remove('open');}}); /* Swipe-down to dismiss (mobile sheet behaviour the grabber promises). */ var startY=null,dY=0; panel.addEventListener('touchstart',function(e){ if(drawer.classList.contains('open')&&e.touches.length===1){ startY=e.touches[0].clientY;dY=0;}},{passive:true}); panel.addEventListener('touchmove',function(e){ if(startY===null)return;dY=e.touches[0].clientY-startY; if(dY>0){panel.style.transform='translateY('+dY+'px)'; panel.style.transition='none';}},{passive:true}); panel.addEventListener('touchend',function(){ if(startY===null)return; panel.style.transition='';panel.style.transform=''; if(dY>90)close(); startY=null;}); })();