Skip to content
This repository has been archived by the owner on Jan 27, 2021. It is now read-only.

Support parsing on other three modes #7

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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).
39 changes: 34 additions & 5 deletions circleparse/replay.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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]
Expand Down Expand Up @@ -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)
Expand Down