zenno: categorize tools

This commit is contained in:
2026-06-10 14:03:42 -04:00
parent dc78d51def
commit 75024c7c11
18 changed files with 119 additions and 42 deletions

View File

@@ -1,6 +1,3 @@
import { affinity, lookup } from './data/affinity';
import { uma, type Uma } from './data/uma';
/** /**
* A legacy, or parents and grandparents. * A legacy, or parents and grandparents.
* Defined as an applicative over generic types to reduce the API surface. * Defined as an applicative over generic types to reduce the API surface.
@@ -41,9 +38,9 @@ export interface Veteran {
saddles: number[]; saddles: number[];
} }
function findUma(umas: Uma[], u: number): Uma | null { // function findUma(umas: Uma[], u: number): Uma | null {
return umas.find((v) => v.chara_card_id === u) ?? null; // return umas.find((v) => v.chara_card_id === u) ?? null;
} // }
/** /**
* Compute individual affinities for a legacy using the global region ruleset. * Compute individual affinities for a legacy using the global region ruleset.
@@ -51,6 +48,7 @@ function findUma(umas: Uma[], u: number): Uma | null {
* @param legacy Legacy veterans * @param legacy Legacy veterans
* @returns Individual affinities * @returns Individual affinities
*/ */
/*
export function globalAffinity(trainee: number, legacy: Legacy<Veteran>): Legacy<number> { export function globalAffinity(trainee: number, legacy: Legacy<Veteran>): Legacy<number> {
const t = findUma(uma.global, trainee)?.chara_id ?? 0; const t = findUma(uma.global, trainee)?.chara_id ?? 0;
const charas = mapLegacy(legacy, (u) => findUma(uma.global, u.uma)?.chara_id ?? 0); const charas = mapLegacy(legacy, (u) => findUma(uma.global, u.uma)?.chara_id ?? 0);
@@ -70,3 +68,4 @@ export function globalAffinity(trainee: number, legacy: Legacy<Veteran>): Legacy
s22, s22,
}; };
} }
*/

View File

@@ -0,0 +1,14 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { resolve } from '$app/paths';
import { onMount } from 'svelte';
onMount(() => {
goto(resolve('/chara/affinity'), { replaceState: true });
});
</script>
<p class="mt-8 block w-full text-center text-4xl">
<a href={resolve('/chara/affinity')}>This page has moved.</a>
</p>
<p class="mt-8 block w-full text-center">You should be redirected momentarily.</p>

View File

@@ -0,0 +1,14 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { resolve } from '$app/paths';
import { onMount } from 'svelte';
onMount(() => {
goto(resolve('/chara/convo'), { replaceState: true });
});
</script>
<p class="mt-8 block w-full text-center text-4xl">
<a href={resolve('/chara/convo')}>This page has moved.</a>
</p>
<p class="mt-8 block w-full text-center">You should be redirected momentarily.</p>

View File

@@ -0,0 +1,14 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { resolve } from '$app/paths';
import { onMount } from 'svelte';
onMount(() => {
goto(resolve('/race/mspeed'), { replaceState: true });
});
</script>
<p class="mt-8 block w-full text-center text-4xl">
<a href={resolve('/race/mspeed')}>This page has moved.</a>
</p>
<p class="mt-8 block w-full text-center">You should be redirected momentarily.</p>

View File

@@ -0,0 +1,14 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { resolve } from '$app/paths';
import { onMount } from 'svelte';
onMount(() => {
goto(resolve('/race/spurt'), { replaceState: true });
});
</script>
<p class="mt-8 block w-full text-center text-4xl">
<a href={resolve('/race/spurt')}>This page has moved.</a>
</p>
<p class="mt-8 block w-full text-center">You should be redirected momentarily.</p>

View File

@@ -2,7 +2,6 @@
import './layout.css'; import './layout.css';
import favicon from '$lib/assets/favicon.png'; import favicon from '$lib/assets/favicon.png';
import { resolve } from '$app/paths'; import { resolve } from '$app/paths';
import { affinity } from '$lib/data/affinity';
let { children } = $props(); let { children } = $props();
</script> </script>
@@ -19,10 +18,8 @@
</span> </span>
<span class="flex-1 text-center"> <span class="flex-1 text-center">
<a href={resolve('/')} class="mx-8 my-1 block font-semibold md:hidden">Zenno Rob Roy</a> <a href={resolve('/')} class="mx-8 my-1 block font-semibold md:hidden">Zenno Rob Roy</a>
<a href={resolve('/spurt')} class="mx-8 my-1 inline-block">Spurt Speed</a> <a href={resolve('/race')} class="mx-8 my-1 inline-block">Race Tools</a>
<a href={resolve('/mspeed')} class="mx-8 my-1 inline-block">Mechanical Speed</a> <a href={resolve('/chara')} class="mx-8 my-1 inline-block">Character Tools</a>
<a href={resolve('/affinity')} class="mx-8 my-1 inline-block">Affinity Details</a>
<a href={resolve('/convo')} class="mx-8 my-1 inline-block">Lobby Conversations</a>
<a href={resolve('/doc')} class="mx-8 my-1 inline-block">Documents</a> <a href={resolve('/doc')} class="mx-8 my-1 inline-block">Documents</a>
</span> </span>
</nav> </nav>

