[F] Fix rating composition null elements, generalize

#35
This commit is contained in:
Azalea 2024-05-16 11:25:22 +08:00
parent f9c8b00587
commit 8173003144
4 changed files with 205 additions and 226 deletions

View File

@ -1,161 +0,0 @@
<!-- Svelte 4.2.11 -->
<script lang="ts">
import { slide } from "svelte/transition";
import { DATA_HOST } from "../libs/config";
import { t } from "../libs/i18n";
import { type GameName, getMult, roundFloor } from "../libs/scoring";
import { coverNotFound } from "../libs/ui";
import type { MusicMeta } from "../libs/generalTypes";
import { tooltip } from "../libs/ui";
export let g: string
export let meta: MusicMeta
export let game: GameName
let mapData = g.split(":").map(Number)
let mult = getMult(mapData[3], game)
let mapRank: number | undefined = meta?.notes?.[mapData[1] === 10 ? 0 : mapData[1]]?.lv
let gameIndexMap = {
'mai2': 3,
'ongeki': 2,
'chu3': 2
};
let gameIndex = gameIndexMap[game as keyof typeof gameIndexMap];
</script>
{#if mapData[0] !== 0}
<div class="map-detail-container" transition:slide>
<div class="scores">
<div>
<img src={`${DATA_HOST}/d/${game}/music/00${mapData[0].toString().padStart(6, '0').substring(2)}.png`} alt="" on:error={coverNotFound} />
<div class="info">
<div class="first-line">
<div class="song-title">{meta?.name ?? t("UserHome.UnknownSong")}</div>
<span class={`lv level-${mapData[1] === 10 ? 3 : mapData[1]}`}>
{ mapRank ?? '-' }
</span>
</div>
<div class="second-line">
<span class={`rank-${getMult(mapData[gameIndex], game)[2].toString()[0]}`}>
<span class="rank-text">{("" + getMult(mapData[gameIndex], game)[2]).replace("p", "+")}</span>
<span class="rank-num" use:tooltip={(mapData[gameIndex] / 10000).toFixed(4)}>
{roundFloor(mapData[gameIndex], game, 1)}%
</span>
</span>
{#if game === 'mai2'}
<span class="dx-change">
{ mapRank ? (mapRank * Number(mult[1])).toFixed(0) : '-' }
</span>
{/if}
</div>
</div>
</div>
</div>
</div>
{/if}
<style lang="sass">
@import "../vars"
$gap: 20px
.map-detail-container
background-color: rgb(35,35,35)
border-radius: $border-radius
overflow: hidden
.scores
display: flex
flex-direction: column
flex-wrap: wrap
gap: $gap
// Image and song info
> div
display: flex
align-items: center
gap: 12px
max-width: 100%
box-sizing: border-box
img
width: 50px
height: 50px
border-radius: $border-radius
object-fit: cover
// Song info and score
> div.info
flex: 1
display: flex
justify-content: space-between
overflow: hidden
flex-direction: column
.first-line
display: flex
flex-direction: row
// Limit song name to one line
.song-title
flex: 1
min-width: 0
overflow: hidden
text-overflow: ellipsis
white-space: nowrap
// Make song score and rank not wrap
> div:last-child
white-space: nowrap
@media (max-width: $w-mobile)
flex-direction: column
gap: 0
.rank-text
text-align: left
.rank-S
// Gold green gradient on text
background: $grad-special
-webkit-background-clip: text
color: transparent
.rank-A
color: #ff8a8a
.rank-B
color: #6ba6ff
.lv
width: 30px
text-align: center
background: rgba(var(--lv-color), 0.6)
padding: 0 6px
border-radius: 0 $border-radius 0 $border-radius
// Inset shadow, like it's a paper below this card with a cut
box-shadow: inset 0 0 10px rgba(0,0,0,0.5)
span
display: inline-block
text-align: left
.second-line
display: flex
justify-content: space-between
align-items: center
// Vertical table-like alignment
span.rank-text
min-width: 40px
span.rank-num
min-width: 60px
span.dx-change
margin-right: 0.5rem
color: $c-good
</style>

View File

@ -0,0 +1,159 @@
<!-- Svelte 4.2.11 -->
<script lang="ts">
import { slide } from "svelte/transition";
import { DATA_HOST } from "../libs/config";
import { t } from "../libs/i18n";
import { type GameName, getMult, roundFloor } from "../libs/scoring";
import { coverNotFound } from "../libs/ui";
import type { MusicMeta } from "../libs/generalTypes";
import { tooltip } from "../libs/ui";
export let g: string
export let meta: MusicMeta
export let game: GameName
let mapData = g.split(":").map(Number)
let mult = getMult(mapData[3], game)
let mapRank: number | undefined = meta?.notes?.[mapData[1] === 10 ? 0 : mapData[1]]?.lv
let gameIndexMap = {
'mai2': 3,
'ongeki': 2,
'chu3': 2
};
let gameIndex = gameIndexMap[game as keyof typeof gameIndexMap];
</script>
<div class="map-detail-container" transition:slide>
<div class="scores">
<div>
<img src={`${DATA_HOST}/d/${game}/music/00${mapData[0].toString().padStart(6, '0').substring(2)}.png`} alt="" on:error={coverNotFound} />
<div class="info">
<div class="first-line">
<div class="song-title">{meta?.name ?? t("UserHome.UnknownSong")}</div>
<span class={`lv level-${mapData[1] === 10 ? 3 : mapData[1]}`}>
{ mapRank ?? '-' }
</span>
</div>
<div class="second-line">
<span class={`rank-${getMult(mapData[gameIndex], game)[2].toString()[0]}`}>
<span class="rank-text">{("" + getMult(mapData[gameIndex], game)[2]).replace("p", "+")}</span>
<span class="rank-num" use:tooltip={(mapData[gameIndex] / 10000).toFixed(4)}>
{roundFloor(mapData[gameIndex], game, 1)}%
</span>
</span>
{#if game === 'mai2'}
<span class="dx-change">
{ mapRank ? (mapRank * Number(mult[1])).toFixed(0) : '-' }
</span>
{/if}
</div>
</div>
</div>
</div>
</div>
<style lang="sass">
@import "../vars"
$gap: 20px
.map-detail-container
background-color: rgb(35,35,35)
border-radius: $border-radius
overflow: hidden
.scores
display: flex
flex-direction: column
flex-wrap: wrap
gap: $gap
// Image and song info
> div
display: flex
align-items: center
gap: 12px
max-width: 100%
box-sizing: border-box
img
width: 50px
height: 50px
border-radius: $border-radius
object-fit: cover
// Song info and score
> div.info
flex: 1
display: flex
justify-content: space-between
overflow: hidden
flex-direction: column
.first-line
display: flex
flex-direction: row
// Limit song name to one line
.song-title
flex: 1
min-width: 0
overflow: hidden
text-overflow: ellipsis
white-space: nowrap
// Make song score and rank not wrap
> div:last-child
white-space: nowrap
@media (max-width: $w-mobile)
flex-direction: column
gap: 0
.rank-text
text-align: left
.rank-S
// Gold green gradient on text
background: $grad-special
-webkit-background-clip: text
color: transparent
.rank-A
color: #ff8a8a
.rank-B
color: #6ba6ff
.lv
width: 30px
text-align: center
background: rgba(var(--lv-color), 0.6)
padding: 0 6px
border-radius: 0 $border-radius 0 $border-radius
// Inset shadow, like it's a paper below this card with a cut
box-shadow: inset 0 0 10px rgba(0,0,0,0.5)
span
display: inline-block
text-align: left
.second-line
display: flex
justify-content: space-between
align-items: center
// Vertical table-like alignment
span.rank-text
min-width: 40px
span.rank-num
min-width: 60px
span.dx-change
margin-right: 0.5rem
color: $c-good
</style>

View File

@ -0,0 +1,41 @@
<!-- Svelte 4.2.11 -->
<script lang="ts">
import RatingCompSong from "./RatingCompSong.svelte";
import { type GameName } from "../libs/scoring";
import { type MusicMeta } from "../libs/generalTypes";
export let title: string;
export let comp: string | undefined;
export let allMusics: Record<string, MusicMeta>;
export let game: GameName;
</script>
{#if comp}
<div>
<h2>{title}</h2>
<div class="rating-composition">
{#each comp.split(",").filter(it => it.split(":")[0] !== '0') as map}
<div>
<RatingCompSong g={map} meta={allMusics[map.split(":")[0]]} game={game}/>
</div>
{/each}
</div>
</div>
{/if}
<style lang="sass">
@import "../vars"
.rating-composition
display: grid
// 3 columns
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr))
gap: $gap
.rating-composition-2
display: grid
// 2 columns
grid-template-columns: repeat(auto-fill, minmax(290px, 1fr))
gap: $gap
</style>

View File

@ -21,7 +21,7 @@
import Icon from "@iconify/svelte";
import { GAME_TITLE, t } from "../libs/i18n";
import RankDetails from "../components/RankDetails.svelte";
import MapDetails from "../components/MapDetails.svelte";
import RatingComposition from "../components/RatingComposition.svelte";
const TREND_DAYS = 60
@ -231,57 +231,10 @@
</div>
</div>
{#if d.user.ratingComposition.best30}
<div>
<h2>B30</h2>
<div class="rating-composition">
{#each d.user.ratingComposition.best30.split(",") as map}
<div>
<MapDetails g={map} meta={allMusics[map.split(":")[0]]} game={game}/>
</div>
{/each}
</div>
</div>
{/if}
{#if d.user.ratingComposition.best35}
<div>
<h2>B35</h2>
<div class="rating-composition">
{#each d.user.ratingComposition.best35.split(",") as map}
<div>
<MapDetails g={map} meta={allMusics[map.split(":")[0]]} game={game}/>
</div>
{/each}
</div>
</div>
{/if}
{#if d.user.ratingComposition.best15}
<div>
<h2>B15</h2>
<div class="rating-composition">
{#each d.user.ratingComposition.best15.split(",") as map}
<div>
<MapDetails g={map} meta={allMusics[map.split(":")[0]]} game={game}/>
</div>
{/each}
</div>
</div>
{/if}
{#if d.user.ratingComposition.recent10}
<div>
<h2>R10</h2>
<div class="rating-composition-2">
{#each d.user.ratingComposition.recent10.split(",") as map}
<div>
<MapDetails g={map} meta={allMusics[map.split(":")[0]]} game={game}/>
</div>
{/each}
</div>
</div>
{/if}
<RatingComposition title="B30" comp={d.user.ratingComposition.best30} {allMusics} {game}/>
<RatingComposition title="B35" comp={d.user.ratingComposition.best35} {allMusics} {game}/>
<RatingComposition title="B15" comp={d.user.ratingComposition.best15} {allMusics} {game}/>
<RatingComposition title="Recent 10" comp={d.user.ratingComposition.recent10} {allMusics} {game}/>
<div class="recent">
<h2>{t('UserHome.RecentScores')}</h2>
@ -569,17 +522,4 @@
&:before
content: "+"
color: $c-good
.rating-composition
display: grid
// 3 columns
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr))
gap: $gap
.rating-composition-2
display: grid
// 2 columns
grid-template-columns: repeat(auto-fill, minmax(290px, 1fr))
gap: $gap
</style>