Last active
March 23, 2021 06:05
-
-
Save cgarz/fc6c2ed41c79683feaa4114865dbc03e to your computer and use it in GitHub Desktop.
Simple python script for Worms Armageddon to get the total time from all replay files logs. Optionally exporting them first if not present.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
from datetime import timedelta | |
from subprocess import run, DEVNULL | |
from mmap import mmap, ACCESS_READ | |
import os, re | |
# CHANGE ME | |
WA_DIR = r'C:\PATH\TO\WA\INSTALL\CHANGE\ME' | |
# Examples: | |
# C:\Program Files (x86)\Steam\steamapps\common\Worms Armageddon | |
# C:\GOG Games\Worms Armageddon | |
# C:\Team17\Worms Armageddon | |
ROUND_LINE = 'Round time: ' | |
GAME_SUBDIR = os.path.join('User', 'Games') | |
TOTAL_TIME_RE = re.compile(rb'\[(?P<timestamp>\d\d:\d\d:\d\d.\d\d)] \x95\x95\x95 Game Ends - .*\r\n') | |
EXPORT_LOG_ARGS = ('WA.exe', '/q', '/getlog') | |
def pause_exit(exit_code): | |
input('Press enter to close') | |
exit(exit_code) | |
def main(): | |
if not os.path.exists(WA_DIR): | |
print('ERROR: Specified WA installation dir does not exist. Edit WA_DIR at the top of this file accordingly.') | |
pause_exit(1) | |
os.chdir(WA_DIR) | |
if not os.path.exists('WA.exe'): | |
print('ERROR: Specified WA installation dir does not contain WA.exe. Edit WA_DIR at the top of this file accordingly or check installation.') | |
pause_exit(1) | |
print('Getting WAgame files list.') | |
games = [f for f in os.listdir(GAME_SUBDIR) if f.endswith('.WAgame')] | |
print('Done.', len(games), 'WAgame files.\n') | |
print('Getting log files list.') | |
logs = [f for f in os.listdir(GAME_SUBDIR) if f.endswith('.log')] | |
print('Done.', len(logs), 'log files.\n') | |
if len(logs) < len(games): | |
print('There are', len(games), 'games but only', len(logs), 'logs in the Games dir.') | |
print('Do you want to export all unexported logs?') | |
ret = input('[Yes/No]: ') | |
if ret.upper() in ('Y', 'YES'): | |
games_width = len(str(len(games))) | |
partial_write = False | |
try: | |
for idx, game in enumerate(games, start=1): | |
print('\rExporting log {current:0{padding}d}/{total:0{padding}d}. Ctrl+C to quit early.'.format( | |
current=idx, | |
total=len(games), | |
padding=games_width | |
), end=' ') | |
path = os.path.join(GAME_SUBDIR, game) | |
if not os.path.getsize(path) > 0: | |
continue | |
log_path = os.path.splitext(path)[0] + '.log' | |
if os.path.exists(log_path) and os.path.getsize(log_path) > 0: | |
continue | |
args = EXPORT_LOG_ARGS + (path,) | |
partial_write = True | |
run(args, stdout=DEVNULL) | |
partial_write = False | |
print() | |
except KeyboardInterrupt: | |
print('\nGot KeyboardInterrupt, quitting early.') | |
if partial_write and os.path.exists(log_path): | |
print('WA was terminated early. Removing potentially corrupted log:\n', log_path, sep='') | |
os.remove(log_path) | |
print('\nGetting log files list again.') | |
logs = [f for f in os.listdir(GAME_SUBDIR) if f.endswith('.log')] | |
print('Done.', len(logs), 'log files.') | |
else: | |
print('Okay, skipping export, total time may be less accurate.') | |
print() | |
logs_width = len(str(len(logs))) | |
total_time = timedelta() | |
for idx, log in enumerate(logs, start=1): | |
print(f'Parsing log {idx:0{logs_width}d}/{len(logs):0{logs_width}d}', end='\r') | |
path = os.path.join(GAME_SUBDIR, log) | |
with open(path, 'rb') as f: | |
mm = mmap(f.fileno(), 0, access=ACCESS_READ) | |
match = re.search(TOTAL_TIME_RE, mm) | |
if match: | |
timestamp = match.group('timestamp').decode() | |
*h, m, s = list(map(float, timestamp.split(':'))) | |
total_time += timedelta(hours=next(iter(h), 0), minutes=m, seconds=s) | |
else: | |
print('ERROR: No data for:', log) | |
input('Press enter to continue') | |
mm.close() | |
min, sec = map(int, divmod(total_time.total_seconds(), 60)) | |
hour, min = map(int, divmod(min, 60)) | |
# day, hour = map(int, divmod(hour, 24)) | |
print( | |
'\n', | |
'\n', | |
'Total game time played:', | |
'\n', | |
# day, ' days, ', | |
hour, ' hours, ', | |
min, ' minutes, and ', | |
sec, ' seconds.', | |
'\n', | |
sep='' | |
) | |
if __name__ == '__main__': | |
try: | |
main() | |
except KeyboardInterrupt: | |
print('Got interrupt, quitting...') | |
pass | |
pause_exit(0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment