more queue related convergence for the future.

This commit is contained in:
legop3
2026-09-27 17:19:56 -04:00
parent 7231809140
commit 34936ab05c
54 changed files with 219 additions and 368 deletions
+6 -13
View File
@@ -2,16 +2,9 @@ const { describeQueue } = require('./queueDisplay');
const { TURN_DURATION_MS, IDLE_TIMEOUT_MS } = require('./constants');
const labels = {
...require('./labels'),
waiting: 'Someone else is driving',
handoff: 'It’s your turn!',
active: 'You’re driving',
idleWarning: 'Start driving or your turn will be skipped',
activeTimer: 'Your turn',
waitingTimer: 'Waiting',
untilTurn: 'until your turn',
timeRemaining: 'left',
showTimer: 'Show turn timer',
hideTimer: 'Hide turn timer',
showName: 'Show rover name',
hideName: 'Hide rover name',
};
@@ -25,14 +18,14 @@ function buildRoverTurn({ rover, mode, socketId, turnInfo, activeDriverId, users
const userIndex = socketId ? queue.indexOf(socketId) : -1;
const enabled = mode === 'turns' && queue.length > 1 && currentIndex >= 0 && userIndex >= 0;
const turnsAhead = enabled ? (userIndex - currentIndex + queue.length) % queue.length : null;
const display = describeQueue(queue, currentDriverId, users);
return {
target: { id: rover.id, name: rover.name, color: rover.color, fallback: rover.id },
...describeQueue(queue, currentDriverId),
userLabels: Object.fromEntries(queue.map((id) => [id,
users.find((user) => user.socketId === id)?.nickname || id,
])),
...display,
// Null distinguishes a rover that has never had a queue from an empty queue.
queue: turnInfo ? display.queue : null,
enabled,
isActive: turnsAhead === 0,
ownsControl: Boolean(socketId && currentDriverId === socketId),
turnsAhead,
queueLength: queue.length,
deadline: turnInfo?.deadline || null,
+1 -2
View File
@@ -1,7 +1,6 @@
// turn Service
// Purpose: Defines the turn Service module and the helpers/state used by this service unit.
// Scope: Keeps runtime behavior unchanged while isolating responsibilities into a clear module boundary.
const { describeQueue } = require('./queueDisplay');
const io = require('../../globals/io');
const { sendAlert } = require('../alertService');
const { MODES, getMode, modeEvents } = require('../modeManager');
@@ -432,7 +431,7 @@ function getTurnQueues() {
driverQueues.forEach((queue, roverId) => {
payload[roverId] = {
mode,
...describeQueue(Array.from(queue.queue), queue.current),
queue: Array.from(queue.queue),
current: queue.current,
deadline: turnDeadlines.get(roverId) || null,
idleDeadline: idleDeadlines.get(roverId) || null,
+10
View File
@@ -0,0 +1,10 @@
module.exports = {
handoff: 'It’s your turn!',
idleWarning: 'Start driving or your turn will be skipped',
activeTimer: 'Your turn',
waitingTimer: 'Waiting',
untilTurn: 'until your turn',
timeRemaining: 'left',
showTimer: 'Show turn timer',
hideTimer: 'Hide turn timer',
};
@@ -1,10 +1,20 @@
// Shared display ordering only; each service still owns its queue policy.
function describeQueue(queue, currentId) {
const currentIndex = currentId ? queue.indexOf(currentId) : -1;
const nextId = queue.length > 1
? queue[(currentIndex + 1) % queue.length]
: null;
return { queue, currentId, nextId };
// Queue entries are complete display records. No browser-side user lookup or
// naming fallback is needed, including when the queue comes from another server.
function describeQueue(socketIds, currentId, users) {
const byId = new Map(users.map((user) => [user.socketId, user]));
const currentIndex = currentId ? socketIds.indexOf(currentId) : -1;
return {
queue: socketIds.map((socketId) => {
const user = byId.get(socketId);
return {
socketId,
name: user?.nickname || user?.name || socketId.slice(0, 6) || 'unknown',
role: user?.role || null,
};
}),
currentId,
nextId: socketIds.length > 1 ? socketIds[(currentIndex + 1) % socketIds.length] : null,
};
}
module.exports = { describeQueue };