Widget:Calculator/Garrison

From Granblue Fantasy Wiki
Jump to navigation Jump to search
<style>
#garrison-calculator-ui input[type=number]::-webkit-inner-spin-button {
    opacity: 1;
}

#garrison-calculator-ui input[type=number]{
    font-size: 20px;
    width: 80px;
}

#gc-ele-rdc {
    font-size: 20px;
    width: 84px;
}


select {
    text-align-last:right;
}

#garrison-calculator-ui input,
#garrison-calculator-ui .gc-total,
#gc-skill-total,
#gc-out-simple {
    text-align:right;
}

#gc-extra input {
    width:80px;
}

th.gc-hp {
    min-width:90px;
}
</style>
<style id="gc-show-ele-rdc">
td.gc-ele-rdc,
td.gc-ele-ehp,
th.gc-ele-rdc-hdr {
     display: none;
}
</style>
<div id="garrison-calculator-ui">
<table>
<tr style="vertical-align:top;">
<td rowspan="2">
<table class="wikitable" id="gc-skill-amount">
<tr><th colspan="4">Weapon Skills</th></tr>
<tr>
<th>Skill</th><th>SL</th><th>Amount</th><th>Total</th>
</tr>
<tr><th colspan="4">Small Garrison</th></tr>
<tr data-base-amt="6" id="gc-s-10">
<th rowspan="2">
<img alt="Ws skill guard 1 1.png" src="/images/thumb/b/b7/Ws_skill_guard_1_1.png/80px-Ws_skill_guard_1_1.png" decoding="async" width="80" height="80" srcset="/images/b/b7/Ws_skill_guard_1_1.png 1.5x" data-file-width="90" data-file-height="90">
</th>
<td>10</td><td><input type="number" value="0" min="0" max="10" onchange="weaponUpdate(this)"></input></td><td class="gc-total">0</td>
</tr>
<tr data-base-amt="7" id="gc-s-15">
<td>15</td><td><input type="number" value="0" min="0" max="10" onchange="weaponUpdate(this)"></input></td><td class="gc-total">0</td>
</tr>
<tr><th colspan="5">Medium Garrison</th></tr>
<tr data-base-amt="8" id="gc-m-10">
<th rowspan="3">
<img alt="Ws skill guard 1 2.png" src="/images/thumb/9/97/Ws_skill_guard_1_2.png/80px-Ws_skill_guard_1_2.png" decoding="async" width="80" height="80" srcset="/images/9/97/Ws_skill_guard_1_2.png 1.5x" data-file-width="90" data-file-height="90">
</th>
<td>10</td><td><input type="number" value="0" min="0" max="10" onchange="weaponUpdate(this)"></input></td><td class="gc-total">0</td>
</tr>
<tr data-base-amt="10" id="gc-m-15">
<td>15</td><td><input type="number" value="0" min="0" max="10" onchange="weaponUpdate(this)"></input></td><td class="gc-total">0</td>
</tr>
<tr data-base-amt="11" id="gc-m-20">
<td>20</td><td><input type="number" value="0" min="0" max="10" onchange="weaponUpdate(this)"></input></td><td class="gc-total">0</td>
</tr>
<tr><th colspan="5">Big Garrison</th></tr>
<tr data-base-amt="10" id="gc-b-10">
<th rowspan="3">
<img alt="Ws skill guard 1 3.png" src="/images/thumb/c/ce/Ws_skill_guard_1_3.png/80px-Ws_skill_guard_1_3.png" decoding="async" width="80" height="80" srcset="/images/c/ce/Ws_skill_guard_1_3.png 1.5x" data-file-width="90" data-file-height="90">
</th>
<td>10</td><td><input type="number" value="0" min="0" max="10" onchange="weaponUpdate(this)"></input></td><td class="gc-total">0</td>
</tr>
<tr data-base-amt="12.5" id="gc-b-15">
<td>15</td><td><input type="number" value="0" min="0" max="10" onchange="weaponUpdate(this)"></input></td><td class="gc-total">0</td>
</tr>
<tr data-base-amt="15" id="gc-s-20">
<td>20</td><td><input type="number" value="0" min="0" max="10" onchange="weaponUpdate(this)"></input></td><td class="gc-total">0</td>
</tr>
<tr><th colspan="3">Overall</th><td id="gc-skill-total">0</td></tr>
</table>
<table id="gc-extra" class="wikitable">
<tr><th colspan="3">Extra</th></tr>
<tr>
<th>
<img alt="Ws skill stance 4.png" src="/images/thumb/a/a0/Ws_skill_stance_4.png/25px-Ws_skill_stance_4.png" decoding="async" width="25" height="25" srcset="/images/thumb/a/a0/Ws_skill_stance_4.png/38px-Ws_skill_stance_4.png 1.5x, /images/thumb/a/a0/Ws_skill_stance_4.png/50px-Ws_skill_stance_4.png 2x" data-file-width="90" data-file-height="90">
</th>
<th>HP</th>
<td>
<input id="gc-max-hp" type="number" step="1000" value="100" min="100" onchange="updateExtra(this)"></input>
</td>
</tr>
<tr>
<th>
<img alt="Status Shield.png" src="/images/thumb/7/75/Status_Shield.png/25px-Status_Shield.png" decoding="async" width="25" height="25" srcset="/images/thumb/7/75/Status_Shield.png/38px-Status_Shield.png 1.5x, /images/thumb/7/75/Status_Shield.png/50px-Status_Shield.png 2x" data-file-width="64" data-file-height="64">
</th>
<th>Shield</th>
<td>
<input id="gc-shield" type="number" step="100" value="0" min="0" onchange="updateExtra(this)"></input>
</td>
</tr>
<tr>
<th>
<img alt="Status DefenseUp.png" src="/images/thumb/5/56/Status_DefenseUp.png/25px-Status_DefenseUp.png" decoding="async" width="25" height="25" srcset="/images/thumb/5/56/Status_DefenseUp.png/38px-Status_DefenseUp.png 1.5x, /images/thumb/5/56/Status_DefenseUp.png/50px-Status_DefenseUp.png 2x" data-file-width="64" data-file-height="64">
</th>
<th>DEF Up</th>
<td>
<input id="gc-def" type="number" step="5" value="0" min="-99" onchange="updateExtra(this)"></input> %</td>
</tr>
<tr>
<th>
<img alt="Ws skill damage red 4.png" src="/images/thumb/b/b0/Ws_skill_damage_red_4.png/25px-Ws_skill_damage_red_4.png" decoding="async" width="25" height="25" srcset="/images/thumb/b/b0/Ws_skill_damage_red_4.png/38px-Ws_skill_damage_red_4.png 1.5x, /images/thumb/b/b0/Ws_skill_damage_red_4.png/50px-Ws_skill_damage_red_4.png 2x" data-file-width="86" data-file-height="86">
</th>
<th><span class="tooltip">Ele Rdc<span class="tooltiptext">Elemental Reduction<hr>There are many sources of Elemental Reduction but this should only be used for Elemental Reductions from the weapon skills</span></span></th></th>
<td>

