Skip to content

Instantly share code, notes, and snippets.

@Maistho
Created July 21, 2019 23:21
Show Gist options
  • Save Maistho/5e93df870604a0842e8931133e552c94 to your computer and use it in GitHub Desktop.
Save Maistho/5e93df870604a0842e8931133e552c94 to your computer and use it in GitHub Desktop.
javascript:var CsgoMap;!function(t){t.de_mirage="Mirage",t.de_dust2="Dust II",t.de_subzero="Subzero",t.de_train="Train",t.de_nuke="Nuke",t.de_inferno="Inferno",t.de_cache="Cache",t.de_overpass="Overpass"}(CsgoMap||(CsgoMap={}));class MinMaxAvg{constructor(){this.min=1/0,this.max=-1/0,this.avg=0,this.total=0}append(t,e){this.min=Math.min(t,this.min),this.max=Math.max(t,this.max),this.total+=t,this.avg=this.total/e}}class PlayerStats{constructor(t){this.timesPlayed=0,this.roundsPlayed=0,this.ping=new MinMaxAvg,this.kills=new MinMaxAvg,this.assists=new MinMaxAvg,this.deaths=new MinMaxAvg,this.mvps=new MinMaxAvg,this.headshotRate=new MinMaxAvg,this.score=new MinMaxAvg,this.link=t.link,this.image=t.image,this.name=t.name}add(t,e){this.roundsPlayed+=e,this.timesPlayed+=1,this.ping.append(t.ping,this.timesPlayed),this.kills.append(t.kills,this.timesPlayed),this.assists.append(t.assists,this.timesPlayed),this.deaths.append(t.deaths,this.timesPlayed),this.mvps.append(t.mvps,this.timesPlayed),this.headshotRate.append(Number(t.headshotRate),this.timesPlayed),this.score.append(t.score,this.timesPlayed)}}async function getAllMatches(){if("steamcommunity.com"!=window.location.hostname)return alert("Redirecting to steamcommunity.com, please run the bookmarklet again after the page has reloaded"),void(window.location.href="https://steamcommunity.com");const t=document.querySelector("#global_actions>a.user_avatar");if(!t)throw alert("You need to be logged in"),new Error("User not logged in");const e=t.href.replace(/\/$/,""),n=[];let a,i=0;do{const t=new URLSearchParams({ajax:"1",tab:"matchhistorycompetitive"});a&&t.append("continue_token",a);const s=`${e}/gcpd/730?${t.toString()}`;let o;const r=`_csgo_stats_cache_${s}`;if(a)try{o=JSON.parse(localStorage.getItem(r)||"")}catch(t){}if(o||(o=await fetch(s,{credentials:"include"}).then(t=>t.json())),!o.success)throw new Error(JSON.stringify(o));localStorage.setItem(r,JSON.stringify(o));const l=(new DOMParser).parseFromString(o.html,"text/html");n.push(...Array.from(l.querySelectorAll(".generic_kv_table.csgo_scoreboard_root>tbody>tr")).map(t=>({map:getMap(t),time:getTime(t),waitTime:getWaitTime(t),matchDuration:getMatchDuration(t),score:getScore(t),demo:getDemo(t),...getTeams(t,e)})).filter(({map:t})=>!!t)),a=o.continue_token,loadingStatus.innerText=`${++i} pages parsed...`}while(a);return n}const getTeams=(t,e)=>{const n=[[],[]],a=Array.from(t.querySelectorAll(".csgo_scoreboard_inner_right>tbody>tr"));let i=-1;for(const t of a){const e=q(t,"a.linkTitle");null!=e?n[i].push({link:e.attributes.getNamedItem("href").textContent||"",name:getInfo(t,"a.linkTitle"),image:getAttribute(q(t,".playerAvatar img"),"src"),ping:parseInt(getInfo(t,"td:nth-child(2)")),kills:parseInt(getInfo(t,"td:nth-child(3)")),assists:parseInt(getInfo(t,"td:nth-child(4)")),deaths:parseInt(getInfo(t,"td:nth-child(5)")),mvps:parseInt(getInfo(t,"td:nth-child(6)").substr(1))||0,headshotRate:getInfo(t,"td:nth-child(7)"),score:parseInt(getInfo(t,"td:nth-child(8)"))}):i+=1}return{teams:n,userTeam:n.findIndex(t=>t.some(t=>t.link===e))}},getDemo=t=>{const e=q(t,".csgo_scoreboard_inner_left .csgo_scoreboard_btn_gotv");return getAttribute(e&&e.parentElement,"href")},getScore=t=>getInfo(t,".csgo_scoreboard_score"),getMatchDuration=t=>getInfo(t,".csgo_scoreboard_inner_left>tbody>tr:nth-child(4)").replace(/^Match Duration: /,""),getWaitTime=t=>getInfo(t,".csgo_scoreboard_inner_left>tbody>tr:nth-child(3)").replace(/^Wait Time: /,""),getTime=t=>new Date(getInfo(t,".csgo_scoreboard_inner_left>tbody>tr:nth-child(2)")),getMap=t=>getInfo(t,".csgo_scoreboard_inner_left>tbody>tr:nth-child(1)").replace(/^Competitive /,"");function getInfo(t,e){return getText(q(t,e))}function getText(t){return(t&&t.textContent||"").trim()}function q(t,e){return t&&t.querySelector(e)}function getAttribute(t,e){return(t&&t.getAttribute(e)||"").trim()}function parseMatches(t){const e={},n={};return t.forEach(t=>{const a=t.score.split(":").map(t=>t.trim()).map(t=>Number(t)),i=a[0]+a[1],s=t.userTeam,o=0===s?1:0;e[t.map]||(e[t.map]={name:t.map,timesPlayed:0,wins:0,losses:0,draws:0,winrate:0,roundsWon:0,roundsLost:0,roundWinrate:0});const r=e[t.map];a[s]>a[o]?r.wins+=1:a[s]<a[o]?r.losses+=1:r.draws+=1,r.timesPlayed+=1,r.roundsWon+=a[s],r.roundsLost+=a[o];for(const e of t.teams)for(const t of e){n[t.link]||(n[t.link]=new PlayerStats(t)),n[t.link].add(t,i)}}),Object.keys(e).forEach(t=>{const n=e[t];n.winrate=n.wins/(n.timesPlayed-n.draws),n.roundWinrate=n.roundsWon/(n.roundsWon+n.roundsLost)}),{maps:e,players:n}}function fmt(t){return Number(t.toFixed(2))}function printStatistics(t,e){console.table(e.sort((t,e)=>e.timesPlayed-t.timesPlayed).slice(0,50).map(t=>({name:t.name,gamesPlayed:t.timesPlayed,kdr:fmt(t.kills.total/t.deaths.total),totalKills:t.kills.total,avgKills:fmt(t.kills.avg),killsPerRound:fmt(t.kills.total/t.roundsPlayed)})));var n=Object.values(t).sort((t,e)=>e.winrate-t.winrate).map(t=>({...t,winrate:formatWinrate(t.winrate),roundWinrate:formatWinrate(t.roundWinrate)}));console.table(n);let a=`<table style="margin: 0 auto;">\n <tr>\n <th>Map</th>\n <th>Winrate</th>\n <th>(W/D/L)</th>\n </tr>\n ${n.map(t=>`\n <tr>\n <td>${t.name}</td>\n <td>${t.winrate}</td>\n <td>(${t.wins}/${t.draws}/${t.losses})</td>\n </tr>\n `).join("\n")}\n </table>`;const i="__maistho_csgo_stats_table_wrapper";let s=document.getElementById(i);s||((s=document.createElement("div")).id=i,s.style.background="#171a21",s.style.color="white",document.body.prepend(s)),s.innerHTML=a;const o=`${s.clientHeight}px`,r=document.querySelector(".responsive_header");r&&(r.style.marginTop=o)}function formatWinrate(t){return(100*t).toLocaleString(void 0,{maximumFractionDigits:2,minimumFractionDigits:0})+"%"}const loadingSpinner=document.createElement("div");loadingSpinner.innerHTML='<img src="https://steamcommunity-a.akamaihd.net/public/images/login/throbber.gif">',loadingSpinner.style.display="flex",loadingSpinner.style.alignItems="center",loadingSpinner.style.justifyContent="center",loadingSpinner.style.position="fixed",loadingSpinner.style.top="0",loadingSpinner.style.left="0",loadingSpinner.style.bottom="0",loadingSpinner.style.right="0",loadingSpinner.style.background="rgba(0,0,0,0.5)",loadingSpinner.style.flexDirection="column",loadingSpinner.style.zIndex="999999";const loadingStatus=document.createElement("div");loadingStatus.innerText="0 pages parsed...",loadingStatus.style.color="white",loadingStatus.style.margin="1em",loadingSpinner.appendChild(loadingStatus),document.body.appendChild(loadingSpinner),getAllMatches().then(t=>{const{maps:e,players:n}=parseMatches(t);printStatistics(e,Object.values(n))}).catch(t=>{alert(t)}).finally(()=>{document.body.removeChild(loadingSpinner)});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment