diff --git a/.env.development b/.env.development index d189dc0..4bfcedf 100644 --- a/.env.development +++ b/.env.development @@ -1,4 +1,4 @@ -VITE_APP_VERSION="3.0.32" +VITE_APP_VERSION="3.0.33" VITE_API_URL="http://localhost:8000/" VITE_API_KEY="your_api_key_should_be_here" VITE_ASSET_PATH="/assets" diff --git a/.env.production b/.env.production index b0dde1e..ec6b008 100644 --- a/.env.production +++ b/.env.production @@ -1,4 +1,4 @@ -VITE_APP_VERSION="3.0.32" +VITE_APP_VERSION="3.0.33" VITE_API_URL="https://restfulsleep.phaseii.network" VITE_API_KEY="your_api_key_should_be_here" VITE_ASSET_PATH="https://cdn.phaseii.network/file/PhaseII/web-assets" diff --git a/public/data-sources/changelog.json b/public/data-sources/changelog.json index 6b4fdd7..7776f1a 100644 --- a/public/data-sources/changelog.json +++ b/public/data-sources/changelog.json @@ -31,5 +31,6 @@ "3.0.29": ["- (Major) Finish arcade PASELI support", "- (Minor) Clean up arcade page, add button for opening owner", "- (Bugfix) Fix table upper curved edges"], "3.0.30": ["- (Major) Rewrite auth flow at backend and frontend", "- (Minor) Add auth to all api calls", "- (Bugfix) Fix bad user auth bug", "- (Minor) Add more greetings"], "3.0.31": ["- (Major) Change all date formatting to a sortable format", "- (Minor) Add news archive page", "- (Bugfix) Add real news limiting", "- (Shrimp) Add more shrimp"], - "3.0.32": ["- (Major) Change phase \"Attempt\" to \"Score\"", "- (Bugfix) Fix pop'n music version sorting", "- (Bugfix) Fix Gitadora chart data formatting issues", "- (Bugfix) Filter personal records to songs with scores"] + "3.0.32": ["- (Major) Change phase \"Attempt\" to \"Score\"", "- (Bugfix) Fix pop'n music version sorting", "- (Bugfix) Fix Gitadora chart data formatting issues", "- (Bugfix) Filter personal records to songs with scores"], + "3.0.33": ["- (Major) Condense all score tables to one parser and format", "- (Major) Add more game metadata", "- (Bugfix) Fix difficulties showing as `NaN`", "- (Beta) Add a developmental device plugin for card effect"] } \ No newline at end of file diff --git a/src/constants/index.js b/src/constants/index.js index d594281..4fcd43c 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -361,8 +361,9 @@ export const gameData = [ noRivals: true, useUnicode: true, scoreHeaders: [ - { text: "Combos", value: "data.combo" }, - { text: "Medal", value: "data.medal" }, + { text: "Clear Gauge", value: "data.clear_gauge", width: 120 }, + { text: "Combos", value: "data.combo", width: 120 }, + { text: "Medal", value: "data.medal", width: 120 }, ], chartTable: { 0: "LIGHT", @@ -441,7 +442,10 @@ export const gameData = [ icon: null, cardBG: null, noRivals: true, - scoreHeaders: [{ text: "Combos", value: "data.combo" }], + scoreHeaders: [ + { text: "Combos", value: "data.combo", width: 120 }, + { text: "Halo", value: "data.param", width: 120 }, + ], chartTable: { 0: "1A", 1: "2A", diff --git a/src/constants/scoreDataFilters.js b/src/constants/scoreDataFilters.js new file mode 100644 index 0000000..9cab3c2 --- /dev/null +++ b/src/constants/scoreDataFilters.js @@ -0,0 +1,13 @@ +export function shouldRenderChart(difficulty, chartTable, chartKey) { + const invalidDifficulties = [0, -1, "-1", null]; + const hasValidDifficulty = !invalidDifficulties.includes(difficulty); + const hasChartInTable = !!chartTable?.[chartKey]; + return hasValidDifficulty && hasChartInTable; +} + +export function formatDifficulty(difficulty, difficultyDenom = 1) { + if (isNaN(difficulty / difficultyDenom)) { + return difficulty; + } + return difficulty / difficultyDenom; +} diff --git a/src/constants/table/scores.js b/src/constants/table/scores.js new file mode 100644 index 0000000..304e745 --- /dev/null +++ b/src/constants/table/scores.js @@ -0,0 +1,143 @@ +import { formatSortableDate } from "@/constants/date"; +import { formatDifficulty } from "@/constants/scoreDataFilters"; + +export function scoreHeaders(thisGame) { + const headers = [ + { text: "Player", value: "username", width: 120 }, + { text: "New PB", value: "newRecord", width: 100 }, + { text: "Timestamp", value: "timestamp", width: 140 }, + { text: "Song", value: "song.name", width: 180 }, + { text: "Artist", value: "song.artist", width: 150 }, + { text: "Chart", value: "song.chart", width: 100 }, + { text: "Grade", value: "data.rank", width: 80 }, + { text: "Score", value: "points", width: 120 }, + ]; + + if (thisGame.scoreHeaders) { + for (var header of thisGame.scoreHeaders) { + headers.push(header); + } + } + + return headers; +} + +export function personalScoreHeaders(thisGame) { + const headers = [ + { text: "Timestamp", value: "timestamp", width: 140 }, + { text: "New PB", value: "newRecord", width: 100 }, + { text: "Song", value: "song.name", width: 180 }, + { text: "Artist", value: "song.artist", width: 180 }, + { text: "Chart", value: "song.chart", width: 120 }, + { text: "Grade", value: "data.rank", width: 80 }, + { text: "Score", value: "points", width: 120 }, + ]; + + if (thisGame.scoreHeaders) { + for (var header of thisGame.scoreHeaders) { + headers.push(header); + } + } + + return headers; +} + +export function formatScoreTable(thisGame, scores) { + var formattedItems = []; + for (var item of scores) { + if (item.newRecord) { + item.newRecord = "✅"; + } else { + item.newRecord = ""; + } + + if (item.timestamp) { + item.timestamp = formatSortableDate(item.timestamp); + } + + if (item.points != undefined) { + item.points = item.points + .toString() + .replace(/\B(? 0) { + item.data.skill_perc = `${item.data?.skill_perc / 100}%`; + } else { + item.data.skill_perc = "0%"; + } + + if (item.data?.skill_points) { + item.data.skill_points = item.data?.skill_points / 10; + } + + if (item.data?.perc > 0) { + item.data.perc = `${item.data?.perc / 100}%`; + } else { + item.data.perc = "0%"; + } + + if (item.data?.new_skill) { + item.data.new_skill = item.data?.new_skill / 10; + } + + if (item.data?.music_rate) { + item.data.music_rate = item.data?.music_rate / 10; + } + + if (item.data?.excellent) { + item.medal = "EX FC"; + } else if (item.data?.fullcombo) { + item.medal = "FC"; + } else if (item.data?.clear) { + item.medal = "CLEARED"; + } else { + item.medal = "FAILED"; + } + + if (item.data?.clear_gauge !== undefined) { + item.data.clear_gauge = `${item.data?.clear_gauge / 10}%`; + } + + formattedItems.push(item); + } + return formattedItems; +} diff --git a/src/views/Game/NetworkRecords.vue b/src/views/Game/NetworkRecords.vue index 3fe43d0..611e12a 100644 --- a/src/views/Game/NetworkRecords.vue +++ b/src/views/Game/NetworkRecords.vue @@ -12,6 +12,11 @@ import GameHeader from "@/components/Cards/GameHeader.vue"; import { APIGetRecordData } from "@/stores/api/music"; import { getGameInfo } from "@/constants"; +import { + shouldRenderChart, + formatDifficulty, +} from "@/constants/scoreDataFilters"; + const $route = useRoute(); const $router = useRouter(); var gameId = $route.params.game; @@ -99,14 +104,22 @@ const filteredSongs = computed(() => {