<select id="gc-ele-rdc" onchange="updateEleRdc(this)">
<optgroup label="Standard">
<option value="0">0</option>
</optgroup>
<optgroup label="Rose Barrier / Qilin Weapons  [10 / 15 / 20]">
<option value="10">10</option>
<option value="15">15</option>
<option value="17.5">17.5</option>
</optgroup>
<optgroup label="Rose Bud Weapons  [10]">
<option value="20">20</option>
</optgroup>
<optgroup label="Draconic Weapons [15 / 20]">
<option value="25">25</option>
<option value="30">30</option>
</optgroup>
<optgroup label="Others" style="height:70px;">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="16">16</option>
<option value="17">17</option>
<option value="18">18</option>
<option value="19">19</option>
<option value="21">21</option>
<option value="22">22</option>
<option value="23">23</option>
<option value="24">24</option>
<option value="26">26</option>
<option value="27">27</option>
<option value="28">28</option>
<option value="29">29</option>
</optgroup>
</select> %
</td>
<tr><th colspan="3"><button onclick="generateCharts()">Generate Charts!</button></th></tr>
</table>
</td>
<td>
<table class="wikitable" id="gc-summon-amount">
<tr><th colspan="3">Active Summons</th></tr>
<tr>
<th>Summon 1</th>
<th>Summon 2</th>
<th>Aura</th>
</tr>
<tr>
<td class="gc-summon" data-amt="150">
<img style="opacity:1" onclick="summonSelect(this)" data-base-amt="150" alt="Summon m 2040094000_02.jpg" src="/images/e/e7/Summon_m_2040094000_02.jpg" decoding="async" width="120" height="69" data-file-width="280" data-file-height="160">
<br>
<img style="opacity:0.3" onclick="summonSelect(this)" data-base-amt="140" alt="Summon m 2040094000.jpg" src="/images/thumb/f/ff/Summon_m_2040094000.jpg/120px-Summon_m_2040094000.jpg" decoding="async" width="120" height="69" srcset="/images/thumb/f/ff/Summon_m_2040094000.jpg/180px-Summon_m_2040094000.jpg 1.5x, /images/thumb/f/ff/Summon_m_2040094000.jpg/240px-Summon_m_2040094000.jpg 2x" data-file-width="280" data-file-height="160">
<br>
<img style="opacity:0.3" onclick="summonSelect(this)" data-base-amt="130" alt="Summon m 2040269000.jpg" src="/images/thumb/5/58/Summon_m_2040269000.jpg/120px-Summon_m_2040269000.jpg" decoding="async" width="120" height="69" srcset="/images/thumb/5/58/Summon_m_2040269000.jpg/180px-Summon_m_2040269000.jpg 1.5x, /images/thumb/5/58/Summon_m_2040269000.jpg/240px-Summon_m_2040269000.jpg 2x" data-file-width="280" data-file-height="160">
<br>
<img style="opacity:0.3" onclick="summonSelect(this)" data-base-amt="0" alt="Base empty weapon small.png" src="/images/thumb/b/bc/Base_empty_weapon_small.png/120px-Base_empty_weapon_small.png" decoding="async" width="120" height="69" srcset="/images/b/bc/Base_empty_weapon_small.png 1.5x" data-file-width="140" data-file-height="80"></td>
<td class="gc-summon" data-amt="150">
<img style="opacity:1" onclick="summonSelect(this)" data-base-amt="150" alt="Summon m 2040094000_02.jpg" src="/images/e/e7/Summon_m_2040094000_02.jpg" decoding="async" width="120" height="69" data-file-width="280" data-file-height="160">
<br>
<img style="opacity:0.3" onclick="summonSelect(this)" data-base-amt="140" alt="Summon m 2040094000.jpg" src="/images/thumb/f/ff/Summon_m_2040094000.jpg/120px-Summon_m_2040094000.jpg" decoding="async" width="120" height="69" srcset="/images/thumb/f/ff/Summon_m_2040094000.jpg/180px-Summon_m_2040094000.jpg 1.5x, /images/thumb/f/ff/Summon_m_2040094000.jpg/240px-Summon_m_2040094000.jpg 2x" data-file-width="280" data-file-height="160">
<br>
<img style="opacity:0.3" onclick="summonSelect(this)" data-base-amt="130" alt="Summon m 2040269000.jpg" src="/images/thumb/5/58/Summon_m_2040269000.jpg/120px-Summon_m_2040269000.jpg" decoding="async" width="120" height="69" srcset="/images/thumb/5/58/Summon_m_2040269000.jpg/180px-Summon_m_2040269000.jpg 1.5x, /images/thumb/5/58/Summon_m_2040269000.jpg/240px-Summon_m_2040269000.jpg 2x" data-file-width="280" data-file-height="160">
<br>
<img style="opacity:0.3" onclick="summonSelect(this)" data-base-amt="0" alt="Base empty weapon small.png" src="/images/thumb/b/bc/Base_empty_weapon_small.png/120px-Base_empty_weapon_small.png" decoding="async" width="120" height="69" srcset="/images/b/bc/Base_empty_weapon_small.png 1.5x" data-file-width="140" data-file-height="80"></td>
<td id="gc-summon-total">300%</td>
</tr>
</table>
</td>
</tr>
<tr style="vertical-align:top;"><td><table id="gc-out-simple" class="wikitable">
<tr>
<th colspan="2">HP</th>
<th>DEF</th>
<th><span class="tooltip">Rdc<span class="tooltiptext">Reduction<hr>Incoming damage can be reduced by this amount if it does not ignore defense.</span></span></th>
<th class="gc-ele-rdc-hdr">+ <span class="tooltip">ER<span class="tooltiptext">Elemental Reduction<hr>Overall Reduction after applying Weapon Elemental Reduction</span></span></th>
<th><span class="tooltip">eHP<span class="tooltiptext">Effective HP<hr>eHP is what you get if you treat the defense and shield values as HP</span></span></th>
<th class="gc-ele-rdc-hdr">+ <span class="tooltip">ER<span class="tooltiptext">Elemental Reduction<hr>Overall eHP after applying Weapon Elemental Reduction</span></span></th>
</tr>
<tr class="gc-result" data-hp="100"><th class="gc-hp">100</th><th>100%</th><td class="gc-def">0%</td><td class="gc-rdc">0%</td><td class="gc-ele-rdc">0%</td><td class="gc-ehp">100</td><td class="gc-ele-ehp">100</td></tr>
<tr class="gc-result" data-hp="90"><th class="gc-hp">90</th><th>90%</th><td class="gc-def">0%</td><td class="gc-rdc">0%</td><td class="gc-ele-rdc">0%</td><td class="gc-ehp">90</td><td class="gc-ele-ehp">90</td></tr>
<tr class="gc-result" data-hp="75"><th class="gc-hp">75</th><th>75%</th><td class="gc-def">0%</td><td class="gc-rdc">0%</td><td class="gc-ele-rdc">0%</td><td class="gc-ehp">75</td><td class="gc-ele-ehp">75</td></tr>
<tr class="gc-result" data-hp="60"><th class="gc-hp">60</th><th>60%</th><td class="gc-def">0%</td><td class="gc-rdc">0%</td><td class="gc-ele-rdc">0%</td><td class="gc-ehp">60</td><td class="gc-ele-ehp">60</td></tr>
<tr class="gc-result" data-hp="50"><th class="gc-hp">50</th><th>50%</th><td class="gc-def">0%</td><td class="gc-rdc">0%</td><td class="gc-ele-rdc">0%</td><td class="gc-ehp">50</td><td class="gc-ele-ehp">50</td></tr>
<tr class="gc-result" data-hp="40"><th class="gc-hp">40</th><th>40%</th><td class="gc-def">0%</td><td class="gc-rdc">0%</td><td class="gc-ele-rdc">0%</td><td class="gc-ehp">40</td><td class="gc-ele-ehp">40</td></tr>
<tr class="gc-result" data-hp="25"><th class="gc-hp">25</th><th>25%</th><td class="gc-def">0%</td><td class="gc-rdc">0%</td><td class="gc-ele-rdc">0%</td><td class="gc-ehp">25</td><td class="gc-ele-ehp">25</td></tr>
<tr class="gc-result" data-hp="10"><th class="gc-hp">10</th><th>10%</th><td class="gc-def">0%</td><td class="gc-rdc">0%</td><td class="gc-ele-rdc">0%</td><td class="gc-ehp">10</td><td class="gc-ele-ehp">10</td></tr>
<tr class="gc-result" data-hp="1"><th class="gc-hp">1</th><th>1%</th><td class="gc-def">0%</td><td class="gc-rdc">0%</td><td class="gc-ele-rdc">0%</td><td class="gc-ehp">1</td><td class="gc-ele-ehp">1</td></tr>
</table></td></tr>
</table>
</div>
<br>
<h3>Generated Charts (Requires NVD3JS)</h3>
<div id="gc-chart-output">
</div>

<script type="application/javascript">
const hpMod = [3,2.989701,2.978808,2.967327,2.9552639999999997,2.942625,2.929416,2.9156429999999998,2.901312,2.886429,2.871,2.855031,2.838528,2.821497,2.803944,2.785875,2.767296,2.748213,2.728632,2.708559,2.688,2.666961,2.645448,2.623467,2.601024,2.578125,2.554776,2.530983,2.506752,2.4820889999999998,2.457,2.431491,2.4055679999999997,2.379237,2.3525039999999997,2.325375,2.297856,2.269953,2.241672,2.213019,2.1839999999999997,2.154621,2.1248880000000003,2.0948070000000003,2.064384,2.0336250000000002,2.002536,1.971123,1.939392,1.907349,1.875,1.842351,1.809408,1.776177,1.742664,1.708875,1.6748159999999999,1.6404930000000002,1.6059120000000002,1.5710790000000001,1.536,1.5006810000000002,1.465128,1.429347,1.393344,1.357125,1.3206959999999999,1.284063,1.247232,1.210209,1.1730000000000003,1.1356110000000001,1.0980480000000001,1.0603170000000002,1.022424,0.984375,0.946176,0.9078329999999999,0.8693519999999999,0.8307389999999999,0.7919999999999998,0.7531409999999998,0.7141680000000001,0.6750870000000001,0.6359040000000001,0.5966250000000001,0.5572560000000001,0.517803,0.478272,0.4386689999999999,0.3989999999999999,0.3592709999999999,0.3194879999999998,0.2796569999999998,0.23978400000000022,0.19987500000000016,0.15993600000000013,0.11997300000000011,0.07999200000000008,0.039999000000000035,0],
hpPercent = "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100";
function getCalculatorState() {
    var state = ['','','','','',''];
    var dom = document.querySelector("#garrison-calculator-ui");
    for(var i of dom.querySelectorAll("#gc-skill-amount input")) {
        state[0] += i.value >= 10 ? 'a' : i.value;
    }
    for(var i of dom.querySelectorAll("#gc-summon-amount .gc-summon")) {
        switch (i.dataset.amt) {
            case '150': state[1] += '0'; break;
            case '140': state[1] += '1'; break;
            case '130': state[1] += '2'; break;
            default:  state[1] += '3'; break;
        } 
    }
    var ids = ['#gc-max-hp', '#gc-shield', '#gc-def', '#gc-ele-rdc'];
    for(var i in ids) {
        state[2+parseInt(i)] = dom.querySelector(ids[i]).value;
    }
    
    return '#'+state.join(';');
}

