1
0
mirror of synced 2024-12-04 19:17:55 +01:00

[eve] Tests pass !

Add load_options to dump & load test strategy
This commit is contained in:
Stepland 2021-05-12 12:58:22 +02:00
parent f72e875898
commit 9c0850f98d
4 changed files with 35 additions and 22 deletions

View File

@ -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]

View File

@ -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},
)

View File

@ -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(

View File

@ -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