zenno: don't use sakura

This commit is contained in:
2026-03-31 16:52:37 -04:00
parent 773625b842
commit d157dfc9b6
5 changed files with 104 additions and 454 deletions

View File

@@ -7,9 +7,10 @@
<svelte:head><link rel="icon" href={favicon} /></svelte:head> <svelte:head><link rel="icon" href={favicon} /></svelte:head>
<nav class="mb-4 flex min-w-full p-4 shadow-md"> <div class="flex h-screen flex-col">
<nav class="mb-4 flex min-w-full bg-mist-300 p-4 shadow-md dark:bg-mist-900">
<span class="hidden flex-1 md:inline"> <span class="hidden flex-1 md:inline">
<a href="/" class="text-7xl">Zenno Rob Roy</a> <a href="/" class="text-4xl">Zenno Rob Roy</a>
</span> </span>
<span class="flex-1 text-center"> <span class="flex-1 text-center">
<a href="/" class="mx-8 my-1 block font-semibold md:hidden">Zenno Rob Roy</a> <a href="/" class="mx-8 my-1 block font-semibold md:hidden">Zenno Rob Roy</a>
@@ -18,11 +19,12 @@
<a href="/vet" class="mx-8 my-1 inline-block">My Veterans</a> <a href="/vet" class="mx-8 my-1 inline-block">My Veterans</a>
<a href="/convo" class="mx-8 my-1 inline-block">Lobby Conversations</a> <a href="/convo" class="mx-8 my-1 inline-block">Lobby Conversations</a>
</span> </span>
</nav> </nav>
<div class="md:m-auto md:max-w-7xl md:min-w-7xl"> <div class="mx-4 grow lg:m-auto lg:max-w-7xl lg:min-w-7xl">
{@render children()} {@render children()}
</div> </div>
<footer class="inset-x-0 bottom-0 mt-32 border-t p-4 text-center text-[14px]"> <footer class="inset-x-0 bottom-0 mt-8 border-t bg-mist-300 p-4 text-center text-sm md:mt-20 dark:border-none dark:bg-mist-900">
Umamusume: Pretty Derby tools by <a href="https://zephyrtronium.date/">zephyrtronium</a>.<br /> Umamusume: Pretty Derby tools by <a href="https://zephyrtronium.date/">zephyrtronium</a>.<br />
All data is generated from the game's local database. All data is generated from the game's local database.
</footer> </footer>
</div>

View File

@@ -1,13 +1,26 @@
<script lang="ts"> <h1 class="m-8 text-center text-7xl">Zenno Rob Roy</h1>
import CharaPick from '$lib/CharaPick.svelte'; <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>
let selChara = $state(0); <ul class="list-disc pl-4">
</script> <li>
<a href="/inherit">Inheritance Chance</a><i>Not yet implemented</i> — Given a legacy, calculate the probability distribution
<h1>Welcome to SvelteKit</h1> of activation counts for each spark.
<CharaPick id="test-chara" bind:value={selChara} /> </li>
<p>selected character is id {selChara}</p> <li>
<p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p> <a href="/spark">Spark Chance</a><i>Not yet implemented</i> — 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.
</li>
<li>
<a href="/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="/convo">Lobby Conversations</a> — Check participants in lobby conversations and get recommendations on unlocking them quickly.
</li>
</ul>
<h2 class="mt-8 mb-4 text-4xl">About</h2>
<p>Tools to fill some gaps I've felt in Umamusume optimization.</p>
<p>This site is very under construction. To demonstrate just how under construction it is, here is lorem ipsum:</p>
<p> <p>
Lorem ipsum (/ ˌ l ɔː. r ə m ˈ ɪ p. s ə m/ LOR-əm IP-səm) is a dummy or placeholder text commonly used in graphic design, Lorem ipsum (/ ˌ l ɔː. r ə m ˈ ɪ p. s ə m/ LOR-əm IP-səm) is a dummy or placeholder text commonly used in graphic design,
publishing, and web development. It is typically a corrupted version of De finibus bonorum et malorum, a 1st-century BC text by publishing, and web development. It is typically a corrupted version of De finibus bonorum et malorum, a 1st-century BC text by

View File

