MineGeekYT / CF Team Interface

// ==UserScript==
// @name         CF Team Interface
// @namespace    https://github.com/PikMike
// @version      0.4
// @description  More team info
// @author       PikMike
// @include      *codeforces.*/team/*
// @grant        none
// @license      MIT
// ==/UserScript==

var lang = getCookie("nocturne.language");

var plurDict = {"country": {"en": "Countries", "ru": "Страны"},
                "city": {"en": "Cities", "ru": "Города"},
                "org": {"en": "Organizations", "ru": "Организации"}};

var singDict = {"rating": {"en": "Rating", "ru": "Рейтинг"},
                "country": {"en": "Country", "ru": "Страна"},
                "city": {"en": "City", "ru": "Город"},
                "org": {"en": "Organization", "ru": "Организация"}};

var note = {"ru" : "Рейтинг участников вне рейтинга устанавливается равным 1500, поэтому суммарный рейтинг неточный.",
            "en" : "Unrated users rating is set to 1500, so there is inaccuracy in total rating."};

var xhr = [];
var countries = [], cities = [], orgs = [];
var teamInfo = document.getElementsByClassName("info")[0];
var list = teamInfo.children[teamInfo.children.length - 1];
var cntProcessed = 0;
var ratings = [];
var inaccRating = false;

var rating = document.createElement("LI");

list.insertBefore(rating, list.children[0]);
rating.innerHTML = singDict["rating"][lang] + ": ";
var ratingValue = document.createElement("SPAN");
ratingValue.style = "font-weight:bold;";
rating.appendChild(ratingValue);

var delimiter = document.createElement("HR");
var countryList = document.createElement("LI");
var cityList = document.createElement("LI");
var orgList = document.createElement("LI");

list.appendChild(delimiter);
list.appendChild(countryList);
list.appendChild(cityList);
list.appendChild(orgList);

function getWinProbability(ra, rb){
    return 1.0 / (1.0 + Math.pow(10.0, (rb - ra) / 400.0));
}

function aggregateRatings(teamRatings){

    let left = 1.0;
    let right = 10000.0;

    for (let tt = 0; tt < 100; tt++){
        let r = (left + right) / 2.0;

        let rWinsProbability = 1.0;
        for(var i = 0; i < teamRatings.length; i++)
            rWinsProbability *= getWinProbability(r, teamRatings[i]);

        rating = Math.log10(1 / (rWinsProbability) - 1) * 400 + r;

        if (rating > r)
            left = r;
        else
            right = r;
    }

    return (left + right) / 2.0;
}


var helperFunc = function(i){
    return function(){
        if(xhr[i].readyState === 4){
            ProcessResponseForItem(i);
        }
    };
};

function ProcessResponseForItem(i){
    if(xhr[i].status === 200){
        var resp = xhr[i].response;
        var info = resp.getElementsByClassName("main-info")[0];
        if (info.children[0].children[0].getAttribute('class') !== "user-black")
            ratings.push(parseInt(resp.getElementsByClassName("info")[0].children[resp.getElementsByClassName("info")[0].children.length - 1].children[0].children[1].innerHTML));
        else{
            ratings.push(1500);
            inaccRating = true;
        }
        console.log("Info about user " + resp.getElementsByClassName("main-info")[0].children[1].children[0].innerHTML + " loaded");
        var country = null;
        var city = null;
        var org = null;
        if (info.children.length > 2){
            var data = info.children[2].children;
            for (var j = 0; j < data.length; j++)
                for (var k = 0; k < data[j].children.length; k++){
                    if (data[j].children[k].tagName != "A")
                        continue;
                    if (data[j].children[k].href.includes("city"))
                        city = data[j].children[k].innerHTML;
                    else if (data[j].children[k].href.includes("country"))
                        country = data[j].children[k].innerHTML;
                    else if (data[j].children[k].href.includes("organization"))
                        org = data[j].children[k].innerHTML;
                }
        }
        if (country !== null && !countries.includes(country)){
            countries.push(country);
            countryList.innerHTML = (countries.length === 1 ? singDict["country"][lang] : plurDict["country"][lang]) + ": " + countries.join(", ");
        }
        if (city !== null && !cities.includes(city)){
            cities.push(city);
            cityList.innerHTML = (cities.length === 1 ? singDict["city"][lang] : plurDict["city"][lang]) + ": " + cities.join(", ");
        }
        if (org !== null && !orgs.includes(org)){
            orgs.push(org);
            orgList.innerHTML = (orgs.length === 1 ? singDict["org"][lang] : plurDict["org"][lang]) + ": " + orgs.join("; ");
        }
        cntProcessed++;
        if (cntProcessed == users.length){
            var ratingNum = Math.round(aggregateRatings(ratings));
            ratingValue.className = determClass(ratingNum);

            ratingValue.innerHTML = "";

            if (ratingValue.className == "user-legendary")
                ratingValue.innerHTML += '<span class="legendary-user-first-letter">' + ratingNum.toString()[0] + '</span>' + ratingNum.toString().slice(1);
            else
                ratingValue.innerHTML += ratingNum.toString();

            if (inaccRating)
                ratingValue.innerHTML += "<sup><font title='" + note[lang] + "' color='grey'>?</font></sup>";
        }
    }
}

function determClass(value){
    if (value === null)
        return "";
    else if (value < 1200)
        return "user-gray";
    else if (value < 1400)
        return "user-green";
    else if (value < 1600)
        return "user-cyan";
    else if (value < 1900)
        return "user-blue";
    else if (value < 2100)
        return "user-violet";
    else if (value < 2400)
        return "user-orange";
    else if (value < 3000)
        return "user-red";
    else
        return "user-legendary";
}

function getCookie(name) {
    var value = "; " + document.cookie;
    var parts = value.split("; " + name + "=");
    if (parts.length == 2) return parts.pop().split(";").shift();
    else return "en";
}


var members = document.getElementsByClassName("members")[0];
var users = members.getElementsByClassName("avatar");

for (var i = 0; i < users.length; i++){
    var url = users[i].children[0].href;
    xhr.push(new XMLHttpRequest());
    xhr[i].open('GET', url, true);
    xhr[i].responseType = "document";
    xhr[i].onreadystatechange = helperFunc(i);
    xhr[i].send(null);
}