MediaWiki:Gadget-SvtNpGetTop5.js

来自Mooncell - 玩家共同构筑的FGO中文Wiki
跳到导航 跳到搜索

注意:在保存之后,您可能需要清除浏览器缓存才能看到所作出的变更的影响。

  • Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5Ctrl-R(Mac为⌘-R
  • Google Chrome:Ctrl-Shift-R(Mac为⌘-Shift-R
  • Internet Explorer:按住Ctrl的同时单击刷新,或按Ctrl-F5
  • Opera:前往菜单 → 历史(Mac为Opera → Preferences),或按Ctrl-Shift-Del,然后清除浏览数据 → 勾选“已缓存的图片和文件” → 清除数据
/*
放弃移植
https://greasyfork.org/zh-CN/scripts/388555-fgo-wiki%E4%BB%8E%E8%80%85np%E8%8E%B7%E5%8F%96%E7%8E%87top5%E6%98%BE%E7%A4%BA-for-mooncell/code

var jQ1 = jQuery.noConflict();
var Global_wiki = {};
jQ1(function () {
    'use strict';
    var no = parseInt(jQ1(".wikitable.nomobile th:contains('No.')").text().replace("No.", ""));

    if (isNaN(no)) {
        console.log('【${no}】不是数字'.replace('${no}',no));
        return;
    }
    var isOK = loadNpData(no);
    if (!isOK) {
        console.log("nps.json文件未更新");
        return;
    };
    var optionsHtml = "<tr class='trCalcBox' data-show='0'><td colspan='12'><div class='calcBox'><ul><li>BUFF</li><li>NP获得提升(%):<input type='number' id='txtNpBuff' value='0'>蓝魔放(%):<input type='number' id='txtArtsBuff' value='0'>绿魔放(%):<input type='number' id='txtQuickBuff' value='0'><label for='ckSpecialSkill1'><input id='ckSpecialSkill1' type='checkbox'>第五势</label></li></ul><ul><li>首卡</li><li><label for='ckIsOverkill_first'><input id='ckIsOverkill_first' type='checkbox'>鞭尸</label></li><li><label for='ckIsCritical_first'><input id='ckIsCritical_first' type='checkbox'>暴击</label></li></ul><ul><li>次卡</li><li><label for='ckIsOverkill_second'><input id='ckIsOverkill_second' type='checkbox'>鞭尸</label></li><li><label for='ckIsCritical_second'><input id='ckIsCritical_second' type='checkbox'>暴击</label></li></ul><ul><li>尾卡</li><li><label for='ckIsOverkill_third'><input id='ckIsOverkill_third' type='checkbox'>鞭尸</label></li><li><label for='ckIsCritical_third'><input id='ckIsCritical_third' type='checkbox'>暴击</label></li></ul><ul><li>EX</li><li><label for='ckIsOverkill_ex'><input id='ckIsOverkill_ex' type='checkbox'>鞭尸</label></li></ul><ul class='treasureHit'><li>宝具Hit数:<input type='number' id='txtTreasureHit' value='0'><label for='ckIsOverkill_treasure'><input id='ckIsOverkill_treasure' type='checkbox'>鞭尸</label>宝具NP回收率(%):<span id='spanTreasureNP'>0</span><label for='ckIsIgnoreTreasure'><input id='ckIsIgnoreTreasure' type='checkbox'>忽略宝具组合</label></li></ul></div></td></tr>";

    var cardBox = $(".wikitable.nomobile th:contains('配卡')").next();
    var tmpNpObj = Global_wiki.tmpNpObj;
    var npObj = {
        no: no,
        arts: {
            hit: tmpNpObj.ah,
            num: cardBox.find("img[src*=Arts]").length,
            np: tmpNpObj.anp
        },
        buster: {
            hit: tmpNpObj.bh,
            num: cardBox.find("img[src*=Buster]").length,
            np: tmpNpObj.bnp
        },
        quick: {
            hit: tmpNpObj.qh,
            num: cardBox.find("img[src*=Quick]").length,
            np: tmpNpObj.qnp
        },
        ex: {
            hit: tmpNpObj.exh,
            np: tmpNpObj.exnp
        },
        treasure: {
            hit: tmpNpObj.h,
            np: tmpNpObj.np,
            card: tmpNpObj.t
        },
        careerSkill: {
            artsBuff: tmpNpObj.a,
            quickBuff: tmpNpObj.q
        }
    };
    Global_wiki.npObj = npObj;
    var tempArr = ["宝"],
        a = npObj.arts,
        b = npObj.buster,
        q = npObj.quick;

    for (var i = 0; i < a.num; i++) {
        tempArr.push("A");
    }
    for (var i = 0; i < b.num; i++) {
        tempArr.push("B");
    }
    for (var i = 0; i < q.num; i++) {
        tempArr.push("Q");
    }

    var tempArr1 = tempArr,
        tempArr2 = tempArr.slice(0),
        tempArr3 = tempArr.slice(0),
        cardArr = [];

    tempArr1.forEach(function (a1, i) {
        //i≠j≠k
        tempArr2.forEach(function (b1, j) {
            tempArr3.forEach(function (q1, k) {
                if (i != j && i != k && j != k) cardArr.push(a1 + b1 + q1);
            });
        });
    });
    //总共42或34种组合(去重后)
    cardArr = Array.from(new Set(cardArr));
    Global_wiki.cardArr = cardArr;

    var npArr = [];
    cardArr.forEach(function (res) {
        // abq
        npArr.push(calcCardNp(res));
    });

    npArr = npArr.sort(compare("totalNp"));
    var parent = jQ1(".wikitable.nomobile th:contains('配卡')").parent().parent(),
        head = jQ1("<tr><td colspan='8' style='background-color:#e6eaeb'>NP获取率TOP<span class='spanTopTimes'>5</span>(敌补正为<span class='spanEnemyCorrections'>1</span>)</td></tr>"),
        contenHtml = "<tr><td colspan='8' class='calcResult'>",
        img = jQ1('<i class="fa-calculator fas btnCalc" style="font-size: 16px;"></i>');
    parent.append(head);
    img.css("width", "27px");
    head.children("td").append(img);
    for (var i = 0; i < npArr.length; i++) {
        var tnpObj = npArr[i],
            cardStr = tnpObj.cardStr;
        if (!cardStr.includes("宝")) cardStr = "&nbsp;" + cardStr;
        if (i == 5) break;
        contenHtml += getContentHtml(cardStr, tnpObj);
    }
    contenHtml += "</td></tr>";
    head.after(contenHtml);
    head.after(optionsHtml);

    //设置默认值
    jQ1("#txtTreasureHit").val(npObj.treasure.hit);
    jQ1("#txtArtsBuff").val(npObj.careerSkill.artsBuff);
    jQ1("#txtQuickBuff").val(npObj.careerSkill.quickBuff);
    jQ1("#spanTreasureNP").text(calcTreasureNP(npObj.treasure.card));

    //追加样式
    jQ1(".trCalcBox").css({
        "display": "none"
    });
    jQ1(".calcBox").css({
        "height": "150px",
        "margin": "0 auto",
        "text-align": "left",
        "padding": "10px 0 0 30px"
    });
    jQ1(".calcBox>ul,.calcBox input[type=checkbox]").css({
        "list-style": "none",
        "margin": "0",
        "padding": "0"
    });
    jQ1(".calcBox input[type=number]").css({
        "text-align": "center"
    });
    jQ1(".calcBox>ul:not(:nth-child(1))").css({
        "float": "left",
        "width": "125px"
    });
    jQ1(".calcBox>ul:last-child").css({
        "clear": "both",
        "width": "100%"
    });
    jQ1(".calcBox>ul>li:not(:nth-child(1))").css({
        "padding-left": "30px"
    });
    jQ1(".calcBox input").css({
        "vertical-align": "middle"
    });
    jQ1(".calcBox input[type=number]").css({
        "width": "50px"
    });
    setFixWidth();

    if (no != "153") { //武藏
        jQ1(".calcBox label[for=ckSpecialSkill1]").hide();
    }
    //设置点击计算器图标事件
    jQ1(".btnCalc").click(function () {
        var show = jQ1(".trCalcBox").data("show");
        if (show == "0") { //原本隐藏状态,现在要显示
            jQ1(".trCalcBox").show();
            jQ1(".spanTopTimes").html(" <input type='number' id='txtTopTimes' value='5'/>");
            jQ1(".spanEnemyCorrections").html(" <input type='number' id='txtEnemyCorrections'value='1'/>");
            jQ1("#txtTopTimes,#txtEnemyCorrections").bind("input propertychange",
                function () {
                    reCalc();
                });
            jQ1("#txtTopTimes,#txtEnemyCorrections").css({
                "color": "#000",
                "width": "50px",
                "text-align": "center"
            });
            var treasureHit = Global_wiki.npObj.treasure.hit;
            jQ1("#txtTreasureHit").val(treasureHit);

        } else { //原本显示状态,现在要隐藏
            jQ1(".trCalcBox").hide();
            jQ1("#txtNpBuff").val("0");
            jQ1("#txtTreasureHit").val(Global_wiki.npObj.treasure.hit); //恢复宝具Hit数默认值
            jQ1("#txtArtsBuff").val(Global_wiki.npObj.careerSkill.artsBuff); //恢复被动蓝卡BUFF
            jQ1("#txtQuickBuff").val(Global_wiki.npObj.careerSkill.quickBuff); //恢复被动绿卡BUFF
            jQ1(".calcBox input[type=checkbox]").prop("checked", false);
            jQ1(".spanEnemyCorrections").html("1");
            jQ1(".spanTopTimes").html("5");
            reCalc();

        }
        jQ1(".trCalcBox").data("show", show == "0" ? "1" : "0");

    });

    //绑定【NP获得提升】、【蓝魔放】、【绿魔放】输入内容改变事件
    jQ1(".calcBox input[type=number]").bind("input propertychange",
        function () {
            reCalc();
        });

    //绑定【第五势】勾选状态切换事件
    jQ1("#ckSpecialSkill1").change(function () {
        var checked = jQ1("#ckSpecialSkill1").prop("checked");
        if (checked) {
            Global_wiki.npObj.arts.hit *= 2;
            Global_wiki.npObj.buster.hit *= 2;
            Global_wiki.npObj.quick.hit *= 2;
            Global_wiki.npObj.ex.hit *= 2;
        } else {
            Global_wiki.npObj.arts.hit = parseInt(jQ1(".ArtHit").text());
            Global_wiki.npObj.buster.hit = parseInt(jQ1(".BusterHit").text());
            Global_wiki.npObj.quick.hit = parseInt(jQ1(".QuickHit").text());
            Global_wiki.npObj.ex.hit = parseInt(jQ1(".ExtraHit").text());
        }
        reCalc();
    });

    //绑定【鞭尸】、【暴击】、【忽略宝具组合】勾选状态切换事件
    jQ1(".calcBox input[type=checkbox]:not(#ckSpecialSkill1)").change(function () {
        reCalc();
    });

});


function setFixWidth() {
    jQ1(".fixWidth").css({
        "display": "inline-block",
        "width": "120px",
        "text-align": "left"
    });
}

function getContentHtml(cardStr, npObj) {
    return "<span class='fixWidth'>${cardStr}+EX:</span> <span class='fixWidth'>首卡:${npObj.first}</span> <span class='fixWidth'>次卡:${npObj.second}</span> <span class='fixWidth'>尾卡:${npObj.third}</span><span class='fixWidth'> EX:${npObj.ex} </span><span class='fixWidth'>总计:${npObj.totalNp}</span><br>".replace('${cardStr}', cardStr).replace('${npObj.first}', npObj.first).replace('${npObj.second}', npObj.second).replace('${npObj.third}', npObj.third).replace('${npObj.ex}', npObj.ex).replace('${npObj.totalNp}',npObj.totalNp);
}

function reCalc() {
    'use strict';
    var cardArr = Global_wiki.cardArr;
    var npArr = [];
    cardArr.forEach(function (res) {
        // abq
        if (!(jQ1("#ckIsIgnoreTreasure").prop("checked") && res.includes("宝"))) {
            var npObj = calcCardNp(res);
            npArr.push(npObj);
        }
    });
    npArr = npArr.sort(compare("totalNp"));
    jQ1(".calcResult").empty();

    var contenHtml = "";
    for (var i = 0; i < npArr.length; i++) {
        var npObj = npArr[i],
            cardStr = npObj.cardStr;
        if (!cardStr.includes("宝")) cardStr = "&nbsp;" + cardStr;
        var topTimes = jQ1("#txtTopTimes").val();
        topTimes = isNaN(topTimes) ? 5 : topTimes;
        if (i == topTimes) break;
        contenHtml += getContentHtml(cardStr, npObj);
    }
    var t = Global_wiki.npObj.treasure,
        treasureNP = calcTreasureNP(t.card);
    jQ1("#spanTreasureNP").text(treasureNP);
    jQ1(".calcResult").html(contenHtml);
    setFixWidth();
}
function loadNpData(no) {
    'use strict';
    var isOk = false;
    jQ1.ajaxSettings.async = false; //同步执行
    jQ1.getJSON('https://xianlechuanshuo.github.io/fgo/js/nps.json', {
        rd: Math.random()
    },
        function (data, textStatus) {
            if (textStatus == "success") {
                for (var i = 0; i < data.length; i++) {
                    if (data[i].n == no) {
                        Global_wiki.tmpNpObj = data[i];
                        isOk = true;
                        break;
                    }
                }
            }
        });
    jQ1.ajaxSettings.async = true; //异步执行
    return isOk;
}

function getIsOverkillAndisCritical(position) {
    'use strict';
    var ckIsOverkill_first = jQ1("#ckIsOverkill_first").prop("checked"),
        ckIsCritical_first = jQ1("#ckIsCritical_first").prop("checked"),
        ckIsOverkill_second = jQ1("#ckIsOverkill_second").prop("checked"),
        ckIsCritical_second = jQ1("#ckIsCritical_second").prop("checked"),
        ckIsOverkill_third = jQ1("#ckIsOverkill_third").prop("checked"),
        ckIsCritical_third = jQ1("#ckIsCritical_third").prop("checked"),
        ckIsOverkill_ex = jQ1("#ckIsOverkill_ex").prop("checked"),
        isOverkill = 1,
        isCritical = 1;
    switch (position) {
        case 1:
            //1位
            isOverkill = ckIsOverkill_first === true ? 1.5 : 1;
            isCritical = ckIsCritical_first === true ? 2 : 1;
            break;
        case 2:
            //2位
            isOverkill = ckIsOverkill_second === true ? 1.5 : 1;
            isCritical = ckIsCritical_second === true ? 2 : 1;
            break;
        case 3:
            //3位
            isOverkill = ckIsOverkill_third === true ? 1.5 : 1;
            isCritical = ckIsCritical_third === true ? 2 : 1;
            break;
        case 4:
            //四位EX
            isOverkill = ckIsOverkill_ex === true ? 1.5 : 1;
            break;
    }
    return {
        isOverkill: isOverkill,
        isCritical: isCritical
    };
}

function calcTreasureNP(card) {
    'use strict';
    // NP获得量 = 基本NP获得率(baseNp) × [(卡片倍率 x (1 ± 卡片性能Buff)] × (1 + NP获得量Buff)
    // × Overkill补正 × 攻击Hit数 × 敌补正(假设为1)
    // console.log("calcTreasureNP card:"+card);
    var cardObj = getTreasureDetials(card);
    // console.log(cardObj);
    var np = cardObj.baseNp * [cardObj.cardRate * (1 + cardObj.cardBuff)] * (1 + cardObj.npBuff) * cardObj.isOverkill * cardObj.hit * cardObj.enemyCorrections;

    return Math.floor(np * 100) / 100;
}

function getTreasureDetials(card) {
    var t = Global_wiki.npObj.treasure,
        c = Global_wiki.npObj.careerSkill;

    if (card == "宝") card = t.card;

    var treasureHit = jQ1("#txtTreasureHit").length === 0 ? t.hit : parseInt(jQ1("#txtTreasureHit").val()),
        artsBuff = jQ1("#txtArtsBuff").length === 0 ? c.artsBuff / 100 : parseFloat(jQ1("#txtArtsBuff").val()) / 100,
        quickBuff = jQ1("#txtQuickBuff").length === 0 ? c.quickBuff / 100 : parseFloat(jQ1("#txtQuickBuff").val()) / 100,
        cardBuff = 0,
        npBuff = jQ1("#txtNpBuff").length === 0 ? 0 : parseFloat(jQ1("#txtNpBuff").val()) / 100,
        isOverkill = jQ1("#ckIsOverkill_treasure").prop("checked") === true ? 1.5 : 1,
        enemyCorrections = jQ1("#txtEnemyCorrections").length === 0 ? 1 : parseFloat(jQ1("#txtEnemyCorrections").val()),
        cardRate = 0;
    switch (card) {
        case "A":
            cardRate = 3;
            cardBuff = artsBuff;
            break;
        case "B":
            cardRate = 0;
            break;
        case "Q":
            cardRate = 1;
            cardBuff = quickBuff;
            break;
    }

    return {
        cardRate: cardRate,
        baseNp: t.np,
        hit: treasureHit,
        cardBuff: cardBuff,
        npBuff: npBuff,
        isOverkill: isOverkill,
        enemyCorrections: enemyCorrections
    };

}

// 计算单卡NP
function calcSingleCardNp(firstCardReward, card, position) {
    'use strict';
    // NP获得量 = 基本NP获得率(baseNp) × [(首卡加成 + 卡片倍率 x (1 ± 卡片性能Buff)] × (1 + NP获得量Buff)
    // × Critical补正 × Overkill补正 × 攻击Hit数 × 敌补正(假设为1)
    var cardObj = getCardDetails(card, position);
    var np = cardObj.baseNp * [firstCardReward + cardObj.cardRate * (1 + cardObj.cardBuff)] * (1 + cardObj.npBuff) * cardObj.isCritical * cardObj.isOverkill * cardObj.hit * cardObj.enemyCorrections;

    return Math.floor(np * 100) / 100;
}

function getCardDetails(card, position) {
    'use strict';
    var cardRate = 0,
        a = Global_wiki.npObj.arts,
        b = Global_wiki.npObj.buster,
        q = Global_wiki.npObj.quick,
        e = Global_wiki.npObj.ex,
        c = Global_wiki.npObj.careerSkill,
        artsBuff = jQ1("#txtArtsBuff").length === 0 ? c.artsBuff / 100 : parseFloat(jQ1("#txtArtsBuff").val()) / 100,
        quickBuff = jQ1("#txtQuickBuff").length === 0 ? c.quickBuff / 100 : parseFloat(jQ1("#txtQuickBuff").val()) / 100,
        npBuff = jQ1("#txtNpBuff").length === 0 ? 0 : parseFloat(jQ1("#txtNpBuff").val()) / 100,
        enemyCorrections = jQ1("#txtEnemyCorrections").length === 0 ? 1 : parseFloat(jQ1("#txtEnemyCorrections").val());
    var temp = getIsOverkillAndisCritical(position);
    switch (card) {
        case "A":
            switch (position) {
                case 1:
                    //1位A卡
                    cardRate = 3;
                    break;
                case 2:
                    //2位A卡
                    cardRate = 4.5;
                    break;
                case 3:
                    //3位A卡
                    cardRate = 6;
                    break;
            }
            return {
                cardRate: cardRate,
                baseNp: a.np,
                hit: a.hit,
                cardBuff: artsBuff,
                npBuff: npBuff,
                isOverkill: temp.isOverkill,
                isCritical: temp.isCritical,
                enemyCorrections: enemyCorrections
            };
        case "B":
            return {
                cardRate:
                    0,
                baseNp: b.np,
                hit: b.hit,
                cardBuff: 0,
                npBuff: npBuff,
                isOverkill: temp.isOverkill,
                isCritical: temp.isCritical,
                enemyCorrections: enemyCorrections
            };
        case "Q":
            switch (position) {
                case 1:
                    //1位Q卡
                    cardRate = 1;
                    break;
                case 2:
                    //2位Q卡
                    cardRate = 1.5;
                    break;
                case 3:
                    //3位Q卡
                    cardRate = 2;
                    break;
            }
            return {
                cardRate: cardRate,
                baseNp: q.np,
                hit: q.hit,
                cardBuff: quickBuff,
                npBuff: npBuff,
                isOverkill: temp.isOverkill,
                isCritical: temp.isCritical,
                enemyCorrections: enemyCorrections
            };
        case "EX":
            return {
                cardRate:
                    1,
                baseNp: e.np,
                hit: e.hit,
                cardBuff: 0,
                npBuff: npBuff,
                isOverkill: temp.isOverkill,
                isCritical: temp.isCritical,
                enemyCorrections: enemyCorrections
            };
    }
}


//从大到小排序
function compare(property) {
    'use strict';
    return function (a, b) {
        var value1 = a[property];
        var value2 = b[property];
        return value2 - value1;
    };
}

function calcCardNp(cardStr) {
    'use strict';
    var first = cardStr[0],
        second = cardStr[1],
        third = cardStr[2],
        firstCardReward = 0,
        isCritical = 1,
        isOverkill = 1,
        enemyCorrections = 1,
        ex = 0,
        totalNp = 0,
        t = Global_wiki.npObj.treasure,
        artChainBuff = 0;
    // console.log(t);
    // console.log(`cardStr:${cardStr},first:${first},second:${second},third:${third}`);
    if (first == "A" || (first == "宝" && t.card == "A")) { //首卡加成:1
        firstCardReward = 1;
    }

    if (cardStr == "AAA") artChainBuff = 20;

    var tmpSecond = second,
        tempThird = third;

    var treasureNP = calcTreasureNP("宝");

    first = first == "宝" ? treasureNP : calcSingleCardNp(firstCardReward, first, 1);
    second = second == "宝" ? treasureNP : calcSingleCardNp(firstCardReward, second, 2);
    third = third == "宝" ? treasureNP : calcSingleCardNp(firstCardReward, third, 3);

    //宝具放完NP就清光了_(:з」∠)_
    if (tmpSecond == "宝") { //A宝A,第一位A的NP清零
        first = 0;
    } else if (tempThird == "宝") { //AA宝,第一位和第二位A的NP清零
        first = 0;
        second = 0;
    }
    ex = calcSingleCardNp(firstCardReward, "EX", 4);

    // console.log(`cardStr:${cardStr},first:${first},second:${second},third:${third},artChainBuff:${artChainBuff}`);
    totalNp = Math.floor((first + second + third + ex + artChainBuff) * 100) / 100;
    return {
        cardStr: cardStr,
        first: first,
        second: second,
        third: third,
        ex: ex,
        totalNp: totalNp
    };
}
*/