mirror of
https://github.com/Jylpah/blitz-tools.git
synced 2026-10-21 10:17:05 +02:00
Fix reading filenames from STDIN
This commit is contained in:
1 parent
02e2efc718
commit
5a9f7587b9
4 files changed
+395
-445
No files matched your search
+22
-2
@@ -133,8 +133,24 @@ class WG:
|
||||
}
|
||||
|
||||
nations = [ 'ussr', 'germany', 'usa', 'china', 'france', 'uk', 'japan', 'other']
|
||||
nation_id = {
|
||||
'ussr' : 0,
|
||||
'germany' : 1,
|
||||
'usa' : 2,
|
||||
'china' : 3,
|
||||
'france' : 4,
|
||||
'uk' : 5,
|
||||
'japan' : 6,
|
||||
'other' : 7
|
||||
}
|
||||
|
||||
tank_type = [ 'lightTank', 'mediumTank', 'heavyTank', 'AT-SPG' ]
|
||||
tank_type_id = {
|
||||
'lightTank' : 0,
|
||||
'mediumTank' : 1,
|
||||
'heavyTank' : 2,
|
||||
'AT-SPG' : 3
|
||||
}
|
||||
|
||||
URL_WG_server = {
|
||||
'eu' : 'https://api.wotblitz.eu/wotb/',
|
||||
@@ -167,9 +183,13 @@ class WG:
|
||||
self.maps = json.loads(f.read())
|
||||
except Exception as err:
|
||||
error('Could not read maps file: ' + maps_fn + '\n' + str(err))
|
||||
|
||||
if self.WG_appID != None:
|
||||
self.session = aiohttp.ClientSession()
|
||||
else:
|
||||
self.session = None
|
||||
|
||||
self.session = aiohttp.ClientSession()
|
||||
# self.session = None
|
||||
|
||||
|
||||
## Class methods ------------------------------
|
||||
|
||||
|
||||
+28
-58
@@ -3,6 +3,7 @@
|
||||
# Extract tankopedia data in WG API JSON format from Blitz app files (Android APK unzipped)
|
||||
|
||||
import sys, argparse, json, os, inspect, aiohttp, asyncio, aiofiles, re, logging, time, xmltodict, collections
|
||||
import blitzutils as bu
|
||||
from blitzutils import WG
|
||||
|
||||
logging.getLogger("asyncio").setLevel(logging.DEBUG)
|
||||
@@ -11,31 +12,25 @@ BLITZAPP_STRINGS='/assets/Data/Strings/en.yaml'
|
||||
BLITZAPP_VEHICLES_DIR='/assets/Data/XML/item_defs/vehicles/'
|
||||
BLITZAPP_VEHICLE_FILE='/list.xml'
|
||||
|
||||
VERBOSE = False
|
||||
DEBUG = False
|
||||
|
||||
wg = WG()
|
||||
NATION_ID = {}
|
||||
for i in range(len(wg.nations)):
|
||||
NATION_ID[wg.nations[i]] = i
|
||||
wg = None
|
||||
|
||||
## main() -------------------------------------------------------------
|
||||
async def main(argv):
|
||||
global VERBOSE, DEBUG
|
||||
global wg
|
||||
|
||||
parser = argparse.ArgumentParser(description='Extract Tankopedia data from Blitz game files')
|
||||
parser.add_argument('blitzAppBase', type=str, metavar="BLITZAPP_FOLDER", default=".", help='Base dir of the Blitz App files')
|
||||
parser.add_argument('file', type=str, metavar="FILE", help='Write Tankopedia to file')
|
||||
parser.add_argument('-fm', '--file-maps', dest='file_maps', type=str, default=None, help='File to write map names')
|
||||
parser.add_argument('tanks', type=str, default='tanks.json',metavar="TANKS_FILE", help='File to write Tankopedia')
|
||||
parser.add_argument('maps', type=str, default='maps.json', metavar='MAPS_FILE', help='File to write map names')
|
||||
parser.add_argument('-d', '--debug', action='store_true', default=False, help='Debug mode')
|
||||
parser.add_argument('-v', '--verbose', action='store_true', default=False, help='Verbose mode')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
VERBOSE = args.verbose
|
||||
DEBUG = args.debug
|
||||
if DEBUG: VERBOSE = True
|
||||
|
||||
bu.setVerbose(args.verbose)
|
||||
bu.setDebug(args.debug)
|
||||
wg = WG()
|
||||
|
||||
tasks = []
|
||||
for nation in wg.nations:
|
||||
tasks.append(asyncio.create_task(extractTanks(args.blitzAppBase, nation)))
|
||||
@@ -46,16 +41,15 @@ async def main(argv):
|
||||
|
||||
tank_strs, map_strs = await readUserStrs(args.blitzAppBase)
|
||||
|
||||
async with aiofiles.open(args.file, 'w', encoding="utf8") as outfile:
|
||||
tankopedia = {}
|
||||
async with aiofiles.open(args.tanks, 'w', encoding="utf8") as outfile:
|
||||
tankopedia = collections.OrderedDict()
|
||||
tankopedia['status'] = 'ok'
|
||||
tankopedia['meta'] = { "count": len(tanklist) }
|
||||
tankopedia['data'], tankopedia['userStr'] = await convertTankNames(tanklist, tank_strs)
|
||||
#debug(tankopedia)
|
||||
await outfile.write(json.dumps(tankopedia, ensure_ascii=False, indent=4, sort_keys=False))
|
||||
|
||||
if args.file_maps != None:
|
||||
async with aiofiles.open(args.file_maps, 'w', encoding="utf8") as outfile:
|
||||
if args.maps != None:
|
||||
async with aiofiles.open(args.maps, 'w', encoding="utf8") as outfile:
|
||||
await outfile.write(json.dumps(map_strs, ensure_ascii=False, indent=4, sort_keys=True))
|
||||
|
||||
return None
|
||||
@@ -67,7 +61,7 @@ async def extractTanks(blitzAppBase : str, nation: str):
|
||||
if not os.path.isfile(list_xml_file):
|
||||
print('ERROR: cannot open ' + list_xml_file)
|
||||
return None
|
||||
debug('Opening file: ' + list_xml_file + ' (Nation: ' + nation + ')')
|
||||
bu.debug('Opening file: ' + list_xml_file + ' (Nation: ' + nation + ')')
|
||||
async with aiofiles.open(list_xml_file, 'r') as f:
|
||||
try:
|
||||
tankList = xmltodict.parse(await f.read())
|
||||
@@ -83,7 +77,7 @@ async def extractTanks(blitzAppBase : str, nation: str):
|
||||
tank['type'] = await getTankType(tank_xml['tags'])
|
||||
tanks.append(tank)
|
||||
except Exception as err:
|
||||
error(err)
|
||||
bu.error(err)
|
||||
sys.exit(2)
|
||||
return tanks
|
||||
|
||||
@@ -92,7 +86,7 @@ async def readUserStrs(blitzAppBase : str) -> dict:
|
||||
tank_strs = {}
|
||||
map_strs = {}
|
||||
filename = blitzAppBase + BLITZAPP_STRINGS
|
||||
debug('Opening file: ' + filename + ' for reading UserStrings')
|
||||
bu.debug('Opening file: ' + filename + ' for reading UserStrings')
|
||||
try:
|
||||
async with aiofiles.open(filename, 'r', encoding="utf8") as f:
|
||||
p_tank = re.compile('^"(#\\w+?_vehicles:.+?)": "(.+)"$')
|
||||
@@ -108,7 +102,7 @@ async def readUserStrs(blitzAppBase : str) -> dict:
|
||||
map_strs[m.group(1)] = m.group(2)
|
||||
|
||||
except Exception as err:
|
||||
error(err)
|
||||
bu.error(err)
|
||||
sys.exit(1)
|
||||
|
||||
return tank_strs, map_strs
|
||||
@@ -117,27 +111,31 @@ async def convertTankNames(tanklist : list, tank_strs: dict) -> dict:
|
||||
"""Convert tank names for Tankopedia"""
|
||||
tankopedia = {}
|
||||
userStrs = {}
|
||||
tank_ids = []
|
||||
|
||||
try:
|
||||
for tank in tanklist:
|
||||
tank['name'] = tank_strs[tank['userStr']]
|
||||
userStrs[tank['userStr'].split(':')[1]] = tank['name']
|
||||
tank.pop('userStr', None)
|
||||
tankopedia[str(tank['tank_id'])] = tank
|
||||
tank_ids.append(tank['tank_id']) # for sorting...
|
||||
|
||||
tank_ids.sort()
|
||||
# sorting
|
||||
tankopedia_sorted = collections.OrderedDict()
|
||||
for tank_id in tank_ids:
|
||||
for tank_id in sorted(tankopedia.keys(), key=int):
|
||||
tankopedia_sorted[str(tank_id)] = tankopedia[str(tank_id)]
|
||||
|
||||
userStrs_sorted = collections.OrderedDict()
|
||||
for userStr in sorted(userStrs.keys()):
|
||||
userStrs_sorted[userStr] = userStrs[userStr]
|
||||
|
||||
except Exception as err:
|
||||
error(err)
|
||||
bu.error(err)
|
||||
sys.exit(1)
|
||||
return tankopedia_sorted, userStrs
|
||||
|
||||
return tankopedia_sorted, userStrs_sorted
|
||||
|
||||
async def getTankID(nation: str, tankID : int) -> int:
|
||||
return (tankID << 8) + (NATION_ID[nation] << 4) + 1
|
||||
return (tankID << 8) + (wg.nation_id[nation] << 4) + 1
|
||||
|
||||
async def getTankType(tagstr : str):
|
||||
tags = tagstr.split(' ')
|
||||
@@ -146,34 +144,6 @@ async def getTankType(tagstr : str):
|
||||
return t_type
|
||||
return None
|
||||
|
||||
def verbose(msg = ""):
|
||||
"""Print a message"""
|
||||
if VERBOSE:
|
||||
curframe = inspect.currentframe()
|
||||
calframe = inspect.getouterframes(curframe, 2)
|
||||
caller = calframe[1][3]
|
||||
print(caller + '(): ' + msg)
|
||||
return None
|
||||
|
||||
def debug(msg = ""):
|
||||
"""print a conditional debug message"""
|
||||
if DEBUG:
|
||||
curframe = inspect.currentframe()
|
||||
calframe = inspect.getouterframes(curframe, 2)
|
||||
caller = calframe[1][3]
|
||||
print('DEBUG: ' + caller + '(): ' + msg)
|
||||
return None
|
||||
|
||||
|
||||
def error(msg = ""):
|
||||
"""Print an error message"""
|
||||
curframe = inspect.currentframe()
|
||||
calframe = inspect.getouterframes(curframe, 2)
|
||||
caller = calframe[1][3]
|
||||
print('ERROR: ' + caller + '(): ' + msg)
|
||||
|
||||
return None
|
||||
|
||||
### main()
|
||||
if __name__ == "__main__":
|
||||
|
||||
|
||||
+310
-310
@@ -2942,363 +2942,363 @@
|
||||
}
|
||||
},
|
||||
"userStr": {
|
||||
"T-34": "T-34",
|
||||
"SU-85": "SU-85",
|
||||
"IS": "IS",
|
||||
"BT-7": "BT-7",
|
||||
"BT-2": "BT-2",
|
||||
"T-28": "T-28",
|
||||
"A-20": "A-20",
|
||||
"SU-152": "SU-152",
|
||||
"T-34-85": "T-34-85",
|
||||
"KV-1s": "KV-1S",
|
||||
"T-46": "T-46",
|
||||
"MS-1": "MS-1",
|
||||
"SU-100": "SU-100",
|
||||
"T-44": "T-44",
|
||||
"T-26": "T-26",
|
||||
"AT-1": "AT-1",
|
||||
"IS-3": "IS-3",
|
||||
"KV-3": "KV-3",
|
||||
"IS-4": "IS-4",
|
||||
"SU-76": "SU-76",
|
||||
"T-43": "T-43",
|
||||
"GAZ-74b": "SU-85B",
|
||||
"IS-7": "IS-7",
|
||||
"ISU-152": "ISU-152",
|
||||
"T-54": "T-54",
|
||||
"Object_704": "Object 704",
|
||||
"KV-13": "KV-13",
|
||||
"IS-6": "IS-6",
|
||||
"SU-101": "SU-101",
|
||||
"SU100M1": "SU-100M1",
|
||||
"KV2": "KV-2",
|
||||
"ST_I": "ST-I",
|
||||
"KV4": "KV-4",
|
||||
"T150": "T-150",
|
||||
"IS8": "IS-8",
|
||||
"KV1": "KV-1",
|
||||
"SU122_54": "SU-122-54",
|
||||
"R127_T44_100_P": "T-44-100",
|
||||
"Object268": "Object 268",
|
||||
"T62A": "T-62A",
|
||||
"Object263": "Object 263",
|
||||
"MT25": "MT-25",
|
||||
"Object_140": "Object 140",
|
||||
"R109_T54S": "T-54 ltwt.",
|
||||
"R107_LTB": "LTTB",
|
||||
"KV-220_test": "KV-220 Beta-Test",
|
||||
"Matilda_II_LL": "Matilda IV",
|
||||
"Churchill_LL": "Churchill III",
|
||||
"BT-SV": "BT-SV",
|
||||
"Valentine_LL": "Valentine II",
|
||||
"M3_Stuart_LL": "M3 Light",
|
||||
"A-32": "A-32",
|
||||
"KV-5": "KV-5",
|
||||
"T-127": "T-127",
|
||||
"SU_85I": "SU-85I",
|
||||
"SU76I": "SU-76I",
|
||||
"Tetrarch_LL": "Tetrarch",
|
||||
"SU100Y": "SU-100Y",
|
||||
"SU122_44": "SU-122-44",
|
||||
"LTP": "LTP",
|
||||
"R113_Object_730": "IS-5 (Object 730)",
|
||||
"R71_IS_2B": "IS-2 (1945)",
|
||||
"R116_ISU122C_Berlin": "ISU-122S",
|
||||
"R112_T54_45": "T-54 first prototype",
|
||||
"IS-2Sh": "IS-2Sh",
|
||||
"R115_IS-3_auto": "IS-3 Defender",
|
||||
"R105_BT_7A": "BT-7 artillery",
|
||||
"T-34-85_Rudy": "T-34-85 Rudy",
|
||||
"T-34-85_Victory": "T-34-85 Victory",
|
||||
"IS-6_Fearless": "IS-6 Fearless",
|
||||
"K-91": "K-91",
|
||||
"R43_T-70_57": "T-70/57",
|
||||
"R111_ISU130": "ISU-130",
|
||||
"PzIV": "Pz.Kpfw. IV",
|
||||
"PzVI": "Tiger I",
|
||||
"Pz35t": "Pz.Kpfw. 35 (t)",
|
||||
"StuGIII": "StuG III Ausf. G",
|
||||
"PzV": "Panther I",
|
||||
"JagdPzIV": "Jagdpanzer IV",
|
||||
"Hetzer": "Hetzer",
|
||||
"PzII": "Pz.Kpfw. II",
|
||||
"VK3601H": "VK 36.01 (H)",
|
||||
"VK3001H": "VK 30.01 (H)",
|
||||
"Ltraktor": "Leichttraktor",
|
||||
"Pz38t": "Pz.Kpfw. 38 (t)",
|
||||
"PanzerJager_I": "Panzerjäger I",
|
||||
"JagdPanther": "Jagdpanther",
|
||||
"VK3002DB": "VK 30.02 (D)",
|
||||
"PzIII": "Pz.Kpfw. III",
|
||||
"PzIII_A": "Pz.Kpfw. III Ausf. A",
|
||||
"PzVIB_Tiger_II": "Tiger II",
|
||||
"VK1602": "VK 16.02 Leopard",
|
||||
"PzII_Luchs": "Pz.Kpfw. II Luchs",
|
||||
"PzIII_IV": "Pz.Kpfw. III/IV",
|
||||
"G20_Marder_II": "Marder II",
|
||||
"Maus": "Maus",
|
||||
"VK3001P": "VK 30.01 (P)",
|
||||
"VK4502P": "VK 45.02 (P) Ausf. B",
|
||||
"Ferdinand": "Ferdinand",
|
||||
"JagdTiger": "Jagdtiger",
|
||||
"Pz38_NA": "Pz.Kpfw. 38 (t) n.A.",
|
||||
"Panther_II": "Panther II",
|
||||
"E-100": "E 100",
|
||||
"E-75": "E 75",
|
||||
"VK2801": "VK 28.01",
|
||||
"E-50": "E 50",
|
||||
"VK4502A": "VK 45.02 (P) Ausf. A",
|
||||
"PzVI_Tiger_P": "Tiger (P)",
|
||||
"Sturer_Emil": "Sturer Emil",
|
||||
"JagdPantherII": "Jagdpanther II",
|
||||
"Nashorn": "Nashorn",
|
||||
"JagdPz_E100": "Jagdpanzer E 100",
|
||||
"E50_Ausf_M": "E 50 Ausf. M",
|
||||
"Pz_II_AusfG": "Pz.Kpfw. II Ausf. G",
|
||||
"DW_II": "Durchbruchswagen 2",
|
||||
"Indien_Panzer": "Indien-Panzer",
|
||||
"VK3002DB_V1": "VK 30.01 (D)",
|
||||
"Leopard1": "Leopard 1",
|
||||
"Pro_Ag_A": "Leopard Prototyp A",
|
||||
"VK3002M": "VK 30.02 (M)",
|
||||
"Pz_Sfl_IVc": "Pz.Sfl. IVc",
|
||||
"Waffentrager_IV": "Waffenträger auf Pz. IV",
|
||||
"RhB_Waffentrager": "Rhm.-Borsig Waffenträger",
|
||||
"Pz_IV_AusfA": "Pz.Kpfw. IV Ausf. A",
|
||||
"Pz_IV_AusfD": "Pz.Kpfw. IV Ausf. D",
|
||||
"G103_RU_251": "Spähpanzer Ru 251",
|
||||
"G113_SP_I_C": "Spähpanzer SP I C",
|
||||
"G121_Grille_15_L63": "Grille 15",
|
||||
"PzV_PzIV": "Pz.Kpfw. V/IV",
|
||||
"PzII_J": "Pz.Kpfw. II Ausf. J",
|
||||
"S35_captured": "Pz.Kpfw. S35 739 (f)",
|
||||
"B-1bis_captured": "Pz.Kpfw. B2 740 (f)",
|
||||
"H39_captured": "Pz.Kpfw. 38H 735 (f)",
|
||||
"Lowe": "Löwe",
|
||||
"T-25": "T-25",
|
||||
"T-15": "T-15",
|
||||
"PzIV_Hydro": "Pz.Kpfw. IV hydrostat.",
|
||||
"JagdTiger_SdKfz_185": "8,8 cm Pak 43 Jagdtiger",
|
||||
"DickerMax": "Dicker Max",
|
||||
"PzIV_schmalturm": "Pz.Kpfw. IV Schmalturm",
|
||||
"Panther_M10": "Panther/M10",
|
||||
"VK7201": "VK 72.01 (K)",
|
||||
"G100_Gtraktor_Krupp": "Großtraktor - Krupp",
|
||||
"G106_PzKpfwPanther_AusfF": "Panther mit 8,8 cm L/71",
|
||||
"G120_M41_90": "leKpz M 41 90 mm",
|
||||
"G118_VK4503": "VK 45.03",
|
||||
"S01_Frankentank": "Tankenstein",
|
||||
"JagdTiger_SdKfz_185_Snowstorm": "Snowstorm Jagdtiger 8.8",
|
||||
"E-25": "E 25",
|
||||
"G_KpfPz_70": "KpfPz 70",
|
||||
"Krupp-38D": "Krupp-38(D)",
|
||||
"G114_Rheinmetall_Scorpion": "Rheinmetall Skorpion G",
|
||||
"G115_VK10001P": "VK 100.01 (P)",
|
||||
"T14": "T14",
|
||||
"M3_Stuart": "M3 Stuart",
|
||||
"T1_Cunningham": "T1 Cunningham",
|
||||
"M6": "M6",
|
||||
"M4_Sherman": "M4 Sherman",
|
||||
"M4A3E8_Sherman": "M4A3E8 Sherman",
|
||||
"T20": "T20",
|
||||
"M2_lt": "M2 Light Tank",
|
||||
"T30": "T30",
|
||||
"T34_hvy": "T34",
|
||||
"M3_Grant": "M3 Lee",
|
||||
"T1_hvy": "T1 Heavy Tank",
|
||||
"T29": "T29",
|
||||
"T32": "T32",
|
||||
"M2_med": "M2 Medium Tank",
|
||||
"M5_Stuart": "M5 Stuart",
|
||||
"M7_med": "M7",
|
||||
"T2_med": "T2 Medium Tank",
|
||||
"Pershing": "M26 Pershing",
|
||||
"T18": "T18",
|
||||
"T82": "T82",
|
||||
"M10_Wolverine": "M10 Wolverine",
|
||||
"M36_Slagger": "M36 Jackson",
|
||||
"T40": "T40",
|
||||
"T28": "T28",
|
||||
"T95": "T95",
|
||||
"M46_Patton": "M46 Patton",
|
||||
"T25_AT": "T25 AT",
|
||||
"M103": "M103",
|
||||
"M24_Chaffee": "M24 Chaffee",
|
||||
"Sherman_Jumbo": "M4A3E2 Sherman Jumbo",
|
||||
"M8A1": "M8A1",
|
||||
"T49": "T67",
|
||||
"T110": "T110E5",
|
||||
"T25_2": "T25/2",
|
||||
"T28_Prototype": "T28 Prototype",
|
||||
"M18_Hellcat": "M18 Hellcat",
|
||||
"T23E3": "T23E3",
|
||||
"T110E4": "T110E4",
|
||||
"T26_E4_SuperPershing": "T26E4 SuperPershing",
|
||||
"T110E3": "T110E3",
|
||||
"M48A1": "M48A1 Patton",
|
||||
"T69": "T69",
|
||||
"T57_58": "T57 Heavy Tank",
|
||||
"T21": "T21",
|
||||
"T54E1": "T54E1",
|
||||
"T71": "T71",
|
||||
"M60": "M60",
|
||||
"T37": "T37",
|
||||
"M41_Bulldog": "M41 Walker Bulldog",
|
||||
"A100_T49": "T49",
|
||||
"T2_lt": "T2 Light Tank",
|
||||
"Ram-II": "Ram II",
|
||||
"M4A2E4": "M4A2E4 Sherman",
|
||||
"M6A2E1": "M6A2E1",
|
||||
"M22_Locust": "M22 Locust",
|
||||
"M6A2E1_exp": "M6A2E1 EXP",
|
||||
"T1_E6": "T1E6",
|
||||
"T7_Combat_Car": "T7 Combat Car",
|
||||
"A104_M4A3E8A": "M4A3E8 Fury",
|
||||
"A102_T28_concept": "T28 Concept",
|
||||
"T34_hvy_Freedom": "T34 Independence",
|
||||
"T49_Rocket": "T49 ATM",
|
||||
"T95E2": "T95E2",
|
||||
"A104_M4A3E8A": "M4A3E8 Fury",
|
||||
"A77_T6M": "T6E1",
|
||||
"AMX38": "AMX 38",
|
||||
"AMX40": "AMX 40",
|
||||
"AMX50_Foch": "AMX 50 Foch",
|
||||
"AMX_12t": "AMX 12 t",
|
||||
"AMX_13_75": "AMX 13 75",
|
||||
"AMX_13_90": "AMX 13 90",
|
||||
"AMX_50Fosh_155": "AMX 50 Foch (155)",
|
||||
"AMX_50_100": "AMX 50 100",
|
||||
"AMX_50_120": "AMX 50 120",
|
||||
"AMX_50_68t": "AMX 50 B",
|
||||
"AMX_AC_Mle1946": "AMX AC mle. 46",
|
||||
"AMX_AC_Mle1948": "AMX AC mle. 48",
|
||||
"AMX_M4_1945": "AMX M4 mle. 45",
|
||||
"AMX_dracula": "T6 Dracula",
|
||||
"ARL_44": "ARL 44",
|
||||
"ARL_V39": "ARL V39",
|
||||
"AT-1": "AT-1",
|
||||
"Akawara": "O-47",
|
||||
"B-1bis_captured": "Pz.Kpfw. B2 740 (f)",
|
||||
"B1": "B1",
|
||||
"BDR_G1B": "BDR G1 B",
|
||||
"BT-2": "BT-2",
|
||||
"BT-7": "BT-7",
|
||||
"BT-SV": "BT-SV",
|
||||
"Bat_Chatillon25t": "Bat.-Châtillon 25 t",
|
||||
"CH38_WZ113G-FT": "WZ-113G FT",
|
||||
"Ch01_Type59": "Type 59",
|
||||
"Ch02_Type62": "Type 62",
|
||||
"Ch03_WZ-111": "WZ-111",
|
||||
"Ch04_T34_1": "T-34-1",
|
||||
"Ch06_Renault_NC31": "Renault NC-31",
|
||||
"Ch05_T34_2": "T-34-2",
|
||||
"Ch18_WZ-120": "WZ-120",
|
||||
"Ch12_111_1_2_3": "WZ-111 model 1-4",
|
||||
"Ch06_Renault_NC31": "Renault NC-31",
|
||||
"Ch07_Vickers_MkE_Type_BT26": "Vickers Mk. E Type B",
|
||||
"Ch11_110": "WZ-110",
|
||||
"Ch08_Type97_Chi_Ha": "Type 2597 Chi-Ha",
|
||||
"Ch09_M5": "M5A1 Stuart",
|
||||
"Ch10_IS2": "IS-2",
|
||||
"Ch11_110": "WZ-110",
|
||||
"Ch12_111_1_2_3": "WZ-111 model 1-4",
|
||||
"Ch14_T34_3": "T-34-3",
|
||||
"Ch18_WZ-120": "WZ-120",
|
||||
"Ch19_121": "WZ-121",
|
||||
"Ch08_Type97_Chi_Ha": "Type 2597 Chi-Ha",
|
||||
"Ch21_T34": "Type T-34",
|
||||
"Ch20_Type58": "Type 58",
|
||||
"Ch21_T34": "Type T-34",
|
||||
"Ch22_113": "WZ-113",
|
||||
"Ch23_112": "112 Glacial",
|
||||
"Ch02_Type62": "Type 62",
|
||||
"Ch24_Type64": "Type 64",
|
||||
"Ch25_121_mod_1971B": "121B",
|
||||
"Ch26_59_Patton": "59-Patton",
|
||||
"Ch14_T34_3": "T-34-3",
|
||||
"CH38_WZ113G-FT": "WZ-113G FT",
|
||||
"Ch39_WZ120_1G_FT": "WZ-120-1G FT",
|
||||
"D2": "D2",
|
||||
"RenaultFT": "Renault FT",
|
||||
"B1": "B1",
|
||||
"Chi_Ha": "Type 97 Chi-Ha",
|
||||
"Chi_He": "Type 1 Chi-He",
|
||||
"Chi_Ni": "Chi-Ni",
|
||||
"Chi_Nu": "Type 3 Chi-Nu",
|
||||
"Chi_Nu_Kai": "Type 3 Chi-Nu Kai",
|
||||
"Chi_Ri": "Type 5 Chi-Ri",
|
||||
"Chi_To": "Type 4 Chi-To",
|
||||
"Churchill_LL": "Churchill III",
|
||||
"D1": "D1",
|
||||
"FCM_36Pak40": "FCM 36 Pak 40",
|
||||
"ARL_44": "ARL 44",
|
||||
"AMX40": "AMX 40",
|
||||
"AMX_50_100": "AMX 50 100",
|
||||
"Bat_Chatillon25t": "Bat.-Châtillon 25 t",
|
||||
"AMX_50_120": "AMX 50 120",
|
||||
"AMX_13_90": "AMX 13 90",
|
||||
"AMX_13_75": "AMX 13 75",
|
||||
"AMX38": "AMX 38",
|
||||
"AMX_50_68t": "AMX 50 B",
|
||||
"AMX_12t": "AMX 12 t",
|
||||
"BDR_G1B": "BDR G1 B",
|
||||
"AMX_M4_1945": "AMX M4 mle. 45",
|
||||
"RenaultFT_AC": "Renault FT AC",
|
||||
"RenaultUE57": "Renault UE 57",
|
||||
"Somua_Sau_40": "Somua SAu 40",
|
||||
"S_35CA": "S35 CA",
|
||||
"AMX_AC_Mle1946": "AMX AC mle. 46",
|
||||
"AMX50_Foch": "AMX 50 Foch",
|
||||
"ARL_V39": "ARL V39",
|
||||
"AMX_AC_Mle1948": "AMX AC mle. 48",
|
||||
"AMX_50Fosh_155": "AMX 50 Foch (155)",
|
||||
"D2": "D2",
|
||||
"DW_II": "Durchbruchswagen 2",
|
||||
"DickerMax": "Dicker Max",
|
||||
"E-100": "E 100",
|
||||
"E-25": "E 25",
|
||||
"E-50": "E 50",
|
||||
"E-75": "E 75",
|
||||
"E50_Ausf_M": "E 50 Ausf. M",
|
||||
"ELC_AMX": "AMX ELC bis",
|
||||
"F68_AMX_Chasseur_de_char_46": "AMX Chasseur de chars",
|
||||
"FCM_50t": "FCM 50 t",
|
||||
"F75_Char_de_25t": "Bat.-Châtillon 25 t AP",
|
||||
"F74_AMX_M4_1949": "AMX M4 mle. 49",
|
||||
"RenaultR35": "Renault R35",
|
||||
"F19_Lorraine40t": "Lorraine 40 t",
|
||||
"F68_AMX_Chasseur_de_char_46": "AMX Chasseur de chars",
|
||||
"F69_AMX_13_57GF": "AMX 13 57 GF",
|
||||
"F71_AMX_30_prototype": "AMX 30 1er prototype",
|
||||
"F72_AMX_30": "AMX 30 B",
|
||||
"F73_M4A1_Revalorise": "M4A1 Revalorisé",
|
||||
"F69_AMX_13_57GF": "AMX 13 57 GF",
|
||||
"F74_AMX_M4_1949": "AMX M4 mle. 49",
|
||||
"F75_Char_de_25t": "Bat.-Châtillon 25 t AP",
|
||||
"FCM_36Pak40": "FCM 36 Pak 40",
|
||||
"FCM_50t": "FCM 50 t",
|
||||
"Ferdinand": "Ferdinand",
|
||||
"G100_Gtraktor_Krupp": "Großtraktor - Krupp",
|
||||
"G103_RU_251": "Spähpanzer Ru 251",
|
||||
"G106_PzKpfwPanther_AusfF": "Panther mit 8,8 cm L/71",
|
||||
"G113_SP_I_C": "Spähpanzer SP I C",
|
||||
"G114_Rheinmetall_Scorpion": "Rheinmetall Skorpion G",
|
||||
"G115_VK10001P": "VK 100.01 (P)",
|
||||
"G118_VK4503": "VK 45.03",
|
||||
"G120_M41_90": "leKpz M 41 90 mm",
|
||||
"G121_Grille_15_L63": "Grille 15",
|
||||
"G20_Marder_II": "Marder II",
|
||||
"GAZ-74b": "SU-85B",
|
||||
"GB01_Medium_Mark_I": "Vickers Medium Mk. I",
|
||||
"GB03_Cruiser_Mk_I": "Cruiser Mk. I",
|
||||
"GB04_Valentine": "Valentine",
|
||||
"GB05_Vickers_Medium_Mk_II": "Vickers Medium Mk. II",
|
||||
"GB07_Matilda": "Matilda",
|
||||
"GB21_Cromwell": "Cromwell",
|
||||
"GB20_Crusader": "Crusader",
|
||||
"GB06_Vickers_Medium_Mk_III": "Vickers Medium Mk. III",
|
||||
"GB07_Matilda": "Matilda",
|
||||
"GB08_Churchill_I": "Churchill I",
|
||||
"GB09_Churchill_VII": "Churchill VII",
|
||||
"GB10_Black_Prince": "Black Prince",
|
||||
"GB11_Caernarvon": "Caernarvon",
|
||||
"GB12_Conqueror": "Conqueror",
|
||||
"GB09_Churchill_VII": "Churchill VII",
|
||||
"GB04_Valentine": "Valentine",
|
||||
"GB03_Cruiser_Mk_I": "Cruiser Mk. I",
|
||||
"GB22_Comet": "Comet",
|
||||
"GB24_Centurion_Mk3": "Centurion Mk. 7/1",
|
||||
"GB23_Centurion": "Centurion Mk. I",
|
||||
"GB13_FV215b": "FV215b",
|
||||
"GB19_Sherman_Firefly": "Sherman Firefly",
|
||||
"GB20_Crusader": "Crusader",
|
||||
"GB21_Cromwell": "Cromwell",
|
||||
"GB22_Comet": "Comet",
|
||||
"GB23_Centurion": "Centurion Mk. I",
|
||||
"GB24_Centurion_Mk3": "Centurion Mk. 7/1",
|
||||
"GB32_Tortoise": "Tortoise",
|
||||
"GB35_Sentinel_AC_IV": "AC IV Sentinel",
|
||||
"GB39_Universal_CarrierQF2": "Universal Carrier 2-pdr",
|
||||
"GB40_Gun_Carrier_Churchill": "Churchill Gun Carrier",
|
||||
"GB42_Valentine_AT": "Valentine AT",
|
||||
"GB44_Archer_Custom": "Angry Connor",
|
||||
"GB48_FV215b_183": "FV215b (183)",
|
||||
"GB51_Excelsior": "Excelsior",
|
||||
"GB52_FV201_A45": "FV201 (A45)",
|
||||
"GB57_Alecto": "Alecto",
|
||||
"GB58_Cruiser_Mk_III": "Cruiser Mk. III",
|
||||
"GB59_Cruiser_Mk_IV": "Cruiser Mk. IV",
|
||||
"GB60_Covenanter": "Covenanter",
|
||||
"GB63_TOG_II": "TOG II*",
|
||||
"GB68_Matilda_Black_Prince": "Matilda Black Prince",
|
||||
"GB69_Cruiser_Mk_II": "Cruiser Mk. II",
|
||||
"GB70_FV4202_105": "FV4202",
|
||||
"GB59_Cruiser_Mk_IV": "Cruiser Mk. IV",
|
||||
"GB58_Cruiser_Mk_III": "Cruiser Mk. III",
|
||||
"GB42_Valentine_AT": "Valentine AT",
|
||||
"GB39_Universal_CarrierQF2": "Universal Carrier 2-pdr",
|
||||
"GB71_AT_15A": "AT 15A",
|
||||
"GB72_AT15": "AT 15",
|
||||
"GB73_AT2": "AT 2",
|
||||
"GB57_Alecto": "Alecto",
|
||||
"GB48_FV215b_183": "FV215b (183)",
|
||||
"GB74_AT8": "AT 8",
|
||||
"GB40_Gun_Carrier_Churchill": "Churchill Gun Carrier",
|
||||
"GB75_AT7": "AT 7",
|
||||
"GB87_Chieftain_T95_turret": "Chieftain/T95",
|
||||
"GB32_Tortoise": "Tortoise",
|
||||
"GB68_Matilda_Black_Prince": "Matilda Black Prince",
|
||||
"GB63_TOG_II": "TOG II*",
|
||||
"GB71_AT_15A": "AT 15A",
|
||||
"GB51_Excelsior": "Excelsior",
|
||||
"GB76_Mk_VIC": "Light Mk. VIC",
|
||||
"GB85_Cromwell_Berlin": "Cromwell B",
|
||||
"GB_Mark_I": "Mk I* Heavy Tank",
|
||||
"GB35_Sentinel_AC_IV": "AC IV Sentinel",
|
||||
"GB44_Archer_Custom": "Angry Connor",
|
||||
"Sentinel_AC1": "AC 1 Sentinel",
|
||||
"GB19_Sherman_Firefly": "Sherman Firefly",
|
||||
"GB_Churchill_MkVI": "Churchill Mk. VI",
|
||||
"GB_Sherman_V": "Sherman V",
|
||||
"GB84_Chieftain_Mk6": "Chieftain Mk.6",
|
||||
"GB52_FV201_A45": "FV201 (A45)",
|
||||
"Chi_Ni": "Chi-Ni",
|
||||
"NC27": "Renault Otsu",
|
||||
"GB85_Cromwell_Berlin": "Cromwell B",
|
||||
"GB87_Chieftain_T95_turret": "Chieftain/T95",
|
||||
"GB_Churchill_MkVI": "Churchill Mk. VI",
|
||||
"GB_Mark_I": "Mk I* Heavy Tank",
|
||||
"GB_Sherman_V": "Sherman V",
|
||||
"G_KpfPz_70": "KpfPz 70",
|
||||
"H39_captured": "Pz.Kpfw. 38H 735 (f)",
|
||||
"Ha_Go": "Type 95 Ha-Go",
|
||||
"Chi_Ri": "Type 5 Chi-Ri",
|
||||
"Chi_Nu": "Type 3 Chi-Nu",
|
||||
"Chi_He": "Type 1 Chi-He",
|
||||
"Chi_To": "Type 4 Chi-To",
|
||||
"Chi_Ha": "Type 97 Chi-Ha",
|
||||
"Ke_Ni": "Type 98 Ke-Ni",
|
||||
"STA_1": "STA-1",
|
||||
"Ke_Ho": "Type 5 Ke-Ho",
|
||||
"Type_61": "Type 61",
|
||||
"ST_B1": "STB-1",
|
||||
"Ke_Ni_B": "Type 98 Ke-Ni Otsu",
|
||||
"PzVI_GuP": "Kuro Mori Mine",
|
||||
"Pz_IV_AusfH": "Panzer IV Anko Special",
|
||||
"Chi_Nu_Kai": "Type 3 Chi-Nu Kai",
|
||||
"Hetzer": "Hetzer",
|
||||
"Hetzer_GuP": "Hetzer Kame SP",
|
||||
"Strv_74A2": "Stridsvagn 74A2",
|
||||
"Sega_Edelweiss": "Edelweiss",
|
||||
"Sega_Nameless": "Nameless",
|
||||
"Van_Helsing": "Helsing H0",
|
||||
"Akawara": "O-47",
|
||||
"WZ-135G_FT": "WZ 135G FT Blaze",
|
||||
"AMX_dracula": "T6 Dracula",
|
||||
"Sega_Lupus": "Lupus",
|
||||
"IS": "IS",
|
||||
"IS-2Sh": "IS-2Sh",
|
||||
"IS-3": "IS-3",
|
||||
"IS-4": "IS-4",
|
||||
"IS-6": "IS-6",
|
||||
"IS-6_Fearless": "IS-6 Fearless",
|
||||
"IS-7": "IS-7",
|
||||
"IS8": "IS-8",
|
||||
"ISU-152": "ISU-152",
|
||||
"Indien_Panzer": "Indien-Panzer",
|
||||
"JagdPanther": "Jagdpanther",
|
||||
"JagdPantherII": "Jagdpanther II",
|
||||
"JagdPzIV": "Jagdpanzer IV",
|
||||
"JagdPz_E100": "Jagdpanzer E 100",
|
||||
"JagdTiger": "Jagdtiger",
|
||||
"JagdTiger_SdKfz_185": "8,8 cm Pak 43 Jagdtiger",
|
||||
"JagdTiger_SdKfz_185_Snowstorm": "Snowstorm Jagdtiger 8.8",
|
||||
"K-91": "K-91",
|
||||
"KV-13": "KV-13",
|
||||
"KV-1s": "KV-1S",
|
||||
"KV-220_test": "KV-220 Beta-Test",
|
||||
"KV-3": "KV-3",
|
||||
"KV-5": "KV-5",
|
||||
"KV1": "KV-1",
|
||||
"KV2": "KV-2",
|
||||
"KV4": "KV-4",
|
||||
"Ke_Ho": "Type 5 Ke-Ho",
|
||||
"Ke_Ni": "Type 98 Ke-Ni",
|
||||
"Ke_Ni_B": "Type 98 Ke-Ni Otsu",
|
||||
"Krupp-38D": "Krupp-38(D)",
|
||||
"LTP": "LTP",
|
||||
"Leopard1": "Leopard 1",
|
||||
"Lowe": "Löwe",
|
||||
"Ltraktor": "Leichttraktor",
|
||||
"M103": "M103",
|
||||
"M10_Wolverine": "M10 Wolverine",
|
||||
"M18_Hellcat": "M18 Hellcat",
|
||||
"M22_Locust": "M22 Locust",
|
||||
"M24_Chaffee": "M24 Chaffee",
|
||||
"M2_lt": "M2 Light Tank",
|
||||
"M2_med": "M2 Medium Tank",
|
||||
"M36_Slagger": "M36 Jackson",
|
||||
"M3_Grant": "M3 Lee",
|
||||
"M3_Stuart": "M3 Stuart",
|
||||
"M3_Stuart_LL": "M3 Light",
|
||||
"M41_Bulldog": "M41 Walker Bulldog",
|
||||
"M46_Patton": "M46 Patton",
|
||||
"M48A1": "M48A1 Patton",
|
||||
"M4A2E4": "M4A2E4 Sherman",
|
||||
"M4A3E8_Sherman": "M4A3E8 Sherman",
|
||||
"M4_Sherman": "M4 Sherman",
|
||||
"M5_Stuart": "M5 Stuart",
|
||||
"M6": "M6",
|
||||
"M60": "M60",
|
||||
"M6A2E1": "M6A2E1",
|
||||
"M6A2E1_exp": "M6A2E1 EXP",
|
||||
"M7_med": "M7",
|
||||
"M8A1": "M8A1",
|
||||
"MS-1": "MS-1",
|
||||
"MT25": "MT-25",
|
||||
"Matilda_II_LL": "Matilda IV",
|
||||
"Maus": "Maus",
|
||||
"NC27": "Renault Otsu",
|
||||
"Nashorn": "Nashorn",
|
||||
"Object263": "Object 263",
|
||||
"Object268": "Object 268",
|
||||
"Object_140": "Object 140",
|
||||
"Object_704": "Object 704",
|
||||
"Oth08_WH_Vindicator": "Vindicator Ultramarines",
|
||||
"Oth09_WH_Predator": "Predator Ultramarines",
|
||||
"Oth11_T-55A": "T 55A",
|
||||
"Oth10_WarDuck": "WarDuck",
|
||||
"Oth12_Sega_Hafen": "Hafen"
|
||||
"Oth11_T-55A": "T 55A",
|
||||
"Oth12_Sega_Hafen": "Hafen",
|
||||
"Panther_II": "Panther II",
|
||||
"Panther_M10": "Panther/M10",
|
||||
"PanzerJager_I": "Panzerjäger I",
|
||||
"Pershing": "M26 Pershing",
|
||||
"Pro_Ag_A": "Leopard Prototyp A",
|
||||
"Pz35t": "Pz.Kpfw. 35 (t)",
|
||||
"Pz38_NA": "Pz.Kpfw. 38 (t) n.A.",
|
||||
"Pz38t": "Pz.Kpfw. 38 (t)",
|
||||
"PzII": "Pz.Kpfw. II",
|
||||
"PzIII": "Pz.Kpfw. III",
|
||||
"PzIII_A": "Pz.Kpfw. III Ausf. A",
|
||||
"PzIII_IV": "Pz.Kpfw. III/IV",
|
||||
"PzII_J": "Pz.Kpfw. II Ausf. J",
|
||||
"PzII_Luchs": "Pz.Kpfw. II Luchs",
|
||||
"PzIV": "Pz.Kpfw. IV",
|
||||
"PzIV_Hydro": "Pz.Kpfw. IV hydrostat.",
|
||||
"PzIV_schmalturm": "Pz.Kpfw. IV Schmalturm",
|
||||
"PzV": "Panther I",
|
||||
"PzVI": "Tiger I",
|
||||
"PzVIB_Tiger_II": "Tiger II",
|
||||
"PzVI_GuP": "Kuro Mori Mine",
|
||||
"PzVI_Tiger_P": "Tiger (P)",
|
||||
"PzV_PzIV": "Pz.Kpfw. V/IV",
|
||||
"Pz_II_AusfG": "Pz.Kpfw. II Ausf. G",
|
||||
"Pz_IV_AusfA": "Pz.Kpfw. IV Ausf. A",
|
||||
"Pz_IV_AusfD": "Pz.Kpfw. IV Ausf. D",
|
||||
"Pz_IV_AusfH": "Panzer IV Anko Special",
|
||||
"Pz_Sfl_IVc": "Pz.Sfl. IVc",
|
||||
"R105_BT_7A": "BT-7 artillery",
|
||||
"R107_LTB": "LTTB",
|
||||
"R109_T54S": "T-54 ltwt.",
|
||||
"R111_ISU130": "ISU-130",
|
||||
"R112_T54_45": "T-54 first prototype",
|
||||
"R113_Object_730": "IS-5 (Object 730)",
|
||||
"R115_IS-3_auto": "IS-3 Defender",
|
||||
"R116_ISU122C_Berlin": "ISU-122S",
|
||||
"R127_T44_100_P": "T-44-100",
|
||||
"R43_T-70_57": "T-70/57",
|
||||
"R71_IS_2B": "IS-2 (1945)",
|
||||
"Ram-II": "Ram II",
|
||||
"RenaultFT": "Renault FT",
|
||||
"RenaultFT_AC": "Renault FT AC",
|
||||
"RenaultR35": "Renault R35",
|
||||
"RenaultUE57": "Renault UE 57",
|
||||
"RhB_Waffentrager": "Rhm.-Borsig Waffenträger",
|
||||
"S01_Frankentank": "Tankenstein",
|
||||
"S35_captured": "Pz.Kpfw. S35 739 (f)",
|
||||
"STA_1": "STA-1",
|
||||
"ST_B1": "STB-1",
|
||||
"ST_I": "ST-I",
|
||||
"SU-100": "SU-100",
|
||||
"SU-101": "SU-101",
|
||||
"SU-152": "SU-152",
|
||||
"SU-76": "SU-76",
|
||||
"SU-85": "SU-85",
|
||||
"SU100M1": "SU-100M1",
|
||||
"SU100Y": "SU-100Y",
|
||||
"SU122_44": "SU-122-44",
|
||||
"SU122_54": "SU-122-54",
|
||||
"SU76I": "SU-76I",
|
||||
"SU_85I": "SU-85I",
|
||||
"S_35CA": "S35 CA",
|
||||
"Sega_Edelweiss": "Edelweiss",
|
||||
"Sega_Lupus": "Lupus",
|
||||
"Sega_Nameless": "Nameless",
|
||||
"Sentinel_AC1": "AC 1 Sentinel",
|
||||
"Sherman_Jumbo": "M4A3E2 Sherman Jumbo",
|
||||
"Somua_Sau_40": "Somua SAu 40",
|
||||
"Strv_74A2": "Stridsvagn 74A2",
|
||||
"StuGIII": "StuG III Ausf. G",
|
||||
"Sturer_Emil": "Sturer Emil",
|
||||
"T-127": "T-127",
|
||||
"T-15": "T-15",
|
||||
"T-25": "T-25",
|
||||
"T-26": "T-26",
|
||||
"T-28": "T-28",
|
||||
"T-34": "T-34",
|
||||
"T-34-85": "T-34-85",
|
||||
"T-34-85_Rudy": "T-34-85 Rudy",
|
||||
"T-34-85_Victory": "T-34-85 Victory",
|
||||
"T-43": "T-43",
|
||||
"T-44": "T-44",
|
||||
"T-46": "T-46",
|
||||
"T-54": "T-54",
|
||||
"T110": "T110E5",
|
||||
"T110E3": "T110E3",
|
||||
"T110E4": "T110E4",
|
||||
"T14": "T14",
|
||||
"T150": "T-150",
|
||||
"T18": "T18",
|
||||
"T1_Cunningham": "T1 Cunningham",
|
||||
"T1_E6": "T1E6",
|
||||
"T1_hvy": "T1 Heavy Tank",
|
||||
"T20": "T20",
|
||||
"T21": "T21",
|
||||
"T23E3": "T23E3",
|
||||
"T25_2": "T25/2",
|
||||
"T25_AT": "T25 AT",
|
||||
"T26_E4_SuperPershing": "T26E4 SuperPershing",
|
||||
"T28": "T28",
|
||||
"T28_Prototype": "T28 Prototype",
|
||||
"T29": "T29",
|
||||
"T2_lt": "T2 Light Tank",
|
||||
"T2_med": "T2 Medium Tank",
|
||||
"T30": "T30",
|
||||
"T32": "T32",
|
||||
"T34_hvy": "T34",
|
||||
"T34_hvy_Freedom": "T34 Independence",
|
||||
"T37": "T37",
|
||||
"T40": "T40",
|
||||
"T49": "T67",
|
||||
"T49_Rocket": "T49 ATM",
|
||||
"T54E1": "T54E1",
|
||||
"T57_58": "T57 Heavy Tank",
|
||||
"T62A": "T-62A",
|
||||
"T69": "T69",
|
||||
"T71": "T71",
|
||||
"T7_Combat_Car": "T7 Combat Car",
|
||||
"T82": "T82",
|
||||
"T95": "T95",
|
||||
"T95E2": "T95E2",
|
||||
"Tetrarch_LL": "Tetrarch",
|
||||
"Type_61": "Type 61",
|
||||
"VK1602": "VK 16.02 Leopard",
|
||||
"VK2801": "VK 28.01",
|
||||
"VK3001H": "VK 30.01 (H)",
|
||||
"VK3001P": "VK 30.01 (P)",
|
||||
"VK3002DB": "VK 30.02 (D)",
|
||||
"VK3002DB_V1": "VK 30.01 (D)",
|
||||
"VK3002M": "VK 30.02 (M)",
|
||||
"VK3601H": "VK 36.01 (H)",
|
||||
"VK4502A": "VK 45.02 (P) Ausf. A",
|
||||
"VK4502P": "VK 45.02 (P) Ausf. B",
|
||||
"VK7201": "VK 72.01 (K)",
|
||||
"Valentine_LL": "Valentine II",
|
||||
"Van_Helsing": "Helsing H0",
|
||||
"WZ-135G_FT": "WZ 135G FT Blaze",
|
||||
"Waffentrager_IV": "Waffenträger auf Pz. IV"
|
||||
}
|
||||
}
|
||||
+35
-75
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/python3.7
|
||||
|
||||
import json, argparse, inspect, sys, os, base64, aiohttp, urllib, asyncio, aiofiles, aioconsole, logging, re
|
||||
import blitzutils as bu
|
||||
from blitzutils import WG
|
||||
|
||||
logging.getLogger("asyncio").setLevel(logging.DEBUG)
|
||||
@@ -21,7 +22,7 @@ wg = None
|
||||
|
||||
|
||||
async def main(argv):
|
||||
global VERBOSE, DEBUG, wg
|
||||
global wg
|
||||
|
||||
parser = argparse.ArgumentParser(description='Post replays(s) to WoTinspector.com and retrieve battle data')
|
||||
parser.add_argument('--output', default='single', choices=['file', 'files', 'db'] , help='Select output mode: single/multiple files or database')
|
||||
@@ -30,21 +31,22 @@ async def main(argv):
|
||||
parser.add_argument('-t','--title', type=str, default=None, help='Title for replays. Use NN for continous numbering. Default is filename-based numbering')
|
||||
parser.add_argument('-p', '--private', dest="private", action='store_true', default=False, help='Set replays private on WoTinspector.com')
|
||||
parser.add_argument('--tasks', dest='N_tasks', type=int, default=10, help='Number of worker threads')
|
||||
parser.add_argument('--tankopedia', type=str, default=None, help='Open Tankopedia')
|
||||
parser.add_argument('--tankopedia', type=str, default=None, help='JSON file to read Tankopedia from')
|
||||
parser.add_argument('--mapfile', type=str, default=None, help='JSON file to read Blitz map names from')
|
||||
parser.add_argument('-d', '--debug', action='store_true', default=False, help='Debug mode')
|
||||
parser.add_argument('-v', '--verbose', action='store_true', default=False, help='Verbose mode')
|
||||
parser.add_argument('files', metavar='FILE1 [FILE2 ...]', type=str, nargs='+', help='Files to read. Use \'-\' for STDIN"')
|
||||
args = parser.parse_args()
|
||||
|
||||
VERBOSE = args.verbose
|
||||
DEBUG = args.debug
|
||||
if DEBUG: VERBOSE = True
|
||||
|
||||
wg = WG(WG_appID, args.tankopedia)
|
||||
print(args.files)
|
||||
bu.setVerbose(args.verbose)
|
||||
bu.setDebug(args.debug)
|
||||
|
||||
wg = WG(WG_appID, args.tankopedia, args.mapfile)
|
||||
|
||||
if args.account != None:
|
||||
args.accountID = await wg.getAccountID(args.account)
|
||||
debug('WG account_id: ' + str(args.accountID))
|
||||
bu.debug('WG account_id: ' + str(args.accountID))
|
||||
|
||||
if args.accountID == None:
|
||||
args.accountID = 0
|
||||
@@ -58,18 +60,18 @@ async def main(argv):
|
||||
# Start tasks to process the Queue
|
||||
for i in range(args.N_tasks):
|
||||
tasks.append(asyncio.create_task(replayWorker(queue, i, args.accountID, args.private)))
|
||||
debug('Task ' + str(i) + ' started')
|
||||
bu.debug('Task ' + str(i) + ' started')
|
||||
|
||||
debug('Waiting for the replay scanner to finish')
|
||||
bu.debug('Waiting for the replay scanner to finish')
|
||||
await asyncio.wait([tasks[0]])
|
||||
debug('Scanner finished. Waiting for workers to finish queue')
|
||||
bu.debug('Scanner finished. Waiting for workers to finish queue')
|
||||
await queue.join()
|
||||
debug('Cancelling workers')
|
||||
bu.debug('Cancelling workers')
|
||||
for task in tasks:
|
||||
task.cancel()
|
||||
debug('Waiting for workers to cancel')
|
||||
bu.debug('Waiting for workers to cancel')
|
||||
await asyncio.gather(*tasks, return_exceptions=True)
|
||||
verbose(str(REPLAY_N) + ' replays: ' + str(REPLAY_N - SKIPPED_N) + ' uploaded, ' + str(SKIPPED_N) + ' skipped')
|
||||
bu.verbose(str(REPLAY_N) + ' replays: ' + str(REPLAY_N - SKIPPED_N) + ' uploaded, ' + str(SKIPPED_N) + ' skipped')
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print('Ctrl-c pressed ...')
|
||||
@@ -85,31 +87,27 @@ async def mkReplayQ(queue : asyncio.Queue, files : list, title : str):
|
||||
"""Create queue of replays to post"""
|
||||
p_replayfile = re.compile('.*\\.wotbreplay$')
|
||||
if files[0] == '-':
|
||||
debug('reading replay file list from STDIN')
|
||||
bu.debug('reading replay file list from STDIN')
|
||||
stdin, _ = await aioconsole.get_standard_streams()
|
||||
#stdin = sys.stdin
|
||||
while True:
|
||||
line = await stdin.readline()
|
||||
line = (await stdin.readline()).decode('utf-8').rstrip()
|
||||
if not line:
|
||||
break
|
||||
else:
|
||||
if (p_replayfile.match(line) != None):
|
||||
await queue.put(await mkQueueItem(line, title))
|
||||
else:
|
||||
# debug('Reading files from the command line: ')
|
||||
# debug(', '.join(files))
|
||||
for fn in files:
|
||||
# debug(fn)
|
||||
if os.path.isfile(fn) and (p_replayfile.match(fn) != None):
|
||||
await queue.put(await mkQueueItem(fn, title))
|
||||
elif os.path.isdir(fn):
|
||||
with os.scandir(fn) as dirEntry:
|
||||
for entry in dirEntry:
|
||||
if entry.is_file() and (p_replayfile.match(entry.name) != None):
|
||||
debug(entry.name)
|
||||
bu.debug(entry.name)
|
||||
await queue.put(await mkQueueItem(entry.path, title))
|
||||
debug('File added to queue: ' + fn)
|
||||
debug('Finished')
|
||||
bu.debug('File added to queue: ' + fn)
|
||||
bu.debug('Finished')
|
||||
return None
|
||||
|
||||
|
||||
@@ -119,7 +117,6 @@ async def mkQueueItem(filename : str, title : str) -> list:
|
||||
REPLAY_N +=1
|
||||
return [filename, REPLAY_N, getTitle(filename, title, REPLAY_N)]
|
||||
|
||||
|
||||
async def replayWorker(queue: asyncio.Queue, workerID: int, account_id: int, priv = False):
|
||||
"""Async Worker to process the replay queue"""
|
||||
global SKIPPED_N
|
||||
@@ -138,12 +135,12 @@ async def replayWorker(queue: asyncio.Queue, workerID: int, account_id: int, pri
|
||||
async with aiofiles.open(replay_json_fn) as fp:
|
||||
replay_json = json.loads(await fp.read())
|
||||
if replay_json['status'] == 'ok':
|
||||
verbose('Replay[' + str(N) + ']: ' + title + ' has already been posted. Skipping.' )
|
||||
bu.verbose('Replay[' + str(N) + ']: ' + title + ' has already been posted. Skipping.' )
|
||||
queue.task_done()
|
||||
SKIPPED_N += 1
|
||||
continue
|
||||
except Exception as err:
|
||||
error(err)
|
||||
bu.error(err)
|
||||
sys.exit(1)
|
||||
|
||||
# debug('Opening file [' + str(N) +']: ' + filename)
|
||||
@@ -158,49 +155,43 @@ async def replayWorker(queue: asyncio.Queue, workerID: int, account_id: int, pri
|
||||
}
|
||||
url = WIurl + urllib.parse.urlencode(params, quote_via=urllib.parse.quote)
|
||||
headers ={'Content-type': 'application/x-www-form-urlencoded'}
|
||||
# debug('Reading the payload')
|
||||
payload = { 'file' : (filename, base64.b64encode(await fp.read())) }
|
||||
# debug('Payload read')
|
||||
# debug('URL: ' + url)
|
||||
for retry in range(MAX_RETRIES):
|
||||
# verbose('Worker ' + str(workerID) + ': Posting replay[' + str(N) +']: ' + title + ' Try #: ' + str(retry+ 1) + '/' + str(MAX_RETRIES) )
|
||||
verbose('Posting replay[' + str(N) +']: ' + title + ' Try #: ' + str(retry+ 1) + '/' + str(MAX_RETRIES) )
|
||||
bu.verbose('Posting replay[' + str(N) +']: ' + title + ' Try #: ' + str(retry+ 1) + '/' + str(MAX_RETRIES) )
|
||||
try:
|
||||
async with session.post(url, headers=headers, data=payload) as resp:
|
||||
debug('Replay #' + str(N) + ' HTTP response: '+ str(resp.status))
|
||||
bu.debug('Replay #' + str(N) + ' HTTP response: '+ str(resp.status))
|
||||
if resp.status == 200:
|
||||
debug('HTTP POST 200 = Success. Reading response data')
|
||||
bu.debug('HTTP POST 200 = Success. Reading response data')
|
||||
json_resp = await resp.json()
|
||||
if json_resp['status'] == 'error':
|
||||
error(json_resp['error']['message'] + ' : Replay[' + str(N) + ']' + title)
|
||||
bu.error(json_resp['error']['message'] + ' : Replay[' + str(N) + ']' + title)
|
||||
else:
|
||||
debug('Response data read')
|
||||
verbose('Replay[' + str(N) + ']: ' + title + ' posted')
|
||||
bu.debug('Response data read')
|
||||
bu.verbose('Replay[' + str(N) + ']: ' + title + ' posted')
|
||||
await storeReplayJSON(replay_json_fn,json_resp)
|
||||
break
|
||||
else:
|
||||
debug('Replay[' + str(N)+ ']: Got HTTP/' + str(resp.status) + ' Retrying... ' + str(retry))
|
||||
bu.debug('Replay[' + str(N)+ ']: Got HTTP/' + str(resp.status) + ' Retrying... ' + str(retry))
|
||||
await asyncio.sleep(SLEEP)
|
||||
except Exception as err:
|
||||
error(str(err))
|
||||
bu.error(str(err))
|
||||
await asyncio.sleep(SLEEP)
|
||||
debug('Marking task ' + str(N) + ' done')
|
||||
bu.debug('Marking task ' + str(N) + ' done')
|
||||
queue.task_done()
|
||||
|
||||
return None
|
||||
|
||||
|
||||
async def storeReplayJSON(filename: str, json_data : dict):
|
||||
try:
|
||||
async with aiofiles.open(filename, 'w', encoding='utf8') as outfile:
|
||||
await outfile.write(json.dumps(json_data, ensure_ascii=False, indent=4))
|
||||
return True
|
||||
except Exception as err:
|
||||
error(str(err))
|
||||
bu.error(str(err))
|
||||
return False
|
||||
return False
|
||||
|
||||
|
||||
def getTitle(replayfile: str, title: str, i : int) -> str:
|
||||
global wg
|
||||
|
||||
@@ -212,52 +203,21 @@ def getTitle(replayfile: str, title: str, i : int) -> str:
|
||||
p = re.compile('\\d{8}_\\d{4}_(.+)_(' + '|'.join(map_usrStrs) + ')(?:-\\d)?\\.wotbreplay$')
|
||||
m = p.match(filename)
|
||||
if (m != None):
|
||||
# debug('Match')
|
||||
if wg.tanks != None:
|
||||
tank = wg.tanks['userStr'][m.group(1)]
|
||||
# debug('Tank from Tankopedia:' + tank)
|
||||
else:
|
||||
tank = m.group(1)
|
||||
# debug(tank)
|
||||
blitz_map = wg.maps[m.group(2)]
|
||||
title = tank + ' @ ' + blitz_map
|
||||
else:
|
||||
# debug('No match')
|
||||
title = re.sub('\\.wotbreplay$', '', filename)
|
||||
except Exception as err:
|
||||
error(err)
|
||||
bu.error(err)
|
||||
else:
|
||||
title.replace('NN', str(i))
|
||||
# debug(title)
|
||||
return title
|
||||
|
||||
|
||||
def verbose(msg = ""):
|
||||
"""Print a message"""
|
||||
if VERBOSE:
|
||||
print(msg)
|
||||
return None
|
||||
|
||||
|
||||
def debug(msg = ""):
|
||||
"""print a conditional debug message"""
|
||||
if DEBUG:
|
||||
curframe = inspect.currentframe()
|
||||
calframe = inspect.getouterframes(curframe, 2)
|
||||
caller = calframe[1][3]
|
||||
print('DEBUG: ' + caller + '(): ' + msg)
|
||||
return None
|
||||
|
||||
|
||||
def error(msg = ""):
|
||||
"""Print an error message"""
|
||||
curframe = inspect.currentframe()
|
||||
calframe = inspect.getouterframes(curframe, 2)
|
||||
caller = calframe[1][3]
|
||||
print('ERROR: ' + caller + '(): ' + msg)
|
||||
|
||||
return None
|
||||
|
||||
### main()
|
||||
### main() -------------------------------------------
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main(sys.argv[1:]), debug=False)
|
||||
Reference in new issue
Block a user