Reworked scores page

This commit is contained in:
nise.moe 2024-03-05 20:42:13 +01:00
parent 6387acaf39
commit ebe6b41a4d
4 changed files with 217 additions and 84 deletions

View File

@ -1,21 +1,119 @@
/* Flex container */
.flex-container { .flex-container {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: center; justify-content: center;
gap: 20px; /* Adjust the gap between items as needed */ gap: 20px;
} }
/* Flex items - default to full width to stack on smaller screens */
.flex-container > div { .flex-container > div {
flex: 0 0 100%; flex: 0 0 100%;
box-sizing: border-box; /* To include padding and border in the element's total width and height */ box-sizing: border-box;
} }
/* Responsive columns */ @media (min-width: 768px) {
@media (min-width: 768px) { /* Adjust the breakpoint as needed */
.flex-container > div { .flex-container > div {
flex: 0 0 15%; flex: 0 0 15%;
max-width: 20%; max-width: 20%;
} }
} }
.link-list a {
padding: 20px;
}
.link-list a:hover {
color: white;
background-color: rgba(47, 47, 47, 0.46);
}
.score-info {
flex-direction: row;
padding-left: 40px;
padding-right: 40px;
}
.score-info__cover::after {
background-color: rgba(23, 26, 28, 0.75);
content: "";
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
}
.score-info {
align-items: center;
background-position: 50%;
background-repeat: no-repeat;
background-size: cover;
display: flex;
flex-direction: column;
min-height: 200px;
padding: 10px 0;
position: relative;
}
.stats-container {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
width: 100%;
padding: 10px 20px;
box-sizing: border-box;
border-radius: 4px;
}
.stat {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
padding: 10px 0;
}
.stat span:first-child {
font-weight: bold;
font-size: 16px;
}
.stat span:last-child {
font-size: 14px;
color: #999;
}
.score-info a {
color: white;
}
.score-player__score {
font-size: 35px;
}
.score-info__item--player {
flex: 1;
color: white;
}
.score-info__item {
flex: none;
margin: 10px;
position: relative;
}
.beatmapset-cover::before {
background-image: var(--bg);
background-position: 50%;
background-size: cover;
border-radius: inherit;
content: "";
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
filter: grayscale(100%);
}

View File

