diff --git a/README.md b/README.md index 2096d85..0e1f6f1 100644 --- a/README.md +++ b/README.md @@ -12,4 +12,5 @@ npm install socket.io npm install mysql npm install sanitizer npm install google-trends-api +npm install promise ```` \ No newline at end of file diff --git a/googletrendsgame/server/server.js b/googletrendsgame/server/server.js index 273fd20..e121119 100644 --- a/googletrendsgame/server/server.js +++ b/googletrendsgame/server/server.js @@ -1,41 +1,164 @@ -var app = require('express')(); -var http = require('http').Server(app); -var io = require('socket.io')(http); +const serverUtils = require('./serverUtils.js'); -const port = 3000; +const utils = require("./utils.js"); -var room = function(capacityP, roomN) +/** + * Object used for storing rooms + * @param capacityP -- the number of people that can be in room + * @param pass -- the room password -- null if none + * @param owner -- the person who is creating the room + */ +var room = function(capacityP, pass, owner) { //max capacity of room -- default is 4 for now this.capacity = capacityP; //name of the room - this.roomName = roomN; + this.roomName = owner.name; + + this.addUser(owner); //list of words used in the game - this.words = []; + //7 for now will change later to be room specific + this.words = utils.getRandomWords(7); + + this.currentWord = this.words.pop(); - //list of clients sockets -- so we can push requests to them + //list players -- so we can push requests to them this.users = []; //increments when rounds pass - this.currentRoom = 0; + this.currentRound = 0; + + // the password of the room -- null if no password + this.password = null; + + /** + 1 = Waiting for users + 2 = Word shown, Waiting for response from users + 3 = Showing Result + 4 = Game Over, Display Final Results + */ + this.state = 1; /** * adds a user to a room - * @param socket + * @param p + * return 0 if they could join + */ + this.addUser = function(player) + { + //check if room is not full + this.users.push(player); + player.room = this; + + if(this.users.length == this.capacity) + { + this.state = 2; + } + + this.sendRoomUpdate(); + + } + + this.sendRoomUpdate = function() + { + var message = this.generateRoomUpdate(); + this.users.forEach(function(u) + { + u.socket.emit('roomUpdate', message); + }); + } + + /** + * Removes a specific user from the room and adjusts the size of the array + * if the array is empty, the room closes + * @param p + */ + this.removeUser = function(p) + { + var temp = new Array(); + + for(var i = 0; i < temp.length; i++) + { + if(p.name === this.users[i].name) + { + + } + else + { + temp.push(this.users[i]); + } + } + + this.users = temp; + + //if room is empty remove the room from rooms list + if(this.users.length == 0) + { + rooms[this.roomName] = null; + } + } + + /** + * creates json to send in the 'roomUpdate' socket event + * + * {users: gameState: roundWinner: currentWord: } */ - this.addUser = function(socket) + this.generateRoomUpdate = function() + { + var result = new Object(); + result.users = []; + this.users.forEach(function(u) + { + result.users.push(u.genJASON()); + }); + + result.gameState = this.state; + + result.roundWinner = "meh"; + + result.currentWord = this.currentWord; + + return result; + } + + /** + * Whether or not a user can join this room -- checks for number of people are + * already in the room and the password + * @param p + * @returns {boolean} + */ + this.canJoin = function(p) + { + if(this.password == null) + { + return (this.users.length < this.capacity); + } + else + { + return (this.users.length < this.capacity) && (p === this.password); + } + } + + //updates room variables + this.update = function() { } } -var player = function(name) +//list of all the rooms +var rooms = {}; + +var player = function(s) { //name of the user - this.name = name; + this.name = null; + + //players socket + this.socket = s; //score of the player this.score = 0; @@ -43,28 +166,134 @@ var player = function(name) //reference to the room -- might not need this this.room = null; - - // + //the word the user selected for current round this.sumbission = null; + + /** + * generate the json object used in 'roomUpdate' socket io event + * + * return {name: score: word:} + */ + this.genJASON = function() + { + var result = new Object(); + result.name = this.name; + result.score = this.score; + result.word = this.sumbission; + } + + /** + * data -- literally a string + * @param data + */ + this.selectWord = function(data) + { + this.sumbission = data; + + this.room.update(); + } } +//list of all players --accessed using names like a dic +var players = {}; + + +var app = require('express')(); +var http = require('http').Server(app); +var io = require('socket.io')(http); + +const port = 3000; -//list of all the rooms -var rooms = []; //Whenever someone connects this gets executed io.on('connection', function(socket) { + var player = new player(socket); + console.log('A user connected'); + /** + *Register user nickname/handle (register) Client => Server + */ + socket.on('register', function(data) { + console.log("Register event called"); + console.log(data); + console.log(" "); + + //checks for user name in use + if(serverUtils.userAvailable(data, players)) + { + player.name = data; - socket.on('clientEvent', function(data) { + players[data] = player; + + socket.emit('sendRooms', serverUtils.generateSendRoomsJSON(rooms)); + } + else + { + socket.emit('registerFailed', 'User name taken'); + } + }); + + /** + *Create Room (createRoom) Client => Server + * data {password: , capacity: } + */ + socket.on('createRoom', function(data) { + console.log("create room event called"); + console.log(data); + console.log(" "); + rooms[player.name] = new room(data.capacity, data.password, player); + + + }); + + /** + * Room Selection (joinRoom) Client => Server + * data {roomName: , password: } + */ + socket.on('joinRoom', function(data) { + console.log("join room event called"); console.log(data); + console.log(" "); + + if(rooms[data.roomName].canJoin(data.password)) + { + rooms[data.roomName].addUser(player); + } + else + { + socket.emit('registerFailed', 'Failed connecting to room'); + } }); + /** + * data -- literally a string + */ + socket.on('submitWord', function(data) { + console.log("submitWord called"); + console.log(data); + console.log(" "); - //Whenever someone disconnects this piece of code executed + player.selectWord(data); + }); + + //Whenever someone disconnects socket.on('disconnect', function () { console.log('A user disconnected'); + + if(rooms[player.name] != null) + { + rooms[player.name] = null; + } + + //leave the room + if(player.room != null) + { + player.room.removeUser(player); + } + + players[player.name] = null; + }); }); diff --git a/googletrendsgame/server/serverUtils.js b/googletrendsgame/server/serverUtils.js new file mode 100644 index 0000000..cef83f9 --- /dev/null +++ b/googletrendsgame/server/serverUtils.js @@ -0,0 +1,65 @@ +module.exports= + { + /** + * Returns a random word + * @returns {string} + */ + roomOpen : function(name, rooms) + { + rooms.foreach(function(r) + { + if(name === r.roomName) + { + return false; + } + }); + return true; + }, + userAvailable : function(name, players) + { + // players.foreach(function(p) + // { + // if(name === p.roomName) + // { + // return false; + // } + // }); + + if(players[name] != null) + return false + return true; + }, + + generateSendRoomsJSON : function(rooms) + { + var obj = new Object(); + obj.rooms = []; + + rooms.forEach(function(r) + { + var roomObj = new Object(); + + if(r.password.password == null) + { + roomObj.passwordBool = false; + } + else + { + roomObj.passwordBool = r.password; + } + roomObj.capacity = r.capacity; + roomObj.occupents = r.users.length; + + obj.rooms.push(roomObj); + + }); + + return obj; + }, + + getOpenIndex : function(rooms) + { + + } + + }; \ No newline at end of file diff --git a/googletrendsgame/server/trendsAPI.js b/googletrendsgame/server/trendsAPI.js index c3abe26..d359614 100644 --- a/googletrendsgame/server/trendsAPI.js +++ b/googletrendsgame/server/trendsAPI.js @@ -1,9 +1,86 @@ +const googt = require('google-trends-api'); +const Promise = require('promise'); +const DAY = 1000 * 60 * 60 * 24; // 1 day in milliseconds +const YEAR = DAY * 365; // 1 year in milliseconds +const GEO = 'US'; //the scope of the trends +/** +desc: helper function for getYearStats, gets list of popularity for days in +the month. +*/ +function getMonthStats(word, month){ + + return new Promise(function(resolve, reject){ + //set up query for 1 month length + googt.interestOverTime({ + keyword:word, + startTime:new Date(Date.now() - (YEAR * month/12)), + endTime:new Date(Date.now() - (YEAR * (month-1)/12)) + }).then(function(results){ + //parse the json, fill return array w tuples of date + value + var times = JSON.parse(results).default.timelineData; + var ret = []; + for(var i = 0; i < times.length; ++i){ + var tup = new Object(); + tup.time = times[i].formattedTime; + tup.value = times[i].value[0]; + ret[i] = tup; + + } + resolve(ret); + }); + }); +} + module.exports= { + /* + desc: returns an integer score for the word over the day + */ getPopularity: function(word) { - return 0; + //must be a promise since call to trends API is async + return new Promise(function(resolve, reject){ + + //specifies the keyword, time interval, granularity, and region + googt.interestOverTime({keyword:word, + startTime:new Date(Date.now() - DAY),granularTimeResolution:true, + geo:GEO + }) + .then(function(results){ + //turn into json object + data = JSON.parse(results).default.timelineData; + + //add up values + var total = 0; + data.forEach(function(element){ + total += element.value[0]; + }) + + //tell function to return + resolve(total); + }).catch(function(err){ + reject("Google Trends Query Failed"); + }); + }); + }, + + /** + desc: returns a list of tuples (date, value) representing word's + popularity for the past year + */ + getYearStats: async function(word){ + var ret = []; + + for (var i = 9; i > 0; --i) { + await getMonthStats(word,i).then(function(data){ + ret = ret.concat(data); + }); + console.log(i); + } + + return ret; } - }; \ No newline at end of file + + }; diff --git a/googletrendsgame/server/utils.js b/googletrendsgame/server/utils.js index f647cc8..fa2633d 100644 --- a/googletrendsgame/server/utils.js +++ b/googletrendsgame/server/utils.js @@ -12,5 +12,15 @@ module.exports= getRandomWord : function() { return ''; + }, + + /** + * returns a specific amount of words -- unique + * @param num + * @returns {Array} + */ + getRandomWords : function(num) + { + return []; } }; \ No newline at end of file