UJS-Ported Luck Graphs

Script will recreate the luck graphs found in the Flash version, into the UJS version

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==UserScript==
// @name         UJS-Ported Luck Graphs
// @namespace    http://tampermonkey.net/
// @version      1.0.9
// @description  Script will recreate the luck graphs found in the Flash version, into the UJS version
// @author       JustinR17
// @match        https://www.warzone.com/MultiPlayer?GameID=*
// @match        https://www.warzone.com/SinglePlayer?*
// ==/UserScript==
var hasInitiatedGraphUI = false;
var captureChanceGraph;
var armiesKilledGraph;

function checkValidInput() {
    var defendingArmies = Number(document.getElementById("defendingArmies").value);
    var luckModifier = Number(document.getElementById("luckModifier").value) / 100.0;
    var attackKillRate = Number(document.getElementById("attackKillRate").value) / 100.0;
    var defenseKillRate = Number(document.getElementById("defenseKillRate").value) / 100.0;

    if (defendingArmies < 0 || luckModifier < 0 || luckModifier > 1 || attackKillRate <= 0 || attackKillRate > 1 || defenseKillRate <= 0 || defenseKillRate > 1) {
        return false;
    } else {
        return true;
    }
}

function doCalculate() {
    if (!hasInitiatedGraphUI) {
        hasInitiatedGraphUI = true;
        initiateGraphUI();
    }
    if (checkValidInput()) {
        makeGraph();
    } else {
        alert("UJS-Ported Flash Graphs -- ENTER CORRECT INPUT!");
    }
}

function getButton() {
    return '<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#ujs_WRAnalyzeAttackDialog" id="ujs_WRAnalyzeAttackBtn">Flash Analyze Attack</button>';
}

function initiateButtonUI() {
    var wrButton = document.createElement("div");
    wrButton.innerHTML = getButton();
    var navBox = document.getElementsByClassName("navbar-nav")[0];
    navBox.prepend(wrButton);

    var el = document.getElementById("ujs_WRAnalyzeAttackBtn");
    if (el.addEventListener) {
        el.addEventListener("click", doCalculate, false);
    } else if (el.attachEvent) {
        el.attachEvent('onclick', doCalculate);
    }
}

function initiateGraphUI() {
    var wrAnalyzeWindow = document.createElement("div");
    var mainWindow = document.getElementById("ujs_Live");
    mainWindow.appendChild(wrAnalyzeWindow);
    wrAnalyzeWindow.outerHTML = getAnalyzeWindow();
    wrAnalyzeWindow.style.margin = "2%";
    wrAnalyzeWindow.style.display = "none";

    var items = document.querySelectorAll(".ujs_wrItem");
    for (var i = 0; i < items.length; i++) {
        items[i].style.color = "white";
        items[i].style.backgroundColor = "black";
    }

    var graphs = document.querySelectorAll(".ujs_wrGraph");
    for (var j = 0; j < graphs.length; j++) {
        graphs[j].style.color = "black";
        graphs[j].style.backgroundColor = "white";
    }

    var el = document.getElementById("ujs_wrCalculateBtn");
    if (el.addEventListener) {
        el.addEventListener("click", doCalculate, false);
    } else if (el.attachEvent) {
        el.attachEvent('onclick', doCalculate);
    }

    window.onkeypress = function(event) {
        if (event.keyCode == 13) {
            doCalculate();
        }
    };
}

(function() {
    'use strict';
    console.log("Running UJS Graph Script by JustinR17");
    initiateButtonUI();

    document.addEventListener("mousewheel", function(event){
        if(document.activeElement.type === "number"){
            document.activeElement.blur();
        }
    });
})();

function getXDataValues(xyDataValues) {
    var values = [];
    for (var i = 0; i < xyDataValues.length; i++) {
        values.push(xyDataValues[i].x);
    }
    return values;
}

function getYDataValues(xyDataValues) {
    var values = [];
    for (var i = 0; i < xyDataValues.length; i++) {
        values.push(xyDataValues[i].y);
    }
    return values;
}

