feat: ratings leaderboard disk format

This commit is contained in:
TrèsAbhi committed 2024-03-18 18:06:45 -05:00
1 parent c8edd16eb3
commit 1c03701e17
5 files changed
+210 -4

No files matched your search

+1
View File
@@ -16,6 +16,7 @@
"betakrieg",
"BINORMAL",
"Binormals",
"BKRL",
"bkwd",
"blitzstars",
"Camo",
+50
View File
@@ -0,0 +1,50 @@
# Blitzkrieg Ratings Leaderboard
A straightforward way of storing the entire World of Tanks Blitz ratings leaderboard to disk.
```cpp
primary BlitzkriegRatingsLeaderboard {
utf8"BKRL" magic;
Header header;
primary Body<header> body;
}
Header {
uint16 version; // always 1
Format format;
uint32 count;
}
Format enum<uint8> {
Minimal,
Comprehensive1,
}
Body<Header header> match<header.format> {
Minimal {
primary {
uint32 id;
uint16 score;
}[header.count] entries;
};
Comprehensive1 {
primary {
uint32 id;
uint16 score;
uint32 battles;
uint32 wins;
uint32 survived;
uint32 damageDealt;
uint32 damageReceived;
uint32 shots;
uint32 hits;
uint32 kills;
}[header.count] entries;
};
}
```
+1 -3
View File
@@ -1,7 +1,5 @@
# Cedilla Object Notation
This documentation uses an experimental binary notation syntax called "Buffer Up".
1. JSON compressed as CDON, written directly to disk (a direct 50% reduction).
2. CDON further compressed with LZ4 (a clean 90% reduction).
3. The raw JSON file as fetched from a random data source.
@@ -19,7 +17,7 @@ primary CedillaObjectNotation {
}
Header {
uint16 version;
uint16 version; // always 1
FSFormat fsFormat;
StringTable<fsFormat> stringTable;
}
+157
View File
@@ -0,0 +1,157 @@
import { times } from 'lodash';
import { ReadStream, WriteStream } from './buffer';
enum Format {
Minimal,
Comprehensive1,
}
interface BkrlMinimalEntry {
id: number;
score: number;
}
interface BkrlComprehensive1Entry {
id: number;
score: number;
battles: number;
wins: number;
survived: number;
damageDealt: number;
damageReceived: number;
shots: number;
hits: number;
kills: number;
}
type DiscriminatedEntries =
| {
format: Format.Minimal;
entries: BkrlMinimalEntry[];
}
| {
format: Format.Comprehensive1;
entries: BkrlComprehensive1Entry[];
};
export class BkrlReadStream extends ReadStream {
bkrl() {
this.magic();
const header = this.header();
return this.body(header);
}
body(header: ReturnType<typeof this.header>): DiscriminatedEntries {
switch (header.format) {
case Format.Minimal: {
return {
format: Format.Minimal,
entries: times(
header.count,
() =>
({
id: this.uint32(),
score: this.uint16(),
}) satisfies BkrlMinimalEntry,
),
};
}
case Format.Comprehensive1: {
return {
format: Format.Comprehensive1,
entries: times(
header.count,
() =>
({
id: this.uint32(),
score: this.uint16(),
battles: this.uint32(),
wins: this.uint32(),
survived: this.uint32(),
damageDealt: this.uint32(),
damageReceived: this.uint32(),
shots: this.uint32(),
hits: this.uint32(),
kills: this.uint32(),
}) satisfies BkrlComprehensive1Entry,
),
};
}
}
}
header() {
return {
version: this.uint16(),
format: this.uint8() as Format,
count: this.uint32(),
};
}
magic() {
const magic = this.utf8(4);
if (magic !== 'BKRL') {
throw new Error(`Invalid BKRL magic number: "${magic}"`);
}
}
}
export class BkrlWriteStream extends WriteStream {
bkrl(discriminatedEntries: DiscriminatedEntries) {
this.magic();
this.header(discriminatedEntries);
this.body(discriminatedEntries);
}
body(discriminatedEntries: DiscriminatedEntries) {
switch (discriminatedEntries.format) {
case Format.Minimal: {
discriminatedEntries.entries.forEach((entry) => {
this.uint32(entry.id);
this.uint16(entry.score);
});
break;
}
case Format.Comprehensive1: {
discriminatedEntries.entries.forEach((entry) => {
this.uint32(entry.id);
this.uint16(entry.score);
this.uint32(entry.battles);
this.uint32(entry.wins);
this.uint32(entry.survived);
this.uint32(entry.damageDealt);
this.uint32(entry.damageReceived);
this.uint32(entry.shots);
this.uint32(entry.hits);
this.uint32(entry.kills);
});
break;
}
}
}
header(discriminatedEntries: DiscriminatedEntries) {
this.uint16(1);
this.uint8(discriminatedEntries.format);
this.uint32(discriminatedEntries.entries.length);
}
magic() {
this.utf8('BKRL');
}
}
+1 -1
View File
@@ -48,7 +48,7 @@ export class CdonReadStream extends ReadStream {
const magic = this.utf8(4);
if (magic !== 'CDON') {
throw new Error(`Invalid Cdon magic number: "${magic}"`);
throw new Error(`Invalid CDON magic number: "${magic}"`);
}
}