-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.js
170 lines (136 loc) · 3.68 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// audience-commands
// *******
// Static
// Serve static directory.
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/public'));
var server = app.listen(process.env.PORT);
// *******
// Sockets
var io = require('socket.io')(server);
io.on('connection', function(client) {
console.log(client.id);
handleConnect(client);
client.on('command', function(command) {
handleCommand(client, command);
});
client.on('start', function() {
startPerformance(client);
});
});
// *******
// Performance
var PerformanceModes = Object.freeze({
"democracy": 1,
"anarchy": 2
});
var VotingModes = Object.freeze({
"time": 1,
"count": 2
});
var performing = false;
var performanceTime = 5 * 60;
var performanceMode = PerformanceModes.democracy;
var performanceStartTime = null;
var votingWindow = 4;
var votingWindowCount = 5;
var votingTimer = null;
var votingMode = VotingModes.time;
var currentVoteMap = {};
var currentVoteList = [];
var currentVoteCount = 0;
function startPerformance(client) {
if (performing) {
return;
}
performing = true;
votingMode = VotingModes.time;
performanceStartTime = new Date();
performanceMode = PerformanceModes.democracy;
io.emit('start', performanceTime);
// Inform all clients that the performance has ended after
// the set performance time.
setTimeout(endPerformance, performanceTime * 1000);
}
function endPerformance() {
performing = false;
io.emit('end');
}
function handleConnect(client) {
if (!performing) {
return;
}
var timeElapsed = (new Date() - performanceStartTime) / 1000;
var timeRemaining = performanceTime - timeElapsed;
client.emit('start', timeRemaining);
}
function handleCommand(client, command) {
if (!performing) {
return;
}
io.emit('command-raw', command);
function reset() {
votingTimer = null;
currentVoteMap = {};
currentVoteList = [];
currentVoteCount = 0;
}
if (votingMode == VotingModes.count) {
// Count-based.
//
// If we've hit the voting window count, calculate vote.
currentVoteMap[command] = (currentVoteMap[command] || 0) + 1;
currentVoteList.push(command);
currentVoteCount++;
if (currentVoteCount == votingWindowCount) {
sendVotedCommand(client);
reset();
}
} else {
// Time-based.
//
// To handle voting, we keep track of the number of votes
// each command receives within a single window. When the
// window passes, we send the command that had the most
// votes, or a random value if all have the same amount
// of votes.
//
// First set up the voting window.
if (votingTimer == null) {
votingTimer = setTimeout(function() {
sendVotedCommand(client);
reset();
}, votingWindow * 1000);
}
// Then track the vote.
currentVoteMap[command] = (currentVoteMap[command] || 0) + 1;
currentVoteList.push(command);
}
}
function sendVotedCommand(client) {
var vote = null;
// Determine the vote.
if (performanceMode == PerformanceModes.democracy) {
// Democracy voting scheme.
var votes = [];
for (var command in currentVoteMap) {
votes.push([command, currentVoteMap[command]]);
}
votes.sort(function(a, b) {
return b[1] - a[1];
});
vote = votes[0][0];
} else {
// Anarchy voting scheme. Pick random vote.
vote = currentVoteList[Math.floor(Math.random() * currentVoteList.length)];
}
// Update the current voting scheme, if needed.
if (PerformanceModes[vote] !== undefined) {
performanceMode = vote;
}
// Send vote to clients.
if (vote != null) {
io.emit('command', vote);
}
}