-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcommandLineInterface.js
417 lines (392 loc) · 15.4 KB
/
commandLineInterface.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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
//Working with command line
var prompt = require('prompt');
//Logging System
var logSystem = require('./logger');
var serverLog = logSystem.getServerLog();
/* File System Object */
var fs = require('fs');
//Save and load saves
var sR = require('./stateRecovery');
//access the server state
var state = require('./serverState');
//access the server
var msgHandler = require('./messageHandler');
//access utils
var utils = require('./utils');
// create directory saves if not already there
if (!fs.existsSync("saves")) {
fs.mkdirSync("saves");
}
//short help text
var helpText = "Valid commands are:\n" +
" about displays information about development team\n".grey +
" disable/enable buzzer disables/enables buzzer\n" +
" fullHelp displays the extended info\n".grey +
" kickUser username moves client to " + state.lobbyTeam + "\n" +
" loadServerState loads the corresponding server state\n".grey +
" key prints the key needed to login as admin\n" +
" renameTeam oldName:newName changes the name of team oldName to newName\n".grey +
" renameUser oldName:newName changes the name of user oldName to newName\n" +
" reset resets the server state".grey;
//full help text
var fullHelp = "Valid commands are:\n" +
" about displays information about development team\n".grey +
" addPoints teamname:points adds the given amount of points to given team\n" +
" changeTeam user:teamname moves user user to the team teamname\n".grey +
" close ends the commandLineInterface\n" +
" createTeam teamname creates team with name teamname\n".grey +
" deleteTeam teamname deletes corresponding team and moves members into lobby\n" +
" disable/enable buzzer disables/enables buzzer\n".grey +
" help displays the info\n" +
" fullHelp displays the extended info\n".grey +
" kickUser username moves client to " + state.lobbyTeam + "\n" +
" loadServerState fileName loads the corresponding server state\n".grey +
" printAK prints the key needed to login as admin\n" +
" renameTeam oldName:newName changes the name of team oldName to newName\n".grey +
" renameUser oldName:newName changes the name of user oldName to newName\n" +
" reset resets the server state\n".grey +
" saveServerState fileName saves the current server state\n" +
" setCountdown newValue sets the countdown start time to newValue\n".grey;
exports.startCLI = function () {
setTimeout(function () {
serverLog.info("This program can be controlled via command line:\n" + "Enter \"help\" to get" +
" further details");
comIntFace();
}, 250);
};
/**
* This starts one iteration of the command line interface
* prompt is used to get the message from the terminal
*/
function comIntFace() {
prompt.start();
prompt.message = "";
prompt.delimiter = "";
var inputCom;
prompt.get([{
name: 'name',
description: 'CLI:'.magenta
}], function (err, result) {
if (err) {
serverLog.warn('CLI terminated by error or via CTL+C');
serverLog.warn('Finishing process');
process.exit(1);
return;
}
inputCom = result.name;
interpretInput(inputCom);
return comIntFace();
}
);
}
/**
* Interprets commands and performs the requested actions
* @param inputCom the commands that needs to be interpreted
*/
function interpretInput(inputCom) {
try {
if (inputCom != null) {
//switch that covers all implemented commands
switch (true) {
case inputCom == "help":
serverLog.info(helpText);
break;
case inputCom == "fullHelp":
serverLog.info(fullHelp);
break;
case stringStartsWith(inputCom, "saveServerState "):
saveServerState(inputCom);
break;
case stringStartsWith(inputCom, "loadServerState"):
loadServerState(inputCom);
break;
case inputCom == "reset":
state.resetServer();
break;
case stringStartsWith(inputCom, "kickUser "):
kickUser(inputCom);
break;
case (inputCom == "printAK" || inputCom == "print key" || inputCom == "printkey" || inputCom == "key"):
serverLog.info(state.getAdminAuthKey());
break;
case inputCom == "close":
return;
case inputCom == "disable buzzer" || inputCom == "d" || inputCom == "disabled":
state.disableBuzzers();
// Broadcast Buzzer status
msgHandler.sendConfigInformation();
break;
case inputCom == "enable buzzer" || inputCom == "e" || inputCom == "enabled":
state.enableBuzzers();
// Broadcast Buzzer status
msgHandler.sendConfigInformation();
break;
case stringStartsWith(inputCom, "createTeam "):
createTeam(inputCom);
break;
case stringStartsWith(inputCom, "deleteTeam "):
deleteTeam(inputCom);
break;
case stringStartsWith(inputCom, "changeTeam "):
changeTeam(inputCom);
break;
case stringStartsWith(inputCom, "renameTeam "):
renameTeam(inputCom);
break;
case stringStartsWith(inputCom, "renameUser "):
renameUser(inputCom);
break;
case stringStartsWith(inputCom, "setCountdown "):
setCountdown(inputCom);
break;
case stringStartsWith(inputCom, "addPoints "):
addPoints(inputCom);
break;
case inputCom == "about":
serverLog.info("\nThis program was developed as project of the course Software " +
"Engineering by Andreas Zeller in ws 2015/2016 at Saarland University.\n" +
"Team Members: Cavelius, Mario\n" +
" Jank, Oliver\n" +
" Jany, Mathäus\n" +
" Merkel, Dieter\n" +
" Schwarz, Fabian\n" +
" Speicher, Patrick\n" +
" Wilhelm, Anna\n" +
"Client: Freiberger, Felix\n" +
"Tutor: Schlosser, Alex\n");
break;
case inputCom == "cake":
serverLog.info("Never heard of it. Must be a lie!\n");
break;
case(inputCom == "do a barrel roll" || inputCom == "use the force luke"):
serverLog.info("This isn't google ...\n");
break;
case inputCom == "answer" :
serverLog.info("42\n");
break;
//if the prompted command is not known the user gets informed that the command is unknown
default:
serverLog.info("Don't know that one ...\n");
}
}
}
catch
(err) {
serverLog.error("Something went wrong! Please check if your arguments are valid for " +
"the requested command.");
}
}
//checks if the string string starts with string prefix
function stringStartsWith(string, prefix) {
return string.slice(0, prefix.length) == prefix;
}
function saveServerState(inputCom){
if (inputCom == "saveServerState") {
serverLog.info("A file name is expected\n")
}
else {
//extract the command
inputCom = inputCom.replace("saveServerState ", "");
//extract all other stuff not allowed in file names
inputCom = inputCom.replace(/[`~!@#$%^&*()|+\-=?;:'",<>\{\}\[\]\\\/]/gi, '');
sR.saveServerStateFileName("saves/" + inputCom);
}
}
function loadServerState(inputCom){
if (inputCom = "loadServerState") {
sR.loadServerState();
return;
}
inputCom = inputCom.replace("loadServerState ", "");
//extract all other stuff not allowed in file names
inputCom = inputCom.replace(/[`~!@#$%^&*()|+\-=?;:'",<>\{\}\[\]\\\/]/gi, '');
sR.loadServerState("saves/" + inputCom);
}
function kickUser(inputCom){
inputCom = inputCom.replace("kickUser ", "");
if (inputCom == "") {
serverLog.warn("no user name given\n");
return;
}
var client = state.getClientGivenName(inputCom);
if (client == null) {
serverLog.warn("Couldn't find user with name: \"" + inputCom + "\"" + "\n");
return;
}
state.removeClientFromTeamsGivenToken(client.basicInfo.clientToken);
state.addClientToTeam(client.basicInfo, state.lobbyTeam);
//Broadcast Team information
msgHandler.sendTeamInformation();
}
function createTeam(inputCom){
inputCom = inputCom.replace("createTeam ", "");
if (state.teamNameAlreadyExists(inputCom)) {
serverLog.warn("Given teamname already exists!\n");
return;
}
var val_res = utils.isValidTeamName(inputCom);
if (!val_res.value) {
serverLog.warn(val_res.description);
return;
}
var newTeam = {
teamName: inputCom,
members: [],
points: 0
};
state.addTeam(newTeam);
//Broadcast Team information
msgHandler.sendTeamInformation();
}
function deleteTeam(inputCom){
inputCom = inputCom.replace("deleteTeam ", "");
if (inputCom == state.lobbyTeam) {
serverLog.warn("Default team \"Lobby\" can't be deleted!\n");
return;
}
if (!state.teamNameAlreadyExists(inputCom)) {
serverLog.warn("Couldn't find team with name: \"" + inputCom + "\"" + "\n");
return;
}
state.removeTeam(inputCom);
//Broadcast Team information
msgHandler.sendTeamInformation();
msgHandler.sendConfigInformation();
}
function renameTeam(inputCom){
inputCom = inputCom.replace("renameTeam ", "");
var oldteam = inputCom.split(":")[0];
var newteam = inputCom.split(":")[1];
if (oldteam == "" || newteam == "") {
serverLog.warn("Parameters not valid. Remember to use : to split old " +
"and new teamname\n");
return;
}
if (oldteam == "Lobby") {
serverLog.warn("Can't rename team Lobby\n");
return;
}
if (state.teamNameAlreadyExists(newteam)) {
serverLog.warn("Name with this name already exists: \"" + newteam + "\"");
return;
}
if (!state.teamNameAlreadyExists(oldteam)) {
serverLog.warn("Team with this name was not found: \"" + oldteam + "\"");
return;
}
var val_res = utils.isValidTeamName(newteam);
if (!val_res.value) {
serverLog.warn(val_res.description);
return;
}
state.renameTeam(oldteam, newteam);
//Broadcast Team information
msgHandler.sendTeamInformation();
msgHandler.sendConfigInformation();
}
function changeTeam(inputCom){
inputCom = inputCom.replace("changeTeam ", "");
var userteam = inputCom.split(":");
var user = userteam[0];
var team = userteam[1];
if (user == "" || team == "") {
serverLog.warn("Parameters not valid. Remember to use : to split user and name of new team\n");
return;
}
if (!state.isTeamChangeAllowed()) {
serverLog.warn("Team change is currently not allowed.\n")
}
if (!state.teamNameAlreadyExists(team)) {
serverLog.warn("Couldn't find team with name: \"" + team + "\"" + "\n");
return;
}
var client = state.getClientGivenName(user);
if (client == null) {
serverLog.warn("Couldn't find user with name: \"" + user + "\"" + "\n");
return;
}
state.removeClientFromTeamsGivenToken(client.basicInfo.clientToken);
state.addClientToTeam(client.basicInfo, team);
//Broadcast Team information
msgHandler.sendTeamInformation();
// Broadcast Buzzer status
msgHandler.sendConfigInformation();
}
function renameUser (inputCom) {
inputCom = inputCom.replace("renameUser ", "");
var useruser = inputCom.split(":");
var olduser = useruser[0];
var newuser = useruser[1];
if (oldteam == "" || newteam == "") {
serverLog.warn("Parameters not valid. Remember to use : to split old " +
"and new username\n");
}
client = state.getClientGivenName(olduser);
if (olduser == null) {
serverLog.warn("User with this name wasn't found: \"" + olduser + "\"");
return;
}
if (state.getClientGivenName(newuser) != null) {
serverLog.warn("User with this name already exists: \"" + newuser + "\"");
return;
}
var val_res = utils.isValidTeamName(newuser);
if (!val_res.value) {
serverLog.warn(val_res.description);
return;
}
client.basicInfo.clientName = newuser;
//Broadcast Team information
msgHandler.sendTeamInformation();
}
function setCountdown(inputCom){
inputCom = inputCom.replace("setCountdown ", "");
inputCom = inputCom.replace(" ", "");
if (isNaN(inputCom)) {
serverLog.warn("Can't set countdown because given parameter is not a number: " + inputCom + "\n");
return;
}
inputCom = parseInt(inputCom, 10);
if (inputCom < 0) {
serverLog.warn("Can't set countdown to a negative value\n");
return;
}
if (inputCom > 600) {
serverLog.warn("You can't set a countdown longer than 10 minutes.\n")
}
inputCom = Math.round(inputCom);
state.setCurrentCountdownConfig(inputCom);
// Broadcast config information to admins
msgHandler.sendAdminConfigInformation();
}
function addPoints(inputCom){
inputCom = inputCom.replace("addPoints ", "");
var team = inputCom.split(":")[0];
var points = inputCom.split(":")[1];
if (team == "" || points == "") {
serverLog.warn("Parameters not valid. Remember to use : to split team " +
"and points\n");
return;
}
if (points == null || isNaN(points)
|| !parseInt(Number(points)) == points || isNaN(parseInt(points, 10))) {
serverLog.warn("Given value is not a number: " + points + "\n");
return;
}
points = parseInt(points, 10);
if (!state.teamNameAlreadyExists(team) || team == state.lobbyTeam) {
serverLog.warn("Given teamname is not valid: " + team + "\n");
return;
}
state.addPointsToTeam(team, points);
//Broadcast Team information
msgHandler.sendTeamInformation();
}
/**
* This calls the intern function interpretInput with the parameter command
* The only purpose of this is to test this module
* @param command
*/
exports.testCLI = function (command) {
interpretInput(command);
};