Release Healer Man 0.1.12
This commit is contained in:
1 parent
13970d03c8
commit
65e24f644e
201 files changed
+5061
-123
No files matched your search
@@ -0,0 +1,136 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { DUNGEON_CATALOG } from "./dungeonCatalog";
|
||||
import {
|
||||
configWithGmReviewNote,
|
||||
configWithGmReviewStatus,
|
||||
describeGmReviewTarget,
|
||||
drawRandomGmReviewTarget,
|
||||
gmReviewQueue,
|
||||
type GmReviewTarget,
|
||||
} from "./gmContentReview";
|
||||
import {
|
||||
DEFAULT_MANASTORM_ADMIN_CONFIG,
|
||||
resolvedBossAdminCatalog,
|
||||
type GmReadinessStatus,
|
||||
type ManastormAdminConfig,
|
||||
} from "./manastormAdminConfig";
|
||||
|
||||
function configWithBossStatuses(statuses: Readonly<Record<string, GmReadinessStatus>>): ManastormAdminConfig {
|
||||
return {
|
||||
...DEFAULT_MANASTORM_ADMIN_CONFIG,
|
||||
bosses: Object.fromEntries(Object.entries(statuses).map(([key, status]) => [key, { status }])),
|
||||
};
|
||||
}
|
||||
|
||||
describe("random GM content review", () => {
|
||||
it("draws Needs tested dungeons before Not ready and never draws Ready", () => {
|
||||
const available = DUNGEON_CATALOG.filter((dungeon) => dungeon.available);
|
||||
expect(available.length).toBeGreaterThan(2);
|
||||
const config: ManastormAdminConfig = {
|
||||
...DEFAULT_MANASTORM_ADMIN_CONFIG,
|
||||
dungeons: Object.fromEntries(available.map((dungeon, index) => [
|
||||
dungeon.id,
|
||||
{ status: index === 0 ? "needs-tested" : index === 1 ? "not-ready" : "ready" },
|
||||
])),
|
||||
};
|
||||
|
||||
expect(drawRandomGmReviewTarget("dungeon", config, null, () => 0.99)).toEqual({
|
||||
kind: "dungeon",
|
||||
dungeonId: available[0].id,
|
||||
});
|
||||
|
||||
const withoutNeedsTested = configWithGmReviewStatus(
|
||||
config,
|
||||
{ kind: "dungeon", dungeonId: available[0].id },
|
||||
"ready",
|
||||
)!;
|
||||
expect(drawRandomGmReviewTarget("dungeon", withoutNeedsTested, null, () => 0)).toEqual({
|
||||
kind: "dungeon",
|
||||
dungeonId: available[1].id,
|
||||
});
|
||||
});
|
||||
|
||||
it("uses separate dungeon-boss and imported-Manastorm source queues", () => {
|
||||
const catalog = resolvedBossAdminCatalog(DEFAULT_MANASTORM_ADMIN_CONFIG);
|
||||
const dungeonBosses = catalog.filter((entry) => entry.runnable && entry.source.includes("dungeon"));
|
||||
const manastorms = catalog.filter((entry) => entry.runnable && entry.source.includes("installed-manastorm"));
|
||||
expect(dungeonBosses.length).toBeGreaterThan(0);
|
||||
expect(manastorms.length).toBeGreaterThan(0);
|
||||
|
||||
const bossQueue = gmReviewQueue("boss", DEFAULT_MANASTORM_ADMIN_CONFIG);
|
||||
const manastormQueue = gmReviewQueue("manastorm", DEFAULT_MANASTORM_ADMIN_CONFIG);
|
||||
expect(bossQueue.every((target) => target.kind === "boss"
|
||||
&& dungeonBosses.some((entry) => entry.key === target.bossKey))).toBe(true);
|
||||
expect(manastormQueue.every((target) => target.kind === "manastorm"
|
||||
&& manastorms.some((entry) => entry.key === target.bossKey))).toBe(true);
|
||||
|
||||
const overlap = catalog.find((entry) => entry.runnable
|
||||
&& entry.source.includes("dungeon")
|
||||
&& entry.source.includes("installed-manastorm"));
|
||||
expect(overlap).toBeTruthy();
|
||||
expect(bossQueue).toContainEqual({ kind: "boss", bossKey: overlap!.key });
|
||||
expect(manastormQueue).toContainEqual({ kind: "manastorm", bossKey: overlap!.key });
|
||||
});
|
||||
|
||||
it("avoids an immediate repeat when another prioritized target exists", () => {
|
||||
const targets = gmReviewQueue("manastorm", DEFAULT_MANASTORM_ADMIN_CONFIG);
|
||||
expect(targets.length).toBeGreaterThan(1);
|
||||
const previous = targets[0] as GmReviewTarget;
|
||||
const next = drawRandomGmReviewTarget("manastorm", DEFAULT_MANASTORM_ADMIN_CONFIG, previous, () => 0);
|
||||
expect(next).not.toEqual(previous);
|
||||
});
|
||||
|
||||
it("returns no target when every runnable record is Ready", () => {
|
||||
const catalog = resolvedBossAdminCatalog(DEFAULT_MANASTORM_ADMIN_CONFIG);
|
||||
const config = configWithBossStatuses(Object.fromEntries(catalog.map((entry) => [entry.key, "ready"])));
|
||||
expect(drawRandomGmReviewTarget("boss", config, null, () => 0)).toBeNull();
|
||||
expect(drawRandomGmReviewTarget("manastorm", config, null, () => 0)).toBeNull();
|
||||
});
|
||||
|
||||
it("updates the shared boss record and resolves exact review details", () => {
|
||||
const target = gmReviewQueue("manastorm", DEFAULT_MANASTORM_ADMIN_CONFIG)[0];
|
||||
expect(target?.kind).toBe("manastorm");
|
||||
const updated = configWithGmReviewStatus(DEFAULT_MANASTORM_ADMIN_CONFIG, target!, "not-ready");
|
||||
expect(updated).toBeTruthy();
|
||||
const descriptor = describeGmReviewTarget(target!, updated!);
|
||||
expect(descriptor).toMatchObject({ status: "not-ready", runnable: true });
|
||||
if (target?.kind !== "dungeon") expect(updated!.bosses[target!.bossKey]?.status).toBe("not-ready");
|
||||
});
|
||||
|
||||
it("keeps one shared review note across overlapping Boss and Manastorm targets", () => {
|
||||
const overlap = resolvedBossAdminCatalog(DEFAULT_MANASTORM_ADMIN_CONFIG).find((entry) => (
|
||||
entry.runnable
|
||||
&& entry.source.includes("dungeon")
|
||||
&& entry.source.includes("installed-manastorm")
|
||||
));
|
||||
expect(overlap).toBeTruthy();
|
||||
const bossTarget = { kind: "boss", bossKey: overlap!.key } as const;
|
||||
const manastormTarget = { kind: "manastorm", bossKey: overlap!.key } as const;
|
||||
const noted = configWithGmReviewNote(
|
||||
DEFAULT_MANASTORM_ADMIN_CONFIG,
|
||||
bossTarget,
|
||||
"Portal clips the west wall.",
|
||||
)!;
|
||||
const changedStatus = configWithGmReviewStatus(noted, manastormTarget, "not-ready")!;
|
||||
|
||||
expect(describeGmReviewTarget(manastormTarget, changedStatus)).toMatchObject({
|
||||
status: "not-ready",
|
||||
note: "Portal clips the west wall.",
|
||||
});
|
||||
expect(changedStatus.bosses[overlap!.key]).toMatchObject({
|
||||
status: "not-ready",
|
||||
note: "Portal clips the west wall.",
|
||||
});
|
||||
});
|
||||
|
||||
it("adds and clears advisory dungeon notes without changing availability", () => {
|
||||
const dungeon = DUNGEON_CATALOG.find((entry) => entry.available)!;
|
||||
const target = { kind: "dungeon", dungeonId: dungeon.id } as const;
|
||||
const noted = configWithGmReviewNote(DEFAULT_MANASTORM_ADMIN_CONFIG, target, "Verify the final door.")!;
|
||||
const cleared = configWithGmReviewNote(noted, target, "")!;
|
||||
|
||||
expect(describeGmReviewTarget(target, noted)).toMatchObject({ note: "Verify the final door.", runnable: true });
|
||||
expect(cleared.dungeons[dungeon.id]?.note).toBeUndefined();
|
||||
expect(dungeon.available).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user