Skip to content

Instantly share code, notes, and snippets.

@Element118
Last active March 21, 2020 10:11
Show Gist options
  • Save Element118/65ded2b36d030e5564971032edff48ea to your computer and use it in GitHub Desktop.
Save Element118/65ded2b36d030e5564971032edff48ea to your computer and use it in GitHub Desktop.
Singapore Sightread Tournament Point Counter
// ==UserScript==
// @name SST counter
// @namespace http://tampermonkey.net/
// @version 1.2
// @description Point counter for Singapore Sightread Tournament
// @author Element118
// @match https://osu.ppy.sh/community/matches/*
// @grant none
// ==/UserScript==
/**
Assumptions:
I'm relying on the first maps being warmups, and each room playing the same number of warmups.
If a room plays a different number of warmups, update this code.
**/
(function() {
'use strict';
// edit these variables according to the requirements
let numMaps = 8;
let firstMapIndex = 3;//1; // number of warmup maps
let DQ = [""]; // usernames of disqualified users and refs
// rest of code
let el = document.createElement("button"); el.innerText = "Calculate!";
let doOver = setInterval(function() {
let title = document.getElementsByClassName("header-v4__title")[0];
if (title) {
clearInterval(doOver);
let doOver2 = setInterval(function() {
let refText = document.getElementsByClassName("mp-history-event__text")[0];
if (refText) {
console.log(refText.textContent);
DQ.push(refText.textContent.split(" created the match")[0]);
clearInterval(doOver2);
title.appendChild(el);
}
}, 500);
}
}, 500);
let rankData = function(scores) {
let result = [];
let prevRank = 0, prevScore = Math.pow(2, 31), prevFail = false;
for (let i=0;i<scores.length;i++) {
let failed = scores[i].getElementsByClassName("mp-history-player-score__failed").length > 0;
let score = scores[i].getElementsByClassName("mp-history-player-score__stat-number mp-history-player-score__stat-number--large")[0].textContent;
result.push({
name: scores[i].getElementsByClassName("mp-history-player-score__username")[0].textContent,
score: score,
failed: failed
});
}
result.sort(function(a, b) {
if (a.failed !== b.failed) {
if (a.failed) return 1;
if (!a.failed) return -1;
}
return b.score - a.score;
});
for (let i=0;i<scores.length;i++) {
let failed = scores[i].failed
let score = scores[i].score
let rank = (+score == +prevScore && failed == prevFail)?prevRank:prevRank+1;
result[i].rank = rank;
prevRank = rank; prevScore = score; prevFail = failed;
}
return result;
};
el.addEventListener("click", function() {
let maps = document.getElementsByClassName("mp-history-game");
let scoreEls = [];
let mapsFound = 0;
for (let i=0;i<maps.length;i++) {
var mapName = maps[i].getElementsByClassName("mp-history-game__metadata mp-history-game__metadata--title")[0].textContent;
if (maps[i].getElementsByClassName("mp-history-game__stat")[0].textContent.indexOf("(match in progress)") === -1) {
let scores = maps[i].getElementsByClassName("mp-history-player-score__main");
scoreEls.push(rankData(scores));
}
}
let dataTb = {};
let mapNum = 0;
let defaultPoints = [];
console.log("Maps played: " + scoreEls.length);
for (let i=0;i<numMaps;i++) {
let index = scoreEls.length-numMaps+i;
if (index < firstMapIndex) continue;
mapsFound++;
let points = 1; // points of next rank
let prevPoints = 0;
let prevRank = 0;
for (let j=0;j<scoreEls[index].length;j++) {
let name = scoreEls[index][j].name;
let rank = scoreEls[index][j].rank;
if (DQ.indexOf(name) === -1) { // not disqualified
dataTb[name] = dataTb[name] || [];
while (dataTb[name].length < mapNum) {
dataTb[name].push(defaultPoints[dataTb[name].length]);
}
if (rank > prevRank) prevPoints = points;
dataTb[name].push(prevPoints);
points++;
}
}
defaultPoints.push(points);
// if player not accounted for?
mapNum++;
for (let i in dataTb) {
dataTb[i] = dataTb[i] || [];
while (dataTb[i].length < mapNum) {
dataTb[i].push(defaultPoints[dataTb[i].length]);
}
}
}
console.log(mapsFound + " out of " + numMaps + " played!");
let sortedData = [];
let longName = 0;
for (let i in dataTb) {
longName = Math.max(longName, i.length);
}
for (let i in dataTb) {
var points = dataTb[i].reduce(function(a, b) { return a+b; });
sortedData.push({
text: i+" ".repeat(longName-i.length)+": "+dataTb[i].join(" ")+" ["+points+"]\n",
points: points
});
}
sortedData.sort(function(a, b) { return a.points-b.points; });
let niceOutput = "";
let hasTies = false;
for (var i=0;i<sortedData.length;i++) {
niceOutput += sortedData[i].text;
if (i > 0 && sortedData[i].points == sortedData[i-1].points) hasTies = true;
}
console.log(niceOutput);
// I think warning about ties here is sufficient.
if (hasTies) {
console.log("WARNING: TIE");
}
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment