chuni: dont show rate percent for notes with 0 count

This commit is contained in:
sk1982 2024-04-13 04:10:49 -04:00
parent 6d5661c1f3
commit 9f126d84b1
6 changed files with 47 additions and 15 deletions

View File

@ -22,11 +22,14 @@ export const getMusic = async (musicId?: number) => {
.on('favorite.favKind', '=', 1) .on('favorite.favKind', '=', 1)
.on('favorite.user', '=', user?.id!) .on('favorite.user', '=', user?.id!)
) )
.innerJoin('actaeon_chuni_static_music_ext as musicExt', join =>
join.onRef('music.songId', '=', 'musicExt.songId')
.onRef('music.chartId', '=', 'musicExt.chartId'))
.select(({ fn }) => [...CHUNI_MUSIC_PROPERTIES, .select(({ fn }) => [...CHUNI_MUSIC_PROPERTIES,
'score.isFullCombo', 'score.isAllJustice', 'score.isSuccess', 'score.scoreRank', 'score.scoreMax', 'score.isFullCombo', 'score.isAllJustice', 'score.isSuccess', 'score.scoreRank', 'score.scoreMax',
'score.maxComboCount', 'score.maxComboCount',
fn<boolean>('NOT ISNULL', ['favorite.favId']).as('favorite'), fn<boolean>('NOT ISNULL', ['favorite.favId']).as('favorite'),
chuniRating()]) chuniRating()] as const)
.where(({ selectFrom, eb, and, or }) => and([ .where(({ selectFrom, eb, and, or }) => and([
eb('music.version', '=', selectFrom('chuni_static_music') eb('music.version', '=', selectFrom('chuni_static_music')
.select(({ fn }) => fn.max('version').as('latest'))), .select(({ fn }) => fn.max('version').as('latest'))),

View File

@ -36,6 +36,9 @@ export async function getPlaylog(opts: GetPlaylogOptions) {
.innerJoin('chuni_static_music as music', join => join .innerJoin('chuni_static_music as music', join => join
.onRef('music.songId', '=', 'playlog.musicId') .onRef('music.songId', '=', 'playlog.musicId')
.onRef('music.chartId', '=', 'playlog.level')) .onRef('music.chartId', '=', 'playlog.level'))
.innerJoin('actaeon_chuni_static_music_ext as musicExt', join => join
.onRef('music.songId', '=', 'musicExt.songId')
.onRef('music.chartId', '=', 'musicExt.chartId'))
.where(({ and, eb, selectFrom }) => and([ .where(({ and, eb, selectFrom }) => and([
eb('playlog.user', '=', user.id), eb('playlog.user', '=', user.id),
eb('music.version', '=', selectFrom('chuni_static_music') eb('music.version', '=', selectFrom('chuni_static_music')
@ -52,7 +55,7 @@ export async function getPlaylog(opts: GetPlaylogOptions) {
chuniRating(ref('playlog.score')), chuniRating(ref('playlog.score')),
sql<number>`(playlog.playerRating - (LEAD(playlog.playerRating) OVER (ORDER BY id DESC)))` sql<number>`(playlog.playerRating - (LEAD(playlog.playerRating) OVER (ORDER BY id DESC)))`
.as('playerRatingChange') .as('playerRatingChange')
]) ] as const)
.orderBy('playlog.id desc') .orderBy('playlog.id desc')
) )
.selectFrom('p') .selectFrom('p')

View File

@ -93,6 +93,9 @@ export async function getUserRating(user: UserPayload) {
))`.as('score'), join => join.onTrue()) ))`.as('score'), join => join.onTrue())
.innerJoin('chuni_static_music as music', join => join.onRef('score.musicId', '=', 'music.songId') .innerJoin('chuni_static_music as music', join => join.onRef('score.musicId', '=', 'music.songId')
.onRef('score.level', '=', 'music.chartId')) .onRef('score.level', '=', 'music.chartId'))
.innerJoin('actaeon_chuni_static_music_ext as musicExt', join => join
.onRef('music.songId', '=', 'musicExt.songId')
.onRef('music.chartId', '=', 'musicExt.chartId'))
.select(({ lit }) => [...CHUNI_MUSIC_PROPERTIES, chuniRating(sql.raw(`CAST(score.scoreMax AS INT)`)), .select(({ lit }) => [...CHUNI_MUSIC_PROPERTIES, chuniRating(sql.raw(`CAST(score.scoreMax AS INT)`)),
sql<string>`CAST(score.scoreMax AS INT)`.as('scoreMax'), sql<string>`CAST(score.scoreMax AS INT)`.as('scoreMax'),
lit<number>(1).as('pastIndex') lit<number>(1).as('pastIndex')
@ -104,8 +107,10 @@ export async function getUserRating(user: UserPayload) {
const top = await db.selectFrom('chuni_score_best as score') const top = await db.selectFrom('chuni_score_best as score')
.innerJoin('chuni_static_music as music', join => join .innerJoin('chuni_static_music as music', join => join
.onRef('music.songId', '=', 'score.musicId') .onRef('music.songId', '=', 'score.musicId')
.onRef('music.chartId', '=', 'score.level') .onRef('music.chartId', '=', 'score.level'))
) .innerJoin('actaeon_chuni_static_music_ext as musicExt', join => join
.onRef('music.songId', '=', 'musicExt.songId')
.onRef('music.chartId', '=', 'musicExt.chartId'))
.where(({ eb, and, selectFrom }) => and([ .where(({ eb, and, selectFrom }) => and([
eb('user', '=', user.id), eb('user', '=', user.id),
eb('score.level', '!=', 5), eb('score.level', '!=', 5),

View File

@ -32,6 +32,14 @@ const getChangeColor = (val: number) => {
}; };
export const ChuniPlaylogCard = ({ playlog, className, badgeClass, showDetails }: ChuniPlaylogCardProps) => { export const ChuniPlaylogCard = ({ playlog, className, badgeClass, showDetails }: ChuniPlaylogCardProps) => {
const rate = showDetails ? <>
{!!playlog.tapJudgeCount && <div>Tap: {(playlog.rateTap! / 100).toFixed(2)}%</div>}
{!!playlog.flickJudgeCount && <div>Flick: {(playlog.rateFlick! / 100).toFixed(2)}%</div>}
{!!playlog.holdJudgeCount && <div>Hold: {(playlog.rateHold! / 100).toFixed(2)}%</div>}
{!!playlog.slideJudgeCount && <div>Slide: {(playlog.rateSlide! / 100).toFixed(2)}%</div>}
{!!playlog.airJudgeCount && <div>Air: {(playlog.rateAir! / 100).toFixed(2)}%</div>}
</> : null;
return (<TickerHoverProvider>{setHover => <div onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)} return (<TickerHoverProvider>{setHover => <div onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
className={`rounded-md bg-content1 relative flex flex-col p-2 pt-1 border border-black/25 ${className ?? ''}`}> className={`rounded-md bg-content1 relative flex flex-col p-2 pt-1 border border-black/25 ${className ?? ''}`}>
<div className="flex"> <div className="flex">
@ -68,11 +76,8 @@ export const ChuniPlaylogCard = ({ playlog, className, badgeClass, showDetails }
{showDetails && <div className="hidden md:flex flex-col text-sm gap-1 items-end text-nowrap ml-1"> {showDetails && <div className="hidden md:flex flex-col text-sm gap-1 items-end text-nowrap ml-1">
<div className="text-xs my-1">{formatJst(playlog.userPlayDate!)}</div> <div className="text-xs my-1">{formatJst(playlog.userPlayDate!)}</div>
<div>Tap: {(playlog.rateTap! / 100).toFixed(2)}%</div> {rate}
<div>Flick: {(playlog.rateFlick! / 100).toFixed(2)}%</div> <div style={{ marginBottom: `${(+!playlog.tapJudgeCount + +!playlog.flickJudgeCount + +!playlog.holdJudgeCount + +!playlog.slideJudgeCount + +!playlog.airJudgeCount) * 1.25}rem` }} />
<div>Hold: {(playlog.rateHold! / 100).toFixed(2)}%</div>
<div>Slide: {(playlog.rateSlide! / 100).toFixed(2)}%</div>
<div>Air: {(playlog.rateAir! / 100).toFixed(2)}%</div>
</div>} </div>}
</div> </div>
<div <div
@ -94,11 +99,7 @@ export const ChuniPlaylogCard = ({ playlog, className, badgeClass, showDetails }
{showDetails && <> {showDetails && <>
<Divider className="md:hidden my-2"/> <Divider className="md:hidden my-2"/>
<div className="flex flex-wrap text-xs justify-around md:hidden gap-1 mb-1"> <div className="flex flex-wrap text-xs justify-around md:hidden gap-1 mb-1">
<div>Tap: {(playlog.rateTap! / 100).toFixed(2)}%</div> {rate}
<div>Flick: {(playlog.rateFlick! / 100).toFixed(2)}%</div>
<div>Hold: {(playlog.rateHold! / 100).toFixed(2)}%</div>
<div>Slide: {(playlog.rateSlide! / 100).toFixed(2)}%</div>
<div>Air: {(playlog.rateAir! / 100).toFixed(2)}%</div>
</div> </div>
</>} </>}
</div>} </div>}

View File

@ -6,6 +6,13 @@ export const CHUNI_MUSIC_PROPERTIES = ['music.songId',
'music.worldsEndTag', 'music.worldsEndTag',
'music.genre', 'music.genre',
'music.version', 'music.version',
'music.level' 'music.level',
'musicExt.chartDesigner',
'musicExt.tapJudgeCount',
'musicExt.holdJudgeCount',
'musicExt.slideJudgeCount',
'musicExt.airJudgeCount',
'musicExt.flickJudgeCount',
'musicExt.allJudgeCount'
// sql<string>`CAST(music.level AS DECIMAL(3, 1))`.as('level') // sql<string>`CAST(music.level AS DECIMAL(3, 1))`.as('level')
] as const; ] as const;

13
src/types/db.d.ts vendored
View File

@ -21,6 +21,18 @@ export interface ActaeonChuniStaticMapIcon {
sortName: string | null; sortName: string | null;
} }
export interface ActaeonChuniStaticMusicExt {
airJudgeCount: number;
allJudgeCount: number;
chartDesigner: string | null;
chartId: number;
flickJudgeCount: number;
holdJudgeCount: number;
slideJudgeCount: number;
songId: number;
tapJudgeCount: number;
}
export interface ActaeonChuniStaticNamePlate { export interface ActaeonChuniStaticNamePlate {
id: number; id: number;
imagePath: string | null; imagePath: string | null;
@ -3343,6 +3355,7 @@ export interface DB {
actaeon_arcade_ext: ActaeonArcadeExt; actaeon_arcade_ext: ActaeonArcadeExt;
actaeon_arcade_join_keys: ActaeonArcadeJoinKeys; actaeon_arcade_join_keys: ActaeonArcadeJoinKeys;
actaeon_chuni_static_map_icon: ActaeonChuniStaticMapIcon; actaeon_chuni_static_map_icon: ActaeonChuniStaticMapIcon;
actaeon_chuni_static_music_ext: ActaeonChuniStaticMusicExt;
actaeon_chuni_static_name_plate: ActaeonChuniStaticNamePlate; actaeon_chuni_static_name_plate: ActaeonChuniStaticNamePlate;
actaeon_chuni_static_system_voice: ActaeonChuniStaticSystemVoice; actaeon_chuni_static_system_voice: ActaeonChuniStaticSystemVoice;
actaeon_chuni_static_trophies: ActaeonChuniStaticTrophies; actaeon_chuni_static_trophies: ActaeonChuniStaticTrophies;