mirror of https://github.com/hykilpikonna/AquaDX
[O] Lint
parent
6afcb364d1
commit
643e0e0c1f
|
@ -1,5 +1,5 @@
|
|||
export interface TrendEntry {
|
||||
date: string
|
||||
rating: number
|
||||
plays: number
|
||||
export interface TrendEntry {
|
||||
date: string
|
||||
rating: number
|
||||
plays: number
|
||||
}
|
|
@ -1,51 +1,51 @@
|
|||
import {aqua_host, data_host} from "./config";
|
||||
import type {TrendEntry} from "./generalTypes";
|
||||
import type {MaimaiUserSummaryEntry} from "./maimaiTypes";
|
||||
|
||||
|
||||
const multTable = [
|
||||
[100.5, 22.4, "SSSp"],
|
||||
[100, 21.6, "SSS"],
|
||||
[99.5, 21.1, "SSp"],
|
||||
[99, 20.8, "SS"],
|
||||
[98, 20.3, "Sp"],
|
||||
[97, 20, "S"],
|
||||
[94, 16.8, "AAA"],
|
||||
[90, 15.2, "AA"],
|
||||
[80, 13.6, "A"]
|
||||
]
|
||||
|
||||
|
||||
export function getMult(achievement: number) {
|
||||
achievement /= 10000
|
||||
for (let i = 0; i < multTable.length; i++) {
|
||||
if (achievement >= (multTable[i][0] as number)) return multTable[i]
|
||||
}
|
||||
return [0, 0, 0]
|
||||
}
|
||||
|
||||
|
||||
export async function getMaimai(endpoint: string, params: any) {
|
||||
return await fetch(`${aqua_host}/Maimai2Servlet/${endpoint}`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify(params)
|
||||
}).then(res => res.json())
|
||||
}
|
||||
|
||||
export async function getMaimaiAllMusic(): Promise<{ [key: string]: any }> {
|
||||
return fetch(`${data_host}/maimai/meta/00/all-music.json`).then(it => it.json())
|
||||
}
|
||||
|
||||
export async function getMaimaiApi(endpoint: string, params: any) {
|
||||
let url = new URL(`${aqua_host}/api/game/maimai2new/${endpoint}`)
|
||||
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]))
|
||||
return await fetch(url).then(res => res.json())
|
||||
}
|
||||
|
||||
export async function getMaimaiTrend(userId: number): Promise<TrendEntry[]> {
|
||||
return await getMaimaiApi("trend", {userId})
|
||||
}
|
||||
|
||||
export async function getMaimaiUser(userId: number): Promise<MaimaiUserSummaryEntry> {
|
||||
return await getMaimaiApi("user-summary", {userId})
|
||||
import { aqua_host, data_host } from './config'
|
||||
import type { TrendEntry } from './generalTypes'
|
||||
import type { MaimaiUserSummaryEntry } from './maimaiTypes'
|
||||
|
||||
|
||||
const multTable = [
|
||||
[ 100.5, 22.4, 'SSSp' ],
|
||||
[ 100, 21.6, 'SSS' ],
|
||||
[ 99.5, 21.1, 'SSp' ],
|
||||
[ 99, 20.8, 'SS' ],
|
||||
[ 98, 20.3, 'Sp' ],
|
||||
[ 97, 20, 'S' ],
|
||||
[ 94, 16.8, 'AAA' ],
|
||||
[ 90, 15.2, 'AA' ],
|
||||
[ 80, 13.6, 'A' ]
|
||||
]
|
||||
|
||||
|
||||
export function getMult(achievement: number) {
|
||||
achievement /= 10000
|
||||
for (let i = 0; i < multTable.length; i++) {
|
||||
if (achievement >= (multTable[i][0] as number)) return multTable[i]
|
||||
}
|
||||
return [ 0, 0, 0 ]
|
||||
}
|
||||
|
||||
|
||||
export async function getMaimai(endpoint: string, params: any) {
|
||||
return await fetch(`${aqua_host}/Maimai2Servlet/${endpoint}`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params)
|
||||
}).then(res => res.json())
|
||||
}
|
||||
|
||||
export async function getMaimaiAllMusic(): Promise<{ [key: string]: any }> {
|
||||
return fetch(`${data_host}/maimai/meta/00/all-music.json`).then(it => it.json())
|
||||
}
|
||||
|
||||
export async function getMaimaiApi(endpoint: string, params: any) {
|
||||
const url = new URL(`${aqua_host}/api/game/maimai2new/${endpoint}`)
|
||||
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]))
|
||||
return await fetch(url).then(res => res.json())
|
||||
}
|
||||
|
||||
export async function getMaimaiTrend(userId: number): Promise<TrendEntry[]> {
|
||||
return await getMaimaiApi('trend', { userId })
|
||||
}
|
||||
|
||||
export async function getMaimaiUser(userId: number): Promise<MaimaiUserSummaryEntry> {
|
||||
return await getMaimaiApi('user-summary', { userId })
|
||||
}
|
|
@ -1,116 +1,116 @@
|
|||
export interface Rating {
|
||||
musicId: number
|
||||
level: number
|
||||
achievement: number
|
||||
}
|
||||
|
||||
export interface ParsedRating extends Rating {
|
||||
music: MaimaiMusic,
|
||||
calc: number,
|
||||
rank: string
|
||||
}
|
||||
|
||||
export interface MaimaiMusic {
|
||||
name: string,
|
||||
composer: string,
|
||||
bpm: number,
|
||||
ver: number,
|
||||
note: {
|
||||
lv: number
|
||||
designer: string
|
||||
lv_id: number
|
||||
notes: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface MaimaiUserSummaryEntry {
|
||||
name: string
|
||||
iconId: number
|
||||
serverRank: number
|
||||
accuracy: number
|
||||
rating: number
|
||||
ratingHighest: number
|
||||
ranks: { name: string, count: number }[]
|
||||
maxCombo: number
|
||||
fullCombo: number
|
||||
allPerfect: number
|
||||
totalDxScore: number
|
||||
plays: number
|
||||
totalPlayTime: number
|
||||
joined: string
|
||||
lastSeen: string
|
||||
lastVersion: string
|
||||
best35: string
|
||||
best15: string
|
||||
recent: MaimaiUserPlaylog[]
|
||||
}
|
||||
|
||||
export interface MaimaiUserPlaylog {
|
||||
id: number;
|
||||
musicId: number;
|
||||
level: number;
|
||||
userPlayDate: string;
|
||||
trackNo: number;
|
||||
vsRank: number;
|
||||
achievement: number;
|
||||
deluxscore: number;
|
||||
scoreRank: number;
|
||||
maxCombo: number;
|
||||
totalCombo: number;
|
||||
maxSync: number;
|
||||
totalSync: number;
|
||||
tapCriticalPerfect: number;
|
||||
tapPerfect: number;
|
||||
tapGreat: number;
|
||||
tapGood: number;
|
||||
tapMiss: number;
|
||||
holdCriticalPerfect: number;
|
||||
holdPerfect: number;
|
||||
holdGreat: number;
|
||||
holdGood: number;
|
||||
holdMiss: number;
|
||||
slideCriticalPerfect: number;
|
||||
slidePerfect: number;
|
||||
slideGreat: number;
|
||||
slideGood: number;
|
||||
slideMiss: number;
|
||||
touchCriticalPerfect: number;
|
||||
touchPerfect: number;
|
||||
touchGreat: number;
|
||||
touchGood: number;
|
||||
touchMiss: number;
|
||||
breakCriticalPerfect: number;
|
||||
breakPerfect: number;
|
||||
breakGreat: number;
|
||||
breakGood: number;
|
||||
breakMiss: number;
|
||||
isTap: boolean;
|
||||
isHold: boolean;
|
||||
isSlide: boolean;
|
||||
isTouch: boolean;
|
||||
isBreak: boolean;
|
||||
isCriticalDisp: boolean;
|
||||
isFastLateDisp: boolean;
|
||||
fastCount: number;
|
||||
lateCount: number;
|
||||
isAchieveNewRecord: boolean;
|
||||
isDeluxscoreNewRecord: boolean;
|
||||
comboStatus: number;
|
||||
syncStatus: number;
|
||||
isClear: boolean;
|
||||
beforeRating: number;
|
||||
afterRating: number;
|
||||
beforeGrade: number;
|
||||
afterGrade: number;
|
||||
afterGradeRank: number;
|
||||
beforeDeluxRating: number;
|
||||
afterDeluxRating: number;
|
||||
isPlayTutorial: boolean;
|
||||
isEventMode: boolean;
|
||||
isFreedomMode: boolean;
|
||||
playMode: number;
|
||||
isNewFree: boolean;
|
||||
trialPlayAchievement: number;
|
||||
extNum1: number;
|
||||
extNum2: number;
|
||||
}
|
||||
export interface Rating {
|
||||
musicId: number
|
||||
level: number
|
||||
achievement: number
|
||||
}
|
||||
|
||||
export interface ParsedRating extends Rating {
|
||||
music: MaimaiMusic,
|
||||
calc: number,
|
||||
rank: string
|
||||
}
|
||||
|
||||
export interface MaimaiMusic {
|
||||
name: string,
|
||||
composer: string,
|
||||
bpm: number,
|
||||
ver: number,
|
||||
note: {
|
||||
lv: number
|
||||
designer: string
|
||||
lv_id: number
|
||||
notes: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface MaimaiUserSummaryEntry {
|
||||
name: string
|
||||
iconId: number
|
||||
serverRank: number
|
||||
accuracy: number
|
||||
rating: number
|
||||
ratingHighest: number
|
||||
ranks: { name: string, count: number }[]
|
||||
maxCombo: number
|
||||
fullCombo: number
|
||||
allPerfect: number
|
||||
totalDxScore: number
|
||||
plays: number
|
||||
totalPlayTime: number
|
||||
joined: string
|
||||
lastSeen: string
|
||||
lastVersion: string
|
||||
best35: string
|
||||
best15: string
|
||||
recent: MaimaiUserPlaylog[]
|
||||
}
|
||||
|
||||
export interface MaimaiUserPlaylog {
|
||||
id: number;
|
||||
musicId: number;
|
||||
level: number;
|
||||
userPlayDate: string;
|
||||
trackNo: number;
|
||||
vsRank: number;
|
||||
achievement: number;
|
||||
deluxscore: number;
|
||||
scoreRank: number;
|
||||
maxCombo: number;
|
||||
totalCombo: number;
|
||||
maxSync: number;
|
||||
totalSync: number;
|
||||
tapCriticalPerfect: number;
|
||||
tapPerfect: number;
|
||||
tapGreat: number;
|
||||
tapGood: number;
|
||||
tapMiss: number;
|
||||
holdCriticalPerfect: number;
|
||||
holdPerfect: number;
|
||||
holdGreat: number;
|
||||
holdGood: number;
|
||||
holdMiss: number;
|
||||
slideCriticalPerfect: number;
|
||||
slidePerfect: number;
|
||||
slideGreat: number;
|
||||
slideGood: number;
|
||||
slideMiss: number;
|
||||
touchCriticalPerfect: number;
|
||||
touchPerfect: number;
|
||||
touchGreat: number;
|
||||
touchGood: number;
|
||||
touchMiss: number;
|
||||
breakCriticalPerfect: number;
|
||||
breakPerfect: number;
|
||||
breakGreat: number;
|
||||
breakGood: number;
|
||||
breakMiss: number;
|
||||
isTap: boolean;
|
||||
isHold: boolean;
|
||||
isSlide: boolean;
|
||||
isTouch: boolean;
|
||||
isBreak: boolean;
|
||||
isCriticalDisp: boolean;
|
||||
isFastLateDisp: boolean;
|
||||
fastCount: number;
|
||||
lateCount: number;
|
||||
isAchieveNewRecord: boolean;
|
||||
isDeluxscoreNewRecord: boolean;
|
||||
comboStatus: number;
|
||||
syncStatus: number;
|
||||
isClear: boolean;
|
||||
beforeRating: number;
|
||||
afterRating: number;
|
||||
beforeGrade: number;
|
||||
afterGrade: number;
|
||||
afterGradeRank: number;
|
||||
beforeDeluxRating: number;
|
||||
afterDeluxRating: number;
|
||||
isPlayTutorial: boolean;
|
||||
isEventMode: boolean;
|
||||
isFreedomMode: boolean;
|
||||
playMode: number;
|
||||
isNewFree: boolean;
|
||||
trialPlayAchievement: number;
|
||||
extNum1: number;
|
||||
extNum2: number;
|
||||
}
|
||||
|
|
|
@ -1,101 +1,100 @@
|
|||
import {
|
||||
Chart as ChartJS,
|
||||
Title,
|
||||
Tooltip,
|
||||
Legend,
|
||||
LineElement,
|
||||
LinearScale,
|
||||
PointElement,
|
||||
CategoryScale, TimeScale, type ChartOptions, type LineOptions,
|
||||
} from 'chart.js';
|
||||
import moment from "moment/moment";
|
||||
// @ts-ignore
|
||||
import CalHeatmap from "cal-heatmap";
|
||||
// @ts-ignore
|
||||
import CalTooltip from 'cal-heatmap/plugins/Tooltip';
|
||||
import type {Line} from "svelte-chartjs";
|
||||
|
||||
export function title(t: string) {
|
||||
document.title = `AquaNet - ${t}`
|
||||
}
|
||||
|
||||
export function registerChart() {
|
||||
ChartJS.register(
|
||||
Title,
|
||||
Tooltip,
|
||||
Legend,
|
||||
LineElement,
|
||||
LinearScale,
|
||||
PointElement,
|
||||
CategoryScale,
|
||||
TimeScale
|
||||
);
|
||||
}
|
||||
|
||||
export function renderCal(el: HTMLElement, d: {date: any, value: any}[]) {
|
||||
const cal = new CalHeatmap();
|
||||
return cal.paint({
|
||||
itemSelector: el,
|
||||
domain: {
|
||||
type: 'month',
|
||||
label: { text: 'MMM', textAlign: 'start', position: 'top' },
|
||||
},
|
||||
subDomain: {
|
||||
type: 'ghDay',
|
||||
radius: 2, width: 11, height: 11, gutter: 4
|
||||
},
|
||||
range: 12,
|
||||
data: {source: d, x: 'date', y: 'value'},
|
||||
scale: {
|
||||
color: {
|
||||
type: 'linear',
|
||||
range: ['#14432a', '#4dd05a'],
|
||||
domain: [0, d.reduce((a, b) => Math.max(a, b.value), 0)]
|
||||
},
|
||||
},
|
||||
date: {start: moment().subtract(1, 'year').add(1, 'month').toDate()},
|
||||
theme: "dark",
|
||||
}, [
|
||||
[CalTooltip, {text: (_: Date, v: number, d: any) =>
|
||||
`${v ?? "No"} songs played on ${d.format('MMMM D, YYYY')}`}]
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
export const CHARTJS_OPT: ChartOptions<"line"> = {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
// TODO: Show point on hover
|
||||
elements: {
|
||||
point: {
|
||||
radius: 0
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
xAxis: {
|
||||
type: 'time',
|
||||
display: false
|
||||
},
|
||||
y: {
|
||||
display: false,
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
tooltip: {
|
||||
mode: "index",
|
||||
intersect: false
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Usage: clazz({a: false, b: true}) -> "b"
|
||||
*
|
||||
* @param obj HashMap<string, boolean>
|
||||
*/
|
||||
export function clazz(obj: { [key: string]: boolean }) {
|
||||
return Object.keys(obj).filter(k => obj[k]).join(" ")
|
||||
}
|
||||
import {
|
||||
Chart as ChartJS,
|
||||
Title,
|
||||
Tooltip,
|
||||
Legend,
|
||||
LineElement,
|
||||
LinearScale,
|
||||
PointElement,
|
||||
CategoryScale, TimeScale, type ChartOptions, type LineOptions,
|
||||
} from 'chart.js'
|
||||
import moment from 'moment/moment'
|
||||
// @ts-expect-error Cal-heatmap does not have proper types
|
||||
import CalHeatmap from 'cal-heatmap'
|
||||
// @ts-expect-error Cal-heatmap does not have proper types
|
||||
import CalTooltip from 'cal-heatmap/plugins/Tooltip'
|
||||
|
||||
export function title(t: string) {
|
||||
document.title = `AquaNet - ${t}`
|
||||
}
|
||||
|
||||
export function registerChart() {
|
||||
ChartJS.register(
|
||||
Title,
|
||||
Tooltip,
|
||||
Legend,
|
||||
LineElement,
|
||||
LinearScale,
|
||||
PointElement,
|
||||
CategoryScale,
|
||||
TimeScale
|
||||
)
|
||||
}
|
||||
|
||||
export function renderCal(el: HTMLElement, d: {date: any, value: any}[]) {
|
||||
const cal = new CalHeatmap()
|
||||
return cal.paint({
|
||||
itemSelector: el,
|
||||
domain: {
|
||||
type: 'month',
|
||||
label: { text: 'MMM', textAlign: 'start', position: 'top' },
|
||||
},
|
||||
subDomain: {
|
||||
type: 'ghDay',
|
||||
radius: 2, width: 11, height: 11, gutter: 4
|
||||
},
|
||||
range: 12,
|
||||
data: { source: d, x: 'date', y: 'value' },
|
||||
scale: {
|
||||
color: {
|
||||
type: 'linear',
|
||||
range: [ '#14432a', '#4dd05a' ],
|
||||
domain: [ 0, d.reduce((a, b) => Math.max(a, b.value), 0) ]
|
||||
},
|
||||
},
|
||||
date: { start: moment().subtract(1, 'year').add(1, 'month').toDate() },
|
||||
theme: 'dark',
|
||||
}, [
|
||||
[ CalTooltip, { text: (_: Date, v: number, d: any) =>
|
||||
`${v ?? 'No'} songs played on ${d.format('MMMM D, YYYY')}` }]
|
||||
])
|
||||
}
|
||||
|
||||
|
||||
export const CHARTJS_OPT: ChartOptions<'line'> = {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
// TODO: Show point on hover
|
||||
elements: {
|
||||
point: {
|
||||
radius: 0
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
xAxis: {
|
||||
type: 'time',
|
||||
display: false
|
||||
},
|
||||
y: {
|
||||
display: false,
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
tooltip: {
|
||||
mode: 'index',
|
||||
intersect: false
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Usage: clazz({a: false, b: true}) -> "b"
|
||||
*
|
||||
* @param obj HashMap<string, boolean>
|
||||
*/
|
||||
export function clazz(obj: { [key: string]: boolean }) {
|
||||
return Object.keys(obj).filter(k => obj[k]).join(' ')
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import './app.sass'
|
||||
import App from './App.svelte'
|
||||
|
||||
// @ts-ignore
|
||||
const app = new App({target: document.getElementById('app')})
|
||||
const app = new App({ target: document.getElementById('app')! })
|
||||
|
||||
export default app
|
Loading…
Reference in New Issue