From 4a8e0707f03b08de5617802d6918f7b3e4e0eeef Mon Sep 17 00:00:00 2001 From: Thome Valentin Date: Mon, 16 May 2022 06:47:59 +0200 Subject: [PATCH 1/2] Added experimental 'Shared Favorite Songs' option. --- .gitignore | 1 + gitadora@asphyxia/README.md | 12 ++- gitadora@asphyxia/handlers/FavoriteMusic.ts | 93 +++++++++++++++++++ gitadora@asphyxia/handlers/profiles.ts | 9 +- gitadora@asphyxia/index.ts | 12 ++- gitadora@asphyxia/models/favoritemusic.ts | 10 ++ gitadora@asphyxia/utils/index.ts | 6 +- .../webui/profile_player_info.pug | 12 +++ 8 files changed, 145 insertions(+), 10 deletions(-) create mode 100644 gitadora@asphyxia/handlers/FavoriteMusic.ts create mode 100644 gitadora@asphyxia/models/favoritemusic.ts diff --git a/.gitignore b/.gitignore index 7439c72..bfc04ff 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ package.json package-lock.json typedoc.json tsconfig.json +gitadora@asphyxia/data/mdb/blacklist.txt diff --git a/gitadora@asphyxia/README.md b/gitadora@asphyxia/README.md index 2fede0c..d87d34b 100644 --- a/gitadora@asphyxia/README.md +++ b/gitadora@asphyxia/README.md @@ -1,6 +1,6 @@ GITADORA Plugin for Asphyxia-Core ================================= -![Version: v1.2.3](https://img.shields.io/badge/version-v1.2.3-blue) +![Version: v1.3.0](https://img.shields.io/badge/version-v1.3.0-blue) This plugin is based on converted from public-exported Asphyxia's Routes. @@ -20,17 +20,19 @@ The folder structure between v1.0 and v1.1 is quite different. Do not overwrite 2. Ctrl-C and Ctrl-V the newest version of `gitadora@asphyxia` 3. (Custom MDB Users) Reupload MDB or move `data/custom_mdb.xml` to `data/mdb/custom.xml` - Known Issues ============ * ~Information dialog keep showing as plugin doesn't store item data currently.~ (Fixed as of version 1.2.1) - * Special Premium Encore on Nextage - - Bandage solution is implemented. Try it. + * Special Premium Encore on Nextage is unimplemented. However, a workaround is available. Try it. * Friends and Rivals are unimplemented. Release Notes ============= +v1.3.0 +---------------- + * Added experimental 'Shared Favorite Songs' option. If disabled, players will be able to keep separate lists of favorite songs for each version of Gitadora, as well as between Guitar Freaks and Drummania. Enable this option to have a single unified list of favorite songs for both games, and across all versions. Default is false, to match original arcade behaviour. + v1.2.3 ---------------- * Fixed bug preventing MDB files in XML format from loading (Thanks to DualEdge for reporting this ). @@ -47,7 +49,7 @@ v1.2.1 * Secret Music (unlocked songs) are now saved and loaded correctly. Partially fixes Github issue #34. Note that all songs are already marked as unlocked by the server - there is no need to unlock them manually. If you would like to lock them, consider using a custom MDB. * Rewards field is now saved and loaded correctly. Fixes Github issue #34 -NOTE: Rewards and secret music is saved at the end of each session, so you will see the unlock notifications one last time after updating the plugin to this version. +NOTE: Rewards and secret music data is saved at the end of each session, so you will see the unlock notifications one last time after updating the plugin to this version. v1.2.0 ---------------- diff --git a/gitadora@asphyxia/handlers/FavoriteMusic.ts b/gitadora@asphyxia/handlers/FavoriteMusic.ts new file mode 100644 index 0000000..003d713 --- /dev/null +++ b/gitadora@asphyxia/handlers/FavoriteMusic.ts @@ -0,0 +1,93 @@ +import { Extra } from "../models/extra"; +import { FavoriteMusic } from "../models/favoritemusic"; +import { isSharedFavoriteMusicEnabled } from "../utils"; +import Logger from "../utils/logger"; + +const logger = new Logger("FavoriteMusic"); + +/** + * Extracts favorite music data from the given extra data container, and saves it to the database as shared favorite music data for the player with the given refid. + * This function has no effect if the 'Shared favorite music' option is not enabled. + * Note that shared favorite music is shared across both Guitar Freaks and Drummania, as well as all supported versions of the game. + * @param refid The refid of the player. + * @param extra The extra data container of the player, containing the favorite music lists to be saved. + * @returns {boolean} - whether the favorite music data was successfully saved. + */ +export async function saveSharedFavoriteMusicFromExtra(refid: string, extra: Extra) : Promise +{ + if (!isSharedFavoriteMusicEnabled()) { + return false + } + + let result : FavoriteMusic = { + collection: 'favoritemusic', + pluginVer: 1, + list_1: extra.list_1, + list_2: extra.list_2, + list_3: extra.list_3, + recommend_musicid_list: extra.recommend_musicid_list, + } + + try + { + await saveFavoriteMusic(refid, result) + logger.debugInfo(`Saved shared favorite music for profile ${refid} successfully.`); + return true + } + catch (e) + { + logger.error(`Failed to save shared favorite music for profile ${refid}.`); + logger.error(e); + return false + } +} + +/** + * Retrieves shared favorite music data from the database for the player with the given refid, and applies the data to the provided extra data container. + * This function has no effect if the 'Shared favorite music' option is not enabled. + * Note that shared favorite music is shared across both Guitar Freaks and Drummania, as well as all supported versions of the game. + * @param refid - The refid of the player. + * @param extra - The destination object where favorite music data should be applied. + */ +export async function applySharedFavoriteMusicToExtra(refid : string, extra : Extra) : Promise +{ + if (!isSharedFavoriteMusicEnabled()) { + return + } + + try + { + let favoriteMusic = await loadFavoriteMusic(refid) + + if (favoriteMusic == null) { + logger.debugInfo(`No shared favourite music available for profile ${refid}. Using game specific favorites. Favorites will be saved as shared favorites at the end of the game session.`); + return + } + + extra.list_1 = favoriteMusic.list_1 + extra.list_2 = favoriteMusic.list_2 + extra.list_3 = favoriteMusic.list_3 + extra.recommend_musicid_list = favoriteMusic.recommend_musicid_list + logger.debugInfo(`Loaded shared favorite music for profile ${refid} successfully.`); + } + catch (e) + { + logger.error(`Failed to load shared favorite music for profile ${refid}.`); + logger.error(e); + } +} + +export async function saveFavoriteMusic(refid: string, data : FavoriteMusic) : Promise +{ + return await DB.Upsert(refid, { + collection: 'favoritemusic', + }, data) +} + +export async function loadFavoriteMusic(refid : string) : Promise +{ + return await DB.FindOne(refid, { + collection: 'favoritemusic' + }) +} + diff --git a/gitadora@asphyxia/handlers/profiles.ts b/gitadora@asphyxia/handlers/profiles.ts index e5ca1fa..6fc053f 100644 --- a/gitadora@asphyxia/handlers/profiles.ts +++ b/gitadora@asphyxia/handlers/profiles.ts @@ -11,6 +11,7 @@ import { PLUGIN_VER } from "../const"; import Logger from "../utils/logger" import { isAsphyxiaDebugMode } from "../Utils/index"; import { SecretMusicEntry } from "../models/secretmusicentry"; +import { applySharedFavoriteMusicToExtra, saveSharedFavoriteMusicFromExtra } from "./FavoriteMusic"; const logger = new Logger("profiles") @@ -92,6 +93,8 @@ export const getPlayer: EPR = async (info, data, send) => { const profile = dm ? dmProfile : gfProfile; const extra = dm ? dmExtra : gfExtra; + await applySharedFavoriteMusicToExtra(refid, extra) + const record: any = { gf: {}, dm: {}, @@ -820,6 +823,7 @@ export const savePlayers: EPR = async (info, data, send) => { } catch (e) { logger.error(e) + logger.error(e.stack) return send.deny(); } }; @@ -831,7 +835,7 @@ async function saveSinglePlayer(dataplayer: KDataReader, refid: string, no: numb const extra = await getExtra(refid, version, game) as any; const rec = await getRecord(refid, version, game) as any; - const autoSet = (field: keyof Profile, path: string, array = false): void => { + const autoSet = function (field: keyof Profile, path: string, array = false): void { if (array) { profile[field] = dataplayer.numbers(path, profile[field]) } else { @@ -964,10 +968,11 @@ async function saveSinglePlayer(dataplayer: KDataReader, refid: string, no: numb await DB.Upsert(refid, { collection: 'extra', game, version }, extra) const playedStages = dataplayer.elements('stage'); - // logStagesPlayed(playedStages) + logStagesPlayed(playedStages) const scores = await updatePlayerScoreCollection(refid, playedStages, version, game) await saveScore(refid, version, game, scores); + await saveSharedFavoriteMusicFromExtra(refid, extra) } async function updatePlayerScoreCollection(refid, playedStages, version, game) { diff --git a/gitadora@asphyxia/index.ts b/gitadora@asphyxia/index.ts index 78f4ee5..c085a66 100644 --- a/gitadora@asphyxia/index.ts +++ b/gitadora@asphyxia/index.ts @@ -9,7 +9,7 @@ const logger = new Logger("main") export function register() { if(!isRequiredCoreVersion(1, 20)) { - console.error("You need newer version of Core. v1.20 or newer required.") + console.error("A newer version of Asphyxia Core (v1.20 or later) is required.") } R.GameCode('M32'); @@ -38,10 +38,18 @@ export function register() { default: false, }) + R.Config("shared_favorite_songs", { + name: "Shared Favorite Songs (Experimental)", + desc: "If disabled, players will be able to keep separate lists of favorite songs for each version of Gitadora, as well as between Guitar Freaks and Drummania. " + + "Enable this option to have a single unified list of favorite songs for both games, and across all versions. Default is false, to match original arcade behaviour.", + type: "boolean", + default: false, + }) + R.DataFile("data/mdb/custom.xml", { accept: ".xml", name: "Custom MDB", - desc: "You need to enable the 'Enable Custom MDB' option for the uploaded file to have any effect." + desc: "Remember to enable the 'Enable Custom MDB' option for the uploaded file to have any effect." }) R.WebUIEvent('updatePlayerInfo', updatePlayerInfo); diff --git a/gitadora@asphyxia/models/favoritemusic.ts b/gitadora@asphyxia/models/favoritemusic.ts new file mode 100644 index 0000000..1a3d699 --- /dev/null +++ b/gitadora@asphyxia/models/favoritemusic.ts @@ -0,0 +1,10 @@ +export interface FavoriteMusic { + collection: 'favoritemusic', + + pluginVer: number; + list_1: number[]; + list_2: number[]; + list_3: number[]; + recommend_musicid_list: number[]; + +} \ No newline at end of file diff --git a/gitadora@asphyxia/utils/index.ts b/gitadora@asphyxia/utils/index.ts index cfb7a39..e291863 100644 --- a/gitadora@asphyxia/utils/index.ts +++ b/gitadora@asphyxia/utils/index.ts @@ -18,7 +18,11 @@ export function isRequiredCoreVersion(major: number, minor: number) { return core_major > major || (core_major === major && core_minor >= minor) }; -export function isAsphyxiaDebugMode() { +export function isAsphyxiaDebugMode() : boolean { const argv = process.argv return argv.includes("--dev") || argv.includes("--console") +} + +export function isSharedFavoriteMusicEnabled() : boolean{ + return Boolean(U.GetConfig("shared_favorite_songs")) } \ No newline at end of file diff --git a/gitadora@asphyxia/webui/profile_player_info.pug b/gitadora@asphyxia/webui/profile_player_info.pug index db89174..76e5c1c 100644 --- a/gitadora@asphyxia/webui/profile_player_info.pug +++ b/gitadora@asphyxia/webui/profile_player_info.pug @@ -78,6 +78,18 @@ div label.label Excellent Full Combos .control input.input(type="text" name="exce_num", value=pr.exce_num readonly) + .field + label.label Highest Difficulty Cleared + .control + input.input(type="text" name="max_clear_diff", value=(pr.max_clear_diff/100) readonly) + .field + label.label Highest Difficulty Full Combo + .control + input.input(type="text" name="max_full_diff", value=(pr.max_full_diff/100) readonly) + .field + label.label Highest Difficulty Excellent Full Combo + .control + input.input(type="text" name="max_exce_diff", value=(pr.max_exce_diff/100) readonly) .field label.label Sessions .control From b84df19e7c8fcb00208a590648994b9a3e39cebf Mon Sep 17 00:00:00 2001 From: Thome Valentin Date: Mon, 23 May 2022 07:43:50 +0200 Subject: [PATCH 2/2] * Added experimental 'Shared Favorite Songs' option. If disabled, players will be able to keep separate lists of favorite songs for each version of Gitadora, as well as between Guitar Freaks and Drummania. Enable this option to have a single unified list of favorite songs for both games, and across all versions. Default is false, to match original arcade behaviour. * Added a leaderboards page to the WebUI. This page displays the rank of all players per game and version, ordered by Skill rating. * More code cleanups to Profiles.ts --- gitadora@asphyxia/README.md | 10 +- gitadora@asphyxia/handlers/profiles.ts | 97 +-------------- .../Responses/playerplayinforesponse.ts | 71 +++++++++++ .../models/Responses/playerrecordresponse.ts | 110 ++++++++++++++++++ gitadora@asphyxia/webui/leaderboards.pug | 85 ++++++++++++++ .../webui/profile_player_info.pug | 2 +- 6 files changed, 279 insertions(+), 96 deletions(-) create mode 100644 gitadora@asphyxia/models/Responses/playerplayinforesponse.ts create mode 100644 gitadora@asphyxia/models/Responses/playerrecordresponse.ts create mode 100644 gitadora@asphyxia/webui/leaderboards.pug diff --git a/gitadora@asphyxia/README.md b/gitadora@asphyxia/README.md index 0fb7102..3dfee5b 100644 --- a/gitadora@asphyxia/README.md +++ b/gitadora@asphyxia/README.md @@ -29,15 +29,17 @@ Known Issues Release Notes ============= +v1.3.0 +---------------- + * Added experimental 'Shared Favorite Songs' option. If disabled, players will be able to keep separate lists of favorite songs for each version of Gitadora, as well as between Guitar Freaks and Drummania. Enable this option to have a single unified list of favorite songs for both games, and across all versions. Default is false, to match original arcade behaviour. + * Added a leaderboards page to the WebUI. This page displays the rank of all players per game and version, ordered by Skill rating. + * More code cleanups to Profiles.ts + v1.2.4 ---------------- * Fixed note scroll speed defaulting to 0.5x for newly registered profiles. * Misc code cleanup. No changes expected to plugin behaviour. -v1.3.0 ----------------- - * Added experimental 'Shared Favorite Songs' option. If disabled, players will be able to keep separate lists of favorite songs for each version of Gitadora, as well as between Guitar Freaks and Drummania. Enable this option to have a single unified list of favorite songs for both games, and across all versions. Default is false, to match original arcade behaviour. - v1.2.3 ---------------- * Fixed bug preventing MDB files in XML format from loading (Thanks to DualEdge for reporting this ). diff --git a/gitadora@asphyxia/handlers/profiles.ts b/gitadora@asphyxia/handlers/profiles.ts index ca1a99c..0b5c3ec 100644 --- a/gitadora@asphyxia/handlers/profiles.ts +++ b/gitadora@asphyxia/handlers/profiles.ts @@ -16,6 +16,8 @@ import { getSecretMusicResponse, SecretMusicResponse } from "../models/Responses import { getSaveProfileResponse } from "../models/Responses/saveprofileresponse"; import { getDefaultBattleDataResponse } from "../models/Responses/battledataresponse"; import { applySharedFavoriteMusicToExtra, saveSharedFavoriteMusicFromExtra } from "./FavoriteMusic"; +import { getPlayerRecordResponse } from "../models/Responses/playerrecordresponse"; +import { getPlayerPlayInfoResponse, PlayerPlayInfoResponse } from "../models/Responses/playerplayinforesponse"; const logger = new Logger("profiles") @@ -89,65 +91,9 @@ export const getPlayer: EPR = async (info, data, send) => { await applySharedFavoriteMusicToExtra(refid, extra) const record: any = { - gf: {}, - dm: {}, + gf: getPlayerRecordResponse(gfProfile, gfRecord), + dm: getPlayerRecordResponse(dmProfile, dmRecord), }; - for (const mode of ['dm', 'gf']) { - let game = mode == 'gf' ? gfProfile : dmProfile; - let rec = mode == 'gf' ? gfRecord : dmRecord; - record[mode] = { - max_record: { - skill: K.ITEM('s32', game.max_skill), - all_skill: K.ITEM('s32', game.max_all_skill), - clear_diff: K.ITEM('s32', game.clear_diff), - full_diff: K.ITEM('s32', game.full_diff), - exce_diff: K.ITEM('s32', game.exce_diff), - clear_music_num: K.ITEM('s32', game.clear_music_num), - full_music_num: K.ITEM('s32', game.full_music_num), - exce_music_num: K.ITEM('s32', game.exce_music_num), - clear_seq_num: K.ITEM('s32', game.clear_seq_num), - classic_all_skill: K.ITEM('s32', game.classic_all_skill), - }, - diff_record: { - diff_100_nr: K.ITEM('s32', rec.diff_100_nr), - diff_150_nr: K.ITEM('s32', rec.diff_150_nr), - diff_200_nr: K.ITEM('s32', rec.diff_200_nr), - diff_250_nr: K.ITEM('s32', rec.diff_250_nr), - diff_300_nr: K.ITEM('s32', rec.diff_300_nr), - diff_350_nr: K.ITEM('s32', rec.diff_350_nr), - diff_400_nr: K.ITEM('s32', rec.diff_400_nr), - diff_450_nr: K.ITEM('s32', rec.diff_450_nr), - diff_500_nr: K.ITEM('s32', rec.diff_500_nr), - diff_550_nr: K.ITEM('s32', rec.diff_550_nr), - diff_600_nr: K.ITEM('s32', rec.diff_600_nr), - diff_650_nr: K.ITEM('s32', rec.diff_650_nr), - diff_700_nr: K.ITEM('s32', rec.diff_700_nr), - diff_750_nr: K.ITEM('s32', rec.diff_750_nr), - diff_800_nr: K.ITEM('s32', rec.diff_800_nr), - diff_850_nr: K.ITEM('s32', rec.diff_850_nr), - diff_900_nr: K.ITEM('s32', rec.diff_900_nr), - diff_950_nr: K.ITEM('s32', rec.diff_950_nr), - diff_100_clear: K.ARRAY('s32', rec.diff_100_clear), - diff_150_clear: K.ARRAY('s32', rec.diff_150_clear), - diff_200_clear: K.ARRAY('s32', rec.diff_200_clear), - diff_250_clear: K.ARRAY('s32', rec.diff_250_clear), - diff_300_clear: K.ARRAY('s32', rec.diff_300_clear), - diff_350_clear: K.ARRAY('s32', rec.diff_350_clear), - diff_400_clear: K.ARRAY('s32', rec.diff_400_clear), - diff_450_clear: K.ARRAY('s32', rec.diff_450_clear), - diff_500_clear: K.ARRAY('s32', rec.diff_500_clear), - diff_550_clear: K.ARRAY('s32', rec.diff_550_clear), - diff_600_clear: K.ARRAY('s32', rec.diff_600_clear), - diff_650_clear: K.ARRAY('s32', rec.diff_650_clear), - diff_700_clear: K.ARRAY('s32', rec.diff_700_clear), - diff_750_clear: K.ARRAY('s32', rec.diff_750_clear), - diff_800_clear: K.ARRAY('s32', rec.diff_800_clear), - diff_850_clear: K.ARRAY('s32', rec.diff_850_clear), - diff_900_clear: K.ARRAY('s32', rec.diff_900_clear), - diff_950_clear: K.ARRAY('s32', rec.diff_950_clear), - }, - }; - } // Format scores const musicdata = []; @@ -229,6 +175,7 @@ export const getPlayer: EPR = async (info, data, send) => { } const sticker: PlayerStickerResponse[] = getPlayerStickerResponse(name.card); + const playinfo: PlayerPlayInfoResponse = getPlayerPlayInfoResponse(profile); const playerData: any = { playerboard: { @@ -247,39 +194,7 @@ export const getPlayer: EPR = async (info, data, send) => { playstyle: K.ARRAY('s32', extra.playstyle), custom: K.ARRAY('s32', extra.custom), }, - playinfo: { - cabid: K.ITEM('s32', 0), - play: K.ITEM('s32', profile.play), - playtime: K.ITEM('s32', profile.playtime), - playterm: K.ITEM('s32', profile.playterm), - session_cnt: K.ITEM('s32', profile.session_cnt), - matching_num: K.ITEM('s32', 0), - extra_stage: K.ITEM('s32', profile.extra_stage), - extra_play: K.ITEM('s32', profile.extra_play), - extra_clear: K.ITEM('s32', profile.extra_clear), - encore_play: K.ITEM('s32', profile.encore_play), - encore_clear: K.ITEM('s32', profile.encore_clear), - pencore_play: K.ITEM('s32', profile.pencore_play), - pencore_clear: K.ITEM('s32', profile.pencore_clear), - max_clear_diff: K.ITEM('s32', profile.max_clear_diff), - max_full_diff: K.ITEM('s32', profile.max_full_diff), - max_exce_diff: K.ITEM('s32', profile.max_exce_diff), - clear_num: K.ITEM('s32', profile.clear_num), - full_num: K.ITEM('s32', profile.full_num), - exce_num: K.ITEM('s32', profile.exce_num), - no_num: K.ITEM('s32', profile.no_num), - e_num: K.ITEM('s32', profile.e_num), - d_num: K.ITEM('s32', profile.d_num), - c_num: K.ITEM('s32', profile.c_num), - b_num: K.ITEM('s32', profile.b_num), - a_num: K.ITEM('s32', profile.a_num), - s_num: K.ITEM('s32', profile.s_num), - ss_num: K.ITEM('s32', profile.ss_num), - last_category: K.ITEM('s32', profile.last_category), - last_musicid: K.ITEM('s32', profile.last_musicid), - last_seq: K.ITEM('s32', profile.last_seq), - disp_level: K.ITEM('s32', profile.disp_level), - }, + playinfo: playinfo, tutorial: { progress: K.ITEM('s32', profile.progress), disp_state: K.ITEM('u32', profile.disp_state), diff --git a/gitadora@asphyxia/models/Responses/playerplayinforesponse.ts b/gitadora@asphyxia/models/Responses/playerplayinforesponse.ts new file mode 100644 index 0000000..6d95d64 --- /dev/null +++ b/gitadora@asphyxia/models/Responses/playerplayinforesponse.ts @@ -0,0 +1,71 @@ +import { Profile } from "../profile"; + +export interface PlayerPlayInfoResponse { + cabid: KITEM<'s32'>, + play: KITEM<'s32'>, + playtime: KITEM<'s32'>, + playterm: KITEM<'s32'>, + session_cnt: KITEM<'s32'>, + matching_num: KITEM<'s32'>, + extra_stage: KITEM<'s32'>, + extra_play: KITEM<'s32'>, + extra_clear: KITEM<'s32'>, + encore_play: KITEM<'s32'>, + encore_clear: KITEM<'s32'>, + pencore_play: KITEM<'s32'>, + pencore_clear: KITEM<'s32'>, + max_clear_diff: KITEM<'s32'>, + max_full_diff: KITEM<'s32'>, + max_exce_diff: KITEM<'s32'>, + clear_num: KITEM<'s32'>, + full_num: KITEM<'s32'>, + exce_num: KITEM<'s32'>, + no_num: KITEM<'s32'>, + e_num: KITEM<'s32'>, + d_num: KITEM<'s32'>, + c_num: KITEM<'s32'>, + b_num: KITEM<'s32'>, + a_num: KITEM<'s32'>, + s_num: KITEM<'s32'>, + ss_num: KITEM<'s32'>, + last_category: KITEM<'s32'>, + last_musicid: KITEM<'s32'>, + last_seq: KITEM<'s32'>, + disp_level: KITEM<'s32'>, +} +export function getPlayerPlayInfoResponse(profile : Profile) : PlayerPlayInfoResponse { + return { + cabid: K.ITEM('s32', 0), + play: K.ITEM('s32', profile.play), + playtime: K.ITEM('s32', profile.playtime), + playterm: K.ITEM('s32', profile.playterm), + session_cnt: K.ITEM('s32', profile.session_cnt), + matching_num: K.ITEM('s32', 0), + extra_stage: K.ITEM('s32', profile.extra_stage), + extra_play: K.ITEM('s32', profile.extra_play), + extra_clear: K.ITEM('s32', profile.extra_clear), + encore_play: K.ITEM('s32', profile.encore_play), + encore_clear: K.ITEM('s32', profile.encore_clear), + pencore_play: K.ITEM('s32', profile.pencore_play), + pencore_clear: K.ITEM('s32', profile.pencore_clear), + max_clear_diff: K.ITEM('s32', profile.max_clear_diff), + max_full_diff: K.ITEM('s32', profile.max_full_diff), + max_exce_diff: K.ITEM('s32', profile.max_exce_diff), + clear_num: K.ITEM('s32', profile.clear_num), + full_num: K.ITEM('s32', profile.full_num), + exce_num: K.ITEM('s32', profile.exce_num), + no_num: K.ITEM('s32', profile.no_num), + e_num: K.ITEM('s32', profile.e_num), + d_num: K.ITEM('s32', profile.d_num), + c_num: K.ITEM('s32', profile.c_num), + b_num: K.ITEM('s32', profile.b_num), + a_num: K.ITEM('s32', profile.a_num), + s_num: K.ITEM('s32', profile.s_num), + ss_num: K.ITEM('s32', profile.ss_num), + last_category: K.ITEM('s32', profile.last_category), + last_musicid: K.ITEM('s32', profile.last_musicid), + last_seq: K.ITEM('s32', profile.last_seq), + disp_level: K.ITEM('s32', profile.disp_level), + } +} + diff --git a/gitadora@asphyxia/models/Responses/playerrecordresponse.ts b/gitadora@asphyxia/models/Responses/playerrecordresponse.ts new file mode 100644 index 0000000..f12699c --- /dev/null +++ b/gitadora@asphyxia/models/Responses/playerrecordresponse.ts @@ -0,0 +1,110 @@ +import { Profile } from "../profile" +import { Record } from "../record" + +export interface PlayerRecordResponse { + max_record: { + skill: KITEM<'s32'>, + all_skill: KITEM<'s32'>, + clear_diff: KITEM<'s32'>, + full_diff: KITEM<'s32'>, + exce_diff: KITEM<'s32'>, + clear_music_num: KITEM<'s32'>, + full_music_num: KITEM<'s32'>, + exce_music_num: KITEM<'s32'>, + clear_seq_num: KITEM<'s32'>, + classic_all_skill: KITEM<'s32'> + }, + diff_record: { + diff_100_nr: KITEM<'s32'>, + diff_150_nr: KITEM<'s32'>, + diff_200_nr: KITEM<'s32'>, + diff_250_nr: KITEM<'s32'>, + diff_300_nr: KITEM<'s32'>, + diff_350_nr: KITEM<'s32'>, + diff_400_nr: KITEM<'s32'>, + diff_450_nr: KITEM<'s32'>, + diff_500_nr: KITEM<'s32'>, + diff_550_nr: KITEM<'s32'>, + diff_600_nr: KITEM<'s32'>, + diff_650_nr: KITEM<'s32'>, + diff_700_nr: KITEM<'s32'>, + diff_750_nr: KITEM<'s32'>, + diff_800_nr: KITEM<'s32'>, + diff_850_nr: KITEM<'s32'>, + diff_900_nr: KITEM<'s32'>, + diff_950_nr: KITEM<'s32'>, + diff_100_clear: KARRAY<'s32'> + diff_150_clear: KARRAY<'s32'> + diff_200_clear: KARRAY<'s32'> + diff_250_clear: KARRAY<'s32'> + diff_300_clear: KARRAY<'s32'> + diff_350_clear: KARRAY<'s32'> + diff_400_clear: KARRAY<'s32'> + diff_450_clear: KARRAY<'s32'> + diff_500_clear: KARRAY<'s32'> + diff_550_clear: KARRAY<'s32'> + diff_600_clear: KARRAY<'s32'> + diff_650_clear: KARRAY<'s32'> + diff_700_clear: KARRAY<'s32'> + diff_750_clear: KARRAY<'s32'> + diff_800_clear: KARRAY<'s32'> + diff_850_clear: KARRAY<'s32'> + diff_900_clear: KARRAY<'s32'> + diff_950_clear: KARRAY<'s32'> + } +} + +export function getPlayerRecordResponse(profile: Profile, rec: Record) : PlayerRecordResponse { + return { + max_record: { + skill: K.ITEM('s32', profile.max_skill), + all_skill: K.ITEM('s32', profile.max_all_skill), + clear_diff: K.ITEM('s32', profile.clear_diff), + full_diff: K.ITEM('s32', profile.full_diff), + exce_diff: K.ITEM('s32', profile.exce_diff), + clear_music_num: K.ITEM('s32', profile.clear_music_num), + full_music_num: K.ITEM('s32', profile.full_music_num), + exce_music_num: K.ITEM('s32', profile.exce_music_num), + clear_seq_num: K.ITEM('s32', profile.clear_seq_num), + classic_all_skill: K.ITEM('s32', profile.classic_all_skill), + }, + diff_record: { + diff_100_nr: K.ITEM('s32', rec.diff_100_nr), + diff_150_nr: K.ITEM('s32', rec.diff_150_nr), + diff_200_nr: K.ITEM('s32', rec.diff_200_nr), + diff_250_nr: K.ITEM('s32', rec.diff_250_nr), + diff_300_nr: K.ITEM('s32', rec.diff_300_nr), + diff_350_nr: K.ITEM('s32', rec.diff_350_nr), + diff_400_nr: K.ITEM('s32', rec.diff_400_nr), + diff_450_nr: K.ITEM('s32', rec.diff_450_nr), + diff_500_nr: K.ITEM('s32', rec.diff_500_nr), + diff_550_nr: K.ITEM('s32', rec.diff_550_nr), + diff_600_nr: K.ITEM('s32', rec.diff_600_nr), + diff_650_nr: K.ITEM('s32', rec.diff_650_nr), + diff_700_nr: K.ITEM('s32', rec.diff_700_nr), + diff_750_nr: K.ITEM('s32', rec.diff_750_nr), + diff_800_nr: K.ITEM('s32', rec.diff_800_nr), + diff_850_nr: K.ITEM('s32', rec.diff_850_nr), + diff_900_nr: K.ITEM('s32', rec.diff_900_nr), + diff_950_nr: K.ITEM('s32', rec.diff_950_nr), + diff_100_clear: K.ARRAY('s32', rec.diff_100_clear), + diff_150_clear: K.ARRAY('s32', rec.diff_150_clear), + diff_200_clear: K.ARRAY('s32', rec.diff_200_clear), + diff_250_clear: K.ARRAY('s32', rec.diff_250_clear), + diff_300_clear: K.ARRAY('s32', rec.diff_300_clear), + diff_350_clear: K.ARRAY('s32', rec.diff_350_clear), + diff_400_clear: K.ARRAY('s32', rec.diff_400_clear), + diff_450_clear: K.ARRAY('s32', rec.diff_450_clear), + diff_500_clear: K.ARRAY('s32', rec.diff_500_clear), + diff_550_clear: K.ARRAY('s32', rec.diff_550_clear), + diff_600_clear: K.ARRAY('s32', rec.diff_600_clear), + diff_650_clear: K.ARRAY('s32', rec.diff_650_clear), + diff_700_clear: K.ARRAY('s32', rec.diff_700_clear), + diff_750_clear: K.ARRAY('s32', rec.diff_750_clear), + diff_800_clear: K.ARRAY('s32', rec.diff_800_clear), + diff_850_clear: K.ARRAY('s32', rec.diff_850_clear), + diff_900_clear: K.ARRAY('s32', rec.diff_900_clear), + diff_950_clear: K.ARRAY('s32', rec.diff_950_clear), + }, + }; +} diff --git a/gitadora@asphyxia/webui/leaderboards.pug b/gitadora@asphyxia/webui/leaderboards.pug new file mode 100644 index 0000000..aebd616 --- /dev/null +++ b/gitadora@asphyxia/webui/leaderboards.pug @@ -0,0 +1,85 @@ +//DATA// + infos: DB.Find(null, { collection: 'playerinfo' }) + profiles: DB.Find(null, { collection: 'profile' }) +- + +- + function getFullGameName(shortName) { + switch (shortName) { + case "dm" : + return "Drummania" + case "gf": + return "Guitar Freaks" + default: + return "Unknown" + } + } + + const versions = ["exchain", "nextage"] + const games = ["gf", "dm"] + + function generateLeaderboards(infos, profiles) { + let result = [] + + for (const version of versions) { + for (const game of games) { + result.push(generateLeaderboard(infos, profiles, version, game)) + } + } + + // Hide versions and games with no entries + result = result.filter((e) => e.entries.length > 0) + return result + } + + function generateLeaderboard(infos, profiles, version, game) { + let entries = [] + let idx = 1 + let currentProfiles = profiles.filter((e) => e.game === game && e.version === version) + currentProfiles = currentProfiles.sort((a, b) => b.skill - a.skill) + + for (const profile of currentProfiles) { + const info = infos.find(i => i.__refid === profile.__refid) + const name = info ? info.name : "Unknown" + const scoreData = { + rank: idx, + name: name, + skill: profile.skill / 100, + all_skill: profile.all_skill / 100, + clear_music_num : profile.clear_music_num, + clear_diff: profile.clear_diff / 100 + } + entries.push(scoreData) + idx++ + } + + let result = { + version: version, + game: game, + entries: entries + } + return result + } + +- + +each board in generateLeaderboards(infos, profiles) + h3 #{getFullGameName(board.game)} #{board.version} + table + tr + th Rank + th Name + th Skill + th All Skill + th Songs Cleared + th Hardest Clear + each e in board.entries + tr + td #{e.rank} + td #{e.name} + td #{e.skill} + td #{e.all_skill} + td #{e.clear_music_num} + td #{e.clear_diff} + +script(src="js/leaderboards.js") \ No newline at end of file diff --git a/gitadora@asphyxia/webui/profile_player_info.pug b/gitadora@asphyxia/webui/profile_player_info.pug index 76e5c1c..a3ac76b 100644 --- a/gitadora@asphyxia/webui/profile_player_info.pug +++ b/gitadora@asphyxia/webui/profile_player_info.pug @@ -67,7 +67,7 @@ div .control input.input(type="text" name="all_skill", value=(pr.all_skill/100) readonly) .field - label.label Stages Cleared + label.label Songs Cleared .control input.input(type="text" name="clear_num", value=pr.clear_num readonly) .field