[eve] Tests pass !
Add load_options to dump & load test strategy
This commit is contained in:
parent
f72e875898
commit
9c0850f98d
@ -43,11 +43,11 @@ def _load_eve(lines: List[str], file_path: Path, *, beat_snap: int = 240) -> son
|
||||
]
|
||||
time_map = TimeMap.from_seconds(bpms)
|
||||
tap_notes: List[AnyNote] = [
|
||||
make_tap_note(e.time, e.value, time_map)
|
||||
make_tap_note(e.time, e.value, time_map, beat_snap)
|
||||
for e in events_by_command[Command.PLAY]
|
||||
]
|
||||
long_notes: List[AnyNote] = [
|
||||
make_long_notes(e.time, e.value, time_map)
|
||||
make_long_note(e.time, e.value, time_map, beat_snap)
|
||||
for e in events_by_command[Command.LONG]
|
||||
]
|
||||
all_notes = sorted(tap_notes + long_notes, key=lambda n: (n.time, n.position))
|
||||
@ -102,22 +102,26 @@ def parse_event(line: str) -> Event:
|
||||
return Event(tick, command, value)
|
||||
|
||||
|
||||
def make_tap_note(ticks: int, value: int, time_map: TimeMap) -> song.TapNote:
|
||||
def make_tap_note(
|
||||
ticks: int, value: int, time_map: TimeMap, beat_snap: int
|
||||
) -> song.TapNote:
|
||||
seconds = ticks_to_seconds(ticks)
|
||||
raw_beats = time_map.beats_at(seconds)
|
||||
beats = round_beats(raw_beats)
|
||||
beats = round_beats(raw_beats, beat_snap)
|
||||
position = song.NotePosition.from_index(value)
|
||||
return song.TapNote(time=beats, position=position)
|
||||
|
||||
|
||||
def make_long_notes(ticks: int, value: int, time_map: TimeMap) -> song.LongNote:
|
||||
def make_long_note(
|
||||
ticks: int, value: int, time_map: TimeMap, beat_snap: int
|
||||
) -> song.LongNote:
|
||||
seconds = ticks_to_seconds(ticks)
|
||||
raw_beats = time_map.beats_at(seconds)
|
||||
beats = round_beats(raw_beats)
|
||||
beats = round_beats(raw_beats, beat_snap)
|
||||
eve_long = EveLong.from_value(value)
|
||||
seconds_duration = ticks_to_seconds(eve_long.duration)
|
||||
raw_beats_duration = time_map.beats_at(seconds + seconds_duration) - raw_beats
|
||||
beats_duration = round_beats(raw_beats_duration)
|
||||
beats_duration = round_beats(raw_beats_duration, beat_snap)
|
||||
position = song.NotePosition.from_index(eve_long.position)
|
||||
direction = VALUE_TO_DIRECTION[eve_long.direction]
|
||||
step_vector = song.TAIL_DIRECTION_TO_OUTWARDS_VECTOR[direction]
|
||||
|
@ -4,7 +4,7 @@ from decimal import Decimal
|
||||
from pathlib import Path
|
||||
from typing import Iterator
|
||||
|
||||
from hypothesis import Verbosity, given, settings
|
||||
from hypothesis import given
|
||||
from hypothesis import strategies as st
|
||||
|
||||
from jubeatools import song
|
||||
@ -20,19 +20,24 @@ simple_beat_strat = jbst.beat_time(
|
||||
|
||||
@st.composite
|
||||
def eve_compatible_song(draw: DrawFunc) -> song.Song:
|
||||
"""eve only keeps notes, timing info and difficulty"""
|
||||
"""eve only keeps notes, timing info and difficulty,
|
||||
the precision you can get out of it is also severly limited"""
|
||||
diff = draw(st.sampled_from(list(song.Difficulty)))
|
||||
chart = draw(
|
||||
jbst.chart(
|
||||
timing_strat=jbst.timing_info(
|
||||
with_bpm_changes=True,
|
||||
bpm_strat=st.decimals(min_value=1, max_value=500, places=2),
|
||||
bpm_strat=st.decimals(min_value=50, max_value=300, places=2),
|
||||
beat_zero_offset_strat=st.decimals(min_value=0, max_value=20, places=2),
|
||||
time_strat=simple_beat_strat,
|
||||
time_strat=jbst.beat_time(
|
||||
min_section=1,
|
||||
max_section=10,
|
||||
denominator_strat=st.sampled_from([4, 8, 3]),
|
||||
),
|
||||
),
|
||||
notes_strat=jbst.notes(
|
||||
note_strat=st.one_of(
|
||||
jbst.tap_note(time_start=simple_beat_strat),
|
||||
jbst.tap_note(time_strat=simple_beat_strat),
|
||||
jbst.long_note(
|
||||
time_strat=simple_beat_strat,
|
||||
duration_strat=jbst.beat_time(
|
||||
@ -41,7 +46,8 @@ def eve_compatible_song(draw: DrawFunc) -> song.Song:
|
||||
denominator_strat=st.sampled_from([4, 8, 3]),
|
||||
),
|
||||
),
|
||||
)
|
||||
),
|
||||
beat_time_strat=simple_beat_strat,
|
||||
),
|
||||
level_strat=st.just(Decimal(0)),
|
||||
)
|
||||
@ -59,11 +65,11 @@ def open_temp_dir() -> Iterator[Path]:
|
||||
|
||||
|
||||
@given(eve_compatible_song())
|
||||
@settings(verbosity=Verbosity.normal)
|
||||
def test_that_full_chart_roundtrips(song: song.Song) -> None:
|
||||
dump_and_load_then_compare(
|
||||
Format.EVE,
|
||||
song,
|
||||
temp_path=open_temp_dir(),
|
||||
bytes_decoder=lambda b: b.decode("ascii"),
|
||||
load_options={"beat_snap": 24},
|
||||
)
|
||||
|
@ -70,9 +70,9 @@ def note_position(draw: DrawFunc) -> NotePosition:
|
||||
|
||||
@st.composite
|
||||
def tap_note(
|
||||
draw: DrawFunc, time_start: st.SearchStrategy[BeatsTime] = beat_time(max_section=10)
|
||||
draw: DrawFunc, time_strat: st.SearchStrategy[BeatsTime] = beat_time(max_section=10)
|
||||
) -> TapNote:
|
||||
time = draw(time_start)
|
||||
time = draw(time_strat)
|
||||
position = draw(note_position())
|
||||
return TapNote(time, position)
|
||||
|
||||
@ -117,9 +117,6 @@ def notes(
|
||||
tap_note(), long_note()
|
||||
),
|
||||
beat_time_strat: st.SearchStrategy[BeatsTime] = beat_time(max_section=3),
|
||||
beat_interval_strat: st.SearchStrategy[BeatsTime] = beat_time(
|
||||
min_numerator=1, max_section=3
|
||||
),
|
||||
) -> Set[Union[TapNote, LongNote]]:
|
||||
raw_notes: Set[Union[TapNote, LongNote]] = draw(st.sets(note_strat, max_size=32))
|
||||
|
||||
@ -135,7 +132,11 @@ def notes(
|
||||
if last_note_time is None:
|
||||
new_time = draw(beat_time_strat)
|
||||
else:
|
||||
new_time = last_note_time + draw(beat_interval_strat)
|
||||
numerator = draw(
|
||||
st.integers(min_value=1, max_value=last_note_time.denominator * 4)
|
||||
)
|
||||
distance = BeatsTime(numerator, last_note_time.denominator)
|
||||
new_time = last_note_time + distance
|
||||
if isinstance(note, LongNote):
|
||||
notes.add(
|
||||
LongNote(
|
||||
|
@ -14,16 +14,18 @@ def dump_and_load_then_compare(
|
||||
song: song.Song,
|
||||
temp_path: ContextManager[Path],
|
||||
bytes_decoder: Callable[[bytes], str],
|
||||
load_options: Optional[dict] = None,
|
||||
dump_options: Optional[dict] = None,
|
||||
) -> None:
|
||||
load_options = load_options or {}
|
||||
dump_options = dump_options or {}
|
||||
loader = LOADERS[format_]
|
||||
dumper = DUMPERS[format_]
|
||||
with temp_path as path:
|
||||
files = dumper(song, path, **(dump_options or {}))
|
||||
files = dumper(song, path, **dump_options)
|
||||
for path, bytes_ in files.items():
|
||||
path.write_bytes(bytes_)
|
||||
note(f"Wrote to {path} :\n{bytes_decoder(bytes_)}")
|
||||
assert guess_format(path) == format_
|
||||
recovered_song = loader(path)
|
||||
recovered_song = loader(path, **load_options)
|
||||
assert recovered_song == song
|
||||
|
Loading…
Reference in New Issue
Block a user