Stage 17 round 6 (#7): reset the nudge cooldown once the player acts
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 8s
CI / integration (pull_request) Successful in 11s
CI / ui (pull_request) Successful in 30s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m4s
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 8s
CI / integration (pull_request) Successful in 11s
CI / ui (pull_request) Successful in 30s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m4s
The hourly nudge cooldown now clears as soon as the sender has moved or posted a chat since their last nudge — engagement lifts the 'don't spam' limit. Backend: Nudge checks game.LastMoveAt + the sender's last non-nudge chat against the last nudge time (GameReader gains LastMoveAt). UI: nudgeOnCooldown mirrors it — a chat reset is read from the message list, a move is tracked client-side (lastActedAt on commit/pass/exchange; the backend stays authoritative across a reload). Integration test covers the reset.
This commit is contained in:
+17
-5
@@ -95,14 +95,23 @@
|
||||
// timer while the chat is open, so it re-enables without waiting for a new message.
|
||||
const nudgeCooldownSecs = 3600;
|
||||
let nudgeTick = $state(0);
|
||||
// Unix seconds of the player's own last move, which resets the nudge cooldown (mirrors the
|
||||
// backend, Stage 17). A chat reset is read from `messages`; a move is tracked client-side
|
||||
// (the backend stays authoritative across a reload).
|
||||
let lastActedAt = $state(0);
|
||||
const nudgeOnCooldown = $derived.by(() => {
|
||||
void nudgeTick;
|
||||
const mine = app.session?.userId ?? '';
|
||||
const last = messages.reduce(
|
||||
(mx, m) => (m.kind === 'nudge' && m.senderId === mine ? Math.max(mx, m.createdAtUnix) : mx),
|
||||
0,
|
||||
);
|
||||
return last > 0 && Date.now() / 1000 - last < nudgeCooldownSecs;
|
||||
let lastNudge = 0;
|
||||
let lastChat = 0;
|
||||
for (const m of messages) {
|
||||
if (m.senderId !== mine) continue;
|
||||
if (m.kind === 'nudge') lastNudge = Math.max(lastNudge, m.createdAtUnix);
|
||||
else lastChat = Math.max(lastChat, m.createdAtUnix);
|
||||
}
|
||||
if (lastNudge === 0 || Date.now() / 1000 - lastNudge >= nudgeCooldownSecs) return false;
|
||||
// Engagement since the nudge clears the cooldown: a chat or a move.
|
||||
return lastChat <= lastNudge && lastActedAt <= lastNudge;
|
||||
});
|
||||
|
||||
async function load() {
|
||||
@@ -361,6 +370,7 @@
|
||||
busy = true;
|
||||
try {
|
||||
await gateway.submitPlay(id, sub.dir, sub.tiles, variant);
|
||||
lastActedAt = Date.now() / 1000; // a move resets the nudge cooldown
|
||||
telegramHaptic('success');
|
||||
zoomed = false;
|
||||
await load();
|
||||
@@ -381,6 +391,7 @@
|
||||
busy = true;
|
||||
try {
|
||||
await gateway.pass(id);
|
||||
lastActedAt = Date.now() / 1000; // a move resets the nudge cooldown
|
||||
await load();
|
||||
} catch (e) {
|
||||
handleError(e);
|
||||
@@ -461,6 +472,7 @@
|
||||
busy = true;
|
||||
try {
|
||||
await gateway.exchange(id, tiles, variant);
|
||||
lastActedAt = Date.now() / 1000; // a move resets the nudge cooldown
|
||||
await load();
|
||||
} catch (e) {
|
||||
handleError(e);
|
||||
|
||||
Reference in New Issue
Block a user