removed ul from most layouts

This commit is contained in:
Frederik Palmø 2022-04-03 22:08:44 +02:00
parent 3b1a0a853c
commit 29b2f7b435
6 changed files with 577 additions and 694 deletions

View File

@ -1,27 +1,28 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head>
<head>
<!-- metadata --> <!-- metadata -->
<meta charset="utf-8"> <meta charset="utf-8" />
<meta name="language" content="english"> <meta name="language" content="english" />
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="style/main.css"> <link rel="stylesheet" href="style/main.css" />
<!-- title and description --> <!-- title and description -->
<title>Erdtree - Armor Optimizer</title> <title>Erdtree - Armor Optimizer</title>
<meta name="description" content="Elden Ring build planner, armor optimizer, weapon finder and more!"> <meta name="description" content="Elden Ring build planner, armor optimizer, weapon finder and more!" />
<meta property="og:title" content="Erdtree Build Planner"> <meta property="og:title" content="Erdtree Build Planner" />
<meta property="og:description" <meta
content="Erdtree - Elden Ring build planner, armor optimizer, weapon finder and more!"> property="og:description"
<meta property="og:url" content="https://erdtree.palmoe.dk"> content="Erdtree - Elden Ring build planner, armor optimizer, weapon finder and more!"
/>
<meta property="og:url" content="https://erdtree.palmoe.dk" />
<!-- scripts --> <!-- scripts -->
<script src="/script/armor.js"></script> <script src="/script/armor.js"></script>
</head> </head>
<body onload="init();"> <body onload="init();">
<nav> <nav>
<h1><a href="/">Elden Ring Build Planner</a></h1> <h1><a href="/">Elden Ring Build Planner</a></h1>
<ul> <ul>
@ -36,161 +37,184 @@
<main> <main>
<div class="app"> <div class="app">
<!-- settings --> <!-- settings -->
<article style="flex-basis: 30%"> <article style="flex-basis: 25%">
<ul> <b>Settings</b>
<li><b>Settings</b></li>
<hr> <hr />
<li>
<label for="max-equip-load">Max. Equip Load</label>
<input style="max-width: 50px" class="stat" id="max-equip-load" type="number" oninput="update()"
min=0 step=0.1 value=30 name="equip-load" lang="en">
</li>
<li>
<label for="current-equip-load">Current Equip Load</label>
<input style="max-width: 50px" class="stat" id="current-equip-load" type="number"
oninput="update()" min=0 step=0.1 value=0 name="equip-load" lang="en">
</li>
<li>
<label for="equip-load-budget">Equip Load Budget</label>
<input style="max-width: 50px" class="stat" id="equip-load-budget" type="number" value=0
name="equip-load" lang="en" disabled>
</li>
<hr>
<li>
<b>Breakpoints</b>
</li>
<li>
<div> <div>
<input type="radio" id="fast-roll" onclick="update()" name="roll-type" value=0.3> <label for="max-equip-load">Max. Equip Load</label>
<input
style="max-width: 50px"
class="stat"
id="max-equip-load"
type="number"
onchange="update()"
min="0"
step="0.1"
value="30"
name="equip-load"
lang="en"
/>
</div>
<div>
<label for="current-equip-load">Current Equip Load</label>
<input
style="max-width: 50px"
class="stat"
id="current-equip-load"
type="number"
onchange="update()"
min="0"
step="0.1"
value="0"
name="equip-load"
lang="en"
/>
</div>
<div>
<label for="equip-load-budget">Equip Load Budget</label>
<input
style="max-width: 50px"
class="stat"
id="equip-load-budget"
type="number"
value="0"
name="equip-load"
lang="en"
disabled
/>
</div>
<hr />
<b>Breakpoints</b>
<div>
<div>
<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> </div>
<li>
<div> <div>
<input type="radio" id="normal-roll" onclick="update()" name="roll-type" value=0.7 checked> <div>
<input
type="radio"
id="normal-roll"
onclick="update()"
name="roll-type"
value="0.7"
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> </div>
<li>
<div> <div>
<input type="radio" id="fat-roll" onclick="update()" name="roll-type" value=1.0> <div>
<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> </div>
<hr> <hr />
<li>
<b>Sort by</b> <b>Sort by</b>
</li>
<li>
<div> <div>
<input type="radio" id="sort-average" name="sorting-order" onclick="update()"> <div>
<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> </div>
<li>
<div> <div>
<input type="radio" id="sort-physical" name="sorting-order" onclick="update()" checked> <div>
<input type="radio" id="sort-physical" name="sorting-order" onclick="update()" checked />
<label for="sort-physical">Greatest Physical Negation</label> <label for="sort-physical">Greatest Physical Negation</label>
</div> </div>
</li> </div>
<li>
<div> <div>
<input type="radio" id="sort-elemental" name="sorting-order" onclick="update()"> <div>
<input type="radio" id="sort-elemental" name="sorting-order" onclick="update()" />
<label for="sort-elemental">Greatest Elemental Negation</label> <label for="sort-elemental">Greatest Elemental Negation</label>
</div> </div>
</li> </div>
<li>
<div> <div>
<input type="radio" id="sort-resistances" name="sorting-order" onclick="update()"> <div>
<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> </div>
<li>
<div> <div>
<input type="radio" id="sort-poise" name="sorting-order" onclick="update()"> <div>
<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> </div>
<hr> <hr />
<li>
<b>Extras</b> <b>Extras</b>
</li>
<li>
<div> <div>
<input type="checkbox" id="winged-crystal-tear" onchange="update()" disabled> <div>
<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> </div>
<li>
<div> <div>
<input type="checkbox" id="fashion" onchange="update()" disabled> <div>
<input type="checkbox" id="fashion" onchange="update()" disabled />
<label for="fashion">Fashion Mode</label> <label for="fashion">Fashion Mode</label>
</div> </div>
</li> </div>
<hr />
<li><b>Filter</b></li>
<hr>
<li>
<b>Locked Items</b> <b>Locked Items</b>
<button id="clear-equipment" onclick="reset()">Clear Locked Equipment</button>
</li>
<li>
<template id="locked-option"> <template id="locked-option">
<option value="">Placeholder</option> <option value="">Placeholder</option>
</template> </template>
<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()"> <select type="text" id="select-helmet" name="locked-items" onchange="update()"></select>
</select>
</div> </div>
<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()"> <select type="text" id="select-chestpiece" name="locked-items" onchange="update()"></select>
</select>
</div> </div>
<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()"> <select type=" text" id="select-gauntlets" name="locked-items" onchange="update()"></select>
</select>
</div> </div>
<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()"> <select type="text" id="select-leggings" name="locked-items" onchange="update()"></select>
</select>
</div> </div>
<div>
<button id="clear-equipment" onclick="reset()">Reset All</button>
</div> </div>
</li>
</ul>
</article> </article>
<!-- sort --> <!-- sort -->
<article style="flex-basis: 60%; min-width: 300px"> <article style="flex-basis: 60%; min-width: 320px">
<ul id="sort-results"> <b>Results</b>
<li><b>Sort</b></li> <hr />
<hr> <div>
<ul id="sort-results"></ul>
</div>
<template id="sort-result"> <template id="sort-result">
<li class="sort-result"> <li class="sort-result">
@ -226,7 +250,6 @@
</table> </table>
</li> </li>
</template> </template>
</ul>
</article> </article>
<!-- filter --> <!-- filter -->
@ -241,10 +264,12 @@
</main> </main>
<footer> <footer>
<h5>Erdtree Planner (<a href="https://git.palmoe.dk/vodofrede/erdtree">available under BSD-3-Clause license</a>) <h5>
Erdtree Planner (<a href="https://git.palmoe.dk/vodofrede/erdtree"
>available under BSD-3-Clause license</a
>)
</h5> </h5>
<h5>Copyright 2022 vodofrede</h5> <h5>Copyright 2022 vodofrede</h5>
</footer> </footer>
</body> </body>
</html> </html>

