rayanbfvr / Pokeassistant Appraisal Refiner

// ==UserScript==
// @name         Pokeassistant Appraisal Refiner
// @namespace    http://tampermonkey.net/
// @version      1.1.2
// @description  Adds a button to appraise your pokémon in order to refine the IVs possibilites.
// @author       /u/rayanbvr & /u/dm_2112
// @match        https://pokeassistant.com/main/ivcalculator*
// @grant        none
// @downloadURL https://openuserjs.org/install/rayanbfvr/Pokeassistant_Appraisal_Refiner.user.js
// @updateURL https://openuserjs.org/meta/rayanbfvr/Pokeassistant_Appraisal_Refiner.meta.js
// ==/UserScript==

// credit to reddit user /u/dm_2112 - adapted by /u/rayanbfvr
// original comment https://www.reddit.com/r/pokemongodev/comments/4zbc3b/new_update_allows_much_more_accurate_iv/d6uhvtr

(function() {
    'use strict';

   $("head").append(
        '<link ' +
        'href="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.min.css" ' +
        'rel="stylesheet" type="text/css">'
    );

    var ivs = [];
    var attack;
    var defense;
    var hp;

    var knownStat;
    var maxKnownStat = 0;

    function refineIVs() {
        var translate = {
            0: 'level',
            1: 'attack',
            2: 'defense',
            3: 'hp',
            4: 'perc'
        };

        $('#possiblecombis').children('tbody').children().each(function() {
            if ($(this).index() != 0) {
                var that = $(this);
                var thisIVs = that.children();
                var objEl = {
                    hidden: false
                };
                objEl['element'] = that;
                for (var i = 0; i < thisIVs.length; i++) {
                    objEl[translate[i]] = thisIVs[i].textContent;
                }
                ivs.push(objEl);
            }
        });
    }

    function derivatePhrase() {

        if (!isNaN(attack)) sortIVs("attack");
        if (!isNaN(defense)) sortIVs("defense");
        if (!isNaN(hp)) sortIVs("hp");

        if (isNaN(attack)) hideNegativeOptions("attack");
        if (isNaN(defense)) hideNegativeOptions("defense");
        if (isNaN(hp)) hideNegativeOptions("hp");

        if (!isNaN(attack) && !isNaN(defense) && !isNaN(hp)) {
            ivs.forEach(function(el) {
                if (el.attack !== el.defense || el.defense !== el.hp || el.attack !== el.hp) {
                    el.hidden = true;
                    el.element.hide();
                }
            });
        }

        if (!isNaN(attack) && !isNaN(defense) && isNaN(hp)) {
            ivs.forEach(function(el) {
                if (el.attack !== el.defense || el.defense === el.hp || el.attack === el.hp) {
                    el.hidden = true;
                    el.element.hide();
                }
            });
        }

        if (!isNaN(attack) && isNaN(defense) && isNaN(hp)) {
            ivs.forEach(function(el) {
                if (el.attack === el.defense || el.attack === el.hp) {
                    el.hidden = true;
                    el.element.hide();
                }
            });
        }

        if (isNaN(attack) && !isNaN(defense) && !isNaN(hp)) {
            ivs.forEach(function(el) {
                if (el.hp !== el.defense || el.defense === el.attack || el.hp === el.attack) {
                    el.hidden = true;
                    el.element.hide();
                }
            });
        }

        if (isNaN(attack) && !isNaN(defense) && isNaN(hp)) {
            ivs.forEach(function(el) {
                if (el.defense === el.attack || el.defense === el.hp) {
                    el.hidden = true;
                    el.element.hide();
                }
            });
        }

        if (!isNaN(attack) && isNaN(defense) && !isNaN(hp)) {
            ivs.forEach(function(el) {
                if (el.hp !== el.attack || el.defense === el.attack || el.defense === el.hp) {
                    el.hidden = true;
                    el.element.hide();
                }
            });
        }

        if (isNaN(attack) && isNaN(defense) && !isNaN(hp)) {
            ivs.forEach(function(el) {
                if (el.hp === el.attack || el.hp === el.defense) {
                    el.hidden = true;
                    el.element.hide();
                }
            });
        }

    }

    function sortIVs(type) {

        var arr = [];
        ivs.forEach(function(el) {
            if (!el.hidden) {
                switch (type) {
                    case "attack":
                        arr.push(parseInt(el.attack));
                        break;
                    case "defense":
                        arr.push(parseInt(el.defense));
                        break;
                    case "hp":
                        arr.push(parseInt(el.hp));
                        break;
                }
            }
        });
        var isEqual = (arr.length && arr.reduce(function(a, b) {
            return (a === b) ? a : false;
        }) === arr[0]);
        if (isEqual) knownStat = parseInt(arr[0]);
        var currentMax = arr.sort(function(a, b) {
            return a - b;
        })[arr.length - 1];
        if (maxKnownStat < currentMax) maxKnownStat = currentMax;
    }

    function hideNegativeOptions(type) {

        var valExact = knownStat;
        var maxValExact = maxKnownStat;

        if (type === "attack" || type === "defense" || type === "hp") {

            if (valExact) {
                ivs.forEach(function(el) {
                    var stat = parseFloat(el[type]);
                    if (stat === valExact || stat > valExact) {
                        el.hidden = true;
                        el.element.hide();
                    }
                });
            } else {
                ivs.forEach(function(el) {
                    var stat = parseFloat(el[type]);
                    if (stat > maxValExact) {
                        el.hidden = true;
                        el.element.hide();
                    }
                });
            }
        }
    }

    function filterIVDivs(statType, valMin, valMax) {
        ivs.forEach(function(el) {
            var elStatType;
            var elStat;
            if (statType == "perc") elStat = parseFloat(el.perc.replace('%', ''));
            else elStat = el[statType];

            if (elStat < valMin || elStat > valMax) {
                el.hidden = true;
                el.element.hide();
            }
        });
    }

    function insertAfter(referenceNode, newNode) {
        referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
    }

    function insertAppraiseBtn() {
        var refinebtn = $(".col-xs-5")[1];

        var appraisebtn = document.createElement("div");
        appraisebtn.className = "col-xs-5";
        appraisebtn.style.width = "15%";

        var input = document.createElement("input");
        input.type = "submit";
        input.name = "commit";
        input.value = "Appraise";
        input.id = "appraisebtn";
        input.className = "form-control center-block btn";

        appraisebtn.appendChild(input);

        $(appraisebtn).on('click', showOverallDialogBox);

        insertAfter(refinebtn, appraisebtn);
    }

    var dialog = document.createElement('div');
    dialog.id = "dialog";
    document.body.appendChild(dialog);

    function showOverallDialogBox() {
        refineIVs();

        $("#dialog").dialog({

            autoOpen: true,
            title: "How good is your pokémon?",
            modal: true,
            draggable: false,
            resizable: false,
            buttons: [{
                text: "0: ...It can accomplish anything!",
                click: function() {
                    processOverall(0);
                }
            }, {
                text: "1: ...You should be proud!",
                click: function() {
                    processOverall(1);
                }
            }, {
                text: "2: ...is a decent Pokemon",
                click: function() {
                    processOverall(2);
                }
            }, {
                text: "3: ...but I still like it!",
                click: function() {
                    processOverall(3);
                }
            }],
            width: "400px"
        });
        $(".ui-dialog")[0].style.position = "fixed";
        $(".ui-dialog")[0].style.zIndex = 9999;
        $(".ui-button").css("display", "block");
        $(".ui-dialog-buttonset").css("float", "none");
        $(".ui-dialog-titlebar").css("background", "#24CCAA");
        $(".ui-dialog-title").css("text-align", "center");
        $(window).resize(function() {
            $("#dialog").dialog("option", "position", {my: "center", at: "center", of: window});
        });
    }

    function showStatDialogBox(type) {

        $("#dialog").dialog({

            autoOpen: true,
            title: type.charAt(0).toUpperCase() + type.slice(1),
            modal: true,
            draggable: false,
            resizable: false,
            buttons: [{
                text: "0: ...WOW!",
                click: function() {
                    processStats(type, 0);
                }
            }, {
                text: "1: ...How exciting!",
                click: function() {
                    processStats(type, 1);
                }
            }, {
                text: "2: ...it'll get the job done.",
                click: function() {
                    processStats(type, 2);
                }
            }, {
                text: "3: ...don't point to greatness in battle.",
                click: function() {
                    processStats(type, 3);
                }
            }, {
                text: "Click here if not provided.",
                click: function() {
                    processStats(type, undefined);
                }
            }],
            width: "400px"
        });
        $(".ui-button").css("display", "block");
    }

    function processOverall(value) {
        var valMin, valMax;

        switch (value) {
            case 0:
                valMin = 80;
                valMax = 100;
                break;
            case 1:
                valMin = 65;
                valMax = 80;
                break;
            case 2:
                valMin = 50;
                valMax = 65;
                break;
            case 3:
                valMin = 0;
                valMax = 50;
                break;
        }
        filterIVDivs("perc", valMin, valMax);
        showStatDialogBox("attack");
    }

    function processStats(type, value) {
        var valMin, valMax;

        if (type === "attack" || type === "defense" || type === "hp") {
            switch (value) {
                case 0:
                    valMin = 15;
                    valMax = 15;
                    break;
                case 1:
                    valMin = 13;
                    valMax = 14;
                    break;
                case 2:
                    valMin = 8;
                    valMax = 12;
                    break;
                case 3:
                    valMin = 0;
                    valMax = 7;
                    break;

            }
            filterIVDivs(type, valMin, valMax);
        }

        switch (type) {
            case "attack":
                showStatDialogBox("defense");
                attack = value;
                break;
            case "defense":
                showStatDialogBox("hp");
                defense = value;
                break;
            case "hp":
                $("#dialog").dialog("close");
                hp = value;
                derivatePhrase();
                break;
        }
    }

    insertAppraiseBtn();
})();