View File

@@ -5,22 +5,26 @@
<h1 class="m-8 text-center text-7xl">Zenno Rob Roy</h1> <h1 class="m-8 text-center text-7xl">Zenno Rob Roy</h1>
<p>She's read all about Umamusume, and she's always happy to share her knowledge and give recommendations!</p> <p>She's read all about Umamusume, and she's always happy to share her knowledge and give recommendations!</p>
<h2 class="mt-8 mb-4 text-4xl">Tools</h2> <h2 class="mt-8 mb-4 text-4xl">Race Mechanics Tools</h2>
<ul class="mb-4 list-disc pl-4"> <ul class="mb-4 list-disc pl-4">
<li> <li>
<a href={resolve('/spurt')}>Spurt Speed</a> &mdash; Calculate a horse's target speed in the last spurt and compare to other distance aptitudes <a href={resolve('/race/spurt')}>Spurt Speed</a> &mdash; Calculate a horse's target speed in the last spurt and compare to other
and running styles. distance aptitudes and running styles.
</li> </li>
<li> <li>
<a href={resolve('/mspeed')}>Front Runner Mechanical Speed Comparator</a> &mdash; Compare spot struggle and lane combo to the effects <a href={resolve('/race/mspeed')}>Front Runner Mechanical Speed Comparator</a> &mdash; Compare spot struggle and lane combo to the
of individual skills. effects of individual skills.
</li>
</ul>
<h2 class="mt-8 mb-4 text-4xl">Character Tools</h2>
<ul>
<li>
<a href={resolve('/chara/affinity')}>Affinity Details</a> &mdash; Details of why characters have the base compatibility numbers
they have.
</li> </li>
<li> <li>
<a href={resolve('/affinity')}>Affinity Details</a> &mdash; Details of why characters have the base compatibility numbers they have. <a href={resolve('/chara/convo')}>Lobby Conversations</a> &mdash; Check participants in lobby conversations and get recommendations
</li> on unlocking them quickly.
<li>
<a href={resolve('/convo')}>Lobby Conversations</a> &mdash; Check participants in lobby conversations and get recommendations on unlocking
them quickly.
</li> </li>
<li> <li>
<a href="https://discord.com/oauth2/authorize?client_id=1461931240264568994" target="_blank" rel="noopener noreferrer" <a href="https://discord.com/oauth2/authorize?client_id=1461931240264568994" target="_blank" rel="noopener noreferrer"

View File

@@ -0,0 +1,17 @@
<script lang="ts">
import { resolve } from '$app/paths';
</script>
<h1 class="m-8 text-center text-7xl">Zenno Rob Roy &mdash; Character Tools</h1>
<p>Tools related to understanding Umamusume characters.</p>
<ul class="mb-4 list-disc pl-4">
<li>
<a href={resolve('/chara/affinity')}>Affinity Details</a> &mdash; Details of why characters have the base compatibility numbers
they have.
</li>
<li>
<a href={resolve('/chara/convo')}>Lobby Conversations</a> &mdash; Check participants in lobby conversations and get recommendations
on unlocking them quickly.
</li>
</ul>

View File

