Add files via upload
This commit is contained in:
218
api/sockets/broadcasting.js
Normal file
218
api/sockets/broadcasting.js
Normal file
@@ -0,0 +1,218 @@
|
||||
const user = require("../models/user");
|
||||
const matching = require("../models/matching");
|
||||
const socketModel = require("../models/socketModel");
|
||||
const filter = require("../models/filter");
|
||||
|
||||
// Used to keep track of who is connected and know their socket
|
||||
const connectedUsers = new Map();
|
||||
let matchingQueue = [];
|
||||
|
||||
function broadcasting(io){ // For connection and disconnection
|
||||
|
||||
io.on("connection", async (socket) => {
|
||||
|
||||
const connectedUserId = socket.handshake.query.userId;
|
||||
|
||||
if(!connectedUserId){
|
||||
socket.emit(`error_user_connected`, {msg:`Invalid connected user id ${connectedUserId}.`});
|
||||
return;
|
||||
}
|
||||
|
||||
if(!connectedUsers.has(connectedUserId)){
|
||||
connectedUsers.set(connectedUserId, socket.id);
|
||||
|
||||
// Check if entry exists in the db
|
||||
const socketInfo = await socketModel.findOne({userId:connectedUserId}).exec();
|
||||
if(socketInfo){
|
||||
if(socketInfo.socketId !== socket.socketId){
|
||||
await socketModel.updateOne({userId:connectedUserId}, {socketId:socket.id}).exec();
|
||||
}
|
||||
}else{
|
||||
await new socketModel({
|
||||
userId: connectedUserId,
|
||||
socketId: socket.id
|
||||
}).save();
|
||||
}
|
||||
|
||||
// save in database
|
||||
socket.emit(`success_user_connected`, {msg:`User with id ${connectedUserId} CONNECTED.`});
|
||||
}else{
|
||||
socket.emit(`error_user_connected`, {msg:`User with id ${connectedUserId} is already connected.`});
|
||||
}
|
||||
|
||||
/* MATCHING */
|
||||
|
||||
socket.on('find_matching', async (findMatchDTO) => {
|
||||
|
||||
// In case user id is invalid.
|
||||
if(!findMatchDTO.userId){
|
||||
socket.emit('error_find_matching',{msg:'User id is invalid.'});
|
||||
return;
|
||||
}
|
||||
if(!findMatchDTO.filters){
|
||||
socket.emit('error_find_matching', {msg:"Filters are invalid."});
|
||||
return;
|
||||
}
|
||||
|
||||
// In case user id is not found
|
||||
if(!connectedUsers.has(findMatchDTO.userId)){
|
||||
socket.emit('error_find_matching', {msg:'User id does not exist.'});
|
||||
return;
|
||||
}
|
||||
|
||||
socket.emit('success_find_matching', {msg:`User with id ${findMatchDTO.userId} ONLINE.`});
|
||||
|
||||
// Attempting to find a match
|
||||
let matchFound = -1;
|
||||
const user1 = await user.findOne({_id:findMatchDTO.userId}).exec();
|
||||
const user1Filters = findMatchDTO.filters;
|
||||
for(let i = 0; i < matchingQueue.length && matchFound == -1; i++){
|
||||
var user2Id = matchingQueue[i];
|
||||
matching.countDocuments( {$or: [ { $and:[ {'firstUser': findMatchDTO.userId}, {'secondUser': user2Id} ]}, { $and:[ {'firstUser': user2Id}, {'secondUser': findMatchDTO.userId} ]}]}).exec().then( count => {
|
||||
if(!count){
|
||||
user.findOne({_id:user2Id}).exec().then( user2 => {
|
||||
filter.findOne({userId:user2Id}).exec().then( user2Filters => {
|
||||
|
||||
// Region Matched
|
||||
const regionMatched = (user1.region === user2Filters.serverPreference) && (user2.region === user1Filters.serverPreference);
|
||||
|
||||
// Game Mode Type
|
||||
const playerTypeMatched = (user1.playerType === user2Filters.gameMode) && (user2.playerType === user1Filters.gameMode);
|
||||
|
||||
// Rank Macthed
|
||||
const rankMatchedUser1 = (user1.rank[0] >= user2Filters.rankDisparity[0] && user1.rank[0] <= user2Filters.rankDisparity[2]);
|
||||
const rankMatchedUser2 = (user2.rank[0] >= user1Filters.rankDisparity[0] && user2.rank[0] <= user1Filters.rankDisparity[2]);
|
||||
const rankMatched = rankMatchedUser1 && rankMatchedUser2;
|
||||
|
||||
// Age Matched
|
||||
const ageMatched = (user1.age >= user2Filters.ageRange[0] && user1.age <= user2Filters.ageRange[1]) &&
|
||||
(user2.age >= user1Filters.ageRange[0] && user2.age <= user1Filters.ageRange[1]);
|
||||
|
||||
// Gender Matched
|
||||
let genderMatched = false;
|
||||
if(user1.gender !== -1 && user2.gender !== -1){
|
||||
genderMatched = user2Filters.genders[user1.gender] && user1Filters.genders[user2.gender];
|
||||
}
|
||||
|
||||
// They are match based on filters...
|
||||
if(regionMatched && playerTypeMatched && rankMatched && ageMatched && genderMatched){
|
||||
|
||||
// Notify each user of the match and remove the matched user from queue
|
||||
socket.emit('match_found', {user:user2});
|
||||
|
||||
if(!connectedUsers.has(user2Id)){
|
||||
socketModel.findOne({userId:receiverId}).exec().then( socketInfo => {
|
||||
if(socketInfo){
|
||||
connectedUsers.set(socketInfo.userId, socketInfo.socketId);
|
||||
io.to(socketInfo.socketId).emit('match_found', {user:user1});
|
||||
}
|
||||
});
|
||||
}else{
|
||||
io.to(connectedUsers?.get(user2Id)).emit('match_found', {user:user1}); // TODO: add DB call if not in there
|
||||
}
|
||||
|
||||
// Store matching in the DB
|
||||
const newMatch = new matching({
|
||||
firstUser: findMatchDTO.userId,
|
||||
secondUser: user2Id,
|
||||
});
|
||||
newMatch.save();
|
||||
|
||||
// Remove matched user from queue
|
||||
matchingQueue = immutableRemove(matchFound, matchingQueue);
|
||||
matchFound = i;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
if(matchFound === -1){
|
||||
matchingQueue.push(findMatchDTO.userId);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('stop_matching', (userId) => {
|
||||
// In case user id is invalid.
|
||||
if(!userId){
|
||||
socket.emit('error_stop_matching',{msg:'User id is invalid.'});
|
||||
return;
|
||||
}
|
||||
|
||||
// In case user id is not found
|
||||
if(!connectedUsers.has(userId)){
|
||||
socket.emit('error_stop_matching', {msg:'User id does not exist.'});
|
||||
return;
|
||||
}
|
||||
|
||||
// Removing user from the matching queue
|
||||
matchingQueue = immutableRemove(matchingQueue.indexOf(userId), matchingQueue);
|
||||
|
||||
socket.emit('success_stop_matching', {msg:`User with id ${userId} OFFLINE`});
|
||||
});
|
||||
|
||||
/* CHAT */
|
||||
socket.on("send_msg" , async (receiverId, msg) => { // msg = Text
|
||||
|
||||
if(!receiverId){
|
||||
socket.emit('error_send_msg', {msg:"Invalid receiver id."});
|
||||
return;
|
||||
}
|
||||
|
||||
if(!connectedUsers.has(receiverId)){
|
||||
|
||||
// Check if it exists in DB
|
||||
const socketInfo = await socketModel.findOne({userId:receiverId}).exec();
|
||||
|
||||
if(!socketInfo){
|
||||
socket.emit('error_send_msg', {msg:"User with that id is not online."})
|
||||
return;
|
||||
}else{
|
||||
connectedUsers.set(receiverId, socketInfo.socketId);
|
||||
io.to(socketInfo.socketId).emit("receive_msg", {msg:msg});
|
||||
}
|
||||
|
||||
}else{
|
||||
io.to(connectedUsers?.get(receiverId)).emit("receive_msg", {msg:msg});
|
||||
}
|
||||
});
|
||||
|
||||
/* DISCONNECT*/
|
||||
socket.on("disconnect", (socket) => {
|
||||
|
||||
const connectedUserId = getUserIdFromSocketId(socket.id);
|
||||
if(!connectedUserId) return;
|
||||
|
||||
// Remove user from map
|
||||
if(connectedUsers.has(connectedUserId)){
|
||||
connectedUsers.delete(connectedUserId);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* HELPER FUNCTIONS */
|
||||
|
||||
function getUserIdFromSocketId(socketId){
|
||||
let userId = "";
|
||||
for (let [uId, info] of connectedUsers) {
|
||||
if(info.socketId === socketId){
|
||||
userId = uId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return userId;
|
||||
}
|
||||
|
||||
function immutableRemove(idx, array){
|
||||
|
||||
if(idx < 0 || idx >= array.length) return array;
|
||||
|
||||
newArray = [];
|
||||
for(let i = 0; i < array.length; i++){
|
||||
if(idx !== i) newArray.push(array[i]);
|
||||
}
|
||||
return newArray;
|
||||
}
|
||||
|
||||
module.exports = { broadcasting };
|
||||
Reference in New Issue
Block a user