#pragma once #include #include #include #include #include #include #include "special_numeric_types.hpp" #include "variant_visitor.hpp" namespace better { /* A specific square on the controller. (0, 0) is the top-left button, x goes right, y goes down. x → 0 1 2 3 y 0 □ □ □ □ ↓ 1 □ □ □ □ 2 □ □ □ □ 3 □ □ □ □ */ class Position { public: explicit Position(unsigned int index); Position(unsigned int x, unsigned int y); unsigned int index() const; unsigned int get_x() const; unsigned int get_y() const; auto operator<=>(const Position&) const = default; private: unsigned int x; unsigned int y; }; std::ostream& operator<<(std::ostream& out, const Position& pos); class TapNote { public: TapNote(Fraction time, Position position); Fraction get_time() const; Position get_position() const; bool operator==(const TapNote&) const = default; nlohmann::ordered_json dump_for_memon_1_0_0() const; private: Fraction time; Position position; }; class LongNote { public: LongNote(Fraction time, Position position, Fraction duration, Position tail_tip); Fraction get_time() const; Position get_position() const; Fraction get_end() const; Fraction get_duration() const; Position get_tail_tip() const; unsigned int get_tail_length() const; unsigned int get_tail_angle() const; bool operator==(const LongNote&) const = default; nlohmann::ordered_json dump_for_memon_1_0_0() const; int tail_as_6_notation() const; private: Fraction time; Position position; Fraction duration; Position tail_tip; }; class Note { public: template Note(Ts&&... Args) : note(std::forward(Args...)) {}; Fraction get_time() const; std::pair get_time_bounds() const; Position get_position() const; Fraction get_end() const; template auto visit(T& visitor) const {return std::visit(visitor, this->note);}; bool operator==(const Note&) const = default; nlohmann::ordered_json dump_for_memon_1_0_0() const; private: std::variant note; }; }