Author SHA1 Message Date
Jylpah ec696d6946 add pyutils 2022-10-29 17:47:33 +03:00
Jylpah 1f41901042 update 9.2 2022-10-09 00:18:30 +03:00
Jylpah d275914b32 Update .gitignore 2022-08-18 09:44:39 +03:00
Jylpah 9f8c82f434 Stream client support 2022-08-18 09:42:55 +03:00
Jylpah 3a8f065f35 Update 9.2 2022-08-18 09:42:32 +03:00
Jylpah 0cac200f06 Update 9.1 2022-07-14 11:25:38 +03:00
Jylpah 342b90bcf9 SSL -> TLS 2022-06-09 20:48:50 +03:00
Jylpah a9845b6fbb Update 9.0 2022-06-08 17:25:06 +03:00
Jylpah ee36e9192f Update 8.10 2022-04-30 21:43:24 +03:00
Jylpah 5d5821564e update 8.9 2022-03-24 15:44:48 +02:00
Jylpah 3c6f9dcae3 Merge branch 'master' of https://github.com/Jylpah/blitz-tools 2022-03-24 15:41:26 +02:00
Jylpah 433e2295c2 Update 8.9 2022-03-24 15:41:22 +02:00
Jylpah 3dc9533c6a Update maps.json 2022-03-24 15:41:15 +02:00
Jylpah 83456ae150 Add updates 8.5 - 8.8 2022-02-16 17:48:01 +02:00
Jylpah 0c25c781a9 Update 8.8 2022-02-16 17:41:50 +02:00
Jylpah 244ae314d8 Update 8.8 2022-02-16 17:40:17 +02:00
Jylpah 33b0efb48d Update 8.6 2022-01-22 22:27:34 +02:00
Jylpah 574fb95f00 Update 8.6 2021-12-20 10:15:47 +02:00
Jylpah fdc5db966e Update installation and usage instructions 2021-11-24 10:28:32 +02:00
Jylpah 65e4fd83d8 Update installation instructions 2021-11-24 09:48:39 +02:00
Jylpah e9451c7f5d Merge pull request #34 from Jylpah/stable-filters-update2
Fix --filters and improve performance when filtering
2021-11-23 21:42:45 +02:00
Jylpah fa65872ad2 --filters: Bug fix and performance improvement 2021-11-23 21:42:09 +02:00
Jylpah b2f37ebcf5 Merge branch 'stable-filter-update' into stable-filters-update2 2021-11-23 18:44:09 +02:00
Jylpah d323f11662 Update analyze_wotb_replays.py 2021-11-23 18:38:49 +02:00
Jylpah d847a394a9 Add allies/enemies categorizations: xxx_damage_dealt, xxx_wins, process_battle_results(): Fix bug filter(s) 2021-11-23 18:20:11 +02:00
Jylpah 8514e9db17 Update analyze_wotb_replays.py 2021-11-23 18:08:24 +02:00
Jylpah 521986adf1 Update 8.5 2021-11-23 18:01:17 +02:00
Jylpah 7e39fdc442 Fix --filters bug with number categorization 2021-11-23 09:46:04 +02:00
Jylpah 14ee570ee5 Merge branch 'master' of https://github.com/Jylpah/blitz-tools 2021-10-29 21:18:27 +03:00
Jylpah e0228a4bf1 Fix shebang 2021-10-29 21:18:24 +03:00
Jylpah 2a93cfbce3 update 8.4 2021-10-24 21:19:06 +03:00
Jylpah 78a959224c Update 8.4 2021-10-23 22:07:23 +03:00
Jylpah ae24ab35f7 Updates 8.0 - 8.3 added 2021-09-17 10:44:38 +03:00
Jylpah ba6b4781e5 Update 8.3 2021-09-16 17:31:10 +03:00
Jylpah 050bd99488 get_filter_categories(): fix, add room_type=5: Quick Tournament(?) 2021-09-10 21:03:41 +03:00
Jylpah eb39c9ce84 Update 8.2 2021-08-22 21:21:42 +03:00
Jylpah 24547763e9 replayWorker(): Better warning text to incomplete replays 2021-08-13 13:43:17 +03:00
Jylpah 28347e1653 Fix printing of player/allies/enemies average damage columns 2021-08-07 16:42:19 +03:00
Jylpah ffe5afbf1e getTitle(): More robust tank names based on tank_ids, not UsrStrs that keep changing. 2021-08-07 16:40:42 +03:00
Jylpah 17ac09afde Update analyze_wotb_replays.py 2021-08-07 16:26:25 +03:00
Jylpah 9117963085 filter_results() bug fix 2021-08-03 19:14:44 +03:00
Jylpah dc8f9a233d Merge pull request #32 from Jylpah/master-platoon
help_extended(): change order of filter helps
2021-08-03 12:43:59 +03:00
Jylpah ce3f9993c5 help_extended(): change order of filter helps 2021-08-03 12:43:43 +03:00
Jylpah fd7eb8261d Merge pull request #31 from Jylpah/master-platoon
Added platoon rate and categorization by platoon/solo games
2021-08-03 12:43:19 +03:00
Jylpah 748ed7806b Added platoon rate and categorization by platoon/solo games 2021-08-03 12:40:36 +03:00
Jylpah 1ada279728 Update Lupus tanks.json 2021-07-27 18:47:08 +03:00
Jylpah 57cbc5b233 Tanks sorted by tank_id 2021-07-15 20:22:46 +03:00
Jylpah 43842dc140 Update 8.1 2021-07-15 20:21:53 +03:00
Jylpah 170a801652 sort_dict(): added 2021-07-15 20:21:32 +03:00
Jylpah 210e943157 Update 8.0 2021-06-08 16:57:42 +03:00
Jylpah b3b7b81eb4 BattleCategory(): add 'hits_bounced' result field 2021-06-03 15:02:27 +03:00
Jylpah 446e289041 Add --mode dmg_received, improved --mode help, new fields 2021-06-03 14:48:17 +03:00
Jylpah f8a0fdfbe1 Merge pull request #30 from Jylpah/stable-export-replays
Stable export replays
2021-05-12 00:16:42 +03:00
Jylpah 4c0de49077 name2tank_str(): error() -> debug() 2021-05-12 00:05:52 +03:00
Jylpah 07aa7af32f bug fix 2021-05-12 00:04:36 +03:00
Jylpah ea3306ee6c WoTinspector.post_replay(): add _id 2021-05-12 00:04:21 +03:00
Jylpah e4882d70af export replays(): --replays option to export replays 2021-05-11 20:55:13 +03:00
Jylpah 433c26d2f8 get_date_str(), get_replay_filename(): added 2021-05-11 20:54:39 +03:00
Jylpah f6b1b1353f Update analyze_wotb_replays.py 2021-05-11 14:14:10 +03:00
Jylpah 36fb53f0e7 convert_tank_names(): Fix tank key sorting 2021-04-29 00:09:40 +03:00
Jylpah b19a2169a7 Update 7.9 2021-04-29 00:09:04 +03:00
Jylpah 67aeaddf36 get_db_player_stats(): Fix aggregation 2021-04-27 10:26:30 +03:00
Jylpah 763f205175 Update 7.9 2021-04-27 10:24:01 +03:00
Jylpah d97c0cabd8 Update analyze_wotb_replays.py 2021-04-17 14:34:05 +03:00
Jylpah e6ff2f438d save_XXX_stats() funcs 2021-04-17 14:33:59 +03:00
Jylpah f4f153a175 stat_worker(): fix bug introduced in earlier commit 2021-04-15 09:15:00 +03:00
Jylpah 829e03f644 get_db_tank_stats(): optimize find() for index 2021-04-14 21:02:43 +03:00
Jylpah 53b2f62817 mk_readerQ_item(): add _id param 2021-04-09 12:08:14 +03:00
Jylpah 804a4a6483 update 7.8 2021-04-05 15:34:34 +03:00
Jylpah 47a1f96c4e Update 7.8 2021-04-05 14:39:38 +03:00
12 changed files with 1806 additions and 349 deletions

