89 lines
3.4 KiB
JavaScript
89 lines
3.4 KiB
JavaScript
import { describe, expect, it } from 'vitest';
|
|
|
|
import { SCORING } from '../../app/static/js/config.js';
|
|
import { multiplierForStreak, ScoreKeeper, waveBonus } from '../../app/static/js/logic/scoring.js';
|
|
|
|
describe('multiplierForStreak', () => {
|
|
it('steigt alle stepKills Abschüsse um stepValue', () => {
|
|
expect(multiplierForStreak(0)).toBe(1);
|
|
expect(multiplierForStreak(1)).toBe(1);
|
|
expect(multiplierForStreak(SCORING.stepKills - 1)).toBe(1);
|
|
expect(multiplierForStreak(SCORING.stepKills)).toBe(1 + SCORING.stepValue);
|
|
expect(multiplierForStreak(SCORING.stepKills * 2)).toBe(1 + 2 * SCORING.stepValue);
|
|
});
|
|
|
|
it('ist nach oben gedeckelt', () => {
|
|
expect(multiplierForStreak(10_000)).toBe(SCORING.maxMultiplier);
|
|
});
|
|
});
|
|
|
|
describe('waveBonus', () => {
|
|
it('wächst linear mit der Welle', () => {
|
|
expect(waveBonus(1)).toBe(SCORING.waveBonusPerWave);
|
|
expect(waveBonus(7)).toBe(7 * SCORING.waveBonusPerWave);
|
|
});
|
|
});
|
|
|
|
describe('ScoreKeeper', () => {
|
|
const cfg = { ...SCORING, streakWindowMs: 1000, stepKills: 2, stepValue: 1, maxMultiplier: 3 };
|
|
|
|
it('zählt Abschüsse ohne Serie mit Faktor 1', () => {
|
|
const keeper = new ScoreKeeper(cfg);
|
|
expect(keeper.registerKill(10, 0)).toEqual({ awarded: 10, multiplier: 1, streak: 1 });
|
|
expect(keeper.registerKill(10, 5000)).toEqual({ awarded: 10, multiplier: 1, streak: 1 });
|
|
expect(keeper.score).toBe(20);
|
|
expect(keeper.kills).toBe(2);
|
|
});
|
|
|
|
it('baut innerhalb des Fensters eine Serie mit Multiplikator auf', () => {
|
|
const keeper = new ScoreKeeper(cfg);
|
|
const results = [0, 500, 900, 1400, 1800].map((t) => keeper.registerKill(10, t));
|
|
expect(results.map((r) => r.multiplier)).toEqual([1, 2, 2, 3, 3]);
|
|
expect(keeper.score).toBe(10 + 20 + 20 + 30 + 30);
|
|
expect(keeper.bestStreak).toBe(5);
|
|
});
|
|
|
|
it('lässt die Serie nach Ablauf des Fensters verfallen', () => {
|
|
const keeper = new ScoreKeeper(cfg);
|
|
keeper.registerKill(10, 0);
|
|
keeper.registerKill(10, 100);
|
|
expect(keeper.multiplierAt(500)).toBe(2);
|
|
expect(keeper.multiplierAt(1200)).toBe(1);
|
|
expect(keeper.registerKill(10, 1200).streak).toBe(1);
|
|
expect(keeper.bestStreak).toBe(2);
|
|
});
|
|
|
|
it('beendet die Serie bei Treffern am Präsidenten', () => {
|
|
const keeper = new ScoreKeeper(cfg);
|
|
keeper.registerKill(10, 0);
|
|
keeper.registerKill(10, 100);
|
|
keeper.breakStreak();
|
|
expect(keeper.multiplierAt(200)).toBe(1);
|
|
expect(keeper.registerKill(10, 200)).toEqual({ awarded: 10, multiplier: 1, streak: 1 });
|
|
});
|
|
|
|
it('vergibt Bonuspunkte ohne Multiplikator und ignoriert negative Werte', () => {
|
|
const keeper = new ScoreKeeper(cfg);
|
|
keeper.registerKill(10, 0);
|
|
keeper.registerKill(10, 10);
|
|
expect(keeper.addBonus(100)).toBe(100);
|
|
expect(keeper.addBonus(-50)).toBe(0);
|
|
expect(keeper.score).toBe(10 + 20 + 100);
|
|
});
|
|
|
|
it('liefert eine Momentaufnahme mit Restzeit der Serie', () => {
|
|
const keeper = new ScoreKeeper(cfg);
|
|
keeper.registerKill(10, 0);
|
|
const snap = keeper.snapshot(250);
|
|
expect(snap).toMatchObject({ score: 10, kills: 1, streak: 1, multiplier: 1, bestStreak: 1 });
|
|
expect(snap.streakTimeLeft).toBeCloseTo(0.75);
|
|
expect(keeper.snapshot(5000)).toMatchObject({ streak: 0, streakTimeLeft: 0 });
|
|
});
|
|
|
|
it('rundet Punkte bei gebrochenen Multiplikatoren', () => {
|
|
const keeper = new ScoreKeeper({ ...cfg, stepValue: 0.5 });
|
|
keeper.registerKill(7, 0);
|
|
expect(keeper.registerKill(7, 10).awarded).toBe(Math.round(7 * 1.5));
|
|
});
|
|
});
|