Пример #1
0
def test_irregular_beats_per_frame_2() -> None:
    chart = """
        b=1
        ①□□□
        □□□□
        □□□□
        □□□□
        --
        □□□□
        □①□□
        □□□□
        □□□□
        --
        b=2.75
        □□□□
        □□□□
        □□①□
        □□□□
        --
        □□□□
        □□□□
        □□□□
        □□□①
        --
        """
    expected = [
        TapNote(BeatsTime("0.00"), NotePosition(0, 0)),
        TapNote(BeatsTime("1.00"), NotePosition(1, 1)),
        TapNote(BeatsTime("2.00"), NotePosition(2, 2)),
        TapNote(BeatsTime("4.75"), NotePosition(3, 3)),
    ]
    compare_chart_notes(chart, expected)
Пример #2
0
def tap_note(
    draw: DrawFunc,
    time_strat: st.SearchStrategy[BeatsTime] = beat_time(max_section=10)
) -> TapNote:
    time = draw(time_strat)
    position = draw(note_position())
    return TapNote(time, position)
Пример #3
0
 def _iter_notes_without_longs(self) -> Iterator[TapNote]:
     for currently_defined_symbols, frame in self._iter_frames():
         # cross compare symbols with the position information
         for y, x in product(range(4), range(4)):
             symbol = frame.position_part[y][x]
             try:
                 symbol_time = currently_defined_symbols[symbol]
             except KeyError:
                 continue
             position = NotePosition(x, y)
             yield TapNote(symbol_time, position)
Пример #4
0
 def _iter_notes_without_longs(self) -> Iterator[TapNote]:
     section_starting_beat = BeatsTime(0)
     for section in self.sections:
         for bloc, y, x in product(section.blocs(), range(4), range(4)):
             symbol = bloc[y][x]
             if symbol in section.symbols:
                 symbol_time = section.symbols[symbol]
                 note_time = section_starting_beat + symbol_time
                 position = NotePosition(x, y)
                 yield TapNote(note_time, position)
         section_starting_beat += section.length
Пример #5
0
def test_simple_section() -> None:
    chart = """
        ①□□□
        □⑤□□
        □□⑨□
        □□□⑬
        -------
        """
    expected = [
        TapNote(time=BeatsTime(i), position=NotePosition(i, i)) for i in range(4)
    ]
    compare_chart_notes(chart, expected)
Пример #6
0
    def _iter_notes(self) -> Iterator[Union[TapNote, LongNote]]:
        unfinished_longs: Dict[NotePosition, UnfinishedLongNote] = {}
        for section_starting_beat, section, bloc in self._iter_blocs():
            should_skip: Set[NotePosition] = set()
            # 1/3 : look for ends to unfinished long notes
            for pos, unfinished_long in unfinished_longs.items():
                x, y = astuple(pos)
                symbol = bloc[y][x]
                if self.circle_free and symbol in CIRCLE_FREE_SYMBOLS:
                    should_skip.add(pos)
                    symbol_time = CIRCLE_FREE_TO_BEATS_TIME[symbol]
                    note_time = section_starting_beat + symbol_time
                    yield unfinished_long.ends_at(note_time)
                elif symbol in section.symbols:
                    should_skip.add(pos)
                    symbol_time = section.symbols[symbol]
                    note_time = section_starting_beat + symbol_time
                    yield unfinished_long.ends_at(note_time)

            unfinished_longs = {
                k: unfinished_longs[k]
                for k in unfinished_longs.keys() - should_skip
            }

            # 2/3 : look for new long notes starting on this bloc
            arrow_to_note_candidates = find_long_note_candidates(
                bloc, section.symbols.keys(), should_skip)
            if arrow_to_note_candidates:
                solution = pick_correct_long_note_candidates(
                    arrow_to_note_candidates,
                    bloc,
                )
                for arrow_pos, note_pos in solution.items():
                    should_skip.add(arrow_pos)
                    should_skip.add(note_pos)
                    symbol = bloc[note_pos.y][note_pos.x]
                    symbol_time = section.symbols[symbol]
                    note_time = section_starting_beat + symbol_time
                    unfinished_longs[note_pos] = UnfinishedLongNote(
                        time=note_time, position=note_pos, tail_tip=arrow_pos)

            # 3/3 : find regular notes
            for y, x in product(range(4), range(4)):
                position = NotePosition(x, y)
                if position in should_skip:
                    continue
                symbol = bloc[y][x]
                if symbol in section.symbols:
                    symbol_time = section.symbols[symbol]
                    note_time = section_starting_beat + symbol_time
                    yield TapNote(note_time, position)
