pp for osu score pages

shows pp data from osustats.ppy.sh on osu score pages.

目前為 2014-12-13 提交的版本,檢視 最新版本

// ==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);