No files matched your search

Executable
+15
View File
@@ -0,0 +1,15 @@
__pycache__/
BlitzApp
tmp/
ssl/
*.ini
*.swp
*.code-workspace
*.sqlite3
.vscode/
*.sqlite3-journal
.gitattributes
export*
*.csv
!/stats/*.csv
!*.py
+3
View File
@@ -0,0 +1,3 @@
[submodule "pyutils"]
path = pyutils
url = https://github.com/Jylpah/pyutils.git
+25 -23
View File
@@ -1,5 +1,5 @@
# 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 higher. I am using 3.8 myself so you may have to change the Python interpreter version in the scripts' first line. Python scripts to analyze WoT Blitz replays and stats. All the scripts require [Python 3.7](https://www.python.org/downloads/) or later.
### 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.
@@ -13,46 +13,48 @@ 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/) on to your computer/laptop 1. Install [Python 3.8](https://www.python.org/downloads/) or later to your computer/laptop
2. Install the required Python modules: motor, aiohttp, aioconsole, aiofiles, aiosqlite, beautifulsoup4, lxml, xmltodict, progress 2. Install the required Python modules (see [requirements.txt](requirements.txt): motor, aiohttp, aioconsole, aiofiles, aiosqlite, beautifulsoup4, lxml, xmltodict, progress
``` ```
# Remember to run the command with a Python interpreter >= 3.7 python -m pip install -r requirements.txt
python -m pip install motor aiohttp aioconsole aiofiles aiosqlite beautifulsoup4 lxml xmltodict progress
``` ```
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`. 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`.
4. Upload your replays.
``` ```
# Windows, run directly from Command Prompt or Powershell git clone https://github.com/Jylpah/blitz-tools.git
# 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
# Syntax # Linux or Windows Subsystem for Linux (WSL)
python.exe .\upload_wotb_replays.py REPLAY_FILE.wotbreplay ./upload_wotb_replays.py --help
# 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. 5. Analyze replays with `analyze_wotb_replays.py`
``` ```
# Windows, run directly from Command Prompt or Powershell ## Check options
# Windows Command Prompt or Powershell
python.exe .\analyze_wotb_replays.py --help python.exe .\analyze_wotb_replays.py --help
# Syntax # Syntax (Windows)
python.exe .\analyze_wotb_replays.py REPLAY_FILE.wotbreplay.json python.exe .\analyze_wotb_replays.py REPLAY_FILE.wotbreplay.json [DIR_WITH_REPLAYS ...]
# Example # Example (Windows)
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 # Linux or Windows Subsystem for Linux (WSL)
./analyze_wotb_replays.py --help ./analyze_wotb_replays.py --help
``` ```
+329 -153
View File
File diff suppressed because it is too large. Load diff
+121 -37
View File
@@ -22,6 +22,11 @@ _log_level = NORMAL
LOG = False LOG = False
LOGGER = None LOGGER = None
MODE_TANK_STATS = 'tank_stats'
MODE_PLAYER_STATS = 'player_stats'
MODE_PLAYER_ACHIEVEMENTS= 'player_achievements'
MODE_TANKOPEDIA = 'tankopedia'
# Progress display # Progress display
_progress_N = 100 _progress_N = 100
_progress_i = 0 _progress_i = 0
@@ -418,12 +423,14 @@ def set_progress_bar(heading: str, max_value: int, step: int = None, slow: bool
return return
def set_counter(heading: str): def set_counter(heading: str, step = None):
global _progress_obj, _progress_i global _progress_obj, _progress_i
_progress_i = 0 _progress_i = 0
if _progress_obj != None: if _progress_obj != None:
finish_progress_bar() finish_progress_bar()
_progress_obj = Counter(heading) _progress_obj = Counter(heading + ': ')
if step != None:
set_progress_step(step)
return return
@@ -479,6 +486,16 @@ def NOW() -> int:
return int(time.time()) return int(time.time())
def get_date_str(timestamp:int = NOW(), date_format = '%Y%m%d_%H%M%S'):
"""Return YYYYMMDD_HHmm date string"""
try:
ts = datetime.fromtimestamp(timestamp)
return ts.strftime(date_format)
except Exception as err:
error(exception=err)
return None
def rebase_file_args(current_dir, files): def rebase_file_args(current_dir, files):
"""REbase file command line params after moving working dir to the script's dir""" """REbase file command line params after moving working dir to the script's dir"""
if isinstance(files, list): if isinstance(files, list):
@@ -626,6 +643,14 @@ def get_JSON_value(json, key : str = None, keys : list = None, keypath = None):
raise KeyError('Key not found: ' + get_JSON_keypath(keypath, keys[0])) raise KeyError('Key not found: ' + get_JSON_keypath(keypath, keys[0]))
def sort_dict(d: dict, number: bool = False) -> dict:
"""Sort a dict by keys"""
if number:
return dict(sorted(d.items(), key=lambda item: int(item[0])))
else:
return dict(sorted(d.items(), key=lambda item: item[0]))
# ----------------------------------------------------------- # -----------------------------------------------------------
# Class SlowBar # Class SlowBar
# ----------------------------------------------------------- # -----------------------------------------------------------
@@ -649,8 +674,6 @@ class StatsNotFound(Exception):
pass pass
# ----------------------------------------------------------- # -----------------------------------------------------------
# Class WG # Class WG
# ----------------------------------------------------------- # -----------------------------------------------------------
@@ -686,7 +709,7 @@ class WG:
# WHERE account_id = {} AND stat = {} # WHERE account_id = {} AND stat = {}
# AND date >= {} LIMIT 1;""" # AND date >= {} LIMIT 1;"""
# TANK_STATS
SQL_TANK_STATS_TBL = 'tank_stats' SQL_TANK_STATS_TBL = 'tank_stats'
SQL_TANK_STATS_CREATE_TBL = 'CREATE TABLE IF NOT EXISTS ' + SQL_TANK_STATS_TBL + \ SQL_TANK_STATS_CREATE_TBL = 'CREATE TABLE IF NOT EXISTS ' + SQL_TANK_STATS_TBL + \
@@ -700,6 +723,7 @@ class WG:
SQL_TANK_STATS_UPDATE = 'REPLACE INTO ' + SQL_TANK_STATS_TBL + '(account_id, tank_id, update_time, stats) VALUES(?,?,?,?)' SQL_TANK_STATS_UPDATE = 'REPLACE INTO ' + SQL_TANK_STATS_TBL + '(account_id, tank_id, update_time, stats) VALUES(?,?,?,?)'
# PLAYER_STATS
SQL_PLAYER_STATS_TBL = 'player_stats' SQL_PLAYER_STATS_TBL = 'player_stats'
SQL_PLAYER_STATS_CREATE_TBL = 'CREATE TABLE IF NOT EXISTS ' + SQL_PLAYER_STATS_TBL + \ SQL_PLAYER_STATS_CREATE_TBL = 'CREATE TABLE IF NOT EXISTS ' + SQL_PLAYER_STATS_TBL + \
@@ -713,6 +737,7 @@ class WG:
SQL_PLAYER_STATS_CACHED = 'SELECT * FROM ' + SQL_PLAYER_STATS_TBL + ' WHERE account_id = ? AND update_time > ?' SQL_PLAYER_STATS_CACHED = 'SELECT * FROM ' + SQL_PLAYER_STATS_TBL + ' WHERE account_id = ? AND update_time > ?'
# PLAYER_ACHIEVEMENTS
SQL_PLAYER_ACHIEVEMENTS_TBL = 'player_achievements' SQL_PLAYER_ACHIEVEMENTS_TBL = 'player_achievements'
SQL_PLAYER_ACHIEVEMENTS_CREATE_TBL = 'CREATE TABLE IF NOT EXISTS ' + SQL_PLAYER_ACHIEVEMENTS_TBL + \ SQL_PLAYER_ACHIEVEMENTS_CREATE_TBL = 'CREATE TABLE IF NOT EXISTS ' + SQL_PLAYER_ACHIEVEMENTS_TBL + \
@@ -720,11 +745,12 @@ class WG:
update_time INTEGER NOT NULL, update_time INTEGER NOT NULL,
stats TEXT)""" stats TEXT)"""
SQL_PLAYER_ACHIEVEMENTS_COUNT = 'SELECT COUNT(*) FROM ' + SQL_PLAYER_ACHIEVEMENTS_TBL
SQL_PLAYER_ACHIEVEMENTS_CACHED = 'SELECT * FROM ' + SQL_PLAYER_ACHIEVEMENTS_TBL + ' WHERE account_id = ? AND update_time > ?' SQL_PLAYER_ACHIEVEMENTS_CACHED = 'SELECT * FROM ' + SQL_PLAYER_ACHIEVEMENTS_TBL + ' WHERE account_id = ? AND update_time > ?'
SQL_PLAYER_ACHIEVEMENTS_UPDATE = 'REPLACE INTO ' + SQL_PLAYER_ACHIEVEMENTS_TBL + '(account_id, update_time, stats) VALUES(?,?,?)' SQL_PLAYER_ACHIEVEMENTS_UPDATE = 'REPLACE INTO ' + SQL_PLAYER_ACHIEVEMENTS_TBL + '(account_id, update_time, stats) VALUES(?,?,?)'
SQL_PLAYER_ACHIEVEMENTS_COUNT = 'SELECT COUNT(*) FROM ' + SQL_PLAYER_ACHIEVEMENTS_TBL
SQL_TABLES = [ SQL_PLAYER_STATS_TBL, SQL_TANK_STATS_TBL, SQL_PLAYER_ACHIEVEMENTS_TBL ] SQL_TABLES = [ SQL_PLAYER_STATS_TBL, SQL_TANK_STATS_TBL, SQL_PLAYER_ACHIEVEMENTS_TBL ]
@@ -908,33 +934,18 @@ class WG:
@classmethod @classmethod
def get_map(cls, map_str: str) -> str: def get_map(self, map_str: str) -> str:
"""Return map name from short map string in replays""" """Return map name from short map string in replays"""
try: try:
return cls.maps[map_str] return self.maps[map_str]
except: except:
error('Map ' + map_str + ' not found') error('Map ' + map_str + ' not found')
return None return None
@classmethod @classmethod
def get_map_user_strs(cls) -> str: def get_tank_user_strs(self) -> str:
return cls.maps.keys() return self.tanks["userStr"].keys()
@classmethod
def tank_str2name(cls, tank_str: str) -> str:
"""Return tank name from short tank string in replays"""
try:
return cls.tanks["userStr"][tank_str]
except:
error('Tank ' + tank_str + ' not found')
return tank_str
@classmethod
def get_tank_user_strs(cls) -> str:
return cls.tanks["userStr"].keys()
@classmethod @classmethod
@@ -1071,10 +1082,14 @@ class WG:
"""Load tanks from tankopedia JSON""" """Load tanks from tankopedia JSON"""
if tankopedia_fn == None: if tankopedia_fn == None:
return False return False
try: try:
with open(tankopedia_fn, 'rt', encoding='utf8') as f: with open(tankopedia_fn, 'rt', encoding='utf8') as f:
self.tanks = json.loads(f.read()) self.tanks = json.loads(f.read())
self.tanks['tankStr'] = dict()
p = re.compile('.+_short$')
for usr_str in self.tanks['userStr']:
if p.match(usr_str) == None:
self.tanks['tankStr'][self.tanks['userStr'][usr_str]] = usr_str
self.tanks_by_tier = dict() self.tanks_by_tier = dict()
for tier in range(1,11): for tier in range(1,11):
self.tanks_by_tier[str(tier)] = list() self.tanks_by_tier[str(tier)] = list()
@@ -1086,6 +1101,43 @@ class WG:
return False return False
def get_replay_filename(self, replay: dict):
try:
summary = replay['data']['summary']
timestamp = int(summary['battle_start_timestamp'])
timestamp = get_date_str(timestamp, date_format='%Y%m%d_%H%M')
player = summary['player_name']
arena_id = int(summary['arena_unique_id'])
vehicle = self.name2tank_str(summary['vehicle'])
vehicle.replace(' ','_')
return '{:s}_{:s}_{:s}_{:d}.wotbreplay.json'.format(timestamp, player, vehicle, arena_id)
except Exception as err:
error('Unexpected Exception', err)
return None
def get_map_user_strs(self) -> str:
return self.maps.keys()
def tank_str2name(self, tank_str: str) -> str:
"""Return tank name from short tank string in replays"""
try:
return self.tanks["userStr"][tank_str]
except:
error('Tank ' + tank_str + ' not found')
return tank_str
def name2tank_str(self, name: str) -> str:
"""Return shorttank string from tank string in replays"""
try:
return self.tanks["tankStr"][name]
except:
debug('Tank ' + name + ' not found')
return name
def get_tanks_by_tier(self, tier: int) -> list(): def get_tanks_by_tier(self, tier: int) -> list():
"""Returns tank_ids by tier""" """Returns tank_ids by tier"""
try: try:
@@ -1261,7 +1313,7 @@ class WG:
# debug('JSON Response received: ' + str(json_data)) # debug('JSON Response received: ' + str(json_data))
stats = json_data['data'][str(account_id)] stats = json_data['data'][str(account_id)]
if cache: if cache:
await self.put_2_statsQ('tank_stats', [account_id, tank_ids], stats) await self.save_tank_stats(account_id, tank_ids, stats)
return stats return stats
except Exception as err: except Exception as err:
error(exception=err) error(exception=err)
@@ -1294,7 +1346,7 @@ class WG:
# debug('JSON Response received: ' + str(json_data)) # debug('JSON Response received: ' + str(json_data))
stats = json_data['data'][str(account_id)] stats = json_data['data'][str(account_id)]
if cache: if cache:
await self.put_2_statsQ('player_stats', [account_id], stats) await self.save_player_stats(account_id, stats)
return stats return stats
except Exception as err: except Exception as err:
error(exception=err) error(exception=err)
@@ -1333,7 +1385,7 @@ class WG:
for account_id in json_data['data'].keys(): for account_id in json_data['data'].keys():
stats[account_id] = json_data['data'][account_id] stats[account_id] = json_data['data'][account_id]
if cache: if cache:
await self.put_2_statsQ('player_achievements', [int(account_id)], json_data['data'][account_id]) await self.save_player_achievements(int(account_id), json_data['data'][account_id])
return stats return stats
except Exception as err: except Exception as err:
error(exception=err) error(exception=err)
@@ -1440,7 +1492,7 @@ class WG:
return None return None
async def put_2_statsQ(self, statsType: str, key: list, stats: list): async def save_stats(self, statsType: str, key: list, stats: list):
"""Save stats to a async queue to be saved by the stat_saver -task""" """Save stats to a async queue to be saved by the stat_saver -task"""
if self.statsQ == None: if self.statsQ == None:
return False return False
@@ -1449,6 +1501,30 @@ class WG:
return True return True
async def save_player_stats(self, account_id: int, stats: dict):
try:
await self.save_stats(MODE_PLAYER_STATS, [int(account_id)], stats)
except Exception as err:
error(exception=err)
return None
async def save_player_achievements(self, account_id: int, stats: dict):
try:
await self.save_stats(MODE_PLAYER_ACHIEVEMENTS, [int(account_id)], stats)
except Exception as err:
error(exception=err)
return None
async def save_tank_stats(self, account_id: int, tank_ids: list, stats: dict):
try:
await self.save_stats(MODE_TANK_STATS, [int(account_id), tank_ids], stats)
except Exception as err:
error(exception=err)
return None
async def stat_saver(self): async def stat_saver(self):
"""Async task for saving stats into cache in background""" """Async task for saving stats into cache in background"""
@@ -1464,8 +1540,13 @@ class WG:
await self.cache.commit() await self.cache.commit()
if is_debug():
async with self.cache.execute(WG.SQL_PLAYER_STATS_COUNT) as cursor:
debug('Cache contains: ' + str((await cursor.fetchone())[0]) + ' player stat records' )
async with self.cache.execute(WG.SQL_PLAYER_ACHIEVEMENTS_COUNT) as cursor:
debug('Cache contains: ' + str((await cursor.fetchone())[0]) + ' player achievement records' )
async with self.cache.execute(WG.SQL_TANK_STATS_COUNT) as cursor: async with self.cache.execute(WG.SQL_TANK_STATS_COUNT) as cursor:
debug('Cache contains: ' + str((await cursor.fetchone())[0]) + ' cached player tank stat records' ) debug('Cache contains: ' + str((await cursor.fetchone())[0]) + ' player tank stat records' )
except Exception as err: except Exception as err:
error(exception=err) error(exception=err)
sys.exit(1) sys.exit(1)
@@ -1474,19 +1555,20 @@ class WG:
try: try:
stats = await self.statsQ.get() stats = await self.statsQ.get()
stats_type = stats[0] stat_type = stats[0]
key = stats[1] key = stats[1]
stats_data = stats[2] stats_data = stats[2]
update_time = stats[3] update_time = stats[3]
if stats_type == 'tank_stats': #debug('stat_type: ' + stat_type + ', key: ' + str(key))
if stat_type == MODE_TANK_STATS:
await self.store_tank_stats(key, stats_data, update_time) await self.store_tank_stats(key, stats_data, update_time)
elif stats_type == 'player_stats': elif stat_type == MODE_PLAYER_STATS:
await self.store_player_stats(key, stats_data, update_time) await self.store_player_stats(key, stats_data, update_time)
elif stats_type == 'player_achievements': elif stat_type == MODE_PLAYER_ACHIEVEMENTS:
await self.store_player_achievements(key, stats_data, update_time) await self.store_player_achievements(key, stats_data, update_time)
else: else:
error('Function to saves stats type \'' + stats_type + '\' is not implemented yet') error('Function to saves stats type \'' + stat_type + '\' is not implemented yet')
except asyncio.CancelledError: except asyncio.CancelledError:
# this is an eternal loop that will wait until cancelled # this is an eternal loop that will wait until cancelled
@@ -1521,7 +1603,7 @@ class WG:
for stat in stats_data: for stat in stats_data:
tank_id = stat['tank_id'] tank_id = stat['tank_id']
await self.cache.execute(WG.SQL_TANK_STATS_UPDATE, (account_id, tank_id, update_time, json.dumps(stat))) await self.cache.execute(WG.SQL_TANK_STATS_UPDATE, (account_id, tank_id, update_time, json.dumps(stat)))
tank_ids.remove(tank_id) tank_ids.discard(tank_id)
# no stats found => Add None to mark that # no stats found => Add None to mark that
for tank_id in tank_ids: for tank_id in tank_ids:
await self.cache.execute(WG.SQL_TANK_STATS_UPDATE, (account_id, tank_id, update_time, None)) await self.cache.execute(WG.SQL_TANK_STATS_UPDATE, (account_id, tank_id, update_time, None))
@@ -1793,6 +1875,8 @@ class WoTinspector:
except Exception as err: except Exception as err:
debug(exception=err, id=N) debug(exception=err, id=N)
await asyncio.sleep(SLEEP) await asyncio.sleep(SLEEP)
_id = self.read_replay_id(json_resp)
json_resp['_id'] = _id
debug(' Could not post replay: ' + title, id=N) debug(' Could not post replay: ' + title, id=N)
return json_resp return json_resp
+22 -14
View File
@@ -3,6 +3,7 @@
# Extract tankopedia data in WG API JSON format from Blitz app files (Android APK unzipped) # Extract tankopedia data in WG API JSON format from Blitz app files (Android APK unzipped)
from os import path
import sys, argparse, json, os, inspect, aiohttp, asyncio, aiofiles, re, logging, time, xmltodict, collections, configparser import sys, argparse, json, os, inspect, aiohttp, asyncio, aiofiles, re, logging, time, xmltodict, collections, configparser
import blitzutils as bu import blitzutils as bu
from blitzutils import WG from blitzutils import WG
@@ -11,9 +12,11 @@ logging.getLogger("asyncio").setLevel(logging.DEBUG)
FILE_CONFIG = 'blitzstats.ini' FILE_CONFIG = 'blitzstats.ini'
BLITZAPP_STRINGS='/assets/Data/Strings/en.yaml' # BLITZAPP_STRINGS='/assets/Data/Strings/en.yaml'
BLITZAPP_VEHICLES_DIR='/assets/Data/XML/item_defs/vehicles/' # BLITZAPP_VEHICLES_DIR='/assets/Data/XML/item_defs/vehicles/'
BLITZAPP_VEHICLE_FILE='/list.xml' BLITZAPP_STRINGS='Data/Strings/en.yaml'
BLITZAPP_VEHICLES_DIR='Data/XML/item_defs/vehicles/'
BLITZAPP_VEHICLE_FILE='list.xml'
wg = None wg = None
@@ -79,8 +82,8 @@ async def main(argv):
tankopedia = collections.OrderedDict() tankopedia = collections.OrderedDict()
tankopedia['status'] = 'ok' tankopedia['status'] = 'ok'
tankopedia['meta'] = { "count": len(tanks) } tankopedia['meta'] = { "count": len(tanks) }
tankopedia['data'] = tanks tankopedia['data'] = bu.sort_dict(tanks, number=True)
tankopedia['userStr'] = userStrs tankopedia['userStr'] = bu.sort_dict(userStrs)
bu.verbose_std('New tankopedia \'' + args.tanks + '\' contains ' + str(len(tanks)) + ' tanks') bu.verbose_std('New tankopedia \'' + args.tanks + '\' contains ' + str(len(tanks)) + ' tanks')
bu.verbose_std('New tankopedia \'' + args.tanks + '\' contains ' + str(len(userStrs)) + ' tank strings') bu.verbose_std('New tankopedia \'' + args.tanks + '\' contains ' + str(len(userStrs)) + ' tank strings')
await outfile.write(json.dumps(tankopedia, ensure_ascii=False, indent=4, sort_keys=False)) await outfile.write(json.dumps(tankopedia, ensure_ascii=False, indent=4, sort_keys=False))
@@ -104,8 +107,11 @@ async def main(argv):
async def extract_tanks(blitz_app_base : str, nation: str): async def extract_tanks(blitz_app_base : str, nation: str):
tanks = [] tanks = []
list_xml_file = blitz_app_base + BLITZAPP_VEHICLES_DIR + nation + BLITZAPP_VEHICLE_FILE # WG has changed the location of Data directory - at least in steam client
if not os.path.isfile(list_xml_file): if path.isdir(path.join(blitz_app_base, 'assets')):
blitz_app_base = path.join(blitz_app_base, 'assets')
list_xml_file = path.join(blitz_app_base, BLITZAPP_VEHICLES_DIR ,nation ,BLITZAPP_VEHICLE_FILE)
if not path.isfile(list_xml_file):
print('ERROR: cannot open ' + list_xml_file) print('ERROR: cannot open ' + list_xml_file)
return None return None
bu.debug('Opening file: ' + list_xml_file + ' (Nation: ' + nation + ')') bu.debug('Opening file: ' + list_xml_file + ' (Nation: ' + nation + ')')
@@ -115,13 +121,12 @@ async def extract_tanks(blitz_app_base : str, nation: str):
for data in tankList['root'].keys(): for data in tankList['root'].keys():
tank_xml = tankList['root'][data] tank_xml = tankList['root'][data]
tank = dict() tank = dict()
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['is_premium'] = issubclass(type(tank_xml['price']), dict)
tank['nation'] = nation
tank['tank_id'] = await get_tank_id(nation, int(tank_xml['id']))
tank['tier'] = int(tank_xml['level'])
tank['type'] = await get_tank_type(tank_xml['tags']) tank['type'] = await get_tank_type(tank_xml['tags'])
tank['userStr'] = tank_xml['userString']
#bu.debug('Reading tank string: ' + tank['userStr'], force=True) #bu.debug('Reading tank string: ' + tank['userStr'], force=True)
tanks.append(tank) tanks.append(tank)
except Exception as err: except Exception as err:
@@ -133,7 +138,7 @@ async def read_user_strs(blitz_app_base : str) -> dict:
"""Read user strings to convert map and tank names""" """Read user strings to convert map and tank names"""
tank_strs = {} tank_strs = {}
map_strs = {} map_strs = {}
filename = blitz_app_base + BLITZAPP_STRINGS filename = path.join(blitz_app_base, BLITZAPP_STRINGS)
bu.debug('Opening file: ' + filename + ' for reading UserStrings') bu.debug('Opening file: ' + filename + ' for reading UserStrings')
try: try:
async with aiofiles.open(filename, 'r', encoding="utf8") as f: async with aiofiles.open(filename, 'r', encoding="utf8") as f:
@@ -165,7 +170,10 @@ async def convert_tank_names(tanklist : list, tank_strs: dict) -> dict:
tank['name'] = tank_strs[tank['userStr']] tank['name'] = tank_strs[tank['userStr']]
#userStrs[tank['userStr'].split(':')[1]] = tank['name'] #userStrs[tank['userStr'].split(':')[1]] = tank['name']
tank.pop('userStr', None) tank.pop('userStr', None)
tankopedia[str(tank['tank_id'])] = tank tank_tmp = collections.OrderedDict()
for key in sorted(tank.keys()):
tank_tmp[key] = tank[key]
tankopedia[str(tank['tank_id'])] = tank_tmp
for tank_str in tank_strs: for tank_str in tank_strs:
skip = False skip = False
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/local/bin/python3.7 #!/usr/bin/env python3
# Get Tankpedia from WoTinspector.com # Get Tankpedia from WoTinspector.com
+5
View File
@@ -18,6 +18,7 @@
"fort": "Fort Despair", "fort": "Fort Despair",
"grossberg": "Dynasty's Pearl", "grossberg": "Dynasty's Pearl",
"himmelsdorf": "Himmelsdorf", "himmelsdorf": "Himmelsdorf",
"holland": "Molendijk",
"holmeisk": "Wasteland", "holmeisk": "Wasteland",
"iceworld": "Everfrost", "iceworld": "Everfrost",
"idle": "Yukon", "idle": "Yukon",
@@ -43,11 +44,15 @@
"neptune_02": "Normandy - Beach", "neptune_02": "Normandy - Beach",
"north": "North", "north": "North",
"ordeal": "Trial by Fire", "ordeal": "Trial by Fire",
"plant": "Ghost Factory",
"pliego": "Castilla", "pliego": "Castilla",
"port": "Port Bay", "port": "Port Bay",
"rift": "Hellas", "rift": "Hellas",
"rock": "Mayan Ruins", "rock": "Mayan Ruins",
"rudniki": "Mines", "rudniki": "Mines",
"rudniki_01": "Mines - Hill",
"rudniki_02": "Mines - Village",
"rudniki_03": "Mines - Center",
"savanna": "Oasis Palms", "savanna": "Oasis Palms",
"skit": "Naval Frontier", "skit": "Naval Frontier",
"test": "World of Ducks", "test": "World of Ducks",
Submodule
+1
Submodule pyutils added at 1eb17e8402.
+94 -79
View File
@@ -1,81 +1,96 @@
# WoT Blitz releases # WoT Blitz releases
| Release | Date | Notes | Inaccurate? | | Release | Date | Notes |
|:-------:|:--------:|-------------|-----| |:-------:|:--------:|-------------|
| 7.7 | 2021-02-24 | Czechoslovakian medium tanks | | | 9.1 | 2022-07-14 | Releases updated via DLC, graphics updates for Object 140, Patton 46 |
| 7.6 | 2021-01-27 | AMC 13 90, TOG II buffs, free replay camera | | | 9.0 | 2022-06-08 | Japanies heavies, Castilla graphics update, new garage |
| 7.5 | 2020-12-09 | ATGM removal, Batchat, Kpz70, T-2020 buff | | | 8.10 | 2022-04-28 | New battle results screen, new "Operation" mechanics |
| 7.4 | 2020-11-12 | TD buffs, Clan missions | | | 8.9 | 2022-03-23 | "Free" camo resupply, VK 72.01 supplies |
| 7.3 | 2020-10-08 | Swedish HT line | | | 8.8 | 2022-02-16 | Molendijk map |
| 7.2 | 2020-08-19 | Balance changes, added tier X ammo capa, new aiming reticles | | | 8.7 | 2022-01-19 | Soviet Light Tanks |
| 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 | | | 8.6 | 2021-12-15 | Joining Light and Medium Tank classes in MM |
| 7.0 | 2020-06-17 | British LTs, graphics improvements, ATGM nerf, Sheridan nerf, map fixes | | | 8.5 | 2021-11-17 | New national crew voices, economy update |
| 6.10 | 2020-04-29 | T92E1 nerf, Tier V-IX heavy HP buff, Battle Pass, map fixes | | | 8.4 | 2021-10-20 | Polish heavy tanks |
| 6.9 | 2020-03-25 | Japanese TDs, Tier X heavy HP buff | | | 8.3 | 2021-09-16 | FV4005, FV4022, VK 91.01 (P) and WZ-121 legendary camos, -5 deg gun depression to WZ-120 |
| 6.8 | 2020-02-19 | ATGM nerf, Hellas map | | | 8.2 | 2021-08-18 | Ghost Factory map, XP/credits nerf for inactive players, new store UI |
| 6.7 | 2020-01-15 | ATGM US Lights | | | 8.1 | 2021-07-15 | Armor highlighting updated |
| 6.6 | 2019-12-18 | T-62A + Leo buffs | | | 8.0 | 2021-06-08 | American experimental heavies (Yoh-line), PBR camos |
| 6.5 | 2019-11-21 | New UI | | | 7.9 | 2021-04-27 | Mines rework, new tutorial, colorblind mode, JgPz E100 legendary camo |
| 6.4 | 2019-10-16 | Halloween map, mid-tier HT buff... | | | 7.8 | 2021-03-24 | Mid-tier balance changes, Grille line new consumables |
| 6.3 | 2019-09-18 | European line | | | 7.7 | 2021-02-24 | Czechoslovakian medium tanks |
| 6.2 | 2019-08-14 | New MM | | | 7.6 | 2021-01-27 | AMC 13 90, TOG II buffs, free replay camera |
| 6.1 | 2019-07-10 | Autoloader buff | | | 7.5 | 2020-12-09 | ATGM removal, Batchat, Kpz70, T-2020 buff |
| 6.0 | 2019-06-05 | UK TD line #2 | | | 7.4 | 2020-11-12 | TD buffs, Clan missions |
| 5.10 | 2019-04-24 | new missions | | | 7.3 | 2020-10-08 | Swedish HT line |
| 5.9 | 2019-03-27 | New shell tracers, minor fixes | | | 7.2 | 2020-08-19 | Balance changes, added tier X ammo capa, new aiming reticles |
| 5.8 | 2019-02-21 | Chinese TD line | | | 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 |
| 5.7 | 2019-01-16 | Avatars | | | 7.0 | 2020-06-17 | British LTs, graphics improvements, ATGM nerf, Sheridan nerf, map fixes |
| 5.6 | 2018-12-05 | Normandy map | | | 6.10 | 2020-04-29 | T92E1 nerf, Tier V-IX heavy HP buff, Battle Pass, map fixes |
| 5.5 | 2018-11-13 | Low-tier clean-up | | | 6.9 | 2020-03-25 | Japanese TDs, Tier X heavy HP buff |
| 5.4 | 2018-10-10 | MM "rigging" adjusted | | | 6.8 | 2020-02-19 | ATGM nerf, Hellas map |
| 5.3 | 2018-09-12 | MM "rigging" started, Newbie queue added | | | 6.7 | 2020-01-15 | ATGM US Lights |
| 5.2 | 2018-08-22 | Faust map | | | 6.6 | 2019-12-18 | T-62A + Leo buffs |
| 5.1 | 2018-07-31 | New MM: vehicle class matching | | | 6.5 | 2019-11-21 | New UI |
| 5.0 | 2018-06-30 | Vineyeards map update, Spare Parts killed | | | 6.4 | 2019-10-16 | Halloween map, mid-tier HT buff... |
| 4.10 | 2018-05-24 | Alpenstadt map | | | 6.3 | 2019-09-18 | European line |
| 4.9 | 2018-04-25 | Chinese heavy tanks | | | 6.2 | 2019-08-14 | New MM |
| 4.8 | 2018-03-28 | Choice of battle modes, crew skills accelerator | | | 6.1 | 2019-07-10 | Autoloader buff |
| 4.7 | 2018-02-28 | New minimap | | | 6.0 | 2019-06-05 | UK TD line #2 |
| 4.6 | 2018-01-31 | Chinese nation | | | 5.10 | 2019-04-24 | new missions |
| 4.5 | 2017-12-19 | Dynasty's Pearl map | | | 5.9 | 2019-03-27 | New shell tracers, minor fixes |
| 4.4 | 2017-11-09 | New British tanks | | | 5.8 | 2019-02-21 | Chinese TD line |
| 4.3 | 2017-10-10 | Level 7 screw skills | | | 5.7 | 2019-01-16 | Avatars |
| 4.2 | 2017-09-12 | French LTs, Naval Frontier map | | | 5.6 | 2018-12-05 | Normandy map |
| 4.1 | 2017-08-16 | New markers | | | 5.5 | 2018-11-13 | Low-tier clean-up :-( |
| 4.0 | 2017-07-13 | Rating battles | Y | | 5.4 | 2018-10-10 | MM "rigging" adjusted |
| 3.10 | 2017-06-15 | Fixes | Y | | 5.3 | 2018-09-12 | MM "rigging" started, Newbie queue added |
| 3.9 | 2017-05-19 | Military Honor, Mayan Ruins | Y | | 5.2 | 2018-08-22 | Faust map |
| 3.8 | 2017-04-24 | Spare Parts, New 9-slot Equipment system | Y | | 5.1 | 2018-07-31 | New MM: vehicle class matching |
| 3.7 | 2017-03-22 | Balance changes, Tournaments | Y | | 5.0 | 2018-06-30 | Vineyeards map update, Spare Parts removed ! |
| 3.6 | 2017-02-16 | Vehicle Enrichment | Y | | 4.10 | 2018-05-24 | Alpenstadt map |
| 3.5 | 2017-01-13 | Boosters, Dead rail update | Y | | 4.9 | 2018-04-25 | Chinese heavy tanks |
| 3.4 | 2016-11-28 | Canyon map, USA T57 line | | | 4.8 | 2018-03-28 | Choice of battle modes, crew skills accelerator |
| 3.3 | 2016-11-01 | Updated Mines map | | | 4.7 | 2018-02-28 | New minimap |
| 3.2 | 2016-10-04 | Copperfield update | | | 4.6 | 2018-01-31 | Chinese nation |
| 3.1 | 2016-09-03 | Clan tournaments, Yamato Harbor map | Y | | 4.5 | 2017-12-19 | Dynasty's Pearl map |
| 3.0 | 2016-07-20 | Supremacy mode, Falls Creek update | Y | | 4.4 | 2017-11-09 | New British tanks |
| 2.11 | 2016-06-28 | Vineyeards map, Oasis Palms update, German paper TDs | | | 4.3 | 2017-10-10 | Level 7 screw skills |
| 2.10 | 2016-06-07 | Rockfield map update, Tank birthdays, high-pen gun for IS-6 | | | 4.2 | 2017-09-12 | French LTs, Naval Frontier map |
| 2.9 | 2016-05-03 | Training rooms, +/-1 Matchmaker | Y | | 4.1 | 2017-08-16 | New markers |
| 2.8 | 2016-04-04 | New Russian TD line, new consumables system | Y | | 4.0 | 2017-07-13 | Rating battles (date uncertain) |
| 2.7 | 2016-03-07 | Mirage map | Y | | 3.10 | 2017-06-15 | Fixes (date uncertain) |
| 2.6 | 2016-02-10 | German LTs, shooting through obstacles | Y | | 3.9 | 2017-05-19 | Military Honor, Mayan Ruins (date uncertain) |
| 2.5 | 2016-01-11 | Camouflages, Clan supply | Y | | 3.8 | 2017-04-24 | Spare Parts, New 9-slot Equipment system (date uncertain) |
| 2.4 | 2015-12-09 | Additional Japanese tanks, windows version | Y | | 3.7 | 2017-03-22 | Balance changes, Tournaments (date uncertain) |
| 2.3 | 2015-11-12 | Canal map | Y | | 3.6 | 2017-02-16 | Vehicle Enrichment (date uncertain) |
| 2.2 | 2015-10-05 | Desert Sands map update | Y | | 3.5 | 2017-01-13 | Boosters, Dead rail update (date uncertain) |
| 2.1 | 2015-09-07 | UK TDs, Clan Chat | Y | | 3.4 | 2016-11-28 | Canyon map, USA T57 line |
| 2.0 | 2015-08-05 | Clans, Oasis Palms updated | | | 3.3 | 2016-11-01 | Updated Mines map |
| 1.11 | 2015-07-13 | KV-2, KV-13, Sherman Jumbo | Y | | 3.2 | 2016-10-04 | Copperfield update |
| 1.10 | 2015-06-11 | Port Bay map | Y | | 3.1 | 2016-09-03 | Clan tournaments, Yamato Harbor map (date uncertain) |
| 1.9 | 2015-05-13 | New German medium tanks (Leo) | Y | | 3.0 | 2016-07-20 | Supremacy mode, Falls Creek update (date uncertain) |
| 1.8 | 2015-04-14 | Game tutorial, Bot map for new players | Y | | 2.11 | 2016-06-28 | Vineyeards map, Oasis Palms update, German paper TDs |
| 1.7 | 2015-02-16 | US Turreted TDs | Y | | 2.10 | 2016-06-07 | Rockfield map update, Tank birthdays, high-pen gun for IS-6 |
| 1.6 | 2015-01-19 | Castilla map, UK HT line | Y | | 2.9 | 2016-05-03 | Training rooms, +/-1 Matchmaker (date uncertain) |
| 1.5 | 2014-12-01 | UK Nation | Y | | 2.8 | 2016-04-04 | New Russian TD line, new consumables system (date uncertain) |
| 1.4 | 2014-10-29 | German HT line (Maus) | Y | | 2.7 | 2016-03-07 | Mirage map (date uncertain) |
| 1.3 | 2014-10-02 | USSR IS-4 line, Lost Temple, Black Goldville maps | Y | | 2.6 | 2016-02-10 | German LTs, shooting through obstacles (date uncertain) |
| 1.2 | 2014-08-20 | Oasis Palms map | Y | | 2.5 | 2016-01-11 | Camouflages, Clan supply (date uncertain) |
| 1.1.1 | 2014-07-23 | Fixes :-) | | | 2.4 | 2015-12-09 | Additional Japanese tanks, windows version (date uncertain) |
| 1.0 | 2014-06-26 | Worldwide launch | | | 2.3 | 2015-11-12 | Canal map (date uncertain) |
| 0.9 | 2014-05-05 | Nordic soft launch | | | 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 |
+1183 -35
View File
File diff suppressed because it is too large. Load diff
+7 -7
View File
@@ -195,7 +195,7 @@ async def replayWorker(queue: asyncio.Queue, workerID: int, account_id: int, pri
bu.verbose_std(msg_str + title + ' has already been posted. Skipping.' ) bu.verbose_std(msg_str + title + ' has already been posted. Skipping.' )
else: else:
os.remove(replay_json_fn) os.remove(replay_json_fn)
bu.debug(msg_str + "Replay JSON not valid: Deleting " + replay_json_fn, id=workerID) bu.debug(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
@@ -216,13 +216,13 @@ async def replayWorker(queue: asyncio.Queue, workerID: int, account_id: int, pri
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(msg_str +'Replay file is not valid: ' + filename) bu.warning(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: ' + filename) bu.error(msg_str + 'Replay file is not valid/complete: ' + filename)
ERROR_N += 1 ERROR_N += 1
except Exception as err: except Exception as err:
bu.error(msg_str + 'Unexpected Exception: ' + str(type(err)) + ' : ' + str(err) ) bu.error(msg_str + 'Unexpected Exception: ' + str(type(err)) + ' : ' + str(err) )
@@ -287,13 +287,13 @@ def getTitle(replayfile: str, title: str = None, i : int = 0) -> str:
try: try:
metadata_json = json.load(meta) metadata_json = json.load(meta)
#player = metadata_json['playerName'] #player = metadata_json['playerName']
tank = wg.tank_str2name(metadata_json['playerVehicleName']) tank_name = wg.get_tank_name(metadata_json['vehicleCompDescriptor'])
map_name = wg.get_map(metadata_json['mapName']) map_name = wg.get_map(metadata_json['mapName'])
bu.debug('Tank: ' + tank + ' Map: ' + map_name) bu.debug('Tank: ' + tank_name if tank_name != 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 != None) and (map_name != None): if (tank_name != None) and (map_name != None):
title = tank + ' @ ' + map_name title = tank_name + ' @ ' + map_name
else: else:
title = re.sub('\\.wotbreplay$', '', filename) title = re.sub('\\.wotbreplay$', '', filename)
except Exception as err: except Exception as err: