+19
-169
@@ -77,36 +77,14 @@ auto clamp_state(vamp_zero::app_state state) -> vamp_zero::app_state {
|
||||
} else {
|
||||
state.selected_part_index = 0U;
|
||||
}
|
||||
state.selected_practice_type_index =
|
||||
std::min(state.selected_practice_type_index, menu_row_count(state.catalog->practice.types.size()) - 1U);
|
||||
if (auto const *type = selected_practice_type(state); type != nullptr) {
|
||||
state.selected_practice_lesson_index =
|
||||
std::min(state.selected_practice_lesson_index, menu_row_count(type->lesson_groups.size()) - 1U);
|
||||
} else {
|
||||
state.selected_practice_lesson_index = 0U;
|
||||
}
|
||||
if (auto const *lesson = selected_practice_lesson(state); lesson != nullptr) {
|
||||
state.selected_practice_exercise_index =
|
||||
std::min(state.selected_practice_exercise_index, menu_row_count(lesson->exercises.size()) - 1U);
|
||||
} else {
|
||||
state.selected_practice_exercise_index = 0U;
|
||||
}
|
||||
state.selected_practice_exercise_index = std::min(state.selected_practice_exercise_index, state.catalog->practice.exercises.size());
|
||||
state.selected_practice_key_index = std::min(state.selected_practice_key_index, practice_key_row_count(state) - 1U);
|
||||
if (state.mode == vamp_zero::app_mode::PERFORMANCE_PART_MENU && selected_group(state) == nullptr) {
|
||||
state.mode = vamp_zero::app_mode::PERFORMANCE_SONG_MENU;
|
||||
}
|
||||
if (state.mode == vamp_zero::app_mode::PRACTICE_LESSON_MENU && selected_practice_type(state) == nullptr) {
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_TYPE_MENU;
|
||||
}
|
||||
if (state.mode == vamp_zero::app_mode::PRACTICE_EXERCISE_MENU && selected_practice_lesson(state) == nullptr) {
|
||||
state.mode = selected_practice_type(state) == nullptr ? vamp_zero::app_mode::PRACTICE_TYPE_MENU
|
||||
: vamp_zero::app_mode::PRACTICE_LESSON_MENU;
|
||||
}
|
||||
if (state.mode == vamp_zero::app_mode::PRACTICE_KEY_MENU) {
|
||||
auto const *exercise = selected_practice_exercise(state);
|
||||
if (exercise == nullptr) {
|
||||
state.mode = practice_fallback_menu(state);
|
||||
} else if (!supports_key_selection(*exercise) || exercise->variants.empty()) {
|
||||
if (exercise == nullptr || exercise->variants.empty()) {
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_EXERCISE_MENU;
|
||||
state.selected_practice_key_index = 0U;
|
||||
}
|
||||
@@ -119,7 +97,7 @@ auto clamp_state(vamp_zero::app_state state) -> vamp_zero::app_state {
|
||||
} else if (state.mode == vamp_zero::app_mode::PRACTICE_SCORE) {
|
||||
auto const *exercise = active_practice(state);
|
||||
if (exercise == nullptr) {
|
||||
state.mode = practice_fallback_menu(state);
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_EXERCISE_MENU;
|
||||
state.active_practice_id.clear();
|
||||
state.page_index = 0;
|
||||
} else if (selected_practice_variant(state, *exercise) == nullptr) {
|
||||
@@ -189,11 +167,6 @@ auto exercise_json(vamp_zero::practice_exercise const &exercise) -> boost::json:
|
||||
}
|
||||
auto result = boost::json::object{};
|
||||
result["id"] = exercise.id;
|
||||
result["practice_type_id"] = exercise.practice_type_id;
|
||||
result["practice_type_title"] = exercise.practice_type_title;
|
||||
result["lesson_group_id"] = exercise.lesson_group_id;
|
||||
result["lesson_group_title"] = exercise.lesson_group_title;
|
||||
result["supports_key_selection"] = supports_key_selection(exercise);
|
||||
result["title"] = exercise.title;
|
||||
result["composer"] = exercise.composer;
|
||||
result["authored_key_signature"] = exercise.authored_key_signature;
|
||||
@@ -209,41 +182,6 @@ auto exercise_json(vamp_zero::practice_exercise const &exercise) -> boost::json:
|
||||
return result;
|
||||
}
|
||||
|
||||
auto lesson_json(vamp_zero::practice_lesson_group const &lesson, vamp_zero::practice_library const &library) -> boost::json::object {
|
||||
auto exercises = boost::json::array{};
|
||||
for (auto const &exercise : lesson.exercises) {
|
||||
exercises.push_back(exercise_json(library.exercises[exercise]));
|
||||
}
|
||||
auto result = boost::json::object{};
|
||||
result["id"] = lesson.id;
|
||||
result["title"] = lesson.title;
|
||||
result["exercise_count"] = static_cast<std::uint64_t>(lesson.exercises.size());
|
||||
result["exercises"] = std::move(exercises);
|
||||
return result;
|
||||
}
|
||||
|
||||
auto practice_type_exercise_count(vamp_zero::practice_type_group const &type) -> std::size_t {
|
||||
auto count = std::size_t{};
|
||||
for (auto const &lesson : type.lesson_groups) {
|
||||
count += lesson.exercises.size();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
auto type_json(vamp_zero::practice_type_group const &type, vamp_zero::practice_library const &library) -> boost::json::object {
|
||||
auto lessons = boost::json::array{};
|
||||
for (auto const &lesson : type.lesson_groups) {
|
||||
lessons.push_back(lesson_json(lesson, library));
|
||||
}
|
||||
auto result = boost::json::object{};
|
||||
result["id"] = type.id;
|
||||
result["title"] = type.title;
|
||||
result["lesson_group_count"] = static_cast<std::uint64_t>(type.lesson_groups.size());
|
||||
result["exercise_count"] = static_cast<std::uint64_t>(practice_type_exercise_count(type));
|
||||
result["lesson_groups"] = std::move(lessons);
|
||||
return result;
|
||||
}
|
||||
|
||||
auto performance_json(vamp_zero::app_state const &state) -> boost::json::object {
|
||||
auto groups = boost::json::array{};
|
||||
for (auto const &group : state.catalog->performance.groups) {
|
||||
@@ -265,10 +203,6 @@ auto performance_json(vamp_zero::app_state const &state) -> boost::json::object
|
||||
}
|
||||
|
||||
auto practice_json(vamp_zero::app_state const &state) -> boost::json::object {
|
||||
auto types = boost::json::array{};
|
||||
for (auto const &type : state.catalog->practice.types) {
|
||||
types.push_back(type_json(type, state.catalog->practice));
|
||||
}
|
||||
auto exercises = boost::json::array{};
|
||||
for (auto const &exercise : state.catalog->practice.exercises) {
|
||||
exercises.push_back(exercise_json(exercise));
|
||||
@@ -278,16 +212,8 @@ auto practice_json(vamp_zero::app_state const &state) -> boost::json::object {
|
||||
keys.push_back(boost::json::value{std::string{key}});
|
||||
}
|
||||
auto selection = boost::json::object{};
|
||||
selection["type_row_index"] = static_cast<std::uint64_t>(state.selected_practice_type_index);
|
||||
selection["lesson_row_index"] = static_cast<std::uint64_t>(state.selected_practice_lesson_index);
|
||||
selection["exercise_row_index"] = static_cast<std::uint64_t>(state.selected_practice_exercise_index);
|
||||
selection["key_row_index"] = static_cast<std::uint64_t>(state.selected_practice_key_index);
|
||||
if (auto const *type = selected_practice_type(state); type != nullptr) {
|
||||
selection["type"] = type_json(*type, state.catalog->practice);
|
||||
}
|
||||
if (auto const *lesson = selected_practice_lesson(state); lesson != nullptr) {
|
||||
selection["lesson_group"] = lesson_json(*lesson, state.catalog->practice);
|
||||
}
|
||||
if (auto const *exercise = selected_practice_exercise(state); exercise != nullptr) {
|
||||
selection["exercise"] = exercise_json(*exercise);
|
||||
auto variant = selected_practice_variant(state, *exercise);
|
||||
@@ -307,9 +233,7 @@ auto practice_json(vamp_zero::app_state const &state) -> boost::json::object {
|
||||
}
|
||||
}
|
||||
auto practice = boost::json::object{};
|
||||
practice["type_count"] = static_cast<std::uint64_t>(state.catalog->practice.types.size());
|
||||
practice["exercise_count"] = static_cast<std::uint64_t>(state.catalog->practice.exercises.size());
|
||||
practice["types"] = std::move(types);
|
||||
practice["exercises"] = std::move(exercises);
|
||||
practice["key_count"] = static_cast<std::uint64_t>(vamp_zero::practice_key_names().size());
|
||||
practice["keys"] = std::move(keys);
|
||||
@@ -359,9 +283,7 @@ auto vamp_zero::apply_app_command(vamp_zero::app_state state, vamp_protocol::pag
|
||||
state.active_part_id.clear();
|
||||
state.page_index = 0;
|
||||
} else if (state.selected_main_menu_index == main_menu_practice) {
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_TYPE_MENU;
|
||||
state.selected_practice_type_index = 0;
|
||||
state.selected_practice_lesson_index = 0;
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_EXERCISE_MENU;
|
||||
state.selected_practice_exercise_index = 0;
|
||||
state.selected_practice_key_index = 0;
|
||||
state.active_practice_id.clear();
|
||||
@@ -422,85 +344,28 @@ auto vamp_zero::apply_app_command(vamp_zero::app_state state, vamp_protocol::pag
|
||||
}
|
||||
}
|
||||
return clamp_state(std::move(state));
|
||||
case vamp_zero::app_mode::PRACTICE_TYPE_MENU:
|
||||
case vamp_zero::app_mode::PRACTICE_EXERCISE_MENU:
|
||||
if (command == vamp_protocol::page_command::NEXT) {
|
||||
state.selected_practice_type_index =
|
||||
wrap_next(state.selected_practice_type_index, menu_row_count(state.catalog->practice.types.size()));
|
||||
state.selected_practice_lesson_index = 0;
|
||||
state.selected_practice_exercise_index = 0;
|
||||
state.selected_practice_exercise_index = wrap_next(state.selected_practice_exercise_index, menu_row_count(state.catalog->practice.exercises.size()));
|
||||
state.selected_practice_key_index = 0;
|
||||
} else if (command == vamp_protocol::page_command::PREVIOUS) {
|
||||
state.selected_practice_type_index =
|
||||
wrap_previous(state.selected_practice_type_index, menu_row_count(state.catalog->practice.types.size()));
|
||||
state.selected_practice_lesson_index = 0;
|
||||
state.selected_practice_exercise_index = 0;
|
||||
state.selected_practice_exercise_index = wrap_previous(state.selected_practice_exercise_index, menu_row_count(state.catalog->practice.exercises.size()));
|
||||
state.selected_practice_key_index = 0;
|
||||
} else if (state.selected_practice_type_index == 0U) {
|
||||
} else if (state.selected_practice_exercise_index == 0U) {
|
||||
state.mode = vamp_zero::app_mode::MAIN_MENU;
|
||||
} else {
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_LESSON_MENU;
|
||||
state.selected_practice_lesson_index = 0;
|
||||
state.selected_practice_exercise_index = 0;
|
||||
state.active_practice_id.clear();
|
||||
state.page_index = 0;
|
||||
} else if (selected_practice_exercise(state) != nullptr) {
|
||||
state.active_part_id.clear();
|
||||
state.active_practice_id.clear();
|
||||
state.page_index = 0;
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_KEY_MENU;
|
||||
state.selected_practice_key_index = 0;
|
||||
}
|
||||
return clamp_state(std::move(state));
|
||||
case vamp_zero::app_mode::PRACTICE_LESSON_MENU:
|
||||
if (auto const *type = selected_practice_type(state); type != nullptr) {
|
||||
if (command == vamp_protocol::page_command::NEXT) {
|
||||
state.selected_practice_lesson_index =
|
||||
wrap_next(state.selected_practice_lesson_index, menu_row_count(type->lesson_groups.size()));
|
||||
state.selected_practice_exercise_index = 0;
|
||||
state.selected_practice_key_index = 0;
|
||||
} else if (command == vamp_protocol::page_command::PREVIOUS) {
|
||||
state.selected_practice_lesson_index =
|
||||
wrap_previous(state.selected_practice_lesson_index, menu_row_count(type->lesson_groups.size()));
|
||||
state.selected_practice_exercise_index = 0;
|
||||
state.selected_practice_key_index = 0;
|
||||
} else if (state.selected_practice_lesson_index == 0U) {
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_TYPE_MENU;
|
||||
state.active_practice_id.clear();
|
||||
state.page_index = 0;
|
||||
} else {
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_EXERCISE_MENU;
|
||||
state.selected_practice_exercise_index = 0;
|
||||
state.selected_practice_key_index = 0;
|
||||
}
|
||||
}
|
||||
return clamp_state(std::move(state));
|
||||
case vamp_zero::app_mode::PRACTICE_EXERCISE_MENU:
|
||||
if (auto const *lesson = selected_practice_lesson(state); lesson != nullptr) {
|
||||
if (command == vamp_protocol::page_command::NEXT) {
|
||||
state.selected_practice_exercise_index =
|
||||
wrap_next(state.selected_practice_exercise_index, menu_row_count(lesson->exercises.size()));
|
||||
state.selected_practice_key_index = 0;
|
||||
} else if (command == vamp_protocol::page_command::PREVIOUS) {
|
||||
state.selected_practice_exercise_index =
|
||||
wrap_previous(state.selected_practice_exercise_index, menu_row_count(lesson->exercises.size()));
|
||||
state.selected_practice_key_index = 0;
|
||||
} else if (state.selected_practice_exercise_index == 0U) {
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_LESSON_MENU;
|
||||
state.active_practice_id.clear();
|
||||
state.page_index = 0;
|
||||
} else if (auto const *exercise = selected_practice_exercise(state); exercise != nullptr) {
|
||||
state.active_part_id.clear();
|
||||
state.active_practice_id.clear();
|
||||
state.page_index = 0;
|
||||
if (supports_key_selection(*exercise) && !exercise->variants.empty()) {
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_KEY_MENU;
|
||||
state.selected_practice_key_index = 0;
|
||||
} else {
|
||||
state.active_practice_id = exercise->id;
|
||||
state.selected_practice_key_index = 0;
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_SCORE;
|
||||
++state.score_session;
|
||||
state.audio.playback_error.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
return clamp_state(std::move(state));
|
||||
case vamp_zero::app_mode::PRACTICE_KEY_MENU:
|
||||
if (auto const *exercise = selected_practice_exercise(state);
|
||||
exercise != nullptr && supports_key_selection(*exercise)) {
|
||||
exercise != nullptr) {
|
||||
if (command == vamp_protocol::page_command::NEXT) {
|
||||
state.selected_practice_key_index =
|
||||
wrap_next(state.selected_practice_key_index, menu_row_count(exercise->variants.size()));
|
||||
@@ -530,8 +395,7 @@ auto vamp_zero::apply_app_command(vamp_zero::app_state state, vamp_protocol::pag
|
||||
} else if (command == vamp_protocol::page_command::PREVIOUS) {
|
||||
state.page_index = state.page_index == 0U ? 0U : state.page_index - 1U;
|
||||
} else {
|
||||
state.mode = supports_key_selection(*exercise) ? vamp_zero::app_mode::PRACTICE_KEY_MENU
|
||||
: vamp_zero::app_mode::PRACTICE_EXERCISE_MENU;
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_KEY_MENU;
|
||||
state.active_practice_id.clear();
|
||||
state.page_index = 0;
|
||||
}
|
||||
@@ -662,29 +526,15 @@ auto vamp_zero::validate_app_state(vamp_zero::app_state const &state) -> std::ex
|
||||
group != nullptr && state.selected_part_index >= menu_row_count(group->parts.size())) {
|
||||
return std::unexpected(vamp_zero::make_error(vamp_zero::error_code::INVALID_ARGUMENT, "selected performance part row is out of range"));
|
||||
}
|
||||
if (state.selected_practice_type_index >= menu_row_count(state.catalog->practice.types.size())) {
|
||||
return std::unexpected(vamp_zero::make_error(vamp_zero::error_code::INVALID_ARGUMENT, "selected practice type row is out of range"));
|
||||
}
|
||||
if (auto const *type = selected_practice_type(state);
|
||||
type != nullptr && state.selected_practice_lesson_index >= menu_row_count(type->lesson_groups.size())) {
|
||||
return std::unexpected(vamp_zero::make_error(vamp_zero::error_code::INVALID_ARGUMENT, "selected practice lesson row is out of range"));
|
||||
}
|
||||
if (auto const *lesson = selected_practice_lesson(state);
|
||||
lesson != nullptr && state.selected_practice_exercise_index >= menu_row_count(lesson->exercises.size())) {
|
||||
if (state.selected_practice_exercise_index >= menu_row_count(state.catalog->practice.exercises.size())) {
|
||||
return std::unexpected(vamp_zero::make_error(vamp_zero::error_code::INVALID_ARGUMENT, "selected practice exercise row is out of range"));
|
||||
}
|
||||
if (state.selected_practice_key_index >= practice_key_row_count(state)) {
|
||||
return std::unexpected(vamp_zero::make_error(vamp_zero::error_code::INVALID_ARGUMENT, "selected practice key row is out of range"));
|
||||
}
|
||||
if (state.mode == vamp_zero::app_mode::PRACTICE_LESSON_MENU && selected_practice_type(state) == nullptr) {
|
||||
return std::unexpected(vamp_zero::make_error(vamp_zero::error_code::INVALID_ARGUMENT, "practice lesson mode requires a selected practice type"));
|
||||
}
|
||||
if (state.mode == vamp_zero::app_mode::PRACTICE_EXERCISE_MENU && selected_practice_lesson(state) == nullptr) {
|
||||
return std::unexpected(vamp_zero::make_error(vamp_zero::error_code::INVALID_ARGUMENT, "practice exercise mode requires a selected lesson group"));
|
||||
}
|
||||
if (state.mode == vamp_zero::app_mode::PRACTICE_KEY_MENU) {
|
||||
auto const *exercise = selected_practice_exercise(state);
|
||||
if (exercise == nullptr || !supports_key_selection(*exercise)) {
|
||||
if (exercise == nullptr || exercise->variants.empty()) {
|
||||
return std::unexpected(vamp_zero::make_error(vamp_zero::error_code::INVALID_ARGUMENT, "practice key mode requires an exercise with key variants"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user