chuni playlog actions
This commit is contained in:
parent
8f9fe5278b
commit
f69ad4da72
64
src/actions/chuni/playlog.ts
Normal file
64
src/actions/chuni/playlog.ts
Normal file
@ -0,0 +1,64 @@
|
||||
'use server';
|
||||
|
||||
import { requireUser } from '@/actions/auth';
|
||||
import { db } from '@/db';
|
||||
import { CHUNI_MUSIC_PROPERTIES } from '@/helpers/chuni/music';
|
||||
import { chuniRating } from '@/helpers/chuni/rating';
|
||||
import { sql } from 'kysely';
|
||||
|
||||
export type GetPlaylogOptions = {
|
||||
limit: number
|
||||
} & ({} |
|
||||
{ musicId: number } |
|
||||
{ musicId: number, chartId: number });
|
||||
|
||||
export async function getPlaylog(opts: GetPlaylogOptions) {
|
||||
const user = await requireUser();
|
||||
|
||||
const playlog = await db.with('p', db => db
|
||||
.selectFrom('chuni_score_playlog as playlog')
|
||||
.innerJoin('chuni_static_music as music', join => join
|
||||
.onRef('music.songId', '=', 'playlog.musicId')
|
||||
.onRef('music.chartId', '=', 'playlog.level'))
|
||||
.where(({ and, eb, selectFrom }) => and([
|
||||
eb('playlog.user', '=', user.id),
|
||||
eb('music.version', '=', selectFrom('chuni_static_music')
|
||||
.select(({ fn }) => fn.max('version').as('latest'))),
|
||||
]))
|
||||
.select(
|
||||
({ ref }) => ['playlog.id', 'playlog.sortNumber', 'playlog.playDate', 'playlog.userPlayDate', 'playlog.track',
|
||||
'playlog.score', 'playlog.rank', 'playlog.maxCombo', 'playlog.maxChain', 'playlog.rateTap',
|
||||
'playlog.rateHold', 'playlog.rateSlide', 'playlog.rateAir', 'playlog.rateFlick', 'playlog.judgeGuilty',
|
||||
'playlog.judgeAttack', 'playlog.judgeCritical', 'playlog.judgeHeaven', 'playlog.playerRating',
|
||||
'playlog.isNewRecord', 'playlog.isFullCombo', 'playlog.fullChainKind', 'playlog.isAllJustice',
|
||||
'playlog.playKind', 'playlog.isClear', 'playlog.placeName',
|
||||
...CHUNI_MUSIC_PROPERTIES,
|
||||
chuniRating(ref('playlog.score')),
|
||||
sql<number>`(playlog.playerRating - (LEAD(playlog.playerRating) OVER (ORDER BY id DESC)))`
|
||||
.as('playerRatingChange')
|
||||
])
|
||||
.orderBy('playlog.id desc')
|
||||
)
|
||||
.selectFrom('p')
|
||||
.where(({ and, eb }) => and([
|
||||
...('musicId' in opts ? [eb('p.songId', '=', opts.musicId)] : []),
|
||||
...('chartId' in opts ? [eb('p.chartId', '=', opts.chartId)] : []),
|
||||
]))
|
||||
.selectAll()
|
||||
.limit(+opts.limit)
|
||||
.execute();
|
||||
|
||||
let remaining = 0;
|
||||
if (playlog.length)
|
||||
remaining = Number((await db.selectFrom('chuni_score_playlog as playlog')
|
||||
.where(({ and, eb }) => and([
|
||||
eb('playlog.user', '=', user.id),
|
||||
eb('playlog.id', '<', playlog.at(-1)!.id),
|
||||
...('musicId' in opts ? [eb('playlog.musicId', '=', opts.musicId)] : []),
|
||||
...('chartId' in opts ? [eb('playlog.level', '=', opts.chartId)] : []),
|
||||
]))
|
||||
.select(({ fn }) => fn.countAll().as('remaining'))
|
||||
.executeTakeFirstOrThrow()).remaining);
|
||||
|
||||
return { data: playlog, remaining };
|
||||
}
|
12
src/helpers/chuni/music.ts
Normal file
12
src/helpers/chuni/music.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { sql } from 'kysely';
|
||||
|
||||
export const CHUNI_MUSIC_PROPERTIES = ['music.songId',
|
||||
'music.chartId',
|
||||
'music.title',
|
||||
'music.artist',
|
||||
'music.jacketPath',
|
||||
'music.worldsEndTag',
|
||||
'music.genre',
|
||||
'music.level'
|
||||
// sql<string>`CAST(music.level AS DECIMAL(3, 1))`.as('level')
|
||||
] as const;
|
16
src/helpers/chuni/rating.ts
Normal file
16
src/helpers/chuni/rating.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { sql } from 'kysely';
|
||||
|
||||
export const chuniRating = (score: any = sql.raw(`CAST(score.scoreMax AS INT)`),
|
||||
level: any = sql.raw(`(CAST(music.level AS DECIMAL(3, 1)) * 100)`)) => sql<string>`
|
||||
CAST(GREATEST((CASE
|
||||
WHEN ${score} IS NULL THEN NULL
|
||||
WHEN ${score} >= 1009000 THEN ${level} + 215
|
||||
WHEN ${score} >= 1007500 THEN ${level} + 200 + (${score} - 1007500) / 100
|
||||
WHEN ${score} >= 1005000 THEN ${level} + 150 + (${score} - 1005000) / 50
|
||||
WHEN ${score} >= 1000000 THEN ${level} + 100 + (${score} - 1000000) / 100
|
||||
WHEN ${score} >= 975000 THEN ${level} + (${score} - 975000) / 250
|
||||
WHEN ${score} >= 900000 THEN ${level} - 500 + (${score} - 900000) / 150
|
||||
WHEN ${score} >= 800000 THEN (${level} - 500) / 2 + (${score} - 800000) * ((${level} - 500) / 2) / 100000
|
||||
WHEN ${score} >= 500000 THEN ((${level} - 500) / 2 * (${score} - 500000)) / 300000
|
||||
ELSE 0 END) / 100, 0) AS DECIMAL(10, 8))
|
||||
`.as('rating');
|
Loading…
Reference in New Issue
Block a user