Count occupied restarts as failed missions; sync published Workshop version
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -287,6 +287,9 @@ snapshots only. Spectators and temporary connection IDs are excluded. A mission
|
||||
victory does not imply a personal escape. Startup failures, empty restarts and
|
||||
interrupted sessions do not count as gameplay wins/losses or player attempts.
|
||||
An interrupted mission can still have raw combat data in its detail snapshot.
|
||||
New clients report occupied restarts as `defeat`, including recovery from the
|
||||
last durable occupied checkpoint after a forced stop. Those explicit final
|
||||
events count as failures and participant attempts; restart links alone do not.
|
||||
|
||||
Legacy missing counters remain null, with `missionsWithKills`,
|
||||
`missionsWithFriendlyKills`, `missionsWithDeaths`, `missionsWithDowned` and
|
||||
|
||||
@@ -110,6 +110,32 @@ test('published fractional-duration defeats are accepted, counted and retry idem
|
||||
assert.equal((await ingest(event({connectedPlayers: 0.5}))).status, 400);
|
||||
});
|
||||
|
||||
test('occupied restart recovery counts one failure and retains the old mission participants', async () => {
|
||||
const terrain = 'Restart recovery fixture';
|
||||
const player = {...event().players[0], escaped: false};
|
||||
const recovered = event({terrain, phase: 6, outcome: 'defeat', players: [player],
|
||||
reason: 'Mission interrupted by a restart while players were connected.'});
|
||||
const snapshot = {...recovered, eventId: crypto.randomUUID(), type: 'heartbeat', phase: 3, outcome: ''};
|
||||
assert.equal((await ingest(snapshot)).status, 201);
|
||||
const first = await ingest(recovered);
|
||||
assert.equal(first.status, 201, await first.clone().text());
|
||||
assert.equal((await ingest(recovered)).status, 200);
|
||||
// A delayed pre-restart snapshot must not reopen the completed mission.
|
||||
assert.equal((await ingest({...snapshot, eventId: crypto.randomUUID(), elapsedSeconds: 150})).status, 201);
|
||||
const next = event({terrain, type: 'mission_restarted', outcome: '', phase: 0,
|
||||
previousMissionId: recovered.missionId, previousOutcome: 'defeat', players: [], connectedPlayers: 0});
|
||||
assert.equal((await ingest(next)).status, 201);
|
||||
const summary = (await (await ingest(recovered)).json()).community;
|
||||
assert.equal(summary.allServers.losses, 1);
|
||||
assert.equal(summary.allServers.completed, 1);
|
||||
const old = await detail(recovered);
|
||||
assert.equal(old.outcome, 'defeat');
|
||||
assert.equal(old.players[0].id, player.id);
|
||||
assert.equal(old.players[0].participated, true);
|
||||
assert.equal(old.players[0].escaped, false);
|
||||
assert.equal((await detail(next)).outcome, '');
|
||||
});
|
||||
|
||||
test('out-of-order snapshots and second terminal reports cannot reopen or double count a mission', async () => {
|
||||
const e = event({players: []});
|
||||
const heartbeat = {...e, type: 'heartbeat', phase: 4, outcome: '', elapsedSeconds: 100};
|
||||
|
||||
Reference in New Issue
Block a user