Skip to content

Commit

Permalink
added best scores table to profiles
Browse files Browse the repository at this point in the history
  • Loading branch information
grumd committed Feb 26, 2024
1 parent d3786d1 commit affb069
Show file tree
Hide file tree
Showing 12 changed files with 238 additions and 5 deletions.
79 changes: 79 additions & 0 deletions packages/api/src/services/players/playerHighestPpCharts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { Transaction, db } from 'db';
import { sql } from 'kysely';

export const getPlayerHighestPpCharts = async (
params: { playerId?: number; limit: number; offset: number },
trx?: Transaction
): Promise<
Array<{
pp: number;
weight: number;
date: Date; // seems like api actually returns string :(
shared_chart: number;
full_name: string;
label: string;
grade: string | null;
score: number | null;
is_pass: boolean;
}>
> => {
if (!params.playerId) {
throw new Error('playerId is required');
}

const query = (trx ?? db)
.selectFrom('results as r')
.innerJoin('shared_charts as sc', 'r.shared_chart', 'sc.id')
.innerJoin('chart_instances as ci', (join) =>
join.on('ci.id', '=', (eb) =>
eb
.selectFrom('chart_instances')
.select('id')
.where('shared_chart', '=', sql.ref('r.shared_chart'))
.orderBy('mix', 'desc')
.limit(1)
)
)
.innerJoin('tracks as t', 't.id', 'sc.track')
.innerJoin(
(eb) =>
eb
.selectFrom('results')
.select(({ fn }) => ['player_id', 'shared_chart', fn.max('pp').as('best_pp')])
.groupBy(['shared_chart', 'player_id'])
.where('pp', 'is not', null)
.as('max_pp_results'),
(join) =>
join
.onRef('max_pp_results.player_id', '=', 'r.player_id')
.onRef('max_pp_results.shared_chart', '=', 'r.shared_chart')
.onRef('max_pp_results.best_pp', '=', `r.pp`)
)
.select([
'pp',
'r.gained as date',
'r.grade',
'r.score_phoenix as score',
'r.is_pass',
't.full_name',
'ci.label',
'r.shared_chart',
])
.where('r.player_id', '=', params.playerId)
.orderBy('pp', 'desc')
.limit(params.limit)
.offset(params.offset)
.$narrowType<{ pp: number }>();

const timeStart = performance.now();
const result = await query.execute();
const timeEnd = performance.now();
console.log('query time:', timeEnd - timeStart, 'ms');

return result.map((row, index) => ({
...row,
date: new Date(row.date),
weight: 0.95 ** (index + params.offset),
is_pass: row.is_pass === 1,
}));
};
24 changes: 24 additions & 0 deletions packages/api/src/trpc/routes/players/highestPpCharts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { getPlayerHighestPpCharts } from 'services/players/playerHighestPpCharts';
import { publicProcedure } from 'trpc/trpc';
import z from 'zod';

export const highestPpCharts = publicProcedure
.input(
z.object({
playerId: z.number().optional(),
cursor: z.number(),
pageSize: z.number(),
})
)
.query(async ({ ctx, input }) => {
const { cursor, pageSize = 20, playerId } = input;
const offset = cursor ?? 0;
return {
items: await getPlayerHighestPpCharts({
playerId: playerId ?? ctx.user?.id,
limit: pageSize,
offset,
}),
nextCursor: offset + pageSize,
};
});
2 changes: 2 additions & 0 deletions packages/api/src/trpc/routes/players/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { achievements } from './achievements';
import { grades } from './grades';
import { highestPpCharts } from './highestPpCharts';
import { list } from './list';
import { mostPlayed } from './mostPlayedCharts';
import { pp } from './pp';
Expand All @@ -13,4 +14,5 @@ export const players = router({
pp,
achievements,
mostPlayed,
highestPpCharts,
});
2 changes: 0 additions & 2 deletions packages/web/src/components/ChartLabel/chart-label.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
justify-content: center;
height: 1.4em;
border-radius: 0.25em;
margin-left: 0;
margin-right: 0.4em;
padding: 0 0.4em;
}

