PUBG / PicStats2

// ==UserScript==
// @name        PicStats2
// @namespace   CrazyJeux/Daring-Do
// @author      CrazyJeux/Daring-Do
// @description (Adaptation d'un ancien script anonyme) Calcule les statistiques d'un topic pour savoir qui a le mieux boosté ;)
// @match       *://www.jeuxvideo.com/*
// @version     4
// @grant       none
// @license     MIT
// ==/UserScript==

function scriptContent() {
    var statsGlobalArea, progressArea, curPageNbArea, statsContentsArea, topicURLIdentifier, isNewNickname, positionsAreas = [], allNicknamesStatsArea = [], nicknamesNbAreas = [], totalNbMsgs, allNicknames = [], errorHasBeenNotified = false;
    var orderOfAppearance = "nbOfMsgsReverse";

    try { //Addition of the script icon
        var msgs = document.querySelectorAll(".bloc-message-forum");
        if (msgs.length > 0) {
            var titleElement = document.querySelector("#bloc-title-forum");
            if (titleElement !== null) {
                var pique = document.createElement("img");
                //pique.src = 'http://image.noelshack.com/fichiers/2013/16/1366561498-13z7y2.png';
                var dataURI = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGdBTUEAAK/INwWK6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAAASAAAAEgARslrPgAAAAl2cEFnAAAACgAAAAoATqZ25QAAADdJREFUGNNjYCAXzDzD8B+bOCMuRekmqHKM+ExCVsyIzzpkxYz4FCErZiLWk0zI7oCxsYlR39cAQ7cW36Gy37kAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTMtMDQtMjFUMTg6MjQ6NTgrMDI6MDCXsF0TAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDEzLTA0LTIxVDE4OjI0OjU4KzAyOjAw5u3lrwAAAEp0RVh0c2lnbmF0dXJlADAyYzQxOTk0N2NlZWNhMTExMTZjYWM2OTY4YzcyMjVkYmRhYTMwY2FiZWI5ZDE0MWI0N2I5ZjA0YjIzNjk1YTXJX5qmAAAAAElFTkSuQmCC';
                pique.src = dataURI;
                pique.style.marginLeft = "5px";
                pique.style.cursor = "pointer";
                pique.classList.add('icono_stats');
                pique.setAttribute('title', 'Calculer les statistiques de ce topic');

                //Maybe not up-to-date
                var JVCMasterBtn = document.querySelector(".JVCMaster_BTN_FAVORITESTOPIC");
                if (JVCMasterBtn !== null) {
                    JVCMasterBtn.parentNode.insertBefore(pique, JVCMasterBtn.nextSibling);
                } else {
                    titleElement.appendChild(pique);
                }

                pique.addEventListener('click', function() {
                    startCalc();
                }, true);
            }
        }
    } catch (e) {
        console.log("Call stack:\n" + new Error().stack);
        console.log("Error: "+ e);
    }

    function startCalc() {
        try {
            var titleElement = document.querySelector("#bloc-title-forum");
            var url = window.location.href;
            var topic_title = titleElement.textContent;
            if (typeof url !== "undefined" && url !== null &&
                typeof topic_title !== "undefined" && topic_title !== null) {
                sessionStorage.removeItem("url_stats");
                sessionStorage.removeItem("title_stats");
                statsGlobalArea = document.querySelector('.layout__row');
                if (statsGlobalArea !== null) {
                    statsGlobalArea.style.width = "50%";
                    statsGlobalArea.style.margin = "auto";
                    statsGlobalArea.style.fontSize = "150%";
                    statsGlobalArea.style.textAlign = "center";
                    document.title = "PicStats : calcul des statistiques du topic en cours...";
                    var urlArray = url.split('-');
                    var p1 = urlArray.shift();
                    var p2 = urlArray.shift();
                    var p3 = urlArray.shift();
                    topicURLIdentifier = p1 + "-" + p2 + "-" + p3;
                    var topic_title_in_url = "picstats";
                    statsGlobalArea.innerHTML = "<br /><br /><a style='color: #006BD7;' target='_blank' href='" + topicURLIdentifier + "-1-0-1-0-" + topic_title_in_url + ".htm'>Sujet : « " + topic_title + ' »</a><br />';
                    statsGlobalArea.innerHTML += "<div id='mainInfo' style='color: orange;'>Le calcul des statistiques est en cours...</div>";

                    progressArea = document.createElement("div");
                    progressArea.id = "progressArea";
                    progressArea.innerHTML = "<span>Initialisation...</span>";
                    statsGlobalArea.appendChild(progressArea);

                    statsContentsArea = document.createElement("div");
                    statsContentsArea.style.fontSize = "75%";
                    statsContentsArea.id = "statsContentsArea";
                    statsGlobalArea.appendChild(statsContentsArea);

                    compute(1, {});
                }
            }
        } catch (e) {
            console.log("Call stack:\n" + new Error().stack);
            console.log("Error: "+ e);
        }
    }

    function compute(page) {
        function onPageLoad() {
            if (xmlhttp.readyState === 4) {
                try {
                    var responsePage = parseInt(xmlhttp.responseURL.split("-")[3], 10);
                    if (responsePage === page) {
                        //console.log("Page #" + page + " chargée.");

                        var resultDiv = document.createElement('div');
                        resultDiv.innerHTML = xmlhttp.responseText;
                        resultDiv.style.display = "none";
                        document.body.appendChild(resultDiv);

                        var lastPageNb = page;
                        //console.log("resultDiv.innerHTML:\n" + resultDiv.innerHTML);
                        var pagiAfter = resultDiv.querySelector(".pagi-after");
                        if (pagiAfter !== null) {
                            //console.log("Before pagiAfter.outerHTML:\n" + pagiAfter.outerHTML);
                            convertJvCareToRealLink(pagiAfter);
                            //console.log("After pagiAfter.outerHTML:\n" + pagiAfter.outerHTML);
                            var lastLink = pagiAfter.querySelector("a.pagi-fin-actif");
                            if (lastLink !== null) {
                                lastPageNb = parseInt(lastLink.href.split("-")[3], 10);
                            }
                        }

                        if (page === 1) {
                            progressArea.innerHTML = "  Analyse de la page n°<span id='curPageNbArea'>" + page + "/" + lastPageNb + "</span>...<br /><br /><img src='http://image.noelshack.com/fichiers/2013/26/1372609034-loading.gif'><br /><br />";
                            curPageNbArea = progressArea.querySelector('#curPageNbArea');
                            totalNbMsgs = 0;
                        } else {
                            curPageNbArea.innerHTML = page + "/" + lastPageNb;
                        }

                        var nicknameStatsArea = null;
                        var authorsNicknames = resultDiv.querySelectorAll(".bloc-pseudo-msg");
                        var nickname;
                        for (var i=0; i<authorsNicknames.length; i++) {
                            //console.log("##################################################");
                            //console.log("Message #" + i + "/" + authorsNicknames.length + "...");

                            isNewNickname = false;

                            nickname = authorsNicknames[i].textContent.trim();
                            //console.log("Nickname: " + nickname);

                            var curMsgDateArea = authorsNicknames[i].parentNode.querySelector(".bloc-date-msg");
                            var curMsgDate = curMsgDateArea.textContent.trim();

                            convertJvCareToRealLink(curMsgDateArea);

                            var curMsgLinkArea = curMsgDateArea.querySelector("a");
                            var curMsgLink = "";
                            if (curMsgLinkArea !== null) {
                                curMsgLink = curMsgLinkArea.href;
                            } else {
                                var dataId = curMsgDateArea.parentNode.parentNode.parentNode.parentNode.getAttribute("data-id");
                                if (dataId !== null && dataId !== "") {
                                    curMsgLink = "http://www.jeuxvideo.com/picstats/forums/message/" + dataId;
                                }
                            }

                            if (hasOwnPropertyCaseInsensitive(allNicknames, nickname)) {
                                //console.log("Already seen");
                                allNicknames[nickname].nbMsgs++;
                                allNicknames[nickname].lastMsgDate = curMsgDate;
                                allNicknames[nickname].lastMsgLink = curMsgLink;

                                var nbMsgs = 0;
                                var nbDays = 1;
                                var ratio2 = 0;
                                var oldNbMsgs = -1;
                                var oldNbDays = -1;
                                var oldRatio2 = -1;
                                nicknameStatsArea = statsContentsArea.querySelector(".nicknameStatsArea[data-picstats-nickname='" + nickname.toLowerCase() + "']");
                                if (nicknameStatsArea !== null) {
                                    var nicknameStatsNbMsgsArea = nicknameStatsArea.querySelector(".nbmsgs");
                                    if (nicknameStatsNbMsgsArea !== null) {
                                        nbMsgs = parseInt(nicknameStatsNbMsgsArea.textContent.trim(), 10);
                                        oldNbMsgs = nbMsgs;
                                        nicknameStatsNbMsgsArea.innerHTML = (nbMsgs + 1) + " messages";
                                    }

                                    var nicknameStatsFirstMsgArea = nicknameStatsArea.querySelector(".firstmsginfo");
                                    var firstMsgDate;
                                    var firstMsgDateTime;
                                    if (nicknameStatsFirstMsgArea !== null) {
                                        firstMsgDate = nicknameStatsFirstMsgArea.textContent;
                                        //console.log("firstMsgDate: " + firstMsgDate);
                                        firstMsgDateTime = convertToTrueDate(firstMsgDate);
                                        //console.log("firstMsgDateTime: " + firstMsgDateTime);
                                        var nicknameStatsLastMsgArea = nicknameStatsArea.querySelector(".lastmsginfo");
                                        if (nicknameStatsLastMsgArea !== null) {
                                            lastMsgDate = nicknameStatsLastMsgArea.textContent;
                                            //console.log("lastMsgDate: " + lastMsgDate);
                                            var lastMsgDateTime = convertToTrueDate(lastMsgDate);
                                            //console.log("lastMsgDateTime: " + lastMsgDateTime);

                                            oldNbDays = dateDiffInDays(firstMsgDateTime, lastMsgDateTime);
                                            //Don't say that someone was here for 0 days... Always at least 1 day.
                                            if (oldNbDays === 0) {
                                                oldNbDays = 1;
                                            }
                                        }
                                    }

                                    var nicknameStatsLastMsgArea = nicknameStatsArea.querySelector(".lastmsg");
                                    if (nicknameStatsLastMsgArea !== null) {
                                        //nicknameStatsLastMsgArea.innerHTML = curMsgDate;
                                        nicknameStatsLastMsgArea.innerHTML = curMsgLink;
                                        if (curMsgLink !== "" && nicknameStatsLastMsgArea.tagName === "A") {
                                            nicknameStatsLastMsgArea.href = curMsgLink;
                                        }
                                    }

                                    var nicknameStatsLastMsgInfoArea = nicknameStatsArea.querySelector(".lastmsginfo");
                                    if (nicknameStatsLastMsgInfoArea !== null) {
                                        //nicknameStatsLastMsgInfoArea.innerHTML = curMsgLink;
                                        nicknameStatsLastMsgInfoArea.innerHTML = curMsgDate;
                                    }

                                    //console.log("curMsgDate: " + curMsgDate);
                                    var lastMsgDateTime = convertToTrueDate(curMsgDate);
                                    //console.log("firstMsgDateTime: " + firstMsgDateTime + "; lastMsgDateTime: " + lastMsgDateTime);

                                    var nicknameDurationArea = nicknameStatsArea.querySelector(".duration");
                                    if (nicknameDurationArea !== null) {
                                        var nbDays = dateDiffInDays(firstMsgDateTime, lastMsgDateTime);
                                        //Don't say that someone was here for 0 days... Always at least 1 day.
                                        if (nbDays === 0) {
                                            nbDays = 1;
                                        }
                                        //console.log("Nb of days for " + nickname + ": old value: " + oldNbDays + ", new value: " + nbDays);
                                        if (nbDays !== oldNbDays) {
                                            nicknameDurationArea.innerHTML = nbDays + " jour" + (nbDays > 1 ? "s" : "");
                                            //console.log("Updated nb of days for " + nickname + ": old value: " + oldNbDays + ", new value: " + nbDays);
                                        }
                                    }

                                    var nicknameStatsRatioArea = nicknameStatsArea.querySelector(".ratio");
                                    if (nicknameStatsRatioArea !== null) {
                                        var txt = nicknameStatsRatioArea.innerHTML.trim();
                                        txt = txt.substring(0, txt.indexOf(" "));
                                        oldRatio2 = parseFloat(txt);
                                        //console.log("oldRatio2: " + oldRatio2);

                                        var ratio = (nbMsgs + 1) / nbDays;
                                        //console.log("ratio: " + ratio);
                                        //ratio2 = ratio.toFixed(1 - Math.floor(Math.log(ratio)/Math.log(10)));
                                        ratio2 = ratio.toFixed(2);
                                        //console.log("ratio2 after toFixed: " + ratio2);
                                        //ratio2 = ratio2.toString();
                                        //console.log("ratio2 after toString: " + ratio2);
                                        ratio2 = parseFloat(ratio2);
                                        //console.log("ratio2 after parseFloat: " + ratio2);
                                        var ratioMsg = ratio2 + " message" + (ratio2 > 1 ? "s" : "") + " par jour.";
                                        nicknameStatsRatioArea.innerHTML = ratioMsg;
                                    }
                                }

                                //console.log("orderOfAppearance: '" + orderOfAppearance + "'");
                                if (((orderOfAppearance === "nbOfMsgs" || orderOfAppearance === "nbOfMsgsReverse")/* && (nbMsgs !== oldNbMsgs)*/) ||
                                    ((orderOfAppearance === "nbDays" || orderOfAppearance === "nbDaysReverse") && (nbDays !== oldNbDays)) ||
                                    ((orderOfAppearance === "ratio" || orderOfAppearance === "ratioReverse") && (ratio2 !== oldRatio2))) {
                                    var comparisonFunction, func, areas = document.querySelectorAll(".nicknameStatsArea");

                                    var getAreaNick = function(area) {
                                        //console.log("area html:\n" + area.outerHTML);
                                        return area.getAttribute("data-picstats-nickname").trim();
                                    };

                                    var getAreaNbMsgs = function(area) {
                                        //console.log("area html:\n" + area.outerHTML);
                                        var txt = area.querySelector(".nbmsgs").textContent.trim();
                                        var nb = txt.match(/\d/g);
                                        nb = nb.join("");
                                        //console.log("nb: " + nb);
                                        return parseInt(nb, 10);
                                    };

                                    var getAreaNbDays = function(area) {
                                        //console.log("area html:\n" + area.outerHTML);
                                        var txt = area.querySelector(".duration").textContent.trim();
                                        var nb = txt.match(/\d/g);
                                        nb = nb.join("");
                                        //console.log("nb: " + nb);
                                        return parseInt(nb, 10);
                                    };

                                    var getAreaRatio = function(area) {
                                        //console.log("area html:\n" + area.outerHTML);
                                        var txt = area.querySelector(".ratio").textContent.trim();
                                        txt = txt.substring(0, txt.indexOf(" "));
                                        nb = parseFloat(txt);
                                        //console.log("nb: " + nb);
                                        return nb;
                                    };

                                    if (orderOfAppearance === "nbOfMsgs" || orderOfAppearance === "nbOfMsgsReverse") {
                                        func = getAreaNbMsgs;
                                    } else {
                                        if (orderOfAppearance === "nbDays" || orderOfAppearance === "nbDaysReverse") {
                                            func = getAreaNbDays;
                                        } else {
                                            func = getAreaRatio;
                                        }
                                    }

                                    if (orderOfAppearance === "nbOfMsgs" || orderOfAppearance === "nbDays" || orderOfAppearance === "ratio") {
                                        comparisonFunction = function(a, b) {
                                            return a <= b;
                                        };
                                    } else {
                                        comparisonFunction = function(a, b) {
                                            return a >= b;
                                        };
                                    }

                                    var newValue;
                                    if (orderOfAppearance === "nbOfMsgs" || orderOfAppearance === "nbOfMsgsReverse") {
                                        newValue = (nbMsgs + 1);
                                    } else {
                                        if (orderOfAppearance === "nbDays" || orderOfAppearance === "nbDaysReverse") {
                                            newValue = nbDays;
                                        } else {
                                            newValue = ratio2;
                                        }
                                    }
                                    //console.log("Already seen nick: " + nickname + "; new value now: " + newValue);
                                    //alert("Already seen nick: " + nickname + "; new value nows: " + newValue);
                                    //console.log("areas.length: " + areas.length);
                                    var curAreaValue;
                                    var done = false;
                                    var index = getElementIndex(nicknameStatsArea);
                                    for (var j=0; j<areas.length; j++) {
                                        var curNick = getAreaNick(areas[j]);
                                        if (curNick === nickname.toLowerCase()) {
                                            continue;
                                        }
                                        //console.log("Before func #" + j + "/" + areas.length);
                                        //alert("Before func #" + j + "/" + areas.length);
                                        curAreaValue = func(areas[j]);
                                        //console.log(curNick + " value: " + curAreaValue);
                                        //alert(curNick + " value: " + curAreaValue);
                                        if (comparisonFunction(newValue, curAreaValue)) {
                                            var newPosition = j - 1;
                                            if (index !== newPosition) {
                                                //console.log("Going to move " + nickname + " (old place: " + index + ") to the correct position: place #" + j + "...");
                                                areas[j].parentNode.insertBefore(nicknameStatsArea, areas[j]);
                                                //console.log("Moved " + nickname + " (old place: " + index + ", value: " + newValue + ") to the correct position: place #" + j + " (before value " + curAreaValue + ")");
                                                //alert("Moved " + nickname + " (old place: " + index + ", value: " + newValue + ") to the correct position: place #" + j + " (before value " + curAreaValue + ")");
                                                done = true;
                                                break;
                                            } else {
                                                done = true;
                                                break;
                                            }
                                        }
                                    }
                                    if (!done) {
                                        areas[0].parentNode.appendChild(nicknameStatsArea);
                                        //console.log("Moved " + nickname + " (old place: " + index + ", value: " + newValue + ") to the last position: place #" + areas.length + " (after value " + curAreaValue + ")");
                                    }

                                    positionsAreas.push(nicknameStatsArea.querySelector(".position"));
                                    //console.log("Added areas to arrays. Size: " + positionsAreas.length);
                                }
                            } else {
                                //console.log("Not already seen");

                                isNewNickname = true;

                                allNicknames[nickname] = {
                                    "nbMsgs": 1,
                                    "firstMsgDate": curMsgDate,
                                    "firstMsgLink": curMsgLink,
                                    "lastMsgDate": curMsgDate,
                                    "lastMsgLink": curMsgLink
                                };

                                nicknameStatsArea = document.createElement("p");
                                nicknameStatsArea.classList.add("nicknameStatsArea");
                                nicknameStatsArea.setAttribute("data-picstats-nickname", nickname.toLowerCase());
                                // ⇒
                                nicknameStatsArea.innerHTML = "<span class='position'></span><span id='nick'>" + nickname + "</span> : <span class='nbmsgs'>1 message</span> en <span class='duration'>1 jour</span>, soit " +
                                    "<span class='ratio'>1 message par jour.</span><br />" +
                                    //(curMsgLink !== "" ? "Début : <a style='color: #006BD7;' target='_blank' class='firstmsg' href='" + curMsgLink + "'>" + curMsgDate + "</a> " + curMsgLink + "<br />"
                                    (curMsgLink !== "" ? "Début : <a style='color: #006BD7;' target='_blank' class='firstmsg' href='" + curMsgLink + "'>" + curMsgLink + "</a> (<span class='firstmsginfo'>" + curMsgDate + "</span>)<br />"
                                     : "Début : <span class='firstsmg'>" + curMsgDate + "</span> (<span class='firstmsginfo'>" + curMsgDate + "</span>)<br />") +
                                    //(curMsgLink !== "" ? "Fin : <a style='color: #006BD7;' target='_blank' class='lastmsg' href='" + curMsgLink + "'>" + curMsgDate + "</a> <span class='lastmsginfo'>" + curMsgLink + "</span>"
                                    (curMsgLink !== "" ? "Fin : <a style='color: #006BD7;' target='_blank' class='lastmsg' href='" + curMsgLink + "'>" + curMsgLink + "</a> (<span class='lastmsginfo'>" + curMsgDate + "</span>)"
                                     : "Fin : <span class='lastmsg'>" + curMsgDate + "</span> (<span class='lastmsginfo' style='display: none;'>" + curMsgDate + "</span>)");
                            }

                            if (isNewNickname) {
                                switch (orderOfAppearance) {
                                    case "chrono":
                                        statsContentsArea.appendChild(nicknameStatsArea);
                                        break;
                                    case "chronoReverse":
                                        statsContentsArea.insertBefore(nicknameStatsArea, statsContentsArea.firstChild);
                                        break;
                                    case "alphabetical":
                                    case "alphabeticalReverse":
                                    case "nbOfMsgs":
                                    case "nbOfMsgsReverse":
                                    case "nbDays":
                                    case "nbDaysReverse":
                                    case "ratio":
                                    case "ratioReverse":
                                        var getAreaValue, comparisonFunction, areas = document.querySelectorAll(".nicknameStatsArea");

                                        var getAreaNick = function(area) {
                                            //console.log("area html:\n" + area.outerHTML);
                                            return area.getAttribute("data-picstats-nickname").trim();
                                        };

                                        var getAreaNbMsgs = function(area) {
                                            //console.log("area html:\n" + area.outerHTML);
                                            var txt = area.querySelector(".nbmsgs").textContent.trim();
                                            var nb = txt.match(/\d/g);
                                            nb = nb.join("");
                                            //console.log("nb: " + nb);
                                            return parseInt(nb, 10);
                                        };

                                        var getAreaNbDays = function(area) {
                                            //console.log("area html:\n" + area.outerHTML);
                                            var txt = area.querySelector(".duration").textContent.trim();
                                            var nb = txt.match(/\d/g);
                                            nb = nb.join("");
                                            //console.log("nb: " + nb);
                                            return parseInt(nb, 10);
                                        };

                                        var getAreaRatio = function(area) {
                                            //console.log("area html:\n" + area.outerHTML);
                                            var txt = area.querySelector(".ratio").textContent.trim();
                                            txt = txt.substring(0, txt.indexOf(" "));
                                            nb = parseFloat(txt);
                                            //console.log("nb: " + nb);
                                            return nb;
                                        };

                                        if (orderOfAppearance === "alphabetical" ||
                                            orderOfAppearance === "alphabeticalReverse") {
                                            getAreaValue = getAreaNick;
                                        } else {
                                            if (orderOfAppearance === "nbOfMsgs" ||
                                                orderOfAppearance === "nbOfMsgsReverse") {
                                                getAreaValue = getAreaNbMsgs;
                                            } else {
                                                if (orderOfAppearance === "nbOfMsgs" ||
                                                    orderOfAppearance === "nbOfMsgsReverse") {
                                                    getAreaValue = getAreaNbDays;
                                                } else {
                                                    getAreaValue = getAreaRatio;
                                                }
                                            }
                                        }

                                        if (orderOfAppearance === "alphabetical" ||
                                            orderOfAppearance === "nbOfMsgsReverse" ||
                                            orderOfAppearance === "nbDaysReverse" ||
                                            orderOfAppearance === "ratioReverse") {
                                            comparisonFunction = function(a, b) {
                                                return a >= b;
                                            };
                                        } else {
                                            comparisonFunction = function(a, b) {
                                                return a <= b;
                                            };
                                        }

                                        if (positionsAreas.length === 0) {
                                            statsContentsArea.appendChild(nicknameStatsArea);
                                            //console.log("Added " + nickname + " to statsContentsArea");
                                        } else {
                                            //console.log("Before getNewValue");
                                            var newValue = getAreaValue(nicknameStatsArea);
                                            //console.log(nickname + " new value: " + newValue);
                                            //console.log("areas.length: " + areas.length);
                                            var done = false;
                                            var curAreaValue;
                                            for (var k=0; k<areas.length; k++) {
                                                //console.log("Before getAreaValue #" + k + "/" + areas.length);
                                                curAreaValue = getAreaValue(areas[k]);
                                                //console.log("Loop #" + k + "/" + areas.length + ": " + getAreaNick(areas[k]) + " value: " + curAreaValue);
                                                if (comparisonFunction(newValue, curAreaValue)) {
                                                    var newPosition = k - 1;
                                                    areas[k].parentNode.insertBefore(nicknameStatsArea, areas[k]);
                                                    //console.log("Added " + nickname + " to the correct position: place #" + k + " (before value " + curAreaValue + ")");
                                                    done = true;
                                                    break;
                                                }
                                            }
                                            if (!done) {
                                                areas[0].parentNode.appendChild(nicknameStatsArea);
                                                //console.log("Added " + nickname + " (value: " + newValue + ") to the last position: place #" + areas.length + " (after value " + curAreaValue + ")");
                                            }
                                        }
                                        break;
                                    default:
                                        statsContentsArea.appendChild(nicknameStatsArea);
                                        if (!errorHasBeenNotified) {
                                            errorHasBeenNotified = true;
                                            alert("Erreur : le script PicStats a une valeur incorrecte pour sa variable orderOfAppearance : '" + orderOfAppearance + "'");
                                        }
                                }

                                positionsAreas.push(nicknameStatsArea.querySelector(".position"));
                                //console.log("Added areas to arrays. Size: " + positionsAreas.length);
                            }

                            totalNbMsgs++;
                            //console.log(totalNbMsgs + " message(s) analysés en tout...");
                        }

                        resultDiv.remove();

                        setTimeout(function() {
                            try {
                                //alert("Before next page");
                                compute(page + 1);
                            } catch (e) {
                                //console.log("Call stack:\n" + new Error().stack);
                                //console.log("Error: "+ e);
                            }
                        }, 20);
                    } else {
                        //console.log("Fin du calcul des stats");

                        for (var l=0; l<positionsAreas.length; l++) {
                            var index = getElementIndex(positionsAreas[l].parentNode);
                            positionsAreas[l].innerHTML = (index + 1) + ". ";
                        }

                        /*
                var listOrder = [];
                for (var x in allNicknames) {
                    if (allNicknames.hasOwnProperty(x)) {
                        listOrder.push([allNicknames[x], x]);
                    }
                }

                listOrder.sort(function (a, b) {
                    if (parseInt(a[0], 10) > parseInt(b[0], 10)) {
                        return -1;
                    } else {
                        if (parseInt(a[0], 10) < parseInt(b[0], 10)) {
                            return 1;
                        } else { //Same number of messages, so compare by nickname
                            alpha = [a[1], b[1]].sort();
                            if (a[1] == alpha[0]) {
                                return -1;
                            } else {
                                return 1;
                            }
                        }
                    }
                });
                //console.log("final listOrder: "+JSON.stringify(listOrder, null, 4));
                */

                        var allNicknamesArray = [];
                        for (var x in allNicknames) {
                            if (allNicknames.hasOwnProperty(x)) {
                                allNicknamesArray.push([x]);
                            }
                        }

                        var shortGlobalStatsArea = document.createElement("p");
                        shortGlobalStatsArea.id = "shortGlobalStatsArea";
                        shortGlobalStatsArea.innerHTML = "<br />Nombre de pseudos : " + allNicknamesArray.length + "<br />Nombre de messages : " + totalNbMsgs;
                        statsContentsArea.appendChild(shortGlobalStatsArea);

                        document.title = "PicStats : /!\\ TERMINÉ /!\\";
                        //console.log("final allNicknames: "+JSON.stringify(allNicknames, null, 4));
                        var mainInfo = document.querySelector("#mainInfo");
                        mainInfo.style.color = "green";
                        progressArea = document.querySelector("#progressArea");
                        if (progressArea !== null) {
                            progressArea.remove();
                        }
                        mainInfo.innerHTML = "Le calcul des statistiques est terminé !" +
                            "<br /><span>" + parseInt(page - 1) + " page" + ((page <= 2) ? " a été analysée" : "s ont été analysées") + ".</span>" +
                            "<br /><br /><input type='button' style='color: black;' value='Tout sélectionner' id='copyBtn'><br /><br />";

                        mainInfo.querySelector('#copyBtn').addEventListener("click", selectData, false);
                    }
                } catch (e) {
                    //console.log("Call stack:\n" + new Error().stack);
                    //console.log("Error: "+ e);
                }
            }
        }

        var link = topicURLIdentifier + "-" + page + "-0-1-0-picstats.htm";

        var xmlhttp = new XMLHttpRequest();
        xmlhttp.onreadystatechange = onPageLoad;
        xmlhttp.open("GET", link, true);
        xmlhttp.send();
        //console.log("Loading "+link+"...");
    }

    var _MS_PER_DAY = 1000 * 60 * 60 * 24;

    function convertJvCareToRealLink(element) {
        function jvCake(link) {
            var _base16 = "0A12B34C56D78E9F";
            var str, rurl = "";
            var ch, cl, j, p, d = 0;
            p = link.indexOf(' ');
            d = link.indexOf(' ', p + 1);
            if (d === -1) {
                d = link.length;
            }
            if (p > 0) {
                str = link.substr(p + 1, d - p - 1);
                for (j = 0; j < str.length; j += 2) {
                    ch = _base16.indexOf(str.charAt(j));
                    cl = _base16.indexOf(str.charAt(j + 1));
                    rurl += String.fromCharCode((ch * 16) + cl);
                }
            }
            return rurl;
        }

        var jvcares = element.querySelectorAll(".JvCare");
        //console.log(jvcares.length + " JvCare elements total");
        for (var m=0; m<jvcares.length; m++) {
            //console.log(i + "/" + jvcares.length + " JvCare element");
            var url2 = jvCake(jvcares[m].getAttribute("class"));
            var classes = jvcares[m].className.split(" ");
            var classToAdd = "";
            for (var n=0; n<classes.length; n++) {
                if (classes[n].indexOf("pagi-") === 0) {
                    classToAdd = classes[n];
                    break;
                }
            }
            //console.log("url2: '" + url2 + "'");
            var newLink = document.createElement("a");
            newLink.href = url2;
            newLink.target = "_blank";
            newLink.classList.add("xXx");
            newLink.classList.add("lien-jv");
            if (classToAdd !== "") {
                newLink.classList.add(classToAdd);
            }
            newLink.innerHTML = jvcares[m].innerHTML;
            jvcares[m].parentNode.replaceChild(newLink, jvcares[m]);
            //console.log("Replace done");
        }
    }

    // a and b are javascript Date objects
    function dateDiffInDays(a, b) {
        // Discard the time and time-zone information.
        var utc1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());
        var utc2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());

        return Math.floor((utc2 - utc1) / _MS_PER_DAY);
    }

    /*
    * Converts a JVC date string into a JS date.
	* @param {String} dateParam: a JVC date string. Example: "01 janvier 2015 à 00:00:00".
	* @returns {Date}: the real date.
	*/
    function convertToTrueDate(dateParam) {
        /*
		* Gets the index of a French month.
		* @param {String} m: the month.
		* @returns {Number}: the index.
		*/
        function getMonthNumber(m) {
            var frenchMonths = ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"];
            return frenchMonths.indexOf(m.toLowerCase()) + 1;
        }

        dateParam = dateParam.replace(/\n/g, '');
        var useRegex = false; //indexOf is a little faster
        //JJ mois AAAA à HH:MM:SS
        var trueDate;
        if (useRegex) {
            var reg = /(.{2}) (.+) (.{4}) à (.{2}):(.{2}):(.{2})/;
            var t = dateParam.match(reg);
            if (t === null) {
                alert("Erreur fonction convertToTrueDate : dateParam='" + dateParam + "'");
            }
            trueDate = new Date(t[3], (getMonthNumber(t[2]) - 1), t[1], t[4], t[5], t[6]);
        } else {
            //Day
            var day = dateParam.substring(0, 2);
            //Month
            dateParam = dateParam.substring(3);
            var monthEnd = dateParam.indexOf(" ");
            var month = getMonthNumber(dateParam.substring(0, monthEnd));
            //Year
            dateParam = dateParam.substring(monthEnd + 1);
            var yearEnd = dateParam.indexOf(" ");
            var year = dateParam.substring(0, yearEnd);
            //Hour
            dateParam = dateParam.substring(yearEnd + 3);
            var hourEnd = dateParam.indexOf(":");
            var hour = dateParam.substring(0, hourEnd);
            //Minute
            dateParam = dateParam.substring(hourEnd + 1);
            var minuteEnd = dateParam.indexOf(":");
            var minute = dateParam.substring(0, minuteEnd);
            //Second
            dateParam = dateParam.substring(minuteEnd + 1);
            var second = dateParam.substring(0, 2);
            //log("'" + dateParam + "' becomes (d/m/y à h:m:s): " + day + "/" + month + "/" + year + " à " + hour + ":" + minute + ":" + second);
            trueDate = new Date(year, month - 1, day, hour, minute, second);
            //log("trueDate is " + trueDate);
        }

        return trueDate;
    }

    function getElementIndex(node) {
        var index = 0;
        while ( (node = node.previousElementSibling) ) {
            index++;
        }
        return index;
    }

    function selectData() {
        function selectText(element) {
            /*
            var range, selection;
            selection = window.getSelection();
            range = document.createRange();
            range.selectNodeContents(element);
            selection.removeAllRanges();
            selection.addRange(range);
            */

            if (document.selection) {
                var range = document.body.createTextRange();
                range.moveToElementText(element);
                range.select();
            } else if (window.getSelection) {
                var range = document.createRange();
                range.selectNode(element);
                window.getSelection().addRange(range);
            }
        }

        selectText(statsContentsArea);
    }

    function hasOwnPropertyCaseInsensitive(obj, prop) {
        return ((Object.keys(obj).filter(function (v) {
            return v.toLowerCase() === prop.toLowerCase();
        }).length) > 0);
    }
}

setTimeout(function() {
    var script = document.createElement("script");
    script.id = "picstats";
    script.type = "text/javascript";
    script.onload = function () {
        //console.log("PicStats loaded in " + (performance.now()) + " ms");
    };
    script.onerror = function () {
        alert("PicStats n'a pas pu être chargé...");
    };
    script.innerHTML = "(function(){ " + scriptContent.toString() + " scriptContent();})();";
    //console.log("Appending script...");
    document.head.appendChild(script);
    //console.log("PicStats call done.");
}, 1);