Initial triangle progression
This commit is contained in:
1 parent
afa6976f1a
commit
23518c7af9
4 files changed
+197
-180
No files matched your search
+181
-176
@@ -15,7 +15,9 @@ static Window *s_status_window;
|
||||
static Window *s_drop_window;
|
||||
static Layer *s_top_bar_layer;
|
||||
static Layer *s_bottom_bar_layer;
|
||||
// static TextLayer *s_time_txt_layer;
|
||||
static TextLayer *s_countdown_txt_layer;
|
||||
// static TextLayer *s_progress_txt_layer;
|
||||
static TextLayer *s_status_txt_layer;
|
||||
//// setter
|
||||
static BitmapLayer *s_clock_bmp_layer;
|
||||
@@ -263,7 +265,8 @@ static void inbox_received_handler(DictionaryIterator *iter, void *context) {
|
||||
apply_uint8_from_tuple(iter, MESSAGE_KEY_PKJS_PAVLOK_ENABLE, &settings.PavlokEnabled);
|
||||
apply_uint8_from_tuple(iter, MESSAGE_KEY_PKJS_PAVLOK_ZAP_INTENSITY, &settings.PavlokIntensity);
|
||||
apply_uint8_from_tuple(iter, MESSAGE_KEY_PKJS_TRIANGLE_COUNT, &settings.TriangleCount);
|
||||
apply_uint8_from_tuple(iter, MESSAGE_KEY_PKJS_TRIANGLE_MIN_SECS, &settings.TriangeMinSecs);
|
||||
apply_uint8_from_tuple(iter, MESSAGE_KEY_PKJS_TRIANGLE_SECS_MIN, &settings.TriangleSecsMin);
|
||||
apply_uint8_from_tuple(iter, MESSAGE_KEY_PKJS_TRIANGLE_SECS_STEP, &settings.TriangleSecsStep);
|
||||
persist_write_data(STORAGE_KEY_SETTINGS, &settings, sizeof(settings));
|
||||
}
|
||||
|
||||
@@ -286,176 +289,6 @@ static void send_zap(uint8_t intensity) {
|
||||
|
||||
////////////////////// ALARM //////////////////////
|
||||
|
||||
static void awareness_alarm_seconds_handler(struct tm *tick_time, TimeUnits units_changed) {
|
||||
s_awareness_countdown_int--;
|
||||
snprintf(s_awareness_countdown_buf, sizeof(s_awareness_countdown_buf), "%03u", s_awareness_countdown_int);
|
||||
text_layer_set_text(s_countdown_txt_layer, s_awareness_countdown_buf);
|
||||
if (s_awareness_countdown_int == 0) {
|
||||
send_zap(settings.PavlokIntensity);
|
||||
// TODO demote and reset countdown int
|
||||
}
|
||||
}
|
||||
|
||||
static void graph_layer_update_proc(Layer *layer, GContext *ctx) {
|
||||
GRect bounds = layer_get_bounds(layer);
|
||||
static const uint8_t s_pixel_gap = PBL_DISPLAY_WIDTH / 20;
|
||||
graphics_context_set_stroke_color(ctx, GColorElectricBlue);
|
||||
for (int i = s_pixel_gap; i < PBL_DISPLAY_WIDTH; i += s_pixel_gap) {
|
||||
graphics_draw_line(ctx, GPoint(0, i), GPoint(bounds.size.w, i)); // horizontal line
|
||||
graphics_draw_line(ctx, GPoint(i, 0), GPoint(i, bounds.size.h)); // vertical line
|
||||
}
|
||||
}
|
||||
|
||||
static void drop_layer_update_proc(Layer *layer, GContext *ctx) {
|
||||
graphics_context_set_fill_color(ctx, GColorWhite);
|
||||
graphics_fill_rect(ctx, layer_get_bounds(layer), 5, GCornersAll);
|
||||
}
|
||||
|
||||
static void division_layer_update_proc(Layer *layer, GContext *ctx) {
|
||||
GRect bounds = layer_get_bounds(layer);
|
||||
graphics_context_set_stroke_color(ctx, GColorWhite);
|
||||
graphics_draw_line(ctx, GPoint(bounds.origin.x, bounds.origin.y), GPoint(bounds.origin.x + bounds.size.w, bounds.origin.y));
|
||||
}
|
||||
|
||||
static void alarm_highlight_layer_update_proc(Layer *layer, GContext *ctx) {
|
||||
graphics_context_set_stroke_color(ctx, GColorRed);
|
||||
graphics_context_set_stroke_width(ctx, 3);
|
||||
graphics_draw_rect(ctx, layer_get_bounds(layer));
|
||||
}
|
||||
|
||||
static void set_alarm_highlighter_frame() {
|
||||
switch (s_highlight_pos) {
|
||||
case 0:
|
||||
layer_set_frame(s_alarm_highlight_layer, s_drop_function_grect);
|
||||
break;
|
||||
case 1:
|
||||
layer_set_frame(s_alarm_highlight_layer, s_drop_over_grect);
|
||||
break;
|
||||
case 2:
|
||||
layer_set_frame(s_alarm_highlight_layer, s_drop_under_grect);
|
||||
}
|
||||
}
|
||||
|
||||
static void alarm_up_click_handler(void *recognizer, void *ctx) {
|
||||
if (s_highlight_pos == 0) {
|
||||
s_highlight_pos = 2;
|
||||
} else {
|
||||
s_highlight_pos--;
|
||||
}
|
||||
set_alarm_highlighter_frame();
|
||||
}
|
||||
|
||||
static void alarm_down_click_handler(void *recognizer, void *ctx) {
|
||||
if (s_highlight_pos == 2) {
|
||||
s_highlight_pos = 0;
|
||||
} else {
|
||||
s_highlight_pos++;
|
||||
}
|
||||
set_alarm_highlighter_frame();
|
||||
}
|
||||
|
||||
static void alarm_select_click_handler(void *recognizer, void *ctx) {
|
||||
window_stack_push(s_drop_window, true);
|
||||
}
|
||||
|
||||
static void alarm_select_hold_handler(void *recognizer, void *ctx) {
|
||||
// check solution
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (s_selected_indices[i] != s_solution_indices[i]) {
|
||||
push_status_window(STATUS_MATH_FAILURE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// solution is correct, meaning a non-recovery alarm needs scheduled;
|
||||
// set dummy handler to avoid overwriting an important alarm with a
|
||||
// no-longer-important recovery alarm
|
||||
wakeup_service_subscribe(NULL);
|
||||
|
||||
if (s_awareness_countdown_int > 0) {
|
||||
// TODO promote OR disarm
|
||||
// if (s_current_triangle == settings.TriangleCount) {
|
||||
tick_timer_service_unsubscribe(); // alarm is fully disarmed - prevent stimulus in confirmation window
|
||||
if (schedule_alarm(WAKE_ALARM)) {
|
||||
push_status_window(STATUS_CONFIRMATION);
|
||||
}
|
||||
// } else {
|
||||
// GENERATE NEW TRIANLGE AND SET TIME LIMIT
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
static void alarm_click_config_provider(void *ctx) {
|
||||
window_single_click_subscribe(BUTTON_ID_BACK, NULL);
|
||||
window_single_click_subscribe(BUTTON_ID_UP, alarm_up_click_handler);
|
||||
window_single_click_subscribe(BUTTON_ID_DOWN, alarm_down_click_handler);
|
||||
window_single_click_subscribe(BUTTON_ID_SELECT, alarm_select_click_handler);
|
||||
window_long_click_subscribe(BUTTON_ID_SELECT, 2500, alarm_select_hold_handler, NULL);
|
||||
}
|
||||
|
||||
static uint16_t menu_get_num_rows(MenuLayer *menu_layer, uint16_t section_index, void *context) {
|
||||
if (s_highlight_pos == 0) {
|
||||
return 3;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void menu_draw_row(GContext *ctx, const Layer *cell_layer, MenuIndex *cell_index, void *context) {
|
||||
switch (s_highlight_pos) {
|
||||
case 0:
|
||||
menu_cell_basic_draw(ctx, cell_layer, s_options_function[cell_index->row], NULL, NULL);
|
||||
break;
|
||||
case 1:
|
||||
menu_cell_basic_draw(ctx, cell_layer, s_options_over[cell_index->row], NULL, NULL);
|
||||
break;
|
||||
case 2:
|
||||
menu_cell_basic_draw(ctx, cell_layer, s_options_under[cell_index->row], NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void menu_select(MenuLayer *menu_layer, MenuIndex *cell_index, void *context) {
|
||||
switch (s_highlight_pos) {
|
||||
case 0:
|
||||
text_layer_set_text(s_drop_txt_function_layer, s_options_function[cell_index->row]);
|
||||
break;
|
||||
case 1:
|
||||
text_layer_set_text(s_drop_txt_over_layer, s_options_over[cell_index->row]);
|
||||
break;
|
||||
case 2:
|
||||
text_layer_set_text(s_drop_txt_under_layer, s_options_under[cell_index->row]);
|
||||
}
|
||||
s_selected_indices[s_highlight_pos] = cell_index->row;
|
||||
window_stack_remove(s_drop_window, true);
|
||||
}
|
||||
|
||||
// when the user presses select, call this to load a menu;
|
||||
// this function will determine the type of menu to load by checking the highlight position;
|
||||
// once the user presses select in this menu, the result is written to a text layer and the menu is exited
|
||||
static void drop_menu_window_load(Window *window) {
|
||||
Layer *window_layer = window_get_root_layer(window);
|
||||
s_drop_menu_layer = menu_layer_create(layer_get_bounds(window_layer));
|
||||
menu_layer_set_callbacks(s_drop_menu_layer, NULL, (MenuLayerCallbacks){
|
||||
.get_num_rows = menu_get_num_rows,
|
||||
.draw_row = menu_draw_row,
|
||||
.select_click = menu_select,
|
||||
});
|
||||
menu_layer_set_click_config_onto_window(s_drop_menu_layer, window);
|
||||
layer_add_child(window_layer, menu_layer_get_layer(s_drop_menu_layer));
|
||||
}
|
||||
|
||||
static void drop_menu_window_unload(Window *window) {
|
||||
menu_layer_destroy(s_drop_menu_layer);
|
||||
s_drop_menu_layer = NULL;
|
||||
}
|
||||
|
||||
static void live_wakeup_handler_for_alarm(WakeupId id, int32_t wakeup_reason) {
|
||||
if (wakeup_reason == WAKE_RECOVERY_ALARM) {
|
||||
// if recovery alarm, re-schedule it
|
||||
schedule_alarm(wakeup_reason);
|
||||
}
|
||||
}
|
||||
|
||||
static void update_for_new_triangle() {
|
||||
// pick & display 2 side lengths to the user
|
||||
static char side_a_buffer[8], side_b_buffer[8], side_c_buffer[8];
|
||||
@@ -579,14 +412,182 @@ static void update_for_new_triangle() {
|
||||
};
|
||||
|
||||
// setup countdown
|
||||
// TODO vary time based on progress:
|
||||
// Store time step per triangle
|
||||
// Determine time remaining from min+(s_total_count-s_current_triangle)*step
|
||||
s_awareness_countdown_int = settings.TriangeMinSecs;
|
||||
s_awareness_countdown_int = settings.TriangleSecsMin + ((settings.TriangleCount - s_current_triangle_num) * settings.TriangleSecsStep);
|
||||
snprintf(s_awareness_countdown_buf, sizeof(s_awareness_countdown_buf), "%03u", s_awareness_countdown_int);
|
||||
text_layer_set_text(s_countdown_txt_layer, s_awareness_countdown_buf);
|
||||
}
|
||||
|
||||
static void awareness_alarm_seconds_handler(struct tm *tick_time, TimeUnits units_changed) {
|
||||
s_awareness_countdown_int--;
|
||||
snprintf(s_awareness_countdown_buf, sizeof(s_awareness_countdown_buf), "%03u", s_awareness_countdown_int);
|
||||
text_layer_set_text(s_countdown_txt_layer, s_awareness_countdown_buf);
|
||||
if (s_awareness_countdown_int == 0) {
|
||||
send_zap(settings.PavlokIntensity);
|
||||
if (s_current_triangle_num > 1) {
|
||||
s_current_triangle_num--;
|
||||
}
|
||||
right_triangle_layer_regen(s_triangle_layer);
|
||||
update_for_new_triangle();
|
||||
}
|
||||
}
|
||||
|
||||
static void graph_layer_update_proc(Layer *layer, GContext *ctx) {
|
||||
GRect bounds = layer_get_bounds(layer);
|
||||
static const uint8_t s_pixel_gap = PBL_DISPLAY_WIDTH / 20;
|
||||
graphics_context_set_stroke_color(ctx, GColorElectricBlue);
|
||||
for (int i = s_pixel_gap; i < PBL_DISPLAY_WIDTH; i += s_pixel_gap) {
|
||||
graphics_draw_line(ctx, GPoint(0, i), GPoint(bounds.size.w, i)); // horizontal line
|
||||
graphics_draw_line(ctx, GPoint(i, 0), GPoint(i, bounds.size.h)); // vertical line
|
||||
}
|
||||
}
|
||||
|
||||
static void drop_layer_update_proc(Layer *layer, GContext *ctx) {
|
||||
graphics_context_set_fill_color(ctx, GColorWhite);
|
||||
graphics_fill_rect(ctx, layer_get_bounds(layer), 5, GCornersAll);
|
||||
}
|
||||
|
||||
static void division_layer_update_proc(Layer *layer, GContext *ctx) {
|
||||
GRect bounds = layer_get_bounds(layer);
|
||||
graphics_context_set_stroke_color(ctx, GColorWhite);
|
||||
graphics_draw_line(ctx, GPoint(bounds.origin.x, bounds.origin.y), GPoint(bounds.origin.x + bounds.size.w, bounds.origin.y));
|
||||
}
|
||||
|
||||
static void alarm_highlight_layer_update_proc(Layer *layer, GContext *ctx) {
|
||||
graphics_context_set_stroke_color(ctx, GColorRed);
|
||||
graphics_context_set_stroke_width(ctx, 3);
|
||||
graphics_draw_rect(ctx, layer_get_bounds(layer));
|
||||
}
|
||||
|
||||
static void set_alarm_highlighter_frame() {
|
||||
switch (s_highlight_pos) {
|
||||
case 0:
|
||||
layer_set_frame(s_alarm_highlight_layer, s_drop_function_grect);
|
||||
break;
|
||||
case 1:
|
||||
layer_set_frame(s_alarm_highlight_layer, s_drop_over_grect);
|
||||
break;
|
||||
case 2:
|
||||
layer_set_frame(s_alarm_highlight_layer, s_drop_under_grect);
|
||||
}
|
||||
}
|
||||
|
||||
static void alarm_up_click_handler(void *recognizer, void *ctx) {
|
||||
if (s_highlight_pos == 0) {
|
||||
s_highlight_pos = 2;
|
||||
} else {
|
||||
s_highlight_pos--;
|
||||
}
|
||||
set_alarm_highlighter_frame();
|
||||
}
|
||||
|
||||
static void alarm_down_click_handler(void *recognizer, void *ctx) {
|
||||
if (s_highlight_pos == 2) {
|
||||
s_highlight_pos = 0;
|
||||
} else {
|
||||
s_highlight_pos++;
|
||||
}
|
||||
set_alarm_highlighter_frame();
|
||||
}
|
||||
|
||||
static void alarm_select_click_handler(void *recognizer, void *ctx) {
|
||||
window_stack_push(s_drop_window, true);
|
||||
}
|
||||
|
||||
static void alarm_select_hold_handler(void *recognizer, void *ctx) {
|
||||
// check solution
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (s_selected_indices[i] != s_solution_indices[i]) {
|
||||
push_status_window(STATUS_MATH_FAILURE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (s_awareness_countdown_int > 0) {
|
||||
if (s_current_triangle_num == settings.TriangleCount) {
|
||||
tick_timer_service_unsubscribe(); // alarm is fully disarmed - prevent stimulus in confirmation window
|
||||
wakeup_service_subscribe(NULL); // ignore wakeup events to avoid overwriting new alarm
|
||||
if (schedule_alarm(WAKE_ALARM)) {
|
||||
push_status_window(STATUS_CONFIRMATION);
|
||||
}
|
||||
} else {
|
||||
s_current_triangle_num++;
|
||||
right_triangle_layer_regen(s_triangle_layer);
|
||||
update_for_new_triangle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void alarm_click_config_provider(void *ctx) {
|
||||
window_single_click_subscribe(BUTTON_ID_BACK, NULL);
|
||||
window_single_click_subscribe(BUTTON_ID_UP, alarm_up_click_handler);
|
||||
window_single_click_subscribe(BUTTON_ID_DOWN, alarm_down_click_handler);
|
||||
window_single_click_subscribe(BUTTON_ID_SELECT, alarm_select_click_handler);
|
||||
window_long_click_subscribe(BUTTON_ID_SELECT, 2500, alarm_select_hold_handler, NULL);
|
||||
}
|
||||
|
||||
static uint16_t menu_get_num_rows(MenuLayer *menu_layer, uint16_t section_index, void *context) {
|
||||
if (s_highlight_pos == 0) {
|
||||
return 3;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void menu_draw_row(GContext *ctx, const Layer *cell_layer, MenuIndex *cell_index, void *context) {
|
||||
switch (s_highlight_pos) {
|
||||
case 0:
|
||||
menu_cell_basic_draw(ctx, cell_layer, s_options_function[cell_index->row], NULL, NULL);
|
||||
break;
|
||||
case 1:
|
||||
menu_cell_basic_draw(ctx, cell_layer, s_options_over[cell_index->row], NULL, NULL);
|
||||
break;
|
||||
case 2:
|
||||
menu_cell_basic_draw(ctx, cell_layer, s_options_under[cell_index->row], NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void menu_select(MenuLayer *menu_layer, MenuIndex *cell_index, void *context) {
|
||||
switch (s_highlight_pos) {
|
||||
case 0:
|
||||
text_layer_set_text(s_drop_txt_function_layer, s_options_function[cell_index->row]);
|
||||
break;
|
||||
case 1:
|
||||
text_layer_set_text(s_drop_txt_over_layer, s_options_over[cell_index->row]);
|
||||
break;
|
||||
case 2:
|
||||
text_layer_set_text(s_drop_txt_under_layer, s_options_under[cell_index->row]);
|
||||
}
|
||||
s_selected_indices[s_highlight_pos] = cell_index->row;
|
||||
window_stack_remove(s_drop_window, true);
|
||||
}
|
||||
|
||||
// when the user presses select, call this to load a menu;
|
||||
// this function will determine the type of menu to load by checking the highlight position;
|
||||
// once the user presses select in this menu, the result is written to a text layer and the menu is exited
|
||||
static void drop_menu_window_load(Window *window) {
|
||||
Layer *window_layer = window_get_root_layer(window);
|
||||
s_drop_menu_layer = menu_layer_create(layer_get_bounds(window_layer));
|
||||
menu_layer_set_callbacks(s_drop_menu_layer, NULL, (MenuLayerCallbacks){
|
||||
.get_num_rows = menu_get_num_rows,
|
||||
.draw_row = menu_draw_row,
|
||||
.select_click = menu_select,
|
||||
});
|
||||
menu_layer_set_click_config_onto_window(s_drop_menu_layer, window);
|
||||
layer_add_child(window_layer, menu_layer_get_layer(s_drop_menu_layer));
|
||||
}
|
||||
|
||||
static void drop_menu_window_unload(Window *window) {
|
||||
menu_layer_destroy(s_drop_menu_layer);
|
||||
s_drop_menu_layer = NULL;
|
||||
}
|
||||
|
||||
static void live_wakeup_handler_for_alarm(WakeupId id, int32_t wakeup_reason) {
|
||||
if (wakeup_reason == WAKE_RECOVERY_ALARM) {
|
||||
// if recovery alarm, re-schedule it
|
||||
schedule_alarm(wakeup_reason);
|
||||
}
|
||||
}
|
||||
|
||||
static void alarm_window_load() {
|
||||
wakeup_service_subscribe(live_wakeup_handler_for_alarm);
|
||||
|
||||
@@ -744,6 +745,7 @@ static void push_alarm_window() {
|
||||
send_zap(settings.PavlokIntensity);
|
||||
}
|
||||
|
||||
s_current_triangle_num = 1;
|
||||
window_set_window_handlers(
|
||||
s_window,
|
||||
(WindowHandlers){.load = alarm_window_load, .unload = alarm_window_unload});
|
||||
@@ -927,6 +929,8 @@ static void setter_window_load() {
|
||||
layer_add_child(window_layer, text_layer_get_layer(s_countdown_txt_layer));
|
||||
update_countdown_display();
|
||||
|
||||
// progress
|
||||
|
||||
// highlighter
|
||||
s_setter_highlight_layer = layer_create(GRect(0, s_top_bar_grect.size.h, PBL_DISPLAY_WIDTH, PBL_DISPLAY_HEIGHT - (2 * s_top_bar_grect.size.h)));
|
||||
layer_set_update_proc(s_setter_highlight_layer, setter_highlight_layer_update_proc);
|
||||
@@ -986,7 +990,8 @@ static void init() {
|
||||
settings.PavlokEnabled = false;
|
||||
settings.PavlokIntensity = 50;
|
||||
settings.TriangleCount = 5;
|
||||
settings.TriangeMinSecs = 25;
|
||||
settings.TriangleSecsMin = 25;
|
||||
settings.TriangleSecsStep = 2;
|
||||
}
|
||||
|
||||
// read even when opening setter to ensure a recovery alarm is not able to be overwritten
|
||||
|
||||
Reference in new issue
Block a user