Release Healer Man 0.1.21
This commit is contained in:
1 parent
699fc858c9
commit
f6f2375145
210 files changed
+976039
-6247
No files matched your search
@@ -0,0 +1,64 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { createHash } from "node:crypto";
|
||||
import { readFile, readdir } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import test from "node:test";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const projectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
||||
const reportFile = path.join(projectRoot, "scripts/runewaker-pipeline/RUNEWAKER_LOOT_IMPORT_REPORT.json");
|
||||
const catalogFile = path.join(projectRoot, "src/game/generated/runewakerLootCatalog.json");
|
||||
|
||||
async function json(file) {
|
||||
return JSON.parse(await readFile(file, "utf8"));
|
||||
}
|
||||
|
||||
test("RuneWaker loot catalog covers every source-classified boss", async () => {
|
||||
const [catalog, recipeNames] = await Promise.all([
|
||||
json(catalogFile),
|
||||
readdir(path.join(projectRoot, "scripts/runewaker-pipeline/recipes")),
|
||||
]);
|
||||
let expectedBosses = 0;
|
||||
for (const name of recipeNames.filter((candidate) => candidate.endsWith("-population.json"))) {
|
||||
const recipe = await json(path.join(projectRoot, "scripts/runewaker-pipeline/recipes", name));
|
||||
expectedBosses += recipe.templates.filter((template) => template.classification === "boss").length;
|
||||
}
|
||||
assert.equal(catalog.bossCount, expectedBosses);
|
||||
assert.equal(catalog.bosses.length, expectedBosses);
|
||||
assert.equal(new Set(catalog.bosses.map((boss) => boss.bossKey)).size, expectedBosses);
|
||||
});
|
||||
|
||||
test("source probabilities and fail-closed outcomes are internally valid", async () => {
|
||||
const catalog = await json(catalogFile);
|
||||
for (const boss of catalog.bosses) {
|
||||
assert.ok(["portable", "partial", "no-source-drops", "blocked"].includes(boss.status));
|
||||
for (const roll of boss.rolls) {
|
||||
assert.ok(roll.chancePerKill > 0 && roll.chancePerKill <= 1);
|
||||
const total = roll.outcomes.reduce((sum, outcome) => sum + outcome.conditionalChance, 0);
|
||||
assert.ok(total <= 1.000000001, `${boss.bossKey} slot ${roll.sourceSlot} exceeds probability 1`);
|
||||
for (const outcome of roll.outcomes) {
|
||||
assert.ok(outcome.conditionalChance > 0 && outcome.conditionalChance <= 1);
|
||||
if (outcome.runtimeStatus === "blocked") assert.ok(outcome.blockedReason);
|
||||
else assert.ok(outcome.sourceCatalog);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test("the compact report agrees with the full catalog and pins every source hash", async () => {
|
||||
const [catalog, report] = await Promise.all([json(catalogFile), json(reportFile)]);
|
||||
for (const key of [
|
||||
"bossCount",
|
||||
"bossWithSourceRollsCount",
|
||||
"portableBossCount",
|
||||
"partialBossCount",
|
||||
"noSourceDropsBossCount",
|
||||
"blockedBossCount",
|
||||
"executableOutcomeCount",
|
||||
"blockedOutcomeCount",
|
||||
]) assert.equal(report[key], catalog[key]);
|
||||
for (const source of report.generatedFrom.sourceFiles) {
|
||||
const bytes = await readFile(path.resolve(projectRoot, source.file));
|
||||
assert.equal(createHash("sha256").update(bytes).digest("hex"), source.sha256);
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user