View File

@ -1,274 +1,171 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head>
<head>
<!-- metadata --> <!-- metadata -->
<meta charset="utf-8"> <meta charset="utf-8" />
<meta name="language" content="english"> <meta name="language" content="english" />
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="style/main.css"> <link rel="stylesheet" href="style/main.css" />
<!-- title and description --> <!-- title and description -->
<title>Erdtree - Class Optimizer</title> <title>Erdtree - Class Optimizer</title>
<meta name="description" content="Elden Ring build planner, armor optimizer, weapon finder and more!"> <meta name="description" content="Elden Ring build planner, armor optimizer, weapon finder and more!" />
<meta property="og:title" content="Erdtree Build Planner"> <meta property="og:title" content="Erdtree Build Planner" />
<meta property="og:description" <meta
content="Erdtree - Elden Ring build planner, armor optimizer, weapon finder and more!"> property="og:description"
<meta property="og:url" content="https://erdtree.palmoe.dk"> content="Erdtree - Elden Ring build planner, armor optimizer, weapon finder and more!"
/>
<meta property="og:url" content="https://erdtree.palmoe.dk" />
<!-- scripts --> <!-- scripts -->
<script src="/script/class.js"></script> <script src="/script/class.js"></script>
</head> </head>
<body onload="init();"> <body onload="init();">
<nav> <nav>
<h1><a href="/">Elden Ring Build Planner</a></h1> <h1><a href="/">Elden Ring Build Planner</a></h1>
<ul> <ul>
<li><a href="/planner.html">Build Planner</a></li> <a href="/planner.html">Build Planner</a>
</ul> </ul>
</nav> </nav>
<header> <header>
<h1>Class Optimizer</h1> <h2>Class Optimizer</h2>
</header> </header>
<main> <main>
<div class="app"> <div class="app">
<!-- class options -->
<article id="class-options">
<ul>
<li>
<label><b>Class</b></label>
<input id="best-class" type="text" disabled>
</li>
<hr>
<li><b>Options</b></li>
<li name="option">
<div></div>
<div></div>
</li>
<li name="option">
<div></div>
<div></div>
</li>
<li name="option">
<div></div>
<div></div>
</li>
<li name="option">
<div></div>
<div></div>
</li>
<li name="option">
<div></div>
<div></div>
</li>
<li name="option">
<div></div>
<div></div>
</li>
<li name="option">
<div></div>
<div></div>
</li>
<li name="option">
<div></div>
<div></div>
</li>
<li name="option">
<div></div>
<div></div>
</li>
<li name="option">
<div></div>
<div></div>
</li>
</ul>
</article>
<!-- stats -->
<article> <article>
<ul> <div>
<b>Class</b>
<input id="best" type="text" disabled />
</div>
<hr />
<template id="class">
<li> <li>
<label> <span></span>
<aside></aside>
</li>
</template>
<div>
<ul id="classes"></ul>
</div>
</article>
<article>
<div>
<b>Level</b> <b>Level</b>
</label>
<div> <div>
<input class="stat" type="text" id="class-level" disabled> <input id="initial-level" type="number" disabled />
<input class="stat" type="text" id="total-level" disabled style="visibility: hidden;"> <input type="number" style="visibility: hidden" disabled />
<input class="stat" type="text" id="subtractive-level" disabled> <input id="final-level" type="number" disabled />
<input class="stat" type="text" id="additive-level" disabled> <input id="virtual-level" type="number" disabled />
</div> </div>
</li> </div>
<hr />
<hr>
<li>
<label>Vigor</label>
<div> <div>
<input name="class-stat" class="stat" type="text" id="class-vigor" disabled> <label for="vigor">Vigor</label>
<input name="desired-stat" class="stat" type="number" id="vigor" oninput="update()" min=0
max=99 maxLength=2>
<input name="subtractive-stat" class="stat" type="text" id="subtractive-vigor" disabled>
<input name="additive-stat" class="stat" type="text" id="additive-vigor" disabled>
</div>
</li>
<li>
<label>Mind</label>
<div> <div>
<input name="class-stat" class="stat" type="text" id="class-mind" disabled> <input type="number" name="initial" disabled />
<input name="desired-stat" class="stat" type="number" id="mind" oninput="update()" min=0 <input id="vigor" type="number" name="total" min="0" max="99" oninput="update()" />
max=99> <input type="number" name="final" disabled />
<input name="subtractive-stat" class="stat" type="text" id="subtractive-mind" disabled> <input type="number" name="virtual" disabled />
<input name="additive-stat" class="stat" type="text" id="additive-mind" disabled> </div>
</div> </div>
</li>
<li>
<label>Endurance</label>
<div> <div>
<input name="class-stat" class="stat" type="text" id="class-endurance" disabled> <label for="mind">Mind</label>
<input name="desired-stat" class="stat" type="number" id="endurance" oninput="update()"
min=0 max=99>
<input name="subtractive-stat" class="stat" type="text" id="subtractive-endurance" disabled>
<input name="additive-stat" class="stat" type="text" id="additive-endurance" disabled>
</div>
</li>
<li>
<label>Strength</label>
<div> <div>
<input name="class-stat" class="stat" type="text" id="class-strength" disabled> <input type="number" name="initial" disabled />
<input name="desired-stat" class="stat" type="number" id="strength" oninput="update()" min=0 <input id="mind" type="number" name="total" min="0" max="99" oninput="update()" />
max=99> <input type="number" name="final" disabled />
<input name="subtractive-stat" class="stat" type="text" id="subtractive-strength" disabled> <input type="number" name="virtual" disabled />
<input name="additive-stat" class="stat" type="text" id="additive-strength" disabled> </div>
</div> </div>
</li>
<li>
<label>Dexterity</label>
<div> <div>
<input name="class-stat" class="stat" type="text" id="class-dexterity" disabled> <label for="endurance">Endurance</label>
<input name="desired-stat" class="stat" type="number" id="dexterity" oninput="update()"
min=0 max=99>
<input name="subtractive-stat" class="stat" type="text" id="subtractive-dexterity" disabled>
<input name="additive-stat" class="stat" type="text" id="additive-dexterity" disabled>
</div>
</li>
<li>
<label>Intelligence</label>
<div> <div>
<input name="class-stat" class="stat" type="text" id="class-intelligence" disabled> <input type="number" name="initial" disabled />
<input name="desired-stat" class="stat" type="number" id="intelligence" oninput="update()" <input id="endurance" type="number" name="total" min="0" max="99" oninput="update()" />
min=0 max=99> <input type="number" name="final" disabled />
<input name="subtractive-stat" class="stat" type="text" id="subtractive-intelligence" <input type="number" name="virtual" disabled />
disabled> </div>
<input name="additive-stat" class="stat" type="text" id="additive-intelligence" disabled>
</div> </div>
</li>
<li>
<label>Faith</label>
<div> <div>
<input name="class-stat" class="stat" type="text" id="class-faith" disabled> <label for="strength">Strength</label>
<input name="desired-stat" class="stat" type="number" id="faith" oninput="update()" min=0
max=99>
<input name="subtractive-stat" class="stat" type="text" id="subtractive-faith" disabled>
<input name="additive-stat" class="stat" type="text" id="additive-faith" disabled>
</div>
</li>
<li>
<label>Arcane</label>
<div> <div>
<input name="class-stat" class="stat" type="text" id="class-arcane" disabled> <input type="number" name="initial" disabled />
<input name="desired-stat" class="stat" type="number" id="arcane" oninput="update()" min=0 <input id="strength" type="number" name="total" min="0" max="99" oninput="update()" />
max=99> <input type="number" name="final" disabled />
<input name="subtractive-stat" class="stat" type="text" id="subtractive-arcane" disabled> <input type="number" name="virtual" disabled />
<input name="additive-stat" class="stat" type="text" id="additive-arcane" disabled> </div>
</div>
<div>
<label for="dexterity">Dexterity</label>
<div>
<input type="number" name="initial" disabled />
<input id="dexterity" type="number" name="total" min="0" max="99" oninput="update()" />
<input type="number" name="final" disabled />
<input type="number" name="virtual" disabled />
</div>
</div>
<div>
<label for="intelligence">Intelligence</label>
<div>
<input type="number" name="initial" disabled />
<input id="intelligence" type="number" name="total" min="0" max="99" oninput="update()" />
<input type="number" name="final" disabled />
<input type="number" name="virtual" disabled />
</div>
</div>
<div>
<label for="faith">Faith</label>
<div>
<input type="number" name="initial" disabled />
<input id="faith" type="number" name="total" min="0" max="99" oninput="update()" />
<input type="number" name="final" disabled />
<input type="number" name="virtual" disabled />
</div>
</div>
<div>
<label for="arcane">Arcane</label>
<div>
<input type="number" name="initial" disabled />
<input id="arcane" type="number" name="total" min="0" max="99" oninput="update()" />
<input type="number" name="final" disabled />
<input type="number" name="virtual" disabled />
</div>
</div> </div>
</li>
<li>
<button onclick="clearAll()">Clear All</button>
</li>
</ul>
</article> </article>
<!-- talismans -->
<article> <article>
<ul id="talismans"> <div>
<li> <b>Helmet</b>
<select id="helmet" name="equipment" onchange="update()">
<option id="none" value="none">No Helmet</option>
</select>
</div>
<hr />
<b>Talismans</b> <b>Talismans</b>
</li> <div>
<ul id="talismans">
<hr>
<template id="talisman"> <template id="talisman">
<li> <li>
<div> <div>
<input type="checkbox" class="talisman" id="" name="equipment" onclick="update()"> <input name="talisman" type="checkbox" onchange="update()" />
<label for="">Placeholder</label> <label></label>
</div> </div>
<aside></aside> <aside></aside>
</li> </li>
</template> </template>
</ul> </ul>
</article>
<!-- helms -->
<article>
<ul>
<li>
<b>Helmets</b>
</li>
<hr>
<details id="helmets">
<summary>Click to show helmets</summary>
<li>
<div>
<input type="radio" name="equipment" id="helm-none" onclick="update()" checked>
<label for="">None</label>
</div> </div>
<aside></aside>
</li>
<template id="helm">
<li>
<div> <div>
<input type="radio" id="" name="equipment" onclick="update()"> <button onclick="reset()">Reset All</button>
<label for="">Placeholder</label>
</div> </div>
<aside></aside>
</li>
</template>
</details>
</ul>
</article> </article>
</div> </div>
<h3>Explanation</h3> <h3 style="text-align: center">Softcaps</h3>
<p>The columns in the second box represent, in order:</p>
<ol>
<li>
The total level and stats of the lowest-level class with your desired statistics.
</li>
<li>
Desired statistics. This is where you input the stats that you definitely want your build to have.
</li>
<li>
Calculated statistics for your build (as they should be in your level-up menu in-game).
</li>
<li>
Calculated final statistics as shown on the "Stats" screen in-game.<br>
The level indicator at the top of this column indicates your "virtual" level, and is not reflected
in-game! This statistic includes stats from your talismans and helmet.
</li>
</ol>
<h3>Softcaps</h3>
<table> <table>
<thead> <thead>
<tr> <tr>
@ -282,7 +179,7 @@
<tr> <tr>
<td>Vigor</td> <td>Vigor</td>
<td>HP</td> <td>HP</td>
<td>25 (800HP)<br>40 (1450HP)<br>60 (1900HP)</td> <td>25 (800HP)<br />40 (1450HP)<br />60 (1900HP)</td>
<td>A +12 upgraded crimson flask heals for 810HP.</td> <td>A +12 upgraded crimson flask heals for 810HP.</td>
</tr> </tr>
<tr> <tr>
@ -294,19 +191,19 @@
<tr> <tr>
<td>Endurance</td> <td>Endurance</td>
<td>Stamina</td> <td>Stamina</td>
<td>30 (125stm.)<br>50 (155stm.)</td> <td>30 (125stm.)<br />50 (155stm.)</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td></td> <td></td>
<td>Equip Load</td> <td>Equip Load</td>
<td>25 (72 wgt.)<br>60 (120 wgt.)</td> <td>25 (72 wgt.)<br />60 (120 wgt.)</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>Strength</td> <td>Strength</td>
<td>AR</td> <td>AR</td>
<td>34 ≃ 50 (2h)<br>54 ≃ 80 (2h)<br>66 ≃ 99 (2h)<br>80</td> <td>34 ≃ 50 (2h)<br />54 ≃ 80 (2h)<br />66 ≃ 99 (2h)<br />80</td>
<td>2-handing gives you 1.5x strength.</td> <td>2-handing gives you 1.5x strength.</td>
</tr> </tr>
<tr> <tr>
@ -354,7 +251,7 @@
<tr> <tr>
<td></td> <td></td>
<td>Spell Buff</td> <td>Spell Buff</td>
<td>60, 80 (Pure catalyst)<br>30, 45 (Hybrid catalyst)</td> <td>60, 80 (Pure catalyst)<br />30, 45 (Hybrid catalyst)</td>
<td></td> <td></td>
</tr> </tr>
</tbody> </tbody>
@ -362,10 +259,12 @@
</main> </main>
<footer> <footer>
<h5>Erdtree Planner (<a href="https://git.palmoe.dk/vodofrede/erdtree">available under BSD-3-Clause license</a>) <h5>
Erdtree Planner (<a href="https://git.palmoe.dk/vodofrede/erdtree"
>available under BSD-3-Clause license</a
>)
</h5> </h5>
<h5>Copyright 2022 vodofrede</h5> <h5>Copyright 2022 vodofrede</h5>
</footer> </footer>
</body> </body>
</html> </html>

