refactored a bit
This commit is contained in:
parent
43cae06c07
commit
0f6455b320
@ -37,13 +37,13 @@
|
|||||||
|
|
||||||
<li>
|
<li>
|
||||||
<label for="max-equip-load">Max. Equip Load</label>
|
<label for="max-equip-load">Max. Equip Load</label>
|
||||||
<input style="max-width: 50px" class="stat" id="max-equip-load" type="number"
|
<input style="max-width: 50px" class="stat" id="max-equip-load" type="number" oninput="update()"
|
||||||
oninput="update(true)" min=0 step=0.1 value=30 name="equip-load" lang="en">
|
min=0 step=0.1 value=30 name="equip-load" lang="en">
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<label for="current-equip-load">Current Equip Load</label>
|
<label for="current-equip-load">Current Equip Load</label>
|
||||||
<input style="max-width: 50px" class="stat" id="current-equip-load" type="number"
|
<input style="max-width: 50px" class="stat" id="current-equip-load" type="number"
|
||||||
oninput="update(true)" min=0 step=0.1 value=0 name="equip-load" lang="en">
|
oninput="update()" min=0 step=0.1 value=0 name="equip-load" lang="en">
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<label for="equip-load-budget">Equip Load Budget</label>
|
<label for="equip-load-budget">Equip Load Budget</label>
|
||||||
@ -59,22 +59,21 @@
|
|||||||
|
|
||||||
<li>
|
<li>
|
||||||
<div>
|
<div>
|
||||||
<input type="radio" id="fast-roll" onclick="update(true)" name="roll-type" value=0.3>
|
<input type="radio" id="fast-roll" onclick="update()" name="roll-type" value=0.3>
|
||||||
<label for="fast-roll">Fast Roll (up to 30% equip load)</label>
|
<label for="fast-roll">Fast Roll (up to 30% equip load)</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<div>
|
<div>
|
||||||
<input type="radio" id="normal-roll" onclick="update(true)" name="roll-type" value=0.7
|
<input type="radio" id="normal-roll" onclick="update()" name="roll-type" value=0.7 checked>
|
||||||
checked>
|
|
||||||
<label for="normal-roll">Normal Roll (up to 70% equip load)</label>
|
<label for="normal-roll">Normal Roll (up to 70% equip load)</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<div>
|
<div>
|
||||||
<input type="radio" id="fat-roll" onclick="update(true)" name="roll-type" value=1.0>
|
<input type="radio" id="fat-roll" onclick="update()" name="roll-type" value=1.0>
|
||||||
<label for="fat-roll">Fat Roll (up to 100% equip load)</label>
|
<label for="fat-roll">Fat Roll (up to 100% equip load)</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
@ -87,35 +86,35 @@
|
|||||||
|
|
||||||
<li>
|
<li>
|
||||||
<div>
|
<div>
|
||||||
<input type="radio" id="sort-average" name="sorting-order" onclick="update(true)">
|
<input type="radio" id="sort-average" name="sorting-order" onclick="update()">
|
||||||
<label for="sort-average">Greatest Average Negation</label>
|
<label for="sort-average">Greatest Average Negation</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<div>
|
<div>
|
||||||
<input type="radio" id="sort-physical" name="sorting-order" onclick="update(true)">
|
<input type="radio" id="sort-physical" name="sorting-order" onclick="update()">
|
||||||
<label for="sort-physical">Greatest Physical Negation</label>
|
<label for="sort-physical">Greatest Physical Negation</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<div>
|
<div>
|
||||||
<input type="radio" id="sort-elemental" name="sorting-order" onclick="update(true)" checked>
|
<input type="radio" id="sort-elemental" name="sorting-order" onclick="update()" checked>
|
||||||
<label for="sort-elemental">Greatest Elemental Negation</label>
|
<label for="sort-elemental">Greatest Elemental Negation</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<div>
|
<div>
|
||||||
<input type="radio" id="sort-resistances" name="sorting-order" onclick="update(true)">
|
<input type="radio" id="sort-resistances" name="sorting-order" onclick="update()">
|
||||||
<label for="sort-resistances">Greatest Resistances</label>
|
<label for="sort-resistances">Greatest Resistances</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<div>
|
<div>
|
||||||
<input type="radio" id="sort-poise" name="sorting-order" onclick="update(true)">
|
<input type="radio" id="sort-poise" name="sorting-order" onclick="update()">
|
||||||
<label for="sort-poise">Greatest Poise</label>
|
<label for="sort-poise">Greatest Poise</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
@ -128,13 +127,13 @@
|
|||||||
|
|
||||||
<li>
|
<li>
|
||||||
<div>
|
<div>
|
||||||
<input type="checkbox" id="winged-crystal-tear" onchange="update(false)" disabled>
|
<input type="checkbox" id="winged-crystal-tear" onchange="update()" disabled>
|
||||||
<label for="winged-crystal-tear">Winged Crystal Tear (in mixed physick)</label>
|
<label for="winged-crystal-tear">Winged Crystal Tear (in mixed physick)</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<div>
|
<div>
|
||||||
<input type="checkbox" id="fashion" onchange="update(false)" disabled>
|
<input type="checkbox" id="fashion" onchange="update()" disabled>
|
||||||
<label for="fashion">Fashion Mode</label>
|
<label for="fashion">Fashion Mode</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
@ -153,7 +152,7 @@
|
|||||||
<div class="select">
|
<div class="select">
|
||||||
<div>
|
<div>
|
||||||
<label for="select-helmet">Helmet</label>
|
<label for="select-helmet">Helmet</label>
|
||||||
<select type="text" id="select-helmet" name="locked-items" onchange="update(true)">
|
<select type="text" id="select-helmet" name="locked-items" onchange="update()">
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -161,7 +160,7 @@
|
|||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label for="select-chestpiece">Chestpiece</label>
|
<label for="select-chestpiece">Chestpiece</label>
|
||||||
<select type="text" id="select-chestpiece" name="locked-items" onchange="update(true)">
|
<select type="text" id="select-chestpiece" name="locked-items" onchange="update()">
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -169,7 +168,7 @@
|
|||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label for="select-gauntlets">Gauntlets</label>
|
<label for="select-gauntlets">Gauntlets</label>
|
||||||
<select type=" text" id="select-gauntlets" name="locked-items" onchange="update(true)">
|
<select type=" text" id="select-gauntlets" name="locked-items" onchange="update()">
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -177,7 +176,7 @@
|
|||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label for="select-leggings">Leggings</label>
|
<label for="select-leggings">Leggings</label>
|
||||||
<select type="text" id="select-leggings" name="locked-items" onchange="update(true)">
|
<select type="text" id="select-leggings" name="locked-items" onchange="update()">
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -15,7 +15,6 @@ var helmets;
|
|||||||
var chestpieces;
|
var chestpieces;
|
||||||
var gauntlets;
|
var gauntlets;
|
||||||
var leggings;
|
var leggings;
|
||||||
var selection;
|
|
||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
// populate filter selects
|
// populate filter selects
|
||||||
@ -27,10 +26,16 @@ async function init() {
|
|||||||
update(true);
|
update(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function update(reselect) {
|
async function update() {
|
||||||
|
// remove any previous results
|
||||||
|
Array.from(document.getElementsByClassName("sort-result")).forEach(elem => elem.parentNode.removeChild(elem));
|
||||||
|
|
||||||
// clamp equip load values to reasonable values
|
// clamp equip load values to reasonable values
|
||||||
[...document.getElementsByName("equip-load")].forEach(el => el.value = Math.max(el.value, 0.0));
|
[...document.getElementsByName("equip-load")].forEach(el => el.value = Math.max(el.value, 0.0));
|
||||||
|
|
||||||
|
// update budget
|
||||||
|
let budget = equipLoadBudget();
|
||||||
|
document.getElementById("equip-load-budget").value = budget.toFixed(1);
|
||||||
let sortBy = [...document.getElementsByName("sorting-order")].find(elem => elem.checked).id;
|
let sortBy = [...document.getElementsByName("sorting-order")].find(elem => elem.checked).id;
|
||||||
|
|
||||||
// get locked items
|
// get locked items
|
||||||
@ -42,25 +47,22 @@ async function update(reselect) {
|
|||||||
.filter(item => !item.id.startsWith("no-"));
|
.filter(item => !item.id.startsWith("no-"));
|
||||||
});
|
});
|
||||||
|
|
||||||
// get budget and sorting order
|
console.log("locked items: " + lockedItems);
|
||||||
let budget = equipLoadBudget();
|
|
||||||
document.getElementById("equip-load-budget").value = budget.toFixed(1);
|
|
||||||
|
|
||||||
// if selection has changed, sort equipment again
|
|
||||||
if (reselect) {
|
|
||||||
// pre-sort and eliminate some equipment
|
// pre-sort and eliminate some equipment
|
||||||
helmets = eliminate(await HELMETS, sortBy, lockedItems);
|
helmets = eliminate(await HELMETS, sortBy, lockedItems);
|
||||||
chestpieces = eliminate(await CHESTPIECES, sortBy, lockedItems);
|
chestpieces = eliminate(await CHESTPIECES, sortBy, lockedItems);
|
||||||
gauntlets = eliminate(await GAUNTLETS, sortBy, lockedItems);
|
gauntlets = eliminate(await GAUNTLETS, sortBy, lockedItems);
|
||||||
leggings = eliminate(await LEGGINGS, sortBy, lockedItems);
|
leggings = eliminate(await LEGGINGS, sortBy, lockedItems);
|
||||||
selection = permutations(budget, lockedItems);
|
let selection = permutations(budget, lockedItems);
|
||||||
}
|
|
||||||
|
|
||||||
// find best set under budget
|
// find best sets to display
|
||||||
let best = knapSack(sortBy);
|
let best = knapSack(selection, sortBy);
|
||||||
|
|
||||||
|
console.log(best.weight);
|
||||||
|
console.log(best.fitness);
|
||||||
|
|
||||||
// show best sets under budget
|
// show best sets under budget
|
||||||
Array.from(document.getElementsByClassName("sort-result")).forEach(elem => elem.parentNode.removeChild(elem));
|
|
||||||
populateResults("sort-result", "sort-results", best);
|
populateResults("sort-result", "sort-results", best);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +80,6 @@ function eliminate(list, sortBy, lockedItems) {
|
|||||||
sorted.sort((a, b) => a.weight - b.weight);
|
sorted.sort((a, b) => a.weight - b.weight);
|
||||||
|
|
||||||
let approved = []
|
let approved = []
|
||||||
|
|
||||||
sorted.forEach(item => {
|
sorted.forEach(item => {
|
||||||
if (!approved.some(other => fitness(item, sortBy) <= fitness(other, sortBy))) {
|
if (!approved.some(other => fitness(item, sortBy) <= fitness(other, sortBy))) {
|
||||||
approved.push(item)
|
approved.push(item)
|
||||||
@ -101,47 +102,33 @@ function permutations(budget, lockedItems) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function knapSack(sortBy) {
|
function knapSack(selection, sortBy) {
|
||||||
return selection.reduce((best, set) => {
|
return selection.reduce((best, set) => {
|
||||||
best.push(set);
|
best.push(set);
|
||||||
best.sort((a, b) => setFitness(b, sortBy) - setFitness(a, sortBy));
|
best.sort((a, b) => setFitness(b, sortBy) - setFitness(a, sortBy));
|
||||||
best.pop();
|
best.pop();
|
||||||
return best;
|
return best;
|
||||||
}, selection.slice(0, 3));
|
}, selection.slice(0, 3)).sort((a, b) => setFitness(b, sortBy) - setFitness(a, sortBy));
|
||||||
}
|
}
|
||||||
|
|
||||||
const average = (item) => item.defenses.reduce((total, n) => total + n, 0);
|
|
||||||
const physical = (item) => item.defenses.slice(0, 4).reduce((total, n) => total + n, 0);
|
|
||||||
const elemental = (item) => item.defenses.slice(4, 8).reduce((total, n) => total + n, 0);
|
|
||||||
const resistances = (item) => item.resistances.reduce((total, n) => total + n, 0);
|
|
||||||
const poise = (item) => item.poise;
|
|
||||||
|
|
||||||
function fitness(item, sortBy) {
|
function fitness(item, sortBy) {
|
||||||
switch (sortBy) {
|
switch (sortBy) {
|
||||||
case "sort-average":
|
case "sort-average":
|
||||||
return average(item);
|
return item.average ??= item.defenses.reduce((total, n) => total + n, 0);
|
||||||
case "sort-physical":
|
case "sort-physical":
|
||||||
return physical(item);
|
return item.physical ??= item.defenses.slice(0, 4).reduce((total, n) => total + n, 0);
|
||||||
case "sort-elemental":
|
case "sort-elemental":
|
||||||
return elemental(item);
|
return item.elemental ??= item.defenses.slice(4, 8).reduce((total, n) => total + n, 0);
|
||||||
case "sort-resistances":
|
case "sort-resistances":
|
||||||
return resistances(item);
|
return item.resistances ??= item.resistances.reduce((total, n) => total + n, 0);
|
||||||
case "sort-poise":
|
case "sort-poise":
|
||||||
return poise(item);
|
return item.poise;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setWeight(set) {
|
const setWeight = (set) => set.weight ??= set.reduce((total, item) => total + item.weight, 0);
|
||||||
return set.reduce((total, item) => total + item.weight, 0);
|
const setFitness = (set, sortBy) => set.fitness ??= set.reduce((total, item) => total + fitness(item, sortBy), 0.0);
|
||||||
}
|
const isAllowedSet = (set, lockedItems) => lockedItems.every(item => set.includes(item));
|
||||||
|
|
||||||
function setFitness(set, sortBy) {
|
|
||||||
return set.reduce((total, item) => total + fitness(item, sortBy), 0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isAllowedSet(set, lockedItems) {
|
|
||||||
return lockedItems.every(item => set.includes(item));
|
|
||||||
}
|
|
||||||
|
|
||||||
function equipLoadBudget() {
|
function equipLoadBudget() {
|
||||||
let rollModifier = parseFloat([...document.getElementsByName("roll-type")].find(elem => elem.checked).value);
|
let rollModifier = parseFloat([...document.getElementsByName("roll-type")].find(elem => elem.checked).value);
|
||||||
|
Loading…
Reference in New Issue
Block a user