Created
March 15, 2016 01:58
-
-
Save alexjurkiewicz/2ff515578cda9a2d268b to your computer and use it in GitHub Desktop.
This file contains hidden or 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 | |
"""Calculate DCSS spell usage from morgues.""" | |
import subprocess | |
import collections | |
total_dacts = collections.Counter() | |
def find_morgue_files(d): | |
"""Return a list of all morgue files. XXX Should be pure python.""" | |
cmd = ['find', d, '-name', 'morgue-*-201*-*.txt', '-type', 'f'] | |
return subprocess.check_output(cmd).splitlines() | |
def validate_morgue(data): | |
"""Raise an error if the morgue has a problem.""" | |
if 'Dungeon Crawl Stone Soup' not in data[0]: | |
raise ValueError("Couldn't find version signature.") | |
if 'Began as a' not in data[3]: | |
raise ValueError("Couldn't find character.") | |
return True | |
def parse_player_combo(combo): | |
"""Stupid code to convert eg Vine Stalker Venom Mage into a char/bg tuple. | |
Currently normalises draconians. | |
XXX make not stupid. | |
""" | |
combo_split = combo.split() | |
if len(combo_split) == 2: | |
return combo_split | |
elif len(combo_split) == 4: | |
if combo_split[1] == 'Draconian': | |
return 'Draconian', ' '.join(combo_split[2:4]) | |
else: | |
return ' '.join(combo_split[0:2]), ' '.join(combo_split[2:4]) | |
else: | |
if combo_split[0] in ('Hill', 'Vine', 'High', 'Deep', 'Ice'): | |
return ' '.join(combo_split[0:2]), combo_split[2] | |
elif combo_split[1] == 'Draconian': | |
return 'Draconian', combo_split[2] | |
elif combo_split[1] in ('Fire', 'Ice', 'Earth', 'Air', 'Venom', | |
'Arcane', 'Death', 'Chaos', 'Abyssal'): | |
return combo_split[0], ' '.join(combo_split[1:3]) | |
raise AttributeError(combo) | |
def parse_dacts(data): | |
"""Parse a morgue file and return dact data. | |
Crappy state machine. | |
""" | |
found_dacts = False | |
dact_section = None | |
dact_data = {} | |
for line in data: | |
if line.startswith('Action') and line.endswith('|| total'): | |
found_dacts = True | |
dact_columns = len(line.split('|')) - 1 | |
continue | |
if found_dacts: | |
if line.startswith('-------------------------'): | |
continue | |
dact_line = line.split('|') | |
if len(dact_line) != dact_columns + 1: | |
# End of table | |
return dact_data | |
if ':' in dact_line[0]: | |
# Parse the section header and then remove it so other logic | |
# is kept the same. | |
dact_section = dact_line[0].split(':')[0] | |
dact_line[0] = dact_line[0].split(':')[1] | |
dact_data[dact_section] = {} | |
dact_name = dact_line[0].strip() | |
dact_data["%s-%s" % | |
(dact_section, dact_name)] = dact_line[-1].strip() | |
def process_morgue(path): | |
"""Process a morgue file.""" | |
with open(path) as f: | |
data = f.read().splitlines() | |
# Don't need this stuff right now, just slows processing | |
# if not validate_morgue(data): | |
# print("Couldn't parse %s" % path) | |
# raise ValueError | |
# version = re.search('version (.*) \((console|webtiles)\)', data[0]).group(1) | |
# canonical_version = re.match('[0-9.]+', version).group(0) | |
# race, background = parse_player_combo(re.search('Began as an? (.*) on', data[3]).group(1)) | |
dacts = parse_dacts(data) | |
if dacts: | |
for k, v in dacts.items(): | |
total_dacts[k] += 1 | |
if __name__ == '__main__': | |
morgues = find_morgue_files('morgue') | |
for morgue in morgues: | |
process_morgue(morgue) | |
print(total_dacts) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment