Skip to content

Commit

Permalink
Fix calculating PP failing if map is not found
Browse files Browse the repository at this point in the history
  • Loading branch information
Yentis committed Nov 24, 2021
1 parent 06954a1 commit cec1cfc
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 36 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "osu-local-scores",
"version": "1.0.0",
"version": "1.0.1",
"description": "Process local replays and present them in a filterable way",
"productName": "osu! Score Overview",
"author": "Yentis#5218",
Expand Down
15 changes: 11 additions & 4 deletions src-electron/electron-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { app, BrowserWindow, dialog, ipcMain, nativeTheme, OpenDialogReturnValue
import path from 'path'
import os from 'os'
import fs, { FSWatcher } from 'fs'
import { FileBufferResult } from 'src/interfaces/ElectronWindow'

// needed in case process is undefined under Linux
const platform = process.platform || os.platform()
Expand Down Expand Up @@ -104,15 +105,21 @@ async function getBackgroundName (path: string): Promise<string | undefined> {
return backgroundImage?.trim()
}

ipcMain.handle('get-file-buffers', async (_, pathMap: Map<string, string>): Promise<Map<string, ArrayBuffer>> => {
ipcMain.handle('get-file-buffers', async (_, pathMap: Map<string, string>): Promise<FileBufferResult> => {
await app.whenReady()
const bufferMap = new Map<string, ArrayBuffer>()
const promises: Promise<void>[] = []
const errors: Error[] = []

pathMap.forEach((path, hash) => {
const promise = new Promise<ArrayBuffer>((resolve, reject) => {
const promise = new Promise<ArrayBuffer>((resolve) => {
fs.readFile(path, (err, data) => {
if (err) return reject(err)
if (err) {
if (err instanceof Error) errors.push(err)
else errors.push(Error(err as string))

return resolve(new ArrayBuffer(0))
}
resolve(data.buffer)
})
})
Expand All @@ -123,7 +130,7 @@ ipcMain.handle('get-file-buffers', async (_, pathMap: Map<string, string>): Prom
})

await Promise.all(promises)
return bufferMap
return { buffers: bufferMap, errors }
})

let fsWait = false
Expand Down
24 changes: 13 additions & 11 deletions src-wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ mod parsing;
mod replay;

#[wasm_bindgen(js_name="getBeatmaps")]
pub fn get_beatmaps(osu_buffer: &[u8], scores_buffer: &[u8]) -> JsValue {
let listing = Listing::from_bytes(osu_buffer).unwrap_throw();
pub fn get_beatmaps(osu_buffer: &[u8], scores_buffer: &[u8]) -> Result<JsValue, JsValue> {
let listing = Listing::from_bytes(osu_buffer).map_err(|e| JsValue::from(e.to_string()))?;
let mut beatmap_map: HashMap<String, osu_db::listing::Beatmap> = HashMap::with_capacity(listing.beatmaps.len());

for beatmap in listing.beatmaps {
Expand All @@ -19,7 +19,7 @@ pub fn get_beatmaps(osu_buffer: &[u8], scores_buffer: &[u8]) -> JsValue {
}
}

let score_list = ScoreList::from_bytes(scores_buffer).unwrap_throw();
let score_list = ScoreList::from_bytes(scores_buffer).map_err(|e| JsValue::from(e.to_string()))?;
let mut results: HashMap<String, ResultEntry> = HashMap::with_capacity(score_list.beatmaps.len());

for beatmap_scores_entry in score_list.beatmaps {
Expand All @@ -43,21 +43,23 @@ pub fn get_beatmaps(osu_buffer: &[u8], scores_buffer: &[u8]) -> JsValue {
results.insert(hash, result_entry);
}

JsValue::from_serde(&results).unwrap_throw()
JsValue::from_serde(&results).map_err(|e| JsValue::from(e.to_string()))
}

#[wasm_bindgen(js_name="calculatePp")]
pub fn calculate_pp(gamemode: u8, scores: &JsValue, map_buffer: &[u8]) -> Vec<JsValue> {
let beatmap = Beatmap::parse(map_buffer).unwrap_throw();
let parsed_scores: Vec<Score> = JsValue::into_serde(scores).unwrap_throw();
pub fn calculate_pp(gamemode: u8, scores: &JsValue, map_buffer: &[u8]) -> Result<Vec<JsValue>, JsValue> {
let beatmap = Beatmap::parse(map_buffer).map_err(|e| JsValue::from(e.to_string()))?;
let parsed_scores: Vec<Score> = JsValue::into_serde(scores).map_err(|e| JsValue::from(e.to_string()))?;
let mut mod_map: HashMap<u32, PerformanceAttributes> = HashMap::new();

parsed_scores
Ok(parsed_scores
.into_iter()
.map(|score| {
// TODO CONVERTS
if score.gamemode != gamemode {
return JsValue::from_serde(&PpOutput::default()).unwrap_throw();
return JsValue::from_serde(&PpOutput::default())
.map_err(|e| JsValue::from(e.to_string()))
.unwrap_throw();
}

let max_attributes = match mod_map.get(&score.mods) {
Expand Down Expand Up @@ -91,6 +93,6 @@ pub fn calculate_pp(gamemode: u8, scores: &JsValue, map_buffer: &[u8]) -> Vec<Js
max_combo
};

JsValue::from_serde(&result).unwrap_throw()
}).collect()
JsValue::from_serde(&result).map_err(|e| JsValue::from(e.to_string())).unwrap_throw()
}).collect())
}
7 changes: 6 additions & 1 deletion src/interfaces/ElectronWindow.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { OpenDialogReturnValue } from 'electron'

export interface FileBufferResult {
buffers: Map<string, ArrayBuffer>,
errors: Error[]
}

export interface OsuLocalScores {
getFileBuffers: (pathMap: Map<string, string>) => Promise<Map<string, ArrayBuffer>>
getFileBuffers: (pathMap: Map<string, string>) => Promise<FileBufferResult>
openURL: (url: string) => Promise<void>
openDialog: (startPath?: string) => Promise<OpenDialogReturnValue>
watchFile: (path: string, onChanged: () => void) => Promise<void>
Expand Down
4 changes: 2 additions & 2 deletions src/services/PlatformService.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { OpenDialogReturnValue } from 'electron'
import { Notify } from 'quasar'
import ElectronWindow from 'src/interfaces/ElectronWindow'
import ElectronWindow, { FileBufferResult } from 'src/interfaces/ElectronWindow'

class PlatformService {
private electronWindow = (window as unknown) as ElectronWindow
Expand All @@ -18,7 +18,7 @@ class PlatformService {
return this.electronWindow.osuLocalScores.watchFile(path, onChanged)
}

getFileBuffers (pathMap: Map<string, string>): Promise<Map<string, ArrayBuffer>> {
getFileBuffers (pathMap: Map<string, string>): Promise<FileBufferResult> {
return this.electronWindow.osuLocalScores.getFileBuffers(pathMap)
}

Expand Down
15 changes: 10 additions & 5 deletions src/services/WorkerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ class WorkerService {
switch (data.func) {
case WorkerFunc.GET_FILE_BUFFERS: {
const pathMap = args as Map<string, string>
this.platformService.getFileBuffers(pathMap).then((bufferMap) => {
this.worker.postMessage({ id, func, args: bufferMap }, Array.from(bufferMap.values()))
this.platformService.getFileBuffers(pathMap).then((bufferResult) => {
this.worker.postMessage({ id, func, args: bufferResult }, Array.from(bufferResult.buffers.values()))
}).catch((error: unknown) => {
this.worker.postMessage({ id, func, args: error })
})
Expand Down Expand Up @@ -71,11 +71,16 @@ class WorkerService {
const pathMap = new Map<string, string>()
pathMap.set('osu', `${osuPath}/osu!.db`)
pathMap.set('scores', `${osuPath}/scores.db`)
const bufferMap = await this.platformService.getFileBuffers(pathMap)
const { buffers, errors } = await this.platformService.getFileBuffers(pathMap)

if (errors.length > 0) {
console.error(errors)
throw errors[0]
}

return {
osuBuffer: bufferMap.get('osu') as ArrayBuffer,
scoresBuffer: bufferMap.get('scores') as ArrayBuffer,
osuBuffer: buffers.get('osu') as ArrayBuffer,
scoresBuffer: buffers.get('scores') as ArrayBuffer,
osuPath
}
}
Expand Down
32 changes: 20 additions & 12 deletions src/worker/Worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { getBeatmaps, calculatePp, PpOutput } from 'app/src-wasm/pkg'
import DatabaseResponse, { MANIA, MODES } from 'src/interfaces/DatabaseResponse'
import { InitData, WorkerData, WorkerEvent, WorkerFunc } from 'src/interfaces/Worker'
import Filter from 'src/interfaces/Filter'
import { FileBufferResult } from 'src/interfaces/ElectronWindow'

type WorkerListener = (workerData: WorkerData) => void
const workerListeners = new Map<string, WorkerListener>()
Expand Down Expand Up @@ -256,7 +257,7 @@ function filterBeatmaps (filter: Filter): DatabaseResponse[] {
return matchingRows
}

function getFileBuffers (pathMap: Map<string, string>): Promise<Map<string, ArrayBuffer>> {
function getFileBuffers (pathMap: Map<string, string>): Promise<FileBufferResult> {
return new Promise((resolve, reject) => {
const id = Math.random().toString()

Expand All @@ -266,7 +267,7 @@ function getFileBuffers (pathMap: Map<string, string>): Promise<Map<string, Arra
return
}

const result = workerData.args as Map<string, ArrayBuffer>
const result = workerData.args as FileBufferResult
resolve(result)
})

Expand Down Expand Up @@ -311,25 +312,32 @@ async function calculatePpValues (osuPath: string, beatmaps: DatabaseResponse[])
pathMap.set(beatmap.beatmap.hash, path)
}

const bufferMap = await getFileBuffers(pathMap)
batchCalculatePp(bufferMap)
const { buffers, errors } = await getFileBuffers(pathMap)
if (errors) console.error(errors)

batchCalculatePp(buffers)
}

function batchCalculatePp (bufferMap: Map<string, ArrayBuffer>) {
bufferMap.forEach((buffer, hash) => {
if (buffer.byteLength === 0) return
const beatmap = beatmaps?.[hash]
if (!beatmap) return
const gamemode = beatmap.beatmap.gamemode

// TODO CONVERTS
calculatePp(gamemode, beatmap.scores, new Uint8Array(buffer)).forEach((ppOutput: PpOutput, index) => {
const score = beatmap.scores[index]
if (!score) return

score.pp = ppOutput.pp === null ? undefined : ppOutput.pp
score.maxPp = ppOutput.maxPp === null ? undefined : ppOutput.maxPp
score.maxCombo = ppOutput.maxCombo === null ? undefined : ppOutput.maxCombo
})
try {
calculatePp(gamemode, beatmap.scores, new Uint8Array(buffer)).forEach((ppOutput: PpOutput, index) => {
const score = beatmap.scores[index]
if (!score) return

score.pp = ppOutput.pp === null ? undefined : ppOutput.pp
score.maxPp = ppOutput.maxPp === null ? undefined : ppOutput.maxPp
score.maxCombo = ppOutput.maxCombo === null ? undefined : ppOutput.maxCombo
})
} catch (error) {
console.error(error)
}
})

if (!beatmaps) return
Expand Down

0 comments on commit cec1cfc

Please sign in to comment.