zenno/spurt: calculator for last spurt speed
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
<a href={resolve('/inherit')} class="mx-8 my-1 inline-block">Inheritance Chance</a>
|
||||
<a href={resolve('/spark')} class="mx-8 my-1 inline-block">Spark Chance</a>
|
||||
<a href={resolve('/vet')} class="mx-8 my-1 inline-block">My Veterans</a>
|
||||
<a href={resolve('/spurt')} class="mx-8 my-1 inline-block">Spurt Speed</a>
|
||||
<a href={resolve('/convo')} class="mx-8 my-1 inline-block">Lobby Conversations</a>
|
||||
</span>
|
||||
</nav>
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
<a href={resolve('/vet')}>My Veterans</a> — <i>Not yet implemented</i> — Set up and track your veterans for Zenno Rob Roy's inspiration
|
||||
and spark calculators.
|
||||
</li>
|
||||
<li>
|
||||
<a href={resolve('/spurt')}>Spurt Speed</a> — Calculate a horse's target speed in the last spurt and compare to other distance aptitudes
|
||||
and running styles.
|
||||
</li>
|
||||
<li>
|
||||
<a href={resolve('/convo')}>Lobby Conversations</a> — Check participants in lobby conversations and get recommendations on unlocking
|
||||
them quickly.
|
||||
|
||||
@@ -38,5 +38,15 @@ a:hover {
|
||||
|
||||
select {
|
||||
background-color: light-dark(var(--color-mist-300), var(--color-mist-900));
|
||||
padding: 0.5rem 0.75rem;
|
||||
padding: 0 0.75rem;
|
||||
min-height: 1.5lh;
|
||||
}
|
||||
|
||||
input {
|
||||
background-color: light-dark(var(--color-mist-300), var(--color-mist-900));
|
||||
padding: 0 0.75rem;
|
||||
}
|
||||
|
||||
input[type='number'] {
|
||||
min-height: 1.5lh;
|
||||
}
|
||||
|
||||
97
zenno/src/routes/spurt/+page.svelte
Normal file
97
zenno/src/routes/spurt/+page.svelte
Normal file
@@ -0,0 +1,97 @@
|
||||
<script lang="ts">
|
||||
import { AptitudeLevel, inverseSpurtSpeed, RunningStyle, spurtSpeed } from '$lib/race';
|
||||
|
||||
const aptsList = Object.entries(AptitudeLevel).filter(([_name, val]) => typeof val === 'number');
|
||||
const stylesList = [
|
||||
['Front Runner', RunningStyle.FrontRunner],
|
||||
['Pace Chaser', RunningStyle.PaceChaser],
|
||||
['Late Surger', RunningStyle.LateSurger],
|
||||
['End Closer', RunningStyle.EndCloser],
|
||||
['Great Escape', RunningStyle.GreatEscape],
|
||||
] as const;
|
||||
|
||||
let rawSpeed: number = $state(1200);
|
||||
let rawGuts: number = $state(1200);
|
||||
let style: RunningStyle = $state(RunningStyle.FrontRunner);
|
||||
let distanceApt: AptitudeLevel = $state(AptitudeLevel.S);
|
||||
let raceLen: number = $state(2000);
|
||||
let isCareer: boolean = $state(false);
|
||||
|
||||
const careerMod = $derived(isCareer ? 400 : 0);
|
||||
const speedStat = $derived(rawSpeed + careerMod);
|
||||
const gutsStat = $derived(rawGuts + careerMod);
|
||||
const speed = $derived(spurtSpeed(speedStat, gutsStat, style, distanceApt, raceLen));
|
||||
|
||||
const sProf = $derived([
|
||||
inverseSpurtSpeed(speed, gutsStat, RunningStyle.FrontRunner, AptitudeLevel.S, raceLen) - careerMod,
|
||||
inverseSpurtSpeed(speed, gutsStat, RunningStyle.PaceChaser, AptitudeLevel.S, raceLen) - careerMod,
|
||||
inverseSpurtSpeed(speed, gutsStat, RunningStyle.LateSurger, AptitudeLevel.S, raceLen) - careerMod,
|
||||
inverseSpurtSpeed(speed, gutsStat, RunningStyle.EndCloser, AptitudeLevel.S, raceLen) - careerMod,
|
||||
inverseSpurtSpeed(speed, gutsStat, RunningStyle.GreatEscape, AptitudeLevel.S, raceLen) - careerMod,
|
||||
]);
|
||||
const aProf = $derived([
|
||||
inverseSpurtSpeed(speed, gutsStat, RunningStyle.FrontRunner, AptitudeLevel.A, raceLen) - careerMod,
|
||||
inverseSpurtSpeed(speed, gutsStat, RunningStyle.PaceChaser, AptitudeLevel.A, raceLen) - careerMod,
|
||||
inverseSpurtSpeed(speed, gutsStat, RunningStyle.LateSurger, AptitudeLevel.A, raceLen) - careerMod,
|
||||
inverseSpurtSpeed(speed, gutsStat, RunningStyle.EndCloser, AptitudeLevel.A, raceLen) - careerMod,
|
||||
inverseSpurtSpeed(speed, gutsStat, RunningStyle.GreatEscape, AptitudeLevel.A, raceLen) - careerMod,
|
||||
]);
|
||||
</script>
|
||||
|
||||
<h1 class="text-4xl">Spurt Speed Calculator</h1>
|
||||
<div class="mx-auto mt-8 grid max-w-4xl grid-cols-1 rounded-md text-center shadow-md ring md:grid-cols-4">
|
||||
<div class="m-4">
|
||||
<label for="speedStat">Speed Stat</label>
|
||||
<input type="number" id="speedStat" required bind:value={rawSpeed} class="w-full" />
|
||||
</div>
|
||||
<div class="m-4">
|
||||
<label for="gutsStat">Guts Stat</label>
|
||||
<input type="number" id="gutsStat" required bind:value={rawGuts} class="w-full" />
|
||||
</div>
|
||||
<div class="m-4">
|
||||
<label for="style">Style</label>
|
||||
<select id="style" required bind:value={style} class="w-full">
|
||||
{#each stylesList as [name, style]}
|
||||
<option value={style}>{style === RunningStyle.GreatEscape ? 'Great Escape (Runaway)' : name}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
<div class="m-4">
|
||||
<label for="distanceApt">Distance Aptitude</label>
|
||||
<select id="distanceApt" required bind:value={distanceApt} class="w-full">
|
||||
{#each aptsList.toReversed() as [name, val] (val)}
|
||||
<option value={val}>{name}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
<div class="m-4 md:col-start-2">
|
||||
<label for="raceLen">Race Distance</label>
|
||||
<input type="number" id="raceLen" required bind:value={raceLen} class="w-full" />
|
||||
</div>
|
||||
<div class="m-4 self-center">
|
||||
<label for="isCareer" class="mr-1 align-middle">In Career</label>
|
||||
<input type="checkbox" id="isCareer" role="switch" bind:checked={isCareer} class="min-h-6 min-w-6 align-middle" />
|
||||
</div>
|
||||
</div>
|
||||
<span class="mt-8 block w-full text-center text-lg">
|
||||
Target spurt speed: {speed.toFixed(3)} m/s
|
||||
</span>
|
||||
{#each [[AptitudeLevel.A, aProf] as const, [AptitudeLevel.S, sProf] as const] as [level, inv] (level)}
|
||||
<div class="mx-auto max-w-3xl">
|
||||
<span class="mt-8 block w-full">
|
||||
With {AptitudeLevel[level]} proficiency, the equivalent speed is
|
||||
</span>
|
||||
<div class="flex flex-col md:flex-row">
|
||||
{#each stylesList as [styleName, s] (s)}
|
||||
<div
|
||||
class={['m-2 flex-1 rounded-md border shadow-sm transition-shadow hover:shadow-md', s === style ? 'border-2' : null]}
|
||||
>
|
||||
<div class="h-full w-full flex-col text-center">
|
||||
<span class="block text-lg">{styleName}</span>
|
||||
<span class="block text-2xl">{inv[s]}</span>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
Reference in New Issue
Block a user