View File

@ -135,15 +135,8 @@ function equipLoadBudget() {
// site rendering functions // site rendering functions
function populateSelect(templateId, destinationId, items) { function populateSelect(templateId, destinationId, items) {
let template = document.getElementById(templateId);
let destination = document.getElementById(destinationId); let destination = document.getElementById(destinationId);
items.forEach(item => { items.forEach(item => {
let clone = template.content.cloneNode(true);
clone.value = item.id;
clone.innerHTML = item.name;
destination.options.add(new Option(item.name, item.id)); destination.options.add(new Option(item.name, item.id));
}); });
} }

View File

@ -1,44 +1,45 @@
const CLASSES = fetch("/data/classes.json") const CLASSES = fetch("/data/classes.json")
.then(response => response.json()) .then((response) => response.json())
.catch(error => console.log(error)); .catch((error) => console.log(error));
const TALISMANS = fetch("/data/talismans.json") const TALISMANS = fetch("/data/talismans.json")
.then(response => response.json()) .then((response) => response.json())
.catch(error => console.log(error)); .catch((error) => console.log(error));
const HELMETS = fetch("/data/helmets.json") const HELMETS = fetch("/data/helmets.json")
.then(response => response.json()) .then((response) => response.json())
.catch(error => console.log(error)); .catch((error) => console.log(error));
const STAT_SHORT_NAMES = [ const STAT_SHORT_NAMES = ["vig.", "mnd.", "end.", "str.", "dex.", "int.", "fth.", "arc."];
"vig.",
"mnd.",
"end.",
"str.",
"dex.",
"int.",
"fth.",
"arc."
]
async function init() { async function init() {
// populate helmet list // populate helmet select
let helmets = await HELMETS; let helmets = Object.values(await HELMETS);
helmets = Object.values(helmets).filter(helmet => helmet.stats != null && helmet.stats != undefined); helmets = helmets.filter((helmet) => helmet.stats != null);
console.log(helmets) let destination = document.getElementById("helmet");
helmets.forEach((helmet) => {
let helmetTemplate = document.getElementById("helm"); destination.options.add(new Option(helmet.name, helmet.id));
let helmetList = document.getElementById("helmets");
helmets.forEach(helmet => {
cloneTemplate(helmetTemplate, helmetList, helmet);
}); });
// populate talisman list // populate talisman list
let talismans = await TALISMANS; let talismans = Object.values(await TALISMANS);
talismans = Object.values(talismans).filter(talisman => talisman.stats != null && talisman.stats != undefined); talismans = talismans.filter((talisman) => talisman.stats != null && !talisman.id.includes("scar"));
let talismanTemplate = document.getElementById("talisman"); let template = document.getElementById("talisman");
let talismanList = document.getElementById("talismans"); destination = document.getElementById("talismans");
talismans.forEach(talisman => { talismans.forEach((item) => {
cloneTemplate(talismanTemplate, talismanList, talisman); let clone = template.content.cloneNode(true);
let li = clone.children[0];
let input = li.children[0].children[0];
let label = li.children[0].children[1];
let aside = li.children[1];
input.id = item.id;
input.value = item.id;
label.htmlFor = item.id;
label.innerHTML = item.name;
aside.innerHTML = statsDescription(item.stats);
destination.appendChild(clone);
}); });
update(); update();
@ -46,59 +47,63 @@ async function init() {
async function update() { async function update() {
// get inputted stats, clamp value to 0..99 // get inputted stats, clamp value to 0..99
let desired = [...document.getElementsByName("desired-stat")].map( let total = [...document.getElementsByName("total")].map((elem) => {
elem => {
elem.value = Math.min(Math.max(elem.value, 0), 99) || null; elem.value = Math.min(Math.max(elem.value, 0), 99) || null;
return parseInt(elem.value) || 0; return parseInt(elem.value) || 0;
} });
)
// get added stats from items // get added stats from items
let items = itemStats(Object.values(await TALISMANS).concat(Object.values(await HELMETS))); let items = itemStats(Object.values(await TALISMANS).concat(Object.values(await HELMETS)));
desired = desired.map((stat, i) => stat - items[i]);
// calculate best class // calculate best class
let sorted = sortClasses(await CLASSES, desired); let sorted = sortClasses(
Object.values(await CLASSES),
total.map((stat, i) => stat - items[i])
);
let best = sorted[0]; let best = sorted[0];
// update document // update document
document.getElementsByName("option").forEach((elem, i) => { document.getElementsByName("initial").forEach((elem, i) => (elem.value = best.stats[i]));
let [name, level] = elem.children; document.getElementsByName("final").forEach((elem, i) => {
name.innerHTML = sorted[i].name; elem.value = Math.max(total[i] - items[i], best.stats[i]);
level.innerHTML = "lvl. " + sorted[i].total; });
}) document.getElementsByName("virtual").forEach((elem, i) => {
document.getElementById("best-class").value = best.name; elem.value = Math.max(total[i], best.stats[i]);
document.getElementById("class-level").value = best.level;
document.getElementById("total-level").value = best.total;
document.getElementById("subtractive-level").value = best.total;
document.getElementById("additive-level").value = [...document.getElementsByName("additive-stat")].reduce((total, elem, i) => {
return total + (desired[i] > best.stats[i] ? desired[i] : best.stats[i]) + items[i];
}, 0) - 79;
document.getElementsByName("class-stat").forEach((elem, i) => elem.value = best.stats[i]);
document.getElementsByName("subtractive-stat").forEach((elem, i) => {
elem.value = ((desired[i] > best.stats[i] ? desired[i] : best.stats[i]));
}); });
document.getElementsByName("additive-stat").forEach((elem, i) => { document.getElementById("initial-level").value = best.stats.reduce((sum, n) => sum + n) - 79;
elem.value = ((desired[i] > best.stats[i] ? desired[i] : best.stats[i]) + items[i]); document.getElementById("final-level").value = best.total;
document.getElementById("virtual-level").value = best.total + items.reduce((sum, n) => sum + n);
// update best classes
document.getElementById("best").value = best.name;
let destination = document.getElementById("classes");
destination.innerHTML = "";
let template = document.getElementById("class");
sorted.forEach((c) => {
let clone = template.content.cloneNode(true);
let li = clone.children[0];
let span = li.children[0];
let aside = li.children[1];
span.innerHTML = c.name;
aside.innerHTML = "lvl. " + c.total;
destination.appendChild(clone);
}); });
// update talismans // update talismans
let talismans = [...document.getElementsByClassName("talisman")] let talismans = [...document.getElementsByName("talisman")];
if (talismans.filter(checkbox => checkbox.checked).length >= 4) { if (talismans.filter((checkbox) => checkbox.checked).length >= 4) {
talismans.forEach(checkbox => checkbox.disabled = !checkbox.checked); talismans.forEach((checkbox) => (checkbox.disabled = !checkbox.checked));
} else { } else {
talismans.forEach(checkbox => checkbox.disabled = false); talismans.forEach((checkbox) => (checkbox.disabled = false));
} }
} }
function sortClasses(classes, desiredStats) { function sortClasses(classes, desiredStats) {
let deltas = Object.values(classes).map(c => { let deltas = classes.map((c) => {
c.total = c.level + statDelta(c.stats, desiredStats); c.total = c.level + statDelta(c.stats, desiredStats);
return c; return c;
}); });
@ -107,48 +112,33 @@ function sortClasses(classes, desiredStats) {
} }
function statDelta(classStats, desiredStats) { function statDelta(classStats, desiredStats) {
return classStats return classStats.map((e, i) => (e < desiredStats[i] ? desiredStats[i] - e : 0)).reduce((total, n) => total + n);
.map((e, i) => e < desiredStats[i] ? desiredStats[i] - e : 0)
.reduce((total, n) => total + n);
} }
function itemStats(relevantItems) { function itemStats(relevantItems) {
let ids = [...document.getElementsByName("equipment")] let helmet = document.getElementById("helmet").options[document.getElementById("helmet").selectedIndex].value;
.filter(elem => elem.checked) let talismans = [...document.getElementsByName("talisman")].filter((t) => t.checked).map((t) => t.value);
.map(elem => elem.id);
let relevant = relevantItems.filter(item => ids.includes(item.id));
return relevant.reduce((total, item) => total.map((stat, i) => stat += item.stats[i]), [0, 0, 0, 0, 0, 0, 0, 0]); ids = [helmet, ...talismans];
let relevant = relevantItems.filter((item) => ids.includes(item.id));
return relevant.reduce((total, item) => total.map((stat, i) => (stat += item.stats[i])), [0, 0, 0, 0, 0, 0, 0, 0]);
} }
function clearAll() { function reset() {
document.getElementsByName("desired-stat").forEach(elem => elem.value = null); document.getElementsByName("total").forEach((elem) => (elem.value = null));
[...document.getElementsByName("equipment")].forEach(elem => elem.checked = false); document.getElementById("helmet").selectedIndex = 0;
document.getElementById("helm-none").checked = true; [...document.getElementsByName("talisman")].forEach((elem) => (elem.checked = false));
update(); update();
} }
function statsDescription(stats) { function statsDescription(stats) {
return stats.reduce((total, stat, i) => { return stats.reduce((total, stat, i) => {
return stat ? (total + " +" + stat + " " + STAT_SHORT_NAMES[i]) : total; return stat ? total + " +" + stat + STAT_SHORT_NAMES[i] : total;
}, ""); }, "");
} }
function cloneTemplate(template, destination, item) { function clamp(n, min, max) {
let clone = template.content.cloneNode(true); return Math.min(Math.max(n, min), max);
let li = clone.children[0]
let div = li.children[0];
let inputElement = div.children[0];
let labelElement = div.children[1]
inputElement.id = item.id;
labelElement.for = item.id;
labelElement.innerHTML = item.name;
let aside = li.children[1];
aside.innerHTML = statsDescription(item.stats);
destination.appendChild(clone);
} }

View File

@ -64,6 +64,8 @@ function reset(area) {
document.getElementById("class").selectedIndex = 0; document.getElementById("class").selectedIndex = 0;
[...document.getElementsByName("stat")].forEach(stat => stat.value = 10); [...document.getElementsByName("stat")].forEach(stat => stat.value = 10);
break; break;
default:
break;
} }
update(); update();
} }

View File

@ -2,8 +2,8 @@
@media (prefers-color-scheme: light) { @media (prefers-color-scheme: light) {
:root { :root {
--primary: white; --primary: white;
--secondary: #f8f8ff; --lighter: #f8f8ff;
--tertiary: #f3f3f3; --darker: #f3f3f3;
--border: grey; --border: grey;
--font-color: black; --font-color: black;
--font-inverted: white; --font-inverted: white;
@ -14,8 +14,8 @@
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
:root { :root {
--primary: #2b2a33; --primary: #2b2a33;
--secondary: #1c1b22; --lighter: #373641;
--tertiary: #1c1b22; --darker: #1f1e25;
--border: black; --border: black;
--font-color: white; --font-color: white;
--font-inverted: black; --font-inverted: black;
@ -33,8 +33,7 @@ html * {
/* fonts */ /* fonts */
html { html {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
"Helvetica Neue", Arial, "Noto Sans", sans-serif;
} }
@media (max-width: 899px) { @media (max-width: 899px) {
@ -89,7 +88,13 @@ footer {
margin-top: auto; margin-top: auto;
outline: 1px solid var(--border); outline: 1px solid var(--border);
background-color: var(--secondary); background-color: var(--lighter);
}
hr {
color: var(--border);
margin-top: 0.3rem;
margin-bottom: 0.3rem;
} }
/* nav */ /* nav */
@ -100,7 +105,7 @@ nav {
align-items: center; align-items: center;
/* look */ /* look */
background-color: var(--secondary); background-color: var(--darker);
outline: 1px solid var(--border); outline: 1px solid var(--border);
} }
@ -173,12 +178,11 @@ table {
text-align: center; text-align: center;
width: 100%; width: 100%;
border-radius: 5px;
margin-bottom: 10px; margin-bottom: 10px;
border: 1px solid var(--border); border: 1px solid var(--border);
border-radius: 5px;
background-color: var(--primary); background-color: var(--lighter);
} }
td, td,
@ -194,7 +198,8 @@ th {
button { button {
/* border: var(--border); /* border: var(--border);
border-radius: 3px;*/ border-radius: 3px;*/
padding: 3px; margin: 0rem 0rem 0.2rem 0rem;
padding: 0.1rem 0.3rem 0.2rem 0.3rem;
color: black; color: black;
} }
@ -202,6 +207,20 @@ label {
user-select: none; user-select: none;
} }
input {
margin: 0rem 0rem 0.2rem 0rem;
color: black;
}
select {
margin: 0rem 0rem 0.2rem 0rem;
color: black;
}
select * {
color: black;
}
/* cards */ /* cards */
.cards { .cards {
display: flex; display: flex;
@ -219,7 +238,7 @@ label {
border-radius: 5px; border-radius: 5px;
/* look */ /* look */
background-color: var(--secondary); background-color: var(--lighter);
} }
.cards article * { .cards article * {
@ -231,96 +250,51 @@ label {
.app { .app {
display: flex; display: flex;
flex-flow: row wrap; flex-flow: row wrap;
justify-content: center; gap: 30px;
padding: 15px;
border: 1px solid var(--border);
border-radius: 5px;
min-width: 320px;
background-color: var(--secondary);
} }
.app > article { .app article {
display: flex;
flex-flow: column nowrap;
flex-basis: 320px;
flex-grow: 1;
padding: 10px;
border: 1px solid var(--border); border: 1px solid var(--border);
border-radius: 5px; border-radius: 5px;
margin: 10px; background-color: var(--lighter);
padding: 10px; }
flex-grow: 1;
flex-basis: 320px;
.app article > * {
display: flex; display: flex;
flex-direction: column; flex-flow: row nowrap;
justify-content: top; justify-content: space-between;
align-items: stretch; align-content: flex-start;
}
.app article input {
text-align: center;
-moz-appearance: textfield;
}
.app article select {
max-width: 200px;
}
.app article input[type="number"] {
width: 45px;
} }
.app ul { .app ul {
padding-left: 0; width: 100%;
padding-top: 5px; padding: 0;
margin: 0; margin: 0;
list-style: none;
list-style-type: none;
} }
.app li { .app li {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
width: 100%; word-wrap: break-word;
list-style: none;
}
.app li * {
flex-grow: 50%;
}
.app input {
text-align: center;
border: 1px solid var(--border);
}
.app input:is([disabled]) {
background-color: var(--tertiary);
}
.app .stat {
align-self: flex-end;
max-width: 40px;
margin-left: 10px;
-webkit-appearance: none;
-moz-appearance: textfield;
}
.app .stat:not([disabled]) {
color: black;
}
.app hr {
margin-top: 2px;
margin-bottom: 4px;
}
.select {
display: flex;
flex-flow: column nowrap;
justify-content: center;
width: 100%;
gap: 10px;
}
.select * {
text-align: center;
display: flex;
flex-grow: 100%;
flex-flow: column nowrap;
}
.select select {
border: 1px solid var(--border);
background-color: var(--primary);
color: var(--font-color);
} }