def main(): verbose = False recursive = False rename = True moving = True source = os.getcwd() output = os.getcwd() skip = -1 # Parse arguments for argind, arg in enumerate(sys.argv[1:]): if argind == skip: pass elif arg == "-v" : verbose = True elif arg == "-r" : recursive = True elif arg == "-n" : rename = False elif arg == "-c" : moving = False elif arg == "-o" : if len(sys.argv) <= argind+2: sys.exit("\nUnspecified Output directory.") output = sys.argv[argind+2] skip = argind+1 if not os.path.isdir(output): print("\nOutput directory: "+output+" doesnt exist. Creating.") try: os.makedirs(output) except: sys.exit("Cant create "+output) elif arg in ("-h", "-?") or arg.startswith("-") : sys.exit("wotrepparser scans replay files and sorts them into categories (incomplete, result, complete, clanwar, error)." "\nUsage:" \ "\n\nwotrepparser file_or_directory -o output_directory -v -r -n" \ "\n\n-o Specify output directory. Default is current." \ "\n-v Verbose, display every file processed." \ "\n-r Recursive scan of all subdirectories." \ "\n-n Dont rename files." \ "\n-c Copy instead of moving.") elif source == os.getcwd(): if not os.path.exists(arg): sys.exit("\n"+arg+" doesnt exist.") source = arg print ("\nSource:", source) print ("Output:", output) print ("Moving:", moving, "Rename:", rename, "Verbose:", verbose, "Recursive:", recursive, "\n") t1 = time.clock() if os.path.isfile(source): listdir = [source] else: listdir = custom_listfiles(source, "wotreplay", recursive, "temp.wotreplay") # listdir = custom_listfiles("G:\\World_of_Tanks\\replays\\clanwars\\", "wotreplay", False) # listdir += custom_listfiles("G:\\World_of_Tanks\\replays\\complete\\", "wotreplay", False) # listdir += custom_listfiles("G:\\World_of_Tanks\\replays\\incomplete\\", "wotreplay", False) # listdir = {"G:\\World_of_Tanks\\replays\\incomplete\\20121213_0553_usa-T110_39_crimea.wotreplay"} if not os.path.exists("clanwar"): os.makedirs("clanwar") if not os.path.exists("incomplete"): os.makedirs("incomplete") if not os.path.exists("result"): os.makedirs("result") if not os.path.exists("complete"): os.makedirs("complete") errors = 0 for files in listdir: while True: chunks, chunks_bitmask, processing = wotdecoder.replay(files,7) #7 means try to decode all three blocks (binary 111) if processing >=10: #decoder encountered an error dest_index = 5 errors += 1 else: date = datetime.strptime(chunks[0]['dateTime'], '%d.%m.%Y %H:%M:%S').strftime('%Y%m%d_%H%M') dest = ["incomplete", "result", "complete", "complete", "clanwar", "error"] dest_index = processing-1 if processing == 9: #mangled replay, but still have some useful data, lets treat it like Incomplete dest_index = 0 if (processing == 3 and (len(chunks[0]['vehicles'])!=len(chunks[1][1]))) or \ (processing == 4 and chunks[2]['common']['bonusType'] == 5): #cw clan_tag = ["", ""] dest_index = 4 if rename: for playind, player in enumerate(chunks[1][1]): if playind == 0: first_tag = chunks[1][1][player]['clanAbbrev'] clan_tag[chunks[1][1][player]['team'] - 1] = chunks[1][1][player]['clanAbbrev'] elif first_tag != chunks[1][1][player]['clanAbbrev']: clan_tag[chunks[1][1][player]['team'] - 1] = chunks[1][1][player]['clanAbbrev'] break winlose=("Loss","Win_")[chunks[1][0]['isWinner']==1] clan_tag[0] = clan_tag[0] +"_"*(5-len(clan_tag[0])) clan_tag[1] = clan_tag[1] +"_"*(5-len(clan_tag[1])) # You can change cw filename format here. fileo = "cw"+date+"_"+clan_tag[0]+"_"+clan_tag[1]+"_"+winlose+"_"+"-".join(chunks[0]['playerVehicle'].split("-")[1:])+"_"+chunks[0]['mapName']+".wotreplay" else: if rename and (chunks_bitmask&2): #is second Json available? use it to determine win/loss winlose=("Loss","Win_")[chunks[1][0]['isWinner']==1] fileo = date+"_"+winlose+"_"+"-".join(chunks[0]['playerVehicle'].split("-")[1:])+"_"+chunks[0]['mapName']+".wotreplay" elif rename and (chunks_bitmask&4): #is pickle available? use it to determine win/loss winlose=("Loss","Win_")[chunks[2]['common']['winnerTeam']==chunks[2]['personal']['team']] fileo = date+"_"+winlose+"_"+"-".join(chunks[0]['playerVehicle'].split("-")[1:])+"_"+chunks[0]['mapName']+".wotreplay" else: fileo = os.path.basename(files) # print ("\n"+files, fileo) if moving: shutil.move(files, output + os.path.sep + dest[dest_index] + os.path.sep + fileo) else: shutil.copy(files, output + os.path.sep + dest[dest_index] + os.path.sep + fileo) if verbose: print ("\n",dest[dest_index], " -->", fileo) print (wotdecoder.status[processing]) break t2 = time.clock() print ("\nProcessed "+str(len(listdir))+" files.", errors, "errors.") print ("Took %0.3fms" % ((t2-t1)*1000))
def main(): verbose = False recursive = False rename = True dry = False mode = 0 b_r = 0 overwrite = False source = os.getcwd() output = os.getcwd() skip = -1 # Parse arguments for argind, arg in enumerate(sys.argv[1:]): if argind == skip: pass elif arg == "-v" : verbose = True elif arg == "-r" : recursive = True elif arg == "-n" : rename = False elif arg == "-b" : b_r = 1 elif arg == "-b1" : b_r = 2 elif arg == "-b2" : b_r = 3 elif arg == "-f" : overwrite = True elif arg == "-c" : mode = 1 elif arg == "-c0" : mode = 2 elif arg == "-o" : if len(sys.argv) <= argind+2: sys.exit("\nUnspecified Output directory.") output = sys.argv[argind+2] skip = argind+1 if not os.path.isdir(output): print("\nOutput directory: "+output+" doesnt exist. Creating.") try: os.makedirs(output) except: sys.exit("Cant create "+output) elif arg in ("-h", "-?") or arg.startswith("-") : sys.exit("wotrepparser scans replay files and sorts them into categories (incomplete, result, complete, clanwar, error)." "\nUsage:" \ "\n\nwotrepparser file_or_directory -o output_directory -v -r -n" \ "\n\n-o Specify output directory. Default is current." \ "\n-v Verbose, display every file processed." \ "\n-r Recursive scan of all subdirectories." \ "\n-n Dont rename files." \ "\n-b Dump raw battle_results pickle to output_directory\\b_r\\number.pickle" \ "\n-b1 Decode battle_results pickle, save output_directory\\b_r\\number.json" \ "\n-b2 Same as above, but human readable json." \ "\n-f Force overwrite. Default is ask." \ "\n-c Copy instead of moving." \ "\n-c0 Dry run, dont copy, dont move.") elif source == os.getcwd(): if not os.path.exists(arg): sys.exit("\n"+arg+" doesnt exist.") source = arg print ("\nSource:", source) print ("Output:", output) print ("Mode :", ("move","copy","dry run")[mode]+",",("dont rename","rename")[rename]+("",", verbose")[verbose]+("",", recursive dir scan")[recursive]+ \ ("",", raw battle_results pickle",", decoded battle_results json",", decoded human readable battle_results json")[b_r]+".\n") t1 = time.clock() if os.path.isfile(source): listdir = [source] else: listdir = custom_listfiles(source, "wotreplay", recursive, "temp.wotreplay") # listdir = custom_listfiles("G:\\World_of_Tanks\\replays\\clanwars\\", "wotreplay", False) # listdir += custom_listfiles("G:\\World_of_Tanks\\replays\\complete\\", "wotreplay", False) # listdir += custom_listfiles("G:\\World_of_Tanks\\replays\\incomplete\\", "wotreplay", False) # listdir = {"G:\\World_of_Tanks\\replays\\incomplete\\20121213_0553_usa-T110_39_crimea.wotreplay"} if not os.path.exists(output + os.path.sep + "clanwar"): os.makedirs(output + os.path.sep + "clanwar") if not os.path.exists(output + os.path.sep + "incomplete"): os.makedirs(output + os.path.sep + "incomplete") if not os.path.exists(output + os.path.sep + "result"): os.makedirs(output + os.path.sep + "result") if not os.path.exists(output + os.path.sep + "complete"): os.makedirs(output + os.path.sep + "complete") if not os.path.exists(output + os.path.sep + "error"): os.makedirs(output + os.path.sep + "error") if b_r>0 and (not os.path.exists(output + os.path.sep + "b_r")): os.makedirs(output + os.path.sep + "b_r") errors = 0 dest = ["incomplete", "result", "complete", "complete", "clanwar", "error"] stats = [0, 0, 0, 0, 0, 0] for files in listdir: while True: # print ("\n"+files) fileo = os.path.basename(files) chunks, chunks_bitmask, processing, version = wotdecoder.replay(files,7) #7 means try to decode all three blocks (binary 111) if processing == 3 and (len(chunks[0]['vehicles'])!=len(chunks[1][1])) or \ processing == 4 and chunks[2]['common']['bonusType'] == 5: #fogofwar = cw, bonusType = 5 = cw dest_index = 4 stats[dest_index] += 1 if rename: date = datetime.strptime(chunks[0]['dateTime'], '%d.%m.%Y %H:%M:%S').strftime('%Y%m%d_%H%M') clan_tag = ["", ""] for playind, player in enumerate(chunks[1][1]): if playind == 0: first_tag = chunks[1][1][player]['clanAbbrev'] clan_tag[chunks[1][1][player]['team'] - 1] = first_tag elif first_tag != chunks[1][1][player]['clanAbbrev']: clan_tag[chunks[1][1][player]['team'] - 1] = chunks[1][1][player]['clanAbbrev'] break winlose=("Loss","Win_")[chunks[1][0]['isWinner']==1] clan_tag[0] = clan_tag[0] +"_"*(5-len(clan_tag[0])) clan_tag[1] = clan_tag[1] +"_"*(5-len(clan_tag[1])) # You can change cw filename format here. fileo = "cw"+date+"_"+clan_tag[0]+"_"+clan_tag[1]+"_"+winlose+"_"+"-".join(chunks[0]['playerVehicle'].split("-")[1:])+"_"+chunks[0]['mapName']+".wotreplay" elif processing <6 and chunks_bitmask&2: #is second Json available? use it to determine win/loss dest_index = processing-1 stats[dest_index] += 1 if rename: date = datetime.strptime(chunks[0]['dateTime'], '%d.%m.%Y %H:%M:%S').strftime('%Y%m%d_%H%M') winlose=("Loss","Win_")[chunks[1][0]['isWinner']==1] fileo = date+"_"+winlose+"_"+"-".join(chunks[0]['playerVehicle'].split("-")[1:])+"_"+chunks[0]['mapName']+".wotreplay" elif processing <6 and chunks_bitmask&4: #is pickle available? use it to determine win/loss dest_index = processing-1 stats[dest_index] += 1 if rename: date = datetime.strptime(chunks[0]['dateTime'], '%d.%m.%Y %H:%M:%S').strftime('%Y%m%d_%H%M') winlose=("Loss","Win_")[chunks[2]['common']['winnerTeam'] == chunks[2]['personal']['team']] fileo = date+"_"+winlose+"_"+wotdecoder.tank[chunks[2]['personal']['typeCompDescr']][0]+"_"+wotdecoder.maps[chunks[2]['common']['arenaTypeID'] & 65535][0]+".wotreplay" elif processing ==6: #bugged, but has valid score and can be renamed dest_index = 5 stats[dest_index] += 1 if rename: date = datetime.strptime(chunks[0]['dateTime'], '%d.%m.%Y %H:%M:%S').strftime('%Y%m%d_%H%M') winlose=("Loss","Win_")[chunks[1][0]['isWinner']==1] fileo = date+"_"+winlose+"_"+"-".join(chunks[0]['playerVehicle'].split("-")[1:])+"_"+chunks[0]['mapName']+".wotreplay" elif processing ==8: #bugged, but has valid pickle, can be renamed and moved to result dest_index = 1 stats[dest_index] += 1 if rename: date = datetime.strptime(chunks[0]['dateTime'], '%d.%m.%Y %H:%M:%S').strftime('%Y%m%d_%H%M') winlose=("Loss","Win_")[chunks[2]['common']['winnerTeam'] == chunks[2]['personal']['team']] fileo = date+"_"+winlose+"_"+wotdecoder.tank[chunks[2]['personal']['typeCompDescr']][0]+"_"+wotdecoder.maps[chunks[2]['common']['arenaTypeID'] & 65535][0]+".wotreplay" elif processing ==1: #incomplete dest_index = processing-1 stats[dest_index] += 1 elif processing >6: #bugged, cant be renamed dest_index = 5 stats[dest_index] += 1 fileo = output + os.path.sep + dest[dest_index] + os.path.sep + fileo exists = os.path.isfile(fileo) ask = 0 if not overwrite and exists: ask = getkeyboard(fileo, files) if ask == 2: overwrite = True else: ask = 1 if mode == 0 and ask>0: shutil.move(files, fileo) elif mode == 1 and ask>0: shutil.copy(files, fileo) fileb_r = "" if b_r >0 and chunks_bitmask&4: fileb_r = output + os.path.sep + "b_r" + os.path.sep + str(chunks[2]['arenaUniqueID']) +("",".pickle",".json",".json")[b_r] exists = os.path.isfile(fileb_r) ask = 0 if not overwrite and exists: ask = getkeyboard(fileb_r) if ask == 2: overwrite = True else: ask = 1 if b_r == 1 and ask>0: try: fo = open(fileb_r,"wb") f = open(files, "rb") f.seek(8) seek_size = struct.unpack("i",f.read(4))[0] f.seek(seek_size,1) if chunks_bitmask&2: #replay with Pickle can have 2 or 3 blocks, we are only interested in the last one and need to skip others seek_size = struct.unpack("i",f.read(4))[0] f.seek(seek_size,1) third_size = struct.unpack("i",f.read(4))[0] third_chunk = f.read(third_size) f.close() except: raise else: fo.write(third_chunk) fo.close() elif b_r == 2 and ask>0: try: fo = open(fileb_r,"w") except: raise else: json.dump(chunks[2],fo) fo.close() elif b_r == 3 and ask>0: try: fo = open(fileb_r,"w") except: raise else: json.dump(chunks[2], fo, sort_keys=True, indent=4) fo.close() if verbose: print ("\n"+files) print ("", dest[dest_index], " | ", wotdecoder.status[processing]) print (fileo) print (fileb_r) break t2 = time.clock() print ("\n{0:10} {1:>5}".format("Processed", str(len(listdir)))) del dest[2] stats[2] += stats[3] del stats[3] for x in range(0, len(dest)): print ("{0:10} {1:>5}".format(dest[x], stats[x])) print ("Took %0.3fms" % ((t2-t1)*1000))
def main(): nickname = "*" clantag = "*" csens = re.IGNORECASE verbose = 1 show_errors = False owner = False recursive = True full_path = False battle_result = False source = os.getcwd() # Parse arguments skip = -1 for argind, arg in enumerate(sys.argv[1:]): if argind == skip: pass elif arg == "-c" : csens = 0 elif arg == "-v0" : verbose = 0 elif arg == "-v1" : verbose = 1 elif arg == "-v2" : verbose = 2 elif arg == "-v3" : verbose = 3 elif arg == "-v4" : verbose = 4 elif arg == "-e" : show_errors = True elif arg == "-o" : owner = True elif arg == "-r" : recursive = False elif arg == "-p" : full_path = True elif arg == "-b" : battle_result = True elif arg == "-i" : if len(sys.argv) <= argind+2: sys.exit("\nUnspecified input directory.") source = sys.argv[argind+2] if not os.path.exists(source): sys.exit("\n"+source+" doesnt exist.") skip = argind+1 elif arg in ("-h", "-?") or arg.startswith("-") : sys.exit("findplayer scans replay files for players using nickname and/or clantag." "\nUsage:" \ "\n\nfindplayer nickname [clantag] -c -v0..3 -e -o -r -p -b -i input_file_or_directory" \ "\n\nTry `*` for string wildcard, `?` for character wildcard." \ "\n-c Case sensitive search." \ "\n-v0 Verbose 0 = silent running, only give summary." \ "\n-v1 + list replay name, default." \ "\n-v2 + show match result, frag count." \ "\n-v3 + detailed stats." \ "\n-v4 + stats summary." \ "\n-e Show errors." \ "\n-o Include replay owner stats." \ "\n-r Turn off recursive subdirectory scan." \ "\n-p Show full patch." \ "\n-b Scan battle_results(.dat) instead of wotreplays." \ "\n-i Specify input directory. Default is current." \ "\n\nExamples:" \ "\n`*z_?l [1?3]` will match Rasz_pl[123]" \ "\n`[*]` will match any person in a clan." \ "\n`[]` will only match people without clan." \ "\n`??` will list all people with 2 letter nicknames." \ "\n`*` will match everyone.") elif arg.startswith("[") and arg.endswith("]"): clantag = arg[1:-1] else: nickname = arg print ("\nLooking for nickname:", nickname, " clantag: ["+clantag+"]") print ("Source:", source) print ("Verbose:", verbose, "Recursive:", recursive, "Errors:", ("hide","show")[show_errors]) t1 = time.clock() if os.path.isfile(source): listdir = [source] if source.endswith(".dat"): battle_result = True else: listdir = custom_listfiles(source, ("wotreplay", "dat")[battle_result], recursive, "temp.wotreplay") # Prepare regex filters regexnickname = fnmatch.translate(nickname) regexclantag = fnmatch.translate(clantag) reobjnickname = re.compile(regexnickname, csens) reobjclantag = re.compile(regexclantag, csens) matches = 0 matches_kills = 0 matches_stats = 0 errors = 0 f = open("tanks.json", "r") tanks = json.load(f) f.close() tank = {} for ta in tanks: tank [ (ta['tankid']<<8) + (ta['countryid']<<4) + 1 ] = ta['title'] f = open("maps.json", "r") mapss = json.load(f) f.close() maps = {} mapidname = {} for ma in mapss: maps [ ma['mapid'] ] = ma['mapname'] mapidname [ ma['mapid'] ] = ma['mapidname'] owner_kills = 0 owner_damage = 0 owner_spotted = 0 player_kills = 0 player_damage = 0 player_spotted = 0 for files in listdir: while True: if verbose < 2: scan_mask = 1 #1 means try to only decode first block (binary 001) else: scan_mask = 7 #7 means decode everything (binary 111) if battle_result: chunks = ["", "", ""] chunks[2] = wotdecoder.battle_result(files) chunks_bitmask = 4 processing = 4 else: chunks, chunks_bitmask, processing = wotdecoder.replay(files, scan_mask) # pprint (chunks[0]) # pprint (chunks[1])chunks[2]['arenaUniqueID'] # pprint (chunks[2]) # pprint (chunks[2]['personal']['accountDBID']) # pprint (chunks[2]['players'][ chunks[2]['personal']['accountDBID'] ]['name']) if (processing >=10) or (not chunks_bitmask&5): #ignore replays with errors, must have at least first Json or pickle errors += 1 if show_errors: print ("\n\n---") print ("", ("",os.path.dirname(files)+os.path.sep)[full_path] + os.path.basename(files)) print (wotdecoder.status[processing]) print ("---", end="") break match = False player_found = 0 owner_found = 0 owner_name = "" owner_clan = "" if chunks_bitmask&4: vehicles = chunks[2]['players'] owner_name = chunks[2]['players'][ chunks[2]['personal']['accountDBID'] ]['name'] owner_found = chunks[2]['personal']['accountDBID'] elif chunks_bitmask&2: vehicles = chunks[1][1] owner_name = chunks[0]['playerName'] else: vehicles = chunks[0]['vehicles'] owner_name = chunks[0]['playerName'] for player in vehicles: check_player_name = vehicles[player]['name'] check_player_clan = vehicles[player]['clanAbbrev'] if not match and reobjnickname.match(check_player_name) and reobjclantag.match(check_player_clan): match = True matches += 1 player_found = player player_name = vehicles[player]['name'] player_clan = "["+vehicles[player]['clanAbbrev']+"]" if owner_found==0 and (vehicles[player]['name'] == owner_name): #find owner playerID owner_found = player owner_clan = "["+vehicles[player]['clanAbbrev']+"]" if not match: break if verbose >0: print ("\n\n--------------------------------------------------------------------------------") print ("", ("",os.path.dirname(files)+os.path.sep)[full_path] + os.path.basename(files)) print ("---") print ("{0:39}{1:39}".format(player_name+player_clan, ("","| "+owner_name+owner_clan)[owner])) if chunks_bitmask&4: vehicle_player_found = chunks[2]['players'][player_found]['vehicleid'] if owner: vehicle_owner_found = chunks[2]['players'][owner_found]['vehicleid'] if verbose >1: if chunks_bitmask&4: #is pickle available? if chunks[2]['common']['finishReason']==3: win_loss="Draw" else: win_loss = ("Loss","Win ")[chunks[2]['common']['winnerTeam']==chunks[2]['vehicles'][vehicle_player_found]['team']] finishReason = "("+("", "extermination", "base capture", "timeout")[ chunks[2]['common']['finishReason'] ]+")" print ("--- {0:4} on {1:28}{2:>40}".format(win_loss, maps[ chunks[2]['common']['arenaTypeID'] ], finishReason)) elif chunks_bitmask&2: #is second Json available? finishReason = "" print ("--- {0:4} on {1:28}{2:15}".format(("Loss","Win ")[chunks[1][0]['isWinner']==1], chunks[0]['mapDisplayName'], finishReason)) else: #incomplete, all we can tell is tanks if owner: owner_string = " {0:<18}".format(chunks[0]['vehicles'][owner_found]['vehicleType'].split(":")[1]) else: owner_string = "" print (" {0:<18}{1:39}".format(chunks[0]['vehicles'][player_found]['vehicleType'].split(":")[1], owner_string)) if chunks_bitmask&4: #is second Json available? if owner: owner_string_kills = "| Kills ={0:>5}".format( chunks[2]['vehicles'][vehicle_owner_found]['kills']) owner_string_tank = "| {0:8} in {1:<27}".format( ("Died","Survived")[chunks[2]['vehicles'][vehicle_owner_found]['health']>0], tank[ chunks[2]['vehicles'][vehicle_owner_found]['typeCompDescr'] ]) owner_kills += chunks[2]['vehicles'][vehicle_owner_found]['kills'] else: owner_string_kills = "" owner_string_tank = "" print ("{0:8} in {1:<27}{2:39}".format(("Died","Survived")[chunks[2]['vehicles'][vehicle_player_found]['health']>0], tank[ chunks[2]['vehicles'][vehicle_player_found]['typeCompDescr'] ], owner_string_tank )) print ("Kills ={0:>5}{1:26}{2:39}".format(chunks[2]['vehicles'][vehicle_player_found]['kills'], "", owner_string_kills )) player_kills += chunks[2]['vehicles'][vehicle_player_found]['kills'] matches_kills += 1 elif chunks_bitmask&2: #is second Json available? if owner: # print (player_found, owner_found) # pprint (chunks[1][1]) owner_string_kills = "| Kills ={0:>5}".format( len(chunks[1][0]['killed']) ) owner_string_tank = "| {0:8} in {1:<27}".format( ("Died","Survived")[ chunks[1][1][owner_found]['isAlive']==1 ], chunks[1][1][owner_found]['vehicleType'].split(":")[1] ) owner_kills += chunks[1][2][owner_found]['frags'] else: owner_string_kills = "" owner_string_tank = "" print ("{0:8} in {1:<27}{2:39}".format(("Died","Survived")[ chunks[1][1][player_found]['isAlive']==1 ], chunks[1][1][player_found]['vehicleType'].split(":")[1], owner_string_tank)) print ("Kills ={0:>5}{1:26}{2:39}".format(chunks[1][2][player_found]['frags'], "", owner_string_kills)) player_kills += chunks[1][2][player_found]['frags'] matches_kills += 1 if verbose >2 and chunks_bitmask&4: #is pickle available? use it for detailed stats player = int(player) if owner: owner_string_damage = "| Damage ={0:>5}".format(chunks[2]['vehicles'][vehicle_owner_found]['damageDealt']) owner_string_spotted = "| Spotted={0:>5}".format(chunks[2]['vehicles'][vehicle_owner_found]['damageAssisted']) owner_damage += chunks[2]['vehicles'][vehicle_owner_found]['damageDealt'] owner_spotted += chunks[2]['vehicles'][vehicle_owner_found]['damageAssisted'] else: owner_string_damage = "" owner_string_spotted = "" print ("Damage ={0:>5}{1:26}{2:39}".format(chunks[2]['vehicles'][vehicle_player_found]['damageDealt'], "", owner_string_damage)) print ("Spotted={0:>5}{1:26}{2:39}".format(chunks[2]['vehicles'][vehicle_player_found]['damageAssisted'], "", owner_string_spotted)) player_damage += chunks[2]['vehicles'][vehicle_player_found]['damageDealt'] player_spotted += chunks[2]['vehicles'][vehicle_player_found]['damageAssisted'] matches_stats += 1 if battle_result: #we are decoding battle_result, lets more-or-less reconstruct potential replay name # its not 'pixel' accurate, im too lazy to get tank country and underscores correct. timestamp = datetime.fromtimestamp(chunks[2]['common']['arenaCreateTime']).strftime('%Y%m%d_%H%M') print ("Belongs to~", timestamp+"_"+tank[ chunks[2]['vehicles'][vehicle_owner_found]['typeCompDescr'] ]+"_"+mapidname[ chunks[2]['common']['arenaTypeID'] ]+".wotreplay") break if matches > 0: if verbose >3: # stats summary if owner: owner_string_kills = "| Kills ={0:>9.2f}".format( owner_kills/matches_kills ) owner_string_damage = "| Damage ={0:>9.2f}".format( owner_damage/matches_stats ) owner_string_spotted = "| Spotted={0:>9.2f}".format( owner_spotted/matches_stats ) else: owner_string_kills = "" owner_string_damage = "" owner_string_spotted = "" print ("\nSummary (average):") print ("Kills ={0:>9.2f}{1:23}{2:39}".format(player_kills/matches_kills , "", owner_string_kills)) print ("Damage ={0:>9.2f}{1:23}{2:39}".format(player_damage/matches_stats , "", owner_string_damage)) print ("Spotted={0:>9.2f}{1:23}{2:39}".format(player_spotted/matches_stats , "", owner_string_spotted)) print("\n\nFound", matches, "matches. ", end="") else: print("\n\nNo matches found. ", end="") print(errors, "errors.") t2 = time.clock() print ("\nProcessing "+str(len(listdir))+" files took %0.3fms" % ((t2-t1)*1000))
def main(): verbose = False recursive = False rename = True moving = True source = os.getcwd() output = os.getcwd() skip = -1 # Parse arguments for argind, arg in enumerate(sys.argv[1:]): if argind == skip: pass elif arg == "-v": verbose = True elif arg == "-r": recursive = True elif arg == "-n": rename = False elif arg == "-c": moving = False elif arg == "-o": if len(sys.argv) <= argind + 2: sys.exit("\nUnspecified Output directory.") output = sys.argv[argind + 2] skip = argind + 1 if not os.path.isdir(output): print("\nOutput directory: " + output + " doesnt exist. Creating.") try: os.makedirs(output) except: sys.exit("Cant create " + output) elif arg in ("-h", "-?") or arg.startswith("-"): sys.exit("wotrepparser scans replay files and sorts them into categories (incomplete, result, complete, clanwar, error)." "\nUsage:" \ "\n\nwotrepparser file_or_directory -o output_directory -v -r -n" \ "\n\n-o Specify output directory. Default is current." \ "\n-v Verbose, display every file processed." \ "\n-r Recursive scan of all subdirectories." \ "\n-n Dont rename files." \ "\n-c Copy instead of moving.") elif source == os.getcwd(): if not os.path.exists(arg): sys.exit("\n" + arg + " doesnt exist.") source = arg print("\nSource:", source) print("Output:", output) print("Moving:", moving, "Rename:", rename, "Verbose:", verbose, "Recursive:", recursive, "\n") t1 = time.clock() if os.path.isfile(source): listdir = [source] else: listdir = custom_listfiles(source, "wotreplay", recursive, "temp.wotreplay") # listdir = custom_listfiles("G:\\World_of_Tanks\\replays\\clanwars\\", "wotreplay", False) # listdir += custom_listfiles("G:\\World_of_Tanks\\replays\\complete\\", "wotreplay", False) # listdir += custom_listfiles("G:\\World_of_Tanks\\replays\\incomplete\\", "wotreplay", False) # listdir = {"G:\\World_of_Tanks\\replays\\incomplete\\20121213_0553_usa-T110_39_crimea.wotreplay"} if not os.path.exists("clanwar"): os.makedirs("clanwar") if not os.path.exists("incomplete"): os.makedirs("incomplete") if not os.path.exists("result"): os.makedirs("result") if not os.path.exists("complete"): os.makedirs("complete") errors = 0 for files in listdir: while True: chunks, chunks_bitmask, processing = wotdecoder.replay( files, 7) #7 means try to decode all three blocks (binary 111) if processing >= 10: #decoder encountered an error dest_index = 5 errors += 1 else: date = datetime.strptime( chunks[0]['dateTime'], '%d.%m.%Y %H:%M:%S').strftime('%Y%m%d_%H%M') dest = [ "incomplete", "result", "complete", "complete", "clanwar", "error" ] dest_index = processing - 1 if processing == 9: #mangled replay, but still have some useful data, lets treat it like Incomplete dest_index = 0 if (processing == 3 and (len(chunks[0]['vehicles'])!=len(chunks[1][1]))) or \ (processing == 4 and chunks[2]['common']['bonusType'] == 5): #cw clan_tag = ["", ""] dest_index = 4 if rename: for playind, player in enumerate(chunks[1][1]): if playind == 0: first_tag = chunks[1][1][player]['clanAbbrev'] clan_tag[chunks[1][1][player]['team'] - 1] = chunks[1][1][player]['clanAbbrev'] elif first_tag != chunks[1][1][player]['clanAbbrev']: clan_tag[chunks[1][1][player]['team'] - 1] = chunks[1][1][player]['clanAbbrev'] break winlose = ("Loss", "Win_")[chunks[1][0]['isWinner'] == 1] clan_tag[0] = clan_tag[0] + "_" * (5 - len(clan_tag[0])) clan_tag[1] = clan_tag[1] + "_" * (5 - len(clan_tag[1])) # You can change cw filename format here. fileo = "cw" + date + "_" + clan_tag[0] + "_" + clan_tag[ 1] + "_" + winlose + "_" + "-".join( chunks[0]['playerVehicle'].split("-") [1:]) + "_" + chunks[0]['mapName'] + ".wotreplay" else: if rename and ( chunks_bitmask & 2 ): #is second Json available? use it to determine win/loss winlose = ("Loss", "Win_")[chunks[1][0]['isWinner'] == 1] fileo = date + "_" + winlose + "_" + "-".join( chunks[0]['playerVehicle'].split("-") [1:]) + "_" + chunks[0]['mapName'] + ".wotreplay" elif rename and ( chunks_bitmask & 4): #is pickle available? use it to determine win/loss winlose = ("Loss", "Win_")[chunks[2]['common']['winnerTeam'] == chunks[2]['personal']['team']] fileo = date + "_" + winlose + "_" + "-".join( chunks[0]['playerVehicle'].split("-") [1:]) + "_" + chunks[0]['mapName'] + ".wotreplay" else: fileo = os.path.basename(files) # print ("\n"+files, fileo) if moving: shutil.move( files, output + os.path.sep + dest[dest_index] + os.path.sep + fileo) else: shutil.copy( files, output + os.path.sep + dest[dest_index] + os.path.sep + fileo) if verbose: print("\n", dest[dest_index], " -->", fileo) print(wotdecoder.status[processing]) break t2 = time.clock() print("\nProcessed " + str(len(listdir)) + " files.", errors, "errors.") print("Took %0.3fms" % ((t2 - t1) * 1000))