function updateOutput() {
     var dom = document.querySelector('div#garrison-calculator-ui'),
         garMod = parseFloat(dom.querySelector('#gc-skill-total').innerText),
         summon = 1 + (parseInt(dom.querySelector('#gc-summon-total').innerText)/100),
         maxHp  = parseInt(dom.querySelector('input#gc-max-hp').value),
         shield = parseInt(dom.querySelector('input#gc-shield').value),
         defUp  = parseInt(dom.querySelector('input#gc-def').value),
         eleRdc = parseFloat(dom.querySelector('select#gc-ele-rdc').value);

     for (var res of dom.querySelectorAll('table#gc-out-simple .gc-result')) {
          var  hpr = parseInt(res.getAttribute('data-hp')),
               gar = summon * hpMod[hpr] * garMod,
               chp = maxHp*(hpr/100);
          gar = Number.isNaN(gar) ? 0 : Math.min(400,gar);
          res.querySelector('.gc-def').innerText = (gar + defUp).toLocaleString(void 0,{maximumFractionDigits:2}) + '%';
          var er = (10000/(100+gar+defUp));
          res.querySelector('.gc-rdc').innerText = (100-er).toLocaleString(void 0,{maximumFractionDigits:2}) + '%';
          res.querySelector('.gc-ele-rdc').innerText = (100-((er*(100-eleRdc))/100)).toLocaleString(void 0,{maximumFractionDigits:2}) + '%';
          res.querySelector('.gc-hp').innerText = chp.toLocaleString(void 0,{maximumFractionDigits:0});
          res.querySelector('.gc-ehp').innerText = ((chp+shield) * (1+((gar+defUp)/100))).toLocaleString(void 0,{maximumFractionDigits:0});
          res.querySelector('.gc-ele-ehp').innerText = ((chp+shield) * (1+((gar+defUp)/100)) / (1-(eleRdc/100))).toLocaleString(void 0,{maximumFractionDigits:0});
     }    
     window.location.hash=getCalculatorState();
}

function updateEleRdc(ele, update=true) {
     if (ele.value == 0) {
          document.querySelector('style#gc-show-ele-rdc').innerHTML = `
td.gc-ele-rdc,
td.gc-ele-ehp,
th.gc-ele-rdc-hdr {
     display: none;
}`;
     } else {
          document.querySelector('style#gc-show-ele-rdc').innerHTML = '';
          if(update) updateOutput();
     }
}

function weaponUpdate(ele, update=true) {
     var v = Math.max(0,parseInt(ele.value)),
     weaps = 0,
     mods  = 0;
     for (var e of ele.parentNode.parentNode.parentNode.querySelectorAll('input')) {
          weaps += parseInt(e.value);
     }
     v = Math.min(10-(weaps-v),v);
     ele.value = v;
     var boost = parseFloat(ele.parentNode.parentNode.getAttribute('data-base-amt')) * v;
     ele.parentNode.nextElementSibling.innerText = boost.toLocaleString(void 0,{maximumFractionDigits:2});
     for (var e of ele.parentNode.parentNode.parentNode.querySelectorAll('#gc-skill-amount input')) {
          mods  += parseFloat(e.parentNode.nextElementSibling.innerText);
     }
     ele.parentNode.parentNode.parentNode.querySelector('#gc-skill-total').innerText = mods.toLocaleString(void 0,{maximumFractionDigits:2});
     if(update) updateOutput();
}

function summonSelect(ele, update=true) {
     for (var e of ele.parentNode.querySelectorAll('img')) {
          e.style.opacity=0.3;
     }
     ele.style.opacity=1;
     ele.parentNode.setAttribute('data-amt',ele.getAttribute('data-base-amt'));
     var amt=0;
     for (var e of ele.parentNode.parentNode.querySelectorAll('.gc-summon')) {
          amt += parseInt(e.getAttribute('data-amt'));
     }
     ele.parentNode.parentNode.querySelector('#gc-summon-total').innerText = amt + '%';
     if(update) updateOutput();
}

function updateExtra(ele, update=true) {
     ele.value = Math.max(parseInt(ele.getAttribute('min')), parseInt(ele.value));
     if(update) updateOutput();
}

function seriesTemplate(type, x, y, disable = false) {
     return `<span
      data-series-label="${type}"
      data-series-color=""
      data-series-area="no"
      data-series-x="${x}"
      data-series-y="${y}"
      data-series-linear-interpolation=""
      data-series-interpolation-step=""
      data-series-disabled="${disable ? 'yes' : ''}"
     >${type} Graph</span>`;
}
function seriesBaseHPTemplate(maxHP) {
     return `<span
      data-series-label="Base HP"
      data-series-color="black"
      data-series-area="yes"
      data-series-x=""
      data-series-y=""
      data-series-linear-interpolation="0 0 100 ${maxHP}"
      data-series-interpolation-step=""
      data-series-disabled=""
     >Base HP Graph</span>`;
}

function chartTemplate(type, data) {
     return `<div
      data-nvd3-chart=""
      data-chart="line"
      data-axis-label-x="HP"
      data-axis-label-y="${type}"
      data-chart-width="720px"
      data-chart-height="480px"
      data-x-number-format=",d"
      data-y-number-format=",.2f"
      data-y-axis-width="100px"
      data-x-grid=""
      data-y-grid=""
     ><span class="alt-text">${type} Chart</span>${data}</div>`;
}

function generateCharts() {
     var dom = document.querySelector('div#garrison-calculator-ui'),
         garMod = parseFloat(dom.querySelector('#gc-skill-total').innerText),
         summon = 1 + (parseInt(dom.querySelector('#gc-summon-total').innerText)/100),
         maxHp  = parseInt(dom.querySelector('input#gc-max-hp').value),
         shield = parseInt(dom.querySelector('input#gc-shield').value),
         defUp  = parseInt(dom.querySelector('input#gc-def').value),
         eleRdc = parseFloat(dom.querySelector('select#gc-ele-rdc').value);

     var x = [], garData = [], defData = [], ehpData = [], shieldData = [], reducData = [], reducDefData = [], allData = [], allEhpData = [];
     for (var i=0;i<101;i++) {
          x.push(parseInt(maxHp*i/100));
          var gar = summon * hpMod[i] * garMod;
          gar = Number.isNaN(gar) ? 0 : Math.min(400,gar);
          garData.push(gar);
          reducDefData.push((100-(10000/(100+gar))).toFixed(3));
          reducData.push((100-(10000/(100+gar+defUp))).toFixed(3));
          defData.push((x[i] * (1+(gar/100))).toFixed(3));
          ehpData.push((x[i] * (1+((gar+defUp)/100))).toFixed(3));
          allData.push((100 - ((100-eleRdc) / ((100 + defUp + gar)/100))).toFixed(3));
          allEhpData.push(((x[i]) * (1+((gar+defUp)/100)) / (1-(eleRdc/100))).toFixed(3));

          if (i > 0 )
               shieldData.push(((x[i]+shield) * (1+((gar+defUp)/100)) / (1-(eleRdc/100))).toFixed(3));
          else
               shieldData.push(0);
     }
     var hps = x.join(',');

     var defSeries = seriesTemplate('DEF (Pure Garrison)', hps, garData.join(','), true)
                   + seriesTemplate('DMG Reduction (Pure Garrison)', hps, reducDefData.join(','));
     if ( defUp > 0 ) { defSeries += seriesTemplate('DMG Reduction (Garrison & DEF)', hps, reducData.join(',')); }
     if ( eleRdc > 0 ) { defSeries += seriesTemplate('DMG Reduction (Garrison & DEF & ER)', hps, allData.join(',')); }
     var defChart = chartTemplate('( % )', defSeries);
     var eHpSeries = seriesTemplate('Pure Garrison', hpPercent, defData.join(','));
     if ( defUp > 0 ) { eHpSeries += seriesTemplate('Garrison & DEF', hpPercent, ehpData.join(',')); }
     if ( eleRdc > 0 ) { eHpSeries += seriesTemplate('Garrison & DEF & ER', hpPercent, allEhpData.join(',')); }
     if ( shield > 0 ) { eHpSeries += seriesTemplate('Garrison & DEF & ER + Shield', hpPercent, shieldData.join(',')); }
     var eHpChart = chartTemplate('Effective HP', eHpSeries + seriesBaseHPTemplate(maxHp));

     var charts = document.querySelector('div#gc-chart-output');
     charts.innerHTML = eHpChart + "<br>" + defChart;

     RLQ.push(['jquery', function() {
          mw.loader.using('ext.cargo.nvd3', function(require) {
               for (var e of document.querySelectorAll('[data-nvd3-chart]')) {
                    processChartElement(e);
               }
          });
     }]);
}

function setCalculatorState(state) {
    // Skills (Hex character for each skill) ; Summon (Decimal (0~3)) ; HP (Decimal) ; Shield (Decimal) ; DEF (Decimal) ; Rdc (Float (0~30))
    var hash = (state.substr(1)+';;;;;').split(';');
    var dom = document.querySelector("#garrison-calculator-ui");

    var inps = dom.querySelectorAll("#gc-skill-amount input");
    for (var i=0; i<inps.length && i<hash[0].length; i++) {
        if (hash[0].charAt(i) != 'a' && Number.isNaN(parseInt(hash[0].charAt(i)))) continue;
        inps[i].value = hash[0].charAt(i) == 'a' ? 10 : hash[0].charAt(i);
        weaponUpdate(inps[i], false);
    }

    inps = dom.querySelectorAll("#gc-summon-amount .gc-summon");
    for (var i=0; i<inps.length && i<hash[1].length; i++) {
        var summs = inps[i].querySelectorAll("img");
        var parsed = parseInt(hash[1].charAt(i));
        if (Number.isNaN(parsed) || parsed >= summs.length) continue;
        summonSelect(summs[parsed], false);
    }

    if (hash[2].length > 0 && !Number.isNaN(parseInt(hash[2]))) {
        inps = dom.querySelector("#gc-max-hp");
        inps.value = hash[2];
        updateExtra(inps, false);
    }

    if (hash[3].length > 0 && !Number.isNaN(parseInt(hash[3]))) {
        inps = dom.querySelector("#gc-shield");
        inps.value = hash[3];
        updateExtra(inps, false);
    }

    if (hash[4].length > 0 && !Number.isNaN(parseInt(hash[4]))) {
        inps = dom.querySelector("#gc-def");
        inps.value = hash[4];
        updateExtra(inps, false);
    }

    inps = dom.querySelector("#gc-ele-rdc");
    if (hash[5].length > 0 && !Number.isNaN(parseFloat(hash[5])) && inps.querySelector(`option[value='${hash[5]}']`)) {
        inps.value = hash[5];
        updateEleRdc(inps, false);
    }
    updateOutput();
}

setCalculatorState(window.location.hash.replace(/\.3B/g,';'));
</script>