diff --git a/README.md b/README.md index 3ce1944..203abe4 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,8 @@ self.replay_hash #String self.number_300s #Integer self.number_100s #Integer self.number_50s #Integer -self.gekis #Integer -self.katus #Integer +self.gekis #Integer, MAX 300 in mania +self.katus #Integer, 200 in mania self.misses #Integer self.score #Integer self.max_combo #Integer @@ -69,7 +69,8 @@ ReplayEvent instances provide these fields ```python self.time_since_previous_action #Integer representing time in milliseconds -self.x #x axis location +self.x #x axis location, integer value of key press self.y #y axis location self.keys_pressed #bitwise sum of keys pressed, documented in OSR format page ``` +For osu!mania replay files, `self.x` refers to the integer value of the key press, `self.y` always returns `None`, and `self.keys_pressed` is the reverse binary equivalent of `self.x`. This process was based from Swan's [Respository](https://github.com/Swan/osuReplayParser). \ No newline at end of file diff --git a/circleparse/replay.py b/circleparse/replay.py index a9fb1da..ac2b83e 100644 --- a/circleparse/replay.py +++ b/circleparse/replay.py @@ -139,11 +139,22 @@ def parse_timestamp_and_replay_length(self, replay_data): def parse_play_data(self, replay_data): offset_end = self.offset+self.replay_length - if self.game_mode != GameMode.STD: - self.play_data = None + datastring = lzma.decompress(replay_data[self.offset:offset_end], format=lzma.FORMAT_AUTO).decode('ascii')[:-1] + events = [eventstring.split('|') for eventstring in datastring.split(',')] + if self.game_mode == GameMode.MANIA: + # Keys pressed in mania is based from the integer value of self.x converted to binary then reversed + def map_columns(event): + event = '{0:010b}'.format(event)[::-1] # '0110000000' means Key 1 and 2 (zero-indexing) were pressed + dict_mapping = {0:False, 1:False, 2:False, \ + 3:False, 4:False, 5:False, \ + 6:False, 7:False, 8:False, 9:False} + for i in range(10): + if event[i] == '1': + dict_mapping[i] = True + return dict_mapping + + self.play_data = [ReplayEvent(int(event[0]), int(event[1]), None, map_columns(int(event[1]))) for event in events] # self.y is insignificant to o!m else: - datastring = lzma.decompress(replay_data[self.offset:offset_end], format=lzma.FORMAT_AUTO).decode('ascii')[:-1] - events = [eventstring.split('|') for eventstring in datastring.split(',')] self.play_data = [ReplayEvent(int(event[0]), float(event[1]), float(event[2]), int(event[3])) for event in events] self.offset = offset_end @@ -163,7 +174,22 @@ def data_from_lmza(self, lzma_string, decompressed_lzma): else: datastring = lzma.decompress(lzma_string, format=lzma.FORMAT_AUTO).decode('ascii')[:-1] events = [eventstring.split('|') for eventstring in datastring.split(',')] - self.play_data = [ReplayEvent(int(event[0]), float(event[1]), float(event[2]), int(event[3])) for event in events] + + if self.game_mode == GameMode.MANIA: + + def map_columns(event): + event = '{0:010b}'.format(event)[::-1] + dict_mapping = {0:False, 1:False, 2:False, \ + 3:False, 4:False, 5:False, \ + 6:False, 7:False, 8:False, 9:False} + for i in range(10): + if event[i] == '1': + dict_mapping[i] = True + return dict_mapping + + self.play_data = [ReplayEvent(int(event[0]), int(event[1]), None, map_columns(int(event[1]))) for event in events] + else: + self.play_data = [ReplayEvent(int(event[0]), float(event[1]), float(event[2]), int(event[3])) for event in events] if self.play_data[-1].time_since_previous_action == -12345: del self.play_data[-1] @@ -200,6 +226,9 @@ def parse_replay(replay_data, pure_lzma, decompressed_lzma=False): Returns: A Replay object with the fields specific in the Replay's init method. If pure_lzma is False, all fields will be filled (nonnull). If pure_lzma is True, only the play_data will be filled. + If the Replay object GameMode is MANIA, self.keys_pressed returns as a dictionary of key columns with length 10. + Each key represents a column from 0 to 9 while the values are boolean that represents key press. + The length of the dictionary stays constant regardless of the keymode of the beatmap. """ return Replay(replay_data, pure_lzma, decompressed_lzma)