osu-stable-db 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -21
- package/dist/index.d.mts +17 -1
- package/dist/index.mjs +2 -2
- package/dist/node.d.mts +168 -1
- package/dist/node.mjs +30 -1
- package/dist/{scores-C35i3lk0.mjs → scores-CW2CUXZ-.mjs} +35 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -69,22 +69,46 @@ const osuFolder = new OsuFolder('C:/osu!')
|
|
|
69
69
|
const osuDatabase = await osuFolder.readOsuDatabase()
|
|
70
70
|
const scoresDatabase = await osuFolder.readScoresDatabase()
|
|
71
71
|
|
|
72
|
-
const
|
|
73
|
-
const newestScore = scoresDatabase.beatmaps.at(-1)?.scores.at(-1)
|
|
72
|
+
const query = osuFolder.createBeatmapScoreQuery(osuDatabase, scoresDatabase)
|
|
74
73
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
console.log(
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (newestScore !== undefined) {
|
|
81
|
-
const osrFilePath = osuFolder.getOsrFilePath(newestScore)
|
|
82
|
-
console.log(osrFilePath)
|
|
74
|
+
for (const { beatmap, score } of query.iterateBeatmapScores()) {
|
|
75
|
+
console.log(beatmap.getOsuFilePath())
|
|
76
|
+
console.log(score.getOsrFilePath())
|
|
83
77
|
}
|
|
84
78
|
```
|
|
85
79
|
|
|
86
80
|
If you only need path-based file IO, the same subpath also exports helpers such as readOsuDatabaseFile, writeCollectionDatabaseFile, and writeScoresDatabaseFile.
|
|
87
81
|
|
|
82
|
+
## Query Helpers
|
|
83
|
+
|
|
84
|
+
Use createBeatmapScoreQuery when you want to join osu!.db beatmaps with scores.db entries by beatmap MD5 hash.
|
|
85
|
+
|
|
86
|
+
It accepts either full database objects or the underlying beatmap and score-group arrays, and returns two generators:
|
|
87
|
+
|
|
88
|
+
- iterateBeatmapScoreGroups yields one beatmap with its matching ScoreEntry array
|
|
89
|
+
- iterateBeatmapScores yields one beatmap with one flattened ScoreEntry at a time
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
import {
|
|
93
|
+
createBeatmapScoreQuery,
|
|
94
|
+
readOsuDatabase,
|
|
95
|
+
readScoresDatabase,
|
|
96
|
+
} from 'osu-stable-db'
|
|
97
|
+
|
|
98
|
+
const osuDatabase = readOsuDatabase(osuBytes)
|
|
99
|
+
const scoresDatabase = readScoresDatabase(scoresBytes)
|
|
100
|
+
|
|
101
|
+
const query = createBeatmapScoreQuery(osuDatabase, scoresDatabase)
|
|
102
|
+
|
|
103
|
+
for (const { beatmap, scores } of query.iterateBeatmapScoreGroups()) {
|
|
104
|
+
console.log(beatmap.beatmapId, scores.length)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
for (const { beatmap, score } of query.iterateBeatmapScores()) {
|
|
108
|
+
console.log(beatmap.difficultyName, score.playerName, score.totalScore)
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
88
112
|
## Types And Time Values
|
|
89
113
|
|
|
90
114
|
- Date-like 64-bit values are exposed as DateTimeTicks, backed by bigint
|
|
@@ -100,7 +124,7 @@ This project is 100% AI-generated.
|
|
|
100
124
|
|
|
101
125
|
Committed minimal fixtures live in [tests/files](tests/files).
|
|
102
126
|
|
|
103
|
-
To run local node tests
|
|
127
|
+
To run local node tests against your real osu! installation, set this in [.env](.env):
|
|
104
128
|
|
|
105
129
|
```dotenv
|
|
106
130
|
OSU_STABLE_DIR=C:/osu!
|
|
@@ -108,16 +132,6 @@ OSU_STABLE_DIR=C:/osu!
|
|
|
108
132
|
|
|
109
133
|
When OSU_STABLE_DIR is set, local node tests read your real database files and verify byte-for-byte round-trip for osu!.db, collection.db, and scores.db.
|
|
110
134
|
|
|
111
|
-
You can also generate a local inspection report for a specific beatmap identifier with:
|
|
112
|
-
|
|
113
|
-
```bash
|
|
114
|
-
pnpm run local:inspect -- 5288868
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
The generated report is written to:
|
|
118
|
-
|
|
119
|
-
- [tests/files/local/reports](tests/files/local/reports)
|
|
120
|
-
|
|
121
135
|
## Development
|
|
122
136
|
|
|
123
137
|
```bash
|
package/dist/index.d.mts
CHANGED
|
@@ -8,8 +8,24 @@ declare function writeCollectionDatabase(database: CollectionDatabase): Uint8Arr
|
|
|
8
8
|
declare function readOsuDatabase(input: ArrayBuffer | Uint8Array): OsuDatabase;
|
|
9
9
|
declare function writeOsuDatabase(database: OsuDatabase): Uint8Array;
|
|
10
10
|
//#endregion
|
|
11
|
+
//#region src/db/query.d.ts
|
|
12
|
+
interface BeatmapScoresGroupMatch {
|
|
13
|
+
beatmap: BeatmapEntry;
|
|
14
|
+
scores: ScoreEntry[];
|
|
15
|
+
}
|
|
16
|
+
interface BeatmapScoreMatch {
|
|
17
|
+
beatmap: BeatmapEntry;
|
|
18
|
+
score: ScoreEntry;
|
|
19
|
+
}
|
|
20
|
+
type BeatmapQuerySource = OsuDatabase | BeatmapEntry[];
|
|
21
|
+
type ScoreQuerySource = ScoresDatabase | ScoresBeatmapEntry[];
|
|
22
|
+
declare function createBeatmapScoreQuery(beatmapsSource: BeatmapQuerySource, scoresSource: ScoreQuerySource): {
|
|
23
|
+
iterateBeatmapScoreGroups: () => Generator<BeatmapScoresGroupMatch>;
|
|
24
|
+
iterateBeatmapScores: () => Generator<BeatmapScoreMatch>;
|
|
25
|
+
};
|
|
26
|
+
//#endregion
|
|
11
27
|
//#region src/db/scores.d.ts
|
|
12
28
|
declare function readScoresDatabase(input: ArrayBuffer | Uint8Array): ScoresDatabase;
|
|
13
29
|
declare function writeScoresDatabase(database: ScoresDatabase): Uint8Array;
|
|
14
30
|
//#endregion
|
|
15
|
-
export { BeatmapEntry, CollectionDatabase, CollectionEntry, DateTimeTicks, GameplayMode, GameplayModes, Grade, Grades, IntFloatPair, MINIMUM_SUPPORTED_VERSION, Mod, ModFlags, Mods, OsuDatabase, RankedStatus, RankedStatuses, ScoreAdditionalModInfo, ScoreEntry, ScoresBeatmapEntry, ScoresDatabase, TimingPoint, UserPermission, UserPermissionFlags, UserPermissions, readCollectionDatabase, readOsuDatabase, readScoresDatabase, writeCollectionDatabase, writeOsuDatabase, writeScoresDatabase };
|
|
31
|
+
export { BeatmapEntry, BeatmapQuerySource, BeatmapScoreMatch, BeatmapScoresGroupMatch, CollectionDatabase, CollectionEntry, DateTimeTicks, GameplayMode, GameplayModes, Grade, Grades, IntFloatPair, MINIMUM_SUPPORTED_VERSION, Mod, ModFlags, Mods, OsuDatabase, RankedStatus, RankedStatuses, ScoreAdditionalModInfo, ScoreEntry, ScoreQuerySource, ScoresBeatmapEntry, ScoresDatabase, TimingPoint, UserPermission, UserPermissionFlags, UserPermissions, createBeatmapScoreQuery, readCollectionDatabase, readOsuDatabase, readScoresDatabase, writeCollectionDatabase, writeOsuDatabase, writeScoresDatabase };
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { GameplayModes, Grades, MINIMUM_SUPPORTED_VERSION, Mods, RankedStatuses, UserPermissions, readCollectionDatabase, readOsuDatabase, readScoresDatabase, writeCollectionDatabase, writeOsuDatabase, writeScoresDatabase };
|
|
1
|
+
import { a as readOsuDatabase, c as writeCollectionDatabase, d as MINIMUM_SUPPORTED_VERSION, f as Mods, i as createBeatmapScoreQuery, l as GameplayModes, m as UserPermissions, n as writeScoresDatabase, o as writeOsuDatabase, p as RankedStatuses, s as readCollectionDatabase, t as readScoresDatabase, u as Grades } from "./scores-CW2CUXZ-.mjs";
|
|
2
|
+
export { GameplayModes, Grades, MINIMUM_SUPPORTED_VERSION, Mods, RankedStatuses, UserPermissions, createBeatmapScoreQuery, readCollectionDatabase, readOsuDatabase, readScoresDatabase, writeCollectionDatabase, writeOsuDatabase, writeScoresDatabase };
|
package/dist/node.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { b as ScoresDatabase, m as OsuDatabase, n as CollectionDatabase, t as BeatmapEntry, v as ScoreEntry } from "./types-DiZMN3fQ.mjs";
|
|
1
|
+
import { _ as ScoreAdditionalModInfo, a as GameplayMode, b as ScoresDatabase, f as ModFlags, h as RankedStatus, i as DateTimeTicks, l as IntFloatPair, m as OsuDatabase, n as CollectionDatabase, s as Grade, t as BeatmapEntry, v as ScoreEntry, x as TimingPoint } from "./types-DiZMN3fQ.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/node.d.ts
|
|
4
4
|
type DatabaseFilePath = string | URL;
|
|
@@ -23,6 +23,173 @@ declare class OsuFolder {
|
|
|
23
23
|
writeCollectionDatabase(database: CollectionDatabase): Promise<void>;
|
|
24
24
|
readScoresDatabase(): Promise<ScoresDatabase>;
|
|
25
25
|
writeScoresDatabase(database: ScoresDatabase): Promise<void>;
|
|
26
|
+
createBeatmapScoreQuery(beatmapsSource: OsuDatabase | BeatmapEntry[], scoresSource: ScoresDatabase | Array<{
|
|
27
|
+
beatmapMd5Hash: string | null;
|
|
28
|
+
scores: ScoreEntry[];
|
|
29
|
+
}>): {
|
|
30
|
+
iterateBeatmapScoreGroups: () => Generator<{
|
|
31
|
+
beatmap: {
|
|
32
|
+
artist: string | null;
|
|
33
|
+
artistUnicode: string | null;
|
|
34
|
+
title: string | null;
|
|
35
|
+
titleUnicode: string | null;
|
|
36
|
+
creator: string | null;
|
|
37
|
+
difficultyName: string | null;
|
|
38
|
+
audioFileName: string | null;
|
|
39
|
+
md5Hash: string | null;
|
|
40
|
+
osuFileName: string | null;
|
|
41
|
+
rankedStatus: RankedStatus;
|
|
42
|
+
hitCircleCount: number;
|
|
43
|
+
sliderCount: number;
|
|
44
|
+
spinnerCount: number;
|
|
45
|
+
lastModificationTime: DateTimeTicks;
|
|
46
|
+
approachRate: number;
|
|
47
|
+
circleSize: number;
|
|
48
|
+
hpDrain: number;
|
|
49
|
+
overallDifficulty: number;
|
|
50
|
+
sliderVelocity: number;
|
|
51
|
+
standardStarRatings: IntFloatPair[];
|
|
52
|
+
taikoStarRatings: IntFloatPair[];
|
|
53
|
+
catchStarRatings: IntFloatPair[];
|
|
54
|
+
maniaStarRatings: IntFloatPair[];
|
|
55
|
+
drainTimeSeconds: number;
|
|
56
|
+
totalTimeMs: number;
|
|
57
|
+
previewOffsetMs: number;
|
|
58
|
+
timingPoints: TimingPoint[];
|
|
59
|
+
difficultyId: number;
|
|
60
|
+
beatmapId: number;
|
|
61
|
+
threadId: number;
|
|
62
|
+
standardGrade: Grade;
|
|
63
|
+
taikoGrade: Grade;
|
|
64
|
+
catchGrade: Grade;
|
|
65
|
+
maniaGrade: Grade;
|
|
66
|
+
localOffset: number;
|
|
67
|
+
stackLeniency: number;
|
|
68
|
+
gameplayMode: GameplayMode;
|
|
69
|
+
source: string | null;
|
|
70
|
+
tags: string | null;
|
|
71
|
+
onlineOffset: number;
|
|
72
|
+
titleFont: string | null;
|
|
73
|
+
isUnplayed: boolean;
|
|
74
|
+
lastPlayedAt: DateTimeTicks;
|
|
75
|
+
isOsz2: boolean;
|
|
76
|
+
beatmapFolderName: string | null;
|
|
77
|
+
lastCheckedAgainstRepositoryAt: DateTimeTicks;
|
|
78
|
+
ignoreBeatmapSound: boolean;
|
|
79
|
+
ignoreBeatmapSkin: boolean;
|
|
80
|
+
disableStoryboard: boolean;
|
|
81
|
+
disableVideo: boolean;
|
|
82
|
+
visualOverride: boolean;
|
|
83
|
+
lastModificationTimeUnknown: number;
|
|
84
|
+
maniaScrollSpeed: number;
|
|
85
|
+
getOsuFilePath: () => string;
|
|
86
|
+
};
|
|
87
|
+
scores: {
|
|
88
|
+
gameplayMode: GameplayMode;
|
|
89
|
+
version: number;
|
|
90
|
+
beatmapMd5Hash: string | null;
|
|
91
|
+
playerName: string | null;
|
|
92
|
+
replayMd5Hash: string | null;
|
|
93
|
+
count300: number;
|
|
94
|
+
count100: number;
|
|
95
|
+
count50: number;
|
|
96
|
+
countGeki: number;
|
|
97
|
+
countKatu: number;
|
|
98
|
+
countMiss: number;
|
|
99
|
+
totalScore: number;
|
|
100
|
+
maxCombo: number;
|
|
101
|
+
perfectCombo: boolean;
|
|
102
|
+
mods: ModFlags;
|
|
103
|
+
reservedEmptyString: string | null;
|
|
104
|
+
replayTimestamp: DateTimeTicks;
|
|
105
|
+
reservedInt32: number;
|
|
106
|
+
onlineScoreId: bigint;
|
|
107
|
+
additionalModInfo?: ScoreAdditionalModInfo;
|
|
108
|
+
getOsrFilePath: () => string;
|
|
109
|
+
}[];
|
|
110
|
+
}, void, unknown>;
|
|
111
|
+
iterateBeatmapScores: () => Generator<{
|
|
112
|
+
beatmap: {
|
|
113
|
+
artist: string | null;
|
|
114
|
+
artistUnicode: string | null;
|
|
115
|
+
title: string | null;
|
|
116
|
+
titleUnicode: string | null;
|
|
117
|
+
creator: string | null;
|
|
118
|
+
difficultyName: string | null;
|
|
119
|
+
audioFileName: string | null;
|
|
120
|
+
md5Hash: string | null;
|
|
121
|
+
osuFileName: string | null;
|
|
122
|
+
rankedStatus: RankedStatus;
|
|
123
|
+
hitCircleCount: number;
|
|
124
|
+
sliderCount: number;
|
|
125
|
+
spinnerCount: number;
|
|
126
|
+
lastModificationTime: DateTimeTicks;
|
|
127
|
+
approachRate: number;
|
|
128
|
+
circleSize: number;
|
|
129
|
+
hpDrain: number;
|
|
130
|
+
overallDifficulty: number;
|
|
131
|
+
sliderVelocity: number;
|
|
132
|
+
standardStarRatings: IntFloatPair[];
|
|
133
|
+
taikoStarRatings: IntFloatPair[];
|
|
134
|
+
catchStarRatings: IntFloatPair[];
|
|
135
|
+
maniaStarRatings: IntFloatPair[];
|
|
136
|
+
drainTimeSeconds: number;
|
|
137
|
+
totalTimeMs: number;
|
|
138
|
+
previewOffsetMs: number;
|
|
139
|
+
timingPoints: TimingPoint[];
|
|
140
|
+
difficultyId: number;
|
|
141
|
+
beatmapId: number;
|
|
142
|
+
threadId: number;
|
|
143
|
+
standardGrade: Grade;
|
|
144
|
+
taikoGrade: Grade;
|
|
145
|
+
catchGrade: Grade;
|
|
146
|
+
maniaGrade: Grade;
|
|
147
|
+
localOffset: number;
|
|
148
|
+
stackLeniency: number;
|
|
149
|
+
gameplayMode: GameplayMode;
|
|
150
|
+
source: string | null;
|
|
151
|
+
tags: string | null;
|
|
152
|
+
onlineOffset: number;
|
|
153
|
+
titleFont: string | null;
|
|
154
|
+
isUnplayed: boolean;
|
|
155
|
+
lastPlayedAt: DateTimeTicks;
|
|
156
|
+
isOsz2: boolean;
|
|
157
|
+
beatmapFolderName: string | null;
|
|
158
|
+
lastCheckedAgainstRepositoryAt: DateTimeTicks;
|
|
159
|
+
ignoreBeatmapSound: boolean;
|
|
160
|
+
ignoreBeatmapSkin: boolean;
|
|
161
|
+
disableStoryboard: boolean;
|
|
162
|
+
disableVideo: boolean;
|
|
163
|
+
visualOverride: boolean;
|
|
164
|
+
lastModificationTimeUnknown: number;
|
|
165
|
+
maniaScrollSpeed: number;
|
|
166
|
+
getOsuFilePath: () => string;
|
|
167
|
+
};
|
|
168
|
+
score: {
|
|
169
|
+
gameplayMode: GameplayMode;
|
|
170
|
+
version: number;
|
|
171
|
+
beatmapMd5Hash: string | null;
|
|
172
|
+
playerName: string | null;
|
|
173
|
+
replayMd5Hash: string | null;
|
|
174
|
+
count300: number;
|
|
175
|
+
count100: number;
|
|
176
|
+
count50: number;
|
|
177
|
+
countGeki: number;
|
|
178
|
+
countKatu: number;
|
|
179
|
+
countMiss: number;
|
|
180
|
+
totalScore: number;
|
|
181
|
+
maxCombo: number;
|
|
182
|
+
perfectCombo: boolean;
|
|
183
|
+
mods: ModFlags;
|
|
184
|
+
reservedEmptyString: string | null;
|
|
185
|
+
replayTimestamp: DateTimeTicks;
|
|
186
|
+
reservedInt32: number;
|
|
187
|
+
onlineScoreId: bigint;
|
|
188
|
+
additionalModInfo?: ScoreAdditionalModInfo;
|
|
189
|
+
getOsrFilePath: () => string;
|
|
190
|
+
};
|
|
191
|
+
}, void, unknown>;
|
|
192
|
+
};
|
|
26
193
|
getOsuFilePath(beatmap: BeatmapEntry): string;
|
|
27
194
|
getOsrFilePath(score: ScoreEntry): string;
|
|
28
195
|
}
|
package/dist/node.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as readOsuDatabase, c as writeCollectionDatabase, i as createBeatmapScoreQuery, n as writeScoresDatabase, o as writeOsuDatabase, r as dateTimeTicksToWindowsFileTimeTicks, s as readCollectionDatabase, t as readScoresDatabase } from "./scores-CW2CUXZ-.mjs";
|
|
2
2
|
import { readFile, writeFile } from "node:fs/promises";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
//#region src/node.ts
|
|
@@ -61,6 +61,35 @@ var OsuFolder = class {
|
|
|
61
61
|
async writeScoresDatabase(database) {
|
|
62
62
|
await writeScoresDatabaseFile(this.getScoresDatabasePath(), database);
|
|
63
63
|
}
|
|
64
|
+
createBeatmapScoreQuery(beatmapsSource, scoresSource) {
|
|
65
|
+
const query = createBeatmapScoreQuery(beatmapsSource, scoresSource);
|
|
66
|
+
const wrapBeatmap = (beatmap) => ({
|
|
67
|
+
...beatmap,
|
|
68
|
+
getOsuFilePath: () => this.getOsuFilePath(beatmap)
|
|
69
|
+
});
|
|
70
|
+
const wrapScore = (score) => ({
|
|
71
|
+
...score,
|
|
72
|
+
getOsrFilePath: () => this.getOsrFilePath(score)
|
|
73
|
+
});
|
|
74
|
+
const wrapBeatmapScoresGroupMatch = ({ beatmap, scores }) => ({
|
|
75
|
+
beatmap: wrapBeatmap(beatmap),
|
|
76
|
+
scores: scores.map(wrapScore)
|
|
77
|
+
});
|
|
78
|
+
const wrapBeatmapScoreMatch = ({ beatmap, score }) => ({
|
|
79
|
+
beatmap: wrapBeatmap(beatmap),
|
|
80
|
+
score: wrapScore(score)
|
|
81
|
+
});
|
|
82
|
+
function* iterateBeatmapScoreGroups() {
|
|
83
|
+
for (const match of query.iterateBeatmapScoreGroups()) yield wrapBeatmapScoresGroupMatch(match);
|
|
84
|
+
}
|
|
85
|
+
function* iterateBeatmapScores() {
|
|
86
|
+
for (const match of query.iterateBeatmapScores()) yield wrapBeatmapScoreMatch(match);
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
iterateBeatmapScoreGroups,
|
|
90
|
+
iterateBeatmapScores
|
|
91
|
+
};
|
|
92
|
+
}
|
|
64
93
|
getOsuFilePath(beatmap) {
|
|
65
94
|
if (beatmap.beatmapFolderName === null || beatmap.osuFileName === null) throw new Error("Beatmap entry is missing beatmapFolderName or osuFileName");
|
|
66
95
|
return join(this.folderPath, "Songs", beatmap.beatmapFolderName, beatmap.osuFileName);
|
|
@@ -353,6 +353,40 @@ function writeOsuDatabase(database) {
|
|
|
353
353
|
return writer.toUint8Array();
|
|
354
354
|
}
|
|
355
355
|
//#endregion
|
|
356
|
+
//#region src/db/query.ts
|
|
357
|
+
function getBeatmapEntries(source) {
|
|
358
|
+
return Array.isArray(source) ? source : source.beatmaps;
|
|
359
|
+
}
|
|
360
|
+
function getScoreEntries(source) {
|
|
361
|
+
return Array.isArray(source) ? source : source.beatmaps;
|
|
362
|
+
}
|
|
363
|
+
function createBeatmapScoreQuery(beatmapsSource, scoresSource) {
|
|
364
|
+
const beatmaps = getBeatmapEntries(beatmapsSource);
|
|
365
|
+
const scoreGroups = getScoreEntries(scoresSource);
|
|
366
|
+
const beatmapByMd5Hash = /* @__PURE__ */ new Map();
|
|
367
|
+
for (const beatmap of beatmaps) if (beatmap.md5Hash !== null) beatmapByMd5Hash.set(beatmap.md5Hash, beatmap);
|
|
368
|
+
function* iterateBeatmapScoreGroups() {
|
|
369
|
+
for (const scoreGroup of scoreGroups) {
|
|
370
|
+
if (scoreGroup.beatmapMd5Hash === null) continue;
|
|
371
|
+
const beatmap = beatmapByMd5Hash.get(scoreGroup.beatmapMd5Hash);
|
|
372
|
+
if (beatmap !== void 0) yield {
|
|
373
|
+
beatmap,
|
|
374
|
+
scores: scoreGroup.scores
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
function* iterateBeatmapScores() {
|
|
379
|
+
for (const { beatmap, scores } of iterateBeatmapScoreGroups()) for (const score of scores) yield {
|
|
380
|
+
beatmap,
|
|
381
|
+
score
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
return {
|
|
385
|
+
iterateBeatmapScoreGroups,
|
|
386
|
+
iterateBeatmapScores
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
//#endregion
|
|
356
390
|
//#region src/core/utils.ts
|
|
357
391
|
const WINDOWS_FILE_TIME_EPOCH_DATE_TIME_TICKS = 504911232000000000n;
|
|
358
392
|
Object.values(Mods).filter((value) => value !== Mods.None);
|
|
@@ -478,4 +512,4 @@ function writeScoresDatabase(database) {
|
|
|
478
512
|
return writer.toUint8Array();
|
|
479
513
|
}
|
|
480
514
|
//#endregion
|
|
481
|
-
export {
|
|
515
|
+
export { readOsuDatabase as a, writeCollectionDatabase as c, MINIMUM_SUPPORTED_VERSION as d, Mods as f, createBeatmapScoreQuery as i, GameplayModes as l, UserPermissions as m, writeScoresDatabase as n, writeOsuDatabase as o, RankedStatuses as p, dateTimeTicksToWindowsFileTimeTicks as r, readCollectionDatabase as s, readScoresDatabase as t, Grades as u };
|