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

View File

@ -1,371 +1,270 @@
<!DOCTYPE html>
<html>
<head>
<!-- metadata -->
<meta charset="utf-8" />
<meta name="language" content="english" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<head>
<!-- metadata -->
<meta charset="utf-8">
<meta name="language" content="english">
<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>Erdtree - Class Optimizer</title>
<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:description"
content="Erdtree - Elden Ring build planner, armor optimizer, weapon finder and more!"
/>
<meta property="og:url" content="https://erdtree.palmoe.dk" />
<!-- title and description -->
<title>Erdtree - Class Optimizer</title>
<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:description"
content="Erdtree - Elden Ring build planner, armor optimizer, weapon finder and more!">
<meta property="og:url" content="https://erdtree.palmoe.dk">
<!-- scripts -->
<script src="/script/class.js"></script>
</head>
<!-- scripts -->
<script src="/script/class.js"></script>
</head>
<body onload="init();">
<nav>
<h1><a href="/">Elden Ring Build Planner</a></h1>
<ul>
<a href="/planner.html">Build Planner</a>
</ul>
</nav>
<body onload="init();">
<nav>
<h1><a href="/">Elden Ring Build Planner</a></h1>
<ul>
<li><a href="/planner.html">Build Planner</a></li>
</ul>
</nav>
<header>
<h2>Class Optimizer</h2>
</header>
<header>
<h1>Class Optimizer</h1>
</header>
<main>
<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>
<ul>
<li>
<label>
<b>Level</b>
</label>
<div>
<input class="stat" type="text" id="class-level" disabled>
<input class="stat" type="text" id="total-level" disabled style="visibility: hidden;">
<input class="stat" type="text" id="subtractive-level" disabled>
<input class="stat" type="text" id="additive-level" disabled>
</div>
</li>
<hr>
<li>
<label>Vigor</label>
<div>
<input name="class-stat" class="stat" type="text" id="class-vigor" disabled>
<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>
<input name="class-stat" class="stat" type="text" id="class-mind" disabled>
<input name="desired-stat" class="stat" type="number" id="mind" oninput="update()" min=0
max=99>
<input name="subtractive-stat" class="stat" type="text" id="subtractive-mind" disabled>
<input name="additive-stat" class="stat" type="text" id="additive-mind" disabled>
</div>
</li>
<li>
<label>Endurance</label>
<div>
<input name="class-stat" class="stat" type="text" id="class-endurance" disabled>
<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>
<input name="class-stat" class="stat" type="text" id="class-strength" disabled>
<input name="desired-stat" class="stat" type="number" id="strength" oninput="update()" min=0
max=99>
<input name="subtractive-stat" class="stat" type="text" id="subtractive-strength" disabled>
<input name="additive-stat" class="stat" type="text" id="additive-strength" disabled>
</div>
</li>
<li>
<label>Dexterity</label>
<div>
<input name="class-stat" class="stat" type="text" id="class-dexterity" disabled>
<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>
<input name="class-stat" class="stat" type="text" id="class-intelligence" disabled>
<input name="desired-stat" class="stat" type="number" id="intelligence" oninput="update()"
min=0 max=99>
<input name="subtractive-stat" class="stat" type="text" id="subtractive-intelligence"
disabled>
<input name="additive-stat" class="stat" type="text" id="additive-intelligence" disabled>
</div>
</li>
<li>
<label>Faith</label>
<div>
<input name="class-stat" class="stat" type="text" id="class-faith" disabled>
<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>
<input name="class-stat" class="stat" type="text" id="class-arcane" disabled>
<input name="desired-stat" class="stat" type="number" id="arcane" oninput="update()" min=0
max=99>
<input name="subtractive-stat" class="stat" type="text" id="subtractive-arcane" disabled>
<input name="additive-stat" class="stat" type="text" id="additive-arcane" disabled>
</div>
</li>
<li>
<button onclick="clearAll()">Clear All</button>
</li>
</ul>
</article>
<!-- talismans -->
<article>
<ul id="talismans">
<li>
<b>Talismans</b>
</li>
<hr>
<template id="talisman">
<main>
<div class="app">
<article>
<div>
<b>Class</b>
<input id="best" type="text" disabled />
</div>
<hr />
<template id="class">
<li>
<div>
<input type="checkbox" class="talisman" id="" name="equipment" onclick="update()">
<label for="">Placeholder</label>
</div>
<span></span>
<aside></aside>
</li>
</template>
</ul>
</article>
<div>
<ul id="classes"></ul>
</div>
</article>
<article>
<div>
<b>Level</b>
<div>
<input id="initial-level" type="number" disabled />
<input type="number" style="visibility: hidden" disabled />
<input id="final-level" type="number" disabled />
<input id="virtual-level" type="number" disabled />
</div>
</div>
<hr />
<div>
<label for="vigor">Vigor</label>
<div>
<input type="number" name="initial" disabled />
<input id="vigor" 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="mind">Mind</label>
<div>
<input type="number" name="initial" disabled />
<input id="mind" 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="endurance">Endurance</label>
<div>
<input type="number" name="initial" disabled />
<input id="endurance" 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="strength">Strength</label>
<div>
<input type="number" name="initial" disabled />
<input id="strength" 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="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>
</article>
<article>
<div>
<b>Helmet</b>
<select id="helmet" name="equipment" onchange="update()">
<option id="none" value="none">No Helmet</option>
</select>
</div>
<hr />
<b>Talismans</b>
<div>
<ul id="talismans">
<template id="talisman">
<li>
<div>
<input name="talisman" type="checkbox" onchange="update()" />
<label></label>
</div>
<aside></aside>
</li>
</template>
</ul>
</div>
<!-- helms -->
<article>
<ul>
<li>
<b>Helmets</b>
</li>
<div>
<button onclick="reset()">Reset All</button>
</div>
</article>
</div>
<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>
<aside></aside>
</li>
<template id="helm">
<li>
<div>
<input type="radio" id="" name="equipment" onclick="update()">
<label for="">Placeholder</label>
</div>
<aside></aside>
</li>
</template>
</details>
</ul>
</article>
</div>
<h3>Explanation</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>
<thead>
<tr>
<th>Skill</th>
<th>Stat</th>
<th>Softcaps</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td>Vigor</td>
<td>HP</td>
<td>25 (800HP)<br>40 (1450HP)<br>60 (1900HP)</td>
<td>A +12 upgraded crimson flask heals for 810HP.</td>
</tr>
<tr>
<td>Mind</td>
<td>FP</td>
<td>40 (220FP)</td>
<td>A +12 upgraded cerulean flask gives 220FP.</td>
</tr>
<tr>
<td>Endurance</td>
<td>Stamina</td>
<td>30 (125stm.)<br>50 (155stm.)</td>
<td></td>
</tr>
<tr>
<td></td>
<td>Equip Load</td>
<td>25 (72 wgt.)<br>60 (120 wgt.)</td>
<td></td>
</tr>
<tr>
<td>Strength</td>
<td>AR</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>
</tr>
<tr>
<td>Dexterity</td>
<td>AR</td>
<td>55, 80</td>
<td></td>
</tr>
<tr>
<td>Intelligence</td>
<td>AR</td>
<td>55, 80</td>
<td></td>
</tr>
<tr>
<td></td>
<td>Spell Buff</td>
<td>60, 80</td>
<td></td>
</tr>
<tr>
<td>Faith</td>
<td>AR</td>
<td>55, 80</td>
<td></td>
</tr>
<tr>
<td></td>
<td>Spell Buff</td>
<td>60, 80</td>
<td></td>
</tr>
<tr>
<td>Arcane</td>
<td>AR</td>
<td>55, 80</td>
<td></td>
</tr>
<tr>
<td></td>
<td>Status</td>
<td>45, 60</td>
<td></td>
</tr>
<tr>
<td></td>
<td>Spell Buff</td>
<td>60, 80 (Pure catalyst)<br>30, 45 (Hybrid catalyst)</td>
<td></td>
</tr>
</tbody>
</table>
</main>
<footer>
<h5>Erdtree Planner (<a href="https://git.palmoe.dk/vodofrede/erdtree">available under BSD-3-Clause license</a>)
</h5>
<h5>Copyright 2022 vodofrede</h5>
</footer>
</body>
<h3 style="text-align: center">Softcaps</h3>
<table>
<thead>
<tr>
<th>Skill</th>
<th>Stat</th>
<th>Softcaps</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td>Vigor</td>
<td>HP</td>
<td>25 (800HP)<br />40 (1450HP)<br />60 (1900HP)</td>
<td>A +12 upgraded crimson flask heals for 810HP.</td>
</tr>
<tr>
<td>Mind</td>
<td>FP</td>
<td>40 (220FP)</td>
<td>A +12 upgraded cerulean flask gives 220FP.</td>
</tr>
<tr>
<td>Endurance</td>
<td>Stamina</td>
<td>30 (125stm.)<br />50 (155stm.)</td>
<td></td>
</tr>
<tr>
<td></td>
<td>Equip Load</td>
<td>25 (72 wgt.)<br />60 (120 wgt.)</td>
<td></td>
</tr>
<tr>
<td>Strength</td>
<td>AR</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>
</tr>
<tr>
<td>Dexterity</td>
<td>AR</td>
<td>55, 80</td>
<td></td>
</tr>
<tr>
<td>Intelligence</td>
<td>AR</td>
<td>55, 80</td>
<td></td>
</tr>
<tr>
<td></td>
<td>Spell Buff</td>
<td>60, 80</td>
<td></td>
</tr>
<tr>
<td>Faith</td>
<td>AR</td>
<td>55, 80</td>
<td></td>
</tr>
<tr>
<td></td>
<td>Spell Buff</td>
<td>60, 80</td>
<td></td>
</tr>
<tr>
<td>Arcane</td>
<td>AR</td>
<td>55, 80</td>
<td></td>
</tr>
<tr>
<td></td>
<td>Status</td>
<td>45, 60</td>
<td></td>
</tr>
<tr>
<td></td>
<td>Spell Buff</td>
<td>60, 80 (Pure catalyst)<br />30, 45 (Hybrid catalyst)</td>
<td></td>
</tr>
</tbody>
</table>
</main>
<footer>
<h5>
Erdtree Planner (<a href="https://git.palmoe.dk/vodofrede/erdtree"
>available under BSD-3-Clause license</a
>)
</h5>
<h5>Copyright 2022 vodofrede</h5>
</footer>
</body>
</html>

View File

@ -135,15 +135,8 @@ function equipLoadBudget() {
// site rendering functions
function populateSelect(templateId, destinationId, items) {
let template = document.getElementById(templateId);
let destination = document.getElementById(destinationId);
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));
});
}

View File

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

View File

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

View File

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