forked from phenom/healer-man
Release Healer Man 0.1.40
This commit is contained in:
1 parent
ed0d2fea3d
commit
197a64117c
215 files changed
+5131
-181
No files matched your search
@@ -6,6 +6,8 @@ import test from "node:test";
|
||||
import { openGameDatabase } from "./database.mjs";
|
||||
import { createGameServer } from "./server.mjs";
|
||||
import catalog from "../src/game/generated/dungeonLeaderboardCatalog.generated.json" with { type: "json" };
|
||||
import { DatabaseSync } from "node:sqlite";
|
||||
import { createDungeonLeaderboardRepository } from "./dungeon-leaderboards.mjs";
|
||||
|
||||
function run(id, durationMs, fullClear = true, dungeonId = "deadmines", difficultyId) {
|
||||
const dungeon = catalog.dungeons.find((entry) => entry.id === dungeonId);
|
||||
@@ -69,6 +71,15 @@ test("public HTTP leaderboards accept completion records and return results with
|
||||
const leaderboard = await fetch(`${base}/api/dungeon-leaderboards?dungeon=barren-caves&clear=full`);
|
||||
assert.equal(leaderboard.status, 200); assert.equal((await leaderboard.json()).entries[0].durationMs, 15555);
|
||||
assert.deepEqual(await (await fetch(`${base}/api/dungeon-runs/${payload.id}`)).json(), result);
|
||||
const slider = { ...payload, id: "http-slider-clear", bossDifficulty: 10 };
|
||||
const sliderResponse = await fetch(`${base}/api/dungeon-runs`, { method: "POST",
|
||||
headers: { "Content-Type": "application/json" }, body: JSON.stringify(slider) });
|
||||
assert.equal(sliderResponse.status, 201);
|
||||
const sliderBoard = await fetch(`${base}/api/dungeon-leaderboards?dungeon=barren-caves&clear=full&bossDifficulty=10`);
|
||||
assert.equal(sliderBoard.status, 200);
|
||||
assert.deepEqual((await sliderBoard.json()).entries.map((entry) => entry.id), [slider.id]);
|
||||
assert.equal((await (await fetch(`${base}/api/dungeon-leaderboards?dungeon=barren-caves&bossDifficulty=1`)).json()).total, 0);
|
||||
assert.equal((await fetch(`${base}/api/dungeon-leaderboards?dungeon=barren-caves&bossDifficulty=11`)).status, 400);
|
||||
const bad = await fetch(`${base}/api/dungeon-runs`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ ...payload, id: "unfinished-run", killedBossIds: [] }) });
|
||||
assert.equal(bad.status, 400);
|
||||
const unauthorized = await fetch(`${base}/api/dungeon-runs`, { method: "POST", headers: { Authorization: "Bearer invalid", "Content-Type": "application/json" }, body: JSON.stringify(payload) });
|
||||
@@ -87,3 +98,43 @@ test("separates normal and heroic times and counts only bosses that exist on eac
|
||||
assert.equal(database.listDungeonLeaderboard({ dungeonId: dungeon.id, difficultyId: difficulty.id, clear: "full" }).total, 1);
|
||||
}
|
||||
}));
|
||||
|
||||
test("isolates ten boss difficulties and legacy scores, preserving retries and ranks after restart", () => withDatabase((database, reopen) => {
|
||||
database.submitDungeonRun(null, run("legacy-fastest-run", 1));
|
||||
for (let difficulty = 1; difficulty <= 10; difficulty += 1) {
|
||||
const payload = { ...run(`slider-level-${difficulty}`, 10000 + difficulty), bossDifficulty: difficulty };
|
||||
const submitted = database.submitDungeonRun(null, payload);
|
||||
assert.deepEqual(submitted.placement, { finalRank: 1, finalTotal: 1, fullRank: 1, fullTotal: 1 });
|
||||
assert.deepEqual(database.submitDungeonRun(null, payload), submitted);
|
||||
assert.throws(() => database.submitDungeonRun(null, { ...payload, bossDifficulty: difficulty === 10 ? 1 : 10 }), { status: 409 });
|
||||
}
|
||||
database = reopen();
|
||||
for (let bossDifficulty = 1; bossDifficulty <= 10; bossDifficulty += 1) {
|
||||
const page = database.listDungeonLeaderboard({ dungeonId: "deadmines", bossDifficulty, clear: "full" });
|
||||
assert.equal(page.total, 1); assert.equal(page.entries[0].bossDifficulty, bossDifficulty);
|
||||
assert.equal(database.getDungeonRun(page.entries[0].id).placement.finalRank, 1);
|
||||
}
|
||||
assert.equal(database.listDungeonLeaderboard({ dungeonId: "deadmines" }).total, 1);
|
||||
for (const bossDifficulty of [0, -1, 11, 1.5, "2", NaN]) {
|
||||
assert.throws(() => database.submitDungeonRun(null, { ...run("invalid-slider-run", 1000), bossDifficulty }), { status: 400 });
|
||||
}
|
||||
}));
|
||||
|
||||
test("migrates the old leaderboard schema and keeps its scores outside Easy", () => {
|
||||
const database = new DatabaseSync(":memory:");
|
||||
try {
|
||||
database.exec(`CREATE TABLE accounts (id TEXT PRIMARY KEY);
|
||||
CREATE TABLE dungeon_runs (id TEXT PRIMARY KEY, dungeon_id TEXT NOT NULL, difficulty_id TEXT NOT NULL,
|
||||
duration_ms INTEGER NOT NULL, full_clear INTEGER NOT NULL, finished_at INTEGER NOT NULL,
|
||||
party_json TEXT NOT NULL, bosses_json TEXT NOT NULL, submitted_by_account_id TEXT, received_at INTEGER NOT NULL)`);
|
||||
const legacy = run("pre-slider-result", 5000);
|
||||
database.prepare("INSERT INTO dungeon_runs VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run(legacy.id,
|
||||
legacy.dungeonId, legacy.difficultyId, legacy.durationMs, 1, legacy.finishedAt,
|
||||
JSON.stringify(legacy.party), JSON.stringify(legacy.killedBossIds), null, Date.now());
|
||||
const repository = createDungeonLeaderboardRepository(database, { ErrorType: Error });
|
||||
assert.equal(repository.listDungeonLeaderboard({ dungeonId: "deadmines" }).total, 1);
|
||||
assert.equal(repository.listDungeonLeaderboard({ dungeonId: "deadmines", bossDifficulty: 1 }).total, 0);
|
||||
createDungeonLeaderboardRepository(database, { ErrorType: Error });
|
||||
assert.equal(repository.getDungeonRun(legacy.id).run.durationMs, 5000);
|
||||
} finally { database.close(); }
|
||||
});
|
||||
Reference in new issue
Block a user