2024-03-03 15:22:03 +00:00
|
|
|
import { BeatmapDecoder } from "osu-parsers";
|
|
|
|
|
import { ScoreDecoder } from "../osu-parsers";
|
|
|
|
|
import { StandardRuleset, StandardBeatmap } from "osu-standard-stable";
|
|
|
|
|
|
|
|
|
|
import { IMod, Score } from "osu-classes";
|
2024-03-10 14:56:49 +00:00
|
|
|
import p5 from "p5";
|
2024-03-03 15:22:03 +00:00
|
|
|
import { create } from "zustand";
|
|
|
|
|
|
|
|
|
|
const ruleset = new StandardRuleset();
|
|
|
|
|
const scoreDecoder = new ScoreDecoder();
|
|
|
|
|
const beatmapDecoder = new BeatmapDecoder();
|
|
|
|
|
|
|
|
|
|
export async function getReplay(buffer: ArrayBuffer) {
|
|
|
|
|
const repl = await scoreDecoder.decodeFromBuffer(buffer);
|
|
|
|
|
repl.info.ruleset = ruleset;
|
|
|
|
|
return repl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function getBeatmap(mapText: string, scoreBase: Score) {
|
|
|
|
|
const map = beatmapDecoder.decodeFromString(mapText);
|
|
|
|
|
|
|
|
|
|
const score = scoreBase.info;
|
|
|
|
|
score.accuracy =
|
|
|
|
|
(score.count300 + score.count100 / 3 + score.count50 / 6) /
|
|
|
|
|
(score.count300 + score.count100 + score.count50 + score.countMiss);
|
|
|
|
|
|
|
|
|
|
return ruleset.applyToBeatmap(map);
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-10 14:56:49 +00:00
|
|
|
export async function loadImageAsync(image: string): Promise<p5.Image> {
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
p.loadImage(
|
|
|
|
|
image,
|
|
|
|
|
(img) => {
|
|
|
|
|
resolve(img);
|
|
|
|
|
},
|
|
|
|
|
(err) => {
|
|
|
|
|
reject(err);
|
|
|
|
|
}
|
|
|
|
|
);
|
2024-03-03 15:22:03 +00:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function clamp(num: number, min: number, max: number) {
|
|
|
|
|
if (num > max) return max;
|
|
|
|
|
if (num < min) return min;
|
|
|
|
|
return num
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const state = create<{
|
|
|
|
|
beatmap: StandardBeatmap | null;
|
|
|
|
|
replay: Score | null;
|
|
|
|
|
metadataEditorDialog: boolean;
|
|
|
|
|
openDialog: boolean;
|
|
|
|
|
saveDialog: boolean;
|
|
|
|
|
dataAnalysisDialog: boolean;
|
|
|
|
|
achivementsDialog: boolean;
|
|
|
|
|
aboutDialog: boolean;
|
|
|
|
|
grda: any;
|
|
|
|
|
tool: "cursor" | "brush" | "advanced" | "smoother";
|
|
|
|
|
mods: IMod[] | null;
|
|
|
|
|
playing: boolean;
|
|
|
|
|
time: number;
|
2024-03-03 16:26:45 +00:00
|
|
|
speed: number;
|
2024-03-03 15:22:03 +00:00
|
|
|
}>(() => ({
|
|
|
|
|
metadataEditorDialog: false,
|
|
|
|
|
openDialog: false,
|
|
|
|
|
saveDialog: false,
|
|
|
|
|
aboutDialog: false,
|
|
|
|
|
achivementsDialog: false,
|
|
|
|
|
dataAnalysisDialog: false,
|
|
|
|
|
beatmap: null,
|
|
|
|
|
replay: null,
|
|
|
|
|
grda: null,
|
|
|
|
|
tool: "cursor",
|
|
|
|
|
mods: null,
|
|
|
|
|
playing: false,
|
|
|
|
|
time: 0,
|
2024-03-03 16:26:45 +00:00
|
|
|
speed: 1
|
2024-03-03 15:22:03 +00:00
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
export let p: p5;
|
|
|
|
|
|
|
|
|
|
export function setEnv(_p: p5) {
|
|
|
|
|
p = _p;
|
|
|
|
|
}
|