2 Commits
Author SHA1 Message Date
Jylpah 4c517a11c5 Update blitzutils.py 2020-12-06 16:33:20 +02:00
Jylpah 1a7fcffa17 WIReplay(): started 2020-12-05 23:19:05 +02:00
13 changed files with 7667 additions and 5135 deletions

No files matched your search

-16
View File
@@ -1,16 +0,0 @@
__pycache__/
BlitzApp
tmp/
ssl/
*.ini
*.swp
*.code-workspace
*.sqlite3
.vscode/
*.sqlite3-journal
.gitattributes
export*
*.csv
!/stats/*.csv
!*.py
/.venv
+23 -29
View File
@@ -1,9 +1,5 @@
## Unmaintained
Please use [blitz-replays](https://github.com/Jylpah/blitz-replays) instead. It is faster and more feature-rich.
# blitz-tools # blitz-tools
Python scripts to analyze WoT Blitz replays and stats. All the scripts require [Python 3.7](https://www.python.org/downloads/) or later. Python scripts to analyze WoT Blitz replays and stats. All the scripts require [Python 3.7](https://www.python.org/downloads/) or higher. I am using 3.8 myself so you may have to change the Python interpreter version in the scripts' first line.
### Replays ### Replays
* [upload_wotb_replays.py](upload_wotb_replays.py): An asynchronous replay uploader. * [upload_wotb_replays.py](upload_wotb_replays.py): An asynchronous replay uploader.
@@ -17,48 +13,46 @@ Python scripts to analyze WoT Blitz replays and stats. All the scripts require [
* [blitzutils.py](blitzutils.py): A utils class for various Blitz related to functions. *Other scripts use this*, so you need to place it to the same folder with the other scripts * [blitzutils.py](blitzutils.py): A utils class for various Blitz related to functions. *Other scripts use this*, so you need to place it to the same folder with the other scripts
### Data ### Data
* [tanks.json](tanks.json): Tankopedia in WG JSON format extracted from the Blitz app files with [extract_tankopedia.py](extractTankopedia.py). Contains only limited information required by the scripts. * [tanks.json](tanks.json): Tankopedia in WG JSON format extracted from the Blitz app files with [extract_tankopedia.py]](extractTankopedia.py]). Contains only limited information required by the scripts.
* [maps.json](maps.json): Blitz map names extracted from the Blitz app files with [extract_tankopedia.py](extract_tankopedia.py). * [maps.json](maps.json): Blitz map names extracted from the Blitz app files with [extract_tankopedia.py]](extract_tankopedia.py]).
### Quick instructions ### Quick instructions
1. Install [Python 3.8](https://www.python.org/downloads/) or later to your computer/laptop 1. Install [Python 3.8](https://www.python.org/downloads/) on to your computer/laptop
2. Install the required Python modules (see [requirements.txt](requirements.txt): motor, aiohttp, aioconsole, aiofiles, aiosqlite, beautifulsoup4, lxml, xmltodict, progress 2. Install the required Python modules: motor, aiohttp, aioconsole, aiofiles, aiosqlite, beautifulsoup4, lxml, xmltodict, progress
``` ```
python -m pip install -r requirements.txt # Remember to run the command with a Python interpreter >= 3.7
python -m pip install motor aiohttp aioconsole aiofiles aiosqlite beautifulsoup4 lxml xmltodict progress
``` ```
3. Clone the repository. [GitHub Desktop](https://desktop.github.com/) is an excellent GUI for `git`. This makes it easy to receive the updates via `git pull`. 3. Download all the files including the [maps.json](maps.json) and [tanks.json](tanks.json) files. **The recommened way** is to install the scipts via `git clone`: [GitHub Desktop](https://desktop.github.com/) is an excellent GUI for git. This makes it easy to receive the updates via `git pull`.
4. Upload your replays.
``` ```
git clone https://github.com/Jylpah/blitz-tools.git # Windows, run directly from Command Prompt or Powershell
``` # Check the options
4. Upload your replays with `upload_wotb_replays.py`
```
## Check the options
# Windows Command Prompt or Powershell
python.exe .\upload_wotb_replays.py --help python.exe .\upload_wotb_replays.py --help
# Linux or Windows Subsystem for Linux (WSL) # Syntax
./upload_wotb_replays.py --help python.exe .\upload_wotb_replays.py REPLAY_FILE.wotbreplay
# Upload replays (Windows)
python.exe .\upload_wotb_replays.py REPLAY_FILE.wotbreplay DIR_WITH_REPLAYS
# example # example
python.exe .\upload_wotb_replays.py 20200223_0122__jylpah_T-54_grossberg.wotbreplay python.exe .\upload_wotb_replays.py 20200223_0122__jylpah_T-54_grossberg.wotbreplay
# Linux
./upload_wotb_replays.py --help
``` ```
5. Analyze replays with `analyze_wotb_replays.py` 5. Analyze replays.
``` ```
## Check options # Windows, run directly from Command Prompt or Powershell
# Windows Command Prompt or Powershell
python.exe .\analyze_wotb_replays.py --help python.exe .\analyze_wotb_replays.py --help
# Syntax (Windows) # Syntax
python.exe .\analyze_wotb_replays.py REPLAY_FILE.wotbreplay.json [DIR_WITH_REPLAYS ...] python.exe .\analyze_wotb_replays.py REPLAY_FILE.wotbreplay.json
# Example (Windows) # Example
python.exe .\analyze_wotb_replays.py 20200223_0122__jylpah_T-54_grossberg.wotbreplay.json python.exe .\analyze_wotb_replays.py 20200223_0122__jylpah_T-54_grossberg.wotbreplay.json
# Linux or Windows Subsystem for Linux (WSL) # Linux
./analyze_wotb_replays.py --help ./analyze_wotb_replays.py --help
``` ```
+762 -1860
View File
File diff suppressed because it is too large. Load diff
Executable
+2199
View File
File diff suppressed because it is too large. Load diff
-2715
View File
File diff suppressed because it is too large. Load diff
+204
View File
@@ -0,0 +1,204 @@
#!/usr/bin/env python3.8
# 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, configparser
import blitzutils as bu
from blitzutils import WG
logging.getLogger("asyncio").setLevel(logging.DEBUG)
FILE_CONFIG = 'blitzstats.ini'
BLITZAPP_STRINGS='/assets/Data/Strings/en.yaml'
BLITZAPP_VEHICLES_DIR='/assets/Data/XML/item_defs/vehicles/'
BLITZAPP_VEHICLE_FILE='/list.xml'
wg = None
## main() -------------------------------------------------------------
async def main(argv):
global wg
# set the directory for the script
os.chdir(os.path.dirname(sys.argv[0]))
## Read config
BLITZAPP_FOLDER = '.'
try:
if os.path.isfile(FILE_CONFIG):
config = configparser.ConfigParser()
config.read(FILE_CONFIG)
configOptions = config['EXTRACT_TANKOPEDIA']
BLITZAPP_FOLDER = configOptions.get('blitz_app_dir', BLITZAPP_FOLDER)
except:
pass
parser = argparse.ArgumentParser(description='Extract Tankopedia data from Blitz game files')
parser.add_argument('blitz_app_base', type=str, nargs='?', metavar="BLITZAPP_FOLDER", default=BLITZAPP_FOLDER, help='Base dir of the Blitz App files')
parser.add_argument('tanks', type=str, default='tanks.json', nargs='?', metavar="TANKS_FILE", help='File to write Tankopedia')
parser.add_argument('maps', type=str, default='maps.json', nargs='?', metavar='MAPS_FILE', help='File to write map names')
arggroup = parser.add_mutually_exclusive_group()
arggroup.add_argument('-d', '--debug', action='store_true', default=False, help='Debug mode')
arggroup.add_argument('-v', '--verbose', action='store_true', default=False, help='Verbose mode')
arggroup.add_argument('-s', '--silent', action='store_true', default=False, help='Silent mode')
args = parser.parse_args()
bu.set_log_level(args.silent, args.verbose, args.debug)
wg = WG()
tasks = []
for nation in wg.NATION:
tasks.append(asyncio.create_task(extract_tanks(args.blitz_app_base, nation)))
tanklist = []
for tanklist_tmp in await asyncio.gather(*tasks):
tanklist.extend(tanklist_tmp)
tank_strs, map_strs = await read_user_strs(args.blitz_app_base)
json_data = None
userStrs = {}
tanks = {}
if os.path.exists(args.tanks):
try:
async with aiofiles.open(args.tanks) as infile:
json_data = json.loads(await infile.read())
userStrs = json_data['userStr']
tanks = json_data['data']
except Exception as err:
bu.error('Unexpected error when reading file: ' + args.tanks + ' : ' + str(err))
async with aiofiles.open(args.tanks, 'w', encoding="utf8") as outfile:
new_tanks, new_userStrs = await convert_tank_names(tanklist, tank_strs)
# merge old and new tankopedia
tanks.update(new_tanks)
userStrs.update(new_userStrs)
tankopedia = collections.OrderedDict()
tankopedia['status'] = 'ok'
tankopedia['meta'] = { "count": len(tanks) }
tankopedia['data'] = tanks
tankopedia['userStr'] = userStrs
bu.verbose_std('New tankopedia \'' + args.tanks + '\' contains ' + str(len(tanks)) + ' tanks')
await outfile.write(json.dumps(tankopedia, ensure_ascii=False, indent=4, sort_keys=False))
if args.maps != None:
maps = {}
if os.path.exists(args.maps):
try:
async with aiofiles.open(args.maps) as infile:
maps = json.loads(await infile.read())
except Exception as err:
bu.error('Unexpected error when reading file: ' + args.maps + ' : ' + str(err))
# merge old and new map data
maps.update(map_strs)
async with aiofiles.open(args.maps, 'w', encoding="utf8") as outfile:
bu.verbose_std('New maps file \'' + args.maps + '\' contains ' + str(len(maps)) + ' maps')
await outfile.write(json.dumps(maps, ensure_ascii=False, indent=4, sort_keys=True))
return None
async def extract_tanks(blitz_app_base : str, nation: str):
tanks = []
list_xml_file = blitz_app_base + BLITZAPP_VEHICLES_DIR + nation + BLITZAPP_VEHICLE_FILE
if not os.path.isfile(list_xml_file):
print('ERROR: cannot open ' + list_xml_file)
return None
bu.debug('Opening file: ' + list_xml_file + ' (Nation: ' + nation + ')')
async with aiofiles.open(list_xml_file, 'r', encoding="utf8") as f:
try:
tankList = xmltodict.parse(await f.read())
for data in tankList['root'].keys():
tank_xml = tankList['root'][data]
tank = {}
tank['tank_id'] = await get_tank_id(nation, int(tank_xml['id']))
tank['userStr'] = tank_xml['userString']
tank['nation'] = nation
tank['tier'] = int(tank_xml['level'])
#debug(tank_xml['price'])
tank['is_premium'] = issubclass(type(tank_xml['price']), dict)
tank['type'] = await get_tank_type(tank_xml['tags'])
tanks.append(tank)
except Exception as err:
bu.error(err)
sys.exit(2)
return tanks
async def read_user_strs(blitz_app_base : str) -> dict:
"""Read user strings to convert map and tank names"""
tank_strs = {}
map_strs = {}
filename = blitz_app_base + BLITZAPP_STRINGS
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:.+?)": "(.+)"$')
p_map = re.compile('^"#maps:(.+?):.+?: "(.+?)"$')
async for l in f:
m = p_tank.match(l)
if m != None:
tank_strs[m.group(1)] = m.group(2)
m = p_map.match(l)
if m != None and m.group(2) != 'Macragge':
map_strs[m.group(1)] = m.group(2)
except Exception as err:
bu.error(err)
sys.exit(1)
return tank_strs, map_strs
async def convert_tank_names(tanklist : list, tank_strs: dict) -> dict:
"""Convert tank names for Tankopedia"""
tankopedia = {}
userStrs = {}
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
# sorting
tankopedia_sorted = collections.OrderedDict()
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:
bu.error(err)
sys.exit(1)
return tankopedia_sorted, userStrs_sorted
async def get_tank_id(nation: str, tank_id : int) -> int:
return (tank_id << 8) + (wg.NATION_ID[nation] << 4) + 1
async def get_tank_type(tagstr : str):
tags = tagstr.split(' ')
for t_type in wg.TANK_TYPE:
if tags[0] == t_type:
return t_type
return None
### main()
if __name__ == "__main__":
# To avoid 'Event loop is closed' RuntimeError due to compatibility issue with aiohttp
if sys.platform.startswith("win") and sys.version_info >= (3, 8):
try:
from asyncio import WindowsSelectorEventLoopPolicy
except ImportError:
pass
else:
if not isinstance(asyncio.get_event_loop_policy(), WindowsSelectorEventLoopPolicy):
asyncio.set_event_loop_policy(WindowsSelectorEventLoopPolicy())
#asyncio.run(main(sys.argv[1:]), debug=True)
asyncio.run(main(sys.argv[1:]))
+91
View File
@@ -0,0 +1,91 @@
#!/usr/local/bin/python3.7
# Get Tankpedia from WoTinspector.com
import sys
import argparse
import json
import os
import inspect
import aiohttp
import asyncio
import re
import logging
from pathlib import Path
import blitzutils as bu
from blitzutils import WG
from blitzutils import WoTinspector
logging.getLogger("asyncio").setLevel(logging.DEBUG)
VERBOSE = False
DEBUG = False
tank_type = ['lightTank', 'mediumTank', 'heavyTank', 'AT-SPG']
# @asyncio.coroutine
async def get_tankopedia(filename: str):
url = "https://wotinspector.com/static/armorinspector/tank_db_blitz.js"
async with aiohttp.ClientSession() as client:
async with client.get(url) as r:
if r.status == 200:
WI_tank_db = await r.text()
WI_tank_db = WI_tank_db.split("\n")
else:
print('Error: Could not get valid HTTPS response. HTTP: ' + str(r.status) )
sys.exit(1)
tanks = {}
n = 0
p = re.compile('\\s*(\\d+):\\s{"en":"([^"]+)",.*?"tier":(\\d+), "type":(\\d), "premium":(\\d).*')
for line in WI_tank_db[1:-1]:
m = p.match(line)
tank = {}
tank['tank_id'] = int(m.group(1))
tank['name'] = m.group(2)
tank['tier'] = int(m.group(3))
tank['type'] = tank_type[int(m.group(4))]
tank['is_premium'] = (int(m.group(5)) == 1)
tanks[str(m.group(1))] = tank
n += 1
tankopedia = {}
tankopedia['status'] = "ok"
tankopedia['meta'] = {"count" : n}
tankopedia['data'] = tanks
print("Tankopedia has " + str(n) + " tanks in: " + filename)
with open(filename,'w') as outfile:
outfile.write(json.dumps(tankopedia, ensure_ascii=False, indent=4, sort_keys=True))
return None
async def main(argv):
# set the directory for the script
os.chdir(os.path.dirname(sys.argv[0]))
parser = argparse.ArgumentParser(description='Retrieve Tankopedia from WoTinspector.com')
parser.add_argument('--file', dest="outfile", help='Write Tankopedia to file')
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('-s', '--silent', action='store_true', default=False, help='Silent mode')
args = parser.parse_args()
bu.set_log_level(args.silent, args.verbose, args.debug)
wi = WoTinspector()
await wi.get_tankopedia(args.outfile)
await wi.close()
# main()
if __name__ == "__main__":
# To avoid 'Event loop is closed' RuntimeError due to compatibility issue with aiohttp
if sys.platform.startswith("win") and sys.version_info >= (3, 8):
try:
from asyncio import WindowsSelectorEventLoopPolicy
except ImportError:
pass
else:
if not isinstance(asyncio.get_event_loop_policy(), WindowsSelectorEventLoopPolicy):
asyncio.set_event_loop_policy(WindowsSelectorEventLoopPolicy())
asyncio.run(main(sys.argv[1:]), debug=False)
+54 -1
View File
@@ -1 +1,54 @@
{"Random": {"key": "Random", "name": "Random map", "id": -1, "mode": 1}, "amigosville": {"key": "amigosville", "name": "Falls Creek", "id": -1, "mode": 1}, "amigosville_02": {"key": "amigosville_02", "name": "Falls Creek - Bridge", "id": -1, "mode": 3}, "amigosville_03": {"key": "amigosville_03", "name": "Falls Creek - Factory", "id": -1, "mode": 3}, "asia": {"key": "asia", "name": "Lost Temple", "id": -1, "mode": 1}, "canal": {"key": "canal", "name": "Canal", "id": -1, "mode": 1}, "canal_01": {"key": "canal_01", "name": "Canal - Factory", "id": -1, "mode": 3}, "canyon": {"key": "canyon", "name": "Canyon", "id": -1, "mode": 1}, "desert_train": {"key": "desert_train", "name": "Desert Sands", "id": -1, "mode": 1}, "desert_train_02": {"key": "desert_train_02", "name": "Desert Sands - Town", "id": -1, "mode": 3}, "desert_train_03": {"key": "desert_train_03", "name": "Desert Sands - Dunes", "id": -1, "mode": 3}, "erlenberg": {"key": "erlenberg", "name": "Middleburg", "id": -1, "mode": 1}, "erlenberg_01": {"key": "erlenberg_01", "name": "Middleburg - Town", "id": -1, "mode": 3}, "erlenberg_02": {"key": "erlenberg_02", "name": "Middleburg - Hill", "id": -1, "mode": 3}, "faust": {"key": "faust", "name": "Faust", "id": -1, "mode": 1}, "forgecity": {"key": "forgecity", "name": "New Bay", "id": -1, "mode": 1}, "fort": {"key": "fort", "name": "Fort Despair", "id": -1, "mode": 1}, "grossberg": {"key": "grossberg", "name": "Dynasty's Pearl", "id": -1, "mode": 1}, "himmelsdorf": {"key": "himmelsdorf", "name": "Himmelsdorf", "id": -1, "mode": 1}, "holland": {"key": "holland", "name": "Molendijk", "id": -1, "mode": 1}, "holmeisk": {"key": "holmeisk", "name": "Wasteland", "id": -1, "mode": 1}, "iceworld": {"key": "iceworld", "name": "Everfrost", "id": -1, "mode": 2}, "idle": {"key": "idle", "name": "Yukon", "id": -1, "mode": 1}, "italy": {"key": "italy", "name": "Vineyards", "id": -1, "mode": 1}, "karelia": {"key": "karelia", "name": "Rockfield", "id": -1, "mode": 1}, "karieri": {"key": "karieri", "name": "Copperfield", "id": -1, "mode": 1}, "lake": {"key": "lake", "name": "Mirage", "id": -1, "mode": 1}, "lumber": {"key": "lumber", "name": "Horrorstadt", "id": -1, "mode": 1}, "lumber_01": {"key": "lumber_01", "name": "Alpenstadt - Town", "id": -1, "mode": 3}, "malinovka": {"key": "malinovka", "name": "Winter Malinovka", "id": -1, "mode": 1}, "medvedkovo": {"key": "medvedkovo", "name": "Dead Rail", "id": -1, "mode": 1}, "medvedkovo_02": {"key": "medvedkovo_02", "name": "Dead Rail - Valley", "id": -1, "mode": 3}, "medvedkovo_03": {"key": "medvedkovo_03", "name": "Dead Rail - Railroad", "id": -1, "mode": 3}, "milbase": {"key": "milbase", "name": "Yamato Harbor", "id": -1, "mode": 1}, "milbase_02": {"key": "milbase_02", "name": "Yamato Harbor - Battleship", "id": -1, "mode": 3}, "milbase_03": {"key": "milbase_03", "name": "Yamato Harbor - Hills", "id": -1, "mode": 3}, "milbase_04": {"key": "milbase_04", "name": "Yamato Harbor - Center", "id": -1, "mode": 3}, "milbase_05": {"key": "milbase_05", "name": "Yamato Harbor - Dock", "id": -1, "mode": 3}, "moon": {"key": "moon", "name": "Sea of Tranquility", "id": -1, "mode": 2}, "mountain": {"key": "mountain", "name": "Black Goldville", "id": -1, "mode": 1}, "neptune": {"key": "neptune", "name": "Normandy", "id": -1, "mode": 1}, "neptune_01": {"key": "neptune_01", "name": "Normandy - Hills", "id": -1, "mode": 3}, "neptune_02": {"key": "neptune_02", "name": "Normandy - Beach", "id": -1, "mode": 3}, "north": {"key": "north", "name": "North", "id": -1, "mode": 1}, "ordeal": {"key": "ordeal", "name": "Trial by Fire", "id": -1, "mode": 1}, "plant": {"key": "plant", "name": "Ghost Factory", "id": -1, "mode": 1}, "pliego": {"key": "pliego", "name": "Castilla", "id": -1, "mode": 1}, "port": {"key": "port", "name": "Port Bay", "id": -1, "mode": 1}, "rift": {"key": "rift", "name": "Hellas", "id": -1, "mode": 1}, "rock": {"key": "rock", "name": "Mayan Ruins", "id": -1, "mode": 1}, "rudniki": {"key": "rudniki", "name": "Mines", "id": -1, "mode": 1}, "rudniki_01": {"key": "rudniki_01", "name": "Mines - Hill", "id": -1, "mode": 3}, "rudniki_02": {"key": "rudniki_02", "name": "Mines - Village", "id": -1, "mode": 3}, "rudniki_03": {"key": "rudniki_03", "name": "Mines - Center", "id": -1, "mode": 3}, "savanna": {"key": "savanna", "name": "Oasis Palms", "id": -1, "mode": 1}, "skit": {"key": "skit", "name": "Naval Frontier", "id": -1, "mode": 1}, "test": {"key": "test", "name": "World of Ducks", "id": -1, "mode": 2}, "tutorial": {"key": "tutorial", "name": "Proving Grounds", "id": -1, "mode": 0}} {
"Random": "Random map",
"amigosville": "Falls Creek",
"amigosville_02": "Falls Creek - Bridge",
"amigosville_03": "Falls Creek - Factory",
"asia": "Lost Temple",
"canal": "Canal",
"canal_01": "Canal - Factory",
"canyon": "Canyon",
"desert_train": "Desert Sands",
"desert_train_02": "Desert Sands - Town",
"desert_train_03": "Desert Sands - Dunes",
"erlenberg": "Middleburg",
"erlenberg_01": "Middleburg - Town",
"erlenberg_02": "Middleburg - Hill",
"faust": "Faust",
"forgecity": "New Bay",
"fort": "Fort Despair",
"grossberg": "Dynasty's Pearl",
"himmelsdorf": "Himmelsdorf",
"holmeisk": "Wasteland",
"idle": "Yukon",
"italy": "Vineyards",
"karelia": "Rockfield",
"karieri": "Copperfield",
"lake": "Mirage",
"lumber": "Alpenstadt",
"lumber_01": "Alpenstadt - Town",
"malinovka": "Winter Malinovka",
"medvedkovo": "Dead Rail",
"medvedkovo_02": "Dead Rail - Valley",
"medvedkovo_03": "Dead Rail - Railroad",
"milbase": "Yamato Harbor",
"milbase_02": "Yamato Harbor - Battleship",
"milbase_03": "Yamato Harbor - Hills",
"milbase_04": "Yamato Harbor - Center",
"milbase_05": "Yamato Harbor - Dock",
"moon": "Sea of Tranquility",
"mountain": "Black Goldville",
"neptune": "Normandy",
"neptune_01": "Normandy - Hills",
"neptune_02": "Normandy - Beach",
"north": "North",
"ordeal": "Trial by Fire",
"pliego": "Castilla",
"port": "Port Bay",
"rift": "Hellas",
"rock": "Mayan Ruins",
"rudniki": "Mines",
"savanna": "Oasis Palms",
"skit": "Naval Frontier",
"test": "World of Ducks",
"tutorial": "Proving Grounds"
}
+76 -106
View File
@@ -1,108 +1,78 @@
# WoT Blitz releases # WoT Blitz releases
| Release | Date | Content updates | | Release | Date | Notes | Inaccurate? |
|:-------:|:--------:|-------------| |:-------:|:--------:|-------------|-----|
| 10.4 | 2023-11-15 | Threesome-platoons for fun modes, camos | | 7.4 | 2020-11-12 | TD buffs, Clan missions | |
| 10.3 | 2023-09-27 | Polish Medium Tanks, Tier X rebalance, map updates: Ghost Factory, Desert Sands, Super-cool legenday camos| | 7.3 | 2020-10-08 | Swedish HT line | |
| 10.2 | 2023-08-16 | PBR Camos and bug fixes ... | | 7.2 | 2020-08-19 | Balance changes, added tier X ammo capa, new aiming reticles | |
| 10.1 | 2023-07-05 | PBR Camos and ? | | 7.1 | 2020-07-15 | New Yukon map, IS-6, KV-4, Patton 48 armor buff, Grille DPM buff, SP IC, AMZ 13 75, M41 Bulldog mobility buff | |
| 10.0 | 2023-05-24 | Lagoon map, Czechoslovakian heavies, tanks start shells loaded | | 7.0 | 2020-06-17 | British LTs, graphics improvements, ATGM nerf, Sheridan nerf, map fixes | |
| 9.8 | 2023-03-22 | F\*cked up The Quick Commands Wheel, camos | | 6.10 | 2020-04-29 | T92E1 nerf, Tier V-IX heavy HP buff, Battle Pass, map fixes | |
| 9.7 | 2023-02-15 | Chinese light tanks | | 6.9 | 2020-03-25 | Japanese TDs, Tier X heavy HP buff | |
| 9.6 | 2023-01-11 | Finally fixing game sounds for players with Genelec studio monitors, more gold camos | | 6.8 | 2020-02-19 | ATGM nerf, Hellas map | |
| 9.5 | 2022-12-14 | Camos and ?| | 6.7 | 2020-01-15 | ATGM US Lights | |
| 9.4 | 2022-11-09 | Italian TD line | | 6.6 | 2019-12-18 | T-62A + Leo buffs | |
| 9.3 | 2022-10-04 | Nothing, except legandary camos and utterly incomprehensible shell icons | | 6.5 | 2019-11-21 | New UI | |
| 9.2 | 2022-08-17 | New shot sounds and shell hit marks, vehicle restoration from the game client | | 6.4 | 2019-10-16 | Halloween map, mid-tier HT buff... | |
| 9.1 | 2022-07-14 | Releases updated via DLC, graphics updates for Object 140, Patton 46 | | 6.3 | 2019-09-18 | European line | |
| 9.0 | 2022-06-08 | Japanies heavies, Castilla graphics update, new garage | | 6.2 | 2019-08-14 | New MM | |
| 8.10 | 2022-04-28 | New battle results screen, new "Operation" mechanics | | 6.1 | 2019-07-10 | Autoloader buff | |
| 8.9 | 2022-03-23 | "Free" camo resupply, VK 72.01 supplies | | 6.0 | 2019-06-05 | UK TD line #2 | |
| 8.8 | 2022-02-16 | Molendijk map | | 5.10 | 2019-04-24 | new missions | |
| 8.7 | 2022-01-19 | Soviet Light Tanks | | 5.9 | 2019-03-27 | New shell tracers, minor fixes | |
| 8.6 | 2021-12-15 | Joining Light and Medium Tank classes in MM | | 5.8 | 2019-02-21 | Chinese TD line | |
| 8.5 | 2021-11-17 | New national crew voices, economy update | | 5.7 | 2019-01-16 | Avatars | |
| 8.4 | 2021-10-20 | Polish heavy tanks | | 5.6 | 2018-12-05 | Normandy map | |
| 8.3 | 2021-09-16 | FV4005, FV4022, VK 91.01 (P) and WZ-121 legendary camos, -5 deg gun depression to WZ-120 | | 5.5 | 2018-11-13 | Low-tier clean-up | |
| 8.2 | 2021-08-18 | Ghost Factory map, XP/credits nerf for inactive players, new store UI | | 5.4 | 2018-10-10 | MM "rigging" adjusted | |
| 8.1 | 2021-07-15 | Armor highlighting updated | | 5.3 | 2018-09-12 | MM "rigging" started, Newbie queue added | |
| 8.0 | 2021-06-08 | American experimental heavies (Yoh-line), PBR camos | | 5.2 | 2018-08-22 | Faust map | |
| 7.9 | 2021-04-27 | Mines rework, new tutorial, colorblind mode, JgPz E100 legendary camo | | 5.1 | 2018-07-31 | New MM: vehicle class matching | |
| 7.8 | 2021-03-24 | Mid-tier balance changes, Grille line new consumables | | 5.0 | 2018-06-30 | Vineyeards map update, Spare Parts killed | |
| 7.7 | 2021-02-24 | Czechoslovakian medium tanks | | 4.10 | 2018-05-24 | Alpenstadt map | |
| 7.6 | 2021-01-27 | AMC 13 90, TOG II buffs, free replay camera | | 4.9 | 2018-04-25 | Chinese heavy tanks | |
| 7.5 | 2020-12-09 | ATGM removal, Batchat, Kpz70, T-2020 buff | | 4.8 | 2018-03-28 | Choice of battle modes, crew skills accelerator | |
| 7.4 | 2020-11-12 | TD buffs, Clan missions | | 4.7 | 2018-02-28 | New minimap | |
| 7.3 | 2020-10-08 | Swedish HT line | | 4.6 | 2018-01-31 | Chinese nation | |
| 7.2 | 2020-08-19 | Balance changes, added tier X ammo capa, new aiming reticles | | 4.5 | 2017-12-19 | Dynasty's Pearl map | |
| 7.1 | 2020-07-15 | New Yukon map, IS-6, KV-4, Patton 48 armor buff, Grille DPM buff, SP IC, AMZ 13 75, M41 Bulldog mobility buff | | 4.4 | 2017-11-09 | New British tanks | |
| 7.0 | 2020-06-17 | British LTs, graphics improvements, ATGM nerf, Sheridan nerf, map fixes | | 4.3 | 2017-10-10 | Level 7 screw skills | |
| 6.10 | 2020-04-29 | T92E1 nerf, Tier V-IX heavy HP buff, Battle Pass, map fixes | | 4.2 | 2017-09-12 | French LTs, Naval Frontier map | |
| 6.9 | 2020-03-25 | Japanese TDs, Tier X heavy HP buff | | 4.1 | 2017-08-16 | New markers | |
| 6.8 | 2020-02-19 | ATGM nerf, Hellas map | | 4.0 | 2017-07-13 | Rating battles | Y |
| 6.7 | 2020-01-15 | ATGM US Lights | | 3.10 | 2017-06-15 | Fixes | Y |
| 6.6 | 2019-12-18 | T-62A + Leo buffs | | 3.9 | 2017-05-19 | Military Honor, Mayan Ruins | Y |
| 6.5 | 2019-11-21 | New UI | | 3.8 | 2017-04-24 | Spare Parts, New 9-slot Equipment system | Y |
| 6.4 | 2019-10-16 | Halloween map, mid-tier HT buff... | | 3.7 | 2017-03-22 | Balance changes, Tournaments | Y |
| 6.3 | 2019-09-18 | European line | | 3.6 | 2017-02-16 | Vehicle Enrichment | Y |
| 6.2 | 2019-08-14 | New MM | | 3.5 | 2017-01-13 | Boosters, Dead rail update | Y |
| 6.1 | 2019-07-10 | Autoloader buff | | 3.4 | 2016-11-28 | Canyon map, USA T57 line | |
| 6.0 | 2019-06-05 | UK TD line #2 | | 3.3 | 2016-11-01 | Updated Mines map | |
| 5.10 | 2019-04-24 | new missions | | 3.2 | 2016-10-04 | Copperfield update | |
| 5.9 | 2019-03-27 | New shell tracers, minor fixes | | 3.1 | 2016-09-03 | Clan tournaments, Yamato Harbor map | Y |
| 5.8 | 2019-02-21 | Chinese TD line | | 3.0 | 2016-07-20 | Supremacy mode, Falls Creek update | Y |
| 5.7 | 2019-01-16 | Avatars | | 2.11 | 2016-06-28 | Vineyeards map, Oasis Palms update, German paper TDs | |
| 5.6 | 2018-12-05 | Normandy map | | 2.10 | 2016-06-07 | Rockfield map update, Tank birthdays, high-pen gun for IS-6 | |
| 5.5 | 2018-11-13 | Low-tier clean-up :-( | | 2.9 | 2016-05-03 | Training rooms, +/-1 Matchmaker | Y |
| 5.4 | 2018-10-10 | MM "rigging" adjusted | | 2.8 | 2016-04-04 | New Russian TD line, new consumables system | Y |
| 5.3 | 2018-09-12 | MM "rigging" started, Newbie queue added | | 2.7 | 2016-03-07 | Mirage map | Y |
| 5.2 | 2018-08-22 | Faust map | | 2.6 | 2016-02-10 | German LTs, shooting through obstacles | Y |
| 5.1 | 2018-07-31 | New MM: vehicle class matching | | 2.5 | 2016-01-11 | Camouflages, Clan supply | Y |
| 5.0 | 2018-06-30 | Vineyeards map update, Spare Parts removed ! | | 2.4 | 2015-12-09 | Additional Japanese tanks, windows version | Y |
| 4.10 | 2018-05-24 | Replays, Alpenstadt map | | 2.3 | 2015-11-12 | Canal map | Y |
| 4.9 | 2018-04-25 | Chinese heavy tanks | | 2.2 | 2015-10-05 | Desert Sands map update | Y |
| 4.8 | 2018-03-28 | Choice of battle modes, crew skills accelerator | | 2.1 | 2015-09-07 | UK TDs, Clan Chat | Y |
| 4.7 | 2018-02-28 | New minimap | | 2.0 | 2015-08-05 | Clans, Oasis Palms updated | |
| 4.6 | 2018-01-31 | Chinese nation | | 1.11 | 2015-07-13 | KV-2, KV-13, Sherman Jumbo | Y |
| 4.5 | 2017-12-19 | Dynasty's Pearl map | | 1.10 | 2015-06-11 | Port Bay map | Y |
| 4.4 | 2017-11-09 | New British tanks | | 1.9 | 2015-05-13 | New German medium tanks (Leo) | Y |
| 4.3 | 2017-10-10 | Level 7 screw skills | | 1.8 | 2015-04-14 | Game tutorial, Bot map for new players | Y |
| 4.2 | 2017-09-12 | French LTs, Naval Frontier map | | 1.7 | 2015-02-16 | US Turreted TDs | Y |
| 4.1 | 2017-08-16 | New markers | | 1.6 | 2015-01-19 | Castilla map, UK HT line | Y |
| 4.0 | 2017-07-13 | Rating battles (date uncertain) | | 1.5 | 2014-12-01 | UK Nation | Y |
| 3.10 | 2017-06-15 | Fixes (date uncertain) | | 1.4 | 2014-10-29 | German HT line (Maus) | Y |
| 3.9 | 2017-05-19 | Military Honor, Mayan Ruins (date uncertain) | | 1.3 | 2014-10-02 | USSR IS-4 line, Lost Temple, Black Goldville maps | Y |
| 3.8 | 2017-04-24 | Spare Parts, New 9-slot Equipment system (date uncertain) | | 1.2 | 2014-08-20 | Oasis Palms map | Y |
| 3.7 | 2017-03-22 | Balance changes, Tournaments (date uncertain) | | 1.1.1 | 2014-07-23 | Fixes :-) | |
| 3.6 | 2017-02-16 | Vehicle Enrichment (date uncertain) | | 1.0 | 2014-06-26 | Worldwide launch | |
| 3.5 | 2017-01-13 | Boosters, Dead rail update (date uncertain) | | 0.9 | 2014-05-05 | Nordic soft launch | |
| 3.4 | 2016-11-28 | Canyon map, USA T57 line |
| 3.3 | 2016-11-01 | Updated Mines map |
| 3.2 | 2016-10-04 | Copperfield update |
| 3.1 | 2016-09-03 | Clan tournaments, Yamato Harbor map (date uncertain) |
| 3.0 | 2016-07-20 | Supremacy mode, Falls Creek update (date uncertain) |
| 2.11 | 2016-06-28 | Vineyeards map, Oasis Palms update, German paper TDs |
| 2.10 | 2016-06-07 | Rockfield map update, Tank birthdays, high-pen gun for IS-6 |
| 2.9 | 2016-05-03 | Training rooms, +/-1 Matchmaker (date uncertain) |
| 2.8 | 2016-04-04 | New Russian TD line, new consumables system (date uncertain) |
| 2.7 | 2016-03-07 | Mirage map (date uncertain) |
| 2.6 | 2016-02-10 | German LTs, shooting through obstacles (date uncertain) |
| 2.5 | 2016-01-11 | Camouflages, Clan supply (date uncertain) |
| 2.4 | 2015-12-09 | Additional Japanese tanks, windows version (date uncertain) |
| 2.3 | 2015-11-12 | Canal map (date uncertain) |
| 2.2 | 2015-10-05 | Desert Sands map update (date uncertain) |
| 2.1 | 2015-09-07 | UK TDs, Clan Chat (date uncertain) |
| 2.0 | 2015-08-05 | Clans, Oasis Palms updated |
| 1.11 | 2015-07-13 | KV-2, KV-13, Sherman Jumbo (date uncertain) |
| 1.10 | 2015-06-11 | Port Bay map (date uncertain) |
| 1.9 | 2015-05-13 | New German medium tanks (Leo) (date uncertain) |
| 1.8 | 2015-04-14 | Game tutorial, Bot map for new players (date uncertain) |
| 1.7 | 2015-02-16 | US Turreted TDs (date uncertain) |
| 1.6 | 2015-01-19 | Castilla map, UK HT line (date uncertain) |
| 1.5 | 2014-12-01 | UK Nation (date uncertain) |
| 1.4 | 2014-10-29 | German HT line (Maus) (date uncertain) |
| 1.3 | 2014-10-02 | USSR IS-4 line, Lost Temple, Black Goldville maps (date uncertain) |
| 1.2 | 2014-08-20 | Oasis Palms map (date uncertain) |
| 1.1.1 | 2014-07-23 | Fixes :-) |
| 1.0 | 2014-06-26 | Worldwide launch |
| 0.9 | 2014-05-05 | Nordic soft launch |
-1
View File
@@ -8,4 +8,3 @@ lxml
xmltodict xmltodict
progress progress
pytest-asyncio pytest-asyncio
blitz-utils @ git+https://github.com/Jylpah/blitz-utils
-172
View File
@@ -1,172 +0,0 @@
,TOTAL,Battles,% Battles,WR,DPB,KPB,Spot,Top tier,DR,KDR,Hit rate,Pen rate,Surv%,Share live,Player WR,Allies WR,Enemies WR,No stats
,Total,6942,100%,71.80%,2058,1.86,1.4,64%,2.3,5.4,86.10%,90.80%,65.30%,90%,57.08%,50.15%,50.12%,0.20%
,,,,,,,,,,,,,,,,,,
,Result,Battles,% Battles,WR,DPB,KPB,Spot,Top tier,DR,KDR,Hit rate,Pen rate,Surv%,Share live,Player WR,Allies WR,Enemies WR,No stats
,Loss,1959,28%,0.00%,1715,1.12,1.3,61%,1.3,1.3,84.70%,88.60%,13.40%,78%,56.47%,49.56%,50.92%,0.10%
,Win,4983,72%,100.00%,2193,2.16,1.4,65%,3,15.1,86.50%,91.40%,85.70%,95%,57.32%,50.39%,49.80%,0.20%
,,,,,,,,,,,,,,,,,,
,Battle Type,Battles,% Battles,WR,DPB,KPB,Spot,Top tier,DR,KDR,Hit rate,Pen rate,Surv%,Share live,Player WR,Allies WR,Enemies WR,No stats
,Encounter,4652,67%,73.00%,1969,1.98,1.4,67%,2.5,6,85.70%,90.70%,66.80%,91%,57.43%,50.41%,50.33%,0.30%
,Supremacy,2290,33%,69.30%,2238,1.63,1.2,60%,2,4.3,87.10%,91.20%,62.20%,89%,56.37%,49.63%,49.69%,0.00%
,,,,,,,,,,,,,,,,,,
,Tier,Battles,% Battles,WR,DPB,KPB,Spot,Top tier,DR,KDR,Hit rate,Pen rate,Surv%,Share live,Player WR,Allies WR,Enemies WR,No stats
,Bottom tier,2480,36%,69.50%,1750,1.53,1.2,0%,2.2,3.9,85.40%,89.20%,60.70%,88%,56.91%,50.13%,49.99%,0.10%
,Top tier,4462,64%,73.10%,2229,2.05,1.5,100%,2.4,6.4,86.50%,91.60%,67.90%,91%,57.18%,50.16%,50.19%,0.20%
,,,,,,,,,,,,,,,,,,
,Tank Tier,Battles,% Battles,WR,DPB,KPB,Spot,Top tier,DR,KDR,Hit rate,Pen rate,Surv%,Share live,Player WR,Allies WR,Enemies WR,No stats
,1,89,1%,80.90%,678,1.89,1.9,40%,3,7.6,86.20%,91.80%,75.30%,95%,55.40%,48.80%,48.40%,0.00%
,2,180,3%,77.80%,970,2.64,1.6,73%,3.3,9.1,82.90%,90.60%,71.10%,93%,56.04%,49.36%,49.46%,0.90%
,3,540,8%,75.70%,1099,2.15,1.4,36%,3.1,7,83.60%,90.00%,69.10%,93%,57.55%,51.15%,50.16%,1.90%
,4,628,9%,75.20%,1256,2.21,1.3,73%,3.1,7.4,85.00%,91.60%,70.20%,94%,55.72%,51.76%,51.65%,0.00%
,5,626,9%,80.20%,1503,2.29,1.3,71%,3.2,8.3,86.90%,89.50%,72.20%,93%,55.69%,50.38%,49.95%,0.00%
,6,1064,15%,74.20%,1801,1.97,1.4,62%,2.4,5.8,86.70%,92.20%,65.90%,90%,56.82%,49.24%,49.31%,0.00%
,7,1141,16%,71.80%,2143,1.69,1.3,50%,2.5,4.9,85.70%,90.10%,65.80%,90%,58.48%,49.62%,49.60%,0.00%
,8,1222,18%,68.20%,2371,1.59,1.4,67%,2.1,4.2,87.40%,90.90%,61.80%,89%,56.84%,49.80%,49.99%,0.00%
,9,598,9%,64.70%,2806,1.61,1.2,49%,2.1,4,89.10%,91.90%,59.50%,87%,56.58%,50.13%,50.32%,0.00%
,10,854,12%,65.60%,3270,1.62,1.5,100%,2,4,88.30%,90.20%,59.60%,88%,58.37%,50.83%,51.16%,0.00%
,,,,,,,,,,,,,,,,,,
,Tank Class,Battles,% Battles,WR,DPB,KPB,Spot,Top tier,DR,KDR,Hit rate,Pen rate,Surv%,Share live,Player WR,Allies WR,Enemies WR,No stats
,Light Tank,1337,19%,74.40%,1589,1.88,1.9,59%,2.3,5.9,83.70%,89.20%,68.40%,90%,57.15%,50.20%,49.90%,0.70%
,Medium Tank,1957,28%,73.10%,2181,1.99,1.7,67%,2.4,5.9,88.20%,91.40%,66.40%,90%,57.23%,50.26%,50.12%,0.10%
,Heavy Tank,2032,29%,70.00%,2180,1.75,1.2,70%,1.9,5,87.20%,90.70%,65.20%,91%,56.72%,50.16%,50.23%,0.00%
,Tank Destroyer,1616,23%,70.30%,2144,1.84,0.7,59%,3,4.8,85.10%,92.60%,61.50%,91%,57.31%,49.98%,50.16%,0.00%
,,,,,,,,,,,,,,,,,,
,Player WR,Battles,% Battles,WR,DPB,KPB,Spot,Top tier,DR,KDR,Hit rate,Pen rate,Surv%,Share live,Player WR,Allies WR,Enemies WR,No stats
,35 - 45%,80,1%,43.80%,1255,0.93,1,55%,1.1,1.5,84.00%,87.10%,37.50%,82%,44.52%,49.84%,51.14%,0.00%
,45 - 50%,584,8%,69.20%,1397,1.46,1.1,62%,1.8,3.8,81.20%,87.40%,61.30%,89%,47.86%,49.84%,49.86%,0.00%
,50 - 55%,1970,28%,69.00%,1861,1.73,1.3,63%,2.1,4.3,85.40%,90.20%,60.20%,88%,53.06%,50.10%,49.99%,0.00%
,55 - 65%,3677,53%,73.50%,2249,2.01,1.4,66%,2.5,6.3,87.50%,91.50%,68.10%,92%,58.78%,50.13%,50.14%,0.00%
,65 - %,631,9%,76.40%,2274,1.95,1.4,61%,2.8,7,84.60%,91.40%,72.10%,91%,69.92%,50.79%,50.51%,1.90%
,,,,,,,,,,,,,,,,,,
,Player Hit Rate,Battles,% Battles,WR,DPB,KPB,Spot,Top tier,DR,KDR,Hit rate,Pen rate,Surv%,Share live,Player WR,Allies WR,Enemies WR,No stats
, 0 - 25%,32,0%,43.80%,1,0,1.6,47%,0,0,0.00%, inf%,25.00%,57%,54.55%,50.15%,51.14%,0.00%
,25 - 50%,47,1%,44.70%,693,0.34,1.3,51%,0.6,0.5,38.70%,90.50%,36.20%,77%,55.05%,50.14%,51.15%,0.00%
,50 - 60%,172,2%,56.40%,876,0.6,1.2,58%,0.8,1.1,54.70%,87.80%,44.80%,81%,56.38%,50.61%,50.48%,0.00%
,60 - 70%,461,7%,58.80%,1254,1.08,1.2,61%,1.4,2.4,65.40%,87.70%,54.20%,87%,56.29%,50.18%,50.50%,0.00%
,70 - 80%,941,14%,70.50%,1691,1.59,1.3,63%,2,4.6,75.50%,89.10%,65.70%,91%,56.92%,50.36%,50.24%,0.00%
,80 - 90%,2091,30%,74.00%,2071,1.98,1.4,66%,2.5,6.3,85.00%,90.60%,68.50%,93%,57.00%,50.10%,50.08%,0.10%
,90 - 95%,1258,18%,81.00%,2561,2.52,1.5,66%,3.3,11,92.30%,92.00%,77.10%,96%,57.73%,50.08%,49.85%,0.30%
,95 - %,1940,28%,69.60%,2259,1.82,1.4,64%,2.2,4.5,99.00%,91.70%,59.80%,86%,57.17%,50.12%,50.11%,0.40%
,,,,,,,,,,,,,,,,,,
,Player Pen Rate,Battles,% Battles,WR,DPB,KPB,Spot,Top tier,DR,KDR,Hit rate,Pen rate,Surv%,Share live,Player WR,Allies WR,Enemies WR,No stats
, 0 - 25%,49,1%,38.80%,6,0,1.5,39%,0,0,45.80%,10.50%,22.40%,56%,55.11%,49.96%,50.47%,0.00%
,25 - 50%,43,1%,30.20%,447,0.19,1.7,44%,0.3,0.2,82.30%,38.40%,20.90%,66%,55.41%,50.75%,51.06%,0.00%
,50 - 60%,110,2%,41.80%,642,0.27,1.5,60%,0.5,0.4,77.50%,53.10%,32.70%,70%,54.44%,50.46%,50.61%,0.00%
,60 - 70%,210,3%,52.40%,1085,0.63,1.3,56%,0.9,1.1,81.00%,65.10%,40.00%,79%,55.71%,50.58%,50.39%,0.00%
,70 - 80%,469,7%,65.00%,1669,1.33,1.4,61%,1.6,3.1,83.50%,75.40%,57.60%,89%,56.39%,50.24%,50.30%,0.00%
,80 - 90%,1544,22%,71.60%,2076,1.86,1.4,61%,2.3,5.5,86.00%,85.30%,66.30%,92%,57.35%,50.17%,50.03%,0.20%
,90 - 95%,1210,17%,79.30%,2509,2.53,1.5,66%,3.3,11,87.80%,92.40%,77.00%,96%,57.57%,50.00%,50.09%,0.20%
,95 - %,3307,48%,73.30%,2100,1.88,1.3,67%,2.4,5.5,86.30%,99.30%,65.60%,90%,57.11%,50.14%,50.10%,0.20%
,,,,,,,,,,,,,,,,,,
Server,account_id_anon,Battles,% Battles,WR,DPB,KPB,Spot,Top tier,DR,KDR,Hit rate,Pen rate,Surv%,Share live,Player WR,Allies WR,Enemies WR,No stats
RU,1,33,0%,78.80%,3112,1.91,1.6,67%,2.5,7.9,89.60%,90.20%,75.80%,87%,71.43%,50.74%,51.07%,0.00%
RU,2,23,0%,87.00%,3525,2.78,1.7,74%,4.3,32,90.40%,94.40%,91.30%,100%,59.39%,48.07%,48.75%,0.00%
RU,3,81,1%,66.70%,1927,1.47,1,75%,1.9,3.1,82.30%,89.60%,53.10%,86%,69.59%,50.23%,50.85%,0.00%
EU,4,26,0%,80.80%,4082,2.62,1.2,62%,4.1,17,91.10%,93.80%,84.60%,98%,53.92%,48.75%,49.31%,0.00%
EU,5,79,1%,59.50%,1920,0.97,1.4,75%,1.4,2,80.20%,87.10%,50.60%,84%,59.06%,50.12%,51.22%,0.00%
EU,6,92,1%,60.90%,1685,0.99,1.5,65%,1.3,1.8,87.80%,88.50%,45.70%,83%,57.79%,50.30%,50.77%,0.00%
EU,7,50,1%,78.00%,2787,2.92,1.9,52%,4,16.2,90.60%,92.70%,82.00%,99%,64.87%,50.49%,50.50%,0.00%
EU,8,69,1%,60.90%,1695,1.48,1.9,55%,1.5,3,87.80%,92.10%,50.70%,77%,54.73%,50.06%,49.81%,0.10%
EU,9,33,0%,63.60%,1529,1.55,1.9,64%,2,3.6,82.10%,91.30%,57.60%,85%,52.48%,49.85%,50.92%,0.00%
EU,10,22,0%,90.90%,2990,3.82,1,59%,3.6,42,85.60%,93.00%,90.90%,100%,57.27%,48.97%,49.67%,0.00%
EU,11,35,1%,62.90%,1197,0.97,1.1,66%,1.3,2,85.20%,88.10%,51.40%,81%,55.89%,50.71%,49.97%,0.00%
EU,12,20,0%,95.00%,4854,3.95,1.2,25%,4.9,79,94.40%,95.60%,95.00%,99%,56.71%,49.15%,49.81%,0.00%
EU,13,80,1%,73.80%,2228,2.65,1.4,69%,3.3,8.5,92.10%,92.70%,68.80%,95%,58.83%,49.43%,49.21%,0.00%
EU,14,30,0%,83.30%,2167,3.93,2,63%,4.2,19.7,87.90%,92.00%,80.00%,98%,62.43%,50.39%,49.69%,0.00%
EU,15,305,4%,55.40%,2126,1.21,1.3,78%,1.6,2.4,85.80%,90.90%,49.50%,87%,58.91%,50.46%,50.47%,0.00%
EU,16,49,1%,69.40%,2362,2.47,1.5,43%,4,7.1,90.20%,93.30%,65.30%,94%,62.94%,49.43%,49.50%,0.00%
EU,17,22,0%,86.40%,1898,4.41,1.4,95%,4.8,48.5,90.60%,94.80%,90.90%,100%,57.61%,48.11%,49.25%,0.00%
EU,18,96,1%,76.00%,1764,2.19,0.9,67%,3.2,7.2,89.40%,95.00%,69.80%,94%,56.39%,50.00%,49.58%,0.00%
EU,19,23,0%,95.70%,1997,2.09,1.3,65%,3.8,16,90.70%,94.20%,87.00%,98%,70.96%,48.51%,49.66%,0.00%
EU,20,256,4%,54.30%,1081,0.58,1.5,55%,0.9,0.8,81.10%,83.80%,28.10%,68%,52.29%,50.31%,49.81%,0.00%
EU,21,73,1%,82.20%,1025,1.9,1.5,55%,2.7,6.3,84.20%,92.30%,69.90%,94%,58.95%,51.61%,50.45%,0.00%
EU,22,53,1%,79.20%,1415,1.98,0.9,47%,3.2,7,87.40%,90.40%,71.70%,95%,57.15%,50.10%,49.76%,0.00%
EU,23,70,1%,81.40%,2224,2.5,1.8,47%,4,9.7,89.20%,90.20%,74.30%,96%,61.99%,50.85%,50.17%,0.00%
EU,24,83,1%,73.50%,3049,2.1,2,73%,3.2,7.2,89.60%,91.70%,71.10%,96%,60.48%,49.78%,49.51%,0.00%
EU,25,127,2%,68.50%,1609,1.86,1.3,52%,2.4,4.5,83.40%,89.50%,59.10%,89%,54.64%,49.76%,49.35%,0.00%
EU,26,52,1%,80.80%,2669,2.62,2.2,50%,3,11.3,87.80%,91.00%,76.90%,95%,62.66%,49.60%,49.65%,0.20%
EU,27,30,0%,86.70%,4246,3.17,1.4,57%,3.6,23.8,88.10%,95.30%,86.70%,99%,56.38%,49.10%,49.54%,0.00%
EU,28,24,0%,83.30%,2823,2.96,1.8,62%,4.9,17.8,89.30%,91.20%,83.30%,98%,64.91%,50.25%,51.06%,0.00%
EU,29,29,0%,75.90%,1750,1.62,1.3,59%,2.2,3.6,88.10%,93.60%,55.20%,91%,54.39%,49.78%,49.34%,0.00%
EU,30,26,0%,92.30%,2631,3.12,1.8,69%,3.1,27,92.90%,93.80%,88.50%,97%,57.57%,49.93%,49.96%,0.00%
EU,31,31,0%,90.30%,2126,2.16,1.2,61%,3.4,13.4,85.20%,91.20%,83.90%,98%,52.31%,50.24%,49.30%,0.00%
EU,32,44,1%,77.30%,1848,2.91,0.7,77%,3.4,14.2,85.40%,91.70%,79.50%,96%,50.22%,50.67%,50.91%,0.00%
EU,33,74,1%,94.60%,1811,3.24,1.5,59%,4.1,48,86.80%,86.30%,93.20%,99%,56.08%,49.98%,49.17%,0.00%
EU,34,158,2%,77.80%,1290,1.66,0.9,53%,2.4,4.4,78.40%,90.70%,62.70%,93%,49.45%,49.80%,50.05%,0.00%
EU,35,21,0%,61.90%,1796,1.19,1.4,86%,1.5,2.5,77.00%,86.60%,52.40%,82%,48.99%,50.98%,50.38%,0.00%
EU,36,120,2%,55.80%,1730,1.1,1.6,68%,1.3,2.2,85.30%,85.90%,49.20%,83%,60.61%,50.43%,49.95%,0.10%
EU,37,25,0%,88.00%,5110,3.6,1.5,96%,3.7,45,94.90%,91.70%,92.00%,100%,60.44%,50.29%,51.16%,0.00%
EU,38,350,5%,62.00%,1159,1.09,1.3,63%,1.2,2.3,83.10%,89.70%,52.30%,84%,52.65%,50.37%,50.42%,0.00%
EU,39,25,0%,84.00%,4965,2.72,1.5,84%,3.6,13.6,89.40%,91.30%,80.00%,97%,54.95%,49.64%,50.59%,0.00%
EU,40,22,0%,90.90%,4394,3.09,2.3,64%,4.2,34,92.60%,90.30%,90.90%,98%,52.49%,50.46%,50.63%,0.00%
EU,41,57,1%,63.20%,3078,1.63,2.3,96%,2,3.3,85.40%,86.30%,50.90%,85%,60.62%,51.59%,52.10%,0.00%
EU,42,22,0%,68.20%,2270,0.95,1.3,91%,1.6,1.9,85.20%,88.90%,50.00%,85%,59.46%,50.97%,50.61%,0.00%
EU,43,45,1%,64.40%,1482,0.93,1.6,62%,1.2,1.8,83.00%,91.60%,48.90%,79%,50.40%,51.15%,50.79%,0.00%
EU,44,56,1%,96.40%,1927,2.79,1.6,77%,5.4,31.2,85.60%,90.20%,91.10%,98%,54.95%,49.96%,49.62%,0.00%
EU,45,28,0%,96.40%,4659,3.5,1.4,64%,3.8,49,89.00%,91.70%,92.90%,100%,54.81%,49.56%,49.85%,0.00%
EU,46,134,2%,70.90%,1291,1.99,1,49%,3.3,5.6,82.90%,91.80%,64.20%,94%,55.71%,51.75%,51.64%,0.00%
EU,47,51,1%,72.50%,1119,1.43,0.9,78%,1.9,3.8,89.20%,89.20%,62.70%,89%,52.58%,52.04%,52.06%,0.00%
EU,48,45,1%,86.70%,2756,2.71,2.2,64%,4.1,12.2,90.10%,91.50%,77.80%,97%,63.68%,49.88%,49.92%,0.00%
EU,49,35,1%,97.10%,5932,3.57,1.1,94%,5.7,41.7,88.10%,96.30%,91.40%,99%,70.46%,49.51%,50.42%,0.00%
EU,50,186,3%,60.80%,1169,1.02,1.2,49%,1.2,2.1,80.20%,89.20%,52.20%,84%,56.65%,50.14%,50.07%,0.00%
EU,51,25,0%,92.00%,2194,4.68,2.3,60%,4.9,117,86.20%,92.00%,96.00%,100%,70.74%,52.26%,51.76%,0.00%
EU,52,93,1%,62.40%,1444,1.1,1.1,54%,1.7,2.9,88.00%,92.30%,62.40%,85%,72.96%,49.89%,50.29%,0.00%
EU,53,25,0%,80.00%,2374,2.8,1.5,68%,3.5,11.7,86.80%,90.50%,76.00%,95%,60.96%,49.42%,48.68%,0.00%
EU,54,30,0%,53.30%,2384,1.27,1.7,73%,1.6,2.5,85.00%,86.50%,50.00%,81%,54.58%,49.33%,50.27%,0.00%
EU,55,29,0%,79.30%,2219,1.93,1.6,69%,2.1,5.1,88.30%,86.10%,62.10%,89%,47.58%,50.43%,49.39%,0.00%
EU,56,73,1%,69.90%,2036,2.33,0.9,64%,3.2,8.5,90.80%,94.00%,72.60%,95%,52.47%,49.24%,49.05%,0.10%
EU,57,26,0%,96.20%,949,3.08,2,50%,3.2,26.7,83.20%,87.10%,88.50%,97%,46.64%,49.42%,48.36%,0.00%
EU,58,20,0%,65.00%,344,0.45,0.9,45%,0.7,1.3,75.50%,73.80%,65.00%,83%,45.36%,49.30%,49.03%,0.00%
EU,59,149,2%,34.90%,1105,0.8,1.1,60%,0.9,1.1,82.80%,85.80%,28.90%,78%,45.21%,50.08%,51.28%,0.00%
EU,60,22,0%,63.60%,1108,0.91,1,91%,1.3,1.4,78.70%,85.00%,36.40%,81%,54.54%,49.66%,49.03%,0.00%
EU,61,36,1%,94.40%,2794,3.81,2.5,83%,6.2,45.7,85.30%,92.10%,91.70%,100%,63.28%,50.37%,50.28%,0.00%
EU,62,32,0%,31.20%,1786,1.19,0.9,75%,1.8,2,90.60%,91.90%,40.60%,88%,61.60%,49.13%,50.35%,0.00%
EU,63,21,0%,85.70%,2476,3.33,2,76%,4.8,35,91.50%,95.70%,90.50%,99%,53.93%,50.29%,49.74%,0.00%
NA,64,23,0%,91.30%,2371,3.57,0.9,70%,4.8,20.5,86.10%,92.50%,82.60%,99%,58.19%,49.00%,50.44%,0.30%
NA,65,25,0%,96.00%,4281,2.56,1.8,72%,4.1,64,90.20%,91.40%,96.00%,100%,62.10%,51.41%,50.28%,0.00%
NA,66,238,3%,76.10%,2183,1.56,1.5,50%,2.8,5.7,79.70%,89.90%,72.70%,92%,68.48%,50.75%,50.57%,0.00%
NA,67,56,1%,73.20%,2022,1.88,1.3,68%,2.5,6.6,85.20%,90.40%,71.40%,93%,55.31%,49.88%,49.73%,0.10%
NA,68,25,0%,92.00%,6141,3.36,1.2,100%,3.5,28,92.20%,93.80%,88.00%,99%,62.64%,49.81%,50.96%,0.00%
NA,69,44,1%,77.30%,4178,1.93,1.5,77%,3,12.1,92.10%,91.60%,84.10%,98%,53.67%,50.20%,50.23%,0.00%
NA,70,26,0%,96.20%,3412,3.46,1.8,69%,3.6,90,92.20%,93.90%,96.20%,100%,65.85%,48.95%,49.25%,0.00%
NA,71,58,1%,77.60%,1642,1.93,0.9,60%,2.2,5.6,86.00%,94.60%,65.50%,87%,46.03%,49.73%,50.08%,0.00%
NA,72,197,3%,78.20%,2416,2.37,1.2,64%,3.3,10.8,86.30%,92.80%,78.20%,97%,56.68%,49.22%,49.50%,0.00%
NA,73,23,0%,60.90%,3932,1.91,2,87%,3,4.9,89.50%,90.70%,60.90%,89%,60.65%,48.75%,50.51%,0.00%
NA,74,42,1%,78.60%,1431,2.45,0.7,36%,2.2,6.9,84.50%,89.30%,64.30%,90%,50.81%,49.26%,49.33%,0.00%
NA,75,21,0%,81.00%,3748,3.29,1.3,57%,4,17.2,91.90%,92.50%,81.00%,100%,61.77%,48.23%,48.98%,0.00%
NA,76,34,0%,88.20%,2707,2.59,1.4,68%,3,44,84.50%,90.50%,94.10%,96%,55.79%,50.34%,49.42%,0.00%
NA,77,115,2%,74.80%,2171,2.19,1.4,74%,2.9,8.4,89.00%,91.40%,73.90%,95%,59.53%,49.65%,49.88%,0.00%
NA,78,23,0%,65.20%,1958,1.96,0.5,61%,2.3,5.6,89.80%,93.30%,65.20%,92%,62.10%,50.31%,49.85%,0.00%
NA,79,218,3%,74.30%,1860,2.16,1.5,65%,2.6,7.2,85.90%,91.60%,70.20%,95%,53.76%,50.11%,49.84%,0.00%
NA,80,35,1%,57.10%,3142,1.71,1.9,80%,2.3,3.2,90.00%,93.10%,45.70%,86%,56.23%,50.16%,51.49%,0.00%
NA,81,32,0%,90.60%,3407,2.62,1.2,62%,3.6,16.8,85.80%,91.90%,84.40%,97%,54.91%,49.20%,49.43%,0.00%
NA,82,20,0%,90.00%,4472,3.4,2.2,75%,4.1,34,86.20%,83.10%,90.00%,100%,50.16%,50.67%,50.02%,0.00%
NA,83,51,1%,72.50%,1023,2.08,1.1,76%,2.2,5.6,88.30%,93.20%,62.70%,91%,73.85%,56.05%,50.69%,23.20%
NA,84,47,1%,80.90%,3820,2.45,1.4,85%,3.7,12.8,93.20%,94.90%,80.90%,98%,61.01%,50.73%,50.39%,0.00%
NA,85,71,1%,91.50%,3159,2.73,0.9,65%,3.9,27.7,89.40%,92.40%,90.10%,99%,55.39%,49.64%,50.01%,0.00%
NA,86,28,0%,85.70%,4249,2.46,1.3,79%,3.1,23,91.90%,93.70%,89.30%,95%,61.07%,50.13%,50.15%,0.00%
NA,87,24,0%,75.00%,3048,2.17,1.9,75%,2.7,10.4,85.40%,90.00%,79.20%,98%,55.74%,49.79%,50.05%,0.00%
NA,88,34,0%,67.60%,3317,2.21,2.1,65%,3.6,6.8,90.50%,91.30%,67.60%,96%,61.83%,49.97%,49.88%,0.00%
NA,89,23,0%,30.40%,1399,0.52,1.3,91%,0.9,0.8,87.30%,85.40%,30.40%,71%,49.58%,50.38%,51.69%,0.00%
NA,90,20,0%,75.00%,1305,0.6,1.4,60%,1.1,1.7,88.10%,80.10%,65.00%,91%,48.23%,49.76%,49.40%,0.00%
NA,91,24,0%,79.20%,2554,2.96,1.2,50%,5.6,17.8,93.30%,95.50%,83.30%,98%,58.79%,50.82%,51.10%,0.00%
NA,92,48,1%,56.20%,1707,0.69,0.7,92%,0.8,1.4,81.30%,86.80%,52.10%,87%,55.85%,53.43%,53.97%,0.00%
NA,93,130,2%,62.30%,1912,1.31,1.3,70%,1.3,2.9,89.00%,91.70%,55.40%,86%,59.63%,49.95%,50.11%,0.00%
NA,94,35,1%,77.10%,3875,2.74,1.8,57%,3.6,12,89.60%,94.40%,77.10%,95%,59.73%,49.60%,50.04%,0.00%
NA,95,23,0%,73.90%,2688,3.17,1,74%,3.4,14.6,92.50%,93.20%,78.30%,96%,51.21%,49.86%,50.33%,0.00%
NA,96,26,0%,61.50%,1796,1.19,1.2,31%,1.6,2.8,75.60%,84.20%,57.70%,91%,54.00%,50.02%,50.03%,0.00%
NA,97,21,0%,90.50%,1869,2.52,2.3,76%,3.2,17.7,85.40%,89.60%,85.70%,96%,56.43%,49.38%,49.01%,0.00%
NA,98,101,1%,71.30%,1499,2,0.7,58%,2.7,5.3,83.30%,91.50%,62.40%,93%,52.60%,49.80%,49.63%,0.10%
NA,99,20,0%,60.00%,1368,1,0.9,45%,1.4,2.9,83.50%,87.90%,65.00%,84%,54.73%,50.49%,50.26%,0.00%
NA,100,24,0%,79.20%,1998,2.54,1.6,75%,3.4,20.3,85.30%,83.70%,87.50%,98%,53.43%,50.95%,50.42%,0.30%
NA,101,26,0%,42.30%,1170,0.77,1.7,73%,1.3,1.2,75.50%,86.50%,34.60%,81%,46.59%,49.31%,50.13%,0.00%
NA,102,26,0%,53.80%,1013,0.85,0.8,62%,1.1,1.2,74.20%,82.40%,26.90%,83%,52.75%,49.08%,49.42%,0.00%
NA,103,23,0%,91.30%,3980,3,1.4,83%,3.1,34.5,86.00%,90.80%,91.30%,97%,63.72%,49.86%,49.82%,0.00%
NA,104,57,1%,71.90%,1694,1.49,0.6,74%,2.8,4.7,82.80%,86.80%,68.40%,92%,46.26%,49.48%,48.84%,0.00%
ASIA,105,330,5%,82.40%,2195,2.01,1.7,63%,2.7,7.5,89.80%,92.70%,73.00%,94%,57.98%,49.95%,49.71%,0.00%
ASIA,106,132,2%,77.30%,1268,1.31,0.8,58%,2.2,3.5,82.20%,92.40%,62.10%,85%,62.78%,49.79%,50.26%,0.00%
ASIA,107,21,0%,90.50%,3749,3.67,1.8,81%,4.1,38.5,90.70%,93.70%,90.50%,97%,53.77%,49.37%,50.06%,0.00%
ASIA,108,35,1%,85.70%,4501,2.6,1.6,74%,4,15.2,89.10%,91.20%,82.90%,99%,54.47%,49.39%,49.24%,0.00%
ASIA,109,67,1%,73.10%,1278,1.7,1.5,54%,2.8,5.7,83.80%,88.00%,70.10%,93%,55.23%,51.01%,50.11%,0.10%
ASIA,110,70,1%,91.40%,1525,1.54,1.1,54%,3.5,54,78.50%,86.10%,97.10%,99%,49.45%,49.53%,48.75%,0.00%
ASIA,111,49,1%,67.30%,2050,1.96,0.7,73%,2.7,5.3,85.70%,91.40%,63.30%,93%,52.58%,49.79%,49.79%,0.00%
1 TOTAL Battles % Battles WR DPB KPB Spot Top tier DR KDR Hit rate Pen rate Surv% Share live Player WR Allies WR Enemies WR No stats
2 Total 6942 100% 71.80% 2058 1.86 1.4 64% 2.3 5.4 86.10% 90.80% 65.30% 90% 57.08% 50.15% 50.12% 0.20%
3
4 Result Battles % Battles WR DPB KPB Spot Top tier DR KDR Hit rate Pen rate Surv% Share live Player WR Allies WR Enemies WR No stats
5 Loss 1959 28% 0.00% 1715 1.12 1.3 61% 1.3 1.3 84.70% 88.60% 13.40% 78% 56.47% 49.56% 50.92% 0.10%
6 Win 4983 72% 100.00% 2193 2.16 1.4 65% 3 15.1 86.50% 91.40% 85.70% 95% 57.32% 50.39% 49.80% 0.20%
7
8 Battle Type Battles % Battles WR DPB KPB Spot Top tier DR KDR Hit rate Pen rate Surv% Share live Player WR Allies WR Enemies WR No stats
9 Encounter 4652 67% 73.00% 1969 1.98 1.4 67% 2.5 6 85.70% 90.70% 66.80% 91% 57.43% 50.41% 50.33% 0.30%
10 Supremacy 2290 33% 69.30% 2238 1.63 1.2 60% 2 4.3 87.10% 91.20% 62.20% 89% 56.37% 49.63% 49.69% 0.00%
11
12 Tier Battles % Battles WR DPB KPB Spot Top tier DR KDR Hit rate Pen rate Surv% Share live Player WR Allies WR Enemies WR No stats
13 Bottom tier 2480 36% 69.50% 1750 1.53 1.2 0% 2.2 3.9 85.40% 89.20% 60.70% 88% 56.91% 50.13% 49.99% 0.10%
14 Top tier 4462 64% 73.10% 2229 2.05 1.5 100% 2.4 6.4 86.50% 91.60% 67.90% 91% 57.18% 50.16% 50.19% 0.20%
15
16 Tank Tier Battles % Battles WR DPB KPB Spot Top tier DR KDR Hit rate Pen rate Surv% Share live Player WR Allies WR Enemies WR No stats
17 1 89 1% 80.90% 678 1.89 1.9 40% 3 7.6 86.20% 91.80% 75.30% 95% 55.40% 48.80% 48.40% 0.00%
18 2 180 3% 77.80% 970 2.64 1.6 73% 3.3 9.1 82.90% 90.60% 71.10% 93% 56.04% 49.36% 49.46% 0.90%
19 3 540 8% 75.70% 1099 2.15 1.4 36% 3.1 7 83.60% 90.00% 69.10% 93% 57.55% 51.15% 50.16% 1.90%
20 4 628 9% 75.20% 1256 2.21 1.3 73% 3.1 7.4 85.00% 91.60% 70.20% 94% 55.72% 51.76% 51.65% 0.00%
21 5 626 9% 80.20% 1503 2.29 1.3 71% 3.2 8.3 86.90% 89.50% 72.20% 93% 55.69% 50.38% 49.95% 0.00%
22 6 1064 15% 74.20% 1801 1.97 1.4 62% 2.4 5.8 86.70% 92.20% 65.90% 90% 56.82% 49.24% 49.31% 0.00%
23 7 1141 16% 71.80% 2143 1.69 1.3 50% 2.5 4.9 85.70% 90.10% 65.80% 90% 58.48% 49.62% 49.60% 0.00%
24 8 1222 18% 68.20% 2371 1.59 1.4 67% 2.1 4.2 87.40% 90.90% 61.80% 89% 56.84% 49.80% 49.99% 0.00%
25 9 598 9% 64.70% 2806 1.61 1.2 49% 2.1 4 89.10% 91.90% 59.50% 87% 56.58% 50.13% 50.32% 0.00%
26 10 854 12% 65.60% 3270 1.62 1.5 100% 2 4 88.30% 90.20% 59.60% 88% 58.37% 50.83% 51.16% 0.00%
27
28 Tank Class Battles % Battles WR DPB KPB Spot Top tier DR KDR Hit rate Pen rate Surv% Share live Player WR Allies WR Enemies WR No stats
29 Light Tank 1337 19% 74.40% 1589 1.88 1.9 59% 2.3 5.9 83.70% 89.20% 68.40% 90% 57.15% 50.20% 49.90% 0.70%
30 Medium Tank 1957 28% 73.10% 2181 1.99 1.7 67% 2.4 5.9 88.20% 91.40% 66.40% 90% 57.23% 50.26% 50.12% 0.10%
31 Heavy Tank 2032 29% 70.00% 2180 1.75 1.2 70% 1.9 5 87.20% 90.70% 65.20% 91% 56.72% 50.16% 50.23% 0.00%
32 Tank Destroyer 1616 23% 70.30% 2144 1.84 0.7 59% 3 4.8 85.10% 92.60% 61.50% 91% 57.31% 49.98% 50.16% 0.00%
33
34 Player WR Battles % Battles WR DPB KPB Spot Top tier DR KDR Hit rate Pen rate Surv% Share live Player WR Allies WR Enemies WR No stats
35 35 - 45% 80 1% 43.80% 1255 0.93 1 55% 1.1 1.5 84.00% 87.10% 37.50% 82% 44.52% 49.84% 51.14% 0.00%
36 45 - 50% 584 8% 69.20% 1397 1.46 1.1 62% 1.8 3.8 81.20% 87.40% 61.30% 89% 47.86% 49.84% 49.86% 0.00%
37 50 - 55% 1970 28% 69.00% 1861 1.73 1.3 63% 2.1 4.3 85.40% 90.20% 60.20% 88% 53.06% 50.10% 49.99% 0.00%
38 55 - 65% 3677 53% 73.50% 2249 2.01 1.4 66% 2.5 6.3 87.50% 91.50% 68.10% 92% 58.78% 50.13% 50.14% 0.00%
39 65 - % 631 9% 76.40% 2274 1.95 1.4 61% 2.8 7 84.60% 91.40% 72.10% 91% 69.92% 50.79% 50.51% 1.90%
40
41 Player Hit Rate Battles % Battles WR DPB KPB Spot Top tier DR KDR Hit rate Pen rate Surv% Share live Player WR Allies WR Enemies WR No stats
42 0 - 25% 32 0% 43.80% 1 0 1.6 47% 0 0 0.00% inf% 25.00% 57% 54.55% 50.15% 51.14% 0.00%
43 25 - 50% 47 1% 44.70% 693 0.34 1.3 51% 0.6 0.5 38.70% 90.50% 36.20% 77% 55.05% 50.14% 51.15% 0.00%
44 50 - 60% 172 2% 56.40% 876 0.6 1.2 58% 0.8 1.1 54.70% 87.80% 44.80% 81% 56.38% 50.61% 50.48% 0.00%
45 60 - 70% 461 7% 58.80% 1254 1.08 1.2 61% 1.4 2.4 65.40% 87.70% 54.20% 87% 56.29% 50.18% 50.50% 0.00%
46 70 - 80% 941 14% 70.50% 1691 1.59 1.3 63% 2 4.6 75.50% 89.10% 65.70% 91% 56.92% 50.36% 50.24% 0.00%
47 80 - 90% 2091 30% 74.00% 2071 1.98 1.4 66% 2.5 6.3 85.00% 90.60% 68.50% 93% 57.00% 50.10% 50.08% 0.10%
48 90 - 95% 1258 18% 81.00% 2561 2.52 1.5 66% 3.3 11 92.30% 92.00% 77.10% 96% 57.73% 50.08% 49.85% 0.30%
49 95 - % 1940 28% 69.60% 2259 1.82 1.4 64% 2.2 4.5 99.00% 91.70% 59.80% 86% 57.17% 50.12% 50.11% 0.40%
50
51 Player Pen Rate Battles % Battles WR DPB KPB Spot Top tier DR KDR Hit rate Pen rate Surv% Share live Player WR Allies WR Enemies WR No stats
52 0 - 25% 49 1% 38.80% 6 0 1.5 39% 0 0 45.80% 10.50% 22.40% 56% 55.11% 49.96% 50.47% 0.00%
53 25 - 50% 43 1% 30.20% 447 0.19 1.7 44% 0.3 0.2 82.30% 38.40% 20.90% 66% 55.41% 50.75% 51.06% 0.00%
54 50 - 60% 110 2% 41.80% 642 0.27 1.5 60% 0.5 0.4 77.50% 53.10% 32.70% 70% 54.44% 50.46% 50.61% 0.00%
55 60 - 70% 210 3% 52.40% 1085 0.63 1.3 56% 0.9 1.1 81.00% 65.10% 40.00% 79% 55.71% 50.58% 50.39% 0.00%
56 70 - 80% 469 7% 65.00% 1669 1.33 1.4 61% 1.6 3.1 83.50% 75.40% 57.60% 89% 56.39% 50.24% 50.30% 0.00%
57 80 - 90% 1544 22% 71.60% 2076 1.86 1.4 61% 2.3 5.5 86.00% 85.30% 66.30% 92% 57.35% 50.17% 50.03% 0.20%
58 90 - 95% 1210 17% 79.30% 2509 2.53 1.5 66% 3.3 11 87.80% 92.40% 77.00% 96% 57.57% 50.00% 50.09% 0.20%
59 95 - % 3307 48% 73.30% 2100 1.88 1.3 67% 2.4 5.5 86.30% 99.30% 65.60% 90% 57.11% 50.14% 50.10% 0.20%
60
61 Server account_id_anon Battles % Battles WR DPB KPB Spot Top tier DR KDR Hit rate Pen rate Surv% Share live Player WR Allies WR Enemies WR No stats
62 RU 1 33 0% 78.80% 3112 1.91 1.6 67% 2.5 7.9 89.60% 90.20% 75.80% 87% 71.43% 50.74% 51.07% 0.00%
63 RU 2 23 0% 87.00% 3525 2.78 1.7 74% 4.3 32 90.40% 94.40% 91.30% 100% 59.39% 48.07% 48.75% 0.00%
64 RU 3 81 1% 66.70% 1927 1.47 1 75% 1.9 3.1 82.30% 89.60% 53.10% 86% 69.59% 50.23% 50.85% 0.00%
65 EU 4 26 0% 80.80% 4082 2.62 1.2 62% 4.1 17 91.10% 93.80% 84.60% 98% 53.92% 48.75% 49.31% 0.00%
66 EU 5 79 1% 59.50% 1920 0.97 1.4 75% 1.4 2 80.20% 87.10% 50.60% 84% 59.06% 50.12% 51.22% 0.00%
67 EU 6 92 1% 60.90% 1685 0.99 1.5 65% 1.3 1.8 87.80% 88.50% 45.70% 83% 57.79% 50.30% 50.77% 0.00%
68 EU 7 50 1% 78.00% 2787 2.92 1.9 52% 4 16.2 90.60% 92.70% 82.00% 99% 64.87% 50.49% 50.50% 0.00%
69 EU 8 69 1% 60.90% 1695 1.48 1.9 55% 1.5 3 87.80% 92.10% 50.70% 77% 54.73% 50.06% 49.81% 0.10%
70 EU 9 33 0% 63.60% 1529 1.55 1.9 64% 2 3.6 82.10% 91.30% 57.60% 85% 52.48% 49.85% 50.92% 0.00%
71 EU 10 22 0% 90.90% 2990 3.82 1 59% 3.6 42 85.60% 93.00% 90.90% 100% 57.27% 48.97% 49.67% 0.00%
72 EU 11 35 1% 62.90% 1197 0.97 1.1 66% 1.3 2 85.20% 88.10% 51.40% 81% 55.89% 50.71% 49.97% 0.00%
73 EU 12 20 0% 95.00% 4854 3.95 1.2 25% 4.9 79 94.40% 95.60% 95.00% 99% 56.71% 49.15% 49.81% 0.00%
74 EU 13 80 1% 73.80% 2228 2.65 1.4 69% 3.3 8.5 92.10% 92.70% 68.80% 95% 58.83% 49.43% 49.21% 0.00%
75 EU 14 30 0% 83.30% 2167 3.93 2 63% 4.2 19.7 87.90% 92.00% 80.00% 98% 62.43% 50.39% 49.69% 0.00%
76 EU 15 305 4% 55.40% 2126 1.21 1.3 78% 1.6 2.4 85.80% 90.90% 49.50% 87% 58.91% 50.46% 50.47% 0.00%
77 EU 16 49 1% 69.40% 2362 2.47 1.5 43% 4 7.1 90.20% 93.30% 65.30% 94% 62.94% 49.43% 49.50% 0.00%
78 EU 17 22 0% 86.40% 1898 4.41 1.4 95% 4.8 48.5 90.60% 94.80% 90.90% 100% 57.61% 48.11% 49.25% 0.00%
79 EU 18 96 1% 76.00% 1764 2.19 0.9 67% 3.2 7.2 89.40% 95.00% 69.80% 94% 56.39% 50.00% 49.58% 0.00%
80 EU 19 23 0% 95.70% 1997 2.09 1.3 65% 3.8 16 90.70% 94.20% 87.00% 98% 70.96% 48.51% 49.66% 0.00%
81 EU 20 256 4% 54.30% 1081 0.58 1.5 55% 0.9 0.8 81.10% 83.80% 28.10% 68% 52.29% 50.31% 49.81% 0.00%
82 EU 21 73 1% 82.20% 1025 1.9 1.5 55% 2.7 6.3 84.20% 92.30% 69.90% 94% 58.95% 51.61% 50.45% 0.00%
83 EU 22 53 1% 79.20% 1415 1.98 0.9 47% 3.2 7 87.40% 90.40% 71.70% 95% 57.15% 50.10% 49.76% 0.00%
84 EU 23 70 1% 81.40% 2224 2.5 1.8 47% 4 9.7 89.20% 90.20% 74.30% 96% 61.99% 50.85% 50.17% 0.00%
85 EU 24 83 1% 73.50% 3049 2.1 2 73% 3.2 7.2 89.60% 91.70% 71.10% 96% 60.48% 49.78% 49.51% 0.00%
86 EU 25 127 2% 68.50% 1609 1.86 1.3 52% 2.4 4.5 83.40% 89.50% 59.10% 89% 54.64% 49.76% 49.35% 0.00%
87 EU 26 52 1% 80.80% 2669 2.62 2.2 50% 3 11.3 87.80% 91.00% 76.90% 95% 62.66% 49.60% 49.65% 0.20%
88 EU 27 30 0% 86.70% 4246 3.17 1.4 57% 3.6 23.8 88.10% 95.30% 86.70% 99% 56.38% 49.10% 49.54% 0.00%
89 EU 28 24 0% 83.30% 2823 2.96 1.8 62% 4.9 17.8 89.30% 91.20% 83.30% 98% 64.91% 50.25% 51.06% 0.00%
90 EU 29 29 0% 75.90% 1750 1.62 1.3 59% 2.2 3.6 88.10% 93.60% 55.20% 91% 54.39% 49.78% 49.34% 0.00%
91 EU 30 26 0% 92.30% 2631 3.12 1.8 69% 3.1 27 92.90% 93.80% 88.50% 97% 57.57% 49.93% 49.96% 0.00%
92 EU 31 31 0% 90.30% 2126 2.16 1.2 61% 3.4 13.4 85.20% 91.20% 83.90% 98% 52.31% 50.24% 49.30% 0.00%
93 EU 32 44 1% 77.30% 1848 2.91 0.7 77% 3.4 14.2 85.40% 91.70% 79.50% 96% 50.22% 50.67% 50.91% 0.00%
94 EU 33 74 1% 94.60% 1811 3.24 1.5 59% 4.1 48 86.80% 86.30% 93.20% 99% 56.08% 49.98% 49.17% 0.00%
95 EU 34 158 2% 77.80% 1290 1.66 0.9 53% 2.4 4.4 78.40% 90.70% 62.70% 93% 49.45% 49.80% 50.05% 0.00%
96 EU 35 21 0% 61.90% 1796 1.19 1.4 86% 1.5 2.5 77.00% 86.60% 52.40% 82% 48.99% 50.98% 50.38% 0.00%
97 EU 36 120 2% 55.80% 1730 1.1 1.6 68% 1.3 2.2 85.30% 85.90% 49.20% 83% 60.61% 50.43% 49.95% 0.10%
98 EU 37 25 0% 88.00% 5110 3.6 1.5 96% 3.7 45 94.90% 91.70% 92.00% 100% 60.44% 50.29% 51.16% 0.00%
99 EU 38 350 5% 62.00% 1159 1.09 1.3 63% 1.2 2.3 83.10% 89.70% 52.30% 84% 52.65% 50.37% 50.42% 0.00%
100 EU 39 25 0% 84.00% 4965 2.72 1.5 84% 3.6 13.6 89.40% 91.30% 80.00% 97% 54.95% 49.64% 50.59% 0.00%
101 EU 40 22 0% 90.90% 4394 3.09 2.3 64% 4.2 34 92.60% 90.30% 90.90% 98% 52.49% 50.46% 50.63% 0.00%
102 EU 41 57 1% 63.20% 3078 1.63 2.3 96% 2 3.3 85.40% 86.30% 50.90% 85% 60.62% 51.59% 52.10% 0.00%
103 EU 42 22 0% 68.20% 2270 0.95 1.3 91% 1.6 1.9 85.20% 88.90% 50.00% 85% 59.46% 50.97% 50.61% 0.00%
104 EU 43 45 1% 64.40% 1482 0.93 1.6 62% 1.2 1.8 83.00% 91.60% 48.90% 79% 50.40% 51.15% 50.79% 0.00%
105 EU 44 56 1% 96.40% 1927 2.79 1.6 77% 5.4 31.2 85.60% 90.20% 91.10% 98% 54.95% 49.96% 49.62% 0.00%
106 EU 45 28 0% 96.40% 4659 3.5 1.4 64% 3.8 49 89.00% 91.70% 92.90% 100% 54.81% 49.56% 49.85% 0.00%
107 EU 46 134 2% 70.90% 1291 1.99 1 49% 3.3 5.6 82.90% 91.80% 64.20% 94% 55.71% 51.75% 51.64% 0.00%
108 EU 47 51 1% 72.50% 1119 1.43 0.9 78% 1.9 3.8 89.20% 89.20% 62.70% 89% 52.58% 52.04% 52.06% 0.00%
109 EU 48 45 1% 86.70% 2756 2.71 2.2 64% 4.1 12.2 90.10% 91.50% 77.80% 97% 63.68% 49.88% 49.92% 0.00%
110 EU 49 35 1% 97.10% 5932 3.57 1.1 94% 5.7 41.7 88.10% 96.30% 91.40% 99% 70.46% 49.51% 50.42% 0.00%
111 EU 50 186 3% 60.80% 1169 1.02 1.2 49% 1.2 2.1 80.20% 89.20% 52.20% 84% 56.65% 50.14% 50.07% 0.00%
112 EU 51 25 0% 92.00% 2194 4.68 2.3 60% 4.9 117 86.20% 92.00% 96.00% 100% 70.74% 52.26% 51.76% 0.00%
113 EU 52 93 1% 62.40% 1444 1.1 1.1 54% 1.7 2.9 88.00% 92.30% 62.40% 85% 72.96% 49.89% 50.29% 0.00%
114 EU 53 25 0% 80.00% 2374 2.8 1.5 68% 3.5 11.7 86.80% 90.50% 76.00% 95% 60.96% 49.42% 48.68% 0.00%
115 EU 54 30 0% 53.30% 2384 1.27 1.7 73% 1.6 2.5 85.00% 86.50% 50.00% 81% 54.58% 49.33% 50.27% 0.00%
116 EU 55 29 0% 79.30% 2219 1.93 1.6 69% 2.1 5.1 88.30% 86.10% 62.10% 89% 47.58% 50.43% 49.39% 0.00%
117 EU 56 73 1% 69.90% 2036 2.33 0.9 64% 3.2 8.5 90.80% 94.00% 72.60% 95% 52.47% 49.24% 49.05% 0.10%
118 EU 57 26 0% 96.20% 949 3.08 2 50% 3.2 26.7 83.20% 87.10% 88.50% 97% 46.64% 49.42% 48.36% 0.00%
119 EU 58 20 0% 65.00% 344 0.45 0.9 45% 0.7 1.3 75.50% 73.80% 65.00% 83% 45.36% 49.30% 49.03% 0.00%
120 EU 59 149 2% 34.90% 1105 0.8 1.1 60% 0.9 1.1 82.80% 85.80% 28.90% 78% 45.21% 50.08% 51.28% 0.00%
121 EU 60 22 0% 63.60% 1108 0.91 1 91% 1.3 1.4 78.70% 85.00% 36.40% 81% 54.54% 49.66% 49.03% 0.00%
122 EU 61 36 1% 94.40% 2794 3.81 2.5 83% 6.2 45.7 85.30% 92.10% 91.70% 100% 63.28% 50.37% 50.28% 0.00%
123 EU 62 32 0% 31.20% 1786 1.19 0.9 75% 1.8 2 90.60% 91.90% 40.60% 88% 61.60% 49.13% 50.35% 0.00%
124 EU 63 21 0% 85.70% 2476 3.33 2 76% 4.8 35 91.50% 95.70% 90.50% 99% 53.93% 50.29% 49.74% 0.00%
125 NA 64 23 0% 91.30% 2371 3.57 0.9 70% 4.8 20.5 86.10% 92.50% 82.60% 99% 58.19% 49.00% 50.44% 0.30%
126 NA 65 25 0% 96.00% 4281 2.56 1.8 72% 4.1 64 90.20% 91.40% 96.00% 100% 62.10% 51.41% 50.28% 0.00%
127 NA 66 238 3% 76.10% 2183 1.56 1.5 50% 2.8 5.7 79.70% 89.90% 72.70% 92% 68.48% 50.75% 50.57% 0.00%
128 NA 67 56 1% 73.20% 2022 1.88 1.3 68% 2.5 6.6 85.20% 90.40% 71.40% 93% 55.31% 49.88% 49.73% 0.10%
129 NA 68 25 0% 92.00% 6141 3.36 1.2 100% 3.5 28 92.20% 93.80% 88.00% 99% 62.64% 49.81% 50.96% 0.00%
130 NA 69 44 1% 77.30% 4178 1.93 1.5 77% 3 12.1 92.10% 91.60% 84.10% 98% 53.67% 50.20% 50.23% 0.00%
131 NA 70 26 0% 96.20% 3412 3.46 1.8 69% 3.6 90 92.20% 93.90% 96.20% 100% 65.85% 48.95% 49.25% 0.00%
132 NA 71 58 1% 77.60% 1642 1.93 0.9 60% 2.2 5.6 86.00% 94.60% 65.50% 87% 46.03% 49.73% 50.08% 0.00%
133 NA 72 197 3% 78.20% 2416 2.37 1.2 64% 3.3 10.8 86.30% 92.80% 78.20% 97% 56.68% 49.22% 49.50% 0.00%
134 NA 73 23 0% 60.90% 3932 1.91 2 87% 3 4.9 89.50% 90.70% 60.90% 89% 60.65% 48.75% 50.51% 0.00%
135 NA 74 42 1% 78.60% 1431 2.45 0.7 36% 2.2 6.9 84.50% 89.30% 64.30% 90% 50.81% 49.26% 49.33% 0.00%
136 NA 75 21 0% 81.00% 3748 3.29 1.3 57% 4 17.2 91.90% 92.50% 81.00% 100% 61.77% 48.23% 48.98% 0.00%
137 NA 76 34 0% 88.20% 2707 2.59 1.4 68% 3 44 84.50% 90.50% 94.10% 96% 55.79% 50.34% 49.42% 0.00%
138 NA 77 115 2% 74.80% 2171 2.19 1.4 74% 2.9 8.4 89.00% 91.40% 73.90% 95% 59.53% 49.65% 49.88% 0.00%
139 NA 78 23 0% 65.20% 1958 1.96 0.5 61% 2.3 5.6 89.80% 93.30% 65.20% 92% 62.10% 50.31% 49.85% 0.00%
140 NA 79 218 3% 74.30% 1860 2.16 1.5 65% 2.6 7.2 85.90% 91.60% 70.20% 95% 53.76% 50.11% 49.84% 0.00%
141 NA 80 35 1% 57.10% 3142 1.71 1.9 80% 2.3 3.2 90.00% 93.10% 45.70% 86% 56.23% 50.16% 51.49% 0.00%
142 NA 81 32 0% 90.60% 3407 2.62 1.2 62% 3.6 16.8 85.80% 91.90% 84.40% 97% 54.91% 49.20% 49.43% 0.00%
143 NA 82 20 0% 90.00% 4472 3.4 2.2 75% 4.1 34 86.20% 83.10% 90.00% 100% 50.16% 50.67% 50.02% 0.00%
144 NA 83 51 1% 72.50% 1023 2.08 1.1 76% 2.2 5.6 88.30% 93.20% 62.70% 91% 73.85% 56.05% 50.69% 23.20%
145 NA 84 47 1% 80.90% 3820 2.45 1.4 85% 3.7 12.8 93.20% 94.90% 80.90% 98% 61.01% 50.73% 50.39% 0.00%
146 NA 85 71 1% 91.50% 3159 2.73 0.9 65% 3.9 27.7 89.40% 92.40% 90.10% 99% 55.39% 49.64% 50.01% 0.00%
147 NA 86 28 0% 85.70% 4249 2.46 1.3 79% 3.1 23 91.90% 93.70% 89.30% 95% 61.07% 50.13% 50.15% 0.00%
148 NA 87 24 0% 75.00% 3048 2.17 1.9 75% 2.7 10.4 85.40% 90.00% 79.20% 98% 55.74% 49.79% 50.05% 0.00%
149 NA 88 34 0% 67.60% 3317 2.21 2.1 65% 3.6 6.8 90.50% 91.30% 67.60% 96% 61.83% 49.97% 49.88% 0.00%
150 NA 89 23 0% 30.40% 1399 0.52 1.3 91% 0.9 0.8 87.30% 85.40% 30.40% 71% 49.58% 50.38% 51.69% 0.00%
151 NA 90 20 0% 75.00% 1305 0.6 1.4 60% 1.1 1.7 88.10% 80.10% 65.00% 91% 48.23% 49.76% 49.40% 0.00%
152 NA 91 24 0% 79.20% 2554 2.96 1.2 50% 5.6 17.8 93.30% 95.50% 83.30% 98% 58.79% 50.82% 51.10% 0.00%
153 NA 92 48 1% 56.20% 1707 0.69 0.7 92% 0.8 1.4 81.30% 86.80% 52.10% 87% 55.85% 53.43% 53.97% 0.00%
154 NA 93 130 2% 62.30% 1912 1.31 1.3 70% 1.3 2.9 89.00% 91.70% 55.40% 86% 59.63% 49.95% 50.11% 0.00%
155 NA 94 35 1% 77.10% 3875 2.74 1.8 57% 3.6 12 89.60% 94.40% 77.10% 95% 59.73% 49.60% 50.04% 0.00%
156 NA 95 23 0% 73.90% 2688 3.17 1 74% 3.4 14.6 92.50% 93.20% 78.30% 96% 51.21% 49.86% 50.33% 0.00%
157 NA 96 26 0% 61.50% 1796 1.19 1.2 31% 1.6 2.8 75.60% 84.20% 57.70% 91% 54.00% 50.02% 50.03% 0.00%
158 NA 97 21 0% 90.50% 1869 2.52 2.3 76% 3.2 17.7 85.40% 89.60% 85.70% 96% 56.43% 49.38% 49.01% 0.00%
159 NA 98 101 1% 71.30% 1499 2 0.7 58% 2.7 5.3 83.30% 91.50% 62.40% 93% 52.60% 49.80% 49.63% 0.10%
160 NA 99 20 0% 60.00% 1368 1 0.9 45% 1.4 2.9 83.50% 87.90% 65.00% 84% 54.73% 50.49% 50.26% 0.00%
161 NA 100 24 0% 79.20% 1998 2.54 1.6 75% 3.4 20.3 85.30% 83.70% 87.50% 98% 53.43% 50.95% 50.42% 0.30%
162 NA 101 26 0% 42.30% 1170 0.77 1.7 73% 1.3 1.2 75.50% 86.50% 34.60% 81% 46.59% 49.31% 50.13% 0.00%
163 NA 102 26 0% 53.80% 1013 0.85 0.8 62% 1.1 1.2 74.20% 82.40% 26.90% 83% 52.75% 49.08% 49.42% 0.00%
164 NA 103 23 0% 91.30% 3980 3 1.4 83% 3.1 34.5 86.00% 90.80% 91.30% 97% 63.72% 49.86% 49.82% 0.00%
165 NA 104 57 1% 71.90% 1694 1.49 0.6 74% 2.8 4.7 82.80% 86.80% 68.40% 92% 46.26% 49.48% 48.84% 0.00%
166 ASIA 105 330 5% 82.40% 2195 2.01 1.7 63% 2.7 7.5 89.80% 92.70% 73.00% 94% 57.98% 49.95% 49.71% 0.00%
167 ASIA 106 132 2% 77.30% 1268 1.31 0.8 58% 2.2 3.5 82.20% 92.40% 62.10% 85% 62.78% 49.79% 50.26% 0.00%
168 ASIA 107 21 0% 90.50% 3749 3.67 1.8 81% 4.1 38.5 90.70% 93.70% 90.50% 97% 53.77% 49.37% 50.06% 0.00%
169 ASIA 108 35 1% 85.70% 4501 2.6 1.6 74% 4 15.2 89.10% 91.20% 82.90% 99% 54.47% 49.39% 49.24% 0.00%
170 ASIA 109 67 1% 73.10% 1278 1.7 1.5 54% 2.8 5.7 83.80% 88.00% 70.10% 93% 55.23% 51.01% 50.11% 0.10%
171 ASIA 110 70 1% 91.40% 1525 1.54 1.1 54% 3.5 54 78.50% 86.10% 97.10% 99% 49.45% 49.53% 48.75% 0.00%
172 ASIA 111 49 1% 67.30% 2050 1.96 0.7 73% 2.7 5.3 85.70% 91.40% 63.30% 93% 52.58% 49.79% 49.79% 0.00%
+4127 -1
View File
File diff suppressed because it is too large. Load diff
+131 -234
View File
@@ -1,15 +1,14 @@
#!/usr/bin/env python3 #!/usr/bin/env python3.8
## PYTHON VERSION MUST BE 3.7 OR HIGHER
import json, argparse, sys, os, io, asyncio, aiofiles, aioconsole import json, argparse, inspect, sys, os, io, base64, aiohttp, urllib, asyncio, aiofiles, aioconsole
import logging, re, configparser, zipfile import logging, re, concurrent.futures, configparser, motor.motor_asyncio, ssl, zipfile
import blitzutils1 as bu import blitzutils as bu
from blitzutils1 import WG from blitzutils import WG
from blitzutils1 import WoTinspector from blitzutils import WoTinspector
logging.getLogger("asyncio").setLevel(logging.DEBUG) logging.getLogger("asyncio").setLevel(logging.DEBUG)
FILE_CONFIG = "blitzstats.ini" FILE_CONFIG = 'blitzstats.ini'
# DB_C_REPLAYS = 'Replays' # DB_C_REPLAYS = 'Replays'
DEBUG = False DEBUG = False
@@ -19,20 +18,19 @@ MAX_RETRIES = 3
REPLAY_N = 0 REPLAY_N = 0
SKIPPED_N = 0 SKIPPED_N = 0
ERROR_N = 0 ERROR_N = 0
WIurl = "https://wotinspector.com/api/replay/upload?" WIurl='https://wotinspector.com/api/replay/upload?'
WG_appID = "81381d3f45fa4aa75b78a7198eb216ad" WG_appID = '81381d3f45fa4aa75b78a7198eb216ad'
wg: WG | None = None wg = None
wi: WoTinspector | None = None wi = None
async def main(argv):
async def main(argv) -> int:
global wg, wi global wg, wi
current_dir = os.getcwd() current_dir = os.getcwd()
# set the directory for the script # set the directory for the script
os.chdir(os.path.dirname(sys.argv[0])) os.chdir(os.path.dirname(sys.argv[0]))
# options defaults # options defaults
OPT_WORKERS_N = 2 OPT_WORKERS_N = 5
WG_ID = None WG_ID = None
WG_ACCOUNT = None # format: nick@server, where server is either 'eu', 'ru', 'na', 'asia' or 'china'. WG_ACCOUNT = None # format: nick@server, where server is either 'eu', 'ru', 'na', 'asia' or 'china'.
# China is not supported since WG API stats are not available there # China is not supported since WG API stats are not available there
@@ -41,101 +39,60 @@ async def main(argv) -> int:
try: try:
## Read config ## Read config
if os.path.isfile(FILE_CONFIG): if os.path.isfile(FILE_CONFIG):
bu.debug("Reading config file: " + FILE_CONFIG) bu.debug('Reading config file: ' + FILE_CONFIG)
config = configparser.ConfigParser() config = configparser.ConfigParser()
config.read(FILE_CONFIG) config.read(FILE_CONFIG)
try:
if 'UPLOADER' in config.sections():
configUploader = config['UPLOADER']
OPT_WORKERS_N = configUploader.getint('opt_workers', OPT_WORKERS_N)
except (KeyError, configparser.NoSectionError) as err:
bu.error(exception=err)
try: try:
if "WG" in config.sections(): if 'WG' in config.sections():
configWG = config["WG"] configWG = config['WG']
# WG account id of the uploader: # WG account id of the uploader:
# # Find it here: https://developers.wargaming.net/reference/all/wotb/account/list/ # # Find it here: https://developers.wargaming.net/reference/all/wotb/account/list/
WG_ID = configWG.getint("wg_id", WG_ID) WG_ID = configWG.getint('wg_id', WG_ID)
WG_ACCOUNT = configWG.get("wg_account", WG_ACCOUNT) WG_ACCOUNT = configWG.get('wg_account', WG_ACCOUNT)
## WG API Rules limit 10 request / sec. Higher rate of requests will return errors ==> extra delay ## WG API Rules limit 10 request / sec. Higher rate of requests will return errors ==> extra delay
WG_RATE_LIMIT = configWG.getint("wg_rate_limit", WG_RATE_LIMIT) WG_RATE_LIMIT = configWG.getint('wg_rate_limit', WG_RATE_LIMIT)
except (KeyError, configparser.NoSectionError) as err: except (KeyError, configparser.NoSectionError) as err:
bu.error(exception=err) bu.error(exception=err)
except Exception as err: except Exception as err:
bu.error(exception=err) bu.error(exception=err)
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(description='Post replays(s) to WoTinspector.com and retrieve replay data as JSON')
description="Post replays(s) to WoTinspector.com and retrieve replay data as JSON" parser.add_argument('-id', dest='accountID', type=int, default=WG_ID, help='WG account_id')
) parser.add_argument('-a', '--account', dest='account', type=str, default=WG_ACCOUNT, help='Uploader\'s WG account name. Format: ACCOUNT_NAME@SERVER')
parser.add_argument( parser.add_argument('-t','--title', type=str, default=None, help='Title for replays. Use "NN" for continous numbering. Default is automatic naming')
"-id", dest="accountID", type=int, default=WG_ID, help="WG account_id" parser.add_argument('-p', '--private', dest="private", action='store_true', default=False, help='Set replays private on WoTinspector.com')
) parser.add_argument('--tankopedia', type=str, default='tanks.json', help='JSON file to read Tankopedia from. Default: "tanks.json"')
parser.add_argument( parser.add_argument('--mapfile', type=str, default='maps.json', help='JSON file to read Blitz map names from. Default: "maps.json"')
"-a", parser.add_argument('-d', '--debug', action='store_true', default=False, help='Debug mode')
"--account", parser.add_argument('-v', '--verbose', action='store_true', default=False, help='Verbose mode')
dest="account", parser.add_argument('-s', '--silent', action='store_true', default=False, help='Silent mode')
type=str, parser.add_argument('files', metavar='FILE1 [FILE2 ...]', type=str, nargs='+', help='Files to read. Use \'-\' for STDIN"')
default=WG_ACCOUNT,
help="Uploader's WG account name. Format: ACCOUNT_NAME@SERVER",
)
parser.add_argument(
"-t",
"--title",
type=str,
default=None,
help='Title for replays. Use "NN" for continous numbering. Default is automatic naming',
)
parser.add_argument(
"-p",
"--private",
dest="private",
action="store_true",
default=False,
help="Set replays private on WoTinspector.com",
)
parser.add_argument(
"--tankopedia",
type=str,
default="tanks.json",
help='JSON file to read Tankopedia from. Default: "tanks.json"',
)
parser.add_argument(
"--mapfile",
type=str,
default="maps.json",
help='JSON file to read Blitz map names from. Default: "maps.json"',
)
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(
"-s", "--silent", action="store_true", default=False, help="Silent mode"
)
parser.add_argument(
"files",
metavar="FILE1 [FILE2 ...]",
type=str,
nargs="+",
help="Files to read. Use '-' for STDIN\"",
)
args = parser.parse_args() args = parser.parse_args()
bu.set_verbose(args.verbose) bu.set_verbose(args.verbose)
bu.set_log_level(args.silent, args.verbose, args.debug) bu.set_log_level(args.silent, args.verbose, args.debug)
wg = WG(WG_appID, args.tankopedia, args.mapfile) wg = WG(WG_appID, args.tankopedia, args.mapfile)
wi = WoTinspector() wi = WoTinspector(rate_limit=WG_RATE_LIMIT)
if args.account is not None: if args.account != None:
args.accountID = await wg.get_account_id(args.account) args.accountID = await wg.get_account_id(args.account)
bu.debug("WG account_id: " + str(args.accountID)) bu.debug('WG account_id: ' + str(args.accountID))
if args.accountID is None: if args.accountID == None:
args.accountID = 0 args.accountID = 0
try: try:
queue: asyncio.Queue = asyncio.Queue() queue = asyncio.Queue()
# rebase file arguments due to moving the working directory to the script location # rebase file arguments due to moving the working directory to the script location
bu.verbose_std("replays.wotinspector.com rate limits replays to 6 / minute")
args.files = bu.rebase_file_args(current_dir, args.files) args.files = bu.rebase_file_args(current_dir, args.files)
tasks = [] tasks = []
@@ -143,81 +100,66 @@ async def main(argv) -> int:
tasks.append(asyncio.create_task(mkReplayQ(queue, args.files, args.title))) tasks.append(asyncio.create_task(mkReplayQ(queue, args.files, args.title)))
# Start tasks to process the Queue # Start tasks to process the Queue
for i in range(OPT_WORKERS_N): for i in range(OPT_WORKERS_N):
tasks.append( tasks.append(asyncio.create_task(replayWorker(queue, i, args.accountID, args.private)))
asyncio.create_task( bu.debug('Task ' + str(i) + ' started')
replayWorker(queue, i, args.accountID, args.private)
)
)
bu.debug("Task " + str(i) + " started")
bu.debug("Waiting for the replay scanner to finish") bu.debug('Waiting for the replay scanner to finish')
await asyncio.wait([tasks[0]]) await asyncio.wait([tasks[0]])
bu.debug("Scanner finished. Waiting for workers to finish queue") bu.debug('Scanner finished. Waiting for workers to finish queue')
await queue.join() await queue.join()
bu.debug("Cancelling workers") bu.debug('Cancelling workers')
for task in tasks: for task in tasks:
task.cancel() task.cancel()
bu.debug("Waiting for workers to cancel") bu.debug('Waiting for workers to cancel')
await asyncio.gather(*tasks, return_exceptions=True) await asyncio.gather(*tasks, return_exceptions=True)
bu.verbose_std( bu.verbose_std(str(REPLAY_N) + ' replays: ' + str(REPLAY_N - SKIPPED_N - ERROR_N) + ' uploaded, ' + str(SKIPPED_N) + ' skipped, ' + str(ERROR_N) + ' errors')
str(REPLAY_N)
+ " replays: "
+ str(REPLAY_N - SKIPPED_N - ERROR_N)
+ " uploaded, "
+ str(SKIPPED_N)
+ " skipped, "
+ str(ERROR_N)
+ " errors"
)
except KeyboardInterrupt: except KeyboardInterrupt:
print("Ctrl-c pressed ...") print('Ctrl-c pressed ...')
sys.exit(1) sys.exit(1)
finally: finally:
## Need to close the aiohttp.session since Python destructors do not support async methods... ## Need to close the aiohttp.session since Python destructors do not support async methods...
await wg.session.close() await wg.session.close()
await wi.close() await wi.close()
return 0 return None
async def mkReplayQ(queue : asyncio.Queue, files : list, title : str): async def mkReplayQ(queue : asyncio.Queue, files : list, title : str):
"""Create queue of replays to post""" """Create queue of replays to post"""
p_replayfile = re.compile(".*\\.wotbreplay$") p_replayfile = re.compile('.*\\.wotbreplay$')
if files[0] == "-": if files[0] == '-':
bu.debug("reading replay file list from STDIN") bu.debug('reading replay file list from STDIN')
stdin, _ = await aioconsole.get_standard_streams() stdin, _ = await aioconsole.get_standard_streams()
while True: while True:
line = (await stdin.readline()).decode("utf-8").rstrip() line = (await stdin.readline()).decode('utf-8').rstrip()
if not line: if not line:
break break
else: else:
if p_replayfile.match(line) is not None: if (p_replayfile.match(line) != None):
await queue.put(await mkQueueItem(line, title)) await queue.put(await mkQueueItem(line, title))
else: else:
for fn in files: for fn in files:
if fn.endswith('"'): if fn.endswith('"'):
fn = fn[:-1] fn = fn[:-1]
if os.path.isfile(fn) and (p_replayfile.match(fn) is not None): if os.path.isfile(fn) and (p_replayfile.match(fn) != None):
await queue.put(await mkQueueItem(fn, title)) await queue.put(await mkQueueItem(fn, title))
bu.debug("File added to queue: " + fn) bu.debug('File added to queue: ' + fn)
elif os.path.isdir(fn): elif os.path.isdir(fn):
with os.scandir(fn) as dirEntry: with os.scandir(fn) as dirEntry:
for entry in dirEntry: for entry in dirEntry:
try: try:
bu.debug("Found: " + entry.name) bu.debug('Found: ' + entry.name)
if entry.is_file() and ( if entry.is_file() and (p_replayfile.match(entry.name) != None):
p_replayfile.match(entry.name) is not None
):
bu.debug(entry.name) bu.debug(entry.name)
await queue.put(await mkQueueItem(entry.path, title)) await queue.put(await mkQueueItem(entry.path, title))
bu.debug("File added to queue: " + entry.path) bu.debug('File added to queue: ' + entry.path)
except Exception as err: except Exception as err:
bu.error(str(err)) bu.error(str(err))
else: else:
bu.error("File not found: " + fn) bu.error('File not found: ' + fn)
bu.debug("Finished") bu.debug('Finished')
return None return None
@@ -228,15 +170,10 @@ async def mkQueueItem(filename: str, title: str) -> list:
return [filename, REPLAY_N, getTitle(filename, title, REPLAY_N)] return [filename, REPLAY_N, getTitle(filename, title, REPLAY_N)]
async def replayWorker( async def replayWorker(queue: asyncio.Queue, workerID: int, account_id: int, priv = False):
queue: asyncio.Queue, workerID: int, account_id: int, priv=False
):
"""Async Worker to process the replay queue""" """Async Worker to process the replay queue"""
global SKIPPED_N global SKIPPED_N
global ERROR_N global ERROR_N
global wi
assert wi is not None, "wi cannot be None"
while True: while True:
item = await queue.get() item = await queue.get()
@@ -244,8 +181,8 @@ async def replayWorker(
N = item[1] N = item[1]
title = item[2] title = item[2]
replay_json_fn = filename + ".json" replay_json_fn = filename + '.json'
msg_str = "Replay[" + str(N) + "]: " msg_str = 'Replay[' + str(N) + ']: '
#bu.debug(msg_str + replay_json_fn) #bu.debug(msg_str + replay_json_fn)
try: try:
@@ -254,17 +191,10 @@ async def replayWorker(
replay_json = json.loads(await fp.read()) replay_json = json.loads(await fp.read())
#if replay_json['status'] == 'ok': #if replay_json['status'] == 'ok':
if wi.chk_JSON_replay(replay_json): if wi.chk_JSON_replay(replay_json):
bu.verbose_std( bu.verbose_std(msg_str + title + ' has already been posted. Skipping.' )
msg_str + title + " has already been posted. Skipping."
)
else: else:
os.remove(replay_json_fn) os.remove(replay_json_fn)
bu.debug( bu.debug(msg_str + "Replay JSON not valid: Deleting " + replay_json_fn, id=workerID)
msg_str
+ "Replay JSON not valid/complete: Deleting "
+ replay_json_fn,
id=workerID,
)
SKIPPED_N += 1 SKIPPED_N += 1
queue.task_done() queue.task_done()
continue continue
@@ -272,137 +202,106 @@ async def replayWorker(
except asyncio.CancelledError as err: except asyncio.CancelledError as err:
raise err raise err
except Exception as err: except Exception as err:
bu.error(msg_str + "Unexpected error: " + str(type(err)) + " : " + str(err)) bu.error(msg_str + 'Unexpected error: ' + str(type(err)) + ' : '+ str(err))
try: try:
#bu.debug('Opening file [' + str(N) +']: ' + filename) #bu.debug('Opening file [' + str(N) +']: ' + filename)
async with aiofiles.open(filename, "rb") as fp: async with aiofiles.open(filename,'rb') as fp:
filename = os.path.basename(filename) filename = os.path.basename(filename)
bu.debug(msg_str + "File: " + filename) bu.debug(msg_str + 'File: ' + filename)
json_resp = await wi.post_replay( json_resp = await wi.post_replay(await fp.read(), filename, account_id, title, priv, N)
await fp.read(), filename, account_id, title, priv, N if json_resp != None:
) if (await bu.save_JSON(replay_json_fn,json_resp)):
if json_resp is not None:
if await bu.save_JSON(replay_json_fn, json_resp):
if wi.chk_JSON_replay(json_resp): if wi.chk_JSON_replay(json_resp):
if not bu.debug(msg_str + "Replay saved OK: " + filename): if not bu.debug(msg_str + 'Replay saved OK: ' + filename):
bu.verbose_std(msg_str + title + " posted") bu.verbose_std(msg_str + title + ' posted')
else: else:
bu.warning( bu.warning(msg_str +'Replay file is not valid: ' + filename)
msg_str
+ "Replay file is not valid/complete: "
+ filename
)
ERROR_N += 1 ERROR_N += 1
else: else:
bu.error(msg_str + "Error saving replay: " + filename) bu.error(msg_str + 'Error saving replay: ' + filename)
ERROR_N += 1 ERROR_N += 1
else: else:
bu.error(msg_str + "Replay file is not valid/complete: " + filename) bu.error(msg_str + 'Replay file is not valid: ' + filename)
ERROR_N += 1 ERROR_N += 1
except Exception as err: except Exception as err:
bu.error( bu.error(msg_str + 'Unexpected Exception: ' + str(type(err)) + ' : ' + str(err) )
msg_str + "Unexpected Exception: " + str(type(err)) + " : " + str(err) bu.debug(msg_str + 'Marking task done')
)
bu.debug(msg_str + "Marking task done")
queue.task_done() queue.task_done()
return None return None
# def getTitle_old(replayfile: str, title: str, i: int) -> str: def getTitle_old(replayfile: str, title: str, i : int) -> str:
# global wg
# if title is None:
# try:
# filename = os.path.basename(replayfile)
# bu.debug(filename)
# map_usrStrs = wg.get_map_user_strs()
# tank_userStrs = wg.get_tank_user_strs()
# # p = re.compile('\\d{8}_\\d{4}_(.+)_(' + '|'.join(map_usrStrs) + ')(?:-\\d)?\\.wotbreplay$')
# # update 6.2 changed the file name format. Bug fixed 2019-09-09 Jylpah
# p = re.compile(
# "\\d{8}_\\d{4}_.*?("
# + "|".join(tank_userStrs)
# + ")_("
# + "|".join(map_usrStrs)
# + ")(?:-\\d)?\\.wotbreplay$"
# )
# m = p.match(filename)
# if m is not None:
# if wg.tanks is not None:
# tank = m.group(1)
# if tank in wg.tanks["userStr"]:
# tank = wg.tanks["userStr"][tank]
# else:
# bu.error(
# 'Tank code: "'
# + tank
# + '" not found from Tankopedia (tanks.json)'
# )
# else:
# tank = m.group(1)
# blitz_map = m.group(2)
# if blitz_map in wg.maps:
# blitz_map = wg.maps[blitz_map]
# else:
# bu.error(
# 'Mapcode: "'
# + blitz_map
# + '" not found from map database (maps.json)'
# )
# title = tank + " @ " + blitz_map
# else:
# title = re.sub("\\.wotbreplay$", "", filename)
# except Exception as err:
# bu.error(err)
# else:
# title.replace("NN", str(i))
# return title
def getTitle(replayfile: str, title: str | None = None, i: int = 0) -> str:
global wg global wg
assert wg is not None, "wg must not be None"
if title is None: if title == None:
try:
filename = os.path.basename(replayfile)
bu.debug(filename)
map_usrStrs = wg.get_map_user_strs()
tank_userStrs = wg.get_tank_user_strs()
#p = re.compile('\\d{8}_\\d{4}_(.+)_(' + '|'.join(map_usrStrs) + ')(?:-\\d)?\\.wotbreplay$')
# update 6.2 changed the file name format. Bug fixed 2019-09-09 Jylpah
p = re.compile('\\d{8}_\\d{4}_.*?(' + '|'.join(tank_userStrs) + ')_(' + '|'.join(map_usrStrs) + ')(?:-\\d)?\\.wotbreplay$')
m = p.match(filename)
if (m != None):
if wg.tanks != None:
tank = m.group(1)
if tank in wg.tanks['userStr']:
tank = wg.tanks['userStr'][tank]
else:
bu.error('Tank code: "' + tank + '" not found from Tankopedia (tanks.json)')
else:
tank = m.group(1)
blitz_map = m.group(2)
if blitz_map in wg.maps:
blitz_map = wg.maps[blitz_map]
else:
bu.error('Mapcode: "' + blitz_map + '" not found from map database (maps.json)')
title = tank + ' @ ' + blitz_map
else:
title = re.sub('\\.wotbreplay$', '', filename)
except Exception as err:
bu.error(err)
else:
title.replace('NN', str(i))
return title
def getTitle(replayfile: str, title: str = None, i : int = 0) -> str:
global wg
if title == None:
try: try:
filename = os.path.basename(replayfile) filename = os.path.basename(replayfile)
bu.debug(filename) bu.debug(filename)
tank = None tank = None
map_name = None map_name = None
with zipfile.ZipFile(replayfile, "r") as archive: with zipfile.ZipFile(replayfile, 'r') as archive:
# bu.debug('Replay file: ' + replayfile + ' opened') # bu.debug('Replay file: ' + replayfile + ' opened')
with io.TextIOWrapper(archive.open("meta.json")) as meta: with io.TextIOWrapper(archive.open('meta.json')) as meta:
# bu.debug('Replay file\'s metadata: opened') # bu.debug('Replay file\'s metadata: opened')
try: try:
metadata_json = json.load(meta) metadata_json = json.load(meta)
#player = metadata_json['playerName'] #player = metadata_json['playerName']
tank_name = wg.get_tank_name( tank = wg.tank_str2name(metadata_json['playerVehicleName'])
metadata_json["vehicleCompDescriptor"] map_name = wg.get_map(metadata_json['mapName'])
) bu.debug('Tank: ' + tank + ' Map: ' + map_name)
map_name = wg.get_map(metadata_json["mapName"])
bu.debug(
"Tank: " + tank_name
if tank_name is not None
else "NOT FOUND IN tanks.json" + " Map: " + map_name
)
except Exception as err: except Exception as err:
bu.error(exception = err) bu.error(exception = err)
if (tank_name is not None) and (map_name is not None): if (tank != None) and (map_name != None):
title = tank_name + " @ " + map_name title = tank + ' @ ' + map_name
else: else:
title = re.sub("\\.wotbreplay$", "", filename) title = re.sub('\\.wotbreplay$', '', filename)
except Exception as err: except Exception as err:
bu.error(err) bu.error(err)
else: else:
title.replace("NN", str(i)) title.replace('NN', str(i))
bu.debug("Returning: " + title) bu.debug('Returning: ' + title)
return title return title
### UNIT TESTS - pytest ### UNIT TESTS - pytest
# class TestClass: # class TestClass:
@@ -438,8 +337,6 @@ if __name__ == "__main__":
except ImportError: except ImportError:
pass pass
else: else:
if not isinstance( if not isinstance(asyncio.get_event_loop_policy(), WindowsSelectorEventLoopPolicy):
asyncio.get_event_loop_policy(), WindowsSelectorEventLoopPolicy
):
asyncio.set_event_loop_policy(WindowsSelectorEventLoopPolicy()) asyncio.set_event_loop_policy(WindowsSelectorEventLoopPolicy())
asyncio.run(main(sys.argv[1:]), debug=False) asyncio.run(main(sys.argv[1:]), debug=False)