1
0
Fork 0
avalon-meteor/avalon.js

1175 lines
32 KiB
JavaScript

Games = new Mongo.Collection("games");
Players = new Mongo.Collection("players");
// A round is one of the 5 game rounds.
Rounds = new Mongo.Collection("rounds");
// Each round contains one or more votes.
Votes = new Mongo.Collection("votes");
// Each vote has a player vote from each player.
PlayerVotes = new Mongo.Collection("playerVotes");
if (Meteor.isClient) {
Template.body.created = function () {
Session.set("currentView", "startMenu");
};
Template.main.helpers({
whichView: function () {
return Session.get("currentView");
}
});
Template.startMenu.events({
"click .button-new-game": function (event) {
Session.set("currentView", "newGame");
},
"click .button-join-game": function (event) {
Session.set("currentView", "joinGame");
}
});
Template.newGame.events({
"click .button-main-menu": function (event) {
Session.set("currentView", "startMenu");
},
'submit .new-game-form': function (event) {
event.preventDefault();
var playerName = $(event.currentTarget).find('.name-input').val();
if (!playerName) {
return false;
}
var game = generateNewGame();
var player = generateNewPlayer(game, playerName);
Meteor.subscribe('games', game.accessCode);
Session.set("loading", true);
Meteor.subscribe('players', game._id, function onReady() {
Session.set("loading", false);
Session.set("gameID", game._id);
Session.set("playerID", player._id);
Session.set("currentView", "lobby");
});
Meteor.subscribe('rounds', game._id)
Meteor.subscribe('votes', game._id)
Meteor.subscribe('playerVotes', game._id)
Tracker.autorun(trackGameState);
}
});
Template.newGame.helpers({
track: function () {
trackGameState();
},
trackPlayers: function () {
trackPlayersState();
}
});
Template.joinGame.events({
"click .button-main-menu": function (event) {
Session.set("currentView", "startMenu");
},
'submit .join-game-form': function (event) {
event.preventDefault();
var code = $(event.currentTarget).find('.code-input').val();
var name = $(event.currentTarget).find('.name-input').val();
if (!name){
return false;
}
code = code.trim().toLowerCase();
var game = Games.findOne({ accessCode: code });
Session.set("loading", true);
Meteor.subscribe('games', code, function onReady() {
Session.set("loading", false);
var game = Games.findOne({ accessCode: code });
if (game.state === 'lobby') {
Meteor.subscribe('players', game._id, function onReady() {
var sameNamePlayer = Players.findOne({ gameID: game._id, name: name });
$('.alert-game-started').hide();
if (sameNamePlayer) {
$('.alert-unique-name').show();
return false;
} else {
$('.alert-unique-name').hide();
}
player = generateNewPlayer(game, name);
Meteor.setInterval(function() {
Players.update(player._id, { $set: { keepAlive: Date.now() } });
}, 1000)
Meteor.subscribe('rounds', game._id)
Meteor.subscribe('votes', game._id)
Meteor.subscribe('playerVotes', game._id)
Session.set("gameID", game._id);
Session.set("playerID", player._id);
Session.set("currentView", "lobby");
});
} else if (game) {
Meteor.subscribe('players', game._id, function onReady() {
var sameNamePlayer = Players.findOne({ gameID: game._id, name: name });
$('.alert-unique-name').hide();
if (sameNamePlayer) {
// Only allow rejoins for players that have been
// disconnected for at least 10 seconds (10000
// milliseconds).
if (Date.now() - sameNamePlayer.keepAlive > 10000) {
$('.alert-game-started').hide();
$('.alert-player-connected').hide();
player = sameNamePlayer;
} else {
$('.alert-game-started').show();
$('.alert-player-connected').show();
return false;
}
} else {
$('.alert-player-connected').hide();
$('.alert-game-started').show();
}
Meteor.setInterval(function() {
Players.update(player._id, { $set: { keepAlive: Date.now() } });
}, 1000)
Meteor.subscribe('rounds', game._id)
Meteor.subscribe('votes', game._id)
Meteor.subscribe('playerVotes', game._id)
Session.set("gameID", game._id);
Session.set("playerID", player._id);
Session.set("currentView", "lobby");
});
} else {
//invalid code validation here
return false;
}
});
Tracker.autorun(trackGameState);
}
});
Template.lobby.events({
"click .button-start":function () {
var game = getCurrentGame();
var players = Players.find({'gameID': game._id});
if (players.count() < 3) {
$('.player-alert-5').show();
$('.player-alert-10').hide();
return false;
}
if (players.count() > 10) {
$('.player-alert-10').show();
$('.player-alert-5').hide();
return false;
}
assignTurnOrder(players);
players = Players.find({'gameID': game._id}, {'sort': {'ord': 1}});
assignTeams(players);
assignSpecialRoles(players, game);
generateNewRound(game, 0);
Games.update(game._id, {$set: {state: 'rolePhase'}});
},
"click .button-leave":function () {
var game = getCurrentGame();
Games.update(game._id, {$set: {numPlayers: game.numPlayers - 1}});
Session.set("currentView", "startMenu");
Players.remove(getCurrentPlayer()._id);
Session.set("playerID", null);
Session.set("gameID", null);
},
"click .displayHistory":function () {
var game = getCurrentGame();
Games.update(game._id, {$set: {displayHistory: ! game.displayHistory}});
},
"click .merlin":function () {
var game = getCurrentGame();
Games.update(game._id, {$set: {merlin: ! game.merlin}});
},
"click .assassin":function () {
var game = getCurrentGame();
Games.update(game._id, {$set: {assassin: ! game.assassin}});
},
"click .morgana":function () {
var game = getCurrentGame();
Games.update(game._id, {$set: {morgana: ! game.morgana}});
},
"click .mordred":function () {
var game = getCurrentGame();
Games.update(game._id, {$set: {mordred: ! game.mordred}});
},
"click .percival":function () {
var game = getCurrentGame();
Games.update(game._id, {$set: {percival: ! game.percival}});
}
});
Template.lobby.helpers({
game: function () {
return getCurrentGame();
},
code: function () {
return getAccessCode();
},
players: function () {
var game = getCurrentGame();
if (!game) { return null; }
var players = Players.find({'gameID': game._id}, {'sort': {'ord': 1}}).fetch();
return players;
},
displayHistory: function () {
return getCurrentGame().displayHistory;
},
merlin: function () {
return getCurrentGame().merlin;
},
assassin: function () {
return getCurrentGame().assassin;
},
morgana: function () {
return getCurrentGame().morgana;
},
mordred: function () {
return getCurrentGame().mordred;
},
percival: function () {
return getCurrentGame().percival;
}
});
Template.score.helpers({
game: function () {
return getCurrentGame();
},
code: function () {
return getAccessCode();
},
missionNum: function (object) {
var game = getCurrentGame();
var numPlayers = missionNumPlayers(object.hash.round, game.numPlayers);
if (!numPlayers) {return null;}
if (numPlayers[1] === 2) {
return numPlayers[0] + "*";
} else {
return numPlayers[0];
}
},
roundFinished: function (object) {
var game = getCurrentGame();
var param = "result" + object.hash.round;
if (game[param] === "pass") {
return "pass";
} else if (game[param] === "fail"){
return "fail";
} else {
return null;
}
}
});
Template.roleInfo.helpers({
player: function () {
return getCurrentPlayer();
},
team: function () {
return capitalize(getCurrentPlayer().team);
},
role: function () {
var role = getCurrentPlayer().role;
if (!role) {
role = "normal";
}
return capitalize(role);
},
isSpy: function () {
return (getCurrentPlayer().team === "spy");
},
isMerlin: function () {
return (getCurrentPlayer().role === "merlin");
},
isAssassin: function () {
return (getCurrentPlayer().role === "assassin");
},
isPercival: function () {
return (getCurrentPlayer().role === "percival");
},
isMorgana: function () {
return (getCurrentPlayer().role === "morgana");
},
isMordred: function () {
return (getCurrentPlayer().role === "mordred");
},
gameHasMordred: function () {
return !!Players.findOne({gameID: getCurrentGame()._id, role: 'mordred'});
},
possibleMerlins: function () {
var result = [];
var merlins = Players.find({
$and: [
{'gameID': getCurrentGame()._id},
{$or :[
{'role': 'merlin'},
{'role': 'morgana'}
] }
]
}, {sort: {'name': 1}});
merlins.forEach(function (player) {
result.push(player.name);
});
return result.join(' or ');
},
allSpies: function () {
var game = getCurrentGame();
var currentPlayer = getCurrentPlayer();
if (!game) { return null; }
var players = Players.find({'gameID': game._id}, {'sort': {'ord': 1}}).fetch();
var spies = [];
players.forEach(function (player) {
if (player.team === "spy" && player._id !== currentPlayer._id
&& !(currentPlayer.role == "merlin" && player.role == "mordred")) {
spies.push(player);
}
});
return spies;
}
});
Template.rolePhase.events({
'click button': function () {
var player = getCurrentPlayer();
Players.update(player._id, {$set: {ready: "ready"}});
Tracker.autorun(trackPlayersState);
}
});
Template.rolePhase.helpers({
player: function () {
return getCurrentPlayer();
},
players: function () {
var game = getCurrentGame();
if (!game) { return null; }
var players = Players.find({'gameID': game._id}, {'sort': {'ord': 1}}).fetch();
return players;
},
});
Template.pickPhaseLeader.events({
'click button':function () {
var game = getCurrentGame();
var numChosen = Players.find({'gameID': game._id, 'chosen': true}).count();
var roundMax = missionNumPlayers(game.round, game.numPlayers)[0];
if (numChosen == roundMax) {
var currentVote = getCurrentVote();
var chosen = [];
Players.find({'gameID': game._id})
.fetch()
.forEach(function (player) {
var pv = PlayerVotes.findOne({voteID: currentVote._id, ord: player.ord});
if(player.chosen) {
chosen.push(player.ord);
pv.classes.push("chosen");
} else {
pv.classes = _.without(pv.classes, "chosen");
}
PlayerVotes.update(pv._id, { $set: { chosen: player.chosen, classes: pv.classes } });
});
Votes.update(currentVote._id, { $set: { chosen: chosen, status: "voting" }});
Games.update(game._id, {$set: {state: "votingPhase"}});
}
}
});
Template.pickPhaseLeader.helpers({
players: function () {
var game = getCurrentGame();
if (!game) { return null; }
var players = Players.find({'gameID': game._id}, {'sort': {'ord': 1}}).fetch();
return players;
},
pickMax: function () {
var game = getCurrentGame();
var numChosen = Players.find({'gameID': game._id, 'chosen': true}).count();
var roundMax = missionNumPlayers(game.round, game.numPlayers)[0];
return numChosen == roundMax;
},
voteRejected: function () {
return getCurrentGame().voteRejected;
}
});
Template.pickPhase.helpers({
player: function () {
return getCurrentPlayer();
},
leader: function () {
return getCurrentGame().leader;
},
chosen: function () {
return getCurrentPlayer().chosen;
},
chosenPlayers:function () {
var game = getCurrentGame();
var players = Players.find({'gameID': game._id, 'chosen': true}, {'sort': {'ord': 1}}).fetch();
if (!players) { return null; }
return players;
},
voteRejected: function () {
return getCurrentGame().voteRejected;
}
});
Template.player.events({
'click .player':function () {
var game = getCurrentGame();
var numChosen = Players.find({'gameID': game._id, 'chosen': true}).count();
var roundMax = missionNumPlayers(game.round, game.numPlayers)[0];
if (numChosen < roundMax) {
Players.update(this._id, {$set: {chosen: ! this.chosen}});
} else if(this.chosen) {
Players.update(this._id, {$set: {chosen: false}});
}
}
});
Template.player.helpers({
isSpy: function () {
return (this.team === "spy" ? true : false);
}
});
Template.votingPhase.helpers({
isLeader: function () {
var game = getCurrentGame();
var leaderOrd = game.turn % game.numPlayers;
return leaderOrd == getCurrentPlayer().ord;
},
chosenPlayers: function () {
var game = getCurrentGame();
var players = Players.find({'gameID': game._id, 'chosen': true}, {'sort': {'ord': 1}}).fetch();
return players;
},
playersCount: function () {
var game = getCurrentGame();
if (!game) { return null; }
var players = Players.find({ $and: [{vote: {$ne: "accept"}}, {vote: {$ne: "reject"}} ]}).fetch();
return players.length;
},
playerVote: function () {
var player = getCurrentPlayer();
return player.vote;
}
});
Template.votingPhase.events({
'click .button-cancel':function () {
var game = Games.findOne(Session.get("gameID"));
var players = Players.find({'gameID': game._id});
resetVotes(players);
Games.update(game._id, {$set: {state: 'pickPhase'}});
var currentVote = getCurrentVote();
PlayerVotes.find({voteID: currentVote._id}).fetch()
.forEach(function(pv) {
pv.classes = _.without(pv.classes, "chosen");
PlayerVotes.update(pv._id, { $set: { classes: pv.classes } });
});
},
'click .button-accept':function () {
var player = getCurrentPlayer();
Players.update(player._id, {$set: {vote: "accept"}});
},
'click .button-reject':function () {
var player = getCurrentPlayer();
Players.update(player._id, {$set: {vote: "reject"}});
}
});
Template.voteResults.helpers({
exists: function () {
var game = getCurrentGame();
if (!game || game.turn < 1) { return null; }
return true;
},
acceptVoters: function () {
var game = getCurrentGame();
if (!game) { return null; }
var players = Players.find({'gameID': game._id, 'previousVote': 'accept'}, {'sort': {'ord': 1}}).fetch();
return players;
},
rejectVoters: function () {
var game = getCurrentGame();
if (!game) { return null; }
var players = Players.find({'gameID': game._id, 'previousVote': 'reject'}, {'sort': {'ord': 1}}).fetch();
return players;
},
numSabotaged: function () {
var game = getCurrentGame();
if (!game) {return null; }
if (game.prevResult[1] < 1) {
return null;
} else {
if (game.prevResult[1] == 1) {
return "1 spy";
} else {
return game.prevResult[1] + " spies";
}
}
},
missionResult: function () {
var game = getCurrentGame();
if (!game) {return null; }
return (game.prevResult[0] === "fail" ? "failed" : "succeeded");
},
missionExists: function () {
var game = getCurrentGame();
if (!game) {return null;}
return game.prevResult;
}
});
Template.missionPhaseChosen.events({
'click .button-pass':function () {
var player = getCurrentPlayer();
Players.update(player._id, {$set: {mission: "pass"}});
},
'click .button-fail':function () {
var player = getCurrentPlayer();
if (player.team === "spy") {
Players.update(player._id, {$set: {mission: "fail"}});
} else {
Players.update(player._id, {$set: {mission: "pass"}});
}
}
});
Template.missionPhaseChosen.helpers({
mission: function () {
return getCurrentPlayer().mission;
}
});
Template.assassinPhase.events({
'click .assassinate': function () {
var game = getCurrentGame();
var merlin = Players.findOne({'gameID': getCurrentGame()._id, 'role': 'merlin'});
var target = Players.findOne({'gameID': getCurrentGame()._id, 'assassinated': true});
if (merlin._id === target._id) {
Games.update(game._id, {$set: {winner: "spies"}});
} else {
Games.update(game._id, {$set: {winner: "resistance"}});
}
}
});
Template.assassinPhase.helpers({
resistanceMembers: function () {
return Players.find({'team': 'resistance', 'gameID': getCurrentGame()._id});
}
});
Template.assassinPick.events({
'click .player': function () {
var player = Players.findOne({'gameID': getCurrentGame()._id, 'assassinated': true});
if (player) { Players.update(player._id, {$set: {assassinated: false}}); }
Players.update(this._id, {$set: {assassinated: true}});
}
});
Template.assassinPick.helpers({
chosen: function () {
return this.assassinated;
}
});
Template.specialGameOver.helpers({
resistanceWins: function () {
return (getCurrentGame().winner === "resistance");
},
destroyGame: function () {
var game = getCurrentGame();
setInterval(function () {
Games.remove(game._id);
}, 20000);
}
});
Template.gameOver.helpers({
destroyGame: function () {
var game = getCurrentGame();
setInterval(function () {
Games.remove(game._id);
}, 5000);
}
});
Template.history.helpers({
displayHistory: function() {
var game = getCurrentGame();
return game != null && game.displayHistory;
},
players: function() {
return Players.find({'gameID': getCurrentGame()._id}, {'sort': {'ord': 1}});
},
rounds: function() {
return Rounds.find({gameID: getCurrentGame()._id}, {sort: {'round': 1}});
},
votes: function() {
return Votes.find({gameID: getCurrentGame()._id, roundID: this._id}, {sort: {'ord': 1}});
},
playerVotes: function() {
return PlayerVotes.find({gameID: getCurrentGame()._id, voteID: this._id}, {sort: {'ord': 1}});
},
classList: function() {
return this.classes.join(' ');
},
isCompleted: function() {
return this.result == "fail" || this.result == "pass";
},
});
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
Games.remove({});
Players.remove({});
Rounds.remove({});
Votes.remove({});
PlayerVotes.remove({});
});
Meteor.publish('games', function(accessCode) {
return Games.find({"accessCode": accessCode});
});
Meteor.publish('players', function(gameID) {
return Players.find({"gameID": gameID});
});
Meteor.publish('rounds', function(gameID) {
return Rounds.find({"gameID": gameID});
});
Meteor.publish('votes', function(gameID) {
return Votes.find({"gameID": gameID});
});
Meteor.publish('playerVotes', function(gameID) {
return PlayerVotes.find({"gameID": gameID});
});
}
function generateNewGame() {
var game = {
accessCode: generateAccessCode(),
numPlayers: 0,
state: "lobby",
turn: 0,
round: 0,
spyRoundsWon: 0,
resRoundsWon: 0,
displayHistory: true,
};
var gameID = Games.insert(game);
game = Games.findOne(gameID);
return game;
}
function generateAccessCode() {
var code = "";
var alpha = "abcdefghjiklmnopqrstuvwxyz";
for (var i = 0; i < 6; i++) {
code += alpha.charAt(Math.floor(Math.random() * alpha.length));
}
return code;
}
function generateNewPlayer(game, name) {
Games.update(game._id, {$set: {numPlayers: game.numPlayers + 1}});
var player = {
gameID: game._id,
name: name,
ord: game.numPlayers,
keepAlive: Date.now(),
};
var playerID = Players.insert(player);
player = Players.findOne(playerID);
return player;
}
function generateNewVote(game, round, leader) {
var vote = {
gameID: game._id,
roundID: round._id,
ord: Votes.find({roundID: round._id}).count(),
leader: leader,
status: "pending",
}
var voteID = Votes.insert(vote);
var vote = Votes.findOne(voteID);
var players = Players.find({'gameID': game._id}, {'sort': {'ord': 1}});
players.forEach(function (player, index) {
var playerVote = {
gameID: game._id,
roundID: round._id,
voteID: voteID,
ord: player.ord,
classes: player.ord == leader ? ["leader"] : [],
}
PlayerVotes.insert(playerVote);
});
}
function generateNewRound(game, leader) {
var roundNum = game.round + 1;
Games.update(game._id, {$set: {round: roundNum}});
var round = {
gameID: game._id,
round: roundNum,
fails: null,
result: null,
};
var roundID = Rounds.insert(round);
var round = Rounds.findOne(roundID);
generateNewVote(game, round, leader);
return round;
}
function getCurrentGame() {
var gameID = Session.get("gameID");
if (gameID) {
return Games.findOne(gameID);
}
return null;
}
function getCurrentRound() {
var game = getCurrentGame();
if (game) {
return Rounds.findOne({gameID: game._id, round: game.round});
}
return null;
}
function getCurrentVote() {
var round = getCurrentRound();
if(round) {
var votes = Votes.find({'gameID': round.gameID, 'roundID': round._id}, { sort: {'ord': -1} }).fetch();
return votes[0];
}
return null;
}
function getCurrentPlayer() {
var playerID = Session.get("playerID");
if (playerID) {
return Players.findOne(playerID);
}
}
function getAccessCode() {
var game = getCurrentGame();
if (!game) { return; }
return game.accessCode;
}
function shuffle(array){
for(var j, x, i = array.length; i; j = Math.floor(Math.random() * i), x = array[--i], array[i] = array[j], array[j] = x);
return array;
}
function capitalize(string) {
return string.slice(0,1).toUpperCase() + string.slice(1);
}
function assignTurnOrder(players) {
var turnOrder = [];
for(var i = 0; i < players.count(); i++) {
turnOrder.push(i);
}
shuffle(turnOrder);
players.forEach(function (player, index) {
Players.update(player._id, {$set: {
ord: turnOrder.pop()
}});
});
}
function assignTeams(players) {
var teams = [];
switch (players.count()) {
case 3:
teams = ["spy", "resistance", "resistance"];
break;
case 4:
teams = ["spy", "resistance", "resistance", "resistance"];
break;
case 5:
teams = ["spy", "spy",
"resistance", "resistance", "resistance"];
break;
case 6:
teams = ["spy", "spy",
"resistance", "resistance", "resistance", "resistance"];
break;
case 7:
teams = ["spy", "spy", "spy",
"resistance", "resistance", "resistance", "resistance"];
break;
case 8:
teams = ["spy", "spy", "spy",
"resistance", "resistance", "resistance", "resistance", "resistance"];
break;
case 9:
teams = ["spy", "spy", "spy",
"resistance", "resistance", "resistance", "resistance", "res)istance", "resistance"];
break;
case 10:
teams = ["spy", "spy", "spy", "spy",
"resistance", "resistance", "resistance", "resistance", "resistance", "resistance"];
break;
}
shuffle(teams);
players.forEach(function (player, index) {
Players.update(player._id, {$set: {
team: teams.pop()
}});
});
return players;
}
function assignSpecialRoles(players, game) {
var goodRoles = [];
var evilRoles = [];
var goodPlayers = [];
var evilPlayers = [];
if (game.merlin) {goodRoles.push("merlin");}
if (game.assassin) {evilRoles.push("assassin");}
if (game.morgana) {evilRoles.push("morgana");}
if (game.mordred) {evilRoles.push("mordred");}
if (game.percival) {goodRoles.push("percival");}
players.forEach(function (player) {
if (player.team == "resistance") {
goodPlayers.push(player);
} else {
evilPlayers.push(player);
}
});
shuffle(goodPlayers);
shuffle(evilPlayers);
for (var i = 0; i < goodRoles.length; i++) {
Players.update(goodPlayers[i]._id, {$set: {role: goodRoles[i] }});
}
for (var j = 0; j < evilRoles.length; j++) {
Players.update(evilPlayers[j]._id, {$set: {role: evilRoles[j] }});
}
}
function trackGameState() {
var gameID = Session.get("gameID");
var playerID = Session.get("playerID");
if (!gameID || !playerID){
return;
}
var game = Games.findOne(gameID);
if (!game) {
return;
}
var player = Players.findOne(playerID);
var players = Players.find({'gameID': game._id}, {'sort': {'ord': 1}});
var leader = Players.findOne({
$and: [
{ 'gameID' : game._id },
{ 'ord': game.turn % game.numPlayers }
]
});
updateLeader(leader, game);
if (!game || !player){
Session.set("gameID", null);
Session.set("playerID", null);
Session.set("currentView", "startMenu");
return;
}
if(game.state === "rolePhase"){
Session.set("currentView", "rolePhase");
} else if (game.state === "votingPhase") {
Games.update(game._id, {$set: {prevResult: "", voteRejected: false}});
Session.set("currentView", 'votingPhase');
} else if (game.state === "lobby") {
Session.set("currentView", "lobby");
} else if (game.state === "pickPhase"){
if (player._id === leader._id) {
Session.set("currentView", "pickPhaseLeader");
} else {
Session.set("currentView", "pickPhase");
}
} else if (game.state === "missionPhase") {
if (player.chosen) {
Session.set("currentView", "missionPhaseChosen");
} else {
Session.set("currentView", "missionPhase");
}
} else if (game.state === "assassinPhase") {
if (player.role === "assassin"){
Session.set("currentView", "assassinPhase");
} else {
Session.set("currentView", "assassinPhaseWait");
}
} else if (game.state === "gameOver") {
Session.set("currentView", "gameOver");
}
if(!game.winner && game.assassin && game.resRoundsWon > 2){
Games.update(game._id, {$set: {state: 'assassinPhase'}});
} else if (!!game.winner) {
Session.set("currentView", "specialGameOver");
} else if (game.resRoundsWon > 2 || game.spyRoundsWon > 2 || game.result5) {
Games.update(game._id, {$set: {state: 'gameOver'}});
}
}
function trackPlayersState() {
var game = Games.findOne(Session.get("gameID"));
var players = Players.find({'gameID': game._id});
if (Session.get("currentView") === "rolePhase" && allReady(players)){
Games.update(game._id, {$set: {state: 'pickPhase'}});
}
if (Session.get("currentView") === "votingPhase" && !!allVoted(players)){
if (allVoted(players) === "accept"){
recordVotes(players);
resetVotes(players);
Games.update(game._id, {$set: {state: "missionPhase", turn: game.turn + 1}});
} else {
recordVotes(players);
resetAll(players);
Games.update(game._id, {$set: {state: "pickPhase", turn: game.turn + 1, voteRejected: true }});
}
}
if (game.state === "missionPhase" && !!missionFinished(players)){
handleMissionResult(missionFinished(players));
resetAll(players);
// All players get here. Only run once.
if (getCurrentPlayer().ord == 0
&& game.spyRoundsWon < 3 && game.resRoundsWon < 3) {
generateNewRound(game, game.turn % game.numPlayers);
}
}
}
function allReady(players) {
var result = true;
players.forEach(function (player) {
if (player.ready !== "ready") {
result = false;
}
});
return result;
}
function allVoted(players) {
var accept = 0;
var reject = 0;
players.forEach(function (player) {
if (player.vote === "accept") {
accept++;
} else if (player.vote === "reject"){
reject++;
}
});
if(players.count() > (accept + reject)) {
return false;
} else {
return ( accept > reject ? "accept" : "reject" );
}
}
function resetAll(players) {
players.forEach(function (player) {
Players.update(player._id, { $set: { vote: "" }});
Players.update(player._id, { $set: { chosen: "" }});
Players.update(player._id, { $set: { mission: "" }});
});
}
function recordVotes(players) {
var currentVote = getCurrentVote();
players.forEach(function (player) {
var pv = PlayerVotes.findOne({voteID: currentVote._id, ord: player.ord});
pv.classes.push(player.vote);
PlayerVotes.update(pv._id, { $set: { vote: player.vote, classes: pv.classes } });
Players.update(player._id, { $set: { previousVote: player.vote }});
});
// This function gets called for every player, but we only want to do
// this once.
if (getCurrentPlayer().ord == 0) {
if (allVoted(players) == "accept") {
Votes.update(currentVote._id, { $set: { status: "accept-pending" }});
} else {
Votes.update(currentVote._id, { $set: { status: "reject" }});
var game = getCurrentGame();
var newLeader = currentVote.leader + 1 % game.numPlayers;
generateNewVote(game, getCurrentRound(), newLeader);
}
}
}
function resetVotes(players) {
players.forEach(function (player) {
Players.update(player._id, { $set: { vote: "" }});
});
}
function updateLeader(player, game) {
Games.update(game._id, {$set: {"leader": player.name}});
}
function missionFinished(players) {
var game = getCurrentGame();
var pass = 0;
var fail = 0;
var numToFail = missionNumPlayers(game.round, game.numPlayers)[1];
players.forEach(function (player) {
if (player.mission === "fail"){
fail ++;
} else if (player.mission === "pass"){
pass ++;
}
});
if (missionNumPlayers(game.round, game.numPlayers)[0] > (pass + fail)) {
return false;
} else {
var round = getCurrentRound();
var resString = fail < numToFail ? "pass" : "fail";
Rounds.update(round._id, { $set: { result: resString, fails: fail } });
var vote = getCurrentVote();
Votes.update(vote._id, { $set: { status: resString } });
return ( fail >= numToFail ? fail : "pass");
}
}
function missionNumPlayers(roundNum, numPlayers) {
switch (true) {
case numPlayers == 5:
switch(roundNum) {
case 1: return [2, 1];
case 2: return [3, 1];
case 3: return [2, 1];
case 4: return [3, 1];
case 5: return [3, 1];
}
break;
case numPlayers == 6:
switch(roundNum) {
case 1: return [2, 1];
case 2: return [3, 1];
case 3: return [4, 1];
case 4: return [3, 1];
case 5: return [4, 1];
}
break;
case numPlayers == 7:
switch(roundNum) {
case 1: return [2, 1];
case 2: return [3, 1];
case 3: return [3, 1];
case 4: return [4, 2];
case 5: return [4, 1];
}
break;
case numPlayers > 7 && numPlayers < 11:
switch(roundNum) {
case 1: return [3, 1];
case 2: return [4, 1];
case 3: return [4, 1];
case 4: return [5, 2];
case 5: return [5, 1];
}
break;
default:
return null;
}
}
function handleMissionResult(result) {
var game = getCurrentGame();
var param = "result" + game.round;
var query = {};
if (result == "pass") {
result = ["pass", null];
Games.update(game._id, {$set: {resRoundsWon: game.resRoundsWon + 1}});
} else {
result = ["fail", result];
Games.update(game._id, {$set: {spyRoundsWon: game.spyRoundsWon + 1}});
}
query[param] = result[0];
Games.update(game._id, {$set: {state: "pickPhase", round: game.round + 1, prevResult: result}});
Games.update(game._id, {$set: query});
}