@@ -3,33 +3,32 @@
import { byChara, locations, groupPopulars } from '$lib/data/convo'; import { byChara, locations, groupPopulars } from '$lib/data/convo';
import CharaPick from '$lib/CharaPick.svelte'; import CharaPick from '$lib/CharaPick.svelte';
const minSuggest = 8;
let charaID = $state(1001); let charaID = $state(1001);
let convo = $state(1); let convo = $state(1);
let options = $derived(byChara.global.get(charaID) ?? []); let options = $derived(byChara.global.get(charaID) ?? []);
let cur = $derived(options.find((c) => c.number === convo)); let cur = $derived(options.find((c) => c.number === convo));
let suggested = $derived.by(() => {
function suggest(n: number, pops: (typeof groupPopulars)['global']) {
if (cur == null) { if (cur == null) {
return []; return [];
} }
const u = pops[locations[cur.location].group].filter( const u = groupPopulars.global[locations[cur.location].group].filter(
(s) => charaNames.get(s[0]) != null && s[0] !== cur.chara_1 && s[0] !== cur.chara_2 && s[0] !== cur.chara_3, (s) => charaNames.get(s[0]) != null && s[0] !== cur.chara_1 && s[0] !== cur.chara_2 && s[0] !== cur.chara_3,
); );
if (u.length <= n) { const r = u.length <= minSuggest ? u : u.filter((s) => s[1] >= u[minSuggest][1]);
return u; return r.map(([chara_id, count]) => ({ chara_id, count }));
} });
return u.filter((s) => s[1] >= u[n][1]);
}
</script> </script>
<h1>Lobby Conversations</h1> <h1 class="text-4xl">Lobby Conversations</h1>
<div class="mt-8 flex text-center"> <div class="mx-auto mt-8 flex flex-col rounded-md text-center shadow-md ring md:max-w-xl md:flex-row">
<div class="flex-1"> <div class="m-4 flex-1 md:mt-3">
<CharaPick id="chara" class="w-full" label="Character" bind:value={charaID} required /> <CharaPick id="chara" class="w-full" label="Character" labelClass="hidden md:inline" bind:value={charaID} required />
</div> </div>
<div class="flex-1"> <div class="m-4 flex-1 md:mt-3">
<label for="convo">Conversation</label> <label for="convo" class="hidden md:inline">Conversation</label>
<select id="convo" bind:value={convo} class="w-full"> <select id="convo" bind:value={convo} class="w-full">
{#each options as opt} {#each options as opt}
<option value={opt.number}>Slice of Life {opt.number}</option> <option value={opt.number}>Slice of Life {opt.number}</option>
@@ -39,8 +38,10 @@
</div> </div>
{#if cur} {#if cur}
<div class="shadow-sm transition-shadow hover:shadow-md"> <div class="shadow-sm transition-shadow hover:shadow-md">
<div class="mt-8 flex text-center"> <div class="mt-8 flex text-center text-lg">
<span class="flex-1">{charaNames.get(cur.chara_1)?.en ?? 'someone not a trainee'}</span> <span class="flex-1"
>{charaNames.get(cur.chara_1)?.en ?? 'someone not a trainee'}{(cur.chara_2 ?? cur.chara_3) == null ? ' alone' : ''}</span
>
{#if cur.chara_2} {#if cur.chara_2}
<span class="flex-1">{charaNames.get(cur.chara_2)?.en ?? 'someone not a trainee'}</span> <span class="flex-1">{charaNames.get(cur.chara_2)?.en ?? 'someone not a trainee'}</span>
{/if} {/if}
@@ -48,22 +49,21 @@
<span class="flex-1">{charaNames.get(cur.chara_3)?.en ?? 'someone not a trainee'}</span> <span class="flex-1">{charaNames.get(cur.chara_3)?.en ?? 'someone not a trainee'}</span>
{/if} {/if}
</div> </div>
<div class="mt-4 flex w-full text-center"> <div class="flex w-full text-center text-lg">
<span class="flex-1">at {locations[cur.location].name.en}</span> <span class="flex-1">at {locations[cur.location].name.en}</span>
</div> </div>
</div> </div>
<div class="mt-4 block text-center"> <div class="mt-4 block text-center">
<span>Characters who appear here most often:</span> <span>Other characters who appear here most often:</span>
</div> </div>
<div class="mt-4 grid text-center shadow-sm transition-shadow ease-in hover:shadow-md hover:ease-out md:grid-cols-4"> <div class="mt-4 grid text-center shadow-sm transition-shadow ease-in hover:shadow-md hover:ease-out md:grid-cols-4">
{#each suggest(8, groupPopulars.global) as s} {#each suggested as s}
<span>{charaNames.get(s[0])?.en}: {s[1]}&#xd7;</span> <span>{charaNames.get(s.chara_id)?.en}: {s.count}&#xd7;</span>
{/each} {/each}
</div> </div>
<div class="mt-4 block text-center"> <div class="mt-4 block text-center">
<span> <span>
Set characters that appear more often to fixed positions (main, upgrades, story, races) to maximize the chance of getting Set these characters to fixed positions (main, upgrades, story, races) to maximize the chance of getting this conversation.
this conversation.
</span> </span>
</div> </div>
{/if} {/if}

View File

@@ -1,6 +1,42 @@
@import 'tailwindcss'; @import 'tailwindcss';
@import './sakura-vars.css';
@theme { :root {
--text-sm: 1.25rem; color-scheme: light dark;
}
html,
body {
height: 100%;
padding: 0;
margin: 0;
}
html {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif;
}
body {
background-color: light-dark(var(--color-mist-200), var(--color-mist-800));
color: light-dark(var(--color-amber-950), var(--color-amber-50));
}
p {
margin-bottom: calc(var(--spacing) * 4);
}
a {
color: light-dark(var(--color-sky-900), var(--color-sky-100));
}
nav > span > a {
color: light-dark(var(--color-amber-950), var(--color-amber-50));
}
a:hover {
border-bottom-width: 1px;
}
select {
background-color: light-dark(var(--color-mist-300), var(--color-mist-900));
padding: 0.5rem 0.75rem;
} }

View File

@@ -1,401 +0,0 @@
/* Sakura.css v1.5.0
* ================
* Minimal css theme.
* Project: https://github.com/oxalorg/sakura/
*/
/* data-theme="taiyō" */
:root {
--blossom: #292722;
--fade: #7d7768;
--bg: #ffecec;
--bg-alt: #ffecec;
--text: #292222;
}
[data-theme='iron goddess'] {
--blossom: #424b51;
--fade: #64707a;
--bg: #fff2e2;
--bg-alt: #fffce2;
--text: #2c2923;
}
[data-theme='main sequence'] {
--blossom: #3a5425;
--fade: #698650;
--bg: #fffde5;
--bg-alt: #fff4e5;
--text: #5e592a;
}
[data-theme='sorcery'] {
--blossom: #5a5a69;
--fade: #868698;
--bg: #e5f4e5;
--bg-alt: #e6f4e6;
--text: #323932;
}
[data-theme='cirrus'] {
--blossom: #565a4b;
--fade: #9da587;
--bg: #e5f6fa;
--bg-alt: #e5f6fa;
--text: #31393b;
}
[data-theme='oxygen'] {
--blossom: #162011;
--fade: #343932;
--bg: #e1e2e4;
--bg-alt: #e3e0e3;
--text: #27282c;
}
[data-theme='dauphin'] {
--blossom: #171e1c;
--fade: #485b58;
--bg: #ebe5f8;
--bg-alt: #ebe5f8;
--text: #1c1a20;
}
[data-theme='diamond-burned'] {
--blossom: #0f0d0b;
--fade: #4d4743;
--bg: #f8ebf2;
--bg-alt: #ebe8f4;
--text: #3e363a;
}
[data-theme='chi'] {
--blossom: #908975;
--fade: #fff8e5;
--bg: #110c0c;
--bg-alt: #0a090c;
--text: #cfa9a9;
}
[data-theme='darjeeling'] {
--blossom: #ba949c;
--fade: #f8e1e6;
--bg: #1c160d;
--bg-alt: #1c160d;
--text: #c9b9a0;
}
[data-theme='subgiant'] {
--blossom: #9fad8a;
--fade: #e8f2d7;
--bg: #16130b;
--bg-alt: #16130b;
--text: #bbb396;
}
[data-theme='goblin'] {
--blossom: #7a808e;
--fade: #dae1ef;
--bg: #070905;
--bg-alt: #0a0906;
--text: #acbd9f;
}
[data-theme='altostratus'] {
--blossom: #a8a0b7;
--fade: #e5dbf7;
--bg: #0c0f0f;
--bg-alt: #1a1614;
--text: #8da4a4;
}
[data-theme='silicon'] {
--blossom: #717f63;
--fade: #c4d4b3;
--bg: #050a0f;
--bg-alt: #050a0f;
--text: #838e9a;
}
[data-theme='imperator'] {
--blossom: #93a0a3;
--fade: #f3fbfd;
--bg: #0e0c12;
--bg-alt: #0e0c12;
--text: #a8a1b1;
}
[data-theme='mædi'] {
--blossom: #ccd3b6;
--fade: #fdfbf3;
--bg: #10090f;
--bg-alt: #2f282e;
--text: #9e889a;
}
/* Body */
html {
font-size: 62.5%;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif;
}
body {
font-size: 1.8rem;
line-height: 1.618;
/* max-width: 38em; */
margin: auto;
color: var(--text);
background-color: var(--bg);
padding: 13px;
}
@media (max-width: 684px) {
body {
font-size: 1.53rem;
}
}
@media (max-width: 382px) {
body {
font-size: 1.35rem;
}
}
h1,
h2,
h3,
h4,
h5,
h6 {
line-height: 1.1;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif;
font-weight: 700;
margin-top: 3rem;
margin-bottom: 1.5rem;
overflow-wrap: break-word;
word-wrap: break-word;
-ms-word-break: break-all;
word-break: break-word;
}
h1 {
font-size: 2.35em;
}
h2 {
font-size: 2em;
}
h3 {
font-size: 1.75em;
}
h4 {
font-size: 1.5em;
}
h5 {
font-size: 1.25em;
}
h6 {
font-size: 1em;
}
p {
margin-top: 0px;
margin-bottom: 2.5rem;
}
small,
sub,
sup {
font-size: 75%;
}
hr {
border-color: var(--blossom);
}
a {
text-decoration: none;
color: var(--blossom);
}
a:hover {
color: var(--fade);
border-bottom: 2px solid var(--text);
}
ul {
padding-left: 1.4em;
margin-top: 0px;
margin-bottom: 2.5rem;
}
li {
margin-bottom: 0.4em;
}
blockquote {
margin-left: 0px;
margin-right: 0px;
padding-left: 1em;
padding-top: 0.8em;
padding-bottom: 0.8em;
padding-right: 0.8em;
border-left: 5px solid var(--blossom);
margin-bottom: 2.5rem;
background-color: var(--bg-alt);
}
blockquote p {
margin-bottom: 0;
}
img,
video {
height: auto;
max-width: 100%;
margin-top: 0px;
margin-bottom: 2.5rem;
}
/* Pre and Code */
pre {
background-color: var(--bg-alt);
display: block;
padding: 1em;
overflow-x: auto;
margin-top: 0px;
margin-bottom: 2.5rem;
font-size: 0.9em;
}
code,
kbd,
samp {
font-size: 0.9em;
padding: 0 0.5em;
background-color: var(--bg-alt);
white-space: pre-wrap;
}
pre > code {
padding: 0;
background-color: transparent;
white-space: pre;
font-size: 1em;
}
/* Tables */
table {
text-align: justify;
width: 100%;
border-collapse: collapse;
margin-bottom: 2rem;
}
td,
th {
padding: 0.5em;
border-bottom: 1px solid var(--bg-alt);
}
/* Buttons, forms and input */
input,
textarea {
border: 1px solid var(--text);
}
input:focus,
textarea:focus {
border: 1px solid var(--blossom);
}
textarea {
width: 100%;
}
.button,
button,
input[type='submit'],
input[type='reset'],
input[type='button'],
input[type='file']::file-selector-button {
display: inline-block;
padding: 5px 10px;
text-align: center;
text-decoration: none;
white-space: nowrap;
background-color: var(--blossom);
color: var(--bg);
border-radius: 1px;
border: 1px solid var(--blossom);
cursor: pointer;
box-sizing: border-box;
}
.button[disabled],
button[disabled],
input[type='submit'][disabled],
input[type='reset'][disabled],
input[type='button'][disabled],
input[type='file']::file-selector-button[disabled] {
cursor: default;
opacity: 0.5;
}
.button:hover,
button:hover,
input[type='submit']:hover,
input[type='reset']:hover,
input[type='button']:hover,
input[type='file']::file-selector-button:hover {
background-color: var(--fade);
color: var(--bg);
outline: 0;
}
.button:focus-visible,
button:focus-visible,
input[type='submit']:focus-visible,
input[type='reset']:focus-visible,
input[type='button']:focus-visible,
input[type='file']::file-selector-button:focus-visible {
outline-style: solid;
outline-width: 2px;
}
textarea,
select,
input {
color: var(--text);
padding: 6px 10px;
/* The 6px vertically centers text on FF, ignored by Webkit */
margin-bottom: 10px;
background-color: var(--bg-alt);
border: 1px solid var(--bg-alt);
border-radius: 4px;
box-shadow: none;
box-sizing: border-box;
}
textarea:focus,
select:focus,
input:focus {
border: 1px solid var(--blossom);
outline: 0;
}
input[type='checkbox']:focus {
outline: 1px dotted var(--blossom);
}
label,
legend,
fieldset {
display: block;
margin-bottom: 0.5rem;
font-weight: 600;
}