/* career.js — 个人生涯,完全对照参考图 */ let _cPuuid=null,_cGames=[],_cParsed=[],_cSummoner=null; const QMAP={420:'单排',440:'灵活组排',430:'普通对战',450:'极地大乱斗', 900:'无限火力',1700:'斗魂竞技场',1090:'云顶之弈',1100:'云顶排位', 3140:'多人 训练模式 自定义',0:'自定义'}; const qname=id=>QMAP[id]||`模式${id}`; const tierZh=t=>({'IRON':'黑铁','BRONZE':'黄铜','SILVER':'白银','GOLD':'黄金', 'PLATINUM':'铂金','EMERALD':'翡翠','DIAMOND':'钻石','MASTER':'大师', 'GRANDMASTER':'宗师','CHALLENGER':'王者'}[t?.toUpperCase()]||t||'--'); const ip=p=>p?`/api/img?path=${encodeURIComponent(p)}`:''; async function renderCareer(){ const page=document.getElementById('page-career'); page.innerHTML='
加载生涯
'; try{ const s=await API.get('summoner'); _cSummoner=s;_cPuuid=s.puuid; await _loadCareer(s.puuid,s); }catch(e){page.innerHTML='

⏳ 请先启动 LOL 客户端

';} } async function _loadCareer(puuid,summoner){ const page=document.getElementById('page-career'); page.innerHTML='
加载生涯数据
'; try{ const[rr,gr]=await Promise.allSettled([ API.get('ranked'), API.get('games',{puuid,beg:0,end:19}) ]); const ranked=rr.status==='fulfilled'?rr.value:null; const raw=gr.status==='fulfilled'?gr.value:null; console.log('[career] raw keys=', raw ? Object.keys(raw) : null); console.log('[career] raw.games=', raw?.games ? Object.keys(raw.games) : null); console.log('[career] gameCount=', raw?.games?.gameCount); const list=raw?.games?.games||raw?.games||[]; _cGames=Array.isArray(list)?list:[]; _cParsed=_cGames.map(g=>_parseGame(g,puuid)); console.log('[career] _cGames.length=', _cGames.length, '_cParsed=', _cParsed.length); if(_cParsed.length) console.log('[career] first game=', _cParsed[0]); _buildPage(summoner,ranked,_cParsed); }catch(e){page.innerHTML='

加载失败

';} } function _parseGame(game,puuid){ const ids=game.participantIdentities||[]; const ps=game.participants||[]; let pid=-1; for(const id of ids){if(id.player?.puuid===puuid){pid=id.participantId;break;}} if(pid===-1&&ids.length)pid=ids[0].participantId; const p=ps.find(x=>x.participantId===pid)||ps[0]||{}; const st=p.stats||{}; const cid=p.championId||0; const secs=game.gameDuration||0; const dur=`${String(Math.floor(secs/60)).padStart(2,'0')}:${String(secs%60).padStart(2,'0')}`; const ts=game.gameCreation||0; let t=''; if(ts){const d=new Date(ts);t=`${String(d.getHours()).padStart(2,'0')}:${String(d.getMinutes()).padStart(2,'0')} · ${d.getFullYear()}/${String(d.getMonth()+1).padStart(2,'0')}/${String(d.getDate()).padStart(2,'0')}`;} return{ queueId:game.queueId||0,win:st.win||false,remake:st.gameEndedInEarlySurrender||false, kills:st.kills||0,deaths:st.deaths||0,assists:st.assists||0, champLevel:st.champLevel||1,cs:(st.totalMinionsKilled||0)+(st.neutralMinionsKilled||0), gold:st.goldEarned||0,champIcon:`/lol-game-data/assets/v1/champion-icons/${cid}.png`, sp1:`/lol-game-data/assets/v1/summoner-spell-icons/${p.spell1Id||0}.png`, sp2:`/lol-game-data/assets/v1/summoner-spell-icons/${p.spell2Id||0}.png`, items:[st.item0,st.item1,st.item2,st.item3,st.item4,st.item5,st.item6] .map(id=>id?`/lol-game-data/assets/v1/item-icons/${id}.png`:''), time:t,dur, }; } function _stats(games){ let k=0,d=0,a=0,w=0,l=0; for(const g of games){ if(g.remake||g.queueId===0)continue; k+=g.kills;d+=g.deaths;a+=g.assists; if(g.win)w++;else l++; } return{k,d,a,w,l,kda:d===0?(k+a).toFixed(1):((k+a)/d).toFixed(1)}; } function _champIcons(games){ const map={}; for(const g of games){ if(!g.champIcon)continue; if(!map[g.champIcon])map[g.champIcon]={icon:g.champIcon,t:0,w:0}; map[g.champIcon].t++;if(g.win)map[g.champIcon].w++; } return Object.values(map).sort((a,b)=>b.t-a.t).slice(0,10); } function _rankRow(r,label){ const t=r.tier||'',dv=r.division||''; const w=r.wins||0,l=r.losses||0,tot=w+l; const div=dv==='NA'?'':dv; const tier=t?tierZh(t)+' '+div:'--'; const high=r.highestTier?tierZh(r.highestTier)+' '+(r.highestDivision==='NA'?'':r.highestDivision):'--'; const prev=r.previousSeasonEndTier?tierZh(r.previousSeasonEndTier)+' '+(r.previousSeasonEndDivision==='NA'?'':r.previousSeasonEndDivision):'--'; return`${label}${tot||0}${tot?Math.round(w*100/tot)+'%':'--'}${w}${l}${tier}${r.leaguePoints??0}${high}${prev}`; } function _buildPage(s,ranked,games){ const page=document.getElementById('page-career'); const name=s.gameName||s.displayName||'---'; const tag=s.tagLine||''; const lvl=s.summonerLevel||'--'; const iconUrl=ip(`/lol-game-data/assets/v1/profile-icons/${s.profileIconId||29}.jpg`); const copyTxt=tag?`${name}#${tag}`:name; const solo=ranked?.queueMap?.['RANKED_SOLO_5x5']||{}; const flex=ranked?.queueMap?.['RANKED_FLEX_SR']||{}; const{k,d,a,w,l,kda}=_stats(games); const champs=_champIcons(games).map(c=>``).join(''); page.innerHTML=`
${lvl}
${esc(name)}
${tag?`
# ${esc(tag)}
`:''}
${_rankRow(solo,'单排')}${_rankRow(flex,'灵活组排')}
游戏类型总计胜率胜场败场段位胜点最高段位上赛季结算段位
近期战绩(最近 ${games.length} 场) 胜场:${w} 败场:${l} KDA: ${k} / ${d} / ${a} (${kda})
${champs}
`; _renderGames(games,0); } function _renderGames(games,qid){ const el=document.getElementById('cvGL');if(!el)return; const list=qid?games.filter(g=>g.queueId===qid):games; if(!list.length){el.innerHTML='

暂无战绩

';return;} el.innerHTML=list.map(g=>{ const win=g.win,rm=g.remake; const rc=rm?'cr':''; const bc=rm?'gbar re':(win?'gbar win':'gbar lose'); const rtxt=rm?'重开':(win?'胜利':'失败'); const rcls=rm?'gres cr':(win?'gres cw':'gres cl'); const gold=g.gold>=1000?(g.gold/1000).toFixed(1)+'k':g.gold||0; const items=(g.items||[]).slice(0,7).map(p=> p?`` :``).join(''); const s1=g.sp1?``:''; const s2=g.sp2?``:''; return`
${rtxt}
${esc(qname(g.queueId))}
${g.champLevel}
${s1}${s2}
${g.kills} / ${g.deaths} / ${g.assists}
${g.cs} CS · ${g.dur}
${items}
${gold} G
${esc(g.time||'')}
`; }).join(''); } function careerFilter(qid){_renderGames(_cParsed,qid);} async function careerRefresh(){if(_cPuuid&&_cSummoner)await _loadCareer(_cPuuid,_cSummoner);} async function careerBackToMe(){ try{const s=await API.get('summoner');_cSummoner=s;_cPuuid=s.puuid;await _loadCareer(s.puuid,s);} catch(e){showToast('获取失败','err');} }