Expand Down
1 change: 1 addition & 0 deletions packages/web/src/constants/translations/en.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ export const en = {
'* to gain an achievement, you should play ~10% of all charts of that level on a specific grade',
ACHIEVEMENTS: 'achievements',
MOST_PLAYED_CHARTS: 'most played charts',
BEST_SCORES: 'best scores',
PLACE_IN_TOP: 'place in top',
TOTAL: 'total',
UNITE_GRAPHS: 'unite graphs',
Expand Down
1 change: 1 addition & 0 deletions packages/web/src/constants/translations/ru.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ export const ru = {
'* для получения ачивки нужно сыграть около 10% всех чартов данного левела на нужный грейд',
ACHIEVEMENTS: 'достижения',
MOST_PLAYED_CHARTS: 'часто играемые чарты',
BEST_SCORES: 'лучшие результаты',
PLACE_IN_TOP: 'место в топе',
TOTAL: 'всего',
UNITE_GRAPHS: 'объединить графики',
Expand Down
1 change: 1 addition & 0 deletions packages/web/src/constants/translations/ua.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ export const ua = {
'* для отримання ачівки треба зіграти близько 10% усіх чартів даного рівня на потрібний грейд',
ACHIEVEMENTS: 'досягнення',
MOST_PLAYED_CHARTS: 'чарти, що часто гралися',
BEST_SCORES: 'найкращі результати',
PLACE_IN_TOP: 'місце у топі',
TOTAL: 'усього',
UNITE_GRAPHS: "об'єднати графіки",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
flex-flow: row nowrap;
justify-content: flex-start;
flex: 0 0 100%;
gap: 0.5em;

> .youtubeLink {
margin-left: 0.5em;
align-self: center;
> a {
display: block;
Expand Down
2 changes: 2 additions & 0 deletions packages/web/src/features/profile/Profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { Achievements } from './components/Achievements/Achievements';
import { ExpFaq } from './components/Exp/ExpFaq';
import { ExpProgress } from './components/Exp/ExpProgress';
import { GradeGraphsCard } from './components/GradeGraphsCard';
import { HighestPpCharts } from './components/HighestPpCharts/HighestPpCharts';
import { LevelAchievements } from './components/LevelAchievements/LevelAchievements';
import { MostPlayedCharts } from './components/MostPlayedCharts/MostPlayedCharts';
import { PpHistoryGraph } from './components/PpHistoryGraph';
Expand Down Expand Up @@ -56,6 +57,7 @@ const Profile = () => {
<LevelAchievements />
<Achievements />
<MostPlayedCharts />
<HighestPpCharts />
</Stack>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { Button, Flex, SimpleGrid, Stack, Text } from '@mantine/core';
import { MdExpandMore } from 'react-icons/md';
import { useParams } from 'react-router';
import { NavLink } from 'react-router-dom';

import { Card } from 'components/Card/Card';
import { ChartLabel } from 'components/ChartLabel/ChartLabel';
import { Grade } from 'components/Grade/Grade';
import Loader from 'components/Loader/Loader';

import { routes } from 'constants/routes';

import { useLanguage } from 'utils/context/translation';
import { labelToTypeLevel } from 'utils/leaderboards';
import { getLongTimeAgo } from 'utils/timeAgo';
import { api } from 'utils/trpc';

import css from './highest-pp-charts.module.css';

const pageSize = 20;

export const HighestPpCharts = (): JSX.Element => {
const params = useParams();
const charts = api.players.highestPpCharts.useInfiniteQuery(
{ playerId: params.id ? Number(params.id) : undefined, pageSize },
{ getNextPageParam: (lastPage) => lastPage.nextCursor, initialCursor: 0 }
);
const lang = useLanguage();

return (
<Card p="xs" title={lang.BEST_SCORES}>
<SimpleGrid spacing="xs" className={css.grid}>
{charts.data?.pages.flatMap((page) =>
page.items.map((item) => {
const date = new Date(item.date);
const daysAgo = Math.floor((Date.now() - date.getTime()) / (1000 * 60 * 60 * 24));
console.log({
date,
daysAgo,
});
const dateColor =
daysAgo < 30
? 'green'
: `rgba(255, 255, 255, ${Math.min(1, Math.max(0.2, 1 - (daysAgo - 30) / 360))})`;
const [chartType, chartLevel] = labelToTypeLevel(item.label);
return (
<Card key={item.shared_chart} fz="md" p="0.5em" level={2} className={css.row}>
{chartType && chartLevel ? (
<Flex>
<ChartLabel type={chartType} level={chartLevel} />
</Flex>
) : (
<span>{item.label}</span>
)}
<NavLink
to={routes.leaderboard.sharedChart.getPath({
sharedChartId: item.shared_chart,
})}
>
{item.full_name}
</NavLink>
<Text lh="1" c={dateColor} fz="xs">
{getLongTimeAgo(lang, date)}
</Text>
<Stack c="dark.2" gap="0.1em" ta="right">
<Text c="dark.1" lh="1em" size="xs">
{(item.pp * item.weight).toFixed(2)}pp
</Text>
<Text lh="1em" size="xs">
weighted {Math.round(item.weight * 100)}%
</Text>
</Stack>
<Grade
pl="0.5em"
h="1em"
score={item.score ?? 0}
isPass={item.is_pass ?? false}
scoring="phoenix"
/>
<Text pl="0.5em" fw="bold" ta="right">
{item.pp?.toFixed(2)}
<Text span c="dark.2" ta="right">
{' '}
pp
</Text>
</Text>
</Card>
);
})
)}
</SimpleGrid>
{charts.isFetchingNextPage ? (
<Loader />
) : (
<Button
leftSection={<MdExpandMore />}
mt="xs"
color="dark.4"
onClick={() => charts.fetchNextPage()}
>
{lang.SHOW_MORE}
</Button>
)}
</Card>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.grid {
grid-template-columns: auto 1fr auto auto auto auto;
}

.row {
display: grid;
grid-template-columns: subgrid;
grid-column: 1 / -1;
align-items: center;
justify-content: start;
line-height: 1;
}

.playIcon {
font-size: 0.7rem;
margin-right: 0.5em;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Button, SimpleGrid, Text } from '@mantine/core';
import { Button, Flex, SimpleGrid, Text } from '@mantine/core';
import { FaPlay } from 'react-icons/fa';
import { MdExpandMore } from 'react-icons/md';
import { useParams } from 'react-router';
Expand Down Expand Up @@ -36,7 +36,9 @@ export const MostPlayedCharts = (): JSX.Element => {
return (
<Card key={item.shared_chart} fz="md" p="0.5em" level={2} className={css.row}>
{chartType && chartLevel ? (
<ChartLabel type={chartType} level={chartLevel} />
<Flex>
<ChartLabel type={chartType} level={chartLevel} />
</Flex>
) : (
<span>{item.label}</span>
)}
Expand Down

0 comments on commit affb069

Please sign in to comment.