-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.py
400 lines (319 loc) · 14.2 KB
/
server.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
import sys
import sqlite3
import time
import json
from operator import attrgetter
from operator import itemgetter
from bottle import Bottle, route, run, template, request, static_file
import constants as con
from tamasimulation import TamaSimulation
import item
import shop
class Server:
def __init__(self, host, port):
self.host = host
self.port = port
self.app = Bottle()
self.setupRouting()
self.dbname = "tamapro_database.db"
self.simulations = {}
self.shop = shop.Shop()
self.createNewTamaJSON("debuguid", "debugpw")
self.simulations["debuguid"].addItemJSON("tire")
self.simulations["debuguid"].addItemJSON("child")
self.simulations["debuguid"].addItemJSON("banana")
self.createNewTamaJSON("debuguid2", "debugpw2")
self.simulations["debuguid"].addFriend("debuguid2")
self.saveToDatabase(verbose=2)
self.loadFromDatabase(verbose=True)
def getDatabaseReadyForUpdate(self, verbose=True):
conn = sqlite3.connect(self.dbname)
c = conn.cursor()
c.execute("DELETE FROM tamas")
c.execute("DELETE FROM has")
c.execute("DELETE FROM knows")
c.execute("DELETE FROM shopitems")
print "Database ready for updating!"
conn.commit()
def saveToDatabase(self, verbose=True):
"""Saves all simulations and shops to the database"""
self.getDatabaseReadyForUpdate()
conn = sqlite3.connect(self.dbname)
c = conn.cursor()
if verbose:
print "Connected to database '%s' and established cursor" % \
self.dbname
#Add all the tamas base information
tamaValues = [sim.getDBValues() for sim in self.simulations.values()]
c.executemany("INSERT INTO tamas VALUES (?,?,?,?,?,?,?)", tamaValues)
if verbose:
print " %s tamas inserted into database" % \
len(self.simulations)
#Add all tamas inventory to the has table
numItems = 0
for sim in self.simulations.values():
if verbose == 2: #extra verbose!
print " Tries inserting inventory = %s for tama %s..." %\
(str(sim.inventory), sim.uid)
itemDBValues = sim.getInventoryDBValues()
c.executemany("INSERT INTO has VALUES (?,?,?)", itemDBValues)
numItems += len(itemDBValues)
#add tama relationships
for uid2, level in sim.knows.items():
c.execute("INSERT INTO knows VALUES (?, ?, ?)",
(sim.uid, uid2, level))
if verbose:
print " %s item entries from %s tamas inserted into database" % \
(numItems, len(self.simulations))
if verbose: print "saving shop items!"
c.executemany("INSERT INTO shopitems VALUES (?, ?)",
self.shop.itemAndCostDict.items())
if verbose: print "Saved shop items"
conn.commit()
if verbose:
print "Successfully saved everything to db!\n"
def loadFromDatabase(self, verbose=True):
"""Loads all simulations and shops from the database"""
#Connect to database
conn = sqlite3.connect(self.dbname)
c = conn.cursor()
if verbose:
print "loadFromDatabase: Connected to database '%s' and established cursor" % \
self.dbname
#First, populate list of simulations
c.execute("SELECT * FROM tamas")
propList = c.fetchall()
self.simulations = {}
if verbose: print "SELECT answer:", propList
for prop in propList:
uid = prop[0]
pw = prop[2]
prop = list(prop)
prop[5] = bool(prop[5]) #sick should be a bool!
self.simulations[uid] = TamaSimulation(uid, pw)
self.simulations[uid].readDBValues(prop)
if verbose:
print "self.simulations: %s" % str(self.simulations)
#Load up all items to all tamas
c.execute("SELECT * FROM has")
hasList = c.fetchall()
if verbose: print "has SELECT answer:", hasList
for has in hasList:
uid, name, amount = has
for _ in range(amount):
self.simulations[uid].inventory.append(name)
#Load up all relationships
c.execute("SELECT * FROM knows")
knowsList = c.fetchall()
if verbose: print "knows SELECT answer:", knowsList
for knows in knowsList:
print "knows:", knows
self.simulations[knows[0]].knows[knows[1]] = knows[2]
def start(self):
self.app.run(host=self.host, port=self.port)
def getSimFromUID(self, uid):
"""Returns a certain simulation, or None if no simulation was found
"""
print "in getSimFromUID, simulations:", str(self.simulations)
if uid in self.simulations:
return self.simulations[uid]
else:
return None
def setupRouting(self):
r = self.app.route
#r('/', method="GET", callback=self.index)
r('/', callback=self.index)
r('/json', callback=self.index)
r('/json/', callback=self.index)
r('/json/showiteminfo/<itemStr>', callback=self.showItemInfoJSON)
r('/json/shopshowiteminfo/<itemStr>',
callback=self.shopShowItemInfoJSON)
r('/json/listallitemsinshop', callback=self.listAllItemsInShop)
r('/json/addtama/<uid>/<password>', callback=self.createNewTamaJSON)
r('/json/addtama/<uid>/<password>/', callback=self.createNewTamaJSON)
r('/json/<uid>/<password>', callback=self.login)
r('/json/<uid>/<password>/', callback=self.login)
r('/json/<uid>/<password>/<command>', callback=self.doActionJSON)
r('/json/<uid>/<password>/<command>/', callback=self.doActionJSON)
r('/json/<uid>/<password>/<command>/<arg>', callback=self.doActionJSON)
r('/updatesimulation/<dt>', callback=self.updateSimulation)
r('/updatesimulation/<dt>/', callback=self.updateSimulation)
r('/images/<imagepath:path>', callback=self.getImageRouting)
#############################################################
# ROUTING
#############################################################
def getImageRouting(self, imagepath):
fullPath = "images/" + imagepath
return static_file(imagepath, root='images')
def index(self):
"""Returns a list of simulations running and a list of items"""
s = ""
sb = []
for sim in self.simulations.values():
url = "{0.uid}/{0.password}/status".format(sim)
sb.append("<a href='{0}'>{1.uid}</a></br>".format(
url, sim))
s += "<b>Simulations running:</b></br>"
s += "\n".join(sb)
s += "<b>List of items in shop:</b>\n</br>"
s += "\n</br>".join(self.shop.itemAndCostDict.keys())
s += "</br><b>List of all items:</b>\n</br>"
s += "\n</br>".join(item.items.keys())
return s
def createNewTamaJSON(self, uid, password):
sim = self.getSimFromUID(uid)
if not sim:
self.simulations[uid] = TamaSimulation(uid, password)
jsonObj = {"error": False, "message": "Tama created."}
self.saveToDatabase(verbose=False)
return json.dumps(jsonObj, indent=4, separators=(",", ": "))
else:
jsonObj = {"error": True, "message": "Tama with name {} already exists.".format(uid)}
return json.dumps(jsonObj, indent=4, separators=(",", ": "))
def login(self, uid, password):
sim = self.getSimFromUID(uid)
if not sim:
jsonObj = {"error": True, "message": "Tama {} does not exist.".format(uid)}
return json.dumps(jsonObj, indent=4, separators=(",", ": "))
if sim.password and sim.password != password:
jsonObj = {"error": True, "message": "Wrong password."}
return json.dumps(jsonObj, indent=4, separators=(",", ": "))
jsonObj = {"error": False, "message": "Success."}
return json.dumps(jsonObj, indent=4, separators=(",", ": "))
def doActionJSON(self, uid, password, command, arg=None):
sim = self.getSimFromUID(uid)
if not sim:
jsonObj = {"error": True, "message": "Tama {} does not exist.".format(uid)}
return json.dumps(jsonObj, indent=4, separators=(",", ": "))
if sim.password and sim.password != password:
jsonObj = {"error": True, "message": "Wrong password."}
return json.dumps(jsonObj, indent=4, separators=(",", ": "))
#jsonObj = {"error": False, "message": "Success."}
#return json.dumps(jsonObj, indent=4, separators=(",", ": "))
#Make sure that the command exists and that it has args if needed
if command not in con.commandList:
jsonObj = {"error": True, "message": "Unknown command."}
return json.dumps(jsonObj, indent=4, separators=(",", ": "))
elif command in con.requiresArguments and arg is None:
msg = "The %s command is missing an argument" % command
jsonObj = {"error": True, "message": msg}
return json.dumps(jsonObj, indent=4, separators=(",", ": "))
return self.handleCommandJSON(sim, command, arg)
def handleCommandJSON(self, sim, command, arg):
s = ""
print "in handleCommandJSON, got command %s and arg %s" % \
(command, arg)
#Handle the commands!
if command == "give":
if arg not in item.items:
s += "%s is not a valid item!" % arg
return json.dumps({"error":True, "message": s})
response = sim.addItemJSON(arg)
return response
elif command == "inventory":
#returns item
return {"error": False, "items": sim.inventory}
elif command == "getimage":
fileName = sim.getImageFileName()
print "Serving image with path %s" % fileName
return static_file(fileName, root='')
elif command == "status":
return sim.getStatusJSON()
elif command == "eat":
if arg not in item.items:
s += "%s is not a valid item!" % arg
return json.dumps({"error": True, "message": s})
response = sim.eatJSON(arg)
return response
elif command == "pet":
response = sim.petJSON(arg)
print "DEBUG: After petting, pet mood is now: %s" % sim.mood
return response
elif command == "playwithitem":
if arg not in item.items:
s += "%s is not a valid item!" % arg
return json.dumps({"error": True, "message": s})
response = sim.playWithItemJSON(arg)
print "DEBUG: After playing with the item %s," % arg,
print "pet mood is now: %s" % sim.mood
return response
elif command == "playwithtama":
if arg not in self.simulations:
s += "Tried playing with uid=%s, which doesn't exist!" % arg
return json.dumps({"error": True, "message": s})
otherTama = self.simulations[arg]
response = sim.playWithTamaJSON(otherTama)
print "DEBUG: After %s played with %s," % (sim.uid, otherTama.uid),
print "their moods are %s and %s respectively" % \
(sim.mood, otherTama.mood)
return response
elif command == "getshopitems":
response = self.shop.getItemsJSON()
return response
elif command == "getmoney":
return json.dumps({"error": False, "money": sim.money})
elif command == "buyitem":
return sim.buyItem(self.shop, arg)
elif command == "commands":
return self.showCommands()
elif command == "addfriend":
if arg not in self.simulations:
return json.dumps({"error":True,
"message": "No tama named %s exists!" % arg})
return sim.addFriend(arg)
#Command wasn't handled if we are here
s += "Command %s wasn't handled." % command
return json.dumps({"error": True, "message": s})
def showItemInfoJSON(self, itemStr):
if itemStr not in item.items:
return json.dumps({"error": True,
"message": "Item %s doesn't exist!" % itemStr})
else:
return json.dumps({"error": False,
"description": item.items[itemStr]["description"]})
def shopShowItemInfoJSON(self, itemStr):
if itemStr not in self.shop.itemAndCostDict:
return json.dumps({"error": True,
"message": "Item %s not in shop!" % itemStr})
else:
return json.dumps({"error": False,
"description": item.items[itemStr]["description"],
"price": self.shop.getPriceOfItem(itemStr)})
response = {"error": False}
response.update(item.items[itemStr])
return json.dumps(response)
def listAllItemsInShop(self):
return self.shop.getItemsNamesJSON()
def showCommands(self):
"""Used for debug only: returns an HTML page"""
s = "<a href='../../'>(Go back to stat page)</a></br>"
s += "Commands:</br>"
for command in con.commandList:
s += "<a href='%s'>%s</a></br>" % (command+"/", command)
#s += "</br>".join(con.commandList)
return s
def updateSimulation(self, dt):
try:
dt = int(dt)
except ValueError as e:
return e.message
except:
return "error"
self.shop.update()
for sim in self.simulations.values():
sim.updateSimulation(dt)
self.saveToDatabase(verbose=True)
return "Successfully ran updateSimulation"
#Simulation stuff
def main():
host = '0.0.0.0'
if len(sys.argv) > 1:
port = int(sys.argv[1])
if len(sys.argv) > 2:
host = sys.argv[2]
else:
port = 8087
server = Server(host=host, port=port)
server.start()
if __name__ == "__main__":
main()