forked from sk1982/actaeon
chuni: dont show rate percent for notes with 0 count
This commit is contained in:
parent
6d5661c1f3
commit
9f126d84b1
@ -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'))),
|
||||||
|
@ -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')
|
||||||
|
@ -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),
|
||||||
|
@ -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>}
|
||||||
|
@ -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
13
src/types/db.d.ts
vendored
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user