emptydev / SE - Roubo Graph

// ==UserScript==
// @name         SE - Roubo Graph
// @namespace    http://tampermonkey.net/
// @version      0.13
// @description  try to take over the world!
// @author       Magnus Man
// @match        https://extreme.sysemp.com/menu.php*
// @match        https://extreme.sysemp.com/messages.php*
// @match        https://extreme.sysemp.com/mainview.php*
// @require      https://code.highcharts.com/highcharts.js
// @require      https://code.highcharts.com/modules/exporting.js
// @require      https://code.highcharts.com/modules/export-data.js
// @require      https://code.highcharts.com/modules/accessibility.js
// @require      http://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js
// @updateURL    https://openuserjs.org/meta/emptydev/SE_-_Roubo_Graph.meta.js
// @downloadURL  https://openuserjs.org/install/emptydev/SE_-_Roubo_Graph.user.js
// @copyright    2020, Magnus Man (https://openuserjs.org/users/emptydev)
// @grant        none
// @license      MIT
// ==/UserScript==

// 0.2 - Alterada a injeção do gráfico
// 0.5 - melhorada a qualidade dos gráficos
//     - retirados os pontos das linhas
//     - melhoradas as cores
// 0.6 - melhoradas do tooltip
// 0.7 - adicionado o botão ao menu
// 0.8 - adicionado o número de ataques por dia ao tooltip do gráfico
// 0.9 - adicionado o gráfico de trocas do mercado
// 0.10 - redução dos valores apresentados para 8 dias.
// 0.11 - adicionada a opção de limpar todos os dados.

(function () {
    'use strict';

    function n(v) {
        return parseInt(v.toString().replace(/\D+/g, '')) || 0;
    }

    function nf(amount, decimalCount = 0, decimal = ".", thousands = ".") {
        try {
            decimalCount = Math.abs(decimalCount);
            decimalCount = isNaN(decimalCount) ? 2 : decimalCount;

            const negativeSign = amount < 0 ? "-" : "";

            let i = parseInt(amount = Math.abs(Number(amount) || 0).toFixed(decimalCount)).toString();
            let j = (i.length > 3) ? i.length % 3 : 0;

            return amount == 0 ? '0' : negativeSign + (j ? i.substr(0, j) + thousands : '') + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thousands) + (decimalCount ? decimal + Math.abs(amount - i).toFixed(decimalCount).slice(2) : "");
        }
        catch (e) {
            console.log("");
        }
    }

    var graphData = JSON.parse(localStorage.getItem("graphData") || "[]");

    $("tr:contains('Frota regressou de ataque')").each(function () {
        var timedate = $(this).find("td:eq(5)").text();
        var datetime = timedate.split(" ");
        var time = datetime[0];
        var date = datetime[1].split("/");
        date[2] = "20" + date[2];
        var fullDate = date[2] + "/" + date[1] + "/" + date[0] + " " + time;

        var resources = $(this).next().eq(0).find("tr").eq(1).text().split(", ");
        var res = [0, 0, 0, 0, 0];
        var tempResources = ["m", "d", "h", "z", "n"];

        for (var i = 0; i < resources.length; i++) {
            for (var j = 0; j < tempResources.length; j++) {
                if (resources[i].toLowerCase().indexOf(tempResources[j]) > -1) {
                    res[j] = n(resources[i]);
                }
            }
        }

        var obj = {
            data: fullDate,
            resources: res
        };

        var objExists = graphData.filter(function (item) {
            return JSON.stringify(item) == JSON.stringify(obj);
        }).length > 0;

        if (!objExists) {
            graphData.push(obj);
        }
    });

    localStorage.setItem("graphData", JSON.stringify(graphData));

    var marketGraph = JSON.parse(localStorage.getItem("marketGraph") || "[]");
    $("tr:contains('Troca com o Mercado concluída')").each(function () {
        var timedate = $(this).find("td:eq(5)").text();
        var datetime = timedate.split(" ");
        var time = datetime[0];
        var date = datetime[1].split("/");
        date[2] = "20" + date[2];
        var fullDate = date[2] + "/" + date[1] + "/" + date[0] + " " + time;

        var resourcesReceived = $(this).next().eq(0).find("tr").eq(1).text().split(", ");
        var resourcesSent = $(this).next().eq(0).find("tr").eq(2).text().replace("A frota entregou no mercado: ", "").split(", ");
        var resRec = [0, 0, 0, 0, 0];
        var resSen = [0, 0, 0, 0, 0];
        var tempResources = ["m", "d", "h", "z", "n"];

        for (var i = 0; i < resourcesReceived.length; i++) {
            for (var j = 0; j < tempResources.length; j++) {
                if (resourcesReceived[i].toLowerCase().indexOf(tempResources[j]) > -1) {
                    resRec[j] = n(resourcesReceived[i]);
                }
            }
        }

        for (var i = 0; i < resourcesSent.length; i++) {
            for (var j = 0; j < tempResources.length; j++) {
                if (resourcesSent[i].toLowerCase().indexOf(tempResources[j]) > -1) {
                    resSen[j] = n(resourcesSent[i]);
                }
            }
        }

        var obj = {
            data: fullDate,
            resourcesSent: resSen,
            resourcesReceived: resRec
        };

        var objExists = marketGraph.filter(function (item) {
            return JSON.stringify(item) == JSON.stringify(obj);
        }).length > 0;

        if (!objExists) {
            marketGraph.push(obj);
        }
    });

    localStorage.setItem("marketGraph", JSON.stringify(marketGraph));

    function arraySum(arr) {
        var ret = 0;
        for (var i = 0; i < arr.length; i++) {
            ret += arr[i];
        }
        return ret;
    }

    function getGraph() {
        var graphData = JSON.parse(localStorage.getItem("graphData") || "[]");
        var resourcesLabel = ["Metal", "Diamante", "Hidrogénio", "Zion", "Nanite"];
        var resourcesColor = ["#b5b5b5", "#2a80ff", "#ff002a", "#fcff00", "#222222"];
        var dates = [];

        var labelDates = [];
        var resources = [];

        var todayResources = [0, 0, 0, 0, 0];
        var totalAttacks = 0;
        $.each(graphData, function (i, e) {
            if (dates.findIndex(function (person) {
                return person.date == e.data.split(" ")[0]
            }) == -1) {
                dates.push({
                    date: e.data.split(" ")[0],
                    resources: e.resources,
                    attacks: 1
                });
                labelDates.push(e.data.split(" ")[0]);
            }
            else {
                var idx = dates.findIndex(function (person) {
                    return person.date == e.data.split(" ")[0]
                });
                for (var j = 0; j < resourcesLabel.length; j++) {
                    dates[idx].resources[j] += e.resources[j];
                }
                dates[idx].attacks += 1;
            }

            if (e.data.indexOf(moment().format("YYYY/MM/DD")) > -1) {
                totalAttacks += 1;
                for (var j = 0; j < resourcesLabel.length; j++) {
                    todayResources[j] += e.resources[j];
                }
            }
        });

        var series = [];
        labelDates.sort();
        labelDates = labelDates.slice(-8);
        for (var k = 0; k < resourcesLabel.length; k++) {
            var obj = {
                type: 'areaspline',
                name: resourcesLabel[k],
                data: [],
                color: resourcesColor[k]
            };
            for (var i = 0; i < labelDates.length; i++) {
                var _resources = dates.filter(function (item) {
                    return item.date == labelDates[i];
                });
                obj.data[i] = _resources[0].resources[k];
            }
            series.push(obj);
        }

        var $divGraph = $("<div />", {
            class: "graphContainer",
            "style": "position:fixed; top:0; left:0; width:100%; height:100%; background: rgba(0,0,0,0.7);"
        });
        var $closeGraph = $("<input />", {
            "type": "button",
            "class": "button",
            "style": "bottom: 50px; position:absolute;"
        }).val("Fechar").on("click", function () {
            $divGraph.remove();
        });

        var $clearGraph = $("<input />", {
            "type": "button",
            "class": "button",
            "style": "bottom: 50px; position:absolute; margin: 0 64px;"
        }).val("Limpar Gráfico").on("click", function () {
            $divGraph.remove();
            localStorage.removeItem("graphData");
        });

        var $graphContainer = $("<div />", {
            "id": "graphAttacks",
            "style": "width:800px; height:400px;background-color:#FFF; margin:120px auto 0px auto;"
        });

        $divGraph.append($("<center />").append($closeGraph, $clearGraph, $graphContainer));

        var resources = [0, 0, 0, 0, 0];
        var racios = [1, 2, 3, 6, 2000];
        $.each(dates, function (i, e) {
            for (var i = 0; i < resourcesLabel.length; i++) {
                resources[i] += e.resources[i];
            }
        });

        var labels = ["<th style='border-top: 1px solid #69c;' colspan='2'>Hoje</th>"];
        var values = ["<th style='border-top: 1px solid #69c;' class='blue' colspan='2'>" + totalAttacks + "</th>"];
        var points = ["<th style='border-top: 1px solid #69c;' colspan='2'>Pontos</th>"];
        var avgAttack = ["<th colspan='2' style='border-top: 1px solid #69c;' >Média Ataque</th>"];
        var sumAvg = 0,
            sumDay = 0,
            sumPoints = 0;
        for (var i = 0; i < resourcesLabel.length; i++) {
            labels.push("<th>" + resourcesLabel[i] + "</th>");
            values.push("<th style='border-top: 1px solid #69c;' class='orange' align='center'>" + nf(todayResources[i]) + "</th>");
            points.push("<th style='border-top: 1px solid #69c;' class='orange' align='center'>" + nf(todayResources[i] * racios[i] / 1000) + "</th>");
            sumAvg += todayResources[i] / totalAttacks;
            sumDay += todayResources[i] / totalAttacks;
            sumPoints += todayResources[i] * racios[i] / 1000;
            avgAttack.push("<th style='border-top: 1px solid #69c;' class='orange' align='center'>" + nf(todayResources[i] / totalAttacks) + "</th>");
        }

        var $table3 = $("<table />", {
            "style": "margin-top:10px; border-collapse:collapse; background:rgba(0,0,0,0.5);",
            "align": "center",
            "cellpadding": "6"
        });
        labels.push("<th style='border-top: 1px solid #69c;'>Total</th>");
        values.push("<th style='border-top: 1px solid #69c;' class='blue'>" + nf(arraySum(todayResources)) + "</th>");
        points.push("<th style='border-top: 1px solid #69c;' class='blue'>" + nf(sumPoints) + "</th>");
        avgAttack.push("<th style='border-top: 1px solid #69c;' class='blue'>" + nf(sumAvg) + "</th>");

        var $tr = $("<tr />").html(labels.join());
        var $tr2 = $("<tr />").html(values.join());
        var $tr5 = $("<tr />").html(points.join());
        var $tr3 = $("<tr />").html(avgAttack.join());

        $table3.append($tr, $tr2, $tr5, $tr3);

        $divGraph.append($table3);

        var pageFrame = $('frame[name="CMAIN"]', top.document)[0].contentDocument;
        $(pageFrame).find(".graphContainer").remove();
        $(pageFrame).find("body").append($divGraph);

        Highcharts.chart(pageFrame.getElementById("graphAttacks"), {
            title: {
                text: 'Roubo por dia'
            },
            chart: {
                style: {
                    fontFamily: 'Verdana'
                }
            },
            xAxis: {
                categories: labelDates
            },
            yAxis: {
                min: 0,
                title: {
                    text: 'Total recursos'
                },
                stackLabels: {
                    enabled: true
                }
            },
            legend: {
                backgroundColor: Highcharts.defaultOptions.legend.backgroundColor || 'white',
                borderColor: '#CCC',
                borderWidth: 1,
                shadow: false
            },
            tooltip: {
                shared: true,
                useHTML: true,
                formatter: function () {
                    var html = "<table style='color: #000;'><tr><td colspan='3' align='center'><b>" + this.x + "</b></td></tr>";
                    var pontos = 0,
                        totalEco = 0;
                    var xx = this.x;
                    $.each(this.points, function (i, e) {
                        if (e.y > 0) {
                            var lblIdx = resourcesLabel.indexOf(e.series.name);
                            var racio = racios[lblIdx];
                            var color = resourcesColor[lblIdx];
                            html += "<tr><td align='right' style='white-space:nowrap; color:" + color + ";'>" + e.series.name + "</td><td style='white-space:nowrap;'><b>" + nf(e.y) + "</b></td><td><small>(" + nf(e.percentage, 2) + "%)</small></td></tr>";
                            pontos += e.y * racio / 1000;
                            totalEco += e.y;
                        }
                    });

                    html += "<tr><td align='right'>Total</td><td colspan='2'><b>" + nf(totalEco) + "</b></td></tr>";
                    html += "<tr><td align='right' style='white-space:nowra;'>Pontos</td><td colspan='2'><b>" + nf(pontos) + "</b></td></tr>";
                    html += "<tr><td align='right'>Ataques</td><td colspan='2'><b>" + nf(dates.filter(function (item) {
                        return item.date == xx;
                    })[0].attacks) + "</b></td></tr></table>";
                    return html;
                },
                positioner: function () {
                    return {
                        x: 50,
                        y: 70
                    };
                }
            },
            plotOptions: {
                series: {
                    stacking: 'normal',
                    marker: {
                        enabled: false
                    }
                }
            },
            series: series
        });
    }

    function getMarketGraph() {
        var marketGraph = JSON.parse(localStorage.getItem("marketGraph") || "[]");
        var resourcesLabel = ["Metal", "Diamante", "Hidrogénio", "Zion", "Nanite"];
        var resourcesColor = ["#b5b5b5", "#2a80ff", "#ff002a", "#c6d91c", "#222222"];
        var dates = [];

        var labelDates = [];
        var resourcesSent = [];
        var resourcesReceived = [];

        var todayResourcesSent = [0, 0, 0, 0, 0];
        var todayResourcesReceived = [0, 0, 0, 0, 0];
        var totalChanges = 0;

        $.each(marketGraph, function (i, e) {
            if (dates.findIndex(function (person) {
                return person.date == e.data.split(" ")[0]
            }) == -1) {
                dates.push({
                    date: e.data.split(" ")[0],
                    resourcesSent: e.resourcesSent,
                    resourcesReceived: e.resourcesReceived,
                    changes: 1
                });
                labelDates.push(e.data.split(" ")[0]);
            }
            else {
                var idx = dates.findIndex(function (person) {
                    return person.date == e.data.split(" ")[0]
                });
                for (var j = 0; j < resourcesLabel.length; j++) {
                    dates[idx].resourcesSent[j] += e.resourcesSent[j];
                }
                for (var j = 0; j < resourcesLabel.length; j++) {
                    dates[idx].resourcesReceived[j] += e.resourcesReceived[j];
                }
                dates[idx].changes += 1;
            }

            if (e.data.indexOf(moment().format("YYYY/MM/DD")) > -1) {
                totalChanges += 1;
                for (var j = 0; j < resourcesLabel.length; j++) {
                    todayResourcesSent[j] += e.resourcesSent[j];
                }
                for (var j = 0; j < resourcesLabel.length; j++) {
                    todayResourcesReceived[j] += e.resourcesReceived[j];
                }
            }
        });

        var $divGraph = $("<div />", {
            class: "graphContainer",
            "style": "position:fixed; top:0; left:0; width:100%; height:100%; background: rgba(0,0,0,0.7);"
        });
        var $closeGraph = $("<input />", {
            "type": "button",
            "class": "button",
            "style": "bottom: 50px; position:absolute;"
        }).val("Fechar").on("click", function () {
            $divGraph.remove();
        });

        var $clearGraph = $("<input />", {
            "type": "button",
            "class": "button",
            "style": "bottom: 50px; position:absolute; margin: 0 64px;"
        }).val("Limpar Gráfico").on("click", function () {
            $divGraph.remove();
            localStorage.removeItem("marketGraph");
        });

        var $graphContainer = $("<div />", {
            "id": "graphAttacks",
            "style": "width:800px; height:600px;background-color:#FFF; margin:120px auto 0px auto;"
        });

        $divGraph.append($("<center />").append($closeGraph,$clearGraph, $graphContainer));

        var resources = [0, 0, 0, 0, 0];
        var racios = [1, 2, 3, 6, 2000];

        var series = [];
        labelDates.sort();
        labelDates = labelDates.slice(-8);
        for (var k = 0; k < resourcesLabel.length; k++) {
            var obj = {
                name: resourcesLabel[k],
                data: [],
                type: 'column',
                color: resourcesColor[k],
                id: 'resource' + (k)
            };
            for (var i = 0; i < labelDates.length; i++) {
                var _resources = dates.filter(function (item) {
                    return item.date == labelDates[i];
                });
                obj.data[i] = _resources[0].resourcesReceived[k];
            }
            series.push(obj);
        }
        for (var k = 0; k < resourcesLabel.length; k++) {
            var obj = {
                name: resourcesLabel[k],
                data: [],
                type: 'column',
                color: resourcesColor[k],
                id: 'resource' + (k),
                linkedTo: 'resource' + (k)
            };
            for (var i = 0; i < labelDates.length; i++) {
                var _resources = dates.filter(function (item) {
                    return item.date == labelDates[i];
                });
                obj.data[i] = _resources[0].resourcesSent[k] * -1;
            }
            series.push(obj);
        }

        var pageFrame = $('frame[name="CMAIN"]', top.document)[0].contentDocument;
        $(pageFrame).find(".graphContainer").remove();
        $(pageFrame).find("body").append($divGraph);

        Highcharts.chart(pageFrame.getElementById("graphAttacks"), {
            title: {
                text: 'Resumo de trocas'
            },
            xAxis: {
                categories: labelDates
            },
            yAxis: {
                title: {
                    text: 'Total recursos'
                },
                stackLabels: {
                    enabled: true,
                    formatter: function () {
                        var v = this.total;
                        if (v < 0) {
                            v = v * -1;
                        }
                        return nf(v);
                    }
                }
            },
            tooltip: {
                shared: true,
                useHTML: true,
                formatter: function () {
                    var html = "<table style='color:#000;'>";
                    html += "<tr><th colspan='2' align='center'>" + this.x + "</th></tr>";
                    html += "<tr><th colspan='2' align='center'>Vendido</th></tr>";
                    $.each(this.points, function (i, e) {
                        if (e.y < 0) {
                            var lblIdx = resourcesLabel.indexOf(e.series.name);
                            var racio = racios[lblIdx];
                            var color = resourcesColor[lblIdx];
                            html += "<tr><td style='color:" + color + ";'>" + e.series.name + "</td><th align='left'>" + nf(e.y * -1) + "</th></tr>";
                        }
                    });
                    html += "<tr><th colspan='2' align='center'>Comprado</th></tr>";
                    $.each(this.points, function (i, e) {
                        if (e.y > 0) {
                            var lblIdx = resourcesLabel.indexOf(e.series.name);
                            var racio = racios[lblIdx];
                            var color = resourcesColor[lblIdx];
                            html += "<tr><td style='color:" + color + ";'>" + e.series.name + "</td><th align='left'>" + nf(e.y) + "</th></tr>";
                        }
                    });
                    html += "</table>";

                    return html;
                }
            },
            credits: {
                enabled: false
            },
            plotOptions: {
                column: {
                    stacking: 'normal',
                    dataLabels: {
                        enabled: false
                    }
                }
            },
            series: series
        });
    }

    var menuEntry = $("<tr />").append($("<td />").append($("<div />", {
        class: "menuoptions"
    }).text("Gráfico Roubo")));
    var menuEntryMarket = $("<tr />").append($("<td />").append($("<div />", {
        class: "menuoptions"
    }).text("Gráfico Mercado")));
    var url = window.location.href;
    if (url.indexOf("menu.php") > -1) {
        $("table.menutable").append(menuEntry);
        $("table.menutable").append(menuEntryMarket);

        var pageFrame = $('frame[name="CMAIN"]', top.document)[0].contentDocument;

        menuEntry.on("click", function () {
            getGraph();
        });

        menuEntryMarket.on("click", function () {
            getMarketGraph();
        });
    }

})();