Created
August 25, 2017 22:48
-
-
Save killerducky/ae713c910077ac361fe089bdf8ee9af7 to your computer and use it in GitHub Desktop.
OGS Glicko to Rank
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name OGS Glicko to Rank | |
// @namespace http://tampermonkey.net/ | |
// @version 0.1 | |
// @description Convert Glicko ratings to dan/kyu ranks. | |
// @author Andy Olsen | |
// @match https://online-go.com/player/* | |
// @grant none | |
// ==/UserScript== | |
// This script modifies the user profile page and replaces the Glicko ratings with traditional dan/kyu ratings. | |
// | |
// Formulas: | |
// glicko = 850*exp(0.032*r) | |
// r = ln(glicko/850)/0.032 | |
// | |
// Table to convert from r to dan/kyu: | |
// Each entry is the weakest of that rank. So r=30 is the weakest 1d. | |
// r=38= 9d | |
// r=30= 1d | |
// r=29= 1k | |
// r= 0=30k | |
// | |
// This script displays kyus as: strong 1k = -1.0k, weak 1k = -1.9k. | |
// OGS displays this as: strong 1k = -0.0k, weak 1k = -0.9k. | |
// I prefer it this way, same as AGA ratings. But maybe it would be better to | |
// be consistent with OGS. Feedback welcome. | |
$(document).ready(function() { | |
'use strict'; | |
waitForKeyElements ("div.rating", glicko2rank); | |
//waitForKeyElements ("svg.chart", modifyRatingsChart); // Not working yet | |
}); | |
function glicko2rank (jNode) { | |
var e2 = document.getElementsByClassName("rating"); | |
for (var i = 0; i < e2.length; i++) { | |
var ratingElement = e2[i].getElementsByClassName("left")[0]; | |
if (!ratingElement) { continue; } // There is also "rating line" class. Not sure how to exclude it, so just abort when there isn't a "left" class under it. | |
var ratingStr = ratingElement.textContent; | |
if (!/[a-zA-Z]/.test(ratingStr)) { | |
var ratingInt = parseInt(ratingStr, 10); | |
var ratingRangeElement = e2[i].getElementsByClassName("right")[0]; | |
var ratingRangeInt = parseInt(ratingRangeElement.textContent, 10); | |
var r = Math.log(ratingInt/850.0)/0.032; | |
var rRange = Math.log((ratingInt+ratingRangeInt)/850.0)/0.032 - r; | |
var rank; | |
if (r >= 30) { | |
rank = "" + (r-29).toFixed(1) + "d"; | |
} else { | |
rank = "-" + (31-r).toFixed(1) + "k"; | |
} | |
var rankRange = rRange.toFixed(1); | |
//console.log(ratingInt, ratingRangeInt, r, rRange, rank, rankRange); | |
ratingElement.textContent = rank; | |
ratingRangeElement.textContent = rankRange; | |
} | |
} | |
} | |
// Not working yet | |
// Trying to increase the chart height | |
function modifyRatingsChart(jNode) { | |
var ratingsChart = document.getElementsByClassName("RatingsChart"); | |
console.log(ratingsChart); | |
chart = ratingsChart[0].getElementsByClassName("chart")[0]; | |
console.log(chart); | |
console.log(chart.height); | |
chart.height = 600; | |
console.log(chart.height); | |
} | |
// waitForKeyElements Source: | |
// https://gist.github.com/zapu/cb24cce69a180df81e12 | |
/*--- waitForKeyElements(): A utility function, for Greasemonkey scripts, | |
that detects and handles AJAXed content. | |
IMPORTANT: This function requires your script to have loaded jQuery. | |
*/ | |
function waitForKeyElements ( | |
selectorTxt, /* Required: The jQuery selector string that | |
specifies the desired element(s). | |
*/ | |
actionFunction, /* Required: The code to run when elements are | |
found. It is passed a jNode to the matched | |
element. | |
*/ | |
bWaitOnce, /* Optional: If false, will continue to scan for | |
new elements even after the first match is | |
found. | |
*/ | |
iframeSelector /* Optional: If set, identifies the iframe to | |
search. | |
*/ | |
) { | |
var targetNodes, btargetsFound; | |
if (typeof iframeSelector == "undefined") | |
targetNodes = $(selectorTxt); | |
else | |
targetNodes = $(iframeSelector).contents () | |
.find (selectorTxt); | |
if (targetNodes && targetNodes.length > 0) { | |
btargetsFound = true; | |
/*--- Found target node(s). Go through each and act if they | |
are new. | |
*/ | |
targetNodes.each ( function () { | |
var jThis = $(this); | |
var alreadyFound = jThis.data ('alreadyFound') || false; | |
if (!alreadyFound) { | |
//--- Call the payload function. | |
var cancelFound = actionFunction (jThis); | |
if (cancelFound) | |
btargetsFound = false; | |
else | |
jThis.data ('alreadyFound', true); | |
} | |
} ); | |
} | |
else { | |
btargetsFound = false; | |
} | |
//--- Get the timer-control variable for this selector. | |
var controlObj = waitForKeyElements.controlObj || {}; | |
var controlKey = selectorTxt.replace (/[^\w]/g, "_"); | |
var timeControl = controlObj [controlKey]; | |
//--- Now set or clear the timer as appropriate. | |
if (btargetsFound && bWaitOnce && timeControl) { | |
//--- The only condition where we need to clear the timer. | |
clearInterval (timeControl); | |
delete controlObj [controlKey]; | |
} | |
else { | |
//--- Set a timer, if needed. | |
if ( ! timeControl) { | |
timeControl = setInterval ( function () { | |
waitForKeyElements ( selectorTxt, | |
actionFunction, | |
bWaitOnce, | |
iframeSelector | |
); | |
}, | |
300 | |
); | |
controlObj [controlKey] = timeControl; | |
} | |
} | |
waitForKeyElements.controlObj = controlObj; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment