.BANCHO. .FIX. Add user stats cache and user stats request packet

This commit is contained in:
Nyo
2016-06-16 13:38:17 +02:00
parent b5806bdfbf
commit 7035743362
15 changed files with 203 additions and 63 deletions

View File

@@ -52,7 +52,7 @@ class db:
__params -- array with params. Optional
"""
log.debug(query)
with self.connection.cursor() as cursor:
try:
# Bind params if needed
@@ -77,7 +77,7 @@ class db:
return -- dictionary with result data or False if failed
"""
log.debug(query)
with self.connection.cursor() as cursor:
try:
# Bind params if needed

View File

@@ -1,5 +1,6 @@
import MySQLdb
import threading
from helpers import logHelper as log
class mysqlWorker:
"""
@@ -66,6 +67,7 @@ class db:
query -- Query to execute. You can bind parameters with %s
params -- Parameters list. First element replaces first %s and so on. Optional.
"""
log.debug(query)
# Get a worker and acquire its lock
worker = self.getWorker()
worker.lock.acquire()
@@ -89,6 +91,7 @@ class db:
params -- Parameters list. First element replaces first %s and so on. Optional.
all -- Fetch one or all values. Used internally. Use fetchAll if you want to fetch all values.
"""
log.debug(query)
# Get a worker and acquire its lock
worker = self.getWorker()
worker.lock.acquire()

View File

@@ -167,36 +167,36 @@ def buildPacket(__packet, __packetData = []):
return packetBytes
def readPacketID(__stream):
def readPacketID(stream):
"""
Read packetID from __stream (0-1 bytes)
Read packetID from stream (0-1 bytes)
__stream -- data stream
stream -- data stream
return -- packet ID (int)
"""
return unpackData(__stream[0:2], dataTypes.uInt16)
return unpackData(stream[0:2], dataTypes.uInt16)
def readPacketLength(__stream):
def readPacketLength(stream):
"""
Read packet length from __stream (3-4-5-6 bytes)
Read packet length from stream (3-4-5-6 bytes)
__stream -- data stream
stream -- data stream
return -- packet length (int)
"""
return unpackData(__stream[3:7], dataTypes.uInt32)
return unpackData(stream[3:7], dataTypes.uInt32)
def readPacketData(__stream, __structure = [], __hasFirstBytes = True):
def readPacketData(stream, structure = [], hasFirstBytes = True):
"""
Read packet data from __stream according to __structure
Read packet data from stream according to structure
__stream -- data stream
__structure -- [[name, dataType], [name, dataType], ...]
__hasFirstBytes -- if True, __stream has packetID and length bytes.
if False, __stream has only packetData.
stream -- data stream
structure -- [[name, dataType], [name, dataType], ...]
hasFirstBytes -- if True, stream has packetID and length bytes.
if False, stream has only packetData.
Optional. Default: True
return -- dictionary. key: name, value: read data
"""
@@ -205,7 +205,7 @@ def readPacketData(__stream, __structure = [], __hasFirstBytes = True):
data = {}
# Skip packet ID and packet length if needed
if __hasFirstBytes == True:
if hasFirstBytes == True:
end = 7
start = 7
else:
@@ -213,26 +213,41 @@ def readPacketData(__stream, __structure = [], __hasFirstBytes = True):
start = 0
# Read packet
for i in __structure:
for i in structure:
start = end
unpack = True
if i[1] == dataTypes.string:
if i[1] == dataTypes.intList:
# sInt32 list.
# Unpack manually with for loop
unpack = False
# Read length (uInt16)
length = unpackData(stream[start:start+2], dataTypes.uInt16)
# Read all int inside list
data[i[0]] = []
for j in range(0,length):
data[i[0]].append(unpackData(stream[start+2+(4*j):start+2+(4*(j+1))], dataTypes.sInt32))
# Update end
end = start+2+(4*length)
elif i[1] == dataTypes.string:
# String, don't unpack
unpack = False
# Check empty string
if __stream[start] == 0:
if stream[start] == 0:
# Empty string
data[i[0]] = ""
end = start+1
else:
# Non empty string
# Read length and calculate end
length = uleb128Decode(__stream[start+1:])
length = uleb128Decode(stream[start+1:])
end = start+length[0]+length[1]+1
# Read bytes
data[i[0]] = ''.join(chr(j) for j in __stream[start+1+length[1]:end])
data[i[0]] = ''.join(chr(j) for j in stream[start+1+length[1]:end])
elif i[1] == dataTypes.byte:
end = start+1
elif i[1] == dataTypes.uInt16 or i[1] == dataTypes.sInt16:
@@ -244,6 +259,6 @@ def readPacketData(__stream, __structure = [], __hasFirstBytes = True):
# Unpack if needed
if unpack == True:
data[i[0]] = unpackData(__stream[start:end], i[1])
data[i[0]] = unpackData(stream[start:end], i[1])
return data

View File

@@ -20,6 +20,8 @@ class asyncRequestHandler(tornado.web.RequestHandler):
yield tornado.gen.Task(runBackground, (self.asyncGet, tuple(args), dict(kwargs)))
except Exception as e:
yield tornado.gen.Task(self.captureException, exc_info=True)
finally:
self.finish()
@tornado.web.asynchronous
@tornado.gen.engine
@@ -28,6 +30,8 @@ class asyncRequestHandler(tornado.web.RequestHandler):
yield tornado.gen.Task(runBackground, (self.asyncPost, tuple(args), dict(kwargs)))
except Exception as e:
yield tornado.gen.Task(self.captureException, exc_info=True)
finally:
self.finish()
def asyncGet(self, *args, **kwargs):
self.send_error(405)

View File

@@ -346,3 +346,32 @@ def check2FA(userID, ip):
result = glob.db.fetch("SELECT id FROM ip_user WHERE userid = %s AND ip = %s", [userID, ip])
return True if result is None else False
def getUserStats(userID, gameMode):
"""
Get all user stats relative to gameMode with only two queries
userID --
gameMode -- gameMode number
return -- dictionary with results
"""
modeForDB = gameModes.getGameModeForDB(gameMode)
# Get stats
stats = glob.db.fetch("""SELECT
ranked_score_{gm} AS rankedScore,
avg_accuracy_{gm} AS accuracy,
playcount_{gm} AS playcount,
total_score_{gm} AS totalScore,
pp_{gm} AS pp
FROM users_stats WHERE id = %s LIMIT 1""".format(gm=modeForDB), [userID])
# Get game rank
result = glob.db.fetch("SELECT position FROM leaderboard_{} WHERE user = %s LIMIT 1".format(modeForDB), [userID])
if result == None:
stats["gameRank"] = 0
else:
stats["gameRank"] = result["position"]
# Return stats + game rank
return stats