ensl_gathers/lib/gather/gather.js

290 lines
7.2 KiB
JavaScript
Raw Normal View History

"use strict";
/*
* Implements Gather Model
*
* Gather States
2015-07-24 13:34:02 +00:00
* - Gathering
* - Election (Electing leaders)
* - Selection (Selecting teams)
* - Done
*
*/
var Gatherer = require("./gatherer");
2015-07-24 13:34:02 +00:00
var StateMachine = require("javascript-state-machine");
2015-07-31 15:06:21 +00:00
function Gather (options) {
if (!(this instanceof Gather)) {
2015-07-31 15:06:21 +00:00
return new Gather(options);
}
2015-07-31 15:06:21 +00:00
2015-08-10 23:44:54 +00:00
var noop = () => {};
2015-08-09 14:38:34 +00:00
2015-08-09 15:29:15 +00:00
if (options && typeof options.onEvent === 'function') {
this.onEvent = options.onEvent;
} else {
2015-08-10 23:44:54 +00:00
this.onEvent = noop;
2015-08-09 15:29:15 +00:00
}
if (options && typeof options.onDone === 'function') {
this.onDone = options.onDone;
} else {
2015-08-10 23:44:54 +00:00
this.onDone = noop;
2015-07-31 15:06:21 +00:00
}
2015-07-24 13:34:02 +00:00
this.TEAM_SIZE = 6;
this.gatherers = [];
this.ELECTION_INTERVAL = 300000; // 5 mins
2015-07-31 15:03:09 +00:00
this.electionStartTime = null;
2015-07-24 13:34:02 +00:00
this.initState();
}
2015-08-10 23:44:54 +00:00
Gather.prototype.alienLeader = () => {
return this.gatherers.reduce((acc, gatherer) => {
2015-07-24 13:34:02 +00:00
if (gatherer.team === "alien" && gatherer.leader) acc.push(gatherer);
return acc;
}, []).pop();
};
2015-08-10 23:44:54 +00:00
Gather.prototype.marineLeader = () => {
return this.gatherers.reduce((acc, gatherer) => {
2015-07-24 13:34:02 +00:00
if (gatherer.team === "marine" && gatherer.leader) acc.push(gatherer);
return acc;
}, []).pop();
};
2015-08-10 23:44:54 +00:00
Gather.prototype.assignMarineLeader = id => {
this.modifyGatherer({id: id}, gatherer => {
2015-07-24 13:34:02 +00:00
gatherer.leader = true;
gatherer.team = "marine";
});
};
2015-08-10 23:44:54 +00:00
Gather.prototype.assignAlienLeader = id => {
this.modifyGatherer({id: id}, gatherer => {
2015-07-24 13:34:02 +00:00
gatherer.leader = true;
gatherer.team = "alien";
});
};
2015-08-10 23:44:54 +00:00
Gather.prototype.containsUser = user => {
return this.gatherers.some(gatherer => {
2015-07-23 13:36:51 +00:00
return gatherer.id === user.id;
});
};
2015-07-22 23:30:14 +00:00
2015-08-10 23:44:54 +00:00
Gather.prototype.addUser = user => {
2015-07-23 13:36:51 +00:00
if (this.containsUser(user)) {
return null;
}
var gatherer = new Gatherer(user);
this.gatherers.push(gatherer);
return gatherer;
2015-07-22 23:30:14 +00:00
};
2015-08-10 23:44:54 +00:00
Gather.prototype.removeUser = user => {
this.gatherers = this.gatherers.filter(gatherer => user.id !== gatherer.id);
2015-07-22 23:30:14 +00:00
};
2015-08-10 23:44:54 +00:00
Gather.prototype.modifyGatherer = (user, callback) => {
this.gatherers.forEach(gatherer => {
if (gatherer.id === user.id) callback(gatherer);
2015-07-23 13:36:51 +00:00
});
2015-07-24 13:34:02 +00:00
}
2015-08-10 23:44:54 +00:00
Gather.prototype.moveToMarine = user => {
2015-07-24 13:34:02 +00:00
if (this.marines().length >= this.TEAM_SIZE) return;
2015-08-10 23:44:54 +00:00
this.modifyGatherer(user, gatherer => gatherer.team = "marine");
2015-07-22 23:30:14 +00:00
};
2015-08-10 23:44:54 +00:00
Gather.prototype.moveToAlien = user => {
2015-07-24 13:34:02 +00:00
if (this.aliens().length >= this.TEAM_SIZE) return;
2015-08-10 23:44:54 +00:00
this.modifyGatherer(user, gatherer => gatherer.team = "alien");
2015-07-23 13:36:51 +00:00
};
2015-08-10 23:44:54 +00:00
Gather.prototype.moveToLobby = user => {
this.gatherers.forEach((gatherer, index, array) => {
2015-07-23 13:36:51 +00:00
if (gatherer.id === user.id) {
gatherer.team = "lobby";
array[index] = gatherer;
}
});
};
2015-08-10 23:44:54 +00:00
Gather.prototype.retrieveGroup = team => {
return this.gatherers.filter(gatherer => gatherer.team === team);
};
2015-07-22 23:30:14 +00:00
2015-08-10 23:44:54 +00:00
Gather.prototype.lobby = () => {
2015-07-23 13:36:51 +00:00
return this.retrieveGroup("lobby");
2015-07-22 23:30:14 +00:00
};
2015-08-10 23:44:54 +00:00
Gather.prototype.aliens = () => {
2015-07-23 13:36:51 +00:00
return this.retrieveGroup("alien");
};
2015-08-10 23:44:54 +00:00
Gather.prototype.marines = () => {
2015-07-23 13:36:51 +00:00
return this.retrieveGroup("marine");
};
2015-08-10 23:44:54 +00:00
Gather.prototype.toJson = () => {
2015-07-23 13:36:51 +00:00
return {
2015-07-24 15:01:56 +00:00
gatherers: this.gatherers,
2015-07-31 15:03:09 +00:00
state: this.current,
election: {
2015-07-31 15:54:08 +00:00
startTime: (this.electionStartTime === null) ? null : this.electionStartTime.toISOString(),
2015-07-31 15:03:09 +00:00
interval: this.ELECTION_INTERVAL
}
2015-07-23 13:36:51 +00:00
}
2015-07-24 13:34:02 +00:00
};
2015-08-10 23:44:54 +00:00
Gather.prototype.voteForMap = (voter, mapId) => {
this.gatherers.forEach((gatherer, index, array) => {
2015-07-29 13:50:39 +00:00
if (gatherer.id === voter.id) {
array[index].mapVote = mapId;
}
});
};
2015-08-10 23:44:54 +00:00
Gather.prototype.voteForServer = (voter, serverId) => {
this.gatherers.forEach((gatherer, index, array) => {
2015-07-29 13:50:39 +00:00
if (gatherer.id === voter.id) {
array[index].serverVote = serverId;
}
});
};
2015-07-24 13:34:02 +00:00
// Returns an array of IDs representing votes for leaders
2015-08-10 23:44:54 +00:00
Gather.prototype.leaderVotes = () => {
2015-07-24 13:34:02 +00:00
var self = this;
2015-08-10 23:44:54 +00:00
return self.gatherers.map(gatherer => gatherer.leaderVote)
.filter(leaderId => typeof leaderId === 'number')
.filter(candidate => {
return self.gatherers.some(gatherer => gatherer.id === candidate);
2015-07-24 13:34:02 +00:00
});
};
2015-08-10 23:44:54 +00:00
Gather.prototype.voteForLeader = (voter, candidate) => {
2015-07-27 11:55:36 +00:00
// Find voter and then assign their vote to candidate id
2015-08-10 23:44:54 +00:00
this.gatherers.forEach((gatherer, index, array) => {
2015-07-24 13:34:02 +00:00
if (gatherer.id === voter.id) {
array[index].voteForLeader(candidate);
}
});
};
2015-08-10 23:44:54 +00:00
Gather.prototype.getGatherer = (user) => {
2015-07-28 15:54:29 +00:00
var matchingGatherer = null;
2015-08-10 23:44:54 +00:00
this.gatherers.forEach((gatherer) => {
2015-07-28 15:54:29 +00:00
if (gatherer.id === user.id) matchingGatherer = gatherer;
});
return matchingGatherer;
};
2015-07-24 13:34:02 +00:00
// Gather States
// - Gathering
// - Election
// - Selection
// - Done
// gather.current - contains the current state
// gather.is(s) - return true if state s is the current state
// gather.can(e) - return true if event e can be fired in the current state
// gather.cannot(e) - return true if event e cannot be fired in the current state
// gather.transitions() - return list of events that are allowed from the current state
StateMachine.create({
target: Gather.prototype,
events: [
{ name: "initState", from: "none", to: "gathering" },
{ name: "addGatherer", from: "gathering", to: "election" },
{ name: "selectLeader", from: "election", to: "selection" },
2015-07-31 15:03:09 +00:00
{ name: "electionTimeout", from: "election", to: "selection" },
2015-07-24 13:34:02 +00:00
{ name: "confirmSelection", from: "selection", to: "done" },
2015-07-24 17:05:12 +00:00
{ name: "removeGatherer", from: ["gathering", "election", "selection"], to: "gathering" }
2015-07-24 13:34:02 +00:00
],
callbacks: {
2015-08-08 17:13:17 +00:00
// Callbacks for events
2015-08-10 23:44:54 +00:00
onafterevent: () => {
2015-08-09 14:38:34 +00:00
this.onEvent.call(this);
2015-08-09 14:27:46 +00:00
},
2015-08-08 17:13:17 +00:00
2015-07-31 15:03:09 +00:00
// Gathering State
2015-08-10 23:44:54 +00:00
onbeforeaddGatherer: (event, from, to, user) => {
2015-07-24 13:34:02 +00:00
this.addUser(user);
if (this.gatherers.length !== 12) {
return false;
}
},
2015-07-31 15:03:09 +00:00
// Election State
2015-08-10 23:44:54 +00:00
onbeforeselectLeader: (event, from, to, voter, candidate) => {
2015-07-24 13:34:02 +00:00
this.voteForLeader(voter, candidate);
if (this.leaderVotes().length !== 12) {
return false;
}
},
2015-07-31 15:03:09 +00:00
2015-08-10 23:44:54 +00:00
onenterelection: () => {
2015-07-31 15:03:09 +00:00
// Setup timer for elections
var self = this;
self.electionStartTime = new Date();
2015-08-10 23:44:54 +00:00
setTimeout(() => {
2015-07-31 15:03:09 +00:00
if (self.can("electionTimeout")) {
self.electionTimeout();
}
}, self.ELECTION_INTERVAL);
},
2015-08-10 23:44:54 +00:00
onleaveelection: () => {
2015-07-31 15:03:09 +00:00
this.electionStartTime = null;
2015-07-24 13:34:02 +00:00
},
2015-07-31 15:03:09 +00:00
// Selection State
2015-08-10 23:44:54 +00:00
onenterselection: () => {
2015-07-24 13:34:02 +00:00
// Remove all leaders and teams
2015-08-10 23:44:54 +00:00
this.gatherers.forEach(gatherer => {
gatherer.leader = false;
gatherer.team = "lobby";
2015-07-24 13:34:02 +00:00
});
// Assign leaders based on vote
// 1st place alien comm
// 2nd place marine comm
var voteCount = {};
2015-08-10 23:44:54 +00:00
this.gatherers.forEach(gatherer => { voteCount[gatherer.id] = 0 });
this.leaderVotes().forEach(candidateId => { voteCount[candidateId]++ });
2015-07-24 13:34:02 +00:00
var rank = [];
for (var candidate in voteCount) {
rank.push({ candidate: candidate, count: voteCount[candidate] });
}
2015-08-10 23:44:54 +00:00
rank.sort((a, b) => {
2015-07-24 13:34:02 +00:00
return a.count - b.count;
});
this.assignAlienLeader(parseInt(rank.pop().candidate, 0));
this.assignMarineLeader(parseInt(rank.pop().candidate, 0));
},
2015-07-31 15:03:09 +00:00
2015-08-10 23:44:54 +00:00
onbeforeconfirmSelection: (event, from, to, leader) => {
2015-07-29 14:35:58 +00:00
return (this.aliens().length === this.TEAM_SIZE
2015-07-24 13:34:02 +00:00
&& this.marines().length === this.TEAM_SIZE);
2015-07-31 15:03:09 +00:00
},
2015-08-08 17:13:17 +00:00
// Remove gatherer event
2015-08-10 23:44:54 +00:00
onbeforeremoveGatherer: (event, from, to, user) => {
// Cancel transition if no gatherers have been removed
let userCount = this.gatherers.length;
2015-07-31 15:03:09 +00:00
this.removeUser(user);
return (userCount > this.gatherers.length);
2015-08-09 14:38:34 +00:00
},
// On enter done
2015-08-10 23:44:54 +00:00
onenterdone: () => {
2015-08-09 14:38:34 +00:00
this.onDone.call(this);
2015-07-24 13:34:02 +00:00
}
}
});
2015-07-23 13:36:51 +00:00
2015-07-24 13:34:02 +00:00
module.exports = Gather;