|
|
|
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
|
|
|
|
self.end = end
|
|
|
|
|
|
|
|
def load(self):
|
|
|
|
self.status, self.blocks, self.comments = read_mapfile(self.mapfilename)
|
|
|
|
if self.start is not None or self.end is not None:
|
|
|
|
self.filter_data()
|
|
|
|
self.size = max(map(lambda blk: blk[0]+blk[1], self.blocks))
|
|
|
|
|
|
|
|
def filter_data(self):
|
|
|
|
assert self.start is not None and self.end is not None
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|