Engine, felt, controls, sounds, card skins, and dev popups; SSE events in the realtime hook, nav and command palette entries, stats migration, and the six blackjack test suites. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
133 lines
3.9 KiB
TypeScript
133 lines
3.9 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
BLACKJACK_XP_ENABLED,
|
|
BLACKJACK_XP_CAP,
|
|
computeBlackjackStatsDelta,
|
|
readBlackjackStats,
|
|
xpForProfit,
|
|
type BlackjackSessionResult,
|
|
type BlackjackStats,
|
|
} from "@/lib/minigames/blackjack/stats";
|
|
|
|
function result(overrides: Partial<BlackjackSessionResult> = {}): BlackjackSessionResult {
|
|
return {
|
|
userId: 1,
|
|
roundsPlayed: 10,
|
|
roundsWon: 4,
|
|
blackjacksHit: 1,
|
|
finalBankroll: 1250,
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
function current(overrides: Partial<BlackjackStats> = {}): BlackjackStats {
|
|
return {
|
|
gamesPlayed: 0,
|
|
roundsWon: 0,
|
|
blackjacksHit: 0,
|
|
bestScore: 0,
|
|
xpEarned: 0,
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
describe("xpForProfit", () => {
|
|
it("awards the base XP for a breakeven or losing session", () => {
|
|
expect(xpForProfit(1000)).toBe(5);
|
|
expect(xpForProfit(500)).toBe(5);
|
|
});
|
|
|
|
it("awards no bracket bonus below a full 25% profit", () => {
|
|
expect(xpForProfit(1100)).toBe(5);
|
|
expect(xpForProfit(1249)).toBe(5);
|
|
});
|
|
|
|
it("awards 10 XP per full 25% profit bracket", () => {
|
|
expect(xpForProfit(1250)).toBe(15);
|
|
expect(xpForProfit(1500)).toBe(25);
|
|
expect(xpForProfit(1750)).toBe(35);
|
|
expect(xpForProfit(2000)).toBe(45);
|
|
});
|
|
|
|
it("caps the payout at the session cap", () => {
|
|
expect(BLACKJACK_XP_CAP).toBe(50);
|
|
expect(xpForProfit(2500)).toBe(BLACKJACK_XP_CAP);
|
|
expect(xpForProfit(100000)).toBe(BLACKJACK_XP_CAP);
|
|
});
|
|
});
|
|
|
|
describe("BLACKJACK_XP_ENABLED", () => {
|
|
it("is disabled by default until the XP system is reworked", () => {
|
|
expect(BLACKJACK_XP_ENABLED).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("computeBlackjackStatsDelta", () => {
|
|
it("increments gamesPlayed by exactly one", () => {
|
|
const next = computeBlackjackStatsDelta(current({ gamesPlayed: 7 }), result());
|
|
expect(next.gamesPlayed).toBe(8);
|
|
});
|
|
|
|
it("accumulates rounds won and blackjacks hit", () => {
|
|
const next = computeBlackjackStatsDelta(
|
|
current({ roundsWon: 10, blackjacksHit: 2 }),
|
|
result({ roundsWon: 4, blackjacksHit: 1 }),
|
|
);
|
|
expect(next.roundsWon).toBe(14);
|
|
expect(next.blackjacksHit).toBe(3);
|
|
});
|
|
|
|
it("keeps bestScore when the final bankroll is lower", () => {
|
|
const next = computeBlackjackStatsDelta(
|
|
current({ bestScore: 9000 }),
|
|
result({ finalBankroll: 1250 }),
|
|
);
|
|
expect(next.bestScore).toBe(9000);
|
|
});
|
|
|
|
it("raises bestScore when the final bankroll is higher", () => {
|
|
const next = computeBlackjackStatsDelta(
|
|
current({ bestScore: 1000 }),
|
|
result({ finalBankroll: 2400 }),
|
|
);
|
|
expect(next.bestScore).toBe(2400);
|
|
});
|
|
|
|
it("adds the profit XP to the existing xpEarned total", () => {
|
|
const next = computeBlackjackStatsDelta(
|
|
current({ xpEarned: 100 }),
|
|
result({ finalBankroll: 1500 }),
|
|
);
|
|
expect(next.xpEarned).toBe(125);
|
|
});
|
|
|
|
it("does not mutate the current stats object", () => {
|
|
const before = current({ gamesPlayed: 1, xpEarned: 125 });
|
|
computeBlackjackStatsDelta(before, result());
|
|
expect(before).toEqual(current({ gamesPlayed: 1, xpEarned: 125 }));
|
|
});
|
|
});
|
|
|
|
describe("readBlackjackStats", () => {
|
|
it("reads blackjack stats from a profile that also carries sibling games", () => {
|
|
const profile = {
|
|
progression: {
|
|
minigames: {
|
|
poker: { gamesPlayed: 12, xpEarned: 40 },
|
|
blackjack: { gamesPlayed: 3, roundsWon: 5, blackjacksHit: 2, bestScore: 1500, xpEarned: 15 },
|
|
},
|
|
},
|
|
};
|
|
expect(readBlackjackStats(profile)).toEqual(
|
|
current({ gamesPlayed: 3, roundsWon: 5, blackjacksHit: 2, bestScore: 1500, xpEarned: 15 }),
|
|
);
|
|
});
|
|
|
|
it("returns all zeros when the blackjack group is missing", () => {
|
|
expect(readBlackjackStats({ progression: { minigames: {} } })).toEqual(current());
|
|
});
|
|
|
|
it("returns all zeros for a nullish profile", () => {
|
|
expect(readBlackjackStats(undefined)).toEqual(current());
|
|
});
|
|
});
|