summaryrefslogtreecommitdiff
path: root/testxml/testxml.py
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2011-01-16 20:23:14 +0200
committerAndrei Karas <akaras@inbox.ru>2011-01-16 20:23:14 +0200
commit3b541786969301af6ba2d747371ab85cf980035c (patch)
tree5dc61670188fe30fe565489ec21685eca0a7bef7 /testxml/testxml.py
parentfbf09712699cc005ddebe4f0cd000e5a14038faf (diff)
downloadtools-3b541786969301af6ba2d747371ab85cf980035c.tar.gz
tools-3b541786969301af6ba2d747371ab85cf980035c.tar.bz2
tools-3b541786969301af6ba2d747371ab85cf980035c.tar.xz
tools-3b541786969301af6ba2d747371ab85cf980035c.zip
Add testxml tool to check client data.
Diffstat (limited to 'testxml/testxml.py')
-rwxr-xr-xtestxml/testxml.py429
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()