Tor's Backloggery enhancements

Adds pie charts and other enhancements to backloggery.com

当前为 2023-02-02 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Tor's Backloggery enhancements
// @version      2.2.1
// @namespace    werhi23uhkjwesda
// @description  Adds pie charts and other enhancements to backloggery.com
// @author       Tor
// @copyright    2010+, Tor
// @license      MIT License; http://www.opensource.org/licenses/mit-license.php
// @match        https://backloggery.com/*
// @match        https://www.backloggery.com/*
// @icon         https://raw.githubusercontent.com/torlye/Backloggery-enhancements/master/icon128.png
// @grant        none
// @require      https://code.jquery.com/jquery-3.4.1.min.js
// ==/UserScript==
"use strict";
//Variables for gathering statistics
const downloadServiceStatistics = {};
const yearStatistics = {};
let downloadServiceTotalCount = 0;
let yearTotalCount = 0;
let gamesSum = 0;
const systemCount = {};
const ownershipCount = [0, 0, 0, 0, 0, 0];
function isNonNullish(variable) {
    if (typeof variable !== 'undefined' && variable !== null) {
        return true;
    }
    return false;
}
function isNonEmpty(value) {
    if (isNonNullish(value) && value !== "") {
        return true;
    }
    return false;
}
//Enable or disable log messages in the browser's javascript console
const enableLogging = false;
function log(message) {
    if (enableLogging) {
        const now = new Date();
        const addZero = function (d) {
            if (d < 10)
                d = "0" + d;
            return d;
        };
        let millis = now.getMilliseconds();
        if (millis < 10)
            millis = "00" + millis;
        else if (millis < 100)
            millis = "0" + millis;
        const displayMessage = addZero(now.getHours()) + ":" +
            addZero(now.getMinutes()) + ":" +
            addZero(now.getSeconds()) + ":" +
            millis + " " + message;
        console.log(displayMessage);
    }
}
/// <reference path="state.ts" />
/// <reference path="utils.ts" />
/// <reference path="logging.ts" />
/*
Use transparent backgrounds for charts. Set to false if the text in the
charts is hard to read.
*/
const transparentBackgroundForCharts = true;
/* In the pie charts, merge categories with very few games
into an "other" category. 0.05 means that services with fewer than 5% of the
total number of games will be put in the "other" category.
This might make the chart less cluttered.
A setting between 0.10 and 0.01 recommended. Set to 0.00 to disable. */
const otherThreshold = 0.04;
// Width and height of charts.
const chartWidth = 281;
const chartHeight = 100;
//Creates pie chart from parameters
function createPieChart(data, labels, colors, transparent, width, height) {
    let pieChartUrl = "http://chart.apis.google.com/chart" +
        "?cht=p&chs=" + width + "x" + height +
        "&chd=t:" + data + "&chl=" + labels;
    if (transparent)
        pieChartUrl += "&chf=bg,s,00000000";
    pieChartUrl += "&chco=" + colors;
    log(pieChartUrl);
    return pieChartUrl;
}
function updateStatusChart(headerSection) {
    const img = headerSection.find("#statusChart");
    if (img.length > 0)
        return;
    $('div#maincolumn > section:first > table').css('display', 'none');
    const tableRows = $('div#maincolumn > section:first > table tr');
    const unfinishedCount = tableRows.eq(0).children(":eq(1)").text();
    const beatenCount = tableRows.eq(1).children(":eq(1)").text();
    const completedCount = tableRows.eq(2).children(":eq(1)").text();
    if (!isNonEmpty(unfinishedCount) ||
        !isNonEmpty(beatenCount) ||
        !isNonEmpty(completedCount) ||
        parseInt(unfinishedCount) + parseInt(beatenCount) + parseInt(completedCount) < 1)
        return;
    const data = unfinishedCount + "," +
        beatenCount + "," + completedCount;
    const url = createPieChart(data, "Unfinished|Beaten|Completed", "990000,BDBDBD,FFCC66", transparentBackgroundForCharts, chartWidth, chartHeight);
    log("Adding status chart");
    const imgHtml = "<img src='" + url +
        "' title='Status chart' " +
        "alt='Status chart' id='statusChart' " +
        "width='" + chartWidth + "' height='" + chartHeight + "'/> ";
    headerSection.append(imgHtml);
}
function createSystemChartUrl() {
    let chartData = "";
    let chartLabels = "";
    let other = 0;
    for (const system in systemCount) {
        if (systemCount[system] / gamesSum > otherThreshold) {
            chartData += 100 * systemCount[system] / gamesSum + ",";
            chartLabels += system + "|";
        }
        else {
            other += systemCount[system];
        }
    }
    if (other > 0) {
        chartData += 100 * other / gamesSum + ",";
        chartLabels += "Other" + "|";
    }
    return createPieChart(chartData.substr(0, chartData.length - 1), chartLabels.substr(0, chartLabels.length - 1), "7777ff", transparentBackgroundForCharts, chartWidth, chartHeight);
}
function updateSystemChart(headerSection) {
    const img = headerSection.find("#systemChart");
    if (gamesSum < 1) {
        img.remove();
        return;
    }
    const url = createSystemChartUrl();
    if (isNonEmpty(url)) {
        if (img.length > 0) {
            log("Updating system chart");
            img.attr("src", url);
        }
        else {
            log("Adding system service chart");
            const imgHtml = "<img src='" + url +
                "' title='System chart' " +
                "alt='System chart' id='systemChart' " +
                "width='" + chartWidth + "' height='" + chartHeight + "'/> ";
            headerSection.append(imgHtml);
        }
    }
}
function createOwnershipChartUrl() {
    const ownershipLabels = ["Owned", "Household", "Subscription", "Borrowed/Rented", "Formerly Owned", "Other"];
    //Use chart colors similar to the ownership icons
    const colors = ["b6b718", "fffcb5", "dec123", "7a9e9c", "9bacff", "9b89b6"];
    let chartData = "";
    let chartLabels = "";
    let chartColors = "";
    for (let i = 0; i < ownershipCount.length; i++)
        if (ownershipCount[i] > 0) {
            chartData += 100 * ownershipCount[i] / gamesSum + ",";
            chartLabels += ownershipLabels[i] + "|";
            chartColors += colors[i] + ",";
        }
    return createPieChart(chartData.substr(0, chartData.length - 1), chartLabels.substr(0, chartLabels.length - 1), chartColors.substr(0, chartColors.length - 1), transparentBackgroundForCharts, chartWidth, chartHeight);
}
function createDDserviceChartUrl() {
    let chartData = "";
    let chartLabels = "";
    let other = 0;
    for (const keyword in downloadServiceStatistics) {
        if (downloadServiceStatistics[keyword] / downloadServiceTotalCount
            > otherThreshold) {
            chartData += 100 * downloadServiceStatistics[keyword]
                / downloadServiceTotalCount + ",";
            chartLabels += keyword + "|";
        }
        else {
            other += downloadServiceStatistics[keyword];
        }
    }
    if (other > 0) {
        chartData += 100 * other / downloadServiceTotalCount + ",";
        chartLabels += "Other" + "|";
    }
    return createPieChart(chartData.substr(0, chartData.length - 1), chartLabels.substr(0, chartLabels.length - 1), "11aa11", transparentBackgroundForCharts, chartWidth, chartHeight);
}
function updateOwnershipChart(headerSection) {
    const img = headerSection.find("#ownershipChart");
    if (gamesSum < 1) {
        img.remove();
        return;
    }
    const url = createOwnershipChartUrl();
    if (isNonEmpty(url)) {
        if (img.length > 0) {
            log("Updating ownership chart");
            img.attr("src", url);
        }
        else {
            log("Adding ownership service chart");
            const imgHtml = "<img src='" + url +
                "' title='Ownership chart' " +
                "alt='Ownership chart' id='ownershipChart' " +
                "width='" + chartWidth + "' height='" + chartHeight + "'/> ";
            headerSection.append(imgHtml);
        }
    }
}
function updateDDserviceChart(headerSection) {
    const img = headerSection.find("#ddChart");
    if (downloadServiceTotalCount < 1) {
        img.remove();
        return;
    }
    const url = createDDserviceChartUrl();
    if (isNonEmpty(url)) {
        if (img.length > 0) {
            log("Updating DD service chart");
            img.attr("src", url);
        }
        else {
            log("Adding DD service chart");
            const imgHtml = "<img src='" + url +
                "' title='Digital distribution services chart' " +
                "alt='Digital distribution services chart' id='ddChart' " +
                "width='" + chartWidth + "' height='" + chartHeight + "'/> ";
            headerSection.append(imgHtml);
        }
    }
}
function createYearChartUrl() {
    const years = new Array();
    let yearStatisticsIdx = 0;
    let highestValue = 0;
    for (const year in yearStatistics) {
        years[yearStatisticsIdx] = year;
        yearStatisticsIdx++;
        if (yearStatistics[year] > highestValue)
            highestValue = yearStatistics[year];
    }
    years.sort();
    const lowestYear = parseInt(years[0]);
    const highestYear = parseInt(years[years.length - 1]);
    let chartDataX = "";
    let chartDataY = "";
    const chartLabelScaleFactor = Math.ceil((1 + highestYear - lowestYear) / 20);
    for (let i = lowestYear; i <= highestYear; i++) {
        if (i % chartLabelScaleFactor == 0)
            chartDataX += i + "|";
        else
            chartDataX += "|";
        if (yearStatistics[i.toString()] == null)
            chartDataY += "0,";
        else
            chartDataY += 100 * yearStatistics[i.toString()] / highestValue + ",";
    }
    let barChartUrl = "http://chart.apis.google.com/chart" +
        "?cht=bvs&chs=" + chartWidth * 2 + "x" + chartHeight +
        "&chd=t:" + chartDataY.substr(0, chartDataY.length - 1) +
        "&chxl=0:|" + chartDataX.substr(0, chartDataX.length - 1) +
        "&chxt=x,y&chbh=a" +
        "&chxr=1,0," + highestValue;
    if (transparentBackgroundForCharts)
        barChartUrl += "&chf=bg,s,00000000";
    barChartUrl += "&chco=4D89F9";
    log(barChartUrl);
    return barChartUrl;
}
function updateYearChart(headerSection) {
    const img = headerSection.find("#yearChart");
    if (yearTotalCount < 2) {
        img.remove();
        return;
    }
    const url = createYearChartUrl();
    if (isNonEmpty(url)) {
        if (img.length > 0) {
            log("Updating year chart");
            img.attr("src", url);
        }
        else {
            log("Adding year chart");
            const imgHtml = "<img src='" + url +
                "' title='Release years chart' alt='Release years chart' id='yearChart' " +
                "width='" + chartWidth * 2 + "' height='" + chartHeight + "'/> ";
            headerSection.append(imgHtml);
        }
    }
}
function updateCharts() {
    log("Updating charts");
    const headerSection = $("section").first();
    if (headerSection.find('div#chartDiv1').length < 1)
        headerSection.append("<div id='chartDiv1'></div>");
    if (headerSection.find('div#chartDiv2').length < 1)
        headerSection.append("<div id='chartDiv2'></div>");
    updateStatusChart(headerSection.find('div#chartDiv1'));
    updateSystemChart(headerSection.find('div#chartDiv1'));
    updateOwnershipChart(headerSection.find('div#chartDiv1'));
    updateDDserviceChart(headerSection.find('div#chartDiv1'));
    updateYearChart(headerSection.find('div#chartDiv2'));
}
//Association between keywords and icons
const ddicons = {};
ddicons['gog.com'] = 0;
ddicons['gog'] = 0;
ddicons['steampowered.com'] = 2;
ddicons['steam'] = 2;
ddicons['playgreenhouse.com'] = 3;
ddicons['greenhouse'] = 3;
ddicons['telltalegames.com'] = 4;
ddicons['telltale'] = 4;
ddicons['zombie-cow.com'] = 5;
ddicons['zombie-cow'] = 5;
ddicons['impulsedriven.com'] = 6;
ddicons['impulse'] = 6;
ddicons['direct2drive.com'] = 7;
ddicons['direct2drive.co.uk'] = 7;
ddicons['direct2drive.eu'] = 7;
ddicons['direct2drive'] = 7;
ddicons['d2d'] = 7;
ddicons['gamersgate.com'] = 8;
ddicons['gamersgate'] = 8;
ddicons['amanita-design.net'] = 9;
ddicons['amanitadesign'] = 9;
ddicons['tale-of-tales.com'] = 10;
ddicons['taleoftales'] = 10;
ddicons['bigfinishgames.com'] = 11;
ddicons['bigfinish'] = 11;
ddicons['2dboy.com'] = 12;
ddicons['2dboy'] = 12;
ddicons['crayonphysics.com'] = 13;
ddicons['crayonphysics'] = 13;
ddicons['bit-blot.com'] = 14;
ddicons['bitblot'] = 14;
ddicons['areo.areograph.com'] = 15;
ddicons['areogames'] = 15;
ddicons['battle.net'] = 20;
ddicons['xboxlive'] = 21;
ddicons['gfw'] = 24;
ddicons['gamesforwindows'] = 24;
ddicons['gamesforwindowsmarketplace'] = 24;
ddicons['getgames'] = 23;
ddicons['getgamesgo'] = 23;
ddicons['android'] = 25;
ddicons['androidmarket'] = 25;
ddicons['googleplay'] = 25;
ddicons['yawma'] = 26;
ddicons['yawma.net'] = 26;
ddicons['humbleindiebundle'] = 27;
ddicons['humblebundle.com'] = 27;
ddicons['humblebundle'] = 27;
ddicons['desura'] = 28;
ddicons['desura.com'] = 28;
ddicons['beamdog'] = 29;
ddicons['beamdog.com'] = 29;
ddicons['casebookthegame.com'] = 30;
ddicons['casebook'] = 30;
ddicons['theballthegame.com'] = 31;
ddicons['theball'] = 31;
ddicons['origin'] = 32;
ddicons['nintendo'] = 33;
ddicons['psn'] = 34;
ddicons['sizefivegames.com'] = 35;
ddicons['sizefivegames'] = 35;
ddicons['indieroyale.com'] = 36;
ddicons['indieroyale'] = 36;
ddicons['gamefly.com'] = 37;
ddicons['gamefly'] = 37;
ddicons['amazon.com'] = 38;
ddicons['amazon'] = 38;
ddicons['greenmangaming.com'] = 39;
ddicons['greenmangaming'] = 39;
ddicons['gmg'] = 39;
ddicons['uplay'] = 40;
ddicons['uplay.ubi.com'] = 40;
ddicons['freebird'] = 41;
ddicons['freebirdgames'] = 41;
ddicons['freebirdgames.com'] = 41;
ddicons['indiegala'] = 42;
ddicons['indiegala.com'] = 42;
ddicons['kickstarter'] = 43;
ddicons['kickstarter.com'] = 43;
ddicons['indiegamestand'] = 44;
ddicons['indiegamestand.com'] = 44;
ddicons['indiegogo'] = 45;
ddicons['indiegogo.com'] = 45;
ddicons['gamestop'] = 46;
ddicons['gamestop.com'] = 46;
ddicons['groupees'] = 47;
ddicons['groupees.com'] = 47;
ddicons['playism'] = 48;
ddicons['playism-games.com'] = 48;
ddicons['bigfish'] = 49;
ddicons['bigfishgames'] = 49;
ddicons['bigfishgames.com'] = 49;
ddicons['dotemu'] = 50;
ddicons['dotemu.com'] = 50;
ddicons['indiecity'] = 51;
ddicons['indiecity.com'] = 51;
ddicons['nuuvem'] = 52;
ddicons['nuuvem.com.br'] = 52;
ddicons['windowsstore'] = 53;
ddicons['itch.io'] = 54;
ddicons['vive'] = 55;
ddicons['oculus'] = 56;
ddicons['rift'] = 56;
//List of URLs to icons
const icon_urls = [];
icon_urls[0] = "https://lh3.googleusercontent.com/-PhuK9fCqWXg/U4sbbMxLmYI/AAAAAAAABhQ/xYtsQcM6LiY/s800/gog.png";
icon_urls[2] = "https://store.steampowered.com/favicon.ico";
icon_urls[3] = "https://lh6.googleusercontent.com/-i1ugqfN2sM4/U4YanM5_lII/AAAAAAAABdM/RIndcc33kwo/s800/greenhouse.png";
icon_urls[4] = "https://lh3.googleusercontent.com/-LqhGwE8Uyjw/U4YcXukagxI/AAAAAAAABeU/ox9DrBYqDsg/s800/telltale.png";
icon_urls[5] = "https://lh5.googleusercontent.com/-wXSLqwLwihM/U4YcUesxPEI/AAAAAAAABeM/qecM551KaEc/s800/zombie-cow.png";
icon_urls[6] = "https://lh6.googleusercontent.com/-Pc3nu4XDPyE/U4YiGtNVuyI/AAAAAAAABgc/5HFCyvMykiQ/s800/impulse.png";
icon_urls[7] = "https://lh4.googleusercontent.com/-uzHpk1lSL34/U4YYKWxA_5I/AAAAAAAABcU/4V4aJ4p402I/s800/d2d.png";
icon_urls[8] = "https://github.com/torlye/Backloggery-enhancements/raw/master/icons/gamersgate.webp";
icon_urls[9] = "https://lh5.googleusercontent.com/-G1BUB8sbDYM/U4Ycre-N0cI/AAAAAAAABe4/XCkQRlAKkRA/s800/amanitadesign.png";
icon_urls[10] = "https://lh4.googleusercontent.com/-z1mzei2qLuk/U4YcMNddPaI/AAAAAAAABeE/kCOwM1d0C98/s800/taleoftales.png";
icon_urls[11] = "https://lh5.googleusercontent.com/-ovDvrXveHKI/U4YY3pqECjI/AAAAAAAABcg/fLSfwSa4PdY/s800/bigfinish.png";
icon_urls[12] = "https://lh3.googleusercontent.com/-cqTpbNOc3Eo/U4YekNHEraI/AAAAAAAABf0/Uimh4LlA9fE/s800/2dboy.png";
icon_urls[13] = "https://lh6.googleusercontent.com/-BCOuRHWLVPU/U4YcMLRzYMI/AAAAAAAABeA/zoLcuAPTTL8/s800/crayonphysics.png";
icon_urls[14] = "https://lh3.googleusercontent.com/-YWvBV6SG95s/U4YVOZiDqOI/AAAAAAAABbg/DWks790O8Tw/s800/bit-blot.png";
icon_urls[15] = "https://lh4.googleusercontent.com/-hiTvab7fNeQ/U4YVNkVzdbI/AAAAAAAABcA/9IR0d7vj5Rw/s800/areogames.png";
icon_urls[16] = "https://lh4.googleusercontent.com/-Fw5IgzTXS0E/U4Yee5J6qWI/AAAAAAAABfs/1I6iJpnY46w/s800/floppy.png";
icon_urls[17] = "https://lh6.googleusercontent.com/-fgYO_GO8n0A/U4Yee6LkbrI/AAAAAAAABfc/syry88tZqUs/s800/disc.png";
icon_urls[18] = "https://lh3.googleusercontent.com/-iwXya8FD7AM/U4YVOp6-AvI/AAAAAAAABbk/WBMb1AgtN2c/s800/cart.png";
icon_urls[19] = "https://lh5.googleusercontent.com/-r8C-lX0w_bI/U4YefafJe7I/AAAAAAAABfo/niNWzjrY3zk/s800/soundtrack.png";
icon_urls[20] = "https://raw.githubusercontent.com/torlye/Backloggery-enhancements/master/icons/battlenet.png";
icon_urls[21] = "https://lh6.googleusercontent.com/-QRWAZw-QeVI/U4YbLQRWCvI/AAAAAAAABdc/UM6aD_OC45Q/s800/xboxlive.png";
icon_urls[22] = "https://lh6.googleusercontent.com/-VQx0m0aF2vU/U4Yee7XwMFI/AAAAAAAABfY/iQuU-QE9jJA/s800/collectors.png";
icon_urls[23] = "https://drive.google.com/uc?id=1w1yMX9TzI4cuwvJwlBkXaXQ1IIp3BWAQSQ";
icon_urls[24] = "https://lh3.googleusercontent.com/-n3zHP5ZTEk8/U4YoNRILjFI/AAAAAAAABgs/donquTXcOI8/s800/gamesforwindows.png";
icon_urls[25] = "https://lh4.googleusercontent.com/-8k0SFFIFooQ/U4YY4QHg-fI/AAAAAAAABco/6yRzMjhm3BA/s800/googleplay.png";
icon_urls[26] = "https://lh6.googleusercontent.com/-QBuHwtRK93I/U4YapJUfBEI/AAAAAAAABdU/MwwsXQ_3fW4/s800/yawma.png";
icon_urls[27] = "https://humblebundle-a.akamaihd.net/static/hashed/46cf2ed85a0641bfdc052121786440c70da77d75.png";
icon_urls[28] = "https://lh6.googleusercontent.com/-YE1_ScE2oSA/U4Yab588McI/AAAAAAAABc8/MW30tqHQTRo/s800/desura.png";
icon_urls[29] = "https://raw.githubusercontent.com/torlye/Backloggery-enhancements/master/icons/beamdog.png";
icon_urls[30] = "https://lh3.googleusercontent.com/-HwUaInJeAcM/U4YcrYrLjNI/AAAAAAAABe8/L1ks1Jtprqg/s800/casebookthegame.png";
icon_urls[31] = "https://lh6.googleusercontent.com/-imwyJ2Luq18/U4YcZ0s4j6I/AAAAAAAABec/HL0PGHlaD0I/s800/theball.png";
icon_urls[32] = "https://lh4.googleusercontent.com/-HrU72c5icvg/U4YalWTsVOI/AAAAAAAABdE/NvEzPCfVgpw/s800/origin.png";
icon_urls[33] = "https://lh5.googleusercontent.com/-1YJ5GkrcnBg/U4YbYfGR41I/AAAAAAAABds/hk6DEBHe6CI/s800/nintendo.png";
icon_urls[34] = "https://i.imgur.com/BEHlNk2.png";
icon_urls[35] = "https://lh6.googleusercontent.com/-sUX5ivzf6ZY/U4Ycr0vY0nI/AAAAAAAABe0/cchIab0uxsk/s800/sizefivegames.png";
icon_urls[36] = "https://lh6.googleusercontent.com/-KXKZW_UP__k/U4YcrhklOqI/AAAAAAAABew/iZYgGG_T7GM/s800/indieroyale.png";
icon_urls[37] = "https://lh6.googleusercontent.com/-T6pBLW644C4/U4YaRDp7F-I/AAAAAAAABc0/tXWjiAAenZ0/s800/gamefly.png";
icon_urls[38] = "https://lh3.googleusercontent.com/-gNQGzO6OVp8/U4YVNiESYAI/AAAAAAAABbs/yFfiybWjTNk/s800/amazon.png";
icon_urls[39] = "https://www.greenmangaming.com/static/favicon.ico";
icon_urls[40] = "https://static2.cdn.ubi.com/gamesites/uplay/201212201711/img/favicon.ico";
icon_urls[41] = "https://lh6.googleusercontent.com/-mquB7vxjefw/U4YcrV1mJ8I/AAAAAAAABfE/N8IEKbWLgv8/s800/freebird.png";
icon_urls[42] = "https://www.indiegala.com/favicon.ico";
icon_urls[43] = "https://lh4.googleusercontent.com/-QxASAMDxDtY/U4YbYdMopKI/AAAAAAAABd0/aktUFbnE_Lk/s800/kickstarter.png";
icon_urls[44] = "https://drive.google.com/uc?id=1i8bjKbIE6JfMNUanDz6-vri0HfI4ZDSI";
icon_urls[45] = "https://lh5.googleusercontent.com/-33drwcq-8Mg/U4YbYdhNlbI/AAAAAAAABdo/o1tR4OM3SaA/s800/indiegogo.png";
icon_urls[46] = "https://www.gamestop.com/favicon.ico";
icon_urls[47] = "https://lh5.googleusercontent.com/-JqxT5YXGyxo/VLJUVkpErPI/AAAAAAAABmQ/IQcgSJH8iGQ/s800/groupees.png";
icon_urls[48] = "https://lh3.googleusercontent.com/--2pe41xzPjQ/VLJUWniehmI/AAAAAAAABmA/RglbG5rP3Jk/s800/playism-games.png";
icon_urls[49] = "https://lh3.googleusercontent.com/-WTH88IRzlQA/VLJUVpYqu8I/AAAAAAAABmM/b3QZTgeeI4s/s800/bigfishgames.png";
icon_urls[50] = "https://lh3.googleusercontent.com/-q3n7oxCgWso/VLJUVsGuhnI/AAAAAAAABmY/iD6J0AtUpdw/s800/dotemu.png";
icon_urls[51] = "https://lh6.googleusercontent.com/-7W3inoXb0rA/VLJUWHMPa1I/AAAAAAAABmI/v2l2bu1WiB8/s800/indiecity.png";
icon_urls[52] = "https://lh6.googleusercontent.com/-yFqz3QiC_kA/VLJWAcx6cbI/AAAAAAAABmo/WhfJU1JhuoU/s800/nuuvem.png";
icon_urls[53] = "https://lh3.googleusercontent.com/-L0Ae5fzDP9I/VLJUXP5o9RI/AAAAAAAABl8/xb9GYMwX3F0/s800/windowsstore.png";
icon_urls[54] = "https://lh5.googleusercontent.com/-CZqVqn8d67I/VLJUWchVXyI/AAAAAAAABmE/ehhftDUkpi4/s800/itch.io.png";
icon_urls[55] = "https://www.vive.com/static/images/favicon.ico";
icon_urls[56] = "https://github.com/torlye/Backloggery-enhancements/raw/master/icons/oculus.png";
//Do not count these icons in the digital distribution stores chart
const miscIcons = {};
miscIcons['floppy'] = 16;
miscIcons['disc'] = 17;
miscIcons['cartridge'] = 18;
miscIcons['soundtrack'] = 19;
miscIcons['collectorsedition'] = 22;
miscIcons['specialedition'] = 22;
//Icons for game systems defined by backloggery.com
const systemIcons = {};
systemIcons['BNet'] = "Battle.net";
systemIcons['Bdog'] = "Beamdog";
systemIcons['BFG'] = "BigFishGames";
systemIcons['Desura'] = "Desura";
systemIcons['DotEmu'] = "DotEmu";
systemIcons['GGate'] = "GamersGate";
systemIcons['G4W'] = "GamesforWindows";
systemIcons['GGames'] = "GetGames";
systemIcons['GMG'] = "GMG";
systemIcons['GOG'] = "GOG";
systemIcons['Imp'] = "GameStop";
systemIcons['IndieC'] = "IndieCity";
systemIcons['Nuuvem'] = "Nuuvem";
systemIcons['Origin'] = "Origin";
systemIcons['Steam'] = "Steam";
systemIcons['UPlay'] = "UPlay";
systemIcons['WinStr'] = "WindowsStore";
/// <reference path="utils.ts" />
/// <reference path="state.ts" />
/// <reference path="icons/ddicons.ts" />
/// <reference path="icons/icon_urls.ts" />
/// <reference path="icons/miscIcons.ts" />
/// <reference path="icons/systemIcons.ts" />
/// <reference path="logging.ts" />
function createIconFromURLandTitle(url, title) {
    return ' <span class="info"><img width="16" height="16" src="' + url +
        '" alt="' + title + '" title="' + title + '" ' +
        'style="margin-bottom: -1px;" /></span> ';
}
function appendIconNumberToNode(iconNumber, iconTitle, node) {
    log("Appending icon " + iconNumber + " with title " + iconTitle + " to current node");
    node.append(createIconFromURLandTitle(icon_urls[iconNumber], iconTitle));
}
function createIconsFromKeyWord(word, iconsNode) {
    const keyWord = /^\[([\w\.-]+)\]$/.exec($.trim(word));
    if (keyWord) {
        log("Found keyword " + keyWord[1]);
        //Try to parse keyword as download service icon
        let iconNumber = ddicons[keyWord[1].toLowerCase()];
        if (isNonNullish(iconNumber)) {
            appendIconNumberToNode(iconNumber, keyWord[1], iconsNode);
            //Increment counters for charts
            downloadServiceTotalCount++;
            if (!downloadServiceStatistics[keyWord[1]])
                downloadServiceStatistics[keyWord[1]] = 1;
            else
                downloadServiceStatistics[keyWord[1]]++;
            return true;
        }
        //Try to parse keyword as "misc" icon
        iconNumber = miscIcons[keyWord[1].toLowerCase()];
        if (isNonNullish(iconNumber)) {
            appendIconNumberToNode(iconNumber, keyWord[1], iconsNode);
            return true;
        }
    }
    return false;
}
function addSystemIcon(system, iconsNode) {
    if (systemIcons[system])
        createIconsFromKeyWord("[" + systemIcons[system] + "]", iconsNode);
}
/// <reference path="state.ts" />
/// <reference path="logging.ts" />
function createYearLabelFromKeyWord(word, yearNode) {
    const year = /^\((\d{4})\)$/.exec($.trim(word));
    if (year) {
        log("Appending year node " + year[0]);
        yearNode.append(" " + year[0]);
        //Update year statistics
        yearTotalCount++;
        if (!yearStatistics[year[1]])
            yearStatistics[year[1]] = 1;
        else
            yearStatistics[year[1]] += 1;
        return true;
    }
    return false;
}
/// <reference path="iconfunctions.ts" />
/// <reference path="yearFunctions.ts" />
/// <reference path="chartFunctions.ts" />
/// <reference path="state.ts" />
/// <reference path="logging.ts" />
/* This script uses icons from the "Silk" and "Diagona" icon sets, which may
be found at http://www.famfamfam.com/lab/icons/silk/
and http://p.yusukekamiyamane.com/
*/
//Process game list on games.php page
function gameListUpdated() {
    log("gameListUpdated starts");
    detachGameListEventReceiver();
    let gameboxesProcessed = 0;
    $("section.gamebox:not(.processed):not(.boxtop):not(.systemend)").each(function (index) {
        if (enableLogging)
            log("Processing gamebox " + $(this).find("h2 b:first").text());
        if ($(this).find('h2 img[alt="Comp"]').length > 0) {
            log("Skipping this gamebox, it's a compilation");
            $(this).addClass("processed");
            return;
        }
        const gameRow1 = $(this).find("div.gamerow").first();
        const gameRow2 = $(this).find("div.gamerow").eq(1);
        //Get system information
        const system = $.trim(gameRow1.text()).split(" ")[0];
        log("System is " + system);
        if (!systemCount[system])
            systemCount[system] = 1;
        else
            systemCount[system]++;
        //Add icons for systems that really represent digital distribution stores
        addSystemIcon(system, gameRow1);
        //Get ownership information
        if (gameRow1.find('img[title="Household"]').length > 0)
            ownershipCount[1]++;
        else if (gameRow1.find('img[title="Subscription"]').length > 0)
            ownershipCount[2]++;
        else if (gameRow1.find('img[title="Borrowed/Rented"]').length > 0)
            ownershipCount[3]++;
        else if (gameRow1.find('img[title="Formerly Owned"]').length > 0)
            ownershipCount[4]++;
        else if (gameRow1.find('img[title="Ownership: Other"]').length > 0)
            ownershipCount[5]++;
        else
            ownershipCount[0]++;
        //Parse words
        const words = gameRow2.text().split(" ");
        let hasYear = false;
        for (const i in words) {
            const word = words[i];
            //Get year
            if (!hasYear) {
                hasYear = createYearLabelFromKeyWord(word, gameRow1.find("b:first"));
                if (hasYear) {
                    words[i] = null;
                    continue;
                }
            }
            //Create icons from keyword
            if (createIconsFromKeyWord(word, gameRow1)) {
                words[i] = null;
                continue;
            }
        }
        gameRow2.text(words.join(" "));
        if (!/\S/.test(gameRow2.text()))
            gameRow2.remove();
        $(this).addClass("processed");
        gameboxesProcessed++;
        gamesSum++;
    });
    if (gameboxesProcessed > 0) {
        updateCharts();
    }
    attachGameListEventReceiver();
    log("gameListUpdated end");
}
//Process now playing list
function processNowPlayingList() {
    $("div.npgame").each(function (index) {
        var _a, _b;
        const progressDiv = $(this).children().eq(-2);
        const words = (_b = (_a = progressDiv.contents().get(0).textContent) === null || _a === void 0 ? void 0 : _a.split(" ")) !== null && _b !== void 0 ? _b : [];
        let hasYear = false;
        progressDiv.prepend("<span class='scripticons'></span>");
        for (const i in words) {
            const word = words[i];
            if (!hasYear) {
                hasYear = createYearLabelFromKeyWord(word, progressDiv.prev());
                if (hasYear) {
                    words[i] = null;
                    continue;
                }
            }
            if (createIconsFromKeyWord(word, progressDiv.find("span.scripticons"))) {
                words[i] = null;
                continue;
            }
        }
        progressDiv.contents().get(1).textContent = words.join(" ");
    });
}
//Process multitap
function processMultitap() {
    $("div.friend li").each(function (index) {
        var _a, _b;
        if ($(this).contents().length < 4)
            return;
        const words = (_b = (_a = $(this).contents().get(3).textContent) === null || _a === void 0 ? void 0 : _a.split(" ")) !== null && _b !== void 0 ? _b : [];
        const hasYear = false;
        $(this).append("<span class='scripticons'></span>");
        for (const i in words) {
            const word = words[i];
            if (createIconsFromKeyWord(word, $(this).find("span.scripticons"))) {
                words[i] = null;
                continue;
            }
        }
        $(this).contents().get(3).textContent = words.join(" ");
    });
}
function attachGameListEventReceiver() {
    $("div#content").bind("DOMNodeInserted", gameListUpdated);
}
function detachGameListEventReceiver() {
    $("div#content").unbind("DOMNodeInserted", gameListUpdated);
}
let loadAllTriggered = false;
$(document).keyup(function (event) {
    if (event.which == 76 && event.shiftKey && event.ctrlKey && !isLoadingAjax()) { //Ctrl-Shift-L
        if (!loadAllTriggered && documentContainsStuffToLoad()) {
            log("Starting load all");
            detachGameListEventReceiver();
            addActivityIndicator();
            loadAllTriggered = true;
            tryLoadNext();
        }
    }
});
function documentContainsStuffToLoad() {
    return ($("input[type='button'][value='Show more games']").length > 0) || ($(".lessmore[onclick]:contains('\u25BC')").length > 0);
}
function isLoadingAjax() {
    return $("img[src$='AJAX_loading.gif']").length > 0;
}
function tryLoadNext() {
    $("div#content").unbind("DOMNodeInserted", tryLoadNext);
    if (isLoadingAjax())
        $("div#content").bind("DOMNodeInserted", tryLoadNext);
    else
        triggerNext();
}
function triggerNext() {
    const showMoreBtn = $("input[type='button'][value='Show more games']");
    if (showMoreBtn.length > 0) {
        log("Loading next page");
        showMoreBtn.click();
        setTimeout(tryLoadNext, 1000);
        return;
    }
    const expandBtn = $(".lessmore[onclick]:contains('\u25BC')").first();
    if (expandBtn.length > 0) {
        log("Expanding collection");
        expandBtn.click();
        setTimeout(tryLoadNext, 1000);
        return;
    }
    log("Load all done");
    gameListUpdated();
    removeActivityIndicator();
}
function addActivityIndicator() {
    let x = (window.innerWidth - 100) / 2;
    let y = (window.innerHeight - 100) / 2;
    $(document.body).append('<div class="loadallindicator" style="width:100px;height:100px;position:fixed;left:' + x + 'px;top:' + y + 'px;z-index:100;background-color:black;opacity:0.7"></div>');
    x += 28;
    y += 27;
    $(document.body).append('<img class="loadallindicator" style="position:fixed;left:' + x + 'px;top:' + y + 'px;z-index:100" src="images/AJAX_loading.gif?foo" alt="Now Loading..." width="44" height="46" />');
}
function removeActivityIndicator() {
    $('.loadallindicator').remove();
}
processNowPlayingList();
processMultitap();
gameListUpdated();