67 lines
2.9 KiB
TypeScript
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';
|
|
}
|