| @ -1,84 +1,29 @@ | |||||
| <!DOCTYPE html> | |||||
| <html lang="en"> | |||||
| <head> | |||||
| <!-- Meta --> | |||||
| <meta charset="UTF-8" /> | |||||
| <title>Trend Spotter | Game</title> | |||||
| <!-- / --> | |||||
| <!-- Styles --> | |||||
| <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> | |||||
| <link href="https://fonts.googleapis.com/css?family=Josefin+Sans:100,300,400,600,700" rel="stylesheet"> | |||||
| <link href="https://fonts.googleapis.com/css?family=Poppins:100,300,400,500,700,800,900" rel="stylesheet"> | |||||
| <link rel="stylesheet" href="app.css"> | |||||
| <!-- / --> | |||||
| </head> | |||||
| <body> | |||||
| <div class=""> | |||||
| <div class="row w-100"> | |||||
| <div class="col-12"> | |||||
| <div class="logo w-100">trend spot</div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="container-fluid game"> | |||||
| <div class="row"> | <div class="row"> | ||||
| <!-- Main --> | |||||
| <div class="col-8 game__main"> | |||||
| <div class="game__round">Round 4/7</div> | |||||
| <div class="row w-100"> | |||||
| <div class="col-8"> | |||||
| <input class="w-100 game__phrase--entry" type="text"> | |||||
| </div> | |||||
| <div class="col-4"> | |||||
| <div class="game__phrase--clue">car</div> | |||||
| </div> | |||||
| <div class="col-xs-12 col-sm-7"> | |||||
| <a class="logo"> | |||||
| <div>WHAT</div> | |||||
| <div>THE </div> | |||||
| <div>TREND?!</div> | |||||
| </a> | |||||
| <div class="game__main"> | |||||
| <form onSubmit={this.sendNickname}> | |||||
| <input class="login__input" maxLength="30" placeholder="Nickname" /> | |||||
| <span> | |||||
| <button class="game__submit">Let's Play!</button> | |||||
| </span> | |||||
| </form> | |||||
| </div> | </div> | ||||
| <button class="game__submit">Submit my answer!</button> | |||||
| <!--<div class="game__user-score">jesseg89: 20,005 points</div>--> | |||||
| <div class="game__room">You're in <em>dave61's room</em> | 12/20 players</div> | |||||
| <a href="lobby.html" class="game__exit">Leave Game</a> | |||||
| </div> | </div> | ||||
| <!-- / --> | |||||
| <div class="col-xs-12 col-sm-5 game__sidebar"> | |||||
| <canvas class="scene scene--full" id="scene" ></canvas> | |||||
| <div class="col-4 col-sm-3 game__sidebar"> | |||||
| <div class="game__timer">60 seconds</div> | |||||
| <ol class="game__players"> | |||||
| <li class="game__player"> | |||||
| <span class="game__player-name">John Daniels</span> | |||||
| <span class="game__player-score">10,000 points</span> | |||||
| <span class="game__player-ready">X</span> | |||||
| </li> | |||||
| <li class="game__player"> | |||||
| <span class="game__player-name">John Daniels</span> | |||||
| <span class="game__player-score">10,000 points</span> | |||||
| <span class="game__player-ready">X</span> | |||||
| </li> | |||||
| <li class="game__player"> | |||||
| <span class="game__player-name">John Daniels</span> | |||||
| <span class="game__player-score">10,000 points</span> | |||||
| <span class="game__player-ready">X</span> | |||||
| </li> | |||||
| </ol> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | |||||
| <!-- Scripts --> | |||||
| <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> | |||||
| <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script> | |||||
| <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script> | |||||
| <script src="scripts/index.js"></script> | |||||
| <!-- / --> | |||||
| </body> | |||||
| </html> | |||||
| </div> | |||||
| @ -0,0 +1,14 @@ | |||||
| <div class="container"> | |||||
| <div class="row"> | |||||
| <ul> | |||||
| {for room in rooms} | |||||
| <li class="lobby__room"> | |||||
| <span class="lobby__room-name">{room.name}</span> | |||||
| <span class="lobby__room-occupancy">{room.occupancy}</span> | |||||
| <span class="lobby__room-status">{room.status}</span> | |||||
| </li> | |||||
| {/for} | |||||
| </ul> | |||||
| </div> | |||||
| <button>Create Room<button> | |||||
| </div> | |||||
| @ -0,0 +1,73 @@ | |||||
| //gets the trending data | |||||
| const trendingAPI = require("./trendsAPI.js"); | |||||
| class Player | |||||
| { | |||||
| constructor(s) | |||||
| { | |||||
| //name of the user | |||||
| this.name = null; | |||||
| //players socket | |||||
| this.socket = s; | |||||
| //score of the player | |||||
| this.score = 0; | |||||
| //reference to the room -- might not need this | |||||
| this.room = null; | |||||
| //the word the user selected for current round | |||||
| this.submission = ''; | |||||
| this.roundScore = 0; | |||||
| //logs the user data so we can record it to data base at end of round | |||||
| this.log = []; | |||||
| } | |||||
| /** | |||||
| * generate the json object used in 'roomUpdate' socket io event | |||||
| * | |||||
| * return {name: score: word:} | |||||
| */ | |||||
| genJASON() | |||||
| { | |||||
| var result = new Object(); | |||||
| result.name = this.name; | |||||
| result.score = this.score; | |||||
| result.word = this.submission; | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * data -- literally a string | |||||
| * @param data | |||||
| */ | |||||
| selectWord(data) | |||||
| { | |||||
| var w = data + " " + this.room.currentWord; | |||||
| this.submission = data; | |||||
| //console.log(w); | |||||
| this.room.update(); | |||||
| return new Promise(function(resolve, reject) | |||||
| { | |||||
| trendingAPI.getPopularity(w).then(function(result) | |||||
| { | |||||
| console.log("api result for " + result + w); | |||||
| resolve(result); | |||||
| }).catch(function(err){ | |||||
| console.log(err); | |||||
| }) | |||||
| }); | |||||
| } | |||||
| } | |||||
| module.exports = Player; | |||||
| @ -0,0 +1,281 @@ | |||||
| //used for the getting the word array | |||||
| const utils = require("./utils.js"); | |||||
| /** | |||||
| * 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 | |||||
| */ | |||||
| class Room | |||||
| { | |||||
| constructor(capacityP, pass, owner) | |||||
| { | |||||
| //max capacity of room -- default is 4 for now | |||||
| this.capacity = capacityP; | |||||
| //name of the room | |||||
| this.roomName = owner.name; | |||||
| //list of words used in the game | |||||
| //7 for now will change later to be room specific | |||||
| this.words = utils.getRandomWords(7); | |||||
| this.currentWord = this.words.pop(); | |||||
| //list players -- so we can push requests to them | |||||
| this.users = []; | |||||
| //increments when rounds pass | |||||
| this.currentRound = 0; | |||||
| // the password of the room -- null if no password | |||||
| this.password = pass; | |||||
| /** | |||||
| 1 = Waiting for users | |||||
| 2 = Word shown, Waiting for response from users | |||||
| 3 = Showing Result | |||||
| 4 = Game Over, Display Final Results | |||||
| */ | |||||
| this.state = 1; | |||||
| this.addUser(owner); | |||||
| } | |||||
| /** | |||||
| * generate the json object used in 'roomUpdate' socket io event | |||||
| * | |||||
| * return {name: score: word:} | |||||
| */ | |||||
| genJASON() | |||||
| { | |||||
| var result = new Object(); | |||||
| result.name = this.roomName; | |||||
| result.users = this.users; | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * creates json to send in the 'roomUpdate' socket event | |||||
| * | |||||
| * {users: gameState: roundWinner: currentWord: } | |||||
| */ | |||||
| generateRoomUpdate() | |||||
| { | |||||
| var result = new Object(); | |||||
| result.users = []; | |||||
| this.users.forEach(function(u) | |||||
| { | |||||
| result.users.push(u.genJASON()); | |||||
| }); | |||||
| //sort the users based on score | |||||
| var countOuter = 0; | |||||
| var countInner = 0; | |||||
| var countSwap = 0; | |||||
| // var swapped; | |||||
| // do | |||||
| // { | |||||
| // countOuter++; | |||||
| // swapped = false; | |||||
| // for(var i = 0; i < result.users.length; i++) | |||||
| // { | |||||
| // countInner++; | |||||
| // if(result.users[i].score && result.users[i + 1].score && | |||||
| // result.users[i].score > result.users[i + 1].score) | |||||
| // { | |||||
| // countSwap++; | |||||
| // var temp = result.users[i]; | |||||
| // result.users[i] = result.users[j]; | |||||
| // result.users[j] = temp; | |||||
| // swapped = true; | |||||
| // } | |||||
| // } | |||||
| // } while(swapped); | |||||
| result.gameState = this.state; | |||||
| //sets round winner | |||||
| var rWinner = -1; | |||||
| for(var i = 0; i < this.users.length; i++) | |||||
| { | |||||
| if(rWinner < this.users[i].roundScore) | |||||
| { | |||||
| result.roundWinner = this.users[i].name; | |||||
| rWinner = this.users[i].roundScore; | |||||
| } | |||||
| } | |||||
| result.currentWord = this.currentWord; | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * adds a user to a room | |||||
| * @param p | |||||
| * return 0 if they could join | |||||
| */ | |||||
| addUser(player) | |||||
| { | |||||
| //console.log("user added"); | |||||
| //check if room is not full | |||||
| this.users.push(player); | |||||
| player.room = this; | |||||
| if(this.users.length == this.capacity) | |||||
| { | |||||
| this.state = 2; | |||||
| } | |||||
| console.log("user added to room " + player.name); | |||||
| //console.log(this.users); | |||||
| this.update(); | |||||
| } | |||||
| /** | |||||
| * Removes a specific user from the room and adjusts the size of the array | |||||
| * if the array is empty, the room closes | |||||
| * @param p | |||||
| */ | |||||
| removeUser(p) | |||||
| { | |||||
| console.log("remove users fnc called"); | |||||
| 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) | |||||
| { | |||||
| console.log("room scrubbed"); | |||||
| delete rooms[this.roomName]; | |||||
| } | |||||
| this.update(); | |||||
| } | |||||
| /** | |||||
| * 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} | |||||
| */ | |||||
| canJoin(p) | |||||
| { | |||||
| if(this.password == null) | |||||
| { | |||||
| return (this.users.length < this.capacity); | |||||
| } | |||||
| else | |||||
| { | |||||
| return (this.users.length < this.capacity) && (p === this.password); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * starts new round for the room -- called once all the players have submitted | |||||
| */ | |||||
| newRound() | |||||
| { | |||||
| console.log("new round started"); | |||||
| if(this.words.length == 0) | |||||
| { | |||||
| this.state == 4; | |||||
| } | |||||
| else | |||||
| { | |||||
| this.currentRound++; | |||||
| this.users.forEach(function(u) | |||||
| { | |||||
| u.submission = ''; | |||||
| }); | |||||
| this.currentWord = this.words.pop(); | |||||
| this.state = 2; | |||||
| } | |||||
| this.sendRoomUpdate(); | |||||
| } | |||||
| //updates room variables | |||||
| update() | |||||
| { | |||||
| switch(this.state) | |||||
| { | |||||
| case 1: //waiting for users to join | |||||
| { | |||||
| if(this.users.length == this.capacity) | |||||
| { | |||||
| this.newRound(); | |||||
| } | |||||
| break; | |||||
| } | |||||
| case 2: // waiting for responses | |||||
| { | |||||
| var flag = true; | |||||
| var test = ""; | |||||
| this.users.forEach(function(u) | |||||
| { | |||||
| test+=u.submission; | |||||
| if(u.submission === '') | |||||
| { | |||||
| flag = false; | |||||
| } | |||||
| }); | |||||
| console.log("big stuff " + test); | |||||
| if(flag) | |||||
| { | |||||
| this.state = 3; | |||||
| this.newRound(); | |||||
| // setTimeout(function() { | |||||
| // | |||||
| // }, 4000); | |||||
| } | |||||
| break; | |||||
| } | |||||
| case 3: // showing results -- time out fnc | |||||
| { | |||||
| console.log("error &&&&&&&&&&&&&&&&&&"); | |||||
| break; | |||||
| } | |||||
| case 4: //game over display final result | |||||
| { | |||||
| //sqlStuff.dumpRoom(this); | |||||
| break; | |||||
| } | |||||
| default: | |||||
| { | |||||
| console.log("You don goof up") | |||||
| } | |||||
| } | |||||
| console.log(this.state + " state"); | |||||
| this.sendRoomUpdate(); | |||||
| } | |||||
| } | |||||
| module.exports = Room; | |||||
| @ -0,0 +1,89 @@ | |||||
| const googt = require('google-trends-api'); | |||||
| 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) | |||||
| { | |||||
| //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 | |||||
| console.log("********************" + total); | |||||
| //pl.selectWord2(total); | |||||
| 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; | |||||
| } | |||||
| */ | |||||
| }; | |||||
| @ -0,0 +1,37 @@ | |||||
| var fs = require('fs'); | |||||
| const WORD_FILE_PATH = '../../words/words.txt'; | |||||
| //loads words from word file | |||||
| var words = []; | |||||
| var data = fs.readFileSync(WORD_FILE_PATH, 'utf8'); | |||||
| var lines = data.split('\n'); | |||||
| lines.forEach(function(element){ | |||||
| words.push(element); | |||||
| }); | |||||
| module.exports= | |||||
| { | |||||
| /** | |||||
| * returns a specific amount of words -- unique | |||||
| * @param num the number of words | |||||
| * @returns {Array} the random, unique words | |||||
| */ | |||||
| getRandomWords : function(num) | |||||
| { | |||||
| var rwords = []; | |||||
| for(var i = 0; i < num; ++i){ | |||||
| var randindex = Math.round((Math.random() * (words.length - 1))); | |||||
| var newword = words[randindex]; | |||||
| var uniq = true; | |||||
| rwords.forEach(function(element){ | |||||
| if(newword === element){ | |||||
| --i; | |||||
| uniq = false; | |||||
| } | |||||
| }); | |||||
| if(uniq)rwords.push(newword); | |||||
| } | |||||
| return rwords; | |||||
| } | |||||
| }; | |||||