diff --git a/gulpfile.js b/gulpfile.js
new file mode 100644
index 0000000..ad0e1db
--- /dev/null
+++ b/gulpfile.js
@@ -0,0 +1,21 @@
+"use strict";
+
+var gulp = require("gulp");
+var react = require("gulp-react");
+var concat = require("gulp-concat");
+var watch = require("gulp-watch");
+var plumber = require("gulp-plumber");
+
+gulp.task('default', ['compile']);
+
+gulp.task('compile', function () {
+ return gulp.src('lib/react/**')
+ .pipe(plumber())
+ .pipe(concat('app.js'))
+ .pipe(react())
+ .pipe(gulp.dest('public/js/'));
+});
+
+gulp.task('watch', function () {
+ gulp.watch('lib/react/**', ['compile']);
+});
\ No newline at end of file
diff --git a/lib/gather/controller.js b/lib/gather/controller.js
index 3496d97..f126cbb 100644
--- a/lib/gather/controller.js
+++ b/lib/gather/controller.js
@@ -53,7 +53,11 @@ async.parallel(instructions, function (error) {
console.log("Error while adding gatherers", error);
} else {
console.log("Loaded gatherers");
-
+ gather.gatherers.forEach(function (gatherer, index, array) {
+ var candidate = Math.floor(Math.random() * array.length);
+ array[index].leaderVote = array[candidate].id;
+ });
+ console.log("Assigned vote for each gatherer");
}
});
@@ -65,7 +69,7 @@ module.exports = function (namespace) {
namespace.sockets.forEach(function (socket) {
socket.emit("gather:refresh", {
gather: gather.toJson(),
- currentUser: socket._user
+ currentGatherer: gather.getGatherer(socket._user)
});
});
};
diff --git a/lib/gather/gather.js b/lib/gather/gather.js
index 637f26e..e08161b 100644
--- a/lib/gather/gather.js
+++ b/lib/gather/gather.js
@@ -164,6 +164,14 @@ Gather.prototype.voteForLeader = function (voter, candidate) {
});
};
+Gather.prototype.getGatherer = function (user) {
+ var matchingGatherer = null;
+ this.gatherers.forEach(function (gatherer) {
+ if (gatherer.id === user.id) matchingGatherer = gatherer;
+ });
+ return matchingGatherer;
+};
+
// Gather States
// - Gathering
// - Election
diff --git a/lib/react/app.jsx b/lib/react/app.jsx
deleted file mode 100644
index fa35ebb..0000000
--- a/lib/react/app.jsx
+++ /dev/null
@@ -1,573 +0,0 @@
-$(function () {
-
-"use strict";
-
-var UserCounter = React.createClass({
- render: function () {
- return (
-
-
- Online
- {this.props.count}
-
-
- );
- }
-});
-
-var UserLogin = React.createClass({
- authorizeId: function (id) {
- id = parseInt(id, 10);
- socket.emit("users:authorize", {
- id: id
- });
- },
- handleSubmit: function (e) {
- e.preventDefault();
- var id = React.findDOMNode(this.refs.authorize_id).value.trim();
- if (!id) return;
- React.findDOMNode(this.refs.authorize_id).value = '';
- this.authorizeId(id);
- return;
- },
- render: function () {
- return (
-
- );
- }
-})
-
-var UserMenu = React.createClass({
- getDefaultProps: function () {
- return {
- count: 0,
- users: []
- };
- },
- componentDidMount: function () {
- socket.on('users:update', this.updateUsers);
- },
- updateUsers: function (data) {
- this.setProps({
- count: data.count,
- users: data.users
- });
- },
- render: function () {
- var users = this.props.users.map(function (user) {
- return (
- {user.username}
- );
- });
- return (
-
- );
- }
-});
-
-var Chatroom = React.createClass({
- getDefaultProps: function () {
- return {
- history: []
- };
- },
- componentDidMount: function () {
- var self = this;
- var TIMER_INTERVAL = 60000; // Every minute
-
- socket.on("message:new", function (data) {
- var history = self.props.history;
- history.push(data);
- self.setProps({
- history: history
- });
- self.scrollToBottom();
- });
-
- // Message History Retrieved
- socket.on("message:refresh", function (data) {
- self.setProps({
- history: data.chatHistory
- });
- self.scrollToBottom();
- });
-
- socket.emit("message:refresh", {});
-
- self.timer = setInterval(function () {
- if (self.refs.messages) self.refs.messages.refreshTime();
- }, TIMER_INTERVAL);
- },
-
- componentDidUnmount: function () {
- clearInterval(this.timer);
- },
- sendMessage: function (message) {
- socket.emit("newMessage", {message: message});
- },
- scrollToBottom: function () {
- var node = React.findDOMNode(this.refs.messageContainer);
- node.scrollTop = node.scrollHeight;
- },
- render: function () {
- var messages = this.props.history.map(function (message) {
- return (
-
- );
- });
- return (
-
- );
- }
-});
-
-var ChatMessage = React.createClass({
- getInitialState: function () {
- return {
- timeAgo: $.timeago(this.props.createdAt)
- }
- },
- refreshTime: function () {
- var self = this;
- self.setState({
- timeAgo: $.timeago(self.props.createdAt)
- });
- },
- render: function () {
- return (
-
-
-
-
-
-
- {this.props.username}
-
- {this.state.timeAgo}
-
-
-
{this.props.content}
-
-
- );
- }
-});
-
-var CurrentUser = React.createClass({
- componentDidMount: function () {
- var self = this;
- socket.on("users:update", function (data) {
- self.setProps({
- user: data.currentUser
- });
- });
- socket.emit("users:refresh", {});
- },
- render: function () {
- if (this.props.user) {
- return (
- {this.props.user.username}
- );
- } else {
- return false;
- }
- }
-});
-
-var VoteButton = React.createClass({
- cancelVote: function (e) {
- socket.emit("gather:vote", {
- leader: {
- candidate: null
- }
- });
- },
- vote: function (e) {
- e.preventDefault();
- socket.emit("gather:vote", {
- leader: {
- candidate: parseInt(e.target.value, 10)
- }
- });
- },
- render: function () {
- if (this.props.currentGatherer === null) {
- return false;
- }
- if (this.props.currentGatherer.leaderVote === this.props.candidate.id) {
- return (
-
- );
- } else {
- return (
-
- );
- }
- }
-});
-
-var MessageBar = React.createClass({
- sendMessage: function (content) {
- socket.emit("message:new", {
- content: content
- });
- },
- handleSubmit: function (e) {
- e.preventDefault();
- var content = React.findDOMNode(this.refs.content).value.trim();
- if (!content) return;
- React.findDOMNode(this.refs.content).value = '';
- this.sendMessage(content);
- return;
- },
- render: function () {
- return (
-
- );
- }
-});
-
-var JoinGatherButton = React.createClass({
- joinGather: function (e) {
- e.preventDefault();
- socket.emit("gather:join", {});
- },
- render: function () {
- var message = this.props.buttonName || "Join Gather";
- var buttonClass = "btn btn-primary";
- if (this.props.buttonClass) {
- buttonClass += " " + this.props.buttonClass;
- }
- return ()
- }
-});
-
-var GatherProgress = React.createClass({
- gatheringProgress: function () {
- var num = this.props.gather.gatherers.length;
- var den = 12;
- return {
- num: num,
- den: den,
- message: num + " / " + den
- };
- },
- electionProgress: function () {
- var num = this.props.gather.gatherers.reduce(function (acc, gatherer) {
- if (gatherer.leaderVote) acc++;
- return acc;
- }, 0);
- var den = 12;
- return {
- num: num,
- den: den,
- message: den - num + " more votes required"
- };
- },
- selectionProgress: function () {
- var num = this.props.gather.gatherers.reduce(function (acc, gatherer) {
- if (gatherer.team !== "lobby") acc++;
- return acc;
- }, 0);
- var den = 12;
-
- return {
- num: num,
- den: den,
- message: num + " out of " + den + " players assigned"
- };
- },
- render: function () {
- var progress;
- var gatherState = this.props.gather.state;
- if (gatherState === 'gathering' && this.props.gather.gatherers.length) {
- progress = this.gatheringProgress();
- } else if (gatherState === 'election') {
- progress = this.electionProgress();
- } else if (gatherState === 'selection') {
- progress = this.selectionProgress();
- }
- if (progress) {
- var style = {
- width: Math.round((progress.num / progress.den * 100)) + "%"
- };
- return (
-
-
Gather Progress
-
-
- {progress.message}
-
-
-
- );
- } else {
- return false;
- }
- }
-});
-
-var Gather = React.createClass({
- getDefaultProps: function () {
- return {
- gather: {
- gatherers: []
- }
- }
- },
- joinedGather: function () {
- var self = this;
- return this.props.gather.gatherers.some(function (gatherer) {
- return gatherer.user.id === self.props.currentUser.id;
- });
- },
- componentDidMount: function () {
- var self = this;
- socket.on("gather:refresh", function (data) {
- self.setProps({
- gather: data.gather,
- currentUser: data.currentUser
- });
- });
- },
- stateDescription: function () {
- switch(this.props.gather.state) {
- case "gathering":
- return "Waiting for more gatherers";
- case "election":
- return "Currently voting for team leaders";
- case "selection":
- return "Waiting for leaders to picking teams";
- case "done":
- return "Gather completed";
- default:
- return "Initialising gather";
- }
- },
- leaveGather: function (e) {
- e.preventDefault();
- socket.emit("gather:leave", {});
- },
- inviteToGather: function (e) {
- e.preventDefault();
- },
- currentGatherer: function () {
- var current = null;
- var self = this;
- this.props.gather.gatherers.forEach(function (gatherer) {
- if (gatherer.id === self.props.currentUser.id) current = gatherer;
- });
- return current;
- },
- render: function () {
- var joinButton;
- if (this.joinedGather()) {
- joinButton = ();
- } else {
- joinButton = ();
- }
- var inviteButton;
- if (this.props.gather.state === 'gathering') {
- inviteButton = ();
- }
- return (
-
-
- NS2 Gather
- {this.props.gather.gatherers.length}
-
- {this.stateDescription()}
-
-
-
-
-
- {inviteButton}
- {joinButton}
-
-
-
- );
- }
-});
-
-var LeaderPoll = React.createClass({
- render: function () {
- return (
-
-
- );
- }
-});
-
-var Gatherers = React.createClass({
- render: function () {
- var self = this;
- var gatherers = this.props.gather.gatherers.map(function (gatherer) {
- var lifeforms = (
- gatherer.user.ability.lifeforms.map(function (lifeform) {
- return ({lifeform});
- })
- );
-
- var commBadge;
- if (gatherer.user.ability.commander) {
- commBadge = ();
- }
-
- var division = ({gatherer.user.ability.division});
- var action = lifeforms;
- if (self.props.gather.state === "election") {
- var votes = self.props.gather.gatherers.reduce(function (acc, voter) {
- if (voter.leaderVote === gatherer.id) acc++;
- return acc;
- }, 0)
- action = (
-
- {votes + " votes"}
-
-
-
- );
- }
-
- return (
-
- {commBadge} |
- {gatherer.user.username} |
- {division} |
- {action} |
-
- );
- })
- if (this.props.gather.gatherers.length) {
- return (
-
- );
- } else {
- return (
);
- }
- }
-});
-
-var socket;
-
-function initialiseComponents () {
- var socketUrl = window.location.protocol + "//" + window.location.host;
- socket = io(socketUrl)
- .on("connect", function () {
- console.log("Connected");
- })
- .on("reconnect", function () {
- console.log("Reconnected");
- })
- .on("disconnect", function () {
- console.log("Disconnected")
- });
-
- React.render(, document.getElementById('side-menu'));
- React.render(, document.getElementById('chatroom'));
- React.render(, document.getElementById('gathers'));
- React.render(, document.getElementById('currentuser'));
-};
-
-initialiseComponents();
-
-
-
-});
-
diff --git a/lib/react/gather.jsx b/lib/react/gather.jsx
new file mode 100644
index 0000000..4e3ab91
--- /dev/null
+++ b/lib/react/gather.jsx
@@ -0,0 +1,354 @@
+"use strict";
+
+var VoteButton = React.createClass({
+ cancelVote: function (e) {
+ socket.emit("gather:vote", {
+ leader: {
+ candidate: null
+ }
+ });
+ },
+ vote: function (e) {
+ e.preventDefault();
+ socket.emit("gather:vote", {
+ leader: {
+ candidate: parseInt(e.target.value, 10)
+ }
+ });
+ },
+ render: function () {
+ if (this.props.currentGatherer === null) {
+ return false;
+ }
+ if (this.props.currentGatherer.leaderVote === this.props.candidate.id) {
+ return (
+
+ );
+ } else {
+ return (
+
+ );
+ }
+ }
+});
+
+var JoinGatherButton = React.createClass({
+ joinGather: function (e) {
+ e.preventDefault();
+ socket.emit("gather:join", {});
+ },
+ render: function () {
+ var message = this.props.buttonName || "Join Gather";
+ var buttonClass = "btn btn-primary";
+ if (this.props.buttonClass) {
+ buttonClass += " " + this.props.buttonClass;
+ }
+ return ()
+ }
+});
+
+var SelectPlayerButton = React.createClass({
+ selectPlayer: function (e) {
+ e.preventDefault();
+ },
+ render: function () {
+ if (!this.props.currentGatherer.leader) {
+ return false;
+ } else {
+ return (
+ );
+ }
+ }
+})
+
+var GatherTeams = React.createClass({
+ alienGatherers: function () {
+ return this.props.gather.gatherers.filter(function (gatherer) {
+ return gatherer.team === "alien";
+ }).sort(function (gatherer) {
+ return (gatherer.leader) ? 1 : 0;
+ });
+ },
+ marineGatherers: function () {
+ return this.props.gather.gatherers.filter(function (gatherer) {
+ return gatherer.team === "marine";
+ }).sort(function (gatherer) {
+ return (gatherer.leader) ? 1 : 0;
+ });
+ },
+ render: function () {
+ var extractGatherer = function (gatherer) {
+ var image;
+ if (gatherer.leader) {
+ image = ();
+ }
+ return (
+
+ {image} |
+ {gatherer.user.username} |
+
+ );
+ }
+ var marines = this.marineGatherers().map(extractGatherer);
+ var aliens = this.alienGatherers().map(extractGatherer);
+ return (
+
+ );
+ }
+})
+
+var GatherProgress = React.createClass({
+ stateDescription: function () {
+ switch(this.props.gather.state) {
+ case "gathering":
+ return "Waiting for more gatherers.";
+ case "election":
+ return "Currently voting for team leaders.";
+ case "selection":
+ return "Waiting for leaders to picking teams.";
+ case "done":
+ return "Gather completed.";
+ default:
+ return "Initialising gather.";
+ }
+ },
+ gatheringProgress: function () {
+ var num = this.props.gather.gatherers.length;
+ var den = 12;
+ var remaining = den - num;
+ var message = (remaining === 1) ? "Waiting for last player" : "Waiting for " + remaining + " more players";
+ return {
+ num: num,
+ den: den,
+ message: message
+ };
+ },
+ electionProgress: function () {
+ var num = this.props.gather.gatherers.reduce(function (acc, gatherer) {
+ if (gatherer.leaderVote) acc++;
+ return acc;
+ }, 0);
+ var den = 12;
+ return {
+ num: num,
+ den: den,
+ message: den - num + " more votes required"
+ };
+ },
+ selectionProgress: function () {
+ var num = this.props.gather.gatherers.reduce(function (acc, gatherer) {
+ if (gatherer.team !== "lobby") acc++;
+ return acc;
+ }, 0);
+ var den = 12;
+
+ return {
+ num: num,
+ den: den,
+ message: num + " out of " + den + " players assigned"
+ };
+ },
+ render: function () {
+ var progress;
+ var gatherState = this.props.gather.state;
+ if (gatherState === 'gathering' && this.props.gather.gatherers.length) {
+ progress = this.gatheringProgress();
+ } else if (gatherState === 'election') {
+ progress = this.electionProgress();
+ } else if (gatherState === 'selection') {
+ progress = this.selectionProgress();
+ }
+ if (progress) {
+ var style = {
+ width: Math.round((progress.num / progress.den * 100)) + "%"
+ };
+ return (
+
+
{this.stateDescription()} {progress.message}
+
+
+ );
+ } else {
+ return false;
+ }
+ }
+});
+
+var Gather = React.createClass({
+ getDefaultProps: function () {
+ return {
+ gather: {
+ gatherers: []
+ }
+ }
+ },
+ joinedGather: function () {
+ return this.props.currentGatherer !== null;
+ },
+ componentDidMount: function () {
+ var self = this;
+ socket.on("gather:refresh", function (data) {
+ self.setProps({
+ gather: data.gather,
+ currentGatherer: data.currentGatherer
+ });
+ });
+ },
+ leaveGather: function (e) {
+ e.preventDefault();
+ socket.emit("gather:leave", {});
+ },
+ inviteToGather: function (e) {
+ e.preventDefault();
+ },
+ render: function () {
+ var joinButton;
+ if (this.joinedGather()) {
+ joinButton = ();
+ } else {
+ joinButton = ();
+ }
+ var inviteButton;
+ if (this.props.gather.state === 'gathering') {
+ inviteButton = ();
+ }
+ var gatherTeams;
+ if (this.props.gather.state === 'selection') {
+ gatherTeams =
+ }
+ return (
+
+
+ NS2 Gather
+ {this.props.gather.gatherers.length}
+
+
+ {gatherTeams}
+
+
+
+ {inviteButton}
+ {joinButton}
+
+
+
+ );
+ }
+});
+
+var Gatherers = React.createClass({
+ render: function () {
+ var self = this;
+ var gatherers = this.props.gather.gatherers.map(function (gatherer) {
+ var lifeforms = (
+ gatherer.user.ability.lifeforms.map(function (lifeform) {
+ return ({lifeform});
+ })
+ );
+
+ // Switch this to online status
+ var online= ( );
+
+ var division = ({gatherer.user.ability.division});
+ var action = lifeforms;
+ if (self.props.gather.state === "election") {
+ var votes = self.props.gather.gatherers.reduce(function (acc, voter) {
+ if (voter.leaderVote === gatherer.id) acc++;
+ return acc;
+ }, 0)
+ action = (
+
+ {votes + " votes"}
+
+
+ );
+ }
+
+ return (
+
+ {online} |
+ {gatherer.user.username} |
+ {division} |
+ {action} |
+
+ );
+ })
+ if (this.props.gather.gatherers.length) {
+ return (
+
+ );
+ } else {
+ return (
);
+ }
+ }
+});
+
+
+
diff --git a/lib/react/init.jsx b/lib/react/init.jsx
new file mode 100644
index 0000000..dfbbd5c
--- /dev/null
+++ b/lib/react/init.jsx
@@ -0,0 +1,22 @@
+"use strict";
+
+var socket;
+
+function initialiseComponents () {
+ var socketUrl = window.location.protocol + "//" + window.location.host;
+ socket = io(socketUrl)
+ .on("connect", function () {
+ console.log("Connected");
+ })
+ .on("reconnect", function () {
+ console.log("Reconnected");
+ })
+ .on("disconnect", function () {
+ console.log("Disconnected")
+ });
+
+ React.render(, document.getElementById('side-menu'));
+ React.render(, document.getElementById('chatroom'));
+ React.render(, document.getElementById('gathers'));
+ React.render(, document.getElementById('currentuser'));
+};
\ No newline at end of file
diff --git a/lib/react/message.jsx b/lib/react/message.jsx
new file mode 100644
index 0000000..503a97d
--- /dev/null
+++ b/lib/react/message.jsx
@@ -0,0 +1,146 @@
+"use strict";
+
+var Chatroom = React.createClass({
+ getDefaultProps: function () {
+ return {
+ history: []
+ };
+ },
+ componentDidMount: function () {
+ var self = this;
+ var TIMER_INTERVAL = 60000; // Every minute
+
+ socket.on("message:new", function (data) {
+ var history = self.props.history;
+ history.push(data);
+ self.setProps({
+ history: history
+ });
+ self.scrollToBottom();
+ });
+
+ // Message History Retrieved
+ socket.on("message:refresh", function (data) {
+ self.setProps({
+ history: data.chatHistory
+ });
+ self.scrollToBottom();
+ });
+
+ socket.emit("message:refresh", {});
+
+ self.timer = setInterval(function () {
+ if (self.refs.messages) self.refs.messages.refreshTime();
+ }, TIMER_INTERVAL);
+ },
+
+ componentDidUnmount: function () {
+ clearInterval(this.timer);
+ },
+ sendMessage: function (message) {
+ socket.emit("newMessage", {message: message});
+ },
+ scrollToBottom: function () {
+ var node = React.findDOMNode(this.refs.messageContainer);
+ node.scrollTop = node.scrollHeight;
+ },
+ render: function () {
+ var messages = this.props.history.map(function (message) {
+ return (
+
+ );
+ });
+ return (
+
+ );
+ }
+});
+
+var ChatMessage = React.createClass({
+ getInitialState: function () {
+ return {
+ timeAgo: $.timeago(this.props.createdAt)
+ }
+ },
+ refreshTime: function () {
+ var self = this;
+ self.setState({
+ timeAgo: $.timeago(self.props.createdAt)
+ });
+ },
+ render: function () {
+ return (
+
+
+
+
+
+
+ {this.props.username}
+
+ {this.state.timeAgo}
+
+
+
{this.props.content}
+
+
+ );
+ }
+});
+
+var MessageBar = React.createClass({
+ sendMessage: function (content) {
+ socket.emit("message:new", {
+ content: content
+ });
+ },
+ handleSubmit: function (e) {
+ e.preventDefault();
+ var content = React.findDOMNode(this.refs.content).value.trim();
+ if (!content) return;
+ React.findDOMNode(this.refs.content).value = '';
+ this.sendMessage(content);
+ return;
+ },
+ render: function () {
+ return (
+
+ );
+ }
+});
diff --git a/lib/react/user.jsx b/lib/react/user.jsx
new file mode 100644
index 0000000..9c6fe65
--- /dev/null
+++ b/lib/react/user.jsx
@@ -0,0 +1,111 @@
+"use strict";
+
+var UserCounter = React.createClass({
+ render: function () {
+ return (
+
+
+ Online
+ {this.props.count}
+
+
+ );
+ }
+});
+
+var UserLogin = React.createClass({
+ authorizeId: function (id) {
+ id = parseInt(id, 10);
+ socket.emit("users:authorize", {
+ id: id
+ });
+ },
+ handleSubmit: function (e) {
+ e.preventDefault();
+ var id = React.findDOMNode(this.refs.authorize_id).value.trim();
+ if (!id) return;
+ React.findDOMNode(this.refs.authorize_id).value = '';
+ this.authorizeId(id);
+ return;
+ },
+ render: function () {
+ return (
+
+ );
+ }
+})
+
+var UserMenu = React.createClass({
+ getDefaultProps: function () {
+ return {
+ count: 0,
+ users: []
+ };
+ },
+ componentDidMount: function () {
+ socket.on('users:update', this.updateUsers);
+ },
+ updateUsers: function (data) {
+ this.setProps({
+ count: data.count,
+ users: data.users
+ });
+ },
+ render: function () {
+ var users = this.props.users.map(function (user) {
+ return (
+ {user.username}
+ );
+ });
+ return (
+
+ );
+ }
+});
+
+var CurrentUser = React.createClass({
+ componentDidMount: function () {
+ var self = this;
+ socket.on("users:update", function (data) {
+ self.setProps({
+ user: data.currentUser
+ });
+ });
+ socket.emit("users:refresh", {});
+ },
+ render: function () {
+ if (this.props.user) {
+ return (
+ {this.props.user.username}
+ );
+ } else {
+ return false;
+ }
+ }
+});
diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json
index 73e051f..c08b804 100644
--- a/npm-shrinkwrap.json
+++ b/npm-shrinkwrap.json
@@ -2,6 +2,11 @@
"name": "sws_gathers",
"version": "1.0.0",
"dependencies": {
+ "async": {
+ "version": "1.4.0",
+ "from": "async@",
+ "resolved": "https://registry.npmjs.org/async/-/async-1.4.0.tgz"
+ },
"express": {
"version": "4.13.1",
"from": "express@",
@@ -405,6 +410,781 @@
"from": "extend@",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz"
},
+ "gulp": {
+ "version": "3.9.0",
+ "from": "gulp@",
+ "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.0.tgz",
+ "dependencies": {
+ "archy": {
+ "version": "1.0.0",
+ "from": "archy@^1.0.0",
+ "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz"
+ },
+ "chalk": {
+ "version": "1.1.0",
+ "from": "chalk@^1.0.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.0.tgz",
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.1.0",
+ "from": "ansi-styles@^2.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.1.0.tgz"
+ },
+ "escape-string-regexp": {
+ "version": "1.0.3",
+ "from": "escape-string-regexp@^1.0.2",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.3.tgz"
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "from": "has-ansi@^2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.0.0",
+ "from": "ansi-regex@^2.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz"
+ }
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.0",
+ "from": "strip-ansi@^3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.0.tgz",
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.0.0",
+ "from": "ansi-regex@^2.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz"
+ }
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "from": "supports-color@^2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz"
+ }
+ }
+ },
+ "deprecated": {
+ "version": "0.0.1",
+ "from": "deprecated@^0.0.1",
+ "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz"
+ },
+ "gulp-util": {
+ "version": "3.0.6",
+ "from": "gulp-util@^3.0.0",
+ "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.6.tgz",
+ "dependencies": {
+ "array-differ": {
+ "version": "1.0.0",
+ "from": "array-differ@^1.0.0",
+ "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz"
+ },
+ "array-uniq": {
+ "version": "1.0.2",
+ "from": "array-uniq@^1.0.2",
+ "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.2.tgz"
+ },
+ "beeper": {
+ "version": "1.1.0",
+ "from": "beeper@^1.0.0",
+ "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.0.tgz"
+ },
+ "dateformat": {
+ "version": "1.0.11",
+ "from": "dateformat@^1.0.11",
+ "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.11.tgz",
+ "dependencies": {
+ "get-stdin": {
+ "version": "4.0.1",
+ "from": "get-stdin@*",
+ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz"
+ },
+ "meow": {
+ "version": "3.3.0",
+ "from": "meow@*",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-3.3.0.tgz",
+ "dependencies": {
+ "camelcase-keys": {
+ "version": "1.0.0",
+ "from": "camelcase-keys@^1.0.0",
+ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-1.0.0.tgz",
+ "dependencies": {
+ "camelcase": {
+ "version": "1.1.0",
+ "from": "camelcase@^1.0.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.1.0.tgz"
+ },
+ "map-obj": {
+ "version": "1.0.1",
+ "from": "map-obj@^1.0.0",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz"
+ }
+ }
+ },
+ "indent-string": {
+ "version": "1.2.2",
+ "from": "indent-string@^1.1.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-1.2.2.tgz",
+ "dependencies": {
+ "repeating": {
+ "version": "1.1.3",
+ "from": "repeating@^1.1.0",
+ "resolved": "https://registry.npmjs.org/repeating/-/repeating-1.1.3.tgz",
+ "dependencies": {
+ "is-finite": {
+ "version": "1.0.1",
+ "from": "is-finite@^1.0.0",
+ "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.1.tgz",
+ "dependencies": {
+ "number-is-nan": {
+ "version": "1.0.0",
+ "from": "number-is-nan@^1.0.0",
+ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "lodash._reescape": {
+ "version": "3.0.0",
+ "from": "lodash._reescape@^3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz"
+ },
+ "lodash._reevaluate": {
+ "version": "3.0.0",
+ "from": "lodash._reevaluate@^3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz"
+ },
+ "lodash._reinterpolate": {
+ "version": "3.0.0",
+ "from": "lodash._reinterpolate@^3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz"
+ },
+ "lodash.template": {
+ "version": "3.6.2",
+ "from": "lodash.template@^3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz",
+ "dependencies": {
+ "lodash._basecopy": {
+ "version": "3.0.1",
+ "from": "lodash._basecopy@^3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz"
+ },
+ "lodash._basetostring": {
+ "version": "3.0.1",
+ "from": "lodash._basetostring@^3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz"
+ },
+ "lodash._basevalues": {
+ "version": "3.0.0",
+ "from": "lodash._basevalues@^3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz"
+ },
+ "lodash._isiterateecall": {
+ "version": "3.0.9",
+ "from": "lodash._isiterateecall@^3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz"
+ },
+ "lodash.escape": {
+ "version": "3.0.0",
+ "from": "lodash.escape@^3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.0.0.tgz"
+ },
+ "lodash.keys": {
+ "version": "3.1.2",
+ "from": "lodash.keys@^3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz",
+ "dependencies": {
+ "lodash._getnative": {
+ "version": "3.9.1",
+ "from": "lodash._getnative@^3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz"
+ },
+ "lodash.isarguments": {
+ "version": "3.0.4",
+ "from": "lodash.isarguments@^3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.0.4.tgz"
+ },
+ "lodash.isarray": {
+ "version": "3.0.4",
+ "from": "lodash.isarray@^3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz"
+ }
+ }
+ },
+ "lodash.restparam": {
+ "version": "3.6.1",
+ "from": "lodash.restparam@^3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz"
+ },
+ "lodash.templatesettings": {
+ "version": "3.1.0",
+ "from": "lodash.templatesettings@^3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.0.tgz"
+ }
+ }
+ },
+ "multipipe": {
+ "version": "0.1.2",
+ "from": "multipipe@^0.1.2",
+ "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz",
+ "dependencies": {
+ "duplexer2": {
+ "version": "0.0.2",
+ "from": "duplexer2@0.0.2",
+ "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz",
+ "dependencies": {
+ "readable-stream": {
+ "version": "1.1.13",
+ "from": "readable-stream@~1.1.9",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz",
+ "dependencies": {
+ "core-util-is": {
+ "version": "1.0.1",
+ "from": "core-util-is@~1.0.0",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz"
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "from": "isarray@0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz"
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "from": "string_decoder@~0.10.x",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz"
+ },
+ "inherits": {
+ "version": "2.0.1",
+ "from": "inherits@~2.0.1",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "object-assign": {
+ "version": "3.0.0",
+ "from": "object-assign@^3.0.0",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz"
+ },
+ "replace-ext": {
+ "version": "0.0.1",
+ "from": "replace-ext@0.0.1",
+ "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz"
+ },
+ "through2": {
+ "version": "2.0.0",
+ "from": "through2@^2.0.0",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.0.tgz",
+ "dependencies": {
+ "readable-stream": {
+ "version": "2.0.2",
+ "from": "readable-stream@~2.0.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.2.tgz",
+ "dependencies": {
+ "core-util-is": {
+ "version": "1.0.1",
+ "from": "core-util-is@~1.0.0",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz"
+ },
+ "inherits": {
+ "version": "2.0.1",
+ "from": "inherits@~2.0.1",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "from": "isarray@0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz"
+ },
+ "process-nextick-args": {
+ "version": "1.0.2",
+ "from": "process-nextick-args@~1.0.0",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.2.tgz"
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "from": "string_decoder@~0.10.x",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz"
+ },
+ "util-deprecate": {
+ "version": "1.0.1",
+ "from": "util-deprecate@~1.0.1",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.1.tgz"
+ }
+ }
+ },
+ "xtend": {
+ "version": "4.0.0",
+ "from": "xtend@>=4.0.0 <4.1.0-0",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz"
+ }
+ }
+ },
+ "vinyl": {
+ "version": "0.5.0",
+ "from": "vinyl@^0.5.0",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.0.tgz",
+ "dependencies": {
+ "clone": {
+ "version": "1.0.2",
+ "from": "clone@^1.0.0",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz"
+ },
+ "clone-stats": {
+ "version": "0.0.1",
+ "from": "clone-stats@^0.0.1",
+ "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz"
+ }
+ }
+ }
+ }
+ },
+ "interpret": {
+ "version": "0.6.5",
+ "from": "interpret@^0.6.2",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-0.6.5.tgz"
+ },
+ "liftoff": {
+ "version": "2.1.0",
+ "from": "liftoff@^2.1.0",
+ "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.1.0.tgz",
+ "dependencies": {
+ "extend": {
+ "version": "2.0.1",
+ "from": "extend@^2.0.1",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-2.0.1.tgz"
+ },
+ "findup-sync": {
+ "version": "0.2.1",
+ "from": "findup-sync@^0.2.1",
+ "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.2.1.tgz",
+ "dependencies": {
+ "glob": {
+ "version": "4.3.5",
+ "from": "glob@~4.3.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-4.3.5.tgz",
+ "dependencies": {
+ "inflight": {
+ "version": "1.0.4",
+ "from": "inflight@^1.0.4",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz",
+ "dependencies": {
+ "wrappy": {
+ "version": "1.0.1",
+ "from": "wrappy@1",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz"
+ }
+ }
+ },
+ "inherits": {
+ "version": "2.0.1",
+ "from": "inherits@2",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
+ },
+ "minimatch": {
+ "version": "2.0.10",
+ "from": "minimatch@^2.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz",
+ "dependencies": {
+ "brace-expansion": {
+ "version": "1.1.0",
+ "from": "brace-expansion@^1.0.0",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz",
+ "dependencies": {
+ "balanced-match": {
+ "version": "0.2.0",
+ "from": "balanced-match@^0.2.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz"
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "from": "concat-map@0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
+ }
+ }
+ }
+ }
+ },
+ "once": {
+ "version": "1.3.2",
+ "from": "once@^1.3.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.3.2.tgz",
+ "dependencies": {
+ "wrappy": {
+ "version": "1.0.1",
+ "from": "wrappy@1",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "flagged-respawn": {
+ "version": "0.3.1",
+ "from": "flagged-respawn@^0.3.1",
+ "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.1.tgz"
+ },
+ "rechoir": {
+ "version": "0.6.2",
+ "from": "rechoir@^0.6.0",
+ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz"
+ },
+ "resolve": {
+ "version": "1.1.6",
+ "from": "resolve@^1.1.6",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.6.tgz"
+ }
+ }
+ },
+ "minimist": {
+ "version": "1.1.2",
+ "from": "minimist@^1.1.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.2.tgz"
+ },
+ "orchestrator": {
+ "version": "0.3.7",
+ "from": "orchestrator@^0.3.0",
+ "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.7.tgz",
+ "dependencies": {
+ "end-of-stream": {
+ "version": "0.1.5",
+ "from": "end-of-stream@~0.1.5",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz",
+ "dependencies": {
+ "once": {
+ "version": "1.3.2",
+ "from": "once@~1.3.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.3.2.tgz",
+ "dependencies": {
+ "wrappy": {
+ "version": "1.0.1",
+ "from": "wrappy@1",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz"
+ }
+ }
+ }
+ }
+ },
+ "sequencify": {
+ "version": "0.0.7",
+ "from": "sequencify@~0.0.7",
+ "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz"
+ },
+ "stream-consume": {
+ "version": "0.1.0",
+ "from": "stream-consume@~0.1.0",
+ "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz"
+ }
+ }
+ },
+ "pretty-hrtime": {
+ "version": "1.0.0",
+ "from": "pretty-hrtime@^1.0.0",
+ "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.0.tgz"
+ },
+ "semver": {
+ "version": "4.3.6",
+ "from": "semver@^4.1.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz"
+ },
+ "tildify": {
+ "version": "1.1.0",
+ "from": "tildify@^1.0.0",
+ "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.1.0.tgz",
+ "dependencies": {
+ "os-homedir": {
+ "version": "1.0.1",
+ "from": "os-homedir@^1.0.0",
+ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.1.tgz"
+ }
+ }
+ },
+ "v8flags": {
+ "version": "2.0.9",
+ "from": "v8flags@^2.0.2",
+ "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.0.9.tgz",
+ "dependencies": {
+ "user-home": {
+ "version": "1.1.1",
+ "from": "user-home@^1.1.1",
+ "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz"
+ }
+ }
+ },
+ "vinyl-fs": {
+ "version": "0.3.13",
+ "from": "vinyl-fs@^0.3.0",
+ "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.13.tgz",
+ "dependencies": {
+ "defaults": {
+ "version": "1.0.2",
+ "from": "defaults@^1.0.0",
+ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.2.tgz",
+ "dependencies": {
+ "clone": {
+ "version": "0.1.19",
+ "from": "clone@~0.1.5",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-0.1.19.tgz"
+ }
+ }
+ },
+ "glob-stream": {
+ "version": "3.1.18",
+ "from": "glob-stream@^3.1.5",
+ "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz",
+ "dependencies": {
+ "glob": {
+ "version": "4.5.3",
+ "from": "glob@^4.3.1",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz",
+ "dependencies": {
+ "inflight": {
+ "version": "1.0.4",
+ "from": "inflight@^1.0.4",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz",
+ "dependencies": {
+ "wrappy": {
+ "version": "1.0.1",
+ "from": "wrappy@1",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz"
+ }
+ }
+ },
+ "inherits": {
+ "version": "2.0.1",
+ "from": "inherits@2",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
+ },
+ "once": {
+ "version": "1.3.2",
+ "from": "once@^1.3.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.3.2.tgz",
+ "dependencies": {
+ "wrappy": {
+ "version": "1.0.1",
+ "from": "wrappy@1",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz"
+ }
+ }
+ }
+ }
+ },
+ "minimatch": {
+ "version": "2.0.10",
+ "from": "minimatch@^2.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz",
+ "dependencies": {
+ "brace-expansion": {
+ "version": "1.1.0",
+ "from": "brace-expansion@^1.0.0",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz",
+ "dependencies": {
+ "balanced-match": {
+ "version": "0.2.0",
+ "from": "balanced-match@^0.2.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz"
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "from": "concat-map@0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
+ }
+ }
+ }
+ }
+ },
+ "ordered-read-streams": {
+ "version": "0.1.0",
+ "from": "ordered-read-streams@^0.1.0",
+ "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz"
+ },
+ "glob2base": {
+ "version": "0.0.12",
+ "from": "glob2base@^0.0.12",
+ "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz",
+ "dependencies": {
+ "find-index": {
+ "version": "0.1.1",
+ "from": "find-index@^0.1.1",
+ "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz"
+ }
+ }
+ },
+ "unique-stream": {
+ "version": "1.0.0",
+ "from": "unique-stream@^1.0.0",
+ "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz"
+ }
+ }
+ },
+ "glob-watcher": {
+ "version": "0.0.6",
+ "from": "glob-watcher@^0.0.6",
+ "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz",
+ "dependencies": {
+ "gaze": {
+ "version": "0.5.1",
+ "from": "gaze@^0.5.1",
+ "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.1.tgz",
+ "dependencies": {
+ "globule": {
+ "version": "0.1.0",
+ "from": "globule@~0.1.0",
+ "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz",
+ "dependencies": {
+ "lodash": {
+ "version": "1.0.2",
+ "from": "lodash@~1.0.1",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz"
+ },
+ "glob": {
+ "version": "3.1.21",
+ "from": "glob@~3.1.21",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz",
+ "dependencies": {
+ "graceful-fs": {
+ "version": "1.2.3",
+ "from": "graceful-fs@~1.2.0",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz"
+ },
+ "inherits": {
+ "version": "1.0.0",
+ "from": "inherits@1",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.0.tgz"
+ }
+ }
+ },
+ "minimatch": {
+ "version": "0.2.14",
+ "from": "minimatch@~0.2.11",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz",
+ "dependencies": {
+ "lru-cache": {
+ "version": "2.6.5",
+ "from": "lru-cache@2",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.5.tgz"
+ },
+ "sigmund": {
+ "version": "1.0.1",
+ "from": "sigmund@~1.0.0",
+ "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "graceful-fs": {
+ "version": "3.0.8",
+ "from": "graceful-fs@^3.0.0",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.8.tgz"
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "from": "mkdirp@^0.5.0",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "dependencies": {
+ "minimist": {
+ "version": "0.0.8",
+ "from": "minimist@0.0.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz"
+ }
+ }
+ },
+ "strip-bom": {
+ "version": "1.0.0",
+ "from": "strip-bom@^1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz",
+ "dependencies": {
+ "first-chunk-stream": {
+ "version": "1.0.0",
+ "from": "first-chunk-stream@^1.0.0",
+ "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz"
+ },
+ "is-utf8": {
+ "version": "0.2.0",
+ "from": "is-utf8@^0.2.0",
+ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.0.tgz"
+ }
+ }
+ },
+ "through2": {
+ "version": "0.6.5",
+ "from": "through2@^0.6.1",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
+ "dependencies": {
+ "readable-stream": {
+ "version": "1.0.33",
+ "from": "readable-stream@>=1.0.33-1 <1.1.0-0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz",
+ "dependencies": {
+ "core-util-is": {
+ "version": "1.0.1",
+ "from": "core-util-is@~1.0.0",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz"
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "from": "isarray@0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz"
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "from": "string_decoder@~0.10.x",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz"
+ },
+ "inherits": {
+ "version": "2.0.1",
+ "from": "inherits@~2.0.1",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
+ }
+ }
+ },
+ "xtend": {
+ "version": "4.0.0",
+ "from": "xtend@>=4.0.0 <4.1.0-0",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz"
+ }
+ }
+ },
+ "vinyl": {
+ "version": "0.4.6",
+ "from": "vinyl@^0.4.0",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz",
+ "dependencies": {
+ "clone": {
+ "version": "0.2.0",
+ "from": "clone@^0.2.0",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz"
+ },
+ "clone-stats": {
+ "version": "0.0.1",
+ "from": "clone-stats@^0.0.1",
+ "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
"javascript-state-machine": {
"version": "2.3.5",
"from": "javascript-state-machine@",
diff --git a/package.json b/package.json
index af576e5..91b1369 100644
--- a/package.json
+++ b/package.json
@@ -10,8 +10,8 @@
"scripts": {
"test": "NODE_ENV=test mocha spec/",
"start": "npm run compile && node index.js",
- "compile:dev": "node_modules/react-tools/bin/jsx --watch --no-cache-dir --source-map-inline -x jsx lib/react/ public/js/",
- "compile": "node_modules/react-tools/bin/jsx -x jsx lib/react/ public/js/",
+ "watch": "node_modules/gulp/bin/gulp.js watch",
+ "compile": "node_modules/gulp/bin/gulp.js",
"dev": "nodemon index.js"
},
"repository": {
@@ -29,16 +29,22 @@
"express": "~4.13.1",
"express-handlebars": "~2.0.1",
"extend": "^3.0.0",
+ "gulp": "^3.9.0",
+ "gulp-concat": "^2.6.0",
+ "gulp-react": "^3.0.1",
"javascript-state-machine": "^2.3.5",
"morgan": "~1.6.1",
"node-mysql": "~0.4.2",
"react-tools": "~0.13.3",
"request": "~2.60.0",
"socket.io": "~1.3.5",
+ "gulp-watch": "^4.3.4",
"winston": "~1.0.1"
},
"devDependencies": {
"chai": "~3.1.0",
+ "gulp": "^3.9.0",
+ "gulp-plumber": "^1.0.1",
"mocha": "~2.2.5",
"nodemon": "~1.3.7",
"supertest": "~1.0.1"
diff --git a/public/css/app.css b/public/css/app.css
index 750a8af..5eb4315 100644
--- a/public/css/app.css
+++ b/public/css/app.css
@@ -19,4 +19,14 @@
.signin {
margin: 0px 10px;
+}
+
+.user-online {
+ border-radius: 50%;
+ width: 10px;
+ height: 10px;
+
+ background-image: -moz-radial-gradient(45px 45px 45deg, circle cover, yellow 0%, orange 100%, red 95%);
+ background-image: -webkit-radial-gradient(45px 45px, circle cover, yellow, orange);
+ background-image: radial-gradient(45px 45px 45deg, circle cover, yellow 0%, orange 100%, red 95%);
}
\ No newline at end of file
diff --git a/public/js/app.js b/public/js/app.js
index 988e1a8..0314448 100644
--- a/public/js/app.js
+++ b/public/js/app.js
@@ -1,93 +1,382 @@
-$(function () {
-
"use strict";
-var UserCounter = React.createClass({displayName: "UserCounter",
+var VoteButton = React.createClass({displayName: "VoteButton",
+ cancelVote: function (e) {
+ socket.emit("gather:vote", {
+ leader: {
+ candidate: null
+ }
+ });
+ },
+ vote: function (e) {
+ e.preventDefault();
+ socket.emit("gather:vote", {
+ leader: {
+ candidate: parseInt(e.target.value, 10)
+ }
+ });
+ },
render: function () {
- return (
- React.createElement("li", null,
- React.createElement("a", {href: "#"},
- React.createElement("i", {className: "fa fa-users fa-fw"}), " Online",
- React.createElement("span", {className: "badge add-left"}, " ", this.props.count, " ")
+ if (this.props.currentGatherer === null) {
+ return false;
+ }
+ if (this.props.currentGatherer.leaderVote === this.props.candidate.id) {
+ return (
+ React.createElement("button", {
+ onClick: this.cancelVote,
+ className: "btn btn-xs btn-success"}, "Voted"
)
- )
- );
+ );
+ } else {
+ return (
+ React.createElement("button", {
+ onClick: this.vote,
+ className: "btn btn-xs btn-default",
+ value: this.props.candidate.id}, "Vote"
+ )
+ );
+ }
}
});
-var UserLogin = React.createClass({displayName: "UserLogin",
- authorizeId: function (id) {
- id = parseInt(id, 10);
- socket.emit("users:authorize", {
- id: id
- });
- },
- handleSubmit: function (e) {
+var JoinGatherButton = React.createClass({displayName: "JoinGatherButton",
+ joinGather: function (e) {
e.preventDefault();
- var id = React.findDOMNode(this.refs.authorize_id).value.trim();
- if (!id) return;
- React.findDOMNode(this.refs.authorize_id).value = '';
- this.authorizeId(id);
- return;
+ socket.emit("gather:join", {});
},
render: function () {
+ var message = this.props.buttonName || "Join Gather";
+ var buttonClass = "btn btn-primary";
+ if (this.props.buttonClass) {
+ buttonClass += " " + this.props.buttonClass;
+ }
+ return (React.createElement("button", {
+ onClick: this.joinGather,
+ className: buttonClass}, message))
+ }
+});
+
+var SelectPlayerButton = React.createClass({displayName: "SelectPlayerButton",
+ selectPlayer: function (e) {
+ e.preventDefault();
+ },
+ render: function () {
+ if (!this.props.currentGatherer.leader) {
+ return false;
+ } else {
+ return (React.createElement("button", {
+ onClick: this.selectPlayer,
+ className: "btn btn-xs btn-primary"}, " Select"
+ )
+ );
+ }
+ }
+})
+
+var GatherTeams = React.createClass({displayName: "GatherTeams",
+ alienGatherers: function () {
+ return this.props.gather.gatherers.filter(function (gatherer) {
+ return gatherer.team === "alien";
+ }).sort(function (gatherer) {
+ return (gatherer.leader) ? 1 : 0;
+ });
+ },
+ marineGatherers: function () {
+ return this.props.gather.gatherers.filter(function (gatherer) {
+ return gatherer.team === "marine";
+ }).sort(function (gatherer) {
+ return (gatherer.leader) ? 1 : 0;
+ });
+ },
+ render: function () {
+ var extractGatherer = function (gatherer) {
+ var image;
+ if (gatherer.leader) {
+ image = (React.createElement("img", {src: "/images/commander.png",
+ alt: "Commander",
+ height: "20",
+ width: "20"}));
+ }
+ return (
+ React.createElement("tr", {key: gatherer.id},
+ React.createElement("td", {className: "col-md-1"}, image),
+ React.createElement("td", {className: "col-md-11"}, gatherer.user.username)
+ )
+ );
+ }
+ var marines = this.marineGatherers().map(extractGatherer);
+ var aliens = this.alienGatherers().map(extractGatherer);
return (
- React.createElement("form", {onSubmit: this.handleSubmit},
- React.createElement("div", {className: "input-group signin"},
- React.createElement("input", {
- id: "btn-input",
- type: "text",
- className: "form-control",
- ref: "authorize_id",
- placeholder: "Choose an ID..."}),
- React.createElement("span", {className: "input-group-btn"},
- React.createElement("input", {
- type: "submit",
- className: "btn btn-primary",
- id: "btn-chat",
- value: "Login"})
+ React.createElement("div", {className: "panel-body"},
+ React.createElement("div", {className: "row"},
+ React.createElement("div", {className: "col-md-6"},
+ React.createElement("div", {className: "panel panel-default"},
+ React.createElement("div", {className: "panel-heading"},
+ "Aliens"
+ ),
+ React.createElement("table", {className: "table"},
+ React.createElement("tbody", null,
+ aliens
+ )
+ )
+ )
+ ),
+ React.createElement("div", {className: "col-md-6"},
+ React.createElement("div", {className: "panel panel-default"},
+ React.createElement("div", {className: "panel-heading"},
+ "Marines"
+ ),
+ React.createElement("table", {className: "table"},
+ React.createElement("tbody", null,
+ marines
+ )
+ )
+ )
)
- ),
- React.createElement("div", {className: "signin"},
- React.createElement("p", {className: "text-center"}, React.createElement("small", null, "Just a temporary measure until genuine authentication is implemented"))
)
)
);
}
})
-var UserMenu = React.createClass({displayName: "UserMenu",
- getDefaultProps: function () {
+var GatherProgress = React.createClass({displayName: "GatherProgress",
+ stateDescription: function () {
+ switch(this.props.gather.state) {
+ case "gathering":
+ return "Waiting for more gatherers.";
+ case "election":
+ return "Currently voting for team leaders.";
+ case "selection":
+ return "Waiting for leaders to picking teams.";
+ case "done":
+ return "Gather completed.";
+ default:
+ return "Initialising gather.";
+ }
+ },
+ gatheringProgress: function () {
+ var num = this.props.gather.gatherers.length;
+ var den = 12;
+ var remaining = den - num;
+ var message = (remaining === 1) ? "Waiting for last player" : "Waiting for " + remaining + " more players";
return {
- count: 0,
- users: []
+ num: num,
+ den: den,
+ message: message
};
},
- componentDidMount: function () {
- socket.on('users:update', this.updateUsers);
+ electionProgress: function () {
+ var num = this.props.gather.gatherers.reduce(function (acc, gatherer) {
+ if (gatherer.leaderVote) acc++;
+ return acc;
+ }, 0);
+ var den = 12;
+ return {
+ num: num,
+ den: den,
+ message: den - num + " more votes required"
+ };
},
- updateUsers: function (data) {
- this.setProps({
- count: data.count,
- users: data.users
- });
+ selectionProgress: function () {
+ var num = this.props.gather.gatherers.reduce(function (acc, gatherer) {
+ if (gatherer.team !== "lobby") acc++;
+ return acc;
+ }, 0);
+ var den = 12;
+
+ return {
+ num: num,
+ den: den,
+ message: num + " out of " + den + " players assigned"
+ };
},
render: function () {
- var users = this.props.users.map(function (user) {
+ var progress;
+ var gatherState = this.props.gather.state;
+ if (gatherState === 'gathering' && this.props.gather.gatherers.length) {
+ progress = this.gatheringProgress();
+ } else if (gatherState === 'election') {
+ progress = this.electionProgress();
+ } else if (gatherState === 'selection') {
+ progress = this.selectionProgress();
+ }
+ if (progress) {
+ var style = {
+ width: Math.round((progress.num / progress.den * 100)) + "%"
+ };
return (
- React.createElement("li", {key: user.id}, React.createElement("a", {href: "#"}, user.username))
+ React.createElement("div", {className: "panel-body"},
+ React.createElement("p", null, React.createElement("strong", null, this.stateDescription()), " ", progress.message),
+ React.createElement("div", {className: "progress"},
+ React.createElement("div", {className: "progress-bar progress-bar-striped active",
+ "data-role": "progressbar",
+ "data-aria-valuenow": progress.num,
+ "data-aria-valuemin": "0",
+ "data-aria-valuemax": progress.den,
+ style: style}
+ )
+ )
+ )
);
+ } else {
+ return false;
+ }
+ }
+});
+
+var Gather = React.createClass({displayName: "Gather",
+ getDefaultProps: function () {
+ return {
+ gather: {
+ gatherers: []
+ }
+ }
+ },
+ joinedGather: function () {
+ return this.props.currentGatherer !== null;
+ },
+ componentDidMount: function () {
+ var self = this;
+ socket.on("gather:refresh", function (data) {
+ self.setProps({
+ gather: data.gather,
+ currentGatherer: data.currentGatherer
+ });
});
+ },
+ leaveGather: function (e) {
+ e.preventDefault();
+ socket.emit("gather:leave", {});
+ },
+ inviteToGather: function (e) {
+ e.preventDefault();
+ },
+ render: function () {
+ var joinButton;
+ if (this.joinedGather()) {
+ joinButton = (React.createElement("li", null, React.createElement("button", {
+ onClick: this.leaveGather,
+ className: "btn btn-danger"}, "Leave Gather")));
+ } else {
+ joinButton = (React.createElement("li", null, React.createElement(JoinGatherButton, null)));
+ }
+ var inviteButton;
+ if (this.props.gather.state === 'gathering') {
+ inviteButton = (React.createElement("li", null, React.createElement("button", {
+ onClick: this.inviteToGather,
+ className: "btn btn-primary"}, "Invite to Gather")));
+ }
+ var gatherTeams;
+ if (this.props.gather.state === 'selection') {
+ gatherTeams = React.createElement(GatherTeams, {gather: this.props.gather})
+ }
return (
- React.createElement("ul", {className: "nav", id: "side-menu"},
- React.createElement(UserCounter, React.__spread({}, this.props)),
- users,
- React.createElement("li", null, React.createElement("br", null), React.createElement(UserLogin, null), React.createElement("br", null))
+ React.createElement("div", {className: "panel panel-default"},
+ React.createElement("div", {className: "panel-heading"},
+ React.createElement("strong", null, "NS2 Gather "),
+ React.createElement("span", {className: "badge add-left"}, this.props.gather.gatherers.length)
+ ),
+ React.createElement(Gatherers, {gather: this.props.gather, currentGatherer: this.props.currentGatherer}),
+ gatherTeams,
+ React.createElement(GatherProgress, {gather: this.props.gather}),
+ React.createElement("div", {className: "panel-footer text-right"},
+ React.createElement("ul", {className: "list-inline"},
+ inviteButton,
+ joinButton
+ )
+ )
)
);
}
});
+var Gatherers = React.createClass({displayName: "Gatherers",
+ render: function () {
+ var self = this;
+ var gatherers = this.props.gather.gatherers.map(function (gatherer) {
+ var lifeforms = (
+ gatherer.user.ability.lifeforms.map(function (lifeform) {
+ return (React.createElement("span", {className: "label label-default"}, lifeform));
+ })
+ );
+
+ // Switch this to online status
+ var online= (React.createElement("span", {src: "/images/commander.png",
+ alt: "online",
+ className: "user-online"}, " "));
+
+ var division = (React.createElement("span", {className: "label label-primary"}, gatherer.user.ability.division));
+ var action = lifeforms;
+ if (self.props.gather.state === "election") {
+ var votes = self.props.gather.gatherers.reduce(function (acc, voter) {
+ if (voter.leaderVote === gatherer.id) acc++;
+ return acc;
+ }, 0)
+ action = (
+ React.createElement("span", null,
+ React.createElement("small", null, votes + " votes", " "),
+ React.createElement(VoteButton, {currentGatherer: self.props.currentGatherer, candidate: gatherer})
+ )
+ );
+ }
+
+ return (
+ React.createElement("tr", {key: gatherer.user.id},
+ React.createElement("td", {className: "col-md-1"}, online),
+ React.createElement("td", {className: "col-md-5"}, gatherer.user.username),
+ React.createElement("td", {className: "col-md-3"}, division, " "),
+ React.createElement("td", {className: "col-md-2 text-right"}, action, " ")
+ )
+ );
+ })
+ if (this.props.gather.gatherers.length) {
+ return (
+ React.createElement("div", {className: "panel-body"},
+ React.createElement("div", {className: "panel panel-default"},
+ React.createElement("div", {className: "panel-heading"},
+ React.createElement("h5", {className: "panel-title"}, "Roster")
+ ),
+ React.createElement("table", {className: "table roster-table"},
+ React.createElement("tbody", null,
+ gatherers
+ )
+ )
+ )
+ )
+ );
+ } else {
+ return (React.createElement("div", {className: "panel-body text-center"}, React.createElement(JoinGatherButton, {buttonClass: "btn-lg", buttonName: "Start a Gather"})));
+ }
+ }
+});
+
+
+
+
+"use strict";
+
+var socket;
+
+function initialiseComponents () {
+ var socketUrl = window.location.protocol + "//" + window.location.host;
+ socket = io(socketUrl)
+ .on("connect", function () {
+ console.log("Connected");
+ })
+ .on("reconnect", function () {
+ console.log("Reconnected");
+ })
+ .on("disconnect", function () {
+ console.log("Disconnected")
+ });
+
+ React.render(React.createElement(UserMenu, null), document.getElementById('side-menu'));
+ React.render(React.createElement(Chatroom, null), document.getElementById('chatroom'));
+ React.render(React.createElement(Gather, null), document.getElementById('gathers'));
+ React.render(React.createElement(CurrentUser, null), document.getElementById('currentuser'));
+};
+"use strict";
+
var Chatroom = React.createClass({displayName: "Chatroom",
getDefaultProps: function () {
return {
@@ -196,69 +485,6 @@ var ChatMessage = React.createClass({displayName: "ChatMessage",
}
});
-var CurrentUser = React.createClass({displayName: "CurrentUser",
- componentDidMount: function () {
- var self = this;
- socket.on("users:update", function (data) {
- self.setProps({
- user: data.currentUser
- });
- });
- socket.emit("users:refresh", {});
- },
- render: function () {
- if (this.props.user) {
- return (
- React.createElement("a", {href: "#"}, this.props.user.username, " ", React.createElement("img", {src: this.props.user.avatar,
- alt: "User Avatar",
- height: "20",
- width: "20"}))
- );
- } else {
- return false;
- }
- }
-});
-
-var VoteButton = React.createClass({displayName: "VoteButton",
- cancelVote: function (e) {
- socket.emit("gather:vote", {
- leader: {
- candidate: null
- }
- });
- },
- vote: function (e) {
- e.preventDefault();
- socket.emit("gather:vote", {
- leader: {
- candidate: parseInt(e.target.value, 10)
- }
- });
- },
- render: function () {
- if (this.props.currentGatherer === null) {
- return false;
- }
- if (this.props.currentGatherer.leaderVote === this.props.candidate.id) {
- return (
- React.createElement("button", {
- onClick: this.cancelVote,
- className: "btn btn-xs btn-success"}, "Voted"
- )
- );
- } else {
- return (
- React.createElement("button", {
- onClick: this.vote,
- className: "btn btn-xs btn-default",
- value: this.props.candidate.id}, "Vote"
- )
- );
- }
- }
-});
-
var MessageBar = React.createClass({displayName: "MessageBar",
sendMessage: function (content) {
socket.emit("message:new", {
@@ -296,280 +522,114 @@ var MessageBar = React.createClass({displayName: "MessageBar",
}
});
-var JoinGatherButton = React.createClass({displayName: "JoinGatherButton",
- joinGather: function (e) {
- e.preventDefault();
- socket.emit("gather:join", {});
- },
+"use strict";
+
+var UserCounter = React.createClass({displayName: "UserCounter",
render: function () {
- var message = this.props.buttonName || "Join Gather";
- var buttonClass = "btn btn-primary";
- if (this.props.buttonClass) {
- buttonClass += " " + this.props.buttonClass;
- }
- return (React.createElement("button", {
- onClick: this.joinGather,
- className: buttonClass}, message))
+ return (
+ React.createElement("li", null,
+ React.createElement("a", {href: "#"},
+ React.createElement("i", {className: "fa fa-users fa-fw"}), " Online",
+ React.createElement("span", {className: "badge add-left"}, " ", this.props.count, " ")
+ )
+ )
+ );
}
});
-var GatherProgress = React.createClass({displayName: "GatherProgress",
- gatheringProgress: function () {
- var num = this.props.gather.gatherers.length;
- var den = 12;
- return {
- num: num,
- den: den,
- message: num + " / " + den
- };
+var UserLogin = React.createClass({displayName: "UserLogin",
+ authorizeId: function (id) {
+ id = parseInt(id, 10);
+ socket.emit("users:authorize", {
+ id: id
+ });
},
- electionProgress: function () {
- var num = this.props.gather.gatherers.reduce(function (acc, gatherer) {
- if (gatherer.leaderVote) acc++;
- return acc;
- }, 0);
- var den = 12;
- return {
- num: num,
- den: den,
- message: den - num + " more votes required"
- };
- },
- selectionProgress: function () {
- var num = this.props.gather.gatherers.reduce(function (acc, gatherer) {
- if (gatherer.team !== "lobby") acc++;
- return acc;
- }, 0);
- var den = 12;
-
- return {
- num: num,
- den: den,
- message: num + " out of " + den + " players assigned"
- };
+ handleSubmit: function (e) {
+ e.preventDefault();
+ var id = React.findDOMNode(this.refs.authorize_id).value.trim();
+ if (!id) return;
+ React.findDOMNode(this.refs.authorize_id).value = '';
+ this.authorizeId(id);
+ return;
},
render: function () {
- var progress;
- var gatherState = this.props.gather.state;
- if (gatherState === 'gathering' && this.props.gather.gatherers.length) {
- progress = this.gatheringProgress();
- } else if (gatherState === 'election') {
- progress = this.electionProgress();
- } else if (gatherState === 'selection') {
- progress = this.selectionProgress();
- }
- if (progress) {
- var style = {
- width: Math.round((progress.num / progress.den * 100)) + "%"
- };
- return (
- React.createElement("div", {className: "panel-body"},
- React.createElement("p", null, "Gather Progress"),
- React.createElement("div", {className: "progress"},
- React.createElement("div", {className: "progress-bar progress-bar-striped active",
- "data-role": "progressbar",
- "data-aria-valuenow": progress.num,
- "data-aria-valuemin": "0",
- "data-aria-valuemax": progress.den,
- style: style},
- progress.message
- )
- )
+ return (
+ React.createElement("form", {onSubmit: this.handleSubmit},
+ React.createElement("div", {className: "input-group signin"},
+ React.createElement("input", {
+ id: "btn-input",
+ type: "text",
+ className: "form-control",
+ ref: "authorize_id",
+ placeholder: "Choose an ID..."}),
+ React.createElement("span", {className: "input-group-btn"},
+ React.createElement("input", {
+ type: "submit",
+ className: "btn btn-primary",
+ id: "btn-chat",
+ value: "Login"})
+ )
+ ),
+ React.createElement("div", {className: "signin"},
+ React.createElement("p", {className: "text-center"}, React.createElement("small", null, "Just a temporary measure until genuine authentication is implemented"))
)
+ )
+ );
+ }
+})
+
+var UserMenu = React.createClass({displayName: "UserMenu",
+ getDefaultProps: function () {
+ return {
+ count: 0,
+ users: []
+ };
+ },
+ componentDidMount: function () {
+ socket.on('users:update', this.updateUsers);
+ },
+ updateUsers: function (data) {
+ this.setProps({
+ count: data.count,
+ users: data.users
+ });
+ },
+ render: function () {
+ var users = this.props.users.map(function (user) {
+ return (
+ React.createElement("li", {key: user.id}, React.createElement("a", {href: "#"}, user.username))
+ );
+ });
+ return (
+ React.createElement("ul", {className: "nav", id: "side-menu"},
+ React.createElement(UserCounter, React.__spread({}, this.props)),
+ users,
+ React.createElement("li", null, React.createElement("br", null), React.createElement(UserLogin, null), React.createElement("br", null))
+ )
+ );
+ }
+});
+
+var CurrentUser = React.createClass({displayName: "CurrentUser",
+ componentDidMount: function () {
+ var self = this;
+ socket.on("users:update", function (data) {
+ self.setProps({
+ user: data.currentUser
+ });
+ });
+ socket.emit("users:refresh", {});
+ },
+ render: function () {
+ if (this.props.user) {
+ return (
+ React.createElement("a", {href: "#"}, this.props.user.username, " ", React.createElement("img", {src: this.props.user.avatar,
+ alt: "User Avatar",
+ height: "20",
+ width: "20"}))
);
} else {
return false;
}
}
});
-
-var Gather = React.createClass({displayName: "Gather",
- getDefaultProps: function () {
- return {
- gather: {
- gatherers: []
- }
- }
- },
- joinedGather: function () {
- var self = this;
- return this.props.gather.gatherers.some(function (gatherer) {
- return gatherer.user.id === self.props.currentUser.id;
- });
- },
- componentDidMount: function () {
- var self = this;
- socket.on("gather:refresh", function (data) {
- self.setProps({
- gather: data.gather,
- currentUser: data.currentUser
- });
- });
- },
- stateDescription: function () {
- switch(this.props.gather.state) {
- case "gathering":
- return "Waiting for more gatherers";
- case "election":
- return "Currently voting for team leaders";
- case "selection":
- return "Waiting for leaders to picking teams";
- case "done":
- return "Gather completed";
- default:
- return "Initialising gather";
- }
- },
- leaveGather: function (e) {
- e.preventDefault();
- socket.emit("gather:leave", {});
- },
- inviteToGather: function (e) {
- e.preventDefault();
- },
- currentGatherer: function () {
- var current = null;
- var self = this;
- this.props.gather.gatherers.forEach(function (gatherer) {
- if (gatherer.id === self.props.currentUser.id) current = gatherer;
- });
- return current;
- },
- render: function () {
- var joinButton;
- if (this.joinedGather()) {
- joinButton = (React.createElement("li", null, React.createElement("button", {
- onClick: this.leaveGather,
- className: "btn btn-danger"}, "Leave Gather")));
- } else {
- joinButton = (React.createElement("li", null, React.createElement(JoinGatherButton, null)));
- }
- var inviteButton;
- if (this.props.gather.state === 'gathering') {
- inviteButton = (React.createElement("li", null, React.createElement("button", {
- onClick: this.inviteToGather,
- className: "btn btn-primary"}, "Invite to Gather")));
- }
- return (
- React.createElement("div", {className: "panel panel-default"},
- React.createElement("div", {className: "panel-heading"},
- React.createElement("strong", null, "NS2 Gather "),
- React.createElement("span", {className: "badge add-left"}, this.props.gather.gatherers.length),
- React.createElement("br", null),
- this.stateDescription()
- ),
- React.createElement(Gatherers, {gather: this.props.gather, currentGatherer: this.currentGatherer()}),
- React.createElement(GatherProgress, {gather: this.props.gather}),
- React.createElement("div", {className: "panel-footer text-right"},
- React.createElement("ul", {className: "list-inline"},
- inviteButton,
- joinButton
- )
- )
- )
- );
- }
-});
-
-var LeaderPoll = React.createClass({displayName: "LeaderPoll",
- render: function () {
- return (
- React.createElement("div", {className: "panel-body"}
- )
- );
- }
-});
-
-var Gatherers = React.createClass({displayName: "Gatherers",
- render: function () {
- var self = this;
- var gatherers = this.props.gather.gatherers.map(function (gatherer) {
- var lifeforms = (
- gatherer.user.ability.lifeforms.map(function (lifeform) {
- return (React.createElement("span", {className: "label label-default"}, lifeform));
- })
- );
-
- var commBadge;
- if (gatherer.user.ability.commander) {
- commBadge = (React.createElement("img", {src: "/images/commander.png",
- alt: "Commander",
- height: "20",
- width: "20"}));
- }
-
- var division = (React.createElement("span", {className: "label label-primary"}, gatherer.user.ability.division));
- var action = lifeforms;
- if (self.props.gather.state === "election") {
- var votes = self.props.gather.gatherers.reduce(function (acc, voter) {
- if (voter.leaderVote === gatherer.id) acc++;
- return acc;
- }, 0)
- action = (
- React.createElement("div", {className: "text-right"},
- React.createElement("small", null, votes + " votes", " "),
-
- React.createElement(VoteButton, {currentGatherer: self.props.currentGatherer, candidate: gatherer})
- )
- );
- }
-
- return (
- React.createElement("tr", {key: gatherer.user.id},
- React.createElement("td", {className: "col-md-1"}, commBadge),
- React.createElement("td", {className: "col-md-5"}, gatherer.user.username),
- React.createElement("td", {className: "col-md-3"}, division, " "),
- React.createElement("td", {className: "col-md-2"}, action, " ")
- )
- );
- })
- if (this.props.gather.gatherers.length) {
- return (
- React.createElement("div", {className: "panel-body"},
- React.createElement("div", {className: "panel panel-default"},
- React.createElement("div", {className: "panel-heading"},
- React.createElement("h5", {className: "panel-title"}, "Roster")
- ),
- React.createElement("table", {className: "table roster-table"},
- React.createElement("tbody", null,
- gatherers
- )
- )
- )
- )
- );
- } else {
- return (React.createElement("div", {className: "panel-body text-center"}, React.createElement(JoinGatherButton, {buttonClass: "btn-lg", buttonName: "Start a Gather"})));
- }
- }
-});
-
-var socket;
-
-function initialiseComponents () {
- var socketUrl = window.location.protocol + "//" + window.location.host;
- socket = io(socketUrl)
- .on("connect", function () {
- console.log("Connected");
- })
- .on("reconnect", function () {
- console.log("Reconnected");
- })
- .on("disconnect", function () {
- console.log("Disconnected")
- });
-
- React.render(React.createElement(UserMenu, null), document.getElementById('side-menu'));
- React.render(React.createElement(Chatroom, null), document.getElementById('chatroom'));
- React.render(React.createElement(Gather, null), document.getElementById('gathers'));
- React.render(React.createElement(CurrentUser, null), document.getElementById('currentuser'));
-};
-
-initialiseComponents();
-
-
-
-});
-
-
-//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNmb3JtZWQuanMiLCJzb3VyY2VzIjpbbnVsbF0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLENBQUMsQ0FBQyxZQUFZOztBQUVkLFlBQVksQ0FBQzs7QUFFYixJQUFJLGlDQUFpQywyQkFBQTtDQUNwQyxNQUFNLEVBQUUsWUFBWTtFQUNuQjtHQUNDLG9CQUFBLElBQUcsRUFBQSxJQUFDLEVBQUE7SUFDSCxvQkFBQSxHQUFFLEVBQUEsQ0FBQSxDQUFDLElBQUEsRUFBSSxDQUFDLEdBQUksQ0FBQSxFQUFBO0tBQ1gsb0JBQUEsR0FBRSxFQUFBLENBQUEsQ0FBQyxTQUFBLEVBQVMsQ0FBQyxtQkFBb0IsQ0FBSSxDQUFBLEVBQUEsU0FBQSxFQUFBLENBQUE7QUFBQSxLQUNyQyxvQkFBQSxNQUFLLEVBQUEsQ0FBQSxDQUFDLFNBQUEsRUFBUyxDQUFDLGdCQUFpQixDQUFBLEVBQUEsR0FBQSxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFDLEdBQVEsQ0FBQTtJQUN6RCxDQUFBO0dBQ0EsQ0FBQTtJQUNKO0VBQ0Y7QUFDRixDQUFDLENBQUMsQ0FBQzs7QUFFSCxJQUFJLCtCQUErQix5QkFBQTtDQUNsQyxXQUFXLEVBQUUsVUFBVSxFQUFFLEVBQUU7RUFDMUIsRUFBRSxHQUFHLFFBQVEsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7RUFDdEIsTUFBTSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsRUFBRTtHQUM5QixFQUFFLEVBQUUsRUFBRTtHQUNOLENBQUMsQ0FBQztFQUNIO0NBQ0QsWUFBWSxFQUFFLFVBQVUsQ0FBQyxFQUFFO0VBQzFCLENBQUMsQ0FBQyxjQUFjLEVBQUUsQ0FBQztFQUNuQixJQUFJLEVBQUUsR0FBRyxLQUFLLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO0VBQ2hFLElBQUksQ0FBQyxFQUFFLEVBQUUsT0FBTztFQUNoQixLQUFLLENB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QUFFLFlBQVk7R0FDN0IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUM7QUFDOUIsR0FBRyxDQUFDLENBQUM7O0NBRUosS0FBSyxDQUFDLE1BQU0sQ0FBQyxvQkFBQyxRQUFRLEVBQUEsSUFBQSxDQUFHLENBQUEsRUFBRSxRQUFRLENBQUMsY0FBYyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUM7Q0FDakUsS0FBSyxDQUFDLE1BQU0sQ0FBQyxvQkFBQyxRQUFRLEVBQUEsSUFBQSxDQUFHLENBQUEsRUFBRSxRQUFRLENBQUMsY0FBYyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7Q0FDaEUsS0FBSyxDQUFDLE1BQU0sQ0FBQyxvQkFBQyxNQUFNLEVBQUEsSUFBQSxDQUFHLENBQUEsRUFBRSxRQUFRLENBQUMsY0FBYyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7Q0FDN0QsS0FBSyxDQUFDLE1BQU0sQ0FBQyxvQkFBQyxXQUFXLEVBQUEsSUFBQSxDQUFHLENBQUEsRUFBRSxRQUFRLENBQUMsY0FBYyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7QUFDdkUsQ0FBQyxDQUFDOztBQUVGLG9CQUFvQixFQUFFLENBQUM7QUFDdkI7QUFDQTs7QUFFQSxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIiQoZnVuY3Rpb24gKCkge1xuXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIFVzZXJDb3VudGVyID0gUmVhY3QuY3JlYXRlQ2xhc3Moe1xuXHRyZW5kZXI6IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gKFxuXHRcdFx0PGxpPlxuXHRcdFx0XHQ8YSBocmVmPVwiI1wiPlxuXHRcdFx0XHRcdDxpIGNsYXNzTmFtZT1cImZhIGZhLXVzZXJzIGZhLWZ3XCI+PC9pPiBPbmxpbmUgXG5cdFx0XHRcdFx0PHNwYW4gY2xhc3NOYW1lPVwiYmFkZ2UgYWRkLWxlZnRcIj4ge3RoaXMucHJvcHMuY291bnR9IDwvc3Bhbj5cblx0XHRcdFx0PC9hPlxuXHRcdFx0PC9saT5cblx0XHQpO1xuXHR9XG59KTtcblxudmFyIFVzZXJMb2dpbiA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtcblx0YXV0aG9yaXplSWQ6IGZ1bmN0aW9uIChpZCkge1xuXHRcdGlkID0gcGFyc2VJbnQoaWQsIDEwKTtcblx0XHRzb2NrZXQuZW1pdChcInVzZXJzOmF1dGhvcml6ZVwiLCB7XG5cdFx0XHRpZDogaWRcblx0XHR9KTtcblx0fSxcblx0aGFuZGxlU3VibWl0OiBmdW5jdGlvbiAoZSkge1xuXHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHR2YXIgaWQgPSBSZWFjdC5maW5kRE9NTm9kZSh0aGlzLnJlZnMuYXV0aG9yaXplX2lkKS52YWx1ZS50cmltKCk7XG5cdFx0aWYgKCFpZCkgcmV0dXJuO1xuXHRcdFJlYWN0LmZpbmRET01Ob2RlKHRoaXMucmVmcy5hdXRob3JpemVfaWQpLnZhbHVlID0gJyc7XG5cdFx0dGhpcy5hdXRob3JpemVJZChpZCk7XG5cdFx0cmV0dXJuO1xuXHR9LFxuXHRyZW5kZXI6IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gKFxuXHRcdFx0PGZvcm0gb25TdWJtaXQ9e3RoaXMuaGFuZGxlU3VibWl0fSA+XG5cdFx0XHRcdDxkaXYgY2xhc3NOYW1lPVwiaW5wdXQtZ3JvdXAgc2lnbmluXCI+XG5cdFx0XHRcdFx0PGlucHV0IFxuXHRcdFx0XHRcdFx0aWQ9XCJidG4taW5wdXRcIiBcblx0XHRcdFx0XHRcdHR5cGU9XCJ0ZXh0XCIgXG5cdFx0XHRcdFx0XHRjbGFzc05hbWU9XCJmb3JtLWNvbnRyb2xcIiBcblx0XHRcdFx0XHRcdHJlZj1cImF1dGhvcml6ZV9pZFwiXG5cdFx0XHRcdFx0XHRwbGFjZWhvbGRlcj1cIkNob29zZSBhbiBJRC4uLlwiIC8+XG5cdFx0XHRcdFx0PHNwYW4gY2xhc3NOYW1lPVwiaW5wdXQtZ3JvdXAtYnRuXCI+XG5cdFx0XHRcdFx0XHQ8aW5wdXQgXG5cdFx0XHRcdFx0XHRcdHR5cGU9XCJzdWJtaXRcIiBcblx0XHRcdFx0XHRcdFx0Y2xhc3NOYW1lPVwiYnRuIGJ0bi1wcmltYXJ5XCIgXG5cdFx0XHRcdFx0XHRcdGlkPVwiYnRuLWNoYXRcIiBcblx0XHRcdFx0XHRcdFx0dmFsdWU9XCJMb2dpblwiIC8+XG5cdFx0XHRcdFx0PC9zcGFuPlxuXHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0PGRpdiBjbGFzc05hbWU9XCJzaWduaW5cIj5cblx0XHRcdFx0PHAgY2xhc3NOYW1lPVwidGV4dC1jZW50ZXJcIj48c21hbGw+SnVzdCBhIHRlbXBvcmFyeSBtZWFzdXJlIHVudGlsIGdlbnVpbmUgYXV0aGVudGljYXRpb24gaXMgaW1wbGVtZW50ZWQ8L3NtYWxsPjwvcD5cblx0XHRcdFx0PC9kaXY+XG5cdFx0XHQ8L2Zvcm0+XG5cdFx0KTtcblx0fVxufSlcblxudmFyIFVzZXJNZW51ID0gUmVhY3QuY3JlYXRlQ2xhc3Moe1xuXHRnZXREZWZhdWx0UHJvcHM6IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4ge1xuXHRcdFx0Y291bnQ6IDAsXG5cdFx0XHR1c2VyczogW11cblx0XHR9O1xuXHR9LFxuXHRjb21wb25lbnREaWRNb3VudDogZnVuY3Rpb24gKCkge1xuXHRcdHNvY2tldC5vbigndXNlcnM6dXBkYXRlJywgdGhpcy51cGRhdGVVc2Vycyk7XG5cdH0sXG5cdHVwZGF0ZVVzZXJzOiBmdW5jdGlvbiAoZGF0YSkge1xuXHRcdHRoaXMuc2V0UHJvcHMoe1xuXHRcdFx0Y291bnQ6IGRhdGEuY291bnQsXG5cdFx0XHR1c2VyczogZGF0YS51c2Vyc1xuXHRcdH0pO1xuXHR9LFxuXHRyZW5kZXI6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgdXNlcnMgPSB0aGlzLnByb3BzLnVzZXJzLm1hcChmdW5jdGlvbiAodXNlcikge1xuXHRcdFx0cmV0dXJuIChcblx0XHRcdFx0PGxpIGtleT17dXNlci5pZH0+PGEgaHJlZj1cIiNcIj57dXNlci51c2VybmFtZX08L2E+PC9saT5cblx0XHRcdCk7XG5cdFx0fSk7XG5cdFx0cmV0dXJuIChcblx0XHRcdDx1bCBjbGFzc05hbWU9XCJuYXZcIiBpZD1cInNpZGUtbWVudVwiPlxuXHRcdFx0XHQ8VXNlckNvdW50ZXIgey4uLnRoaXMucHJvcHN9IC8+XG5cdFx0XHRcdHt1c2Vyc31cblx0XHRcdFx0PGxpPjxiciAvPjxVc2VyTG9naW4gLz48YnIgLz48L2xpPlxuXHRcdFx0PC91bD5cblx0XHQpO1xuXHR9XG59KTtcblxudmFyIENoYXRyb29tID0gUmVhY3QuY3JlYXRlQ2xhc3Moe1xuXHRnZXREZWZhdWx0UHJvcHM6IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4ge1xuXHRcdFx0aGlzdG9yeTogW11cblx0XHR9O1xuXHR9LFxuXHRjb21wb25lbnREaWRNb3VudDogZnVuY3Rpb24gKCkge1xuXHRcdHZhciBzZWxmID0gdGhpcztcblx0XHR2YXIgVElNRVJfSU5URVJWQUwgPSA2MDAwMDsgLy8gRXZlcnkgbWludXRlXG5cblx0XHRzb2NrZXQub24oXCJtZXNzYWdlOm5ld1wiLCBmdW5jdGlvbiAoZGF0YSkge1xuXHRcdFx0dmFyIGhpc3RvcnkgPSBzZWxmLnByb3BzLmhpc3Rvcnk7XG5cdFx0XHRoaXN0b3J5LnB1c2goZGF0YSk7XG5cdFx0XHRzZWxmLnNldFByb3BzKHtcblx0XHRcdFx0aGlzdG9yeTogaGlzdG9yeVxuXHRcdFx0fSk7XG5cdFx0XHRzZWxmLnNjcm9sbFRvQm90dG9tKCk7XG5cdFx0fSk7XG5cblx0XHQvLyBNZXNzYWdlIEhpc3RvcnkgUmV0cmlldmVkXG5cdFx0c29ja2V0Lm9uKFwibWVzc2FnZTpyZWZyZXNoXCIsIGZ1bmN0aW9uIChkYXRhKSB7XG5cdFx0XHRzZWxmLnNldFByb3BzKHtcblx0XHRcdFx0aGlzdG9yeTogZGF0YS5jaGF0SGlzdG9yeVxuXHRcdFx0fSk7XG5cdFx0XHRzZWxmLnNjcm9sbFRvQm90dG9tKCk7XG5cdFx0fSk7XG5cblx0XHRzb2NrZXQuZW1pdChcIm1lc3NhZ2U6cmVmcmVzaFwiLCB7fSk7XG5cblx0XHRzZWxmLnRpbWVyID0gc2V0SW50ZXJ2YWwoZnVuY3Rpb24gKCkge1xuXHRcdFx0aWYgKHNlbGYucmVmcy5tZXNzYWdlcykgc2VsZi5yZWZzLm1lc3NhZ2VzLnJlZnJlc2hUaW1lKCk7XG5cdFx0fSwgVElNRVJfSU5URVJWQUwpO1xuXHR9LFxuXG5cdGNvbXBvbmVudERpZFVubW91bnQ6IGZ1bmN0aW9uICgpIHtcblx0XHRjbGVhckludGVydmFsKHRoaXMudGltZXIpO1xuXHR9LFxuXHRzZW5kTWVzc2FnZTogZnVuY3Rpb24gKG1lc3NhZ2UpIHtcblx0XHRzb2NrZXQuZW1pdChcIm5ld01lc3NhZ2VcIiwge21lc3NhZ2U6IG1lc3NhZ2V9KTtcblx0fSxcblx0c2Nyb2xsVG9Cb3R0b206IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgbm9kZSA9IFJlYWN0LmZpbmRET01Ob2RlKHRoaXMucmVmcy5tZXNzYWdlQ29udGFpbmVyKTtcblx0ICBub2RlLnNjcm9sbFRvcCA9IG5vZGUuc2Nyb2xsSGVpZ2h0O1xuXHR9LFxuXHRyZW5kZXI6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgbWVzc2FnZXMgPSB0aGlzLnByb3BzLmhpc3RvcnkubWFwKGZ1bmN0aW9uIChtZXNzYWdlKSB7XG5cdFx0XHRyZXR1cm4gKFxuXHRcdFx0XHQ8Q2hhdE1lc3NhZ2UgXG5cdFx0XHRcdFx0YXZhdGFyPXttZXNzYWdlLmF1dGhvci5hdmF0YXJ9IFxuXHRcdFx0XHRcdHVzZXJuYW1lPXttZXNzYWdlLmF1dGhvci51c2VybmFtZX1cblx0XHRcdFx0XHRjb250ZW50PXttZXNzYWdlLmNvbnRlbnR9XG5cdFx0XHRcdFx0cmVmPVwibWVzc2FnZXNcIlxuXHRcdFx0XHRcdGNyZWF0ZWRBdD17bWVzc2FnZS5jcmVhdGVkQXR9IC8+XG5cdFx0XHQpO1xuXHRcdH0pO1xuXHRcdHJldHVybiAoXG5cdFx0XHQ8ZGl2IGNsYXNzTmFtZT1cInBhbmVsIHBhbmVsLWRlZmF1bHRcIj5cblx0XHRcdFx0PGRpdiBjbGFzc05hbWU9XCJwYW5lbC1oZWFkaW5nXCI+R2F0aGVyIENoYXQ8L2Rpdj5cblx0XHRcdFx0PGRpdiBjbGFzc05hbWU9XCJwYW5lbC1ib2R5XCI+XG5cdFx0XHRcdFx0PHVsIGNsYXNzTmFtZT1cImNoYXRcIiBpZD1cImNoYXRtZXNzYWdlc1wiIHJlZj1cIm1lc3NhZ2VDb250YWluZXJcIj5cblx0XHRcdFx0XHRcdHttZXNzYWdlc31cblx0XHRcdFx0XHQ8L3VsPlxuXHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0PGRpdiBjbGFzc05hbWU9XCJwYW5lbC1mb290ZXJcIj5cblx0XHRcdFx0XHQ8TWVzc2FnZUJhciAvPlxuXHRcdFx0XHQ8L2Rpdj5cblx0XHRcdDwvZGl2PlxuXHRcdCk7XG5cdH1cbn0pO1xuXG52YXIgQ2hhdE1lc3NhZ2UgPSBSZWFjdC5jcmVhdGVDbGFzcyh7XG5cdGdldEluaXRpYWxTdGF0ZTogZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiB7XG5cdFx0XHR0aW1lQWdvOiAkLnRpbWVhZ28odGhpcy5wcm9wcy5jcmVhdGVkQXQpXG5cdFx0fVxuXHR9LFxuXHRyZWZyZXNoVGltZTogZnVuY3Rpb24gKCkge1xuXHRcdHZhciBzZWxmID0gdGhpcztcblx0XHRzZWxmLnNldFN0YXRlKHtcblx0XHRcdHRpbWVBZ286ICQudGltZWFnbyhzZWxmLnByb3BzLmNyZWF0ZWRBdClcblx0XHR9KTtcblx0fSxcblx0cmVuZGVyOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIChcblx0XHRcdDxsaSBjbGFzc05hbWU9XCJsZWZ0IGNsZWFyZml4XCI+XG5cdFx0XHRcdDxzcGFuIGNsYXNzTmFtZT1cImNoYXQtaW1nIHB1bGwtbGVmdFwiPlxuXHRcdFx0XHRcdFx0PGltZyBcblx0XHRcdFx0XHRcdFx0c3JjPXt0aGlzLnByb3BzLmF2YXRhcn0gXG5cdFx0XHRcdFx0XHRcdGFsdD1cIlVzZXIgQXZhdGFyXCIgXG5cdFx0XHRcdFx0XHRcdGhlaWdodD1cIjQwXCJcblx0XHRcdFx0XHRcdFx0d2lkdGg9XCI0MFwiXG5cdFx0XHRcdFx0XHRcdGNsYXNzTmFtZT1cImltZy1jaXJjbGVcIiAvPlxuXHRcdFx0XHQ8L3NwYW4+XG5cdFx0XHRcdDxkaXYgY2xhc3NOYW1lPVwiY2hhdC1ib2R5IGNsZWFyZml4XCI+XG5cdFx0XHRcdFx0PGRpdiBjbGFzc05hbWU9XCJoZWFkZXJcIj5cblx0XHRcdFx0XHRcdDxzdHJvbmcgY2xhc3NOYW1lPVwicHJpbWFyeS1mb250XCI+e3RoaXMucHJvcHMudXNlcm5hbWV9PC9zdHJvbmc+XG5cdFx0XHRcdFx0XHQ8c21hbGwgY2xhc3NOYW1lPVwicHVsbC1yaWdodCB0ZXh0LW11dGVkXCI+XG5cdFx0XHRcdFx0XHRcdDxpIGNsYXNzTmFtZT1cImZhIGZhLWNsb2NrLW8gZmEtZndcIj48L2k+IHt0aGlzLnN0YXRlLnRpbWVBZ299XG5cdFx0XHRcdFx0XHQ8L3NtYWxsPlxuXHRcdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHRcdDxwPnt0aGlzLnByb3BzLmNvbnRlbnR9PC9wPlxuXHRcdFx0XHQ8L2Rpdj5cblx0XHRcdDwvbGk+XG5cdFx0KTtcblx0fVxufSk7XG5cbnZhciBDdXJyZW50VXNlciA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtcblx0Y29tcG9uZW50RGlkTW91bnQ6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgc2VsZiA9IHRoaXM7XG5cdFx0c29ja2V0Lm9uKFwidXNlcnM6dXBkYXRlXCIsIGZ1bmN0aW9uIChkYXRhKSB7XG5cdFx0XHRzZWxmLnNldFByb3BzKHtcblx0XHRcdFx0dXNlcjogZGF0YS5jdXJyZW50VXNlclxuXHRcdFx0fSk7XG5cdFx0fSk7XG5cdFx0c29ja2V0LmVtaXQoXCJ1c2VyczpyZWZyZXNoXCIsIHt9KTtcblx0fSxcblx0cmVuZGVyOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMucHJvcHMudXNlcikge1xuXHRcdFx0cmV0dXJuIChcblx0XHRcdFx0PGEgaHJlZj1cIiNcIj57dGhpcy5wcm9wcy51c2VyLnVzZXJuYW1lfSAmbmJzcDs8aW1nIHNyYz17dGhpcy5wcm9wcy51c2VyLmF2YXRhcn1cblx0XHRcdFx0XHRhbHQ9XCJVc2VyIEF2YXRhclwiIFxuXHRcdFx0XHRcdGhlaWdodD1cIjIwXCJcblx0XHRcdFx0XHR3aWR0aD1cIjIwXCIgLz48L2E+XG5cdFx0XHQpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHR9XG59KTtcblxudmFyIFZvdGVCdXR0b24gPSBSZWFjdC5jcmVhdGVDbGFzcyh7XG5cdGNhbmNlbFZvdGU6IGZ1bmN0aW9uIChlKSB7XG5cdFx0c29ja2V0LmVtaXQoXCJnYXRoZXI6dm90ZVwiLCB7XG5cdFx0XHRsZWFkZXI6IHtcblx0XHRcdFx0Y2FuZGlkYXRlOiBudWxsXG5cdFx0XHR9XG5cdFx0fSk7XG5cdH0sXG5cdHZvdGU6IGZ1bmN0aW9uIChlKSB7XG5cdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdHNvY2tldC5lbWl0KFwiZ2F0aGVyOnZvdGVcIiwge1xuXHRcdFx0bGVhZGVyOiB7XG5cdFx0XHRcdGNhbmRpZGF0ZTogcGFyc2VJbnQoZS50YXJnZXQudmFsdWUsIDEwKVxuXHRcdFx0fVxuXHRcdH0pO1xuXHR9LFxuXHRyZW5kZXI6IGZ1bmN0aW9uICgpIHtcblx0XHRpZiAodGhpcy5wcm9wcy5jdXJyZW50R2F0aGVyZXIgPT09IG51bGwpIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdFx0aWYgKHRoaXMucHJvcHMuY3VycmVudEdhdGhlcmVyLmxlYWRlclZvdGUgPT09IHRoaXMucHJvcHMuY2FuZGlkYXRlLmlkKSB7XG5cdFx0XHRyZXR1cm4gKFxuXHRcdFx0XHQ8YnV0dG9uIFxuXHRcdFx0XHRcdG9uQ2xpY2s9e3RoaXMuY2FuY2VsVm90ZX0gXG5cdFx0XHRcdFx0Y2xhc3NOYW1lPVwiYnRuIGJ0bi14cyBidG4tc3VjY2Vzc1wiPlZvdGVkXG5cdFx0XHRcdDwvYnV0dG9uPlxuXHRcdFx0KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIChcblx0XHRcdFx0PGJ1dHRvbiBcblx0XHRcdFx0XHRvbkNsaWNrPXt0aGlzLnZvdGV9IFxuXHRcdFx0XHRcdGNsYXNzTmFtZT1cImJ0biBidG4teHMgYnRuLWRlZmF1bHRcIlxuXHRcdFx0XHRcdHZhbHVlPXt0aGlzLnByb3BzLmNhbmRpZGF0ZS5pZH0+Vm90ZVxuXHRcdFx0XHQ8L2J1dHRvbj5cblx0XHRcdCk7XG5cdFx0fVxuXHR9XG59KTtcblxudmFyIE1lc3NhZ2VCYXIgPSBSZWFjdC5jcmVhdGVDbGFzcyh7XG5cdHNlbmRNZXNzYWdlOiBmdW5jdGlvbiAoY29udGVudCkge1xuXHRcdHNvY2tldC5lbWl0KFwibWVzc2FnZTpuZXdcIiwge1xuXHRcdFx0Y29udGVudDogY29udGVudFxuXHRcdH0pO1xuXHR9LFxuXHRoYW5kbGVTdWJtaXQ6IGZ1bmN0aW9uIChlKSB7XG5cdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdHZhciBjb250ZW50ID0gUmVhY3QuZmluZERPTU5vZGUodGhpcy5yZWZzLmNvbnRlbnQpLnZhbHVlLnRyaW0oKTtcblx0XHRpZiAoIWNvbnRlbnQpIHJldHVybjtcblx0XHRSZWFjdC5maW5kRE9NTm9kZSh0aGlzLnJlZnMuY29udGVudCkudmFsdWUgPSAnJztcblx0XHR0aGlzLnNlbmRNZXNzYWdlKGNvbnRlbnQpO1xuXHRcdHJldHVybjtcblx0fSxcblx0cmVuZGVyOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIChcblx0XHRcdDxmb3JtIG9uU3VibWl0PXt0aGlzLmhhbmRsZVN1Ym1pdH0gPlxuXHRcdFx0XHQ8ZGl2IGNsYXNzTmFtZT1cImlucHV0LWdyb3VwXCI+XG5cdFx0XHRcdFx0PGlucHV0IFxuXHRcdFx0XHRcdFx0aWQ9XCJidG4taW5wdXRcIiBcblx0XHRcdFx0XHRcdHR5cGU9XCJ0ZXh0XCIgXG5cdFx0XHRcdFx0XHRjbGFzc05hbWU9XCJmb3JtLWNvbnRyb2xcIiBcblx0XHRcdFx0XHRcdHJlZj1cImNvbnRlbnRcIlxuXHRcdFx0XHRcdFx0cGxhY2Vob2xkZXI9XCJCZSBwb2xpdGUgcGxlYXNlLi4uXCIgLz5cblx0XHRcdFx0XHQ8c3BhbiBjbGFzc05hbWU9XCJpbnB1dC1ncm91cC1idG5cIj5cblx0XHRcdFx0XHRcdDxpbnB1dCBcblx0XHRcdFx0XHRcdFx0dHlwZT1cInN1Ym1pdFwiIFxuXHRcdFx0XHRcdFx0XHRjbGFzc05hbWU9XCJidG4gYnRuLXByaW1hcnlcIiBcblx0XHRcdFx0XHRcdFx0aWQ9XCJidG4tY2hhdFwiIFxuXHRcdFx0XHRcdFx0XHR2YWx1ZT1cIlNlbmRcIiAvPlxuXHRcdFx0XHRcdDwvc3Bhbj5cblx0XHRcdFx0PC9kaXY+XG5cdFx0XHQ8L2Zvcm0+XG5cdFx0KTtcblx0fVxufSk7XG5cbnZhciBKb2luR2F0aGVyQnV0dG9uID0gUmVhY3QuY3JlYXRlQ2xhc3Moe1xuXHRqb2luR2F0aGVyOiBmdW5jdGlvbiAoZSkge1xuXHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRzb2NrZXQuZW1pdChcImdhdGhlcjpqb2luXCIsIHt9KTtcblx0fSxcblx0cmVuZGVyOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIG1lc3NhZ2UgPSB0aGlzLnByb3BzLmJ1dHRvbk5hbWUgfHwgXCJKb2luIEdhdGhlclwiO1xuXHRcdHZhciBidXR0b25DbGFzcyA9IFwiYnRuIGJ0bi1wcmltYXJ5XCI7XG5cdFx0aWYgKHRoaXMucHJvcHMuYnV0dG9uQ2xhc3MpIHtcblx0XHRcdGJ1dHRvbkNsYXNzICs9IFwiIFwiICsgdGhpcy5wcm9wcy5idXR0b25DbGFzcztcblx0XHR9XG5cdFx0cmV0dXJuICg8YnV0dG9uIFxuXHRcdFx0XHRcdFx0XHRvbkNsaWNrPXt0aGlzLmpvaW5HYXRoZXJ9IFxuXHRcdFx0XHRcdFx0XHRjbGFzc05hbWU9e2J1dHRvbkNsYXNzfT57bWVzc2FnZX08L2J1dHRvbj4pXG5cdH1cbn0pO1xuXG52YXIgR2F0aGVyUHJvZ3Jlc3MgPSBSZWFjdC5jcmVhdGVDbGFzcyh7XG5cdGdhdGhlcmluZ1Byb2dyZXNzOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIG51bSA9IHRoaXMucHJvcHMuZ2F0aGVyLmdhdGhlcmVycy5sZW5ndGg7XG5cdFx0dmFyIGRlbiA9IDEyO1xuXHRcdHJldHVybiB7XG5cdFx0XHRudW06IG51bSxcblx0XHRcdGRlbjogZGVuLFxuXHRcdFx0bWVzc2FnZTogbnVtICsgXCIgLyBcIiArIGRlblxuXHRcdH07XG5cdH0sXG5cdGVsZWN0aW9uUHJvZ3Jlc3M6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgbnVtID0gdGhpcy5wcm9wcy5nYXRoZXIuZ2F0aGVyZXJzLnJlZHVjZShmdW5jdGlvbiAoYWNjLCBnYXRoZXJlcikge1xuXHRcdFx0aWYgKGdhdGhlcmVyLmxlYWRlclZvdGUpIGFjYysrO1xuXHRcdFx0cmV0dXJuIGFjYztcblx0XHR9LCAwKTtcblx0XHR2YXIgZGVuID0gMTI7XG5cdFx0cmV0dXJuIHtcblx0XHRcdG51bTogbnVtLFxuXHRcdFx0ZGVuOiBkZW4sXG5cdFx0XHRtZXNzYWdlOiBkZW4gLSBudW0gKyBcIiBtb3JlIHZvdGVzIHJlcXVpcmVkXCJcblx0XHR9O1xuXHR9LFxuXHRzZWxlY3Rpb25Qcm9ncmVzczogZnVuY3Rpb24gKCkge1xuXHRcdHZhciBudW0gPSB0aGlzLnByb3BzLmdhdGhlci5nYXRoZXJlcnMucmVkdWNlKGZ1bmN0aW9uIChhY2MsIGdhdGhlcmVyKSB7XG5cdFx0XHRpZiAoZ2F0aGVyZXIudGVhbSAhPT0gXCJsb2JieVwiKSBhY2MrKztcblx0XHRcdHJldHVybiBhY2M7XG5cdFx0fSwgMCk7XG5cdFx0dmFyIGRlbiA9IDEyO1xuXG5cdFx0cmV0dXJuIHtcblx0XHRcdG51bTogbnVtLFxuXHRcdFx0ZGVuOiBkZW4sXG5cdFx0XHRtZXNzYWdlOiBudW0gKyBcIiBvdXQgb2YgXCIgKyBkZW4gKyBcIiBwbGF5ZXJzIGFzc2lnbmVkXCJcblx0XHR9O1xuXHR9LFxuXHRyZW5kZXI6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgcHJvZ3Jlc3M7XG5cdFx0dmFyIGdhdGhlclN0YXRlID0gdGhpcy5wcm9wcy5nYXRoZXIuc3RhdGU7XG5cdFx0aWYgKGdhdGhlclN0YXRlID09PSAnZ2F0aGVyaW5nJyAmJiB0aGlzLnByb3BzLmdhdGhlci5nYXRoZXJlcnMubGVuZ3RoKSB7XG5cdFx0XHRwcm9ncmVzcyA9IHRoaXMuZ2F0aGVyaW5nUHJvZ3Jlc3MoKTtcblx0XHR9IGVsc2UgaWYgKGdhdGhlclN0YXRlID09PSAnZWxlY3Rpb24nKSB7XG5cdFx0XHRwcm9ncmVzcyA9IHRoaXMuZWxlY3Rpb25Qcm9ncmVzcygpO1xuXHRcdH0gZWxzZSBpZiAoZ2F0aGVyU3RhdGUgPT09ICdzZWxlY3Rpb24nKSB7XG5cdFx0XHRwcm9ncmVzcyA9IHRoaXMuc2VsZWN0aW9uUHJvZ3Jlc3MoKTtcblx0XHR9XG5cdFx0aWYgKHByb2dyZXNzKSB7XG5cdFx0XHR2YXIgc3R5bGUgPSB7XG5cdFx0XHRcdHdpZHRoOiBNYXRoLnJvdW5kKChwcm9ncmVzcy5udW0gLyBwcm9ncmVzcy5kZW4gKiAxMDApKSArIFwiJVwiXG5cdFx0XHR9O1xuXHRcdFx0cmV0dXJuIChcblx0XHRcdFx0PGRpdiBjbGFzc05hbWU9XCJwYW5lbC1ib2R5XCI+XG5cdFx0XHRcdFx0PHA+R2F0aGVyIFByb2dyZXNzPC9wPlxuXHRcdFx0XHRcdDxkaXYgY2xhc3NOYW1lPVwicHJvZ3Jlc3NcIj5cblx0XHRcdFx0XHQgIDxkaXYgY2xhc3NOYW1lPVwicHJvZ3Jlc3MtYmFyIHByb2dyZXNzLWJhci1zdHJpcGVkIGFjdGl2ZVwiIFxuXHRcdFx0XHRcdCAgXHRkYXRhLXJvbGU9XCJwcm9ncmVzc2JhclwiIFxuXHRcdFx0XHRcdCAgXHRkYXRhLWFyaWEtdmFsdWVub3c9e3Byb2dyZXNzLm51bX0gXG5cdFx0XHRcdFx0ICBcdGRhdGEtYXJpYS12YWx1ZW1pbj1cIjBcIiBcblx0XHRcdFx0XHQgIFx0ZGF0YS1hcmlhLXZhbHVlbWF4PXtwcm9ncmVzcy5kZW59IFxuXHRcdFx0XHRcdCAgXHRzdHlsZT17c3R5bGV9PlxuXHRcdFx0XHRcdCAgICB7cHJvZ3Jlc3MubWVzc2FnZX1cblx0XHRcdFx0XHQgIDwvZGl2PlxuXHRcdFx0XHQgIDwvZGl2PlxuXHRcdFx0XHQ8L2Rpdj5cblx0XHRcdCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdH1cbn0pO1xuXG52YXIgR2F0aGVyID0gUmVhY3QuY3JlYXRlQ2xhc3Moe1xuXHRnZXREZWZhdWx0UHJvcHM6IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4ge1xuXHRcdFx0Z2F0aGVyOiB7XG5cdFx0XHRcdGdhdGhlcmVyczogW11cblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cdGpvaW5lZEdhdGhlcjogZnVuY3Rpb24gKCkge1xuXHRcdHZhciBzZWxmID0gdGhpcztcblx0XHRyZXR1cm4gdGhpcy5wcm9wcy5nYXRoZXIuZ2F0aGVyZXJzLnNvbWUoZnVuY3Rpb24gKGdhdGhlcmVyKSB7XG5cdFx0XHRyZXR1cm4gZ2F0aGVyZXIudXNlci5pZCA9PT0gc2VsZi5wcm9wcy5jdXJyZW50VXNlci5pZDtcblx0XHR9KTtcblx0fSxcblx0Y29tcG9uZW50RGlkTW91bnQ6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgc2VsZiA9IHRoaXM7XG5cdFx0c29ja2V0Lm9uKFwiZ2F0aGVyOnJlZnJlc2hcIiwgZnVuY3Rpb24gKGRhdGEpIHtcblx0XHRcdHNlbGYuc2V0UHJvcHMoe1xuXHRcdFx0XHRnYXRoZXI6IGRhdGEuZ2F0aGVyLFxuXHRcdFx0XHRjdXJyZW50VXNlcjogZGF0YS5jdXJyZW50VXNlclxuXHRcdFx0fSk7XG5cdFx0fSk7XG5cdH0sXG5cdHN0YXRlRGVzY3JpcHRpb246IGZ1bmN0aW9uICgpIHtcblx0XHRzd2l0Y2godGhpcy5wcm9wcy5nYXRoZXIuc3RhdGUpIHtcblx0XHRcdGNhc2UgXCJnYXRoZXJpbmdcIjpcblx0XHRcdFx0cmV0dXJuIFwiV2FpdGluZyBmb3IgbW9yZSBnYXRoZXJlcnNcIjtcblx0XHRcdGNhc2UgXCJlbGVjdGlvblwiOlxuXHRcdFx0XHRyZXR1cm4gXCJDdXJyZW50bHkgdm90aW5nIGZvciB0ZWFtIGxlYWRlcnNcIjtcblx0XHRcdGNhc2UgXCJzZWxlY3Rpb25cIjpcblx0XHRcdFx0cmV0dXJuIFwiV2FpdGluZyBmb3IgbGVhZGVycyB0byBwaWNraW5nIHRlYW1zXCI7XG5cdFx0XHRjYXNlIFwiZG9uZVwiOlxuXHRcdFx0XHRyZXR1cm4gXCJHYXRoZXIgY29tcGxldGVkXCI7XG5cdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRyZXR1cm4gXCJJbml0aWFsaXNpbmcgZ2F0aGVyXCI7XG5cdFx0fVxuXHR9LFxuXHRsZWF2ZUdhdGhlcjogZnVuY3Rpb24gKGUpIHtcblx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0c29ja2V0LmVtaXQoXCJnYXRoZXI6bGVhdmVcIiwge30pO1xuXHR9LFxuXHRpbnZpdGVUb0dhdGhlcjogZnVuY3Rpb24gKGUpIHtcblx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdH0sXG5cdGN1cnJlbnRHYXRoZXJlcjogZnVuY3Rpb24gKCkge1xuXHRcdHZhciBjdXJyZW50ID0gbnVsbDtcblx0XHR2YXIgc2VsZiA9IHRoaXM7XG5cdFx0dGhpcy5wcm9wcy5nYXRoZXIuZ2F0aGVyZXJzLmZvckVhY2goZnVuY3Rpb24gKGdhdGhlcmVyKSB7XG5cdFx0XHRpZiAoZ2F0aGVyZXIuaWQgPT09IHNlbGYucHJvcHMuY3VycmVudFVzZXIuaWQpIGN1cnJlbnQgPSBnYXRoZXJlcjtcblx0XHR9KTtcblx0XHRyZXR1cm4gY3VycmVudDtcblx0fSxcblx0cmVuZGVyOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIGpvaW5CdXR0b247XG5cdFx0aWYgKHRoaXMuam9pbmVkR2F0aGVyKCkpIHtcblx0XHRcdGpvaW5CdXR0b24gPSAoPGxpPjxidXR0b24gXG5cdFx0XHRcdFx0XHRcdG9uQ2xpY2s9e3RoaXMubGVhdmVHYXRoZXJ9IFxuXHRcdFx0XHRcdFx0XHRjbGFzc05hbWU9XCJidG4gYnRuLWRhbmdlclwiPkxlYXZlIEdhdGhlcjwvYnV0dG9uPjwvbGk+KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0am9pbkJ1dHRvbiA9ICg8bGk+PEpvaW5HYXRoZXJCdXR0b24gLz48L2xpPik7XG5cdFx0fVxuXHRcdHZhciBpbnZpdGVCdXR0b247XG5cdFx0aWYgKHRoaXMucHJvcHMuZ2F0aGVyLnN0YXRlID09PSAnZ2F0aGVyaW5nJykge1xuXHRcdFx0aW52aXRlQnV0dG9uID0gKDxsaT48YnV0dG9uXG5cdFx0XHRcdFx0XHRcdG9uQ2xpY2s9e3RoaXMuaW52aXRlVG9HYXRoZXJ9XG5cdFx0XHRcdFx0XHRcdGNsYXNzTmFtZT1cImJ0biBidG4tcHJpbWFyeVwiPkludml0ZSB0byBHYXRoZXI8L2J1dHRvbj48L2xpPik7XG5cdFx0fVxuXHRcdHJldHVybiAoXG5cdFx0XHQ8ZGl2IGNsYXNzTmFtZT1cInBhbmVsIHBhbmVsLWRlZmF1bHRcIj5cblx0XHRcdFx0PGRpdiBjbGFzc05hbWU9XCJwYW5lbC1oZWFkaW5nXCI+XG5cdFx0XHRcdFx0PHN0cm9uZz5OUzIgR2F0aGVyIDwvc3Ryb25nPlxuXHRcdFx0XHRcdDxzcGFuIGNsYXNzTmFtZT1cImJhZGdlIGFkZC1sZWZ0XCI+e3RoaXMucHJvcHMuZ2F0aGVyLmdhdGhlcmVycy5sZW5ndGh9PC9zcGFuPlxuXHRcdFx0XHRcdDxiciAvPlxuXHRcdFx0XHRcdHt0aGlzLnN0YXRlRGVzY3JpcHRpb24oKX1cblx0XHRcdFx0PC9kaXY+XG5cdFx0XHRcdDxHYXRoZXJlcnMgZ2F0aGVyPXt0aGlzLnByb3BzLmdhdGhlcn0gY3VycmVudEdhdGhlcmVyPXt0aGlzLmN1cnJlbnRHYXRoZXJlcigpfSAvPlxuXHRcdFx0XHQ8R2F0aGVyUHJvZ3Jlc3MgZ2F0aGVyPXt0aGlzLnByb3BzLmdhdGhlcn0gLz5cblx0XHRcdFx0PGRpdiBjbGFzc05hbWU9XCJwYW5lbC1mb290ZXIgdGV4dC1yaWdodFwiPlxuXHRcdFx0XHRcdDx1bCBjbGFzc05hbWU9XCJsaXN0LWlubGluZVwiPlxuXHRcdFx0XHRcdFx0e2ludml0ZUJ1dHRvbn1cblx0XHRcdFx0XHRcdHtqb2luQnV0dG9ufVxuXHRcdFx0XHRcdDwvdWw+XG5cdFx0XHRcdDwvZGl2PlxuXHRcdFx0PC9kaXY+XG5cdFx0KTtcblx0fVxufSk7XG5cbnZhciBMZWFkZXJQb2xsID0gUmVhY3QuY3JlYXRlQ2xhc3Moe1xuXHRyZW5kZXI6IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gKFxuXHRcdFx0PGRpdiBjbGFzc05hbWU9XCJwYW5lbC1ib2R5XCI+XG5cdFx0XHQ8L2Rpdj5cblx0XHQpO1xuXHR9XG59KTtcblxudmFyIEdhdGhlcmVycyA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtcblx0cmVuZGVyOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIHNlbGYgPSB0aGlzO1xuXHRcdHZhciBnYXRoZXJlcnMgPSB0aGlzLnByb3BzLmdhdGhlci5nYXRoZXJlcnMubWFwKGZ1bmN0aW9uIChnYXRoZXJlcikge1xuXHRcdFx0dmFyIGxpZmVmb3JtcyA9IChcblx0XHRcdFx0Z2F0aGVyZXIudXNlci5hYmlsaXR5LmxpZmVmb3Jtcy5tYXAoZnVuY3Rpb24gKGxpZmVmb3JtKSB7XG5cdFx0XHRcdFx0cmV0dXJuICg8c3BhbiBjbGFzc05hbWU9XCJsYWJlbCBsYWJlbC1kZWZhdWx0XCI+e2xpZmVmb3JtfTwvc3Bhbj4pO1xuXHRcdFx0XHR9KVxuXHRcdFx0KTtcblxuXHRcdFx0dmFyIGNvbW1CYWRnZTtcblx0XHRcdGlmIChnYXRoZXJlci51c2VyLmFiaWxpdHkuY29tbWFuZGVyKSB7XG5cdFx0XHRcdGNvbW1CYWRnZSA9ICg8aW1nIHNyYz1cIi9pbWFnZXMvY29tbWFuZGVyLnBuZ1wiIFxuXHRcdFx0XHRcdFx0XHRhbHQ9XCJDb21tYW5kZXJcIiBcblx0XHRcdFx0XHRcdFx0aGVpZ2h0PVwiMjBcIlxuXHRcdFx0XHRcdFx0XHR3aWR0aD1cIjIwXCIgLz4pO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgZGl2aXNpb24gPSAoPHNwYW4gY2xhc3NOYW1lPVwibGFiZWwgbGFiZWwtcHJpbWFyeVwiPntnYXRoZXJlci51c2VyLmFiaWxpdHkuZGl2aXNpb259PC9zcGFuPik7XG5cdFx0XHR2YXIgYWN0aW9uID0gbGlmZWZvcm1zO1xuXHRcdFx0aWYgKHNlbGYucHJvcHMuZ2F0aGVyLnN0YXRlID09PSBcImVsZWN0aW9uXCIpIHtcblx0XHRcdFx0dmFyIHZvdGVzID0gc2VsZi5wcm9wcy5nYXRoZXIuZ2F0aGVyZXJzLnJlZHVjZShmdW5jdGlvbiAoYWNjLCB2b3Rlcikge1xuXHRcdFx0XHRcdGlmICh2b3Rlci5sZWFkZXJWb3RlID09PSBnYXRoZXJlci5pZCkgYWNjKys7XG5cdFx0XHRcdFx0cmV0dXJuIGFjYztcblx0XHRcdFx0fSwgMClcblx0XHRcdFx0YWN0aW9uID0gKFxuXHRcdFx0XHRcdDxkaXYgY2xhc3NOYW1lPVwidGV4dC1yaWdodFwiPlxuXHRcdFx0XHRcdDxzbWFsbD57dm90ZXMgKyBcIiB2b3Rlc1wifSAmbmJzcDs8L3NtYWxsPlxuXG5cdFx0XHRcdFx0PFZvdGVCdXR0b24gY3VycmVudEdhdGhlcmVyPXtzZWxmLnByb3BzLmN1cnJlbnRHYXRoZXJlcn0gY2FuZGlkYXRlPXtnYXRoZXJlcn0gLz5cblx0XHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0KTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIChcblx0XHRcdFx0PHRyIGtleT17Z2F0aGVyZXIudXNlci5pZH0+XG5cdFx0XHRcdFx0PHRkIGNsYXNzTmFtZT1cImNvbC1tZC0xXCI+e2NvbW1CYWRnZX08L3RkPlxuXHRcdFx0XHRcdDx0ZCBjbGFzc05hbWU9XCJjb2wtbWQtNVwiPntnYXRoZXJlci51c2VyLnVzZXJuYW1lfTwvdGQ+XG5cdFx0XHRcdFx0PHRkIGNsYXNzTmFtZT1cImNvbC1tZC0zXCI+e2RpdmlzaW9ufSZuYnNwOzwvdGQ+XG5cdFx0XHRcdFx0PHRkIGNsYXNzTmFtZT1cImNvbC1tZC0yXCI+e2FjdGlvbn0mbmJzcDs8L3RkPlxuXHRcdFx0XHQ8L3RyPlxuXHRcdFx0KTtcblx0XHR9KVxuXHRcdGlmICh0aGlzLnByb3BzLmdhdGhlci5nYXRoZXJlcnMubGVuZ3RoKSB7XG5cdFx0XHRyZXR1cm4gKFxuXHRcdFx0XHQ8ZGl2IGNsYXNzTmFtZT1cInBhbmVsLWJvZHlcIj5cblx0XHRcdFx0XHQ8ZGl2IGNsYXNzTmFtZT1cInBhbmVsIHBhbmVsLWRlZmF1bHRcIj5cblx0XHRcdFx0XHRcdDxkaXYgY2xhc3NOYW1lPVwicGFuZWwtaGVhZGluZ1wiPlxuXHRcdFx0XHRcdFx0XHQ8aDUgY2xhc3NOYW1lPVwicGFuZWwtdGl0bGVcIj5Sb3N0ZXI8L2g1PlxuXHRcdFx0XHRcdFx0PC9kaXY+XG5cdFx0XHRcdFx0XHQ8dGFibGUgY2xhc3NOYW1lPVwidGFibGUgcm9zdGVyLXRhYmxlXCI+XG5cdFx0XHRcdFx0XHRcdDx0Ym9keT5cblx0XHRcdFx0XHRcdFx0XHR7Z2F0aGVyZXJzfVxuXHRcdFx0XHRcdFx0XHQ8L3Rib2R5PlxuXHRcdFx0XHRcdFx0PC90YWJsZT5cblx0XHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0PC9kaXY+XG5cdFx0XHQpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gKDxkaXYgY2xhc3NOYW1lPVwicGFuZWwtYm9keSB0ZXh0LWNlbnRlclwiPjxKb2luR2F0aGVyQnV0dG9uIGJ1dHRvbkNsYXNzPVwiYnRuLWxnXCIgYnV0dG9uTmFtZT1cIlN0YXJ0IGEgR2F0aGVyXCIgLz48L2Rpdj4pO1xuXHRcdH1cblx0fVxufSk7XG5cbnZhciBzb2NrZXQ7XG5cbmZ1bmN0aW9uIGluaXRpYWxpc2VDb21wb25lbnRzICgpIHtcblx0dmFyIHNvY2tldFVybCA9IHdpbmRvdy5sb2NhdGlvbi5wcm90b2NvbCArIFwiLy9cIiArIHdpbmRvdy5sb2NhdGlvbi5ob3N0O1xuXHRzb2NrZXQgPSBpbyhzb2NrZXRVcmwpXG5cdFx0Lm9uKFwiY29ubmVjdFwiLCBmdW5jdGlvbiAoKSB7XG5cdFx0XHRjb25zb2xlLmxvZyhcIkNvbm5lY3RlZFwiKTtcblx0XHR9KVxuXHRcdC5vbihcInJlY29ubmVjdFwiLCBmdW5jdGlvbiAoKSB7XG5cdFx0XHRjb25zb2xlLmxvZyhcIlJlY29ubmVjdGVkXCIpO1xuXHRcdH0pXG5cdFx0Lm9uKFwiZGlzY29ubmVjdFwiLCBmdW5jdGlvbiAoKSB7XG5cdFx0XHRjb25zb2xlLmxvZyhcIkRpc2Nvbm5lY3RlZFwiKVxuXHRcdH0pO1xuXG5cdFJlYWN0LnJlbmRlcig8VXNlck1lbnUgLz4sIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdzaWRlLW1lbnUnKSk7XG5cdFJlYWN0LnJlbmRlcig8Q2hhdHJvb20gLz4sIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdjaGF0cm9vbScpKTtcblx0UmVhY3QucmVuZGVyKDxHYXRoZXIgLz4sIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdnYXRoZXJzJykpO1xuXHRSZWFjdC5yZW5kZXIoPEN1cnJlbnRVc2VyIC8+LCBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnY3VycmVudHVzZXInKSk7XG59O1xuXG5pbml0aWFsaXNlQ29tcG9uZW50cygpO1xuXG5cblxufSk7XG5cbiJdfQ==
\ No newline at end of file
diff --git a/public/js/client.js b/public/js/client.js
new file mode 100644
index 0000000..9732ed5
--- /dev/null
+++ b/public/js/client.js
@@ -0,0 +1,4 @@
+$(function () {
+ initialiseComponents();
+
+});
diff --git a/public/js/gather.js b/public/js/gather.js
new file mode 100644
index 0000000..88e6e3c
--- /dev/null
+++ b/public/js/gather.js
@@ -0,0 +1,282 @@
+"use strict";
+
+var VoteButton = React.createClass({displayName: "VoteButton",
+ cancelVote: function (e) {
+ socket.emit("gather:vote", {
+ leader: {
+ candidate: null
+ }
+ });
+ },
+ vote: function (e) {
+ e.preventDefault();
+ socket.emit("gather:vote", {
+ leader: {
+ candidate: parseInt(e.target.value, 10)
+ }
+ });
+ },
+ render: function () {
+ if (this.props.currentGatherer === null) {
+ return false;
+ }
+ if (this.props.currentGatherer.leaderVote === this.props.candidate.id) {
+ return (
+ React.createElement("button", {
+ onClick: this.cancelVote,
+ className: "btn btn-xs btn-success"}, "Voted"
+ )
+ );
+ } else {
+ return (
+ React.createElement("button", {
+ onClick: this.vote,
+ className: "btn btn-xs btn-default",
+ value: this.props.candidate.id}, "Vote"
+ )
+ );
+ }
+ }
+});
+
+var JoinGatherButton = React.createClass({displayName: "JoinGatherButton",
+ joinGather: function (e) {
+ e.preventDefault();
+ socket.emit("gather:join", {});
+ },
+ render: function () {
+ var message = this.props.buttonName || "Join Gather";
+ var buttonClass = "btn btn-primary";
+ if (this.props.buttonClass) {
+ buttonClass += " " + this.props.buttonClass;
+ }
+ return (React.createElement("button", {
+ onClick: this.joinGather,
+ className: buttonClass}, message))
+ }
+});
+
+var GatherProgress = React.createClass({displayName: "GatherProgress",
+ stateDescription: function () {
+ switch(this.props.gather.state) {
+ case "gathering":
+ return "Waiting for more gatherers.";
+ case "election":
+ return "Currently voting for team leaders.";
+ case "selection":
+ return "Waiting for leaders to picking teams.";
+ case "done":
+ return "Gather completed.";
+ default:
+ return "Initialising gather.";
+ }
+ },
+ gatheringProgress: function () {
+ var num = this.props.gather.gatherers.length;
+ var den = 12;
+ var remaining = den - num;
+ var message = (remaining === 1) ? "Waiting for last player" : "Waiting for " + remaining + " more players";
+ return {
+ num: num,
+ den: den,
+ message: message
+ };
+ },
+ electionProgress: function () {
+ var num = this.props.gather.gatherers.reduce(function (acc, gatherer) {
+ if (gatherer.leaderVote) acc++;
+ return acc;
+ }, 0);
+ var den = 12;
+ return {
+ num: num,
+ den: den,
+ message: den - num + " more votes required"
+ };
+ },
+ selectionProgress: function () {
+ var num = this.props.gather.gatherers.reduce(function (acc, gatherer) {
+ if (gatherer.team !== "lobby") acc++;
+ return acc;
+ }, 0);
+ var den = 12;
+
+ return {
+ num: num,
+ den: den,
+ message: num + " out of " + den + " players assigned"
+ };
+ },
+ render: function () {
+ var progress;
+ var gatherState = this.props.gather.state;
+ if (gatherState === 'gathering' && this.props.gather.gatherers.length) {
+ progress = this.gatheringProgress();
+ } else if (gatherState === 'election') {
+ progress = this.electionProgress();
+ } else if (gatherState === 'selection') {
+ progress = this.selectionProgress();
+ }
+ if (progress) {
+ var style = {
+ width: Math.round((progress.num / progress.den * 100)) + "%"
+ };
+ return (
+ React.createElement("div", {className: "panel-body"},
+ React.createElement("p", null, React.createElement("strong", null, this.stateDescription()), " ", progress.message),
+ React.createElement("div", {className: "progress"},
+ React.createElement("div", {className: "progress-bar progress-bar-striped active",
+ "data-role": "progressbar",
+ "data-aria-valuenow": progress.num,
+ "data-aria-valuemin": "0",
+ "data-aria-valuemax": progress.den,
+ style: style}
+ )
+ )
+ )
+ );
+ } else {
+ return false;
+ }
+ }
+});
+
+var Gather = React.createClass({displayName: "Gather",
+ getDefaultProps: function () {
+ return {
+ gather: {
+ gatherers: []
+ }
+ }
+ },
+ joinedGather: function () {
+ var self = this;
+ return this.props.gather.gatherers.some(function (gatherer) {
+ return gatherer.user.id === self.props.currentUser.id;
+ });
+ },
+ componentDidMount: function () {
+ var self = this;
+ socket.on("gather:refresh", function (data) {
+ self.setProps({
+ gather: data.gather,
+ currentUser: data.currentUser
+ });
+ });
+ },
+ leaveGather: function (e) {
+ e.preventDefault();
+ socket.emit("gather:leave", {});
+ },
+ inviteToGather: function (e) {
+ e.preventDefault();
+ },
+ currentGatherer: function () {
+ var current = null;
+ var self = this;
+ this.props.gather.gatherers.forEach(function (gatherer) {
+ if (gatherer.id === self.props.currentUser.id) current = gatherer;
+ });
+ return current;
+ },
+ render: function () {
+ var joinButton;
+ if (this.joinedGather()) {
+ joinButton = (React.createElement("li", null, React.createElement("button", {
+ onClick: this.leaveGather,
+ className: "btn btn-danger"}, "Leave Gather")));
+ } else {
+ joinButton = (React.createElement("li", null, React.createElement(JoinGatherButton, null)));
+ }
+ var inviteButton;
+ if (this.props.gather.state === 'gathering') {
+ inviteButton = (React.createElement("li", null, React.createElement("button", {
+ onClick: this.inviteToGather,
+ className: "btn btn-primary"}, "Invite to Gather")));
+ }
+ return (
+ React.createElement("div", {className: "panel panel-default"},
+ React.createElement("div", {className: "panel-heading"},
+ React.createElement("strong", null, "NS2 Gather "),
+ React.createElement("span", {className: "badge add-left"}, this.props.gather.gatherers.length)
+ ),
+ React.createElement(Gatherers, {gather: this.props.gather, currentGatherer: this.currentGatherer()}),
+ React.createElement(GatherProgress, {gather: this.props.gather}),
+ React.createElement("div", {className: "panel-footer text-right"},
+ React.createElement("ul", {className: "list-inline"},
+ inviteButton,
+ joinButton
+ )
+ )
+ )
+ );
+ }
+});
+
+var Gatherers = React.createClass({displayName: "Gatherers",
+ render: function () {
+ var self = this;
+ var gatherers = this.props.gather.gatherers.map(function (gatherer) {
+ var lifeforms = (
+ gatherer.user.ability.lifeforms.map(function (lifeform) {
+ return (React.createElement("span", {className: "label label-default"}, lifeform));
+ })
+ );
+
+ var commBadge;
+ if (gatherer.user.ability.commander) {
+ commBadge = (React.createElement("img", {src: "/images/commander.png",
+ alt: "Commander",
+ height: "20",
+ width: "20"}));
+ }
+
+ var division = (React.createElement("span", {className: "label label-primary"}, gatherer.user.ability.division));
+ var action = lifeforms;
+ if (self.props.gather.state === "election") {
+ var votes = self.props.gather.gatherers.reduce(function (acc, voter) {
+ if (voter.leaderVote === gatherer.id) acc++;
+ return acc;
+ }, 0)
+ action = (
+ React.createElement("span", null,
+ React.createElement("small", null, votes + " votes", " "),
+ React.createElement(VoteButton, {currentGatherer: self.props.currentGatherer, candidate: gatherer})
+ )
+ );
+ }
+
+ return (
+ React.createElement("tr", {key: gatherer.user.id},
+ React.createElement("td", {className: "col-md-1"}, commBadge),
+ React.createElement("td", {className: "col-md-5"}, gatherer.user.username),
+ React.createElement("td", {className: "col-md-3"}, division, " "),
+ React.createElement("td", {className: "col-md-2 text-right"}, action, " ")
+ )
+ );
+ })
+ if (this.props.gather.gatherers.length) {
+ return (
+ React.createElement("div", {className: "panel-body"},
+ React.createElement("div", {className: "panel panel-default"},
+ React.createElement("div", {className: "panel-heading"},
+ React.createElement("h5", {className: "panel-title"}, "Roster")
+ ),
+ React.createElement("table", {className: "table roster-table"},
+ React.createElement("tbody", null,
+ gatherers
+ )
+ )
+ )
+ )
+ );
+ } else {
+ return (React.createElement("div", {className: "panel-body text-center"}, React.createElement(JoinGatherButton, {buttonClass: "btn-lg", buttonName: "Start a Gather"})));
+ }
+ }
+});
+
+
+
+
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNmb3JtZWQuanMiLCJzb3VyY2VzIjpbbnVsbF0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVksQ0FBQzs7QUFFYixJQUFJLGdDQUFnQywwQkFBQTtDQUNuQyxVQUFVLEVBQUUsVUFBVSxDQUFDLEVBQUU7RUFDeEIsTUFBTSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUU7R0FDMUIsTUFBTSxFQUFFO0lBQ1AsU0FBUyxFQUFFLElBQUk7SUFDZjtHQUNELENBQUMsQ0FBQztFQUNIO0NBQ0QsSUFBSSxFQUFFLFVBQVUsQ0FBQyxFQUFFO0VBQ2xCLENBQUMsQ0FBQyxjQUFjLEVBQUUsQ0FBQztFQUNuQixNQUFNLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRTtHQUMxQixNQUFNLEVBQUU7SUFDUCxTQUFTLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQztJQUN2QztHQUNELENBQUMsQ0FBQztFQUNIO0NBQ0QsTUFBTSxFQUFFLFlBQVk7RUFDbkIsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLGVBQWUsS0FBSyxJQUFJLEVBQUU7R0FDeEMsT0FBTyxLQUFLLENBQUM7R0FDYjtFQUNELElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsVUFBVSxLQUFLLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLEVBQUUsRUFBRTtHQUN0RTtJQUNDLG9CQUFBLFFBQU8sRUFBQSxDQUFBO0tBQ04sT0FBQSxFQUFPLENBQUUsSUFBSSxDQUFDLFVBQVUsRUFBQztLQUN6QixTQUFBLEVBQVMsQ0FBQyx3QkFBeUIsQ0FBQSxFQUFBLE9BQUE7QUFBQSxJQUMzQixDQUFBO0tBQ1I7R0FDRixNQUFNO0dBQ047SUFDQyxvQkFBQSxRQUFPLEVBQUEsQ0FBQTtLQUNOLE9BQUEsRUFBTyxDQUFFLElBQUksQ0FBQyxJQUFJLEVBQUM7S0FDbkIsU0FBQSxFQUFTLENBQUMsd0JBQUEsRUFBd0I7S0FDbEMsS0FBQSxFQUFL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LENBQUE7SUFDbkQsQ0FBQTtLQUNKO0dBQ0YsQ0FBQztFQUNGLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRTtHQUN2QztJQUNDLG9CQUFBLEtBQUksRUFBQSxDQUFBLENBQUMsU0FBQSxFQUFTLENBQUMsWUFBYSxDQUFBLEVBQUE7S0FDM0Isb0JBQUEsS0FBSSxFQUFBLENBQUEsQ0FBQyxTQUFBLEVBQVMsQ0FBQyxxQkFBc0IsQ0FBQSxFQUFBO01BQ3BDLG9CQUFBLEtBQUksRUFBQSxDQUFBLENBQUMsU0FBQSxFQUFTLENBQUMsZUFBZ0IsQ0FBQSxFQUFBO09BQzlCLG9CQUFBLElBQUcsRUFBQSxDQUFBLENBQUMsU0FBQSxFQUFTLENBQUMsYUFBYyxDQUFBLEVBQUEsUUFBVyxDQUFBO01BQ2xDLENBQUEsRUFBQTtNQUNOLG9CQUFBLE9BQU0sRUFBQSxDQUFBLENBQUMsU0FBQSxFQUFTLENBQUMsb0JBQXFCLENBQUEsRUFBQTtPQUNyQyxvQkFBQSxPQUFNLEVBQUEsSUFBQyxFQUFBO1FBQ0wsU0FBVTtPQUNKLENBQUE7TUFDRCxDQUFBO0tBQ0gsQ0FBQTtJQUNELENBQUE7S0FDTDtHQUNGLE1BQU07R0FDTixRQUFRLG9CQUFBLEtBQUksRUFBQSxDQUFBLENBQUMsU0FBQSxFQUFTLENBQUMsd0JBQXlCLENBQUEsRUFBQSxvQkFBQyxnQkFBZ0IsRUFBQSxDQUFBLENBQUMsV0FBQSxFQUFXLENBQUMsUUFBQSxFQUFRLENBQUMsVUFBQSxFQUFVLENBQUMsZ0JBQWdCLENBQUEsQ0FBRyxDQUFNLENBQUEsRUFBRTtHQUM3SDtFQUNEO0FBQ0YsQ0FBQyxDQUFDLENBQUM7QUFDSDtBQUNBIiwic291cmNlc0NvbnRlbnQiOlsiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBWb3RlQnV0dG9uID0gUmVhY3QuY3JlYXRlQ2xhc3Moe1xuXHRjYW5jZWxWb3RlOiBmdW5jdGlvbiAoZSkge1xuXHRcdHNvY2tldC5lbWl0KFwiZ2F0aGVyOnZvdGVcIiwge1xuXHRcdFx0bGVhZGVyOiB7XG5cdFx0XHRcdGNhbmRpZGF0ZTogbnVsbFxuXHRcdFx0fVxuXHRcdH0pO1xuXHR9LFxuXHR2b3RlOiBmdW5jdGlvbiAoZSkge1xuXHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRzb2NrZXQuZW1pdChcImdhdGhlcjp2b3RlXCIsIHtcblx0XHRcdGxlYWRlcjoge1xuXHRcdFx0XHRjYW5kaWRhdGU6IHBhcnNlSW50KGUudGFyZ2V0LnZhbHVlLCAxMClcblx0XHRcdH1cblx0XHR9KTtcblx0fSxcblx0cmVuZGVyOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMucHJvcHMuY3VycmVudEdhdGhlcmVyID09PSBudWxsKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdGlmICh0aGlzLnByb3BzLmN1cnJlbnRHYXRoZXJlci5sZWFkZXJWb3RlID09PSB0aGlzLnByb3BzLmNhbmRpZGF0ZS5pZCkge1xuXHRcdFx0cmV0dXJuIChcblx0XHRcdFx0PGJ1dHRvbiBcblx0XHRcdFx0XHRvbkNsaWNrPXt0aGlzLmNhbmNlbFZvdGV9IFxuXHRcdFx0XHRcdGNsYXNzTmFtZT1cImJ0biBidG4teHMgYnRuLXN1Y2Nlc3NcIj5Wb3RlZFxuXHRcdFx0XHQ8L2J1dHRvbj5cblx0XHRcdCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiAoXG5cdFx0XHRcdDxidXR0b24gXG5cdFx0XHRcdFx0b25DbGljaz17dGhpcy52b3RlfSBcblx0XHRcdFx0XHRjbGFzc05hbWU9XCJidG4gYnRuLXhzIGJ0bi1kZWZhdWx0XCJcblx0XHRcdFx0XHR2YWx1ZT17dGhpcy5wcm9wcy5jYW5kaWRhdGUuaWR9PlZvdGVcblx0XHRcdFx0PC9idXR0b24+XG5cdFx0XHQpO1xuXHRcdH1cblx0fVxufSk7XG5cbnZhciBKb2luR2F0aGVyQnV0dG9uID0gUmVhY3QuY3JlYXRlQ2xhc3Moe1xuXHRqb2luR2F0aGVyOiBmdW5jdGlvbiAoZSkge1xuXHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRzb2NrZXQuZW1pdChcImdhdGhlcjpqb2luXCIsIHt9KTtcblx0fSxcblx0cmVuZGVyOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIG1lc3NhZ2UgPSB0aGlzLnByb3BzLmJ1dHRvbk5hbWUgfHwgXCJKb2luIEdhdGhlclwiO1xuXHRcdHZhciBidXR0b25DbGFzcyA9IFwiYnRuIGJ0bi1wcmltYXJ5XCI7XG5cdFx0aWYgKHRoaXMucHJvcHMuYnV0dG9uQ2xhc3MpIHtcblx0XHRcdGJ1dHRvbkNsYXNzICs9IFwiIFwiICsgdGhpcy5wcm9wcy5idXR0b25DbGFzcztcblx0XHR9XG5cdFx0cmV0dXJuICg8YnV0dG9uIFxuXHRcdFx0XHRcdFx0XHRvbkNsaWNrPXt0aGlzLmpvaW5HYXRoZXJ9IFxuXHRcdFx0XHRcdFx0XHRjbGFzc05hbWU9e2J1dHRvbkNsYXNzfT57bWVzc2FnZX08L2J1dHRvbj4pXG5cdH1cbn0pO1xuXG52YXIgR2F0aGVyUHJvZ3Jlc3MgPSBSZWFjdC5jcmVhdGVDbGFzcyh7XG5cdHN0YXRlRGVzY3JpcHRpb246IGZ1bmN0aW9uICgpIHtcblx0XHRzd2l0Y2godGhpcy5wcm9wcy5nYXRoZXIuc3RhdGUpIHtcblx0XHRcdGNhc2UgXCJnYXRoZXJpbmdcIjpcblx0XHRcdFx0cmV0dXJuIFwiV2FpdGluZyBmb3IgbW9yZSBnYXRoZXJlcnMuXCI7XG5cdFx0XHRjYXNlIFwiZWxlY3Rpb25cIjpcblx0XHRcdFx0cmV0dXJuIFwiQ3VycmVudGx5IHZvdGluZyBmb3IgdGVhbSBsZWFkZXJzLlwiO1xuXHRcdFx0Y2FzZSBcInNlbGVjdGlvblwiOlxuXHRcdFx0XHRyZXR1cm4gXCJXYWl0aW5nIGZvciBsZWFkZXJzIHRvIHBpY2tpbmcgdGVhbXMuXCI7XG5cdFx0XHRjYXNlIFwiZG9uZVwiOlxuXHRcdFx0XHRyZXR1cm4gXCJHYXRoZXIgY29tcGxldGVkLlwiO1xuXHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0cmV0dXJuIFwiSW5pdGlhbGlzaW5nIGdhdGhlci5cIjtcblx0XHR9XG5cdH0sXG5cdGdhdGhlcmluZ1Byb2dyZXNzOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIG51bSA9IHRoaXMucHJvcHMuZ2F0aGVyLmdhdGhlcmVycy5sZW5ndGg7XG5cdFx0dmFyIGRlbiA9IDEyO1xuXHRcdHZhciByZW1haW5pbmcgPSBkZW4gLSBudW07XG5cdFx0dmFyIG1lc3NhZ2UgPSAocmVtYWluaW5nID09PSAxKSA/IFwiV2FpdGluZyBmb3IgbGFzdCBwbGF5ZXJcIiA6IFwiV2FpdGluZyBmb3IgXCIgKyByZW1haW5pbmcgKyBcIiBtb3JlIHBsYXllcnNcIjtcblx0XHRyZXR1cm4ge1xuXHRcdFx0bnVtOiBudW0sXG5cdFx0XHRkZW46IGRlbixcblx0XHRcdG1lc3NhZ2U6IG1lc3NhZ2Vcblx0XHR9O1xuXHR9LFxuXHRlbGVjdGlvblByb2dyZXNzOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIG51bSA9IHRoaXMucHJvcHMuZ2F0aGVyLmdhdGhlcmVycy5yZWR1Y2UoZnVuY3Rpb24gKGFjYywgZ2F0aGVyZXIpIHtcblx0XHRcdGlmIChnYXRoZXJlci5sZWFkZXJWb3RlKSBhY2MrKztcblx0XHRcdHJldHVybiBhY2M7XG5cdFx0fSwgMCk7XG5cdFx0dmFyIGRlbiA9IDEyO1xuXHRcdHJldHVybiB7XG5cdFx0XHRudW06IG51bSxcblx0XHRcdGRlbjogZGVuLFxuXHRcdFx0bWVzc2FnZTogZGVuIC0gbnVtICsgXCIgbW9yZSB2b3RlcyByZXF1aXJlZFwiXG5cdFx0fTtcblx0fSxcblx0c2VsZWN0aW9uUHJvZ3Jlc3M6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgbnVtID0gdGhpcy5wcm9wcy5nYXRoZXIuZ2F0aGVyZXJzLnJlZHVjZShmdW5jdGlvbiAoYWNjLCBnYXRoZXJlcikge1xuXHRcdFx0aWYgKGdhdGhlcmVyLnRlYW0gIT09IFwibG9iYnlcIikgYWNjKys7XG5cdFx0XHRyZXR1cm4gYWNjO1xuXHRcdH0sIDApO1xuXHRcdHZhciBkZW4gPSAxMjtcblxuXHRcdHJldHVybiB7XG5cdFx0XHRudW06IG51bSxcblx0XHRcdGRlbjogZGVuLFxuXHRcdFx0bWVzc2FnZTogbnVtICsgXCIgb3V0IG9mIFwiICsgZGVuICsgXCIgcGxheWVycyBhc3NpZ25lZFwiXG5cdFx0fTtcblx0fSxcblx0cmVuZGVyOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIHByb2dyZXNzO1xuXHRcdHZhciBnYXRoZXJTdGF0ZSA9IHRoaXMucHJvcHMuZ2F0aGVyLnN0YXRlO1xuXHRcdGlmIChnYXRoZXJTdGF0ZSA9PT0gJ2dhdGhlcmluZycgJiYgdGhpcy5wcm9wcy5nYXRoZXIuZ2F0aGVyZXJzLmxlbmd0aCkge1xuXHRcdFx0cHJvZ3Jlc3MgPSB0aGlzLmdhdGhlcmluZ1Byb2dyZXNzKCk7XG5cdFx0fSBlbHNlIGlmIChnYXRoZXJTdGF0ZSA9PT0gJ2VsZWN0aW9uJykge1xuXHRcdFx0cHJvZ3Jlc3MgPSB0aGlzLmVsZWN0aW9uUHJvZ3Jlc3MoKTtcblx0XHR9IGVsc2UgaWYgKGdhdGhlclN0YXRlID09PSAnc2VsZWN0aW9uJykge1xuXHRcdFx0cHJvZ3Jlc3MgPSB0aGlzLnNlbGVjdGlvblByb2dyZXNzKCk7XG5cdFx0fVxuXHRcdGlmIChwcm9ncmVzcykge1xuXHRcdFx0dmFyIHN0eWxlID0ge1xuXHRcdFx0XHR3aWR0aDogTWF0aC5yb3VuZCgocHJvZ3Jlc3MubnVtIC8gcHJvZ3Jlc3MuZGVuICogMTAwKSkgKyBcIiVcIlxuXHRcdFx0fTtcblx0XHRcdHJldHVybiAoXG5cdFx0XHRcdDxkaXYgY2xhc3NOYW1lPVwicGFuZWwtYm9keVwiPlxuXHRcdFx0XHRcdDxwPjxzdHJvbmc+e3RoaXMuc3RhdGVEZXNjcmlwdGlvbigpfTwvc3Ryb25nPiB7cHJvZ3Jlc3MubWVzc2FnZX08L3A+XG5cdFx0XHRcdFx0PGRpdiBjbGFzc05hbWU9XCJwcm9ncmVzc1wiPlxuXHRcdFx0XHRcdCAgPGRpdiBjbGFzc05hbWU9XCJwcm9ncmVzcy1iYXIgcHJvZ3Jlc3MtYmFyLXN0cmlwZWQgYWN0aXZlXCIgXG5cdFx0XHRcdFx0ICBcdGRhdGEtcm9sZT1cInByb2dyZXNzYmFyXCIgXG5cdFx0XHRcdFx0ICBcdGRhdGEtYXJpYS12YWx1ZW5vdz17cHJvZ3Jlc3MubnVtfSBcblx0XHRcdFx0XHQgIFx0ZGF0YS1hcmlhLXZhbHVlbWluPVwiMFwiIFxuXHRcdFx0XHRcdCAgXHRkYXRhLWFyaWEtdmFsdWVtYXg9e3Byb2dyZXNzLmRlbn0gXG5cdFx0XHRcdFx0ICBcdHN0eWxlPXtzdHlsZX0+XG5cdFx0XHRcdFx0ICA8L2Rpdj5cblx0XHRcdFx0ICA8L2Rpdj5cblx0XHRcdFx0PC9kaXY+XG5cdFx0XHQpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHR9XG59KTtcblxudmFyIEdhdGhlciA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtcblx0Z2V0RGVmYXVsdFByb3BzOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIHtcblx0XHRcdGdhdGhlcjoge1xuXHRcdFx0XHRnYXRoZXJlcnM6IFtdXG5cdFx0XHR9XG5cdFx0fVxuXHR9LFxuXHRqb2luZWRHYXRoZXI6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgc2VsZiA9IHRoaXM7XG5cdFx0cmV0dXJuIHRoaXMucHJvcHMuZ2F0aGVyLmdhdGhlcmVycy5zb21lKGZ1bmN0aW9uIChnYXRoZXJlcikge1xuXHRcdFx0cmV0dXJuIGdhdGhlcmVyLnVzZXIuaWQgPT09IHNlbGYucHJvcHMuY3VycmVudFVzZXIuaWQ7XG5cdFx0fSk7XG5cdH0sXG5cdGNvbXBvbmVudERpZE1vdW50OiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIHNlbGYgPSB0aGlzO1xuXHRcdHNvY2tldC5vbihcImdhdGhlcjpyZWZyZXNoXCIsIGZ1bmN0aW9uIChkYXRhKSB7XG5cdFx0XHRzZWxmLnNldFByb3BzKHtcblx0XHRcdFx0Z2F0aGVyOiBkYXRhLmdhdGhlcixcblx0XHRcdFx0Y3VycmVudFVzZXI6IGRhdGEuY3VycmVudFVzZXJcblx0XHRcdH0pO1xuXHRcdH0pO1xuXHR9LFxuXHRsZWF2ZUdhdGhlcjogZnVuY3Rpb24gKGUpIHtcblx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0c29ja2V0LmVtaXQoXCJnYXRoZXI6bGVhdmVcIiwge30pO1xuXHR9LFxuXHRpbnZpdGVUb0dhdGhlcjogZnVuY3Rpb24gKGUpIHtcblx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdH0sXG5cdGN1cnJlbnRHYXRoZXJlcjogZnVuY3Rpb24gKCkge1xuXHRcdHZhciBjdXJyZW50ID0gbnVsbDtcblx0XHR2YXIgc2VsZiA9IHRoaXM7XG5cdFx0dGhpcy5wcm9wcy5nYXRoZXIuZ2F0aGVyZXJzLmZvckVhY2goZnVuY3Rpb24gKGdhdGhlcmVyKSB7XG5cdFx0XHRpZiAoZ2F0aGVyZXIuaWQgPT09IHNlbGYucHJvcHMuY3VycmVudFVzZXIuaWQpIGN1cnJlbnQgPSBnYXRoZXJlcjtcblx0XHR9KTtcblx0XHRyZXR1cm4gY3VycmVudDtcblx0fSxcblx0cmVuZGVyOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIGpvaW5CdXR0b247XG5cdFx0aWYgKHRoaXMuam9pbmVkR2F0aGVyKCkpIHtcblx0XHRcdGpvaW5CdXR0b24gPSAoPGxpPjxidXR0b24gXG5cdFx0XHRcdFx0XHRcdG9uQ2xpY2s9e3RoaXMubGVhdmVHYXRoZXJ9IFxuXHRcdFx0XHRcdFx0XHRjbGFzc05hbWU9XCJidG4gYnRuLWRhbmdlclwiPkxlYXZlIEdhdGhlcjwvYnV0dG9uPjwvbGk+KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0am9pbkJ1dHRvbiA9ICg8bGk+PEpvaW5HYXRoZXJCdXR0b24gLz48L2xpPik7XG5cdFx0fVxuXHRcdHZhciBpbnZpdGVCdXR0b247XG5cdFx0aWYgKHRoaXMucHJvcHMuZ2F0aGVyLnN0YXRlID09PSAnZ2F0aGVyaW5nJykge1xuXHRcdFx0aW52aXRlQnV0dG9uID0gKDxsaT48YnV0dG9uXG5cdFx0XHRcdFx0XHRcdG9uQ2xpY2s9e3RoaXMuaW52aXRlVG9HYXRoZXJ9XG5cdFx0XHRcdFx0XHRcdGNsYXNzTmFtZT1cImJ0biBidG4tcHJpbWFyeVwiPkludml0ZSB0byBHYXRoZXI8L2J1dHRvbj48L2xpPik7XG5cdFx0fVxuXHRcdHJldHVybiAoXG5cdFx0XHQ8ZGl2IGNsYXNzTmFtZT1cInBhbmVsIHBhbmVsLWRlZmF1bHRcIj5cblx0XHRcdFx0PGRpdiBjbGFzc05hbWU9XCJwYW5lbC1oZWFkaW5nXCI+XG5cdFx0XHRcdFx0PHN0cm9uZz5OUzIgR2F0aGVyIDwvc3Ryb25nPlxuXHRcdFx0XHRcdDxzcGFuIGNsYXNzTmFtZT1cImJhZGdlIGFkZC1sZWZ0XCI+e3RoaXMucHJvcHMuZ2F0aGVyLmdhdGhlcmVycy5sZW5ndGh9PC9zcGFuPlxuXHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0PEdhdGhlcmVycyBnYXRoZXI9e3RoaXMucHJvcHMuZ2F0aGVyfSBjdXJyZW50R2F0aGVyZXI9e3RoaXMuY3VycmVudEdhdGhlcmVyKCl9IC8+XG5cdFx0XHRcdDxHYXRoZXJQcm9ncmVzcyBnYXRoZXI9e3RoaXMucHJvcHMuZ2F0aGVyfSAvPlxuXHRcdFx0XHQ8ZGl2IGNsYXNzTmFtZT1cInBhbmVsLWZvb3RlciB0ZXh0LXJpZ2h0XCI+XG5cdFx0XHRcdFx0PHVsIGNsYXNzTmFtZT1cImxpc3QtaW5saW5lXCI+XG5cdFx0XHRcdFx0XHR7aW52aXRlQnV0dG9ufVxuXHRcdFx0XHRcdFx0e2pvaW5CdXR0b259XG5cdFx0XHRcdFx0PC91bD5cblx0XHRcdFx0PC9kaXY+XG5cdFx0XHQ8L2Rpdj5cblx0XHQpO1xuXHR9XG59KTtcblxudmFyIEdhdGhlcmVycyA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtcblx0cmVuZGVyOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIHNlbGYgPSB0aGlzO1xuXHRcdHZhciBnYXRoZXJlcnMgPSB0aGlzLnByb3BzLmdhdGhlci5nYXRoZXJlcnMubWFwKGZ1bmN0aW9uIChnYXRoZXJlcikge1xuXHRcdFx0dmFyIGxpZmVmb3JtcyA9IChcblx0XHRcdFx0Z2F0aGVyZXIudXNlci5hYmlsaXR5LmxpZmVmb3Jtcy5tYXAoZnVuY3Rpb24gKGxpZmVmb3JtKSB7XG5cdFx0XHRcdFx0cmV0dXJuICg8c3BhbiBjbGFzc05hbWU9XCJsYWJlbCBsYWJlbC1kZWZhdWx0XCI+e2xpZmVmb3JtfTwvc3Bhbj4pO1xuXHRcdFx0XHR9KVxuXHRcdFx0KTtcblxuXHRcdFx0dmFyIGNvbW1CYWRnZTtcblx0XHRcdGlmIChnYXRoZXJlci51c2VyLmFiaWxpdHkuY29tbWFuZGVyKSB7XG5cdFx0XHRcdGNvbW1CYWRnZSA9ICg8aW1nIHNyYz1cIi9pbWFnZXMvY29tbWFuZGVyLnBuZ1wiIFxuXHRcdFx0XHRcdFx0XHRhbHQ9XCJDb21tYW5kZXJcIiBcblx0XHRcdFx0XHRcdFx0aGVpZ2h0PVwiMjBcIlxuXHRcdFx0XHRcdFx0XHR3aWR0aD1cIjIwXCIgLz4pO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgZGl2aXNpb24gPSAoPHNwYW4gY2xhc3NOYW1lPVwibGFiZWwgbGFiZWwtcHJpbWFyeVwiPntnYXRoZXJlci51c2VyLmFiaWxpdHkuZGl2aXNpb259PC9zcGFuPik7XG5cdFx0XHR2YXIgYWN0aW9uID0gbGlmZWZvcm1zO1xuXHRcdFx0aWYgKHNlbGYucHJvcHMuZ2F0aGVyLnN0YXRlID09PSBcImVsZWN0aW9uXCIpIHtcblx0XHRcdFx0dmFyIHZvdGVzID0gc2VsZi5wcm9wcy5nYXRoZXIuZ2F0aGVyZXJzLnJlZHVjZShmdW5jdGlvbiAoYWNjLCB2b3Rlcikge1xuXHRcdFx0XHRcdGlmICh2b3Rlci5sZWFkZXJWb3RlID09PSBnYXRoZXJlci5pZCkgYWNjKys7XG5cdFx0XHRcdFx0cmV0dXJuIGFjYztcblx0XHRcdFx0fSwgMClcblx0XHRcdFx0YWN0aW9uID0gKFxuXHRcdFx0XHRcdDxzcGFuPlxuXHRcdFx0XHRcdFx0PHNtYWxsPnt2b3RlcyArIFwiIHZvdGVzXCJ9ICZuYnNwOzwvc21hbGw+XG5cdFx0XHRcdFx0XHQ8Vm90ZUJ1dHRvbiBjdXJyZW50R2F0aGVyZXI9e3NlbGYucHJvcHMuY3VycmVudEdhdGhlcmVyfSBjYW5kaWRhdGU9e2dhdGhlcmVyfSAvPlxuXHRcdFx0XHRcdDwvc3Bhbj5cblx0XHRcdFx0KTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIChcblx0XHRcdFx0PHRyIGtleT17Z2F0aGVyZXIudXNlci5pZH0+XG5cdFx0XHRcdFx0PHRkIGNsYXNzTmFtZT1cImNvbC1tZC0xXCI+e2NvbW1CYWRnZX08L3RkPlxuXHRcdFx0XHRcdDx0ZCBjbGFzc05hbWU9XCJjb2wtbWQtNVwiPntnYXRoZXJlci51c2VyLnVzZXJuYW1lfTwvdGQ+XG5cdFx0XHRcdFx0PHRkIGNsYXNzTmFtZT1cImNvbC1tZC0zXCI+e2RpdmlzaW9ufSZuYnNwOzwvdGQ+XG5cdFx0XHRcdFx0PHRkIGNsYXNzTmFtZT1cImNvbC1tZC0yIHRleHQtcmlnaHRcIj57YWN0aW9ufSZuYnNwOzwvdGQ+XG5cdFx0XHRcdDwvdHI+XG5cdFx0XHQpO1xuXHRcdH0pXG5cdFx0aWYgKHRoaXMucHJvcHMuZ2F0aGVyLmdhdGhlcmVycy5sZW5ndGgpIHtcblx0XHRcdHJldHVybiAoXG5cdFx0XHRcdDxkaXYgY2xhc3NOYW1lPVwicGFuZWwtYm9keVwiPlxuXHRcdFx0XHRcdDxkaXYgY2xhc3NOYW1lPVwicGFuZWwgcGFuZWwtZGVmYXVsdFwiPlxuXHRcdFx0XHRcdFx0PGRpdiBjbGFzc05hbWU9XCJwYW5lbC1oZWFkaW5nXCI+XG5cdFx0XHRcdFx0XHRcdDxoNSBjbGFzc05hbWU9XCJwYW5lbC10aXRsZVwiPlJvc3RlcjwvaDU+XG5cdFx0XHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0XHRcdDx0YWJsZSBjbGFzc05hbWU9XCJ0YWJsZSByb3N0ZXItdGFibGVcIj5cblx0XHRcdFx0XHRcdFx0PHRib2R5PlxuXHRcdFx0XHRcdFx0XHRcdHtnYXRoZXJlcnN9XG5cdFx0XHRcdFx0XHRcdDwvdGJvZHk+XG5cdFx0XHRcdFx0XHQ8L3RhYmxlPlxuXHRcdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHQ8L2Rpdj5cblx0XHRcdCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiAoPGRpdiBjbGFzc05hbWU9XCJwYW5lbC1ib2R5IHRleHQtY2VudGVyXCI+PEpvaW5HYXRoZXJCdXR0b24gYnV0dG9uQ2xhc3M9XCJidG4tbGdcIiBidXR0b25OYW1lPVwiU3RhcnQgYSBHYXRoZXJcIiAvPjwvZGl2Pik7XG5cdFx0fVxuXHR9XG59KTtcblxuXG5cbiJdfQ==
\ No newline at end of file
diff --git a/public/js/init.js b/public/js/init.js
new file mode 100644
index 0000000..b4f148b
--- /dev/null
+++ b/public/js/init.js
@@ -0,0 +1,23 @@
+"use strict";
+
+var socket;
+
+function initialiseComponents () {
+ var socketUrl = window.location.protocol + "//" + window.location.host;
+ socket = io(socketUrl)
+ .on("connect", function () {
+ console.log("Connected");
+ })
+ .on("reconnect", function () {
+ console.log("Reconnected");
+ })
+ .on("disconnect", function () {
+ console.log("Disconnected")
+ });
+
+ React.render(React.createElement(UserMenu, null), document.getElementById('side-menu'));
+ React.render(React.createElement(Chatroom, null), document.getElementById('chatroom'));
+ React.render(React.createElement(Gather, null), document.getElementById('gathers'));
+ React.render(React.createElement(CurrentUser, null), document.getElementById('currentuser'));
+};
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNmb3JtZWQuanMiLCJzb3VyY2VzIjpbbnVsbF0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVksQ0FBQzs7QUFFYixJQUFJLE1BQU0sQ0FBQzs7QUFFWCxTQUFTLG9CQUFvQixJQUFJO0NBQ2hDLElBQUksU0FBUyxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsUUFBUSxHQUFHLElBQUksR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQztDQUN2RSxNQUFNLEdBQUcsRUFBRSxDQUFDLFNBQVMsQ0FBQztHQUNwQixFQUFFLENBQUMsU0FBUyxFQUFFLFlBQVk7R0FDMUIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQztHQUN6QixDQUFDO0dBQ0QsRUFBRSxDQUFDLFdBQVcsRUFBRSxZQUFZO0dBQzVCLE9BQU8sQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLENBQUM7R0FDM0IsQ0FBQztHQUNELEVBQUUsQ0FBQyxZQUFZLEVBQUUsWUFBWTtHQUM3QixPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQztBQUM5QixHQUFHLENBQUMsQ0FBQzs7Q0FFSixLQUFLLENBQUMsTUFBTSxDQUFDLG9CQUFDLFFBQVEsRUFBQSxJQUFBLENBQUcsQ0FBQSxFQUFFLFFBQVEsQ0FBQyxjQUFjLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztDQUNqRSxLQUFLLENBQUMsTUFBTSxDQUFDLG9CQUFDLFFBQVEsRUFBQSxJQUFBLENBQUcsQ0FBQSxFQUFFLFFBQVEsQ0FBQyxjQUFjLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztDQUNoRSxLQUFLLENBQUMsTUFBTSxDQUFDLG9CQUFDLE1BQU0sRUFBQSxJQUFBLENBQUcsQ0FBQSxFQUFFLFFBQVEsQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztDQUM3RCxLQUFLLENBQUMsTUFBTSxDQUFDLG9CQUFDLFdBQVcsRUFBQSxJQUFBLENBQUcsQ0FBQSxFQUFFLFFBQVEsQ0FBQyxjQUFjLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQztDQUN0RSIsInNvdXJjZXNDb250ZW50IjpbIlwidXNlIHN0cmljdFwiO1xuXG52YXIgc29ja2V0O1xuXG5mdW5jdGlvbiBpbml0aWFsaXNlQ29tcG9uZW50cyAoKSB7XG5cdHZhciBzb2NrZXRVcmwgPSB3aW5kb3cubG9jYXRpb24ucHJvdG9jb2wgKyBcIi8vXCIgKyB3aW5kb3cubG9jYXRpb24uaG9zdDtcblx0c29ja2V0ID0gaW8oc29ja2V0VXJsKVxuXHRcdC5vbihcImNvbm5lY3RcIiwgZnVuY3Rpb24gKCkge1xuXHRcdFx0Y29uc29sZS5sb2coXCJDb25uZWN0ZWRcIik7XG5cdFx0fSlcblx0XHQub24oXCJyZWNvbm5lY3RcIiwgZnVuY3Rpb24gKCkge1xuXHRcdFx0Y29uc29sZS5sb2coXCJSZWNvbm5lY3RlZFwiKTtcblx0XHR9KVxuXHRcdC5vbihcImRpc2Nvbm5lY3RcIiwgZnVuY3Rpb24gKCkge1xuXHRcdFx0Y29uc29sZS5sb2coXCJEaXNjb25uZWN0ZWRcIilcblx0XHR9KTtcblxuXHRSZWFjdC5yZW5kZXIoPFVzZXJNZW51IC8+LCBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnc2lkZS1tZW51JykpO1xuXHRSZWFjdC5yZW5kZXIoPENoYXRyb29tIC8+LCBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnY2hhdHJvb20nKSk7XG5cdFJlYWN0LnJlbmRlcig8R2F0aGVyIC8+LCBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZ2F0aGVycycpKTtcblx0UmVhY3QucmVuZGVyKDxDdXJyZW50VXNlciAvPiwgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2N1cnJlbnR1c2VyJykpO1xufTsiXX0=
\ No newline at end of file
diff --git a/public/js/message.js b/public/js/message.js
new file mode 100644
index 0000000..6fce96a
--- /dev/null
+++ b/public/js/message.js
@@ -0,0 +1,148 @@
+"use strict";
+
+var Chatroom = React.createClass({displayName: "Chatroom",
+ getDefaultProps: function () {
+ return {
+ history: []
+ };
+ },
+ componentDidMount: function () {
+ var self = this;
+ var TIMER_INTERVAL = 60000; // Every minute
+
+ socket.on("message:new", function (data) {
+ var history = self.props.history;
+ history.push(data);
+ self.setProps({
+ history: history
+ });
+ self.scrollToBottom();
+ });
+
+ // Message History Retrieved
+ socket.on("message:refresh", function (data) {
+ self.setProps({
+ history: data.chatHistory
+ });
+ self.scrollToBottom();
+ });
+
+ socket.emit("message:refresh", {});
+
+ self.timer = setInterval(function () {
+ if (self.refs.messages) self.refs.messages.refreshTime();
+ }, TIMER_INTERVAL);
+ },
+
+ componentDidUnmount: function () {
+ clearInterval(this.timer);
+ },
+ sendMessage: function (message) {
+ socket.emit("newMessage", {message: message});
+ },
+ scrollToBottom: function () {
+ var node = React.findDOMNode(this.refs.messageContainer);
+ node.scrollTop = node.scrollHeight;
+ },
+ render: function () {
+ var messages = this.props.history.map(function (message) {
+ return (
+ React.createElement(ChatMessage, {
+ avatar: message.author.avatar,
+ username: message.author.username,
+ content: message.content,
+ ref: "messages",
+ createdAt: message.createdAt})
+ );
+ });
+ return (
+ React.createElement("div", {className: "panel panel-default"},
+ React.createElement("div", {className: "panel-heading"}, "Gather Chat"),
+ React.createElement("div", {className: "panel-body"},
+ React.createElement("ul", {className: "chat", id: "chatmessages", ref: "messageContainer"},
+ messages
+ )
+ ),
+ React.createElement("div", {className: "panel-footer"},
+ React.createElement(MessageBar, null)
+ )
+ )
+ );
+ }
+});
+
+var ChatMessage = React.createClass({displayName: "ChatMessage",
+ getInitialState: function () {
+ return {
+ timeAgo: $.timeago(this.props.createdAt)
+ }
+ },
+ refreshTime: function () {
+ var self = this;
+ self.setState({
+ timeAgo: $.timeago(self.props.createdAt)
+ });
+ },
+ render: function () {
+ return (
+ React.createElement("li", {className: "left clearfix"},
+ React.createElement("span", {className: "chat-img pull-left"},
+ React.createElement("img", {
+ src: this.props.avatar,
+ alt: "User Avatar",
+ height: "40",
+ width: "40",
+ className: "img-circle"})
+ ),
+ React.createElement("div", {className: "chat-body clearfix"},
+ React.createElement("div", {className: "header"},
+ React.createElement("strong", {className: "primary-font"}, this.props.username),
+ React.createElement("small", {className: "pull-right text-muted"},
+ React.createElement("i", {className: "fa fa-clock-o fa-fw"}), " ", this.state.timeAgo
+ )
+ ),
+ React.createElement("p", null, this.props.content)
+ )
+ )
+ );
+ }
+});
+
+var MessageBar = React.createClass({displayName: "MessageBar",
+ sendMessage: function (content) {
+ socket.emit("message:new", {
+ content: content
+ });
+ },
+ handleSubmit: function (e) {
+ e.preventDefault();
+ var content = React.findDOMNode(this.refs.content).value.trim();
+ if (!content) return;
+ React.findDOMNode(this.refs.content).value = '';
+ this.sendMessage(content);
+ return;
+ },
+ render: function () {
+ return (
+ React.createElement("form", {onSubmit: this.handleSubmit},
+ React.createElement("div", {className: "input-group"},
+ React.createElement("input", {
+ id: "btn-input",
+ type: "text",
+ className: "form-control",
+ ref: "content",
+ placeholder: "Be polite please..."}),
+ React.createElement("span", {className: "input-group-btn"},
+ React.createElement("input", {
+ type: "submit",
+ className: "btn btn-primary",
+ id: "btn-chat",
+ value: "Send"})
+ )
+ )
+ )
+ );
+ }
+});
+
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNmb3JtZWQuanMiLCJzb3VyY2VzIjpbbnVsbF0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVksQ0FBQzs7QUFFYixJQUFJLDhCQUE4Qix3QkFBQTtDQUNqQyxlQUFlLEVBQUUsWUFBWTtFQUM1QixPQUFPO0dBQ04sT0FBTyxFQUFFLEVBQUU7R0FDWCxDQUFDO0VBQ0Y7Q0FDRCxpQkFBaUIsRUFBRSxZQUFZO0VBQzlCLElBQUksSUFBSSxHQUFHLElBQUksQ0FBQztBQUNsQixFQUFFLElBQUksY0FBYyxHQUFHLEtBQUssQ0FBQzs7RUFFM0IsTUFBTSxDQUFDLEVBQUUsQ0FBQyxhQUFhLEVBQUUsVUFBVSxJQUFJLEVBQUU7R0FDeEMsSUFBSSxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUM7R0FDakMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztHQUNuQixJQUFJLENBQUMsUUFBUSxDQUFDO0lBQ2IsT0FBTyxFQUFFLE9BQU87SUFDaEIsQ0FBQyxDQUFDO0dBQ0gsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO0FBQ3pCLEdBQUcsQ0FBQyxDQUFDO0FBQ0w7O0VBRUUsTUFBTSxDQUFDLEVBQUUsQ0FBQyxpQkFBaUIsRUFBRSxVQUFVLElBQUksRUFBRTtHQUM1QyxJQUFJLENBQUMsUUFBUSxDQUFDO0lBQ2IsT0FBTyxFQUFFLElBQUksQ0FBQyxXQUFXO0lBQ3pCLENBQUMsQ0FBQztHQUNILElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztBQUN6QixHQUFHLENBQUMsQ0FBQzs7QUFFTCxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsRUFBRSxDQUFDLENBQUM7O0VBRW5DLElBQUksQ0FBQyxLQUFLLEdBQUcsV0FBVyxDQUFDLFlBQVk7R0FDcEMsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLEVBQUUsQ0FBQztHQUN6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b29tID0gUmVhY3QuY3JlYXRlQ2xhc3Moe1xuXHRnZXREZWZhdWx0UHJvcHM6IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4ge1xuXHRcdFx0aGlzdG9yeTogW11cblx0XHR9O1xuXHR9LFxuXHRjb21wb25lbnREaWRNb3VudDogZnVuY3Rpb24gKCkge1xuXHRcdHZhciBzZWxmID0gdGhpcztcblx0XHR2YXIgVElNRVJfSU5URVJWQUwgPSA2MDAwMDsgLy8gRXZlcnkgbWludXRlXG5cblx0XHRzb2NrZXQub24oXCJtZXNzYWdlOm5ld1wiLCBmdW5jdGlvbiAoZGF0YSkge1xuXHRcdFx0dmFyIGhpc3RvcnkgPSBzZWxmLnByb3BzLmhpc3Rvcnk7XG5cdFx0XHRoaXN0b3J5LnB1c2goZGF0YSk7XG5cdFx0XHRzZWxmLnNldFByb3BzKHtcblx0XHRcdFx0aGlzdG9yeTogaGlzdG9yeVxuXHRcdFx0fSk7XG5cdFx0XHRzZWxmLnNjcm9sbFRvQm90dG9tKCk7XG5cdFx0fSk7XG5cblx0XHQvLyBNZXNzYWdlIEhpc3RvcnkgUmV0cmlldmVkXG5cdFx0c29ja2V0Lm9uKFwibWVzc2FnZTpyZWZyZXNoXCIsIGZ1bmN0aW9uIChkYXRhKSB7XG5cdFx0XHRzZWxmLnNldFByb3BzKHtcblx0XHRcdFx0aGlzdG9yeTogZGF0YS5jaGF0SGlzdG9yeVxuXHRcdFx0fSk7XG5cdFx0XHRzZWxmLnNjcm9sbFRvQm90dG9tKCk7XG5cdFx0fSk7XG5cblx0XHRzb2NrZXQuZW1pdChcIm1lc3NhZ2U6cmVmcmVzaFwiLCB7fSk7XG5cblx0XHRzZWxmLnRpbWVyID0gc2V0SW50ZXJ2YWwoZnVuY3Rpb24gKCkge1xuXHRcdFx0aWYgKHNlbGYucmVmcy5tZXNzYWdlcykgc2VsZi5yZWZzLm1lc3NhZ2VzLnJlZnJlc2hUaW1lKCk7XG5cdFx0fSwgVElNRVJfSU5URVJWQUwpO1xuXHR9LFxuXG5cdGNvbXBvbmVudERpZFVubW91bnQ6IGZ1bmN0aW9uICgpIHtcblx0XHRjbGVhckludGVydmFsKHRoaXMudGltZXIpO1xuXHR9LFxuXHRzZW5kTWVzc2FnZTogZnVuY3Rpb24gKG1lc3NhZ2UpIHtcblx0XHRzb2NrZXQuZW1pdChcIm5ld01lc3NhZ2VcIiwge21lc3NhZ2U6IG1lc3NhZ2V9KTtcblx0fSxcblx0c2Nyb2xsVG9Cb3R0b206IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgbm9kZSA9IFJlYWN0LmZpbmRET01Ob2RlKHRoaXMucmVmcy5tZXNzYWdlQ29udGFpbmVyKTtcblx0ICBub2RlLnNjcm9sbFRvcCA9IG5vZGUuc2Nyb2xsSGVpZ2h0O1xuXHR9LFxuXHRyZW5kZXI6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgbWVzc2FnZXMgPSB0aGlzLnByb3BzLmhpc3RvcnkubWFwKGZ1bmN0aW9uIChtZXNzYWdlKSB7XG5cdFx0XHRyZXR1cm4gKFxuXHRcdFx0XHQ8Q2hhdE1lc3NhZ2UgXG5cdFx0XHRcdFx0YXZhdGFyPXttZXNzYWdlLmF1dGhvci5hdmF0YXJ9IFxuXHRcdFx0XHRcdHVzZXJuYW1lPXttZXNzYWdlLmF1dGhvci51c2VybmFtZX1cblx0XHRcdFx0XHRjb250ZW50PXttZXNzYWdlLmNvbnRlbnR9XG5cdFx0XHRcdFx0cmVmPVwibWVzc2FnZXNcIlxuXHRcdFx0XHRcdGNyZWF0ZWRBdD17bWVzc2FnZS5jcmVhdGVkQXR9IC8+XG5cdFx0XHQpO1xuXHRcdH0pO1xuXHRcdHJldHVybiAoXG5cdFx0XHQ8ZGl2IGNsYXNzTmFtZT1cInBhbmVsIHBhbmVsLWRlZmF1bHRcIj5cblx0XHRcdFx0PGRpdiBjbGFzc05hbWU9XCJwYW5lbC1oZWFkaW5nXCI+R2F0aGVyIENoYXQ8L2Rpdj5cblx0XHRcdFx0PGRpdiBjbGFzc05hbWU9XCJwYW5lbC1ib2R5XCI+XG5cdFx0XHRcdFx0PHVsIGNsYXNzTmFtZT1cImNoYXRcIiBpZD1cImNoYXRtZXNzYWdlc1wiIHJlZj1cIm1lc3NhZ2VDb250YWluZXJcIj5cblx0XHRcdFx0XHRcdHttZXNzYWdlc31cblx0XHRcdFx0XHQ8L3VsPlxuXHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0PGRpdiBjbGFzc05hbWU9XCJwYW5lbC1mb290ZXJcIj5cblx0XHRcdFx0XHQ8TWVzc2FnZUJhciAvPlxuXHRcdFx0XHQ8L2Rpdj5cblx0XHRcdDwvZGl2PlxuXHRcdCk7XG5cdH1cbn0pO1xuXG52YXIgQ2hhdE1lc3NhZ2UgPSBSZWFjdC5jcmVhdGVDbGFzcyh7XG5cdGdldEluaXRpYWxTdGF0ZTogZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiB7XG5cdFx0XHR0aW1lQWdvOiAkLnRpbWVhZ28odGhpcy5wcm9wcy5jcmVhdGVkQXQpXG5cdFx0fVxuXHR9LFxuXHRyZWZyZXNoVGltZTogZnVuY3Rpb24gKCkge1xuXHRcdHZhciBzZWxmID0gdGhpcztcblx0XHRzZWxmLnNldFN0YXRlKHtcblx0XHRcdHRpbWVBZ286ICQudGltZWFnbyhzZWxmLnByb3BzLmNyZWF0ZWRBdClcblx0XHR9KTtcblx0fSxcblx0cmVuZGVyOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIChcblx0XHRcdDxsaSBjbGFzc05hbWU9XCJsZWZ0IGNsZWFyZml4XCI+XG5cdFx0XHRcdDxzcGFuIGNsYXNzTmFtZT1cImNoYXQtaW1nIHB1bGwtbGVmdFwiPlxuXHRcdFx0XHRcdFx0PGltZyBcblx0XHRcdFx0XHRcdFx0c3JjPXt0aGlzLnByb3BzLmF2YXRhcn0gXG5cdFx0XHRcdFx0XHRcdGFsdD1cIlVzZXIgQXZhdGFyXCIgXG5cdFx0XHRcdFx0XHRcdGhlaWdodD1cIjQwXCJcblx0XHRcdFx0XHRcdFx0d2lkdGg9XCI0MFwiXG5cdFx0XHRcdFx0XHRcdGNsYXNzTmFtZT1cImltZy1jaXJjbGVcIiAvPlxuXHRcdFx0XHQ8L3NwYW4+XG5cdFx0XHRcdDxkaXYgY2xhc3NOYW1lPVwiY2hhdC1ib2R5IGNsZWFyZml4XCI+XG5cdFx0XHRcdFx0PGRpdiBjbGFzc05hbWU9XCJoZWFkZXJcIj5cblx0XHRcdFx0XHRcdDxzdHJvbmcgY2xhc3NOYW1lPVwicHJpbWFyeS1mb250XCI+e3RoaXMucHJvcHMudXNlcm5hbWV9PC9zdHJvbmc+XG5cdFx0XHRcdFx0XHQ8c21hbGwgY2xhc3NOYW1lPVwicHVsbC1yaWdodCB0ZXh0LW11dGVkXCI+XG5cdFx0XHRcdFx0XHRcdDxpIGNsYXNzTmFtZT1cImZhIGZhLWNsb2NrLW8gZmEtZndcIj48L2k+IHt0aGlzLnN0YXRlLnRpbWVBZ299XG5cdFx0XHRcdFx0XHQ8L3NtYWxsPlxuXHRcdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHRcdDxwPnt0aGlzLnByb3BzLmNvbnRlbnR9PC9wPlxuXHRcdFx0XHQ8L2Rpdj5cblx0XHRcdDwvbGk+XG5cdFx0KTtcblx0fVxufSk7XG5cbnZhciBNZXNzYWdlQmFyID0gUmVhY3QuY3JlYXRlQ2xhc3Moe1xuXHRzZW5kTWVzc2FnZTogZnVuY3Rpb24gKGNvbnRlbnQpIHtcblx0XHRzb2NrZXQuZW1pdChcIm1lc3NhZ2U6bmV3XCIsIHtcblx0XHRcdGNvbnRlbnQ6IGNvbnRlbnRcblx0XHR9KTtcblx0fSxcblx0aGFuZGxlU3VibWl0OiBmdW5jdGlvbiAoZSkge1xuXHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHR2YXIgY29udGVudCA9IFJlYWN0LmZpbmRET01Ob2RlKHRoaXMucmVmcy5jb250ZW50KS52YWx1ZS50cmltKCk7XG5cdFx0aWYgKCFjb250ZW50KSByZXR1cm47XG5cdFx0UmVhY3QuZmluZERPTU5vZGUodGhpcy5yZWZzLmNvbnRlbnQpLnZhbHVlID0gJyc7XG5cdFx0dGhpcy5zZW5kTWVzc2FnZShjb250ZW50KTtcblx0XHRyZXR1cm47XG5cdH0sXG5cdHJlbmRlcjogZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiAoXG5cdFx0XHQ8Zm9ybSBvblN1Ym1pdD17dGhpcy5oYW5kbGVTdWJtaXR9ID5cblx0XHRcdFx0PGRpdiBjbGFzc05hbWU9XCJpbnB1dC1ncm91cFwiPlxuXHRcdFx0XHRcdDxpbnB1dCBcblx0XHRcdFx0XHRcdGlkPVwiYnRuLWlucHV0XCIgXG5cdFx0XHRcdFx0XHR0eXBlPVwidGV4dFwiIFxuXHRcdFx0XHRcdFx0Y2xhc3NOYW1lPVwiZm9ybS1jb250cm9sXCIgXG5cdFx0XHRcdFx0XHRyZWY9XCJjb250ZW50XCJcblx0XHRcdFx0XHRcdHBsYWNlaG9sZGVyPVwiQmUgcG9saXRlIHBsZWFzZS4uLlwiIC8+XG5cdFx0XHRcdFx0PHNwYW4gY2xhc3NOYW1lPVwiaW5wdXQtZ3JvdXAtYnRuXCI+XG5cdFx0XHRcdFx0XHQ8aW5wdXQgXG5cdFx0XHRcdFx0XHRcdHR5cGU9XCJzdWJtaXRcIiBcblx0XHRcdFx0XHRcdFx0Y2xhc3NOYW1lPVwiYnRuIGJ0bi1wcmltYXJ5XCIgXG5cdFx0XHRcdFx0XHRcdGlkPVwiYnRuLWNoYXRcIiBcblx0XHRcdFx0XHRcdFx0dmFsdWU9XCJTZW5kXCIgLz5cblx0XHRcdFx0XHQ8L3NwYW4+XG5cdFx0XHRcdDwvZGl2PlxuXHRcdFx0PC9mb3JtPlxuXHRcdCk7XG5cdH1cbn0pO1xuIl19
\ No newline at end of file
diff --git a/public/js/user.js b/public/js/user.js
new file mode 100644
index 0000000..4bea783
--- /dev/null
+++ b/public/js/user.js
@@ -0,0 +1,114 @@
+"use strict";
+
+var UserCounter = React.createClass({displayName: "UserCounter",
+ render: function () {
+ return (
+ React.createElement("li", null,
+ React.createElement("a", {href: "#"},
+ React.createElement("i", {className: "fa fa-users fa-fw"}), " Online",
+ React.createElement("span", {className: "badge add-left"}, " ", this.props.count, " ")
+ )
+ )
+ );
+ }
+});
+
+var UserLogin = React.createClass({displayName: "UserLogin",
+ authorizeId: function (id) {
+ id = parseInt(id, 10);
+ socket.emit("users:authorize", {
+ id: id
+ });
+ },
+ handleSubmit: function (e) {
+ e.preventDefault();
+ var id = React.findDOMNode(this.refs.authorize_id).value.trim();
+ if (!id) return;
+ React.findDOMNode(this.refs.authorize_id).value = '';
+ this.authorizeId(id);
+ return;
+ },
+ render: function () {
+ return (
+ React.createElement("form", {onSubmit: this.handleSubmit},
+ React.createElement("div", {className: "input-group signin"},
+ React.createElement("input", {
+ id: "btn-input",
+ type: "text",
+ className: "form-control",
+ ref: "authorize_id",
+ placeholder: "Choose an ID..."}),
+ React.createElement("span", {className: "input-group-btn"},
+ React.createElement("input", {
+ type: "submit",
+ className: "btn btn-primary",
+ id: "btn-chat",
+ value: "Login"})
+ )
+ ),
+ React.createElement("div", {className: "signin"},
+ React.createElement("p", {className: "text-center"}, React.createElement("small", null, "Just a temporary measure until genuine authentication is implemented"))
+ )
+ )
+ );
+ }
+})
+
+var UserMenu = React.createClass({displayName: "UserMenu",
+ getDefaultProps: function () {
+ return {
+ count: 0,
+ users: []
+ };
+ },
+ componentDidMount: function () {
+ socket.on('users:update', this.updateUsers);
+ },
+ updateUsers: function (data) {
+ this.setProps({
+ count: data.count,
+ users: data.users
+ });
+ },
+ render: function () {
+ var users = this.props.users.map(function (user) {
+ return (
+ React.createElement("li", {key: user.id}, React.createElement("a", {href: "#"}, user.username))
+ );
+ });
+ return (
+ React.createElement("ul", {className: "nav", id: "side-menu"},
+ React.createElement(UserCounter, React.__spread({}, this.props)),
+ users,
+ React.createElement("li", null, React.createElement("br", null), React.createElement(UserLogin, null), React.createElement("br", null))
+ )
+ );
+ }
+});
+
+var CurrentUser = React.createClass({displayName: "CurrentUser",
+ componentDidMount: function () {
+ var self = this;
+ socket.on("users:update", function (data) {
+ self.setProps({
+ user: data.currentUser
+ });
+ });
+ socket.emit("users:refresh", {});
+ },
+ render: function () {
+ if (this.props.user) {
+ return (
+ React.createElement("a", {href: "#"}, this.props.user.username, " ", React.createElement("img", {src: this.props.user.avatar,
+ alt: "User Avatar",
+ height: "20",
+ width: "20"}))
+ );
+ } else {
+ return false;
+ }
+ }
+});
+
+alert("foo")
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNmb3JtZWQuanMiLCJzb3VyY2VzIjpbbnVsbF0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVksQ0FBQzs7QUFFYixJQUFJLGlDQUFpQywyQkFBQTtDQUNwQyxNQUFNLEVBQUUsWUFBWTtFQUNuQjtHQUNDLG9CQUFBLElBQUcsRUFBQSxJQUFDLEVBQUE7SUFDSCxvQkFBQSxHQUFFLEVBQUEsQ0FBQSxDQUFDLElBQUEsRUFBSSxDQUFDLEdBQUksQ0FBQSxFQUFBO0tBQ1gsb0JBQUEsR0FBRSxFQUFBLENBQUEsQ0FBQyxTQUFBLEVBQVMsQ0FBQyxtQkFBb0IsQ0FBSSxDQUFBLEVBQUEsU0FBQSxFQUFBLENBQUE7QUFBQSxLQUNyQyxvQkFBQSxNQUFLLEVBQUEsQ0FBQSxDQUFDLFNBQUEsRUFBUyxDQUFDLGdCQUFpQixDQUFBLEVBQUEsR0FBQSxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFDLEdBQVEsQ0FBQTtJQUN6RCxDQUFBO0dBQ0EsQ0FBQTtJQUNKO0VBQ0Y7QUFDRixDQUFDLENBQUMsQ0FBQzs7QUFFSCxJQUFJLCtCQUErQix5QkFBQTtDQUNsQyxXQUFXLEVBQUUsVUFBVSxFQUFFLEVBQUU7RUFDMUIsRUFBRSxHQUFHLFFBQVEsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7RUFDdEIsTUFBTSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsRUFBRTtHQUM5QixFQUFFLEVBQUUsRUFBRTtHQUNOLENBQUMsQ0FBQztFQUNIO0NBQ0QsWUFBWSxFQUFFLFVBQVUsQ0FBQyxFQUFFO0VBQzFCLENBQUMsQ0FBQyxjQUFjLEVBQUUsQ0FBQztFQUNuQixJQUFJLEVBQUUsR0FBRyxLQUFLLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO0VBQ2hFLElBQUksQ0FBQyxFQUFFLEVBQUUsT0FBTztFQUNoQixLQUFLLENBQUMsV0FBVyxDQUFDLElBQUksQ0FB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ZWF0ZUNsYXNzKHtcblx0cmVuZGVyOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIChcblx0XHRcdDxsaT5cblx0XHRcdFx0PGEgaHJlZj1cIiNcIj5cblx0XHRcdFx0XHQ8aSBjbGFzc05hbWU9XCJmYSBmYS11c2VycyBmYS1md1wiPjwvaT4gT25saW5lIFxuXHRcdFx0XHRcdDxzcGFuIGNsYXNzTmFtZT1cImJhZGdlIGFkZC1sZWZ0XCI+IHt0aGlzLnByb3BzLmNvdW50fSA8L3NwYW4+XG5cdFx0XHRcdDwvYT5cblx0XHRcdDwvbGk+XG5cdFx0KTtcblx0fVxufSk7XG5cbnZhciBVc2VyTG9naW4gPSBSZWFjdC5jcmVhdGVDbGFzcyh7XG5cdGF1dGhvcml6ZUlkOiBmdW5jdGlvbiAoaWQpIHtcblx0XHRpZCA9IHBhcnNlSW50KGlkLCAxMCk7XG5cdFx0c29ja2V0LmVtaXQoXCJ1c2VyczphdXRob3JpemVcIiwge1xuXHRcdFx0aWQ6IGlkXG5cdFx0fSk7XG5cdH0sXG5cdGhhbmRsZVN1Ym1pdDogZnVuY3Rpb24gKGUpIHtcblx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0dmFyIGlkID0gUmVhY3QuZmluZERPTU5vZGUodGhpcy5yZWZzLmF1dGhvcml6ZV9pZCkudmFsdWUudHJpbSgpO1xuXHRcdGlmICghaWQpIHJldHVybjtcblx0XHRSZWFjdC5maW5kRE9NTm9kZSh0aGlzLnJlZnMuYXV0aG9yaXplX2lkKS52YWx1ZSA9ICcnO1xuXHRcdHRoaXMuYXV0aG9yaXplSWQoaWQpO1xuXHRcdHJldHVybjtcblx0fSxcblx0cmVuZGVyOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIChcblx0XHRcdDxmb3JtIG9uU3VibWl0PXt0aGlzLmhhbmRsZVN1Ym1pdH0gPlxuXHRcdFx0XHQ8ZGl2IGNsYXNzTmFtZT1cImlucHV0LWdyb3VwIHNpZ25pblwiPlxuXHRcdFx0XHRcdDxpbnB1dCBcblx0XHRcdFx0XHRcdGlkPVwiYnRuLWlucHV0XCIgXG5cdFx0XHRcdFx0XHR0eXBlPVwidGV4dFwiIFxuXHRcdFx0XHRcdFx0Y2xhc3NOYW1lPVwiZm9ybS1jb250cm9sXCIgXG5cdFx0XHRcdFx0XHRyZWY9XCJhdXRob3JpemVfaWRcIlxuXHRcdFx0XHRcdFx0cGxhY2Vob2xkZXI9XCJDaG9vc2UgYW4gSUQuLi5cIiAvPlxuXHRcdFx0XHRcdDxzcGFuIGNsYXNzTmFtZT1cImlucHV0LWdyb3VwLWJ0blwiPlxuXHRcdFx0XHRcdFx0PGlucHV0IFxuXHRcdFx0XHRcdFx0XHR0eXBlPVwic3VibWl0XCIgXG5cdFx0XHRcdFx0XHRcdGNsYXNzTmFtZT1cImJ0biBidG4tcHJpbWFyeVwiIFxuXHRcdFx0XHRcdFx0XHRpZD1cImJ0bi1jaGF0XCIgXG5cdFx0XHRcdFx0XHRcdHZhbHVlPVwiTG9naW5cIiAvPlxuXHRcdFx0XHRcdDwvc3Bhbj5cblx0XHRcdFx0PC9kaXY+XG5cdFx0XHRcdDxkaXYgY2xhc3NOYW1lPVwic2lnbmluXCI+XG5cdFx0XHRcdDxwIGNsYXNzTmFtZT1cInRleHQtY2VudGVyXCI+PHNtYWxsPkp1c3QgYSB0ZW1wb3JhcnkgbWVhc3VyZSB1bnRpbCBnZW51aW5lIGF1dGhlbnRpY2F0aW9uIGlzIGltcGxlbWVudGVkPC9zbWFsbD48L3A+XG5cdFx0XHRcdDwvZGl2PlxuXHRcdFx0PC9mb3JtPlxuXHRcdCk7XG5cdH1cbn0pXG5cbnZhciBVc2VyTWVudSA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtcblx0Z2V0RGVmYXVsdFByb3BzOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIHtcblx0XHRcdGNvdW50OiAwLFxuXHRcdFx0dXNlcnM6IFtdXG5cdFx0fTtcblx0fSxcblx0Y29tcG9uZW50RGlkTW91bnQ6IGZ1bmN0aW9uICgpIHtcblx0XHRzb2NrZXQub24oJ3VzZXJzOnVwZGF0ZScsIHRoaXMudXBkYXRlVXNlcnMpO1xuXHR9LFxuXHR1cGRhdGVVc2VyczogZnVuY3Rpb24gKGRhdGEpIHtcblx0XHR0aGlzLnNldFByb3BzKHtcblx0XHRcdGNvdW50OiBkYXRhLmNvdW50LFxuXHRcdFx0dXNlcnM6IGRhdGEudXNlcnNcblx0XHR9KTtcblx0fSxcblx0cmVuZGVyOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIHVzZXJzID0gdGhpcy5wcm9wcy51c2Vycy5tYXAoZnVuY3Rpb24gKHVzZXIpIHtcblx0XHRcdHJldHVybiAoXG5cdFx0XHRcdDxsaSBrZXk9e3VzZXIuaWR9PjxhIGhyZWY9XCIjXCI+e3VzZXIudXNlcm5hbWV9PC9hPjwvbGk+XG5cdFx0XHQpO1xuXHRcdH0pO1xuXHRcdHJldHVybiAoXG5cdFx0XHQ8dWwgY2xhc3NOYW1lPVwibmF2XCIgaWQ9XCJzaWRlLW1lbnVcIj5cblx0XHRcdFx0PFVzZXJDb3VudGVyIHsuLi50aGlzLnByb3BzfSAvPlxuXHRcdFx0XHR7dXNlcnN9XG5cdFx0XHRcdDxsaT48YnIgLz48VXNlckxvZ2luIC8+PGJyIC8+PC9saT5cblx0XHRcdDwvdWw+XG5cdFx0KTtcblx0fVxufSk7XG5cbnZhciBDdXJyZW50VXNlciA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtcblx0Y29tcG9uZW50RGlkTW91bnQ6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgc2VsZiA9IHRoaXM7XG5cdFx0c29ja2V0Lm9uKFwidXNlcnM6dXBkYXRlXCIsIGZ1bmN0aW9uIChkYXRhKSB7XG5cdFx0XHRzZWxmLnNldFByb3BzKHtcblx0XHRcdFx0dXNlcjogZGF0YS5jdXJyZW50VXNlclxuXHRcdFx0fSk7XG5cdFx0fSk7XG5cdFx0c29ja2V0LmVtaXQoXCJ1c2VyczpyZWZyZXNoXCIsIHt9KTtcblx0fSxcblx0cmVuZGVyOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMucHJvcHMudXNlcikge1xuXHRcdFx0cmV0dXJuIChcblx0XHRcdFx0PGEgaHJlZj1cIiNcIj57dGhpcy5wcm9wcy51c2VyLnVzZXJuYW1lfSAmbmJzcDs8aW1nIHNyYz17dGhpcy5wcm9wcy51c2VyLmF2YXRhcn1cblx0XHRcdFx0XHRhbHQ9XCJVc2VyIEF2YXRhclwiIFxuXHRcdFx0XHRcdGhlaWdodD1cIjIwXCJcblx0XHRcdFx0XHR3aWR0aD1cIjIwXCIgLz48L2E+XG5cdFx0XHQpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHR9XG59KTtcblxuYWxlcnQoXCJmb29cIikiXX0=
\ No newline at end of file
diff --git a/spec/gather.js b/spec/gather.js
index 530b590..f27c7bd 100644
--- a/spec/gather.js
+++ b/spec/gather.js
@@ -147,6 +147,7 @@ describe("Gather Model:", function () {
});
});
});
+
describe("addUser", function () {
it ("adds gatherer to lobby", function () {
gather.addUser(user);
@@ -159,6 +160,7 @@ describe("Gather Model:", function () {
assert.equal(gather.gatherers.length, 1);
});
});
+
describe("removeUser", function () {
it ("removes gatherer altogether", function () {
gather.addUser(user);
@@ -168,6 +170,7 @@ describe("Gather Model:", function () {
assert.equal(gather.gatherers.length, 0);
});
});
+
describe("moveToMarine", function () {
it ("moves a player to marine", function () {
gather.addUser(user);
@@ -183,6 +186,7 @@ describe("Gather Model:", function () {
});
});
});
+
describe("moveToAlien", function () {
it ("moves a player to alien", function () {
gather.addUser(user);
@@ -198,6 +202,7 @@ describe("Gather Model:", function () {
});
});
});
+
describe("moveToLobby", function () {
it ("moves a player to lobby", function () {
gather.addUser(user);
@@ -208,6 +213,7 @@ describe("Gather Model:", function () {
assert.equal(gather.lobby()[0].id, user.id);
});
});
+
describe("aliens", function () {
it ("returns all gatherers in aliens", function () {
gather.addUser(user);
@@ -215,6 +221,7 @@ describe("Gather Model:", function () {
assert.equal(gather.aliens().length, 1);
});
});
+
describe("marines", function () {
it ("returns all gatherers in marines", function () {
gather.addUser(user);
@@ -222,12 +229,14 @@ describe("Gather Model:", function () {
assert.equal(gather.marines().length, 1);
});
});
+
describe("lobby", function () {
it ("returns all gatherers in lobby", function () {
gather.addUser(user);
assert.equal(gather.lobby().length, 1);
});
});
+
describe("toJson", function () {
it ("returns a json representation of the gather instance", function () {
var output = gather.toJson();
@@ -235,6 +244,7 @@ describe("Gather Model:", function () {
assert.isString(output.state);
});
});
+
describe("leaderVotes", function () {
beforeEach(function () {
gatherers.forEach(function (user) {
@@ -261,6 +271,7 @@ describe("Gather Model:", function () {
assert.equal(gather.leaderVotes().length, 0);
});
});
+
describe("voteForLeader", function () {
beforeEach(function () {
gatherers.forEach(function (user) {
@@ -289,6 +300,7 @@ describe("Gather Model:", function () {
assert.equal(votes[0], secondCandidate.id);
});
});
+
describe("alienLeader", function () {
beforeEach(function () {
gatherers.forEach(function (gatherer) {
@@ -304,6 +316,7 @@ describe("Gather Model:", function () {
assert.isUndefined(gather.alienLeader());
});
});
+
describe("marineLeader", function () {
beforeEach(function () {
gatherers.forEach(function (gatherer) {
@@ -319,6 +332,7 @@ describe("Gather Model:", function () {
assert.isUndefined(gather.marineLeader());
});
});
+
describe("assignMarineLeader", function () {
it ("assigns a marine leader", function () {
gather.addUser(user);
@@ -327,6 +341,7 @@ describe("Gather Model:", function () {
assert.equal(leader.id, user.id);
});
});
+
describe("assignAlienLeader", function () {
it ("assigns an alien leader", function () {
gather.addUser(user);
@@ -335,6 +350,21 @@ describe("Gather Model:", function () {
assert.equal(leader.id, user.id);
});
});
+
+ describe("getGatherer", function () {
+ beforeEach(function () {
+ gather.addGatherer(user);
+ });
+ it ("returns a gatherer given a user", function () {
+ var gatherer = gather.getGatherer(user);
+ assert.equal(gatherer.id, user.id);
+ });
+ it ("returns null if user is not a gatherer", function () {
+ var gatherer = gather.getGatherer(gatherers[0]);
+ assert.isNull(gatherer);
+ });
+ });
+
describe("confirmTeam", function () {
var leader;
beforeEach(function () {
diff --git a/views/partials/foot.hbs b/views/partials/foot.hbs
index 13d57a5..806d4e9 100644
--- a/views/partials/foot.hbs
+++ b/views/partials/foot.hbs
@@ -1 +1,2 @@
-
\ No newline at end of file
+
+
\ No newline at end of file