Пример #7
0
def test_half_width_symbols() -> None:
    chart = """
        b=7
        *⑲:4.5
        *21:5
        *25:6

        口⑪①口
        ①⑮⑤⑪
        ⑤口口⑮
        ⑨口口⑨

        21口口⑲
        25口口25
        口⑲21口
        25口口25
        ----------
        """
    expected = [
        TapNote(BeatsTime(t), NotePosition(x, y))
        for t, x, y in [
            ("0.0", 2, 0),
            ("0.0", 0, 1),
            ("1.0", 2, 1),
            ("1.0", 0, 2),
            ("2.0", 0, 3),
            ("2.0", 3, 3),
            ("2.5", 1, 0),
            ("2.5", 3, 1),
            ("3.5", 1, 1),
            ("3.5", 3, 2),
            ("4.5", 1, 2),
            ("4.5", 3, 0),
            ("5.0", 0, 0),
            ("5.0", 2, 2),
            ("6.0", 0, 1),
            ("6.0", 3, 1),
            ("6.0", 0, 3),
            ("6.0", 3, 3),
        ]
    ]
    compare_chart_notes(chart, expected)
Пример #8
0
def test_symbol_definition() -> None:
    chart = """
        *A:2 //⑨と同タイミング
        *B:2.125
        *C:2.25 //⑩と同じ
        *D:2.375
        *E:2.5 //⑪と同じ
        *F:2.625
        *G:2.75 //⑫と同じ
        *H:2.875
        *I:3 //⑬と同じ
        *J:3.125
        *K:3.25 //⑭と同じ
        *L:3.375

        ABCD
        L③□E
        K⑦□F
        JIHG
        --
        """
    expected = [
        TapNote(BeatsTime(t), NotePosition(x, y))
        for t, x, y in [
            ("4/8", 1, 1),
            ("12/8", 1, 2),
            ("16/8", 0, 0),
            ("17/8", 1, 0),
            ("18/8", 2, 0),
            ("19/8", 3, 0),
            ("20/8", 3, 1),
            ("21/8", 3, 2),
            ("22/8", 3, 3),
            ("23/8", 2, 3),
            ("24/8", 1, 3),
            ("25/8", 0, 3),
            ("26/8", 0, 2),
            ("27/8", 0, 1),
        ]
    ]
    compare_chart_notes(chart, expected)
Пример #9
0
def notes(
    draw: DrawFunc,
    collisions: bool = False,
    note_strat: st.SearchStrategy[Union[TapNote, LongNote]] = st.one_of(
        tap_note(), long_note()),
    beat_time_strat: st.SearchStrategy[BeatsTime] = beat_time(max_section=3),
) -> Set[Union[TapNote, LongNote]]:
    raw_notes: Set[Union[TapNote,
                         LongNote]] = draw(st.sets(note_strat, max_size=32))

    if collisions:
        return raw_notes
    else:
        last_notes: Dict[NotePosition, Optional[BeatsTime]] = {
            NotePosition(x, y): None
            for y, x in product(range(4), range(4))
        }
        notes: Set[Union[TapNote, LongNote]] = set()
        for note in sorted(raw_notes, key=lambda n: (n.time, n.position)):
            last_note_time = last_notes[note.position]
            if last_note_time is None:
                new_time = draw(beat_time_strat)
            else:
                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(
                        time=new_time,
                        position=note.position,
                        duration=note.duration,
                        tail_tip=note.tail_tip,
                    ))
                last_notes[note.position] = new_time + note.duration
            else:
                notes.add(TapNote(time=new_time, position=note.position))
                last_notes[note.position] = new_time
        return notes
Пример #10
0
def test_compound_section() -> None:
    chart = """
        □①①□
        □⑩⑪□
        ④⑧⑨⑤
        ③⑥⑦③

        ⑯⑫⑬⑯
        □□□□
        □□□□
        ⑭□□⑭
        ------------- 2
        """
    expected = [
        TapNote(time=BeatsTime("1/4") * (t - 1), position=NotePosition(x, y))
        for t, x, y in [
            (1, 1, 0),
            (1, 2, 0),
            (3, 0, 3),
            (3, 3, 3),
            (4, 0, 2),
            (5, 3, 2),
            (6, 1, 3),
            (7, 2, 3),
            (8, 1, 2),
            (9, 2, 2),
            (10, 1, 1),
            (11, 2, 1),
            (12, 1, 0),
            (13, 2, 0),
            (14, 0, 3),
            (14, 3, 3),
            (16, 0, 0),
            (16, 3, 0),
        ]
    ]
    compare_chart_notes(chart, expected)