@ -13,90 +13,115 @@
</div> </div>
</ng-container> </ng-container>
<ng-container *ngIf="this.replayData && !this.isLoading && !this.error"> <ng-container *ngIf="this.replayData && !this.isLoading && !this.error">
<div class="main term mb-2"> <div class="main term mb-2" style="padding: 0; width: 882px !important;">
<div class="fade-stuff">
<div class="image-container">
<a href="https://osu.ppy.sh/beatmaps/{{ this.replayData.beatmap_id }}?mode=osu" target="_blank">
<img ngSrc="https://assets.ppy.sh/beatmaps/{{ this.replayData.beatmap_beatmapset_id }}/covers/cover.jpg" width="260" height="72"
alt="Beatmap Cover">
<div class="overlay">
<h4>
{{ this.replayData.beatmap_title }} <span class="text-muted">by</span> {{ this.replayData.beatmap_artist }}
</h4>
★{{ this.replayData.beatmap_star_rating | number: '1.0-2' }} {{ this.replayData.beatmap_version }}
</div>
</a>
</div>
<hr class="mt-2 mb-2">
<div class="score-info">
<div class="score-info__cover">
<div class="beatmapset-cover beatmapset-cover--full"
style="--bg: url('https://assets.ppy.sh/beatmaps/{{ this.replayData.beatmap_beatmapset_id }}/covers/cover.jpg');"></div>
</div>
<div class="score-info__item score-info__item--player">
<div>
<div>
<div class="badge-list"> <div class="badge-list">
<span class="badge" *ngFor="let mod of this.replayData.mods"> <span class="badge mod" *ngFor="let mod of this.replayData.mods">
{{ mod }} {{ mod }}
</span> </span>
</div> </div>
<div class="score-player__score mt-2">
<app-osu-grade [grade]="this.replayData.rank"></app-osu-grade> {{ this.replayData.score | number }}
</div>
</div>
<div class="score-player__row score-player__row--player mt-2">
Played by <a [routerLink]="['/u/' + this.replayData.username]">{{ this.replayData.username }}</a> <a class="btn" style="margin-left: 5px" href="https://osu.ppy.sh/users/{{ this.replayData.user_id }}" target="_blank">osu!web</a>
<br>
Submitted on <strong>{{ this.replayData.date }}</strong>
</div>
</div>
</div>
</div>
<h1> <div style="display: flex; justify-content: space-between; margin-bottom: 10px" class="link-list">
{{ this.replayData.score | number }} <span style="font-size: 14px">Played at: {{ this.replayData.date }}</span>
</h1> <a style="flex: 1" class="text-center" href="https://osu.ppy.sh/scores/osu/{{ this.replayData.replay_id }}" target="_blank">
Open in osu!web
</a>
<a style="flex: 1" class="text-center" [href]="this.buildCircleguardUrl()">
Open in CircleGuard
</a>
<a style="flex: 1" class="text-center" [href]="'https://replay.nise.moe/' + this.replayData.replay_id" target="_blank">
Open in Replay Viewer
</a>
</div>
<div style="padding: 16px">
<div style="display: flex; justify-content: space-between;"> <div style="display: flex; justify-content: space-between;">
<div style="flex: 1; padding-right: 10px;" class="text-center">
<h2>
{{ this.replayData.beatmap_title }} <span class="text-muted">by</span> {{ this.replayData.beatmap_artist }}
</h2>
<span class="badge">★{{ this.replayData.beatmap_star_rating | number: '1.0-2' }}</span> {{ this.replayData.beatmap_version }}
</div>
<div style="flex: 1; padding-right: 10px;"> <div style="flex: 1; padding-right: 10px;">
<ul style="line-height: 2.2"> <div class="stats-container">
<li>Played by: <a [routerLink]="['/u/' + this.replayData.username]">{{ this.replayData.username }}</a> <a class="btn" style="margin-left: 5px" href="https://osu.ppy.sh/users/{{ this.replayData.user_id }}" target="_blank">osu!web</a></li> <div class="stat">
<li>Link to score: <a class="btn" href="https://osu.ppy.sh/scores/osu/{{ this.replayData.replay_id }}" target="_blank">osu!web</a></li> <span class="stat-label">Accuracy</span>
<li><a class="btn" [href]="this.buildCircleguardUrl()">Open in CircleGuard</a></li> <span class="stat-value">{{ calculateAccuracy(this.replayData) | number: '1.2-2' }}%</span>
<li *ngIf="this.replayData.replay_id">
<a class="btn" [href]="'https://replay.nise.moe/' + this.replayData.replay_id" target="_blank">Open in Replay Viewer</a>
</li>
<li>PP: {{ this.replayData.pp }}</li>
<li>Grade: <app-osu-grade [grade]="this.replayData.rank"></app-osu-grade></li>
</ul>
</div> </div>
<div style="flex: 1; padding-left: 10px;"> <div class="stat">
<ul> <span class="stat-label">Max Combo</span>
<li> <span class="stat-value">{{ this.replayData.max_combo }}x <span *ngIf="this.replayData.perfect" class="badge badge-green">perfect</span></span>
Max combo: {{ this.replayData.max_combo }}x </div>
<span *ngIf="this.replayData.perfect" class="badge badge-green">perfect</span> <div class="stat">
</li> <span class="stat-label">PP</span>
<li>Accuracy: {{ calculateAccuracy(this.replayData) | number: '1.2-2' }}%</li> <span class="stat-value">{{ this.replayData.pp }}</span>
<li>300x: {{ this.replayData.count_300 }}</li>
<li>100x: {{ this.replayData.count_100 }}</li>
<li>50x: {{ this.replayData.count_50 }}</li>
<li>Misses: {{ this.replayData.count_miss }}</li>
</ul>
</div> </div>
</div> </div>
<div class="stats-container">
<div class="stat">
<div class="text-center mb-4 flex-container"> <span class="stat-label">300x</span>
<span class="stat-value">{{ this.replayData.count_300 }}</span>
<div *ngIf="this.replayData.ur">
<h2 title="Converted Unstable Rate">cvUR</h2>
<div>{{ this.replayData.ur | number: '1.2-2' }}</div>
</div> </div>
<div *ngIf="this.replayData.adjusted_ur"> <div class="stat">
<h2 title="Adjusted cvUR - filters outlier hits">Adj. cvUR</h2> <span class="stat-label">100x</span>
<div>{{ this.replayData.adjusted_ur | number: '1.2-2' }}</div> <span class="stat-value">{{ this.replayData.count_100 }}</span>
</div> </div>
<div *ngIf="this.replayData.frametime"> <div class="stat">
<h2 title="Median time between frames">Frametime</h2> <span class="stat-label">50x</span>
<div>{{ this.replayData.frametime | number: '1.0-2' }}ms</div> <span class="stat-value">{{ this.replayData.count_50 }}</span>
</div>
<div class="stat">
<span class="stat-label">Miss</span>
<span class="stat-value">{{ this.replayData.count_miss }}</span>
</div>
</div>
<div class="stats-container">
<div class="stat" *ngIf="this.replayData.ur">
<span class="stat-label">cvUR</span>
<span class="stat-value">{{ this.replayData.ur | number: '1.2-2' }}</span>
</div>
<div class="stat" *ngIf="this.replayData.adjusted_ur">
<span class="stat-label">Adj. cvUR</span>
<span class="stat-value">{{ this.replayData.adjusted_ur | number: '1.2-2' }}</span>
</div>
<div class="stat" *ngIf="this.replayData.frametime">
<span class="stat-label">Frametime</span>
<span class="stat-value">{{ this.replayData.frametime | number: '1.0-2' }}ms</span>
</div>
<div class="stat" *ngIf="this.replayData.hits">
<span class="stat-label">Edge Hits</span>
<span class="stat-value">{{ this.replayData.hits }}</span>
</div>
<div class="stat" *ngIf="this.replayData.snaps">
<span class="stat-label">Snaps</span>
<span class="stat-value">{{ this.replayData.snaps }}</span>
</div> </div>
<div *ngIf="this.replayData.hits">
<h2 title="Hits within <1px of the edge">Edge Hits</h2>
<div>{{ this.replayData.hits }}</div>
</div>
<div *ngIf="this.replayData.snaps">
<h2 title="Unusual snaps in the cursor movement">Snaps</h2>
<div>{{ this.replayData.snaps }}</div>
</div> </div>
</div> </div>
<div class="alert text-center" *ngIf="this.replayData.average_ur">
<p class="bold">Heads up!</p>
<p>The average cvUR for this beatmap is <span class="bold">{{ this.replayData.average_ur | number: '1.0-2' }}</span></p>
</div> </div>
</div> </div>
</div> </div>
@ -139,6 +164,10 @@
<div class="main term mb-2" *ngIf="this.replayData.mean_error"> <div class="main term mb-2" *ngIf="this.replayData.mean_error">
<h1># nerd stats</h1> <h1># nerd stats</h1>
<div class="alert text-center" *ngIf="this.replayData.average_ur">
<p class="bold">Heads up!</p>
<p>The average cvUR for this beatmap is <span class="bold">{{ this.replayData.average_ur | number: '1.0-2' }}</span></p>
</div>
<table> <table>
<thead> <thead>
<th></th> <th></th>

