From 8cb3035597c9ae2f817f5fa6d32784af427402e7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 1 Mar 2026 22:56:59 +0000 Subject: [PATCH 1/2] Initial plan From 8a0e30f281424bff0312ee3c0ad07b7a82424b3b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 1 Mar 2026 23:03:52 +0000 Subject: [PATCH 2/2] Remove players from multiplayer room on leave if they record no stats and no buzzes Co-authored-by: geoffrey-wu <42471355+geoffrey-wu@users.noreply.github.com> --- client/play/mp/MultiplayerTossupBonusClient.js | 15 ++++++++++----- quizbowl/Player.js | 10 ++++++++++ quizbowl/Room.js | 15 +++++++++++---- quizbowl/TossupRoom.js | 1 + 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/client/play/mp/MultiplayerTossupBonusClient.js b/client/play/mp/MultiplayerTossupBonusClient.js index 8e19be11f..e6279db08 100644 --- a/client/play/mp/MultiplayerTossupBonusClient.js +++ b/client/play/mp/MultiplayerTossupBonusClient.js @@ -388,12 +388,17 @@ export const MultiplayerClientMixin = (ClientClass) => class extends ClientClass } } - leave ({ userId, username }) { + leave ({ userId, username, remove }) { this.logEventConditionally(username, 'left the game'); - this.room.players[userId].online = false; - document.getElementById(`list-group-${userId}`).classList.add('offline'); - document.getElementById(`points-${userId}`).classList.remove('bg-success'); - document.getElementById(`points-${userId}`).classList.add('bg-secondary'); + if (remove) { + delete this.room.players[userId]; + document.getElementById(`list-group-${userId}`)?.remove(); + } else { + this.room.players[userId].online = false; + document.getElementById(`list-group-${userId}`).classList.add('offline'); + document.getElementById(`points-${userId}`).classList.remove('bg-success'); + document.getElementById(`points-${userId}`).classList.add('bg-secondary'); + } } /** diff --git a/quizbowl/Player.js b/quizbowl/Player.js index eb0333f62..e52c1d346 100644 --- a/quizbowl/Player.js +++ b/quizbowl/Player.js @@ -5,6 +5,7 @@ class Player { this.teamId = undefined; this.username = ''; + this.buzzes = 0; this.powers = 0; this.tens = 0; this.zeroes = 0; @@ -24,6 +25,7 @@ class Player { } clearStats () { + this.buzzes = 0; this.powers = 0; this.tens = 0; this.zeroes = 0; @@ -63,6 +65,14 @@ class Player { } } + /** + * Returns true if the player has recorded any stats or buzzes. + * @returns {boolean} + */ + hasActivity () { + return this.tuh > 0 || this.buzzes > 0 || this.powers > 0 || this.tens > 0 || this.zeroes > 0 || this.negs > 0; + } + /** * Safely update the player's username, and return the new username. * @param {string} username diff --git a/quizbowl/Room.js b/quizbowl/Room.js index 9dd165db1..f49d79fe8 100644 --- a/quizbowl/Room.js +++ b/quizbowl/Room.js @@ -37,11 +37,18 @@ export default class Room { } leave (userId) { - // this.deletePlayer(userId); - this.players[userId].online = false; + if (!this.players[userId]) { return; } + const player = this.players[userId]; + const username = player.username; delete this.sockets[userId]; - const username = this.players[userId].username; - this.emitMessage({ type: 'leave', userId, username }); + if (!player.hasActivity()) { + delete this.players[userId]; + delete this.teams[userId]; + this.emitMessage({ type: 'leave', userId, username, remove: true }); + } else { + player.online = false; + this.emitMessage({ type: 'leave', userId, username }); + } } /** diff --git a/quizbowl/TossupRoom.js b/quizbowl/TossupRoom.js index 73cae6779..25e012c23 100644 --- a/quizbowl/TossupRoom.js +++ b/quizbowl/TossupRoom.js @@ -70,6 +70,7 @@ export const TossupRoomMixin = (QuestionRoomClass) => class extends QuestionRoom clearTimeout(this.timeoutID); this.buzzedIn = userId; this.buzzes.push(userId); + this.players[userId].buzzes++; this.buzzpointIndices.push(this.questionSplit.slice(0, this.wordIndex).join(' ').length); this.paused = false;