Add proximity-based map record reminders
This commit is contained in:
+118
-1
@@ -24,7 +24,7 @@ function translate(source) {
|
||||
const result = [];
|
||||
for (let match; (match = headers.exec(protectedSource));) {
|
||||
const name = match[1];
|
||||
if (!/^(service_|help_|make_)/.test(name) && !['common_config', 'ensure_config', 'register_help_command', 'show_help', 'show_record', 'register_core_elem', 'set_core_alpha', 'toggle_core_hud', 'hud_connect', 'hud_text', 'afk_hud_create', 'destroy_on_disconnect'].includes(name)) continue;
|
||||
if (!/^(service_|help_|make_)/.test(name) && !['common_config', 'ensure_config', 'register_help_command', 'show_help', 'show_record', 'show_record_reminder', 'register_core_elem', 'set_core_alpha', 'toggle_core_hud', 'hud_connect', 'hud_text', 'afk_hud_create', 'destroy_on_disconnect'].includes(name)) continue;
|
||||
if (name === 'help_chat_listener') continue;
|
||||
let end = headers.lastIndex, depth = 1;
|
||||
while (depth) {
|
||||
@@ -133,6 +133,7 @@ function engine(game, count = 8, withHud = false) {
|
||||
},
|
||||
addPlayer() { const player = { sessionstate: 'spectator' }; players.add(player); return player; },
|
||||
help: () => c.show_help(), record: snapshot => c.show_record(snapshot),
|
||||
reminder: (snapshot, message) => c.show_record_reminder(snapshot, message),
|
||||
event: name => emit(self, name), end: name => emit(level, name),
|
||||
get state() { return self.tws_service; },
|
||||
get live() { return elements.filter(e => !e.destroyCalls); },
|
||||
@@ -322,6 +323,120 @@ for (const game of ['t5', 't6']) {
|
||||
assert(e.state.record, 'previous expiry cannot hide newer request');
|
||||
assert.equal(e.textCalls, texts);
|
||||
});
|
||||
check(`${game} automatic reminders use two elements and expire after six seconds`, () => {
|
||||
const e = engine(game);
|
||||
assert.equal(e.reminder({ round: 82 }, '5 rounds to tie'), true);
|
||||
const request = e.state.record;
|
||||
assert.equal(request.kind, 'reminder');
|
||||
assert.equal(request.pages, 1);
|
||||
assert.equal(request.remaining, 6000);
|
||||
assert.equal(e.state.record_title.text, 'Map record | Round 82');
|
||||
assert.equal(e.state.rows.length, 1);
|
||||
assert.equal(e.state.rows[0].text, '5 rounds to tie');
|
||||
assert.equal(e.live.length, 2);
|
||||
assert.equal(e.visible.length, 2);
|
||||
assertCounter(e, 1, 1);
|
||||
assertTextOnly(e);
|
||||
const calls = e.textCalls, allocated = e.elements.length;
|
||||
e.advance(5900);
|
||||
assert.equal(e.state.record, request);
|
||||
assert.equal(request.remaining, 100);
|
||||
assert.equal(e.reminder({ round: 83 }, 'Newer target'), false);
|
||||
assert.equal(e.state.record, request, 'rejected hints do not replace or restart a visible hint');
|
||||
assert.equal(request.remaining, 100);
|
||||
assert.equal(e.textCalls, calls);
|
||||
assert.equal(e.elements.length, allocated);
|
||||
e.advance(100);
|
||||
assert.equal(e.state.record, undefined);
|
||||
assert.equal(e.live.length, 0);
|
||||
assert(e.elements.every(elem => elem.destroyCalls === 1));
|
||||
assert.equal(e.reminder({ round: 83 }, '6 rounds to tie'), true);
|
||||
assert.equal(e.state.record.remaining, 6000);
|
||||
assert.equal(e.live.length, 2);
|
||||
assert.equal(e.peakLive, 2);
|
||||
});
|
||||
check(`${game} automatic reminders never replace or queue behind help and full records`, () => {
|
||||
const e = engine(game);
|
||||
e.record(snapshot(['One', 'Two', 'Three', 'Four']));
|
||||
e.advance(1000);
|
||||
const record = e.state.record;
|
||||
const generation = e.state.generation, allocations = e.elements.length;
|
||||
assert.equal(e.reminder({ round: 82 }, '5 rounds to tie'), false);
|
||||
assert.equal(e.state.record, record);
|
||||
assert.equal(record.remaining, 11000);
|
||||
assert.equal(e.state.generation, generation);
|
||||
assert.equal(e.elements.length, allocations);
|
||||
e.help();
|
||||
e.advance(1000);
|
||||
const help = e.state.help, withHelp = e.elements.length;
|
||||
assert.equal(e.reminder({ round: 82 }, '5 rounds to tie'), false);
|
||||
assert.equal(e.state.help, help);
|
||||
assert.equal(e.state.record, record);
|
||||
assert.equal(e.elements.length, withHelp);
|
||||
e.advance(11000);
|
||||
assert.equal(e.state.record, record);
|
||||
assert.equal(record.remaining, 11000, 'manual record still resumes with its remaining time');
|
||||
e.advance(23000);
|
||||
assert.equal(e.state.record, undefined);
|
||||
assert.equal(e.live.length, 0, 'skipped hints do not appear later');
|
||||
e.help();
|
||||
assert.equal(e.reminder({ round: 82 }, '5 rounds to tie'), false);
|
||||
assert.equal(e.state.record, undefined, 'help alone must not queue a hint');
|
||||
e.advance(12000);
|
||||
assert.equal(e.live.length, 0);
|
||||
});
|
||||
check(`${game} help discards a reminder and manual replay replaces it at full duration`, () => {
|
||||
const e = engine(game);
|
||||
e.reminder({ round: 82 }, '5 rounds to tie');
|
||||
const reminderElements = [...e.live];
|
||||
e.advance(2000);
|
||||
e.help();
|
||||
assert.equal(e.state.record, undefined);
|
||||
assert(reminderElements.every(elem => elem.destroyCalls === 1));
|
||||
e.advance(12000);
|
||||
assert.equal(e.state.help, undefined);
|
||||
assert.equal(e.live.length, 0, 'an interrupted round hint does not resume after help');
|
||||
e.reminder({ round: 82 }, '4 rounds to tie');
|
||||
const replaced = [...e.live];
|
||||
e.advance(5900);
|
||||
e.record(snapshot(['One', 'Two', 'Three', 'Four']));
|
||||
assert.equal(e.state.record.kind, 'record');
|
||||
assert.equal(e.state.record.remaining, 12000);
|
||||
assert.equal(e.state.record.pages, 2);
|
||||
assert.equal(e.live.length, 5);
|
||||
assert(replaced.every(elem => elem.destroyCalls === 1));
|
||||
e.advance(100);
|
||||
assert.equal(e.state.record.page, 0, 'old reminder expiry cannot dismiss manual replay');
|
||||
assert.equal(e.state.record.remaining, 11900);
|
||||
e.advance(11900);
|
||||
assert.equal(e.state.record.page, 1);
|
||||
assert.equal(e.state.rows[0].text, 'Four');
|
||||
e.advance(12000);
|
||||
assert.equal(e.live.length, 0);
|
||||
});
|
||||
check(`${game} invalid reminders do not initialize a service or allocate elements`, () => {
|
||||
const e = engine(game);
|
||||
for (const bad of [undefined, {}, { round: 0 }, { round: -1 }])
|
||||
assert.equal(e.reminder(bad, '5 rounds to tie'), false);
|
||||
for (const message of [undefined, ''])
|
||||
assert.equal(e.reminder({ round: 82 }, message), false);
|
||||
assert.equal(e.state, undefined);
|
||||
assert.equal(e.elements.length, 0);
|
||||
});
|
||||
for (const event of ['end_game', 'game_ended', 'intermission', 'disconnect'])
|
||||
check(`${game} ${event} cleans a reminder and blocks reopening`, () => {
|
||||
const e = engine(game);
|
||||
e.reminder({ round: 82 }, '5 rounds to tie');
|
||||
e.advance(1000);
|
||||
if (event === 'disconnect') e.event(event); else e.end(event);
|
||||
assert.equal(e.state.closed, true);
|
||||
assert.equal(e.state.record, undefined);
|
||||
assert.equal(e.live.length, 0);
|
||||
assert.equal(e.reminder({ round: 82 }, '4 rounds to tie'), false);
|
||||
e.advance(12000);
|
||||
assert.equal(e.elements.length, 2);
|
||||
assert(e.elements.every(elem => elem.destroyCalls === 1));
|
||||
});
|
||||
check(`${game} unavailable, empty and paged records rebuild only when their allocation changes`, () => {
|
||||
const e = engine(game);
|
||||
e.record(undefined);
|
||||
@@ -372,6 +487,8 @@ for (const game of ['t5', 't6']) {
|
||||
check(`${game} ending before first service blocks lazy creation`, () => {
|
||||
const e = engine(game);
|
||||
e.end('end_game'); e.help(); e.record(snapshot());
|
||||
assert.equal(e.reminder({ round: 82 }, '5 rounds to tie'), false);
|
||||
assert.equal(e.state, undefined);
|
||||
assert.equal(e.elements.length, 0);
|
||||
});
|
||||
check(`${game} rendered records cache text and never allocate on timer ticks`, () => {
|
||||
|
||||
Reference in New Issue
Block a user