diff options
author | mat <github@matdoes.dev> | 2022-02-16 22:13:11 +0000 |
---|---|---|
committer | mat <github@matdoes.dev> | 2022-02-16 22:13:11 +0000 |
commit | cd982e64595ab47a5fa71a40f8249893dbf867df (patch) | |
tree | a2c9c5ed31bd1f5f48c3b992f344cc2f461ecebc | |
parent | 81543e5307c98df0d44c1cf553bcdfefbfe4ea7f (diff) | |
download | skyblock-stats-cd982e64595ab47a5fa71a40f8249893dbf867df.tar.gz skyblock-stats-cd982e64595ab47a5fa71a40f8249893dbf867df.tar.bz2 skyblock-stats-cd982e64595ab47a5fa71a40f8249893dbf867df.zip |
add
-rw-r--r-- | src/lib/ListItemWithIcon.svelte | 18 | ||||
-rw-r--r-- | src/lib/Toc.svelte | 27 | ||||
-rw-r--r-- | src/lib/Tooltip.svelte | 75 | ||||
-rw-r--r-- | src/lib/sections/Infobox.svelte | 70 | ||||
-rw-r--r-- | src/lib/sections/Skills.svelte | 64 | ||||
-rw-r--r-- | src/routes/constants.json.ts | 18 |
6 files changed, 272 insertions, 0 deletions
diff --git a/src/lib/ListItemWithIcon.svelte b/src/lib/ListItemWithIcon.svelte new file mode 100644 index 0000000..2c7aade --- /dev/null +++ b/src/lib/ListItemWithIcon.svelte @@ -0,0 +1,18 @@ +<script lang="ts"> + export let url: string +</script> + +<li class="list-item-with-icon" style="background: url({url}) 0 0/1em no-repeat"> + <slot /> +</li> + +<style> + .list-item-with-icon { + list-style: none; + padding-left: 1.2em; + position: relative; + right: 1.2em; + image-rendering: crisp-edges; + image-rendering: pixelated; + } +</style> diff --git a/src/lib/Toc.svelte b/src/lib/Toc.svelte new file mode 100644 index 0000000..190c6a4 --- /dev/null +++ b/src/lib/Toc.svelte @@ -0,0 +1,27 @@ +<script lang="ts"> + import { cleanId } from './utils' + + export let categories: string[] +</script> + +<ul id="toc"> + <h3>Contents</h3> + {#each categories as category} + <li><a href="#{category}">{cleanId(category)}</a></li> + {/each} +</ul> + +<style> + #toc { + border: 1px solid rgba(255, 255, 255, 0.1); + max-width: max-content; + padding: 0.75em; + border-radius: 1em; + + display: inline-block; + background: rgba(0, 0, 0, 0.1); + } + #toc li { + list-style-type: none; + } +</style> diff --git a/src/lib/Tooltip.svelte b/src/lib/Tooltip.svelte new file mode 100644 index 0000000..55cbc21 --- /dev/null +++ b/src/lib/Tooltip.svelte @@ -0,0 +1,75 @@ +<!-- + @component + + A tooltip that works without requiring JavaScript to be enabled. + When you hover or click on the element, it shows the value in a box above the element. + --> + +<span class="tooltip-container" tabindex="1"> + <span class="tooltip-content"> + <slot name="tooltip">No tooltip!</slot> + </span> + <span class="tooltip-inner"> + <slot /> + </span> +</span> + +<!-- <li class="tooltip list-item-with-icon" data-tooltip="{% if skill.levelXpRequired != null %}{{ ((skill.levelXp/skill.levelXpRequired)*100)|round }}% to next level, {{ skill.levelXp|round|cleannumber }}/{{ skill.levelXpRequired|formatnumber(3) }} xp{% else %}{{ skill.levelXp|round|cleannumber }} extra xp{% endif %}" tabindex="1" style="background: url('{{ imageUrl }}') 0 0/1em no-repeat;"></li> --> +<style> + .tooltip-container { + position: relative; + cursor: pointer; + touch-action: manipulation; + /* + * We remove the outline here because in safari the tooltip looks weird + * and glitchy. The outline is readded later on so it's only for the content. + */ + outline: none !important; + } + .tooltip-container > .tooltip-content { + font-size: 1rem; + display: inline-block; + left: 50%; + opacity: 0; + position: absolute; + + background: var(--theme-lightest-background); + border-radius: 0.25em; + bottom: 125%; + color: var(--theme-main-text); + margin-left: max(calc(-50% - 1em), -5em); + padding: 0.5em; + + /* this doesn't work in safari */ + transition-delay: none; + transition: all 200ms; + + transform: scale(0.6) translateY(50%); + + width: max-content; + text-align: center; + max-width: 10em; + cursor: auto; + box-shadow: 0 0 1em 0.5em #0002; + pointer-events: none; + } + .tooltip-container:hover > .tooltip-content, + .tooltip-container:focus > .tooltip-content { + opacity: 0.9; + transform: scale(1) translateY(0); + } + + /* Here's where the outline is re-added */ + .tooltip-container:focus > .tooltip-inner { + border-radius: 0.1em; + box-shadow: 0 0 0 2pt #06e7; + } + /* + * hide all the tooltips after if one is selected, unfortunately we can't + * select all the elements before and outside :( + */ + :global(.tooltip-container:focus ~ .tooltip-container + .tooltip-content) { + transform: scale(0.6) translateY(50%); + opacity: 0; + } +</style> diff --git a/src/lib/sections/Infobox.svelte b/src/lib/sections/Infobox.svelte new file mode 100644 index 0000000..eda7d22 --- /dev/null +++ b/src/lib/sections/Infobox.svelte @@ -0,0 +1,70 @@ +<script lang="ts"> + import { generateInfobox, prettyTimestamp } from '$lib/profile' + import Username from '$lib/Username.svelte' + import Emoji from '$lib/Emoji.svelte' + + export let data + export let constants +</script> + +<!-- <div id="infobox"> + <h2>{{ render.username(data.member, prefix=true) }} ({{ data.member.profileName }})</h2> + <p>{{ '💾'|twemojiHtml|safe }} Last save: {% if getTime() - data.member.last_save < 60 * 60 * 24 * 7 %}{{ ((getTime() - data.member.last_save) * 1000)|cleannumber('time') }} ago {% else %}{{ data.member.last_save|cleannumber('date') }}{% endif %}</p> + <p>{{ '🚶'|twemojiHtml|safe }} Profile created: {% if getTime() - data.member.first_join < 60 * 60 * 24 * 7 %}{{ ((getTime() - data.member.first_join) * 1000)|cleannumber('time') }} ago {% else %}{{ data.member.first_join|cleannumber('date') }}{% endif %}</p> + <p>{{ '✨'|twemojiHtml|safe }} Fairy souls: {{ data.member.fairy_souls.total }}/{{ getConstants().max_fairy_souls }}</p> +{%- if data.profile.minion_count == getConstants().max_minions -%}<p>{{ '🤖'|twemojiHtml|safe }} Minion count: {{ data.profile.minion_count }}</p>{% endif %} +{%- set mostSignificantKillsStat = {} -%} +{%- set mostSignificantDeathsStat = {} -%} +{%- for stat in data.member.stats -%} +{%- if stat.category == 'kills' and stat.rawName != 'kills' and stat.value >= 200000 and stat.value > (mostSignificantKillsStat.value or 0) -%} +{%- set mostSignificantKillsStat = stat -%} +{%- endif -%} +{%- if stat.category == 'deaths' and stat.rawName != 'deaths' and stat.value >= 1000000 and stat.value > (mostSignificantDeathsStat.value or 0) -%} +{%- set mostSignificantDeathsStat = stat -%} +{%- endif -%} +{%- endfor -%} +{%- if mostSignificantKillsStat.value -%} + <p>{{ '⚔️'|twemojiHtml|safe }} {{ mostSignificantKillsStat.value|cleannumber(mostSignificantKillsStat.unit or mostSignificantKillsStat.rawName|clean|lower) }}</p> +{%- endif -%} +{%- if mostSignificantDeathsStat.value -%} + <p>{{ '☠'|twemojiHtml|safe }} {{ mostSignificantDeathsStat.value|cleannumber(mostSignificantDeathsStat.unit or mostSignificantDeathsStat.rawName|clean|lower) }}</p> +{%- endif -%} +</div> --> + +<div id="infobox"> + <h2><Username player={data.member} prefix /> ({data.member.profileName})</h2> + {#each generateInfobox(data, constants, { meta: false }) as item} + <p><Emoji value={item} /></p> + {/each} +</div> + +<style> + #infobox { + float: right; + max-width: 95%; + background-color: rgba(20, 20, 20, 0.4); + padding: 1em; + margin-top: 2em; + width: 20em; + border-radius: 0.5em; + box-shadow: 0 0 1em #000; + } + p { + margin: 0 0 0.25em 0; + } + @media only screen and (max-width: 600px) { + #infobox { + position: relative; + right: -2em; + margin-top: 0; + } + } + @media only screen and (max-width: 550px) { + #infobox { + position: unset; + box-shadow: none; + float: none; + border: 1px solid var(--theme-lighter-background); + } + } +</style> diff --git a/src/lib/sections/Skills.svelte b/src/lib/sections/Skills.svelte new file mode 100644 index 0000000..790da6d --- /dev/null +++ b/src/lib/sections/Skills.svelte @@ -0,0 +1,64 @@ +<script lang="ts"> + import Tooltip from '$lib/Tooltip.svelte' + import { cleanId, formatNumber } from '$lib/utils' + + const skillImages = { + runecrafting: 'https://cdn.matdoes.dev/images/runescape/runecrafting.webp', + alchemy: 'https://cdn.matdoes.dev/images/runescape/herblore.webp', + combat: 'https://cdn.matdoes.dev/images/runescape/attack.webp', + enchanting: 'https://cdn.matdoes.dev/images/runescape/magic.webp', + foraging: 'https://cdn.matdoes.dev/images/runescape/woodcutting.webp', + mining: 'https://cdn.matdoes.dev/images/runescape/mining.webp', + taming: 'https://cdn.matdoes.dev/images/runescape/hunter.webp', + farming: 'https://cdn.matdoes.dev/images/runescape/farming.webp', + fishing: 'https://cdn.matdoes.dev/images/runescape/fishing.webp', + carpentry: 'https://cdn.matdoes.dev/images/runescape/construction.webp', + } + + export let data +</script> + +<ul> + {#each data.member.skills as skill} + <li + class="list-item-with-icon" + style="background: url({skillImages[skill.name]}) 0 0/1em no-repeat" + > + <Tooltip> + <span slot="tooltip"> + {#if skill.levelXpRequired !== null} + {Math.round((skill.levelXp / skill.levelXpRequired) * 100)}% to next level, {Math.round( + skill.levelXp + ).toLocaleString()}/{formatNumber(skill.levelXpRequired, 3)} xp + {:else} + {Math.round(skill.levelXp).toLocaleString()} extra xp + {/if} + </span> + <span> + {cleanId(skill.name)} + <span class="skill-level" class:skill-maxed={skill.level === skill.maxLevel}> + {skill.level} + </span> + </span> + </Tooltip> + </li> + {/each} +</ul> + +<style> + .skill-level { + opacity: 0.9; + } + .skill-maxed { + color: #0e0; + opacity: 1; + } + .list-item-with-icon { + list-style: none; + padding-left: 1.2em; + position: relative; + right: 1.2em; + image-rendering: crisp-edges; + image-rendering: pixelated; + } +</style> diff --git a/src/routes/constants.json.ts b/src/routes/constants.json.ts new file mode 100644 index 0000000..301da58 --- /dev/null +++ b/src/routes/constants.json.ts @@ -0,0 +1,18 @@ +import { API_URL } from '$lib/api' + +export let constants: any = {} + +async function updateConstants() { + constants = await fetch(API_URL + 'constants').then(r => r.json()) + console.log('updated constants') +} + +updateConstants() +setInterval(updateConstants, 60 * 60 * 1000) // update every hour + +export async function get({ request }) { + console.log('gotten constants') + return { + body: constants || {} + } +}
\ No newline at end of file |