// ==UserScript==
// @name pp for osu score pages
// @namespace http://osustats.ppy.sh
// @description shows pp data from osustats.ppy.sh on osu score pages.
// @include http*://osu.ppy.sh/b/*
// @include http*://osu.ppy.sh/s/*
// @include http*://osu.ppy.sh/p/beatmap?b=*
// @include http*://osu.ppy.sh/p/beatmap?s=*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_deleteValue
// @grant GM_xmlhttpRequest
// @version 4.2
// ==/UserScript==
if (!this.GM_getValue || (this.GM_getValue.toString && this.GM_getValue.toString().indexOf("not supported")>-1)) {
this.GM_getValue=function (key,def) {
return localStorage[key] || def;
};
this.GM_setValue=function (key,value) {
return localStorage[key]=value;
};
this.GM_deleteValue=function (key) {
return delete localStorage[key];
};
}
var result = null,
mapID = null,
mapMode = null,
scoresMissing = false,
time = 2,
interval,
requestedUpdate = false,
updateInProgress=true,
isNoModOnly=false,
InfoBoxRef = null,
scoresTableRef = null,
scoresTableBodyRef = null;
function Start() {
scoresMissing = false;
if (mapID != null && mapMode != null) {
GetScores(mapID, mapMode, function(res) {
result = JSON.parse(res);
UpdateOsuScoresTable();
if (scoresMissing) {
if(requestedUpdate) {
updateInProgress = false;
SetInfoText("Updated successfully");
if(GM_getValue("Sort_by_pp"))
SortOsuScoresTable(true);
}
else
{
if(!isNoModOnly)
{
RequestBeatmapUpdate(mapID, mapMode, function(accepted) {
if (accepted) {
interval = setInterval(Countdown, 1000);
}
});
}
}
}
else
{
updateInProgress = false;
if(GM_getValue("Sort_by_pp"))
SortOsuScoresTable(true);
}
});
}
}
function Init() {
InfoBoxRef = document.getElementsByClassName("content-with-bg")[0].getElementsByTagName("h2")[document.getElementsByClassName("content-with-bg")[0].getElementsByTagName("h2").length-1];
if (InfoBoxRef != null) {
mapID = InfoBoxRef.nextElementSibling.children[0].children[0].value;
mapMode = InfoBoxRef.nextElementSibling.children[0].children[1].value;
if (mapID != null) {
RefreshTableReferences();
isNoModOnly =InfoBoxRef.nextElementSibling.children[0].children[2].checked;
AddppSortCheckbox();
return true;
}
}
return false;
}
function RefreshTableReferences() {
scoresTableRef = document.getElementsByClassName("beatmapListing")[0].children[0];
scoresTableBodyRef = scoresTableRef.getElementsByTagName('tbody')[0];
}
function UpdateOsuScoresTable() {
numOfRows = scoresTableBodyRef.getElementsByTagName("tr").length;
if (!requestedUpdate) {
th = document.createElement('th');
th.innerHTML = "pp"
scoresTableBodyRef.children[0].insertBefore(th, scoresTableBodyRef.children[0].childNodes[3]);
}
for (var i = 1; i < numOfRows; i++) {
row = scoresTableBodyRef.children[i];
if(requestedUpdate)
{
username = row.children[5].children[1].innerHTML;
ppCell = scoresTableBodyRef.getElementsByTagName("tr")[i].children[3];
}
else
{
username = row.children[4].children[1].innerHTML;
ppCell = scoresTableBodyRef.getElementsByTagName("tr")[i].insertCell(3);
}
score = row.children[2].innerHTML.replace(/,/g, '').replace(/<b>/g, '').replace(/<\/b>/g, '');
pp = GetPpFromUsername(username, score);
ppCell.innerHTML = pp;
};
}
function GetPpFromUsername(username, score) {
for (var i = 0; i < result.length; i++) {
if (username == result[i].name) {
if (score == result[i].score) {
return (Math.round(result[i].pp * 100) / 100);
}
scoresMissing = true;
return "N/U";
}
}
scoresMissing = true;
return "N/D";
}
function GetScores(mapID, mapMode, callback) {
GetPage("http://osustats.ppy.sh/api/beatmap/getScores/" + mapID + "/" + mapMode, function(res) {
callback(res);
});
}
function RequestBeatmapUpdate(mapID, mapMode, callback) {
GetPage("http://osustats.ppy.sh/api/beatmap/updateRequest/" + mapID + "/" + mapMode, function(res) {
requestedUpdate = true;
res = JSON.parse(res);
if (res.status == "OK") {
callback(true);
} else {
callback(false);
SetInfoText("Request failed- try again later.");
}
});
}
function GetPage(url, callback) {
GM_xmlhttpRequest({
method: "GET",
url: url,
synchronous: true,
headers: {
Referer: location.href
},
onload: function(resp) {
callback(resp.responseText);
}
});
}
function Countdown() {
time--;
SetInfoText("Missing scores detected- Update requested</br>Updating in " + time + " seconds");
if (time == 0) {
clearInterval(interval);
SetInfoText("Updating...");
Start();
}
}
function SetInfoText(text) {
InfoBoxRef.innerHTML = "<div style=\"font: 30px; text-align: center;\">" + text + "</div>"
}
function AddppSortCheckbox() {
var checkbox = document.createElement('input');
checkbox.type = "checkbox";
checkbox.name = "name";
checkbox.value = "value";
checkbox.id = "id";
checkbox.onchange=function x() {
GM_setValue("Sort_by_pp", InfoBoxRef.nextElementSibling.children[0].children[4].checked);
SortOsuScoresTable(GM_getValue("Sort_by_pp"));
};
if(GM_getValue("Sort_by_pp"))
checkbox.checked = GM_getValue("Sort_by_pp");
var label = document.createElement('label')
label.htmlFor = "id";
label.appendChild(document.createTextNode('Sort score table by pp'));
InfoBoxRef.nextElementSibling.children[0].appendChild(checkbox);
InfoBoxRef.nextElementSibling.children[0].appendChild(label);
}
function SortOsuScoresTable(sortByPp) {
if(updateInProgress) return;
if(sortByPp)
column=3;
else
column=2;
function isNumeric(num){
return !isNaN(num)
}
function RowCompareNumbers(a, b) {
var aVal = parseInt(a.value);
var bVal = parseInt(b.value);
return (bVal - aVal);
}
var rows = scoresTableBodyRef.getElementsByTagName('tr');
var rowArray = new Array();
var tempValue;
for (var i = 1, length = rows.length; i < length; i++) {
rowArray[i] = new Object;
rowArray[i].oldIndex = i;
tempValue =rows[i].getElementsByTagName('td')[column].firstChild.textContent.replace(/\,/g, '');;
if(isNumeric(tempValue))
rowArray[i].value = tempValue;
else
rowArray[i].value = "0";
}
rowArray.sort(RowCompareNumbers);
var newTbody = document.createElement('tbody');
newTbody.appendChild(rows[0].cloneNode(true));
for (var i = 0, length = rowArray.length - 1; i < length; i++) {
newTbody.appendChild(rows[rowArray[i].oldIndex].cloneNode(true));
}
scoresTableRef.replaceChild(newTbody, scoresTableBodyRef);
RefreshTableReferences();
}
window.addEventListener('load', function() {
if (Init()) {
Start();
}
}, false);