Skip to content

Instantly share code, notes, and snippets.

@cgarz
Last active March 23, 2021 06:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cgarz/fc6c2ed41c79683feaa4114865dbc03e to your computer and use it in GitHub Desktop.
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.
#!/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