''' Created on Aug 18, 2019 @author: Brett Paufler (c) Copyright Brett Paufler Parses the Logfile ''' ''' Created on Apr 25, 2018 @author: Brett Paufler Copyright Brett Paufler To Parse BUG Logfiles We'll see how it goes Gets Graphs: 1) Research, Gold, Espionage, Culture 2) Total Population TODO: take draft into account Takes a CIV 4 The Bat Mod Log file Outputs Graphs ''' from os import listdir #from os.path import join as path_join import re from datetime import datetime #from collections import defaultdict #import matplotlib.pyplot as plt #dir_in = './input/' #dir_out = './output/' #test_file = '14-montezume_bat_autolog.txt' #log_list = [path_join(dir_in, log_file) # for log_file in listdir(dir_in)] class Turn(object): '''Holds and extracts each turn object.''' def __init__(self, text): #print 'Turn' self.text = text self.lines = self.text.split('\n') self.num = int(re.match( '\d*', self.text).group(0)) #Clearly Crap, Munged to Death, but Works self.date_str = self.lines[0][-21:-1] self.date = datetime.strptime( self.date_str, '%d-%b-%Y %H:%M:%S') self.research_percent = 0 self.research_amount = 0 self.gold_percent = 0 self.gold_amount = 0 self.culture_percent = 0 self.culture_amount = 0 self.espionage_percent = 0 self.espionage_amount = 0 research_line = [line for line in self.lines if '% Research: ' in line] gold_line = [line for line in self.lines if '% Gold: ' in line] culture_line = [line for line in self.lines if '% Culture: ' in line] espionage_line = [line for line in self.lines if '% Espionage: ' in line] if research_line: parts = research_line[0].split() self.research_percent = int(parts[0][:-1]) self.research_amount = int(parts[2]) if gold_line: parts = gold_line[0].split() self.gold_percent = int(parts[0][:-1]) self.gold_amount = int(parts[2]) if culture_line: parts = culture_line[0].split() self.culture_percent = int(parts[0][:-1]) self.culture_amount = int(parts[2]) if espionage_line: parts = espionage_line[0].split() self.espionage_percent = int(parts[0][:-1]) self.espionage_amount = int(parts[2]) #Techs per Turn Finished #print 'Here' self.tech_finished = [] #SELF TECHING tech_finished_lines = [line for line in self.lines if 'Tech research finished: ' in line] if tech_finished_lines: #print'Tech Inside' for line in tech_finished_lines: tech = line[24:] self.tech_finished.append(tech) #print line #print civ_parse_tech_tree #TECH ACQUIRED: Trade and Whatnot tech_acquired_lines = [line for line in self.lines if 'Tech acquired (trade, lightbulb, hut, espionage): ' in line] if tech_acquired_lines: for line in tech_acquired_lines: tech = line[50:] self.tech_finished.append(tech) #print line #print civ_parse_tech_tree #civ_parse_tech_tree#Tech acquired #Growth is a Dictionary of Cities #CityName: Population growth_pairs = [line.split(' grows to size ') for line in self.lines if ' grows to size ' in line] self.growth = dict([(city, int(size)) for city, size in growth_pairs ]) #print growth #List of Cities Where Whip Was Used self.whips = [line[24:] for line in self.lines if 'The whip was applie' in line] #print whips #Cities captured This turn self.captured = [line.split(' ')[1] for line in self.lines if line.startswith('Captured')] #print self.captured #Wonders are very Specific #Will need list of Wonders #Tenochtitlan finishes: The Great Wall #Cities founded is counfounded with religions #Maybe will not do, not this go round def __repr__(self): text = 'Turn %d\n' % self.num text += '\tR %3d%%: %d\n' % ( self.research_percent, self.research_amount) text += '\tG %3d%%: %d\n' % ( self.gold_percent, self.gold_amount) text += '\tE %3d%%: %d\n' % ( self.espionage_percent, self.espionage_amount) text += '\tC %3d%%: %d\n' % ( self.culture_percent, self.culture_amount) return text class Game(object): '''Extracts Game info from each logfile, utilizing turn object above ''' def __repr__(self): text = '%s: %d Turns' % ( self.name, self.num_turns) #text + return text def __init__(self, file_path): #Toggled by self.cleanse() if turns removed #Dirty: True means turns were replayed self.dirty = False with open(file_path, 'r') as f: self.name = file_path[8:-4] self.text_raw = f.read() #Removes Blank Lines, Logging Line, --- lines self.text = '\n'.join( line.strip() for line in self.text_raw.split('\n') if line.strip() #blank lines if not line.startswith('Logging by BUG') if not line.startswith('-----') ) reg = re.compile( '^Turn ', flags=re.MULTILINE | re.DOTALL ) #(?!^Turn)') raw_turns = reg.split(self.text) self.turns = [Turn(turn) for turn in raw_turns if turn] self.cleanse() self.num_turns = len(self.turns) #print self.name def cleanse(self): '''Removes multiple turns.''' len_start = len(self.turns) #Running List of turns_to_keep = [] turn_nums_in_keepers = [] while self.turns: turn = self.turns.pop() #print turn.num, turn_nums_in_keepers if not turn.num in turn_nums_in_keepers: turn_nums_in_keepers.append(turn.num) turns_to_keep.append(turn) #print turn.num, turn_nums_in_keepers self.turns = turns_to_keep[::-1] if len_start != len(turns_to_keep): self.dirty = True if __name__ == "__main__": test_logfile_path = './input/' + listdir('.//input//')[0] #print test_logfile_path game = Game(test_logfile_path) print game