function makeGraph() {
    var xyDataValues = getCaptureChanceData();
    var xDataValues = getXDataValues(xyDataValues);

    var captureChance = document.getElementById('ujs_CaptureChanceGraph');
    if (captureChanceGraph) {
        captureChanceGraph.destroy();
    }
    captureChanceGraph = new Chart(captureChance, {
        type: 'line',
        data: {
            labels: xDataValues,
            datasets: [
                {
                    data: xyDataValues,
                    label: "Capture Chance",
                    borderColor: "#3e95cd"
                }
            ]
        },
        xAxisId: "Number of Attacking Armies",
        yAxisId: "Percent chance of taking",
        options: {
            legend: false,
            scales: {
                yAxes: [{
                    ticks: {
                        beginAtZero: true,
                        min: 0,
                        max: 100
                    },
                    scaleLabel: {
                        display: true,
                        labelString: "Percent Chance of Taking Territory"
                    }
                }],
                xAxes: [{
                    scaleLabel: {
                        display: true,
                        labelString: "Number of Attacking Armies"
                    }
                }]
            }
        }
    });

    var xyOffenseDataValues = getAttackerArmiesKilledData();
    var xyDefenseDataValues = getDefenderArmiesKilledData();
    var xArmiesDataValues = getXDataValues(xyDefenseDataValues);

    var armiesKilled = document.getElementById('ujs_ArmiesKilledGraph');
    if (armiesKilledGraph) {
        armiesKilledGraph.destroy();
    }
    armiesKilledGraph = new Chart(armiesKilled, {
        type: 'line',
        data: {
            labels: xArmiesDataValues,
            datasets: [
                {
                    data: xyOffenseDataValues,
                    label: "Attackers Lost",
                    borderColor: "#3e95cd"
                },{
                    data: xyDefenseDataValues,
                    label: "Defenders Lost",
                    borderColor: "#8e5ea2"
                }
            ]
        },
        xAxisId: "Number of Attacking Armies",
        yAxisId: "Armies Lost",
        showLine: true,
        options: {
            scales: {
                yAxes: [{
                    ticks: {
                        beginAtZero: true,
                        min: 0,
                        max: Number(document.getElementById("defendingArmies").value)
                    },
                    scaleLabel: {
                        display: true,
                        labelString: "Armies Lost"
                    }
                }],
                xAxes: [{
                    scaleLabel: {
                        display: true,
                        labelString: "Number of Attacking Armies"
                    }
                }]
            }
        }
    });
}

function round(value, decimals) {
    return Number(Math.round(value +'e'+ decimals) +'e-'+ decimals).toFixed(decimals);
}

function attackSimulation(attackingArmies, attackKillRate, luckModifier, isWeightedRandom, defendingArmies) {
    var analysis = [];
    var total = 0;
    var squaredTotal = 0;
    var simulations = 1000.0;
    for (var i = 0; i < 1000; i++) {
        var tossSuccesses = 0;
        for (var j = 0; j < attackingArmies; j++) {
            var rng = Math.random();
            if (rng < attackKillRate) {
                tossSuccesses++;
            }
        }

        var expectedKills = attackingArmies * attackKillRate;
        var armiesKilled = tossSuccesses * luckModifier + expectedKills * (1.00 - luckModifier);

        if (isWeightedRandom) {
            armiesKilled = round(armiesKilled, 2);
        } else {
            armiesKilled = round(armiesKilled, 0);
        }
        var percentCapture;
        if (armiesKilled - defendingArmies < -1) {
            percentCapture = 0.0;
        } else if (armiesKilled > defendingArmies || armiesKilled == defendingArmies) {
            percentCapture = 100.0;
        } else {
            percentCapture = (armiesKilled % 1.0) * 100.0;
        }
        total += Number(round(percentCapture, 2));
        squaredTotal += Math.pow(tossSuccesses - expectedKills, 2);
    }
    analysis.push(total / simulations);
    analysis.push(Math.sqrt(squaredTotal / simulations));

    return analysis;
}

function getCaptureChanceData() {
    var data = [];
    var defendingArmies = Number(document.getElementById("defendingArmies").value);
    var attackKillRate = Number(document.getElementById("attackKillRate").value) / 100.0;
    var isWeightedRandom = document.getElementById("ujs_wrWRRadio").checked;
    var luckModifier = Number(document.getElementById("luckModifier").value) / 100.0;

    var pivot;
    var pivotAnalysis;
    if (luckModifier == 0) {
        pivot = Number(round(defendingArmies / attackKillRate, 0));
    } else {
        pivot = Number(round((defendingArmies - defendingArmies * (1.00 - luckModifier)) / (luckModifier * attackKillRate), 0));
    }
    pivotAnalysis = attackSimulation(pivot, attackKillRate, luckModifier, isWeightedRandom, defendingArmies);
    var spread = Number(round(pivotAnalysis[1], 0)) < 3 ? 3 : Number(round(pivotAnalysis[1], 0));

    for (var i = pivot - spread; i < pivot + spread + 1; i++) {
        var percentCapture = attackSimulation(i, attackKillRate, luckModifier, isWeightedRandom, defendingArmies);
        var temp = {x: i, y: percentCapture[0]};
        data.push(temp);
    }
    return data;
}

function getMaxTurns(defenders, attackKillRate) {
    var maxTurns = defenders / attackKillRate + 5;
    return maxTurns;
}

function getAttackerArmiesKilledData() {
    var data = [];

    var attackKillRate = Number(document.getElementById("attackKillRate").value) / 100.0;
    var defenseKillRate = Number(document.getElementById("defenseKillRate").value) / 100.0;
    var isWeightedRandom = document.getElementById("ujs_wrWRRadio").checked;

    var defenders = Number(document.getElementById("defendingArmies").value);
    var maxTurns = getMaxTurns(defenders, attackKillRate);
    var maxAttackersKilled = defenders * defenseKillRate;

    for (var i = 0; i < maxTurns; i++) {
        var armiesKilled = maxAttackersKilled;
        if (isWeightedRandom) {
            armiesKilled = round(armiesKilled, 2);
        } else {
            armiesKilled = round(armiesKilled, 0);
        }

        if (i < maxAttackersKilled) {
            armiesKilled = i;
        }
        var temp = {x: i, y: armiesKilled};
        data.push(temp);
    }

    return data;
}

function getDefenderArmiesKilledData() {
    var data = [];

    var attackKillRate = Number(document.getElementById("attackKillRate").value) / 100.0;
    var luckModifier = Number(document.getElementById("luckModifier").value) / 100.0;
    var isWeightedRandom = document.getElementById("ujs_wrWRRadio").checked;

    var defenders = Number(document.getElementById("defendingArmies").value);
    var maxTurns = getMaxTurns(defenders, attackKillRate);

    for (var i = 0; i < maxTurns; i++) {
        var defenderArmiesKilled = round(i * attackKillRate, 0) * luckModifier + i * attackKillRate * (1.00 - luckModifier);
        if (isWeightedRandom) {
            defenderArmiesKilled = round(defenderArmiesKilled, 2);
        } else {
            defenderArmiesKilled = round(defenderArmiesKilled, 0);
        }

        if (defenderArmiesKilled > defenders) {
            defenderArmiesKilled = defenders;
        }

        var temp = {x: i, y: defenderArmiesKilled};
        data.push(temp);
    }

    return data;
}

function getAnalyzeWindow() {
    return `
    <div class="modal fade" id="ujs_WRAnalyzeAttackDialog">
        <div class="modal-dialog modal-dialog-centered">
            <div class="modal-content ujs_wrItem" id="ujs_WRAnalyzeAttackDialog">
                <div class="modal-header modal-title ujs_wrItem" id="ujs_wrAnalyzeTitle">
                    Flash-Style Analyze Attack by JustinR17
                </div>
                <div class="modal-body ujs_wrItem" id="ujs_wrSettingsPanel">
                    <div class="ujs_wrItem" id="ujs_wrDefendingArmies">
                        Defending Armies:&nbsp;<input class="ujs_wrInput" type="number" min="1" step="1" id="defendingArmies" value="10">
                    </div>
                    <div class="ujs_wrItem" id="ujs_wrKillRates">
                        Attacking Kill Rate (%):&nbsp;<input class="ujs_wrInput" type="number" min="1" max ="100" step="1" id="attackKillRate" value="60"><br>
                        Defending Kill Rate (%):&nbsp;<input class="ujs_wrInput" type="number" min="1" max ="100" step="1" id="defenseKillRate" value="70"><br>
                    </div>
                    <div class="ujs_wrItem" id="ujs_wrLuckSettings">
                        Luck Modifier (%):&nbsp;<input class="ujs_wrInput" type="number" min="0" max ="100" step="1" id="luckModifier" value="16">
                    </div>
                    <div class="ujs_wrItem" id="ujs_wrRoundMode">
                        <div class="form-check-inline ujs_wrItem">
                            Rounding Mode:
                            <label class="form-check-label">
                                <input type="radio" class="form-check-input" id="ujs_wrWRRadio" name="optradio" checked>Weighted Random
                            </label>
                        </div>
                        <div class="form-check-inline ujs_wrItem">
                            <label class="form-check-label">
                                <input type="radio" class="form-check-input" id="ujs_wrSRRadio" name="optradio">Straight Round
                            </label>
                        </div>
                    </div><br>
                    <div class="ujs_wrItem" id="ujs_wrGraphContainer">
                        <div class="ujs_wrGraph" id="ujs_wrCaptureChanceContainer"
                            style="left: 10px; bottom: 10px; transform-origin: 247px -105px;  background-color: white;">
                            <br><h4 class="ujs_wrGraph"  style="text-align:center; color: black">Capture Percent Chance Graph</h4><br>
                            <canvas class="ujs_wrGraph" id="ujs_CaptureChanceGraph" width="600" height="300"></canvas>
                        </div>
                        <br>
                        <div class="ujs_wrGraph" id="ujs_wrArmiesKilledContainer"
                            style="left: 10px; bottom: 10px; transform-origin: 247px -105px; background-color: white;">
                            <br><h4 class="ujs_wrGraph" style="text-align:center; color: black">Armies Lost Graph</h4>
                            <canvas class="ujs_wrGraph" id="ujs_ArmiesKilledGraph" width="600" height="300"></canvas>
                        </div>
                    </div>
                    <div class="ujs_wrItem" id="ujs_wrCalculate" style="text-align: center; margin: 2%; display: block">
                        <button class="btn btn-primary" id="ujs_wrCalculateBtn">Recalculate</button>
                    </div>
                </div>
                <div class="modal-footer">
                    <button class="btn btn-primary" data-dismiss="modal" id="ujs_wrCloseButton" style="background-color: blue">Close</button>
                </div>
            </div>
        </div>
    </div>
    `;
}