def read_mapfile(fn): comments = [] status = None blockstrings = [] with open(fn, 'r') as f: for line in f: if line.startswith("#"): comments.append(line) elif status is None: status = line else: blockstrings.append(line) # Post-processing status = status.split() status[0] = int(status[0], base=0) status[2] = int(status[2], base=0) status = tuple(status) blocks = [] for blockstring in blockstrings: spl = blockstring.split() start = int(spl[0], base=0) length = int(spl[1], base=0) char = spl[2] blocks.append((start, length, char)) return (status, blocks, comments) class MapFile: def __init__(self, filename, start=None, end=None): self.mapfilename = filename self.start = start if start is not None else 0 self.end = end def load(self): self.status, self.blocks, self.comments = read_mapfile(self.mapfilename) # Virtual self-position block self.blocks.append((self.status[0], 1, '@')) if self.end is not None: # FIXME: what about only start being set? self.filter_data() self.size = max(map(lambda blk: blk[0]+blk[1], self.blocks)) def filter_data(self): self.blocks = self.filter_blocks(self.blocks, self.start, self.end) self.blocks = self.trim_blocks(self.blocks, self.start, self.end) # Move blocks: self.status = tuple([self.status[0] - self.start, *self.status[1:]]) nblocks = [] for blk in self.blocks: nblk = tuple([blk[0] - self.start, *blk[1:]]) nblocks.append(nblk) self.blocks = nblocks def get_state(self, pos): # TODO: this is lame for blk in self.blocks: if pos >= blk[0] and pos < blk[0] + blk[1]: return blk[2] @staticmethod def filter_blocks(blocks, start, end): relevant_blocks = [] for blk in blocks: if start < blk[0] + blk[1] and end >= blk[0]: relevant_blocks.append(blk) return relevant_blocks @staticmethod def trim_blocks(blocks, start, end): trmblks = [] for blk in blocks: bg, lt, symb = blk if bg < start: lt -= start - bg bg = start if bg + lt > end: lt -= bg+lt - end trmblks.append((bg, lt, symb)) return trmblks def get_hist(self, start, end): relevant_blocks = self.filter_blocks(self.blocks, start, end) trmblks = self.trim_blocks(relevant_blocks, start, end) # Grouping by symbols: grp = {} for blk in trmblks: if blk[2] not in grp: grp[blk[2]] = 0 grp[blk[2]] += blk[1] return grp