feat: build compact BO2 grind companion with cumulative ranks
Some checks failed
Test and deploy staging / staging (push) Failing after 2m50s
Some checks failed
Test and deploy staging / staging (push) Failing after 2m50s
This commit is contained in:
84
src/lib/game-tracker/rank-progress.test.ts
Normal file
84
src/lib/game-tracker/rank-progress.test.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import catalog from '../../../data/call-of-duty.json';
|
||||
import type { MasteryRules, Weapon } from './mastery';
|
||||
import { playerRankLimits, weaponRankLimits } from './rank-limits';
|
||||
import {
|
||||
gameRanksProgress,
|
||||
hasReachedMaxLevel,
|
||||
rankProgress,
|
||||
weaponFinished,
|
||||
weaponLevelsProgress
|
||||
} from './rank-progress';
|
||||
|
||||
const game = catalog.games.find((g) => g.slug === 'black-ops-2')!;
|
||||
const rules = { ...game, classes: game.classes.map((c) => c.name) } as MasteryRules;
|
||||
const m27: Weapon = { id: 1, name: 'M27', category: 'Assault Rifles', postLaunch: false };
|
||||
const mp7: Weapon = { id: 2, name: 'MP7', category: 'Submachine Guns', postLaunch: false };
|
||||
|
||||
describe('BO2 rank progression', () => {
|
||||
it('counts every level in each of three weapon runs', () => {
|
||||
const limits = weaponRankLimits(rules, m27);
|
||||
expect(rankProgress(limits)).toEqual({ value: 0, total: 51 });
|
||||
for (let prestige = 0; prestige <= 2; prestige++) {
|
||||
for (let level = 1; level <= 17; level++) {
|
||||
expect(rankProgress(limits, { level, prestige })).toEqual({
|
||||
value: prestige * 17 + level,
|
||||
total: 51
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
it('weights the combined arsenal by levels and excludes unranked weapons', () => {
|
||||
const rpg = { ...m27, id: 3, name: 'RPG', category: 'Launchers' };
|
||||
const ranks = new Map([
|
||||
[1, { level: 9, prestige: 1 }],
|
||||
[2, { level: 8, prestige: 0 }]
|
||||
]);
|
||||
expect(weaponLevelsProgress(rules, [m27, mp7, rpg], ranks)).toEqual({ value: 34, total: 99 });
|
||||
expect(gameRanksProgress(rules, [m27, mp7, rpg], ranks, { level: 20, prestige: 2 })).toEqual({
|
||||
value: 164,
|
||||
total: 704
|
||||
});
|
||||
});
|
||||
it('uses class caps and individual exceptions', () => {
|
||||
const expected: Record<string, number | null> = {
|
||||
M27: 17,
|
||||
MP7: 16,
|
||||
'Vector K10': 16,
|
||||
'Skorpion EVO': 16,
|
||||
Peacekeeper: 16,
|
||||
'DSR 50': 10,
|
||||
Ballista: 11,
|
||||
Crossbow: 6,
|
||||
RPG: null,
|
||||
'Combat Knife': null
|
||||
};
|
||||
for (const c of game.classes)
|
||||
for (const name of [...c.weapons, ...('postLaunch' in c ? (c.postLaunch ?? []) : [])]) {
|
||||
const limits = weaponRankLimits(rules, { name, category: c.name });
|
||||
if (name in expected) expect(limits.maxLevel, name).toBe(expected[name]);
|
||||
expect(limits.maxPrestige).toBe(2);
|
||||
}
|
||||
expect(playerRankLimits(rules).maxLevel).toBe(55);
|
||||
expect(rankProgress(playerRankLimits(rules), { level: 55, prestige: 10 })).toEqual({
|
||||
value: 605,
|
||||
total: 605
|
||||
});
|
||||
});
|
||||
it('keeps first-run attachment completion separate from all prestige runs', () => {
|
||||
expect(hasReachedMaxLevel(rules, m27, { level: 17, prestige: 0 })).toBe(true);
|
||||
expect(hasReachedMaxLevel(rules, m27, { level: 1, prestige: 1 })).toBe(true);
|
||||
expect(weaponFinished(rules, m27, { level: 17, prestige: 0 }, () => true)).toBe(false);
|
||||
expect(weaponFinished(rules, m27, { level: 16, prestige: 2 }, () => true)).toBe(false);
|
||||
expect(weaponFinished(rules, m27, { level: 17, prestige: 2 }, () => true)).toBe(true);
|
||||
});
|
||||
it('bounds historic out-of-range values without mutating saved data', () => {
|
||||
const rank = { level: 100, prestige: 999 };
|
||||
expect(rankProgress(weaponRankLimits(rules, m27), rank)).toEqual({ value: 51, total: 51 });
|
||||
expect(rank).toEqual({ level: 100, prestige: 999 });
|
||||
expect(rankProgress(weaponRankLimits({ ...rules, rankCaps: undefined }, m27), rank)).toEqual({
|
||||
value: 0,
|
||||
total: 0
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user