1 Commits
Author SHA1 Message Date
zephyr 56bd5b460d zenno/doc/race: better section speed charts
ci/woodpecker/push/zenno Pipeline was successful
ci/woodpecker/push/horsebot Pipeline was successful
Fixes #49.
2026-11-05 14:45:59 -05:00
+57 -53
View File
@@ -7,10 +7,6 @@
import { resolve } from '$app/paths'; import { resolve } from '$app/paths';
import RaceLenSlider from '$lib/RaceLenSlider.svelte'; import RaceLenSlider from '$lib/RaceLenSlider.svelte';
function modemean(x: number, bonus: number, p: number): number {
return x * (1 - p) + x * bonus * p;
}
let style = $state(race.RunningStyle.FrontRunner); let style = $state(race.RunningStyle.FrontRunner);
let surfaceApt = $state(race.AptitudeLevel.A); let surfaceApt = $state(race.AptitudeLevel.A);
let distanceApt = $state(race.AptitudeLevel.A); let distanceApt = $state(race.AptitudeLevel.A);
@@ -84,39 +80,39 @@
]; ];
const duelSpeed: ComputedSeries[] = [{ label: 'Dueling Speed Boost', y: (x) => race.duelSpeedMod(x) }]; const duelSpeed: ComputedSeries[] = [{ label: 'Dueling Speed Boost', y: (x) => race.duelSpeedMod(x) }];
const duelAccel: ComputedSeries[] = [{ label: 'Dueling Acceleration Boost', y: (x) => race.duelAccelMod(x) }]; const duelAccel: ComputedSeries[] = [{ label: 'Dueling Acceleration Boost', y: (x) => race.duelAccelMod(x) }];
const secSpeed: Array<ComputedAreas | null> = $derived([ const secSpeedEarly: Array<ComputedAreas | null> = $derived([
{ {
label: 'Early Race', label: styleIsFront ? 'Front S' : 'Style S',
y1: (x) => race.sectionSpeed(raceLen, x * 1.1, style, race.Phase.EarlyRace)[0],
y2: (x) => race.sectionSpeed(raceLen, x * 1.1, style, race.Phase.EarlyRace)[1],
},
{
label: styleIsFront ? 'Front A' : 'Style A',
y1: (x) => race.sectionSpeed(raceLen, x, style, race.Phase.EarlyRace)[0], y1: (x) => race.sectionSpeed(raceLen, x, style, race.Phase.EarlyRace)[0],
y2: (x) => race.sectionSpeed(raceLen, x, style, race.Phase.EarlyRace)[1], y2: (x) => race.sectionSpeed(raceLen, x, style, race.Phase.EarlyRace)[1],
}, },
{ {
label: 'Mid Race', label: styleIsFront ? 'Front A Speed-Up Mode' : 'Style A Pace-Up Mode',
y1: (x) => race.sectionSpeed(raceLen, x, style, race.Phase.EarlyRace)[0] * 1.04,
y2: (x) => race.sectionSpeed(raceLen, x, style, race.Phase.EarlyRace)[1] * 1.04,
},
]);
const secSpeedMid: Array<ComputedAreas | null> = $derived([
{
label: styleIsFront ? 'Front S' : 'Style S',
y1: (x) => race.sectionSpeed(raceLen, x * 1.1, style, race.Phase.MidRace)[0],
y2: (x) => race.sectionSpeed(raceLen, x * 1.1, style, race.Phase.MidRace)[1],
},
{
label: styleIsFront ? 'Front A' : 'Style A',
y1: (x) => race.sectionSpeed(raceLen, x, style, race.Phase.MidRace)[0], y1: (x) => race.sectionSpeed(raceLen, x, style, race.Phase.MidRace)[0],
y2: (x) => race.sectionSpeed(raceLen, x, style, race.Phase.MidRace)[1], y2: (x) => race.sectionSpeed(raceLen, x, style, race.Phase.MidRace)[1],
}, },
styleIsFront {
? { label: styleIsFront ? 'Front A Speed-Up Mode' : 'Style A Pace-Up Mode',
label: 'Early Race + Mean Speed-Up Mode', y1: (x) => race.sectionSpeed(raceLen, x, style, race.Phase.MidRace)[0] * 1.04,
y1: (x) => modemean(race.sectionSpeed(raceLen, x, style, race.Phase.EarlyRace)[0], 1.04, race.frontModeEnterChance(x)), y2: (x) => race.sectionSpeed(raceLen, x, style, race.Phase.MidRace)[1] * 1.04,
y2: (x) => modemean(race.sectionSpeed(raceLen, x, style, race.Phase.EarlyRace)[1], 1.04, race.frontModeEnterChance(x)), },
}
: {
label: 'Early Race + Mean Pace-Up Mode',
y1: (x) => modemean(race.sectionSpeed(raceLen, x, style, race.Phase.EarlyRace)[0], 1.04, race.paceUpEnterChance(x)),
y2: (x) => modemean(race.sectionSpeed(raceLen, x, style, race.Phase.EarlyRace)[1], 1.04, race.paceUpEnterChance(x)),
},
styleIsFront
? {
label: 'Mid Race + Mean Speed-Up Mode',
y1: (x) => modemean(race.sectionSpeed(raceLen, x, style, race.Phase.MidRace)[0], 1.04, race.frontModeEnterChance(x)),
y2: (x) => modemean(race.sectionSpeed(raceLen, x, style, race.Phase.MidRace)[1], 1.04, race.frontModeEnterChance(x)),
}
: {
label: 'Mid Race + Mean Pace-Up Mode',
y1: (x) => modemean(race.sectionSpeed(raceLen, x, style, race.Phase.MidRace)[0], 1.04, race.paceUpEnterChance(x)),
y2: (x) => modemean(race.sectionSpeed(raceLen, x, style, race.Phase.MidRace)[1], 1.04, race.paceUpEnterChance(x)),
},
]); ]);
const downhill: ComputedSeries[] = [ const downhill: ComputedSeries[] = [
{ label: 'Style S', y: (x) => race.downhillAccelEnterChance(x * 1.1) * 100 }, { label: 'Style S', y: (x) => race.downhillAccelEnterChance(x * 1.1) * 100 },
@@ -396,34 +392,42 @@
>Section Speed</Sec >Section Speed</Sec
> >
<p>Random variance in target speed per race section.</p> <p>Random variance in target speed per race section.</p>
<div class="mb-24 h-60 w-full md:mb-20 md:h-96"> <div class="mb-10 grid h-96 w-full md:grid-cols-2">
<StatChart <StatChart
class="mx-auto mb-12 h-full w-full max-w-3xl md:mb-10"
stat={race.Stat.Wit} stat={race.Stat.Wit}
yArea={secSpeed} yArea={secSpeedEarly}
yLabel="Section Speed (m/s)" yLabel="Early Race Section Speed (m/s)"
range={[17, 23]} range={[17, 23.5]}
plotOptions={{ color: { legend: true } }} plotOptions={{ color: { legend: true } }}
class="h-96 max-h-96"
/> />
<div class="mx-auto flex w-full md:max-w-2xl"> <StatChart
<label class="my-auto hidden flex-1 pr-2 text-right text-sm md:inline" for="secSpeedRaceLen">Race Length</label> stat={race.Stat.Wit}
<input yArea={secSpeedMid}
class="my-auto max-w-40 flex-1 md:flex-2" yLabel="Mid Race Section Speed (m/s)"
type="range" range={[17, 23.5]}
id="secSpeedRaceLen" plotOptions={{ color: { legend: true } }}
min="1000" class="h-96 max-h-96"
max="3600" />
step="100" </div>
bind:value={raceLen} <div class="mx-auto mb-4 flex w-full md:max-w-2xl">
/> <label class="my-auto hidden flex-1 pr-2 text-right text-sm md:inline" for="secSpeedRaceLen">Race Length</label>
<span class="my-auto flex-1 pl-2 text-sm">{raceLen}m</span> <input
<label class="my-auto hidden flex-1 pr-2 text-right text-sm md:inline" for="secSpeedStyle">Style</label> class="my-auto max-w-40 flex-1 md:flex-2"
<select class="my-auto flex-1 text-sm" id="secSpeedStyle" bind:value={style}> type="range"
{#each race.RUNNING_STYLES as [name, style] (style)} id="secSpeedRaceLen"
<option value={style}>{name}</option> min="1000"
{/each} max="3600"
</select> step="100"
</div> bind:value={raceLen}
/>
<span class="my-auto flex-1 pl-2 text-sm">{raceLen}m</span>
<label class="my-auto hidden flex-1 pr-2 text-right text-sm md:inline" for="secSpeedStyle">Style</label>
<select class="my-auto flex-1 text-sm" id="secSpeedStyle" bind:value={style}>
{#each race.RUNNING_STYLES as [name, style] (style)}
<option value={style}>{name}</option>
{/each}
</select>
</div> </div>
<Sec <Sec