Пример #11
0
    def _iter_notes(self) -> Iterator[Union[TapNote, LongNote]]:
        unfinished_longs: Dict[NotePosition, UnfinishedLongNote] = {}
        for (
                currently_defined_symbols,
                frame,
                section_starting_beat,
                section,
        ) in self._iter_frames():
            should_skip: Set[NotePosition] = set()

            # 1/3 : look for ends to unfinished long notes
            for pos, unfinished_long in unfinished_longs.items():
                x, y = astuple(pos)
                symbol = frame.position_part[y][x]
                if self.circle_free and symbol in CIRCLE_FREE_SYMBOLS:
                    circled_symbol = CIRCLE_FREE_TO_NOTE_SYMBOL[symbol]
                    try:
                        symbol_time = currently_defined_symbols[circled_symbol]
                    except KeyError:
                        raise SyntaxError(
                            "Chart section positional part constains the circle free "
                            f"symbol '{symbol}' but the associated circled symbol "
                            f"'{circled_symbol}' could not be found in the timing part:\n"
                            f"{section}")
                else:
                    try:
                        symbol_time = currently_defined_symbols[symbol]
                    except KeyError:
                        continue

                should_skip.add(pos)
                note_time = section_starting_beat + symbol_time
                yield unfinished_long.ends_at(note_time)

            unfinished_longs = {
                k: unfinished_longs[k]
                for k in unfinished_longs.keys() - should_skip
            }

            # 2/3 : look for new long notes starting on this bloc
            arrow_to_note_candidates = find_long_note_candidates(
                frame.position_part, currently_defined_symbols.keys(),
                should_skip)
            if arrow_to_note_candidates:
                solution = pick_correct_long_note_candidates(
                    arrow_to_note_candidates,
                    frame.position_part,
                )
                for arrow_pos, note_pos in solution.items():
                    should_skip.add(arrow_pos)
                    should_skip.add(note_pos)
                    symbol = frame.position_part[note_pos.y][note_pos.x]
                    symbol_time = currently_defined_symbols[symbol]
                    note_time = section_starting_beat + symbol_time
                    unfinished_longs[note_pos] = UnfinishedLongNote(
                        time=note_time, position=note_pos, tail_tip=arrow_pos)

            # 3/3 : find regular notes
            for y, x in product(range(4), range(4)):
                position = NotePosition(x, y)
                if position in should_skip:
                    continue
                symbol = frame.position_part[y][x]
                try:
                    symbol_time = currently_defined_symbols[symbol]
                except KeyError:
                    continue
                note_time = section_starting_beat + symbol_time
                yield TapNote(note_time, position)
Пример #12
0
from fractions import Fraction

from jubeatools.song import LongNote, NotePosition, TapNote

notes = {
    TapNote(time=Fraction(0, 1), position=NotePosition(x=0, y=0)),
    TapNote(time=Fraction(0, 1), position=NotePosition(x=0, y=1)),
    TapNote(time=Fraction(0, 1), position=NotePosition(x=0, y=3)),
    LongNote(
        time=Fraction(0, 1),
        position=NotePosition(x=1, y=0),
        duration=Fraction(1, 16),
        tail_tip=NotePosition(x=2, y=0),
    ),
    TapNote(time=Fraction(0, 1), position=NotePosition(x=1, y=1)),
    LongNote(
        time=Fraction(0, 1),
        position=NotePosition(x=1, y=2),
        duration=Fraction(1, 3),
        tail_tip=NotePosition(x=2, y=2),
    ),
    LongNote(
        time=Fraction(1, 8),
        position=NotePosition(x=0, y=3),
        duration=Fraction(1, 4),
        tail_tip=NotePosition(x=2, y=3),
    ),
    TapNote(time=Fraction(1, 4), position=NotePosition(x=0, y=0)),
    TapNote(time=Fraction(5, 16), position=NotePosition(x=1, y=0)),
    LongNote(
        time=Fraction(1, 2),