import re class Demo: def __init__(self, demo="0:0"): self.set(demo) def __delitem__(self, key): if isinstance(key, int): start, stop = key, key+1 elif isinstance(key, slice): start, stop = key.start, key.stop self.demo = self.demo[:start] + self.demo[stop:] self.length = len(self.demo) def __iter__(self): return iter(map(lambda n: int(n, 16), list(self.demo))) def __getitem__(self, key): return self.demo[key] def __len__(self): return self.length def __nonzero__(self): return self.length != 0 def __setitem__(self, key, value): if isinstance(key, int): start, stop = key, key+1 elif isinstance(key, slice): start, stop = key.start, key.stop self.demo = self.demo[:start] + value + self.demo[stop:] self.length = len(self.demo) def __str__(self): return self.demo def decode(self, demo=None): if demo == None: demo = self.demo # self.demo pads to 7 characters, so dividing its length # by 7 will always yield an integer fragment_count = len(demo) / 7 fragment_list = [str(int(demo[i*7:(i+1)*7][::-1], 16)) for i in range(fragment_count)] return str(self.length) + ':' + '|'.join(fragment_list) def set(self, demo): if self.validate(demo): if ':' in demo: # format is 18:0|35782656|35791394|0 self.length = int(demo.split(':')[0]) self.demo = ''.join( [("%07X" % (int(fragment)))[::-1] for fragment in demo.split(":")[1].split("|")]) else: # format is 0111C5540 self.length = len(demo) self.demo = demo else: raise Exception("Failed to set demo data: " + demo) def validate(self, demo): return re.match("^\d+:\d+(\|\d+)*$", demo) or \ re.match("^[0-9A-Fa-f]+$", demo) if __name__ == "__main__": # Demonstration mydemo = Demo("148:35791392|107405858|107374182|71582788|71582788|89408580|89478485|17895765|17895697|17895697|17895697|17895697|17895697|17895697|17895697|17895697|219222289|219223381|89478485|18175317|17|0") print mydemo, '\n\n', \ mydemo.length, '\n\n', \ mydemo.decode(), '\n\n', \ list(mydemo), '\n\n', \ mydemo[5], '\n\n', \ mydemo[5:40], '\n' # Use bitwise AND to see if each frame has the player holding jump print ''.join(['j' if frame & 4 else '.' for frame in mydemo]) mydemo[15:25] = '0000000000' print mydemo[5:40] del mydemo[15:25] print mydemo.length print mydemo[5:40] print 'Not null' if mydemo else 'Null' mydemo.set('0:0') print 'Not null' if mydemo else 'Null'