View File

@ -277,7 +277,7 @@ fieldset button:not(:last-child) {
.badge-list .badge { .badge-list .badge {
font-weight: bold; font-weight: bold;
font-style: italic; font-style: italic;
padding: 2px 2px 2px 6px; padding: 2px 2px 2px 10px;
} }
@ -290,6 +290,12 @@ fieldset p label {
margin-right: 100px !important; margin-right: 100px !important;
} }
.badge.mod {
font-style: normal;
color: #474b56;
background-color: #fecb21;
}
.badge { .badge {
padding: 3px; padding: 3px;
background-color: rgba(255, 255, 255, 0.05); background-color: rgba(255, 255, 255, 0.05);
@ -300,7 +306,7 @@ fieldset p label {
.badge-green { .badge-green {
font-size: 12px; font-size: 12px;
border-color: rgba(150, 187, 150, 0.98); border-color: rgba(150, 187, 150, 0.98);
color: rgba(150, 187, 150, 0.98); color: rgba(150, 187, 150, 0.98) !important;
} }
fieldset p { fieldset p {

View File

@ -1,5 +1,5 @@
.badge { .badge {
padding: 2px 5px 2px 2px; padding: 4px 10px 4px 4px;
border-radius: 4px; border-radius: 4px;
color: white; color: white;
filter: grayscale(40%); filter: grayscale(40%);