Click here to Skip to main content
15,892,965 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
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


JavaScript
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');
});


What I have tried:

i tried multiple things and there is one that partially works ,i separated the code that cleared the timer into its own function and now it solved the issue of timer state not changing after the third user reconnects but there are multiples of issues 1- even when no diconnection happens it appears that the timer is not taking next turns it only executes for the first user and freezes when it reaches 1 and does not move to the next user 2- it appears when i try to diconnect a third user the timer still immediatly starts and takes next turn for a next user until the timer reaches 1 and it doesn't move to the next user 3- when i attempt to reconnect the third user the timer restarts but only for one turn and then it reaches 1 and freezes repeating the same behavior

JavaScript
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;

}

function clearTurnTimer() {
  if (turnTimer) {
    clearInterval(turnTimer);
    turnTimer = null;
    TimerActive = false;
  }
}


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); 

      clearTurnTimer();
      //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
    clearTurnTimer();

    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');
});
Posted
Updated 26-Apr-24 3:43am

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900