Files
electric-cherry/src/lib/beta-plan-summary.ts
T

67 lines
2.9 KiB
TypeScript

import type { BetaPlan, BetaRequirement } from './beta-plan.js';
const count = (n: number, word: string) => `${n} ${word}${n === 1 ? '' : 's'}`;
const duration = (minutes: number) =>
minutes >= 60 && minutes % 60 === 0 ? count(minutes / 60, 'hour') : count(minutes, 'minute');
export const presetDescriptions: Record<string, string> = {
'Quick smoke test': 'A quick check that the server starts and stays healthy.',
'Gameplay validation': 'Prove the build through real matches and populated playtime.',
'Long soak': 'Exercise stability and participation over a longer test.'
};
export function requirementSummary(r: BetaRequirement): string {
const players =
r.minPlayers > 1 ? ` with at least ${r.minPlayers} players` : ' with players present';
switch (r.kind) {
case 'round':
return `Reach round ${r.target}${players}`;
case 'matches':
return `Complete ${count(r.target, 'match').replace('matchs', 'matches')}${r.minRound ? ` reaching round ${r.minRound}` : ''}${r.minPlayers > 1 ? players : ''}${r.minMinutes ? ` lasting at least ${duration(r.minMinutes)} each` : ''}`;
case 'populated-minutes':
return `Accumulate ${duration(r.target)}${players}`;
case 'player-hours':
return `Accumulate ${r.target} player-hours${r.minPlayers > 1 ? players : ''}`;
case 'population':
return `Reach ${count(r.target, 'player')} online`;
case 'sustained-population':
return `Keep at least ${count(r.minPlayers, 'player')} online for ${duration(r.target)}`;
case 'healthy-minutes':
return `Stay continuously healthy for ${duration(r.target)}`;
case 'failure-budget':
return r.target === 0
? 'Allow no health outages'
: `Allow at most ${count(r.target, 'health outage')}`;
case 'recovery':
return `Repeat the checks after ${count(r.target, 'recovery restart')}`;
case 'manual':
return r.label;
}
}
export function coverageSummary(plan: BetaPlan): string {
return plan.scope === 'all'
? 'Every selected server'
: plan.scope === 'quorum'
? `At least ${count(plan.quorum, 'selected server')}`
: plan.scope === 'map'
? 'One server per selected map'
: plan.scope === 'game'
? 'One server per selected game'
: 'One server per game / map';
}
export function needsGameTelemetry(r: BetaRequirement): boolean {
return [
'round',
'matches',
'population',
'populated-minutes',
'player-hours',
'sustained-population'
].includes(r.kind);
}
export function requirementCategory(r: BetaRequirement): string {
return r.kind === 'manual'
? 'Tester sign-off'
: ['healthy-minutes', 'failure-budget'].includes(r.kind)
? 'Continuous check'
: 'Milestone';
}