Map-Pools: Overpass, Vertigo und Cache für Competitive, Map-Auswahl im Admin, Veto-Ablauf passend zur Map-Anzahl

This commit is contained in:
mregosar committed 2026-10-29 21:03:29 +01:00
1 parent e3834bb071
commit 2d65634d6e
13 files changed
+459 -45

No files matched your search

+43 -6
View File
@@ -2,11 +2,14 @@ import { test } from 'node:test';
import assert from 'node:assert/strict';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { computeVetoState, resolveAction, validateFlow } from '../src/veto.js';
import { buildMapPools, loadMapPools } from '../src/mapPools.js';
import { computeVetoState, generateFlow, resolveAction, validateFlow } from '../src/veto.js';
import { buildMapPools, loadMapPools, setActiveMaps } from '../src/mapPools.js';
const here = path.dirname(fileURLToPath(import.meta.url));
const pools = loadMapPools(path.join(here, '..', 'config', 'map-pools.json'));
// Die klassischen 7 Competitive-Maps: dafür gilt der fest hinterlegte Ablauf
const SEVEN = ['de_ancient', 'de_anubis', 'de_dust2', 'de_inferno', 'de_mirage', 'de_nuke', 'de_train'];
const competitive7 = () => setActiveMaps(structuredClone(pools.competitive), SEVEN);
test('alle ausgelieferten Abläufe sind gültig, Wingman-BO5 ist nicht unterstützt', () => {
assert.equal(pools.competitive.formats.bo1.supported, true);
@@ -37,8 +40,42 @@ test('ungültiger Ablauf in der Konfiguration deaktiviert nur dieses Format', ()
},
});
assert.equal(custom.mini.formats.bo1.supported, true);
assert.equal(custom.mini.formats.bo3.supported, false);
assert.match(custom.mini.formats.bo5.reason, /Kein Veto-Ablauf/);
assert.equal(custom.mini.formats.bo1.generated, false, 'passender fester Ablauf wird genommen');
// Ungültiger fester Ablauf: die Anwendung erzeugt einen passenden
assert.equal(custom.mini.formats.bo3.supported, true);
assert.equal(custom.mini.formats.bo3.generated, true);
assert.match(custom.mini.formats.bo5.reason, /mindestens 5 Maps/);
});
test('Erzeugte Abläufe sind für jede Map-Anzahl gültig', () => {
for (let n = 2; n <= 12; n += 1) {
for (const format of ['bo1', 'bo3', 'bo5']) {
const flow = generateFlow(n, format);
const need = { bo1: 2, bo3: 3, bo5: 5 }[format];
if (n < need) {
assert.equal(flow, null, `${format} mit ${n} Maps`);
continue;
}
assert.deepEqual(validateFlow(flow, n, format), [], `${format} mit ${n} Maps: ${flow.join(' ')}`);
}
}
// Bans und Picks wechseln sich ab, die Seite der Entscheidungsmap wählt das Team, das nicht zuletzt dran war
assert.deepEqual(generateFlow(5, 'bo3'), ['ban:X', 'ban:Y', 'pick:X', 'side:Y', 'pick:Y', 'side:X', 'decider', 'side:X']);
assert.deepEqual(generateFlow(3, 'bo1'), ['ban:X', 'ban:Y', 'decider', 'side:X']);
});
test('Aktive Maps wählen: Formate passen sich an, Reihenfolge bleibt wie im Katalog', () => {
const pool = structuredClone(pools.competitive);
setActiveMaps(pool, ['de_vertigo', 'de_cache', 'de_mirage', 'de_unbekannt']);
assert.deepEqual(pool.maps.map((m) => m.id), ['de_cache', 'de_mirage', 'de_vertigo']);
assert.equal(pool.formats.bo1.supported, true);
assert.equal(pool.formats.bo3.supported, true);
assert.equal(pool.formats.bo5.supported, false);
// 10 Maps (alle): kein fester Ablauf passt, es wird erzeugt
assert.equal(pools.competitive.maps.length, 10);
assert.equal(pools.competitive.formats.bo3.generated, true);
// 7 klassische Maps: fester Ablauf aus der Konfiguration
assert.equal(competitive7().formats.bo3.generated, false);
});
function play(pool, format, firstTeam, choices) {
@@ -52,7 +89,7 @@ function play(pool, format, firstTeam, choices) {
}
test('BO3 Competitive: kompletter Ablauf mit Seitenwahl und Entscheidungsmap', () => {
const state = play(pools.competitive, 'bo3', 'B', [
const state = play(competitive7(), 'bo3', 'B', [
{ map: 'de_train' }, // B bannt
{ map: 'de_nuke' }, // A bannt
{ map: 'de_mirage' }, // B pickt
@@ -82,7 +119,7 @@ test('BO1 Wingman: Entscheidungsmap wird automatisch übernommen', () => {
});
test('falsches Team, veraltete Schritte und vergebene Maps werden abgelehnt', () => {
const pool = pools.competitive;
const pool = competitive7();
const ctx = { maps: pool.maps, flow: pool.formats.bo1.flow, firstTeam: 'A', actions: [] };
assert.throws(() => resolveAction(ctx, { team: 'B', stepIndex: 0, map: 'de_nuke' }), { code: 'not_your_turn' });
assert.throws(() => resolveAction(ctx, { team: 'A', stepIndex: 1, map: 'de_nuke' }), { code: 'stale_step' });