@@ -416,8 +416,8 @@
<p> <p>
In medium+ races, the extra HP consumption is a serious consideration; front runners need more stamina and recoveries than In medium+ races, the extra HP consumption is a serious consideration; front runners need more stamina and recoveries than
other styles. At 1600m and shorter, the fact that Spot Struggle doesn't scale with race distance means that it can be worth other styles. At 1600m and shorter, the fact that Spot Struggle doesn't scale with race distance means that it can be worth
multiple gold speed skills in total distance gained. See the <a href={resolve('/mspeed')}>mechanical speed calculator</a> for precise multiple gold speed skills in total distance gained. See the <a href={resolve('/race/mspeed')}>mechanical speed calculator</a> for
analysis. precise analysis.
</p> </p>
<Sec h={3} id="lane-combo">Lane Combo</Sec> <Sec h={3} id="lane-combo">Lane Combo</Sec>
@@ -471,8 +471,8 @@
consistency at the cost of lowering the maximum gain. consistency at the cost of lowering the maximum gain.
</p> </p>
<p> <p>
The <a href={resolve('/mspeed')}>mechanical speed calculator</a> has an approximation of lane combo's benefit. A more precise The <a href={resolve('/race/mspeed')}>mechanical speed calculator</a> has an approximation of lane combo's benefit. A more
lane combo simulator exists at precise lane combo simulator exists at
<a href="https://lanecalc.hf-uma.net/" target="_blank" rel="noopener noreferrer">危険回避シミュ</a>, but I am not sufficiently <a href="https://lanecalc.hf-uma.net/" target="_blank" rel="noopener noreferrer">危険回避シミュ</a>, but I am not sufficiently
confident in my Japanese to try to guide readers through it. confident in my Japanese to try to guide readers through it.
<!-- TODO(zeph): i could totally annotate a picture though, or find someone else's explanation --> <!-- TODO(zeph): i could totally annotate a picture though, or find someone else's explanation -->
@@ -682,7 +682,7 @@
Angling, they are almost certainly a different running style. Angling, they are almost certainly a different running style.
</p> </p>
<p> <p>
The <a href={resolve('/spurt')}>spurt speed calculator</a> analyzes this situation. A 1200 speed front runner with a 0.25 speed The <a href={resolve('/race/spurt')}>spurt speed calculator</a> analyzes this situation. A 1200 speed front runner with a 0.25 speed
skill active has speed equivalent to an 1187 speed pace chaser. In other words, as long as that pace chaser is built the way Global skill active has speed equivalent to an 1187 speed pace chaser. In other words, as long as that pace chaser is built the way Global
players tend to build, Pulse does not allow the front runner to pass back. So, if you happen to inherit it off a grandparent, it players tend to build, Pulse does not allow the front runner to pass back. So, if you happen to inherit it off a grandparent, it
is not worth taking. is not worth taking.
@@ -868,7 +868,7 @@
<p> <p>
SS supports do best on medium and long tracks, because you want to be building <i>everyone</i> for spot struggle on miles and SS supports do best on medium and long tracks, because you want to be building <i>everyone</i> for spot struggle on miles and
sprints. However, spot struggle is the only mechanic in the game that scales superlinearly with stats, so even the difference sprints. However, spot struggle is the only mechanic in the game that scales superlinearly with stats, so even the difference
between 1200 and 1000 guts can matter. See the <a href={resolve('/mspeed')}>mechanical speed calculator</a> for details. between 1200 and 1000 guts can matter. See the <a href={resolve('/race/mspeed')}>mechanical speed calculator</a> for details.
</p> </p>
<Sec h={3} id="chariot">Chariot</Sec> <Sec h={3} id="chariot">Chariot</Sec>
@@ -996,8 +996,8 @@
</p> </p>
<p> <p>
As a corollary, you also cannot win this race with B mile. A miraculous start can get to 350 speed for this race; a B mile As a corollary, you also cannot win this race with B mile. A miraculous start can get to 350 speed for this race; a B mile
runner with 350 speed is equivalent to an A mile runner with only 207 speed in career. See the <a href={resolve('/spurt')} runner with 350 speed is equivalent to an A mile runner with only 207 speed in career. See the <a
>spurt calculator</a href={resolve('/race/spurt')}>spurt calculator</a
>. (This race is why I made it.) >. (This race is why I made it.)
</p> </p>

View File

@@ -1,3 +0,0 @@
<h1>Inheritance Chance</h1>
<p>Given a legacy, calculate the probability distribution of activation counts for each spark.</p>
<p>TODO</p>

View File

@@ -0,0 +1,17 @@
<script lang="ts">
import { resolve } from '$app/paths';
</script>
<h1 class="m-8 text-center text-7xl">Zenno Rob Roy &mdash; Character Tools</h1>
<p>Tools related to understanding Umamusume characters.</p>
<ul class="mb-4 list-disc pl-4">
<li>
<a href={resolve('/race/spurt')}>Spurt Speed</a> &mdash; Calculate a horse's target speed in the last spurt and compare to other
distance aptitudes and running styles.
</li>
<li>
<a href={resolve('/race/mspeed')}>Front Runner Mechanical Speed Comparator</a> &mdash; Compare spot struggle and lane combo to the
effects of individual skills.
</li>
</ul>

View File

@@ -1,6 +0,0 @@
<h1>Spark Generation Chance</h1>
<p>
Given a legacy, calculate the chance of generating each spark if you fulfill the conditions to do so, and the distribution of
total spark counts.
</p>
<p>TODO</p>

View File

@@ -1,4 +0,0 @@
<h1>My Veterans</h1>
<p>Set up and track your veterans for Zenno Rob Roy's inspiration and spark calculators.</p>
<p>All data is saved on your own machine, not transmitted or shared unless you explicitly choose to do so.</p>
<p>TODO</p>