The chat application is built on Node.js utilizing Socket.io and express for real-time client-server communication. The software is designed to handle up to 3 users and the chat doesn’t start unless there’s a minimum of 3 users connected.The issue lies in the timer logic in the chat application. The timer is supposed to start only when the minimum number of users (3 users) is connected. However, the timer appears to start even with fewer users when a user disconnevts.We have revised the code to ensure checks for minimum users before starting the timer, specifically within the ‘disconnect’, ‘set-username’, and ‘Input Submit’ events. But it seems the timer is still activating with fewer users starting immediatly after the third user leaves the room but freezing when it reaches 1 second , important to note that we didn’t test by sending messages we tested by the timer display each user is given 20 seconds to write a message if the timer displayes this means its the user turn There might possibly be an issue with the scope of the variable that is controlling the timer activation (‘TimerActive’) or the way the timer is initialized and cleared.The goal is to ensure that the timer function (startTurnTimer) only activates when the minimum number of users is connected, and when user disconnects, timer should restart if remaining connected users equal or exceed the minimum, or halt otherwise
const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server);
app.use(express.static('public'));
let connectedUsers = [];
let maxUsers = 3; // max users allowed
let minUsers =3; //minimum users for the game to start
let turnIndex = 0;
let turnTimer = null;
let TimerActive=false;
const turnTimeout = 20; // 20 seconds
function startTurnTimer() {
let remainingTime = turnTimeout;
TimerActive = true; // Set timer activity to true, as it started
turnTimer = setInterval(() => {
remainingTime--;
if (remainingTime <= 0) {
io.to(connectedUsers[turnIndex].id).emit('turn-timeout');
NextTurn();
} else {
io.to(connectedUsers[turnIndex].id).emit('timer', remainingTime);
}
}, 1000); // Update timer every second
}
function IsMinimum () {
if (connectedUsers.length >= minUsers) {
return true;
} else {
return false;
}
}
function IsTurn (SocketID){
if (connectedUsers[turnIndex] && SocketID === connectedUsers[turnIndex].id){
return true;
} else{
return false;
}
}
function NextTurn (){
if (connectedUsers.length === 0) {
return;
}
turnIndex = (turnIndex + 1) % connectedUsers.length;
}
io.on('connection', (socket) => {
if (connectedUsers.length >= maxUsers) {
console.log('Chat is full, rejecting connection.');
// Immediately emit a "chat full" event to the new user
socket.emit('full');
socket.disconnect(true); // Disconnect the user
return;
}else{
socket.emit('joined'); /* verify that a user joined */
//let CurrentUser="";
socket.on('set-username', (username) => {
//CurrentUser=username;
const user = { id: socket.id, username: username };
connectedUsers.push(user);
console.log('A user connected!', connectedUsers);
socket.emit('user-count', connectedUsers.length);
socket.broadcast.emit('user-count', connectedUsers.length);
//if the game has the minimum no. of users and a timer has not previously started
if (IsMinimum() && !TimerActive) { //when no timer is already active to avoid multiple timers
startTurnTimer();
}
});
// Listen for chat messages from clients
socket.on('Input Submit', (msg) => {
let UsersCheck=IsMinimum(); //check if the minimum no. of users are connected already
let TurnCheck = IsTurn(socket.id); //check if it is the user's turn to send a message
//first we will check that the minimum no. of users is at least the max no. specified above
if (UsersCheck === true) {
io.emit('all_users_connected');
if (TurnCheck === true) {
io.emit('Input Submit', {
msg
});
NextTurn(); //go to the next turn
startTurnTimer();
} else {
console.log('It is not your turn to send a message.');
socket.emit('no_turn');
}
} else {
socket.emit('no_users');
}
/* io.emit('Input Submit', { msg }); */
}
);
socket.on('disconnect', () => {
//if it is his turn move to the next turn before deleting him
if (IsTurn(socket.id)) {
NextTurn();
}
// Reset the timer
clearInterval(turnTimer);
turnTimer = null;
TimerActive = false;
if (IsMinimum()) {
startTurnTimer();
}
// Remove the disconnected user from the array
connectedUsers = connectedUsers.filter(user => user.id !== socket.id);
// Emit updated user count to all clients
io.emit('user-count', connectedUsers.length);
socket.broadcast.emit('user-count', connectedUsers.length);
console.log('A user disconnected!');
});
}
});
server.listen(5000, () => {
console.log(' Server listening on port 3000');
});
I tried refining the logic when a user disconnect multiple times adding more flags and checks but something else is triggering the timer
Amir Amgad is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.