-
Notifications
You must be signed in to change notification settings - Fork 0
/
validate.py
executable file
·426 lines (378 loc) · 14.5 KB
/
validate.py
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
418
419
420
421
422
423
424
425
426
#!/usr/bin/env python
import unittest
from numbers import Number
from game_instance import game
from vector import distance
import Constants
import traceback
def extract(keys, dict):
answer = {}
for k in keys:
answer[k] = dict[k]
return answer
resource_counter = 0
def handle_input(input, turn):
"""Handle POST request data and passes to validators.
@param input: Dictionary of input values to handle
"""
if 'auth' in input.keys():
alive_players = [x.auth for x in game.players.itervalues() if x.alive]
if input['auth'] in alive_players:
player = game.get_player_by_auth(input['auth'])
return validate_actions(game.players[id(player)], input, turn)
else:
return {'success':False,
'message':'bad auth token or non-active player'}
else:
return {'success':False, 'message':'no auth token provided'}
def validate_actions(player, input, turn):
"""Validate actions requested by a player
False
@param player: The player requesting these actions
@param input: JSON actions to parse
@return JSON dump of parse results
"""
if 'actions' not in input:
return {'success':False, 'message': 'no actions provided'}
results = []
with game.action_list_lock:
game.actions[turn][player.auth] = []
resource_counter = player.resources
player.missed = 0
for action in input['actions']:
try:
if action['obj_type'] == "Ship":
results.append(validate_ship_action(action, player, turn, resource_counter))
elif action['obj_type'] == "Base":
results.append(validate_base_action(action, player, turn, resource_counter))
elif action['obj_type'] == "Refinery":
results.append(validate_refinery_action(action, player, turn, resource_counter))
elif action['obj_type'] == "Player":
results.append(validate_player_action(action, player, turn, resource_counter))
else:
results.append({'success':False, 'message':'bad or no obj_type in action'})
except Exception as e:
print e.__class__
traceback.print_exc()
results.append({'success':False, 'message':'action caused server error'})
with game.action_list_lock:
game.completed_turns[game.turn][player.auth] = True
return results
def validate_ship_action(action, player, turn, resource_counter):
"""Valide an action performed by a ship
@param action: Action to validate
@param player: The player that requested the action
"""
# make sure a ship action has all required keys
attrs = ['command', 'obj_id', 'args']
for attr in attrs:
if attr not in action.keys():
return {'success':False,
'message':'ship action requires a %s attribute' % attr}
# attempt to coerce the obj_id to int
try:
obj_id = action['obj_id']
except:
return {'success':False, 'message':'invalid ship id'}
# check if ship exiss
if obj_id in game.game_map.ships.keys():
ship = game.game_map.ships[obj_id]
else:
return {'success':False, 'message': 'ship does not exist'}
# make sure the player owns the ship
if ship.owner != player:
return {'success':False, 'message':'not authenticated for that ship'}
# make sure args is a dict
if not isinstance(action['args'], dict):
return {'success':False, 'message':'args must be a object'}
# validate commands
if action['command'] == 'thrust':
if ship.methods_used['thrust']:
return {'success':False, 'message':'thrust action already used'}
elif 'direction' not in action['args'].keys():
return {'success':False, 'message':'thrust requires direction arg'}
elif not isinstance(action['args']['direction'], list):
return {'success':False, 'message':'direction must be list'}
elif 'speed' not in action['args'].keys():
return {'success':False, 'message':'thrust requires speed arg'}
elif not isinstance(action['args']['speed'], Number):
return {'success':False, 'message':'speed must be Number'}
else:
accel = action['args']['direction']
try:
(a, b) = (accel[0], accel[1])
except:
return {'success':False, 'message':'invalid direction values'}
result = {'object': ship,
'method': action['command'],
'params': extract(['direction', 'speed'], action['args'])}
with game.action_list_lock:
game.actions[turn][player.auth].append(result)
ship.methods_used['thrust'] = True
return {'success' : True, 'message':'success'}
elif action['command'] == 'fire':
if ship.methods_used['fire']:
return {'success':False, 'message':'fire action already used'}
elif 'direction' not in action['args'].keys():
return {'success':False, 'message':'fire requires direction arg'}
else:
direction = action['args']['direction']
if not isinstance(direction, list):
return {'success':False, 'message':'direction must be a list'}
result = {'object': ship,
'method': action['command'],
'params': extract(['direction'], action['args'])}
with game.action_list_lock:
game.actions[turn][player.auth].append(result)
ship.methods_used['fire'] = True
return {'success' : True, 'message':'success'}
elif action['command'] == 'create_refinery':
if ship.methods_used['create_refinery']:
return {'success':False, 'message':'create_refinery action already used'}
elif resource_counter - Constants.refinery_price < 0:
return {'success':False,
'message':'not enough resources'}
elif 'asteroid_id' not in action['args'].keys():
return {'success':False,
'message':'create_refinery requires asteroid_id arg'}
elif player.resources < Constants.refinery_price:
return {'success':False, 'message':'not enough resources!'}
else:
asteroid_id = action['args']['asteroid_id']
if not isinstance(asteroid_id, int):
return {'success':False, 'message':'asteroid_id must be int'}
asteroid = game.game_map.asteroids[asteroid_id]
if distance(ship.position, asteroid.position) > \
Constants.ship_build_radius:
return {'success':False, 'message':'too far away from asteroid'}
if asteroid.refinery != None:
return {'success':False, 'message':'asteroid already has a refinery'}
result = {'object': ship,
'method': action['command'],
'params': extract(['asteroid_id'], action['args'])}
# TODO Check if another ship has built a base/refinery
with game.action_list_lock:
game.actions[turn][player.auth].append(result)
ship.methods_used['create_refinery'] = True
resource_counter -= Constants.refinery_price
return {'success' : True, 'message':'success'}
elif action['command'] == 'create_base':
if ship.methods_used['create_base']:
return {'success':False,
'message':'create_base action already used'}
elif turn == 0:
return {'success':False,
'message':'create_base action can\'t be used first turn'}
elif resource_counter - Constants.base_price < 0:
return {'success':False,
'message':'not enough resources'}
elif 'planet_id' not in action['args'].keys():
return {'success':False,
'message':'create_base requires planet_id arg'}
else:
planet_id = action['args']['planet_id']
if not isinstance(planet_id, int):
return {'success':False, 'message':'planet must be int'}
planet = game.game_map.planets[planet_id]
if distance(ship.position, planet.position) > \
Constants.ship_build_radius:
return {'success':False, 'message':'too far away from planet'}
if planet.base != None:
return {'success':False, 'message':'planet already has a base'}
result = {'object': ship,
'method': action['command'],
'params': extract(['planet_id'], action['args'])}
with game.action_list_lock:
game.actions[turn][player.auth].append(result)
ship.methods_used['create_base'] = True
resource_counter -= Constants.base_price
return {'success' : True, 'message':'success'}
else:
return {'success':False, 'message':'invalid ship command'}
def validate_base_action(action, player, turn, resource_counter):
"""
Validate an action performed by a base
@param action: Action to validate
@param player: The player that requested the action
"""
# make sure a base action h as all required keys
attrs = ['command', 'obj_id', 'args']
for attr in attrs:
if attr not in action.keys():
return {'success':False,
'message':'base action requires a %s attribute' % attr}
# attempt to coerce the obj_id to int
try:
obj_id = action['obj_id']
except:
return {'success':False, 'message':'invalid base id'}
# check if base exists
base = None
for planet in game.game_map.planets.itervalues():
if obj_id == id(planet.base):
base = planet.base
if base == None:
return {'success':False, 'message': 'base does not exist'}
# make sure the player owns the base
if base.owner != player:
return {'success':False, 'message':'not authenticated for that base'}
# check to see if base is active
if base.built > 0:
return {'success':False, 'message':'base is under construction'}
# check if the base is busy
if base.busy != 0:
return {'success':False, 'message':'base is busy'}
# make sure args is a dict
if not isinstance(action['args'], dict):
return {'success':False, 'message':'args must be a object'}
if action['command'] == 'create_ship':
if 'position' not in action['args'].keys():
return {'success':False,
'message':'create_ship requires position arg'}
elif not isinstance(action['args']['position'], list):
return {'success':False, 'message':'position must be list'}
elif resource_counter - Constants.ship_price < 0:
return {'success':False,
'message':'not enough resources'}
position = action['args']['position']
if distance(position, base.position) > \
Constants.base_build_radius:
return {'success':False,
'message':'too far away to build ship'}
else:
position = action['args']['position']
try:
(a, b) = (position[0], position[1])
except:
return {'success':False, 'message':'invalid position values'}
result = {'object': base,
'method': action['command'],
'params':extract(['position'], action['args']) }
with game.action_list_lock:
game.actions[turn][player.auth].append(result)
base.busy = Constants.base_build_busy
resource_counter -= Constants.ship_price
return {'success' : True, 'message':'success'}
elif action['command'] == 'salvage_ship':
if 'ship_id' not in action['args'].keys():
return {'success':False, 'message':'salvage_ship requires ship_id arg'}
else:
ship_id = action['args']['ship_id']
if not isinstance(ship_id, int):
return {'success':False, 'message':'ship must be int'}
ship = game.game_map.ships[ship_id]
if distance(ship.position, base.position) > \
Constants.base_salvage_radius:
return {'success':False,
'message':'too far away to salvage ship'}
result = {'object': base,
'method': action['command'],
'params': extract(['ship_id'], action['args'])}
with game.action_list_lock:
game.actions[turn][player.auth].append(result)
base.busy = Constants.base_salvage_busy
return {'success' : True, 'message':'success'}
elif action['command'] == 'repair_ship':
if 'ship_id' not in action['args'].keys():
return {'success':False, 'message':'repair_ship requires ship_id arg'}
else:
ship_id = action['args']['ship_id']
if not isinstance(ship_id, int):
return {'success':False, 'message':'ship must be int'}
ship = game.game_map.ships[ship_id]
if distance(ship.position, base.position) > \
Constants.base_repair_radius:
return {'success':False,
'message':'too far away to repair ship'}
elif ship.health == Constants.base_health:
return {'success':False,
'message':'ship already at full health'}
result = {'object': base,
'method': action['command'],
'params': extract(['ship_id'], action['args'])}
with game.action_list_lock:
game.actions[turn][player.auth].append(result)
base.busy = Constants.base_repair_busy
return {'success' : True, 'message':'success'}
elif action['command'] == 'destroy':
result = {'object': base,
'method': action['command'],
'params': {}}
with game.action_list_lock:
game.actions[turn][player.auth].append(result)
return {'success' : True, 'message':'success'}
else:
return {'success':False, 'message':'invalid base command'}
def validate_refinery_action(action, player, turn, resource_counter):
"""
Validate an action performed by a refinery
@param action: Action to validate
@param player: The player that requested the action
"""
# make sure a refinery action has all required keys
attrs = ['command', 'obj_id', 'args']
for attr in attrs:
if attr not in action.keys():
return {'success':False,
'message':'refinery action requires a %s attribute' % attr}
# attempt to coerce the obj_id to int
try:
obj_id = action['obj_id']
except:
return {'success':False, 'message':'invalid refinery id'}
# check if refinery exists
for asteroid in game.game_map.asteroids.itervalues():
if obj_id == id(asteroid.refinery):
refinery = asteroid.refinery
else:
return {'success':False, 'message': 'refinery does not exist'}
# make sure the player owns the base
if refinery.owner != player:
return {'success':False, 'message':'not authenticated for that refinery'}
# check to see if base is active
if refinery.built > 0:
return {'success':False, 'message':'refinery is under construction'}
# make sure args is a dict
if not isinstance(action['args'], dict):
return {'success':False, 'message':'args must be a object'}
if action['command'] == 'destroy':
result = {'object': refinery,
'method': action['command'],
'params': {}}
with game.action_list_lock:
game.actions[turn][player.auth].append(result)
return {'success' : True, 'message':'success'}
else:
return {'success':False, 'message':'invalid refinery command'}
def validate_player_action(action, player, turn):
"""
Validate an action performed by a player
@param action: Action to validate
@param player: The player that requested the action
"""
# make sure a base action has all required keys
attrs = ['command']
for attr in attrs:
if attr not in action.keys():
return {'success':False,
'message':'player action requires a %s attribute' % attr}
if action['command'] == 'forfeit':
if player.alive == False:
return {'success' : False, 'message':'player not active'}
else:
game._log("Player " + player.name + " foreited the game.")
result = {'object': player,
'method': action['command'],
'params': {}}
with game.action_list_lock:
game.actions[turn][player.auth].append(result)
return {'success' : True,
'message':'success, thanks for playing!'}
else:
return {'success':False, 'message':'invalid base command'}
class UnitTests(unittest.TestCase):
def test_main(self):
print "hello world"
self.assertTrue(True)
if __name__ == "__main__":
unittest.main()