#!/usr/bin/python import sys, re, json import elementtree.ElementTree as ET import getarmorydata outputFileName = 'arenadata.json' classNames = ['Druid', 'Hunter', 'Mage', 'Warrior', 'Warlock', 'Shaman', 'Paladin', 'Priest', 'Rogue'] def parseClass(s): possibleClass = None s = s.lower() for cl in classNames: if cl.lower().startswith(s): if (possibleClass != None): raise "Two possible classes ('%s', '%s') found for string '%s'" % (possibleClass, cl, s) possibleClass = cl if (possibleClass == None): raise "No possible class found for string '%s'" % s return possibleClass def updateClasses(old, new): if (new == None): return old vals = new.split(' ') return [parseClass(x) for x in vals] def updatePlayers(old, new): if (new == None): return old newVals = new.split(' ') if (old != None): # Merge them finalNew = old[:] for newVal in newVals: if newVal.startswith('-'): toSubtract = newVal[1:] if (toSubtract not in finalNew): raise "Couldn't find subtracted player '%s'!" % toSubtract else: finalNew.remove(toSubtract) elif newVal.startswith('+'): toAdd = newVal[1:] finalNew.append(toAdd) else: raise "Improperly formatted player: '%s'" % newVal else: finalNew = newVals if (len(finalNew) != 5): raise "Incorrect number of players! Are: %s" % finalNew return finalNew def parseInt(s): return int(s) fields = {'Date': {}, 'Players': {'updateFn': updatePlayers}, 'StartRating': {'parseFn': parseInt}, 'Arena': {}, 'Opponents': {}, 'OpponentsClasses': {'updateFn': updateClasses}, 'Strategy': {}, 'RatingChange': {'parseFn': parseInt}, 'EndRating': {'parseFn': parseInt}, 'Season': {'parseFn': parseInt}} def defaultUpdate(old, new): if (new == None): return old else: return new def initFields(): for field in fields: if ('updateFn' not in fields[field]): fields[field]['updateFn'] = defaultUpdate if ('parseFn' not in fields[field]): fields[field]['parseFn'] = lambda x: x lineRe = re.compile('^(\w+): (.*)$') ratingCache = {} def getRating(teamName): if teamName in ratingCache: return ratingCache[teamName] teamData = getarmorydata.getArenaTeamData(teamName) if (teamData != None and teamData.get('rating') != None): ratingCache[teamName] = int(teamData.get('rating')) else: print "Couldn't find rating for old team %s!" % teamName ratingCache[teamName] = None return ratingCache[teamName] def parseFile(fileName): records = [] # First, read in the existing data. existingLines = '' try: existingFile = open(outputFileName, 'r') existingLines = ''.join(existingFile.readlines()) existingFile.close() records = json.read(existingLines) except Exception, e: pass existingDates = set([record['Date'] for record in records]) # Read in the new ratings for record in records: rating = getRating(record['Opponents']) if (rating != None): record['OpponentsCurRating'] = getRating(record['Opponents']) # If we couldn't get the original rating for some reason, at least # record it now. if ('OpponentsOrigRating' not in record or record['OpponentsOrigRating'] == None): record['OpponentsOrigRating'] = getRating(record['Opponents']) initFields() myfile = open(fileName, 'r') lines = myfile.readlines() myfile.close() curRecord = {} linenumber = 0 # For simplicity, make sure there's a blank line on the end. lines.append('') firstAfterBeginning = True for line in lines: linenumber += 1 line = line.strip() if line == '': # Done with this record; write it out if it's unique. if (len(curRecord) > 0): # First, see if it's unique for field in ['Date'] + [x for x in fields]: if len(records) == 0: if field not in curRecord: raise "First record missing field %s" % field oldValue = None else: oldValue = fields[field]['parseFn'](records[len(records) - 1][field]) if (field == 'Players' and firstAfterBeginning): oldValue = None if field not in curRecord: newValue = None else: newValue = curRecord[field] curRecord[field] = fields[field]['parseFn'](fields[field]['updateFn'](oldValue, newValue)) if (field == 'Date' and curRecord['Date'] in existingDates): # We need to skip this record break firstAfterBeginning = False # Make sure the date is unique if curRecord['Date'] not in existingDates: checkRating = True if (len(records) != 0): if (records[len(records) - 1]["Season"] != curRecord['Season']): # new season, don't check checkRating = False else: curRecord['StartRating'] = records[len(records) - 1]['EndRating'] if (checkRating and (curRecord['StartRating'] + curRecord['RatingChange'] != curRecord['EndRating'])): raise "Inconsistent rating: %d + %d != %d on line %d" % (curRecord['StartRating'], curRecord['RatingChange'], curRecord['EndRating'], linenumber) # Get the opposing team's rating rating = getRating(curRecord['Opponents']) curRecord['OpponentsOrigRating'] = rating curRecord['OpponentsCurRating'] = rating records.append(curRecord) curRecord = {} elif (not line.startswith('#')): lineMatch = lineRe.match(line) if (not lineMatch): raise "Couldn't parse line %d: %s" % (linenumber, line) field = lineMatch.group(1) if (field not in fields): raise "Unrecognized field in line %d: %s" % (linenumber, field) if (field in curRecord): raise "Duplicate field in line %d: %s" % (linenumber, field) curRecord[field] = lineMatch.group(2) outFile = open(outputFileName, 'w') outFile.write(json.write(records)) outFile.close() #for record in records: # print record if (__name__ == '__main__'): parseFile(sys.argv[1])