diff options
author | Andrei Karas <akaras@inbox.ru> | 2011-01-16 20:23:14 +0200 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2011-01-16 20:23:14 +0200 |
commit | 3b541786969301af6ba2d747371ab85cf980035c (patch) | |
tree | 5dc61670188fe30fe565489ec21685eca0a7bef7 /testxml/testxml.py | |
parent | fbf09712699cc005ddebe4f0cd000e5a14038faf (diff) | |
download | evol-tools-3b541786969301af6ba2d747371ab85cf980035c.tar.gz evol-tools-3b541786969301af6ba2d747371ab85cf980035c.tar.bz2 evol-tools-3b541786969301af6ba2d747371ab85cf980035c.tar.xz evol-tools-3b541786969301af6ba2d747371ab85cf980035c.zip |
Add testxml tool to check client data.
Diffstat (limited to 'testxml/testxml.py')
-rwxr-xr-x | testxml/testxml.py | 429 |
1 files changed, 429 insertions, 0 deletions
diff --git a/testxml/testxml.py b/testxml/testxml.py new file mode 100755 index 0000000..3be69d0 --- /dev/null +++ b/testxml/testxml.py @@ -0,0 +1,429 @@ +#! /usr/bin/env python2.6 +# -*- coding: utf8 -*- + +import os +import re +import xml +from xml.dom import minidom +from PIL import Image + +filt = re.compile(".+[.]xml", re.IGNORECASE) +dyesplit1 = re.compile(";") +dyesplit2 = re.compile(",") +parentDir = "../../clientdata" +iconsDir = "graphics/items/" +spritesDir = "graphics/sprites/" +errors = 0 +warnings = 0 +errDict = set() + +def printErr(err): + errDict.add(err) + print err + +def showFileErrorById(id, rootDir, fileDir): + print "error: id=" + id + ", file not found: " + fileDir + " (" + rootDir + fileDir + ")" + +def showFileWarningById(id, rootDir, fileDir): + print "warn: id=" + id + ", file not found: " + fileDir + " (" + rootDir + fileDir + ")" + +def showError(id, text): + print "error: id=" + id + " " + text + +def showWarning(id, text): + print "warn: id=" + id + " " + text + +def showMsg(id, text, iserr): + global errors, warnings + if iserr == True: + if text not in errDict: + showError(id, text) + errDict.add(text) + errors = errors + 1 + else: + if text not in errDict: + showWarning(id, text) + errDict.add(text) + warnings = warnings + 1 + +def showMsgSprite(file, text, iserr): + global errors, warnings + if iserr == True: + err = "error: sprite=" + file + " " + text + if err not in errDict: + printErr(err) + errors = errors + 1 + else: + err = "warn: sprite=" + file + " " + text + if err not in errDict: + printErr(err) + warnings = warnings + 1 + +def showMsgFile(file, text, iserr): + global errors, warnings + if iserr == True: + err = "error: file=" + file + " " + text + if err not in errDict: + printErr(err) + errors = errors + 1 + else: + err = "warn: file=" + file + " " + text + if err not in errDict: + printErr(err) + warnings = warnigs + 1 + + +def showFileMsgById(id, rootDir, fileDir, iserr): + global errors, warnings + if iserr == True: + showFileErrorById(id, rootDir, fileDir) + errors = errors + 1 + else: + showFileWarningById(id, rootDir, fileDir) + warnings = warnings + 1 + +def printSeparator(): + print "--------------------------------------------------------------------------------" + +def showHeader(): + print "Evol client data validator" + printSeparator() + +def showFooter(): + printSeparator() + print "Total:" + print " Warnings: " + str(warnings) + print " Errors: " + str(errors) + +def enumDirs(parentDir): + global warnings, errors + files = os.listdir(parentDir) + for file1 in files: + if file1[0] == ".": + continue + file2 = os.path.abspath(parentDir + os.path.sep + file1) + if not os.path.isfile(file2): + enumDirs(file2) + elif filt.search(file1): + try: + minidom.parse(file2) + except xml.parsers.expat.ExpatError as err: + print "error: " + file2 + ", line=" + str(err.lineno) + ", char=" + str(err.offset) + errors = errors + 1 + +def loadPaths(): + try: + dom = minidom.parse(parentDir + "/paths.xml") + for node in dom.getElementsByTagName("option"): + if node.attributes["name"].value == "itemIcons": + iconsDir = node.attributes["value"].value + elif node.attributes["name"].value == "sprites": + spritesDir = node.attributes["value"].value + except: + print "warn: paths.xml not found" + warnings = warnings + 1 + +def splitImage(image): + try: + idx = image.find("|") + if idx > 0: + imagecolor = image[idx + 1:] + image = image[0:idx] + else: + imagecolor = "" + except: + image = "" + imagecolor = "" + return [image, imagecolor] + +def testDye(id, color, text, iserr): + if len(color) < 4: + showMsg(id, "dye to small size: " + text, iserr) + return + colors = dyesplit1.split(color) + for col in colors: + if len(col) < 4: + showMsg(id, "dye to small size: " + text, iserr) + continue + + c = col[0]; + if col[1] != ":": + showMsg(id, "incorrect dye string: " + text, iserr) + continue + + if c != "R" and c != "G" and c != "B" and c != "Y" and c != "M" \ + and c != "C" and c != "W": + showMsg(id, "incorrect dye color: " + c + " in " + text, iserr) + continue + if testDyeInternal(id, col[2:], text, iserr) == False: + continue + + +def testDyeInternal(id, col, text, iserr): + if col[0] != "#": + showMsg(id, "incorrect dye colors: " + text, iserr) + return False + + paletes = dyesplit2.split(col[1:]) + for palete in paletes: + if len(palete) != 6: + showMsg(id, "incorrect dye palete: " + text, iserr) + return False + + for char in palete.lower(): + if (char < '0' or char > '9') and (char < 'a' or char > 'f'): + showMsg(id, "incorrect dye palete: " + text, iserr) + return False + return True + + +def testDyeColors(id, color, text, iserr): + if len(color) < 4: + showMsg(id, "dye to small size: " + text, iserr) + return + colors = dyesplit1.split(color) + for col in colors: + if len(col) < 4: + showMsg(id, "dye to small size: " + text, iserr) + continue + if testDyeInternal(id, col, text, iserr) == False: + continue + + +def testSprites(id, node, iserr): + try: + tmp = node.getElementsByTagName("nosprite") + if tmp is not None and len(tmp) > 1: + showMsg(id, "more than one nosprite tag found", iserr) + nosprite = True + except: + nosprite = False + + try: + sprites = node.getElementsByTagName("sprite") + except: + sprites = None + if nosprite == False: + showMsg(id, "no sprite tag found", iserr) + + if sprites is not None: + if len(sprites) == 0: + if nosprite == False: + showMsg(id, "no sprite tags found", iserr) + elif len(sprites) > 3: + showMsg(id, "incorrect number of sprite tags", iserr) + elif len(sprites) == 1: + file = sprites[0].childNodes[0].data + try: + gender = sprites[0].attributes["gender"].value + except: + gender = "" + + if gender != "" and gender != "unisex": + showMsg(id, "gender tag in alone sprite", iserr) + + testSprite(id, file, iserr) + else: + male = False + female = False + for sprite in sprites: + file = sprite.childNodes[0].data + try: + gender = sprite.attributes["gender"].value + except: + gender = "" + if gender == "male": + if male == True: + showMsg(id, "double male sprite tag", iserr) + male = True + elif gender == "female": + if female == True: + showMsg(id, "double female sprite tag", iserr) + female = True + elif gender == "unisex": + if female == True or male == True: + showMsg(id, "gender sprite tag with unisex tag", False) + male = True + female = True + testSprite(id, file, iserr) + if male == False: + showMsg(id, "no male sprite tag", iserr) + if female == False: + showMsg(id, "no female sprite tag", iserr) + + +def testSprite(id, file, iserr): + tmp = splitImage(file) + color = tmp[1] + file2 = tmp[0] + if color != "": + testDyeColors(id, color, file, iserr) + + fullPath = os.path.abspath(parentDir + "/" + spritesDir + file2) + if not os.path.isfile(fullPath) or os.path.exists(fullPath) == False: + showFileMsgById(id, spritesDir, file2, iserr) + else: + testSpriteFile(id, fullPath, file, spritesDir + file2, iserr) + +def testSpriteFile(id, fullPath, file, fileLoc, iserr): + #todo check src dye + try: + dom = minidom.parse(fullPath) + except: + return + + if len(dom.childNodes) < 1: + return + + root = dom.childNodes[0]; + imagesets = dom.getElementsByTagName("imageset") + if imagesets is None or len(imagesets) != 1: + showMsgSprite(fileLoc, "incorrect number of imageset tags", iserr) + imageset = imagesets[0] + + try: + image = imageset.attributes["src"].value + image0 = image + img = splitImage(image) + image = img[0] + imagecolor = img[1] + except: + showMsgSprite(fileLoc, "image attribute not exist: " + image, iserr) + return + + try: + width = imageset.attributes["width"].value + except: + showMsgSprite(fileLoc, "no width attribute", iserr) + return + + try: + height = imageset.attributes["height"].value + except: + showMsgSprite(fileLoc, "no height attribute", iserr) + + + fullPath = os.path.abspath(parentDir + "/" + image) + if not os.path.isfile(fullPath) or os.path.exists(fullPath) == False: + showMsgSprite(fileLoc, "image file not exist: " + image, iserr) + return + sizes = testImageFile(image, fullPath, 0, iserr) + s = int(sizes[0] / int(width)) * int(width) + if sizes[0] != s: + showMsgSprite(fileLoc, "image width " + str(sizes[0]) + \ + " (need " + str(s) + ") is not multiply to frame size " + width + ", image:" + image, False) + s = int(sizes[1] / int(height)) * int(height) + if sizes[1] != s: + showMsgSprite(fileLoc, "image height " + str(sizes[1]) + \ + " (need " + str(s) + ") is not multiply to frame size " + height + ", image:" + image, False) + + + +def testImageFile(file, fullPath, sz, iserr): + try: + img = Image.open(fullPath, "r") + img.load() + except: + showMsgFile(file, "incorrect image format", iserr) + return + + if img.format != "PNG": + showMsgFile(file, "image format is not png", False) + + sizes = img.size + if sz != 0: + if sizes[0] > sz or sizes[1] > sz: + showMsgFile(file, "image size incorrect (" + str(sizes[0]) \ + + "x" + str(sizes[1]) + ") should be (" + str(sz) + "x" \ + + str(sz) + ")", iserr) + + return sizes + + +def testItems(fileName, imgDir): + global warnings, errors + print "Checking items.xml" + dom = minidom.parse(parentDir + fileName) + idset = set() + for node in dom.getElementsByTagName("item"): + id = node.attributes["id"].value + if id in idset: + print "error: duplicated id=" + id + errors = errors + 1 + else: + idset.add(id) + + idI = int(id) + try: + type = node.attributes["type"].value + except: + type = "" + print "warn: no type attribute for id=" + id + warnings = warnings + 1 + try: + image = node.attributes["image"].value + image0 = image + img = splitImage(image) + image = img[0] + imagecolor = img[1] + except: + image = "" + image0 = "" + imagecolor = "" + + if type == "hairsprite": + if idI >= 0: + print "error: hairsprite with id=" + id + errors = errors + 1 + elif idI < -100: + print "error: hairsprite override player sprites" + errors = errors + 1 + + testSprites(id, node, True) + + elif type == "racesprite": + if idI >= 0: + print "error: racesprite with id=" + id + errors = errors + 1 + elif idI > -100: + print "error: racesprite override player hair" + errors = errors + 1 + elif type == "usable" or type == "unusable" or type == "generic" \ + or type == "equip-necklace" or type == "equip-torso" or type == "equip-feet" \ + or type == "equip-arms" or type == "equip-legs" or type == "equip-head" \ + or type == "equip-shield" or type == "equip-1hand" or type == "equip-2hand" \ + or type == "equip-charm" or type == "equip-ammo" or type == "equip-neck" \ + or type == "equip-ring": + if image == "": + print "error: missing image attribute on id=" + id + errors = errors + 1 + continue + elif len(imagecolor) > 0: + testDye(id, imagecolor, "image=" + image0, True) + + + fullPath = os.path.abspath(parentDir + "/" + imgDir + image) + if not os.path.isfile(fullPath) or os.path.exists(fullPath) == False: + showFileErrorById (id, imgDir, image) + errors = errors + 1 + else: + testImageFile(imgDir + image, fullPath, 32, True) + + if type != "usable" and type != "unusable" and type != "generic" \ + and type != "equip-necklace" and type != "equip-1hand" \ + and type != "equip-2hand" and type != "equip-ammo" \ + and type != "equip-charm" and type != "equip-neck": + err = type != "equip-shield" + testSprites(id, node, err) + elif type == "other": + None + elif type != "": + print "warn: unknown type '" + type + "' for id=" + id + warnings = warnings + 1 + +showHeader() +print "Checking xml file syntax" +enumDirs("../../clientdata") +loadPaths() +testItems("/items.xml", iconsDir) +showFooter() |