Poodletooth-iLand/toontown/uberdog/TopToonsManagerUD.py
2015-11-14 14:28:53 -05:00

246 lines
No EOL
7.6 KiB
Python

# CLEANUP IMPORTS
from direct.directnotify import DirectNotifyGlobal
from direct.fsm.FSM import FSM
from direct.showbase.DirectObject import *
from toontown.toon.ToonDNA import ToonDNA, getSpeciesName
import TopToonsGlobals
import time, random
import datetime, json
import urllib
import urllib2
import hashlib
def getCurrentMonth():
dt = datetime.date.today()
month = dt.month
year = dt.year
return year * 100 + month
def getPrevMonth():
current = getCurrentMonth()
year, month = divmod(current, 100)
month -= 1
if not month:
month = 12
year -= 1
return year * 100 + month
def getNextMonth():
current = getCurrentMonth()
year, month = divmod(current, 100)
month += 1
if month > 12:
month = 1
year += 1
return year * 100 + month
def timeToNextMonth():
now = datetime.datetime.now()
year, month = divmod(getNextMonth(), 100)
return (datetime.datetime(year, month, 1) - now).total_seconds()
def getEmptySiteToonsColl(month):
coll = {}
start = TopToonsGlobals._CAT_BEGIN
end = TopToonsGlobals._CAT_END
while start <= end:
coll[str(start)] = {}
start *= 2
coll['month'] = month
return coll
class SiteUploadFSM(FSM):
notify = DirectNotifyGlobal.directNotify.newCategory('SiteUploadFSM')
URL = config.GetString('toptoons-api-endpoint', 'http://toontownstride.com/toptoons/post/') # Let's hope jumbleweed hasn't changed this
def __init__(self, mgr, data):
FSM.__init__(self, 'SiteUploadFSM')
self.mgr = mgr
self.data = {}
self.month = data.pop('month')
for category, avs in data.items():
self.data[int(category)] = sorted(avs.items(), key=lambda x: -x[1])
self.__cat = TopToonsGlobals._CAT_BEGIN
self.__responses = {}
self.__cache = {}
self.__waiting = {}
self.__dataToSend = {}
self.__failures = -1
self.demand('QueryAvatars')
def enterQueryAvatars(self):
avs = self.data[self.__cat]
cutoff = self.__failures
if cutoff == -1:
cutoff = 5
selected, remaining = avs[:cutoff], avs[cutoff:]
self.data[self.__cat] = remaining
self.__waiting = {int(x[0]): x[1] for x in selected}
avIds = self.__waiting.keys()
for avId in avIds:
if avId in self.__cache:
self.__responses[avId] = (self.__cache[avId][0], self.__waiting.pop(avId))
self.__failures = 0
for avId in self.__waiting:
def response(x, y, avId=avId):
self.__handleToon(avId, x, y)
self.mgr.air.dbInterface.queryObject(self.mgr.air.dbId, avId, response)
if not self.__waiting:
self.demand('SortResults')
def __handleToon(self, avId, dclass, fields):
if avId not in self.__waiting:
return
if dclass != self.mgr.air.dclassesByName['DistributedToonUD']:
self.__failures += 1
self.notify.warning('%d query failed!' % avId)
del self.__waiting[avId]
if not self.__waiting:
self.demand('QueryAvatars')
return
name = fields['setName'][0]
hp = fields['setMaxHp'][0]
dna = ToonDNA(fields['setDNAString'][0])
species = getSpeciesName(dna.head)
color = dna.headColor
if species == 'pig':
dna = 'pig'
else:
if species == 'cat' and color == 26:
dna = 'blackcat'
else:
if color > 23:
color = 0
dna = '%s_%s_%d' % (species, dna.head[1:], color)
self.__responses[avId] = ((name, dna, hp), self.__waiting.pop(avId))
if not self.__waiting:
self.demand('QueryAvatars')
def enterSortResults(self):
responses = sorted(self.__responses.values(), key=lambda x: -x[-1])
self.__dataToSend[self.__cat] = responses
self.__cache.update(self.__responses)
self.__failures = -1
self.__responses = {}
self.__cat *= 2
if self.__cat * 2 == TopToonsGlobals._CAT_END:
self.demand('Upload')
return
self.demand('QueryAvatars')
def enterUpload(self):
self.__dataToSend['month'] = self.month
(success, error), res = self.post(self.URL, self.__dataToSend)
print (success, error), res
def post(self, url, data):
headers = {'User-Agent' : 'TTUberAgent'}
innerData = json.dumps(data)
hmac = hashlib.sha512(innerData + self.mgr.air.getApiKey()).hexdigest() # XXX PROVIDE THE KEY HERE
data = 'data=%s' % urllib.quote(innerData)
data += '&hmac=%s' % urllib.quote(hmac)
success = True
error = None
res = {}
try:
req = urllib2.Request(url, data, headers)
res = json.loads(urllib2.urlopen(req).read())
success = res['success']
error = res.get('error')
except Exception as e:
if hasattr(e, 'read'):
with open('../e.html', 'wb') as f:
f.write(e.read())
success = False
error = str(e)
return (success, error), res
class TopToonsManagerUD(DirectObject):
notify = DirectNotifyGlobal.directNotify.newCategory('TopToonsManagerUD')
def __init__(self, air):
self.air = air
self.__curMonth = getCurrentMonth()
coll = None
if self.air.dbConn:
coll = self.air.dbGlobalCursor.strideToons.find_one({'month': self.__curMonth})
if not coll:
lastMonthColl = self.air.dbGlobalCursor.strideToons.find_one({'month': getPrevMonth()})
if lastMonthColl:
self.__uploadLastMonth(lastMonthColl)
if not coll:
coll = getEmptySiteToonsColl(self.__curMonth)
self.__topToonsData = coll
self.__topToonsData.pop('_id', None)
self.accept('topToonsManager-AI-score-site', self.__topToonsScore)
self.waitForNextMonth()
def __uploadLastMonth(self, data):
self.notify.info('Sending last month result to site...')
SiteUploadFSM(self, data)
def waitForNextMonth(self):
def _nm(task):
self.__uploadLastMonth(self.__topToonsData)
self.__curMonth = getCurrentMonth()
self.__topToonsData = getEmptySiteToonsColl(self.__curMonth)
self.waitForNextMonth()
return task.done
taskMgr.doMethodLater(timeToNextMonth() + 1, _nm, 'TopToonsManagerUD-nextMonth')
def saveSite(self):
if self.air.dbConn:
self.air.dbGlobalCursor.strideToons.update({'month': self.__curMonth}, {'$set': self.__topToonsData}, upsert=True)
def __topToonsScore(self, avId, categories, score):
def _add(cat):
cd = self.__topToonsData[str(cat)]
cd[str(avId)] = cd.get(str(avId), 0) + score
start = TopToonsGlobals._CAT_BEGIN
end = TopToonsGlobals._CAT_END
while start <= end:
if categories & start:
_add(start)
start *= 2
self.saveSite()