#!/usr/bin/python3
import sys, os, os.path, re, cgi
# Configuration variables
realmName = 'maiev'
auctionHouseName = 'horde'
wowdir = '/home/gregstoll/.cedega/World of Warcraft/c_drive/Program Files/World of Warcraft'
accountName = 'gregstoll'
auctionDataFileName = os.path.join(wowdir, 'WTF', 'Account', accountName.upper(), 'SavedVariables', 'Auctioneer.lua')
#auctionDatas = [{'description': "Rilinar's data (less accurate)", 'fileName': auctionDataFileName},
# {'description': "Falandre's data (more accurate)", 'fileName': '/home/gregstoll/projects/auctioneerlookup/Auctioneernew.lua'}]
auctionDatas = [{'description': "Tsouzer's data", 'fileName': auctionDataFileName}]
auctionHouseSpecifier = realmName + '-' + auctionHouseName
def getKeyName(line):
if (line.startswith('[')):
endKeyIndex = line.find(']', 1)
if (endKeyIndex > -1):
key = line[1:endKeyIndex]
if (key.startswith('"')):
key = key[1:]
if (key.endswith('"')):
key = key[:-1]
return key
else:
print("Couldn't find end of key with line \"%s\"!" % line)
else:
# We're in the case of a top-level object. Look for that.
keyMatch = re.compile(r'(\w+)').match(line)
if (keyMatch):
key = keyMatch.group(1)
return key
else:
return None
def getKeyAndValue(line):
key = getKeyName(line)
if (key != None):
startIndex = len(key)
equalsSignIndex = line.find('=', startIndex)
if (equalsSignIndex > -1):
value = line[equalsSignIndex+1:]
else:
value = None
else:
value = line
if (value != None):
value = value.strip()
if (value.startswith('"')):
value = value[1:]
if (value.endswith('"')):
value = value[:-1]
elif (value.endswith('",')):
value = value[:-2]
elif (value.endswith(',')):
value = value[:-1]
return key, value
# This method tests curPathList to see if it conforms to sectionPath.
# ? means match any one 'directory'.
# * means match all directories. You can't have another element after a *.
def testSectionPath(sectionPathList, curPathList):
# Start checking at the beginning.
index = 0
for sectPathElem in sectionPathList:
if (index >= len(curPathList)):
return False
if (sectPathElem == "*"):
return True
elif (sectPathElem != '?'):
if (sectPathElem != curPathList[index]):
return False
index = index + 1
if (len(curPathList) != index):
return False
return True
def doLookupDefer(fileName, sectionPath, matchFunction, callbackFunction, previousDeferObject=None):
if (previousDeferObject == None):
return {'fileName' : fileName,
'sectionPaths' : [sectionPath],
'matchFunctions' : [matchFunction],
'callbackFunctions' : [callbackFunction]}
else:
if (previousDeferObject['fileName'] != fileName):
print("Filename mismatch!")
raise Exception("Filename mismatch!")
previousDeferObject['sectionPaths'].append(sectionPath)
previousDeferObject['matchFunctions'].append(matchFunction)
previousDeferObject['callbackFunctions'].append(callbackFunction)
return previousDeferObject
# What we would like to do is parse this properly and look up things. However,
# this is impractical given the size of the file (it takes 10 seconds or so
# just to parse). So we do an ad-hoc thing.
def runDeferredLookup(deferObject):
file = open(deferObject['fileName'], 'r')
numLines = 0
curPath = []
sectionPathsList = [sectionPath.split('/') for sectionPath in deferObject['sectionPaths']]
isInSectionPaths = [testSectionPath(sectionPathList, curPath) for sectionPathList in sectionPathsList]
for line in file:
line = line.strip()
if (line.endswith('{')):
key = getKeyName(line)
if (key):
curPath.append(key)
else:
print("Couldn't find key with line \"%s\"!" % line)
isInSectionPaths = [testSectionPath(sectionPathList, curPath) for sectionPathList in sectionPathsList]
elif (line.endswith('}') or line.endswith('},')):
curPath.pop()
isInSectionPaths = [testSectionPath(sectionPathList, curPath) for sectionPathList in sectionPathsList]
else:
for i in range(len(isInSectionPaths)):
if (isInSectionPaths[i]):
key, value = getKeyAndValue(line)
#if (key):
if (deferObject['matchFunctions'][i](key, value, curPath)):
#print "Got it in line (path %s): %s" % ('/'.join(curPath), line)
deferObject['callbackFunctions'][i](key, value, curPath)
numLines = numLines + 1
file.close()
# What we would like to do is parse this properly and look up things. However,
# this is impractical given the size of the file (it takes 10 seconds or so
# just to parse). So we do an ad-hoc thing.
def doLookup(fileName, sectionPath, matchFunction, callbackFunction):
deferObject = doLookupDefer(fileName, sectionPath, matchFunction, callbackFunction)
runDeferredLookup(deferObject)
def appendItemToList(value, target):
target[0].append(value[:value.find(';')])
def findAllItemPrefixes(fileName, prefix):
toReturn = [[]]
prefix = prefix.lower()
doLookup(fileName, "AuctioneerItemDB/items", lambda key, value, curPath: value.lower().startswith(prefix), lambda key, value, curPath: appendItemToList(value, toReturn))
return toReturn
def setKey(key, value, target):
target[0] = key
# Find the real name of the item and return it.
target[1] = value
def findItemKey(fileName, itemName):
toReturn = [None, None]
itemName = itemName.lower()
doLookup(fileName, "AuctioneerItemDB/items", lambda key, value, curPath: value.lower().startswith(itemName + ';'), lambda key, value, curPath: setKey(key, value[:value.index(';')], toReturn))
return toReturn
def setBuyoutInfo(value, target):
compactBuyouts = value.split(':')
realBuyouts = []
for buyout in compactBuyouts:
if 'x' in buyout:
splitInfo = buyout.split('x')
splitInfo = [int(x) for x in splitInfo]
for i in range(0,splitInfo[1]):
realBuyouts.append(splitInfo[0])
else:
realBuyouts.append(int(buyout))
# Now, find the median.
numBuyouts = len(realBuyouts)
if (numBuyouts > 0):
if (numBuyouts % 2 == 0):
median = (realBuyouts[(numBuyouts/2) - 1] + realBuyouts[numBuyouts/2]) / 2
else:
median = realBuyouts[(numBuyouts-1)/2]
target['buyoutMedian'] = median
target['buyoutCount'] = numBuyouts
def getAuctionBuyoutData(buyoutData):
toReturn = ''
#for buyoutKey in ('histcount', 'histmed', 'snapcount', 'snapmed'):
for buyoutKey in ('buyoutMedian','buyoutCount'):
if buyoutKey in buyoutData:
toReturn += '<%s>%s%s>' % (buyoutKey, buyoutData[buyoutKey], buyoutKey)
return toReturn
def processAuctionData(data, target):
#print "Got data: %s" % data
prices = data
aCount, minCount, minPrice, bidCount, bidPrice, buyCount, buyPrice = prices.split(';')
# FFV - surely there's a better way to do this section!
aCount = int(aCount)
minCount = int(minCount)
minPrice = int(minPrice)
bidCount = int(bidCount)
bidPrice = int(bidPrice)
buyCount = int(buyCount)
buyPrice = int(buyPrice)
if (aCount > 0):
avgMin = minPrice / minCount
bidPct = (100 * bidCount) / minCount
avgBid = 0
if (bidCount > 0):
avgBid = bidPrice / bidCount
buyPct = (100 * buyCount) / minCount
avgBuy = 0
if (buyCount > 0):
avgBuy = buyPrice / buyCount
toReturn = ''
toReturn += '%d' % aCount
if (aCount > 0):
toReturn += '%d' % avgMin
toReturn += '%d' % bidPct
toReturn += '%d' % avgBid
toReturn += '%d' % buyPct
toReturn += '%d' % avgBuy
target[0] = toReturn
def setLastScanAge(value, target):
target[0] = value[:value.index(';')]
def searchForItem(dataFileName, prefix):
[allItemNames] = findAllItemPrefixes(dataFileName, prefix)
toReturn = ''
toReturn += '%s' % prefix
allItemNames.sort()
for itemName in allItemNames:
toReturn += '%s' % itemName
toReturn += ''
return toReturn
def getAuctionData(itemName):
itemName = itemName.strip()
firstAuctionDataFileName = auctionDatas[0]['fileName']
if (itemName[-1] == '*'):
return searchForItem(firstAuctionDataFileName, itemName[:-1])
[itemKey, realItemName] = findItemKey(auctionDataFileName, itemName)
toReturn = ''
if (realItemName != None):
toReturn += '%s' % realItemName
if (itemKey):
for data in auctionDatas:
toReturn += "" % data['description']
lastScanAge = [None]
buyoutInfo = {}
output = [None]
# FFV - pretty eot sure about this
deferLookup = doLookupDefer(data['fileName'], "AuctioneerSnapshotDB/" + auctionHouseSpecifier + "/updates", lambda key, value, curPath: True, lambda key, value, curPath: setLastScanAge(value, lastScanAge))
# TODO - lookup in AuctioneerSnapshotDB/maiev-horde/auctions
# TODO - Also, AuctioneerHistoryDB/maiev-horde/buyoutPrices for buyout prices (do median)
# deferLookup = doLookupDefer(data['fileName'], "AuctionConfig/stats/?/" + auctionHouseSpecifier, lambda key, value, curPath: (key == itemKey), lambda key, value, curPath: setMedianInfo(value, curPath, medianStats), deferLookup)
deferLookup = doLookupDefer(data['fileName'], "AuctioneerHistoryDB/" + auctionHouseSpecifier + "/totals", lambda key, value, curPath: (key == itemKey), lambda key, value, curPath: processAuctionData(value, output), deferLookup)
deferLookup = doLookupDefer(data['fileName'], "AuctioneerHistoryDB/" + auctionHouseSpecifier + "/buyoutPrices", lambda key, value, curPath: (key == itemKey), lambda key, value, curPath: setBuyoutInfo(value, buyoutInfo), deferLookup)
runDeferredLookup(deferLookup)
if (lastScanAge[0] != None):
toReturn += '%s' % lastScanAge[0]
if (output[0]):
toReturn += output[0]
toReturn += getAuctionBuyoutData(buyoutInfo)
toReturn += ""
toReturn += ''
return toReturn
if (__name__ == '__main__'):
form = cgi.FieldStorage()
itemName = form.getfirst('itemName')
auctionData = getAuctionData(itemName)
print("Content-type: text/xml\n\n")
print(auctionData)