Просмотр исходного кода

feat: add happiness management (#10)

* small refactoring of time functions
* Add deed on pomodoro complete
* Event queue refactoring
Mikhail Gubenko 3 лет назад
Родитель
Сommit
fa6358214d
5 измененных файлов с 121 добавлено и 62 удалено
  1. 2 2
      application.fam
  2. 64 60
      flipp_pomodoro_app.c
  3. 9 0
      flipp_pomodoro_app_i.h
  4. 21 0
      helpers/time.c
  5. 25 0
      helpers/time.h

+ 2 - 2
application.fam

@@ -3,9 +3,9 @@ App(
     name="Flipp Pomodoro",
     apptype=FlipperAppType.EXTERNAL,
     entry_point="flipp_pomodoro_main",
-    requires=["gui", "notification"],
+    requires=["gui", "notification", "dolphin"],
     stack_size=1 * 1024,
     fap_category="Productivity",
     fap_icon_assets="images",
     fap_icon="flipp_pomodoro_10.png",
-)
+)

+ 64 - 60
flipp_pomodoro.c → flipp_pomodoro_app.c

@@ -1,8 +1,9 @@
+#include "flipp_pomodoro_app_i.h"
 #include <furi.h>
-#include <furi_hal.h>
 
 #include <notification/notification_messages.h>
 #include <gui/gui.h>
+#include <dolphin/dolphin.h>
 #include <gui/elements.h>
 #include <input/input.h>
 
@@ -10,8 +11,6 @@
  * Just set fap_icon_assets in application.fam and #include {APPID}_icons.h */
 #include "flipp_pomodoro_icons.h"
 
-const int SECONDS_IN_MINUTE = 60;
-
 /// @brief Actions to be processed in a queue
 typedef enum {
     TimerTickType = 42,
@@ -97,42 +96,17 @@ static const PomodoroStage stage_rotaion_map[] = {
     [Rest] = Work,
 };
 
-static const int32_t stage_duration_seconds_map[] = {
-    [Work] = 25 * SECONDS_IN_MINUTE,
-    [Rest] = 5 * SECONDS_IN_MINUTE,
-};
-
 const PomodoroStage default_stage = Work;
 
-/// @brief Container for a time period
-typedef struct {
-    uint8_t seconds;
-    uint8_t minutes;
-    uint32_t total_seconds;
-} TimeDifference;
-
 typedef struct {
     PomodoroStage stage;
     uint32_t started_at_timestamp;
 } FlippPomodoroState;
 
-/// @brief Calculates difference between two provided timestamps
-/// @param begin - start timestamp of the period
-/// @param end - end timestamp of the period to measure
-/// @return TimeDifference struct
-static TimeDifference get_timestamp_difference_seconds(uint32_t begin, uint32_t end) {
-    const uint32_t duration_seconds = end - begin;
-
-    uint32_t minutes = (duration_seconds / SECONDS_IN_MINUTE) % SECONDS_IN_MINUTE;
-    uint32_t seconds = duration_seconds % SECONDS_IN_MINUTE;
-
-    return (TimeDifference){.total_seconds=duration_seconds, .minutes=minutes, .seconds=seconds};
-}
-
 static void flipp_pomodoro__toggle_stage(FlippPomodoroState* state) {
     furi_assert(state);
     state->stage = stage_rotaion_map[state->stage];
-    state->started_at_timestamp = furi_hal_rtc_get_timestamp();
+    state->started_at_timestamp = time_now();
 }
 
 static char* flipp_pomodoro__next_stage_label(FlippPomodoroState* state) {
@@ -146,25 +120,32 @@ static void flipp_pomodoro__destroy(FlippPomodoroState* state) {
     free(state);
 }
 
+static uint32_t flipp_pomodoro__current_stage_total_duration(FlippPomodoroState* state) {
+    const int32_t stage_duration_seconds_map[] = {
+        [Work] = 25 * TIME_SECONDS_IN_MINUTE,
+        [Rest] = 5 * TIME_SECONDS_IN_MINUTE,
+    };
+
+    return stage_duration_seconds_map[state->stage];
+}
+
 static uint32_t flipp_pomodoro__stage_expires_timestamp(FlippPomodoroState* state) {
-    return state->started_at_timestamp + stage_duration_seconds_map[state->stage];
+    return state->started_at_timestamp + flipp_pomodoro__current_stage_total_duration(state);
 }
 
 static TimeDifference flipp_pomodoro__stage_remaining_duration(FlippPomodoroState* state) {
-    const uint32_t now = furi_hal_rtc_get_timestamp();
     const uint32_t stage_ends_at = flipp_pomodoro__stage_expires_timestamp(state);
-    return get_timestamp_difference_seconds(now, stage_ends_at);
+    return time_difference_seconds(time_now(), stage_ends_at);
 }
 
 static bool flipp_pomodoro__is_stage_expired(FlippPomodoroState* state) {
-    const uint32_t now = furi_hal_rtc_get_timestamp();
     const uint32_t expired_by = flipp_pomodoro__stage_expires_timestamp(state);
     const uint8_t seamless_change_span_seconds = 1;
-    return (now - seamless_change_span_seconds) >= expired_by;
+    return (time_now() - seamless_change_span_seconds) >= expired_by;
 }
 
 static FlippPomodoroState flipp_pomodoro__new() {
-    const uint32_t now = furi_hal_rtc_get_timestamp();
+    const uint32_t now = time_now();
     const FlippPomodoroState new_state = {.stage=default_stage, .started_at_timestamp=now};
     return new_state;
 }
@@ -238,23 +219,30 @@ static void app_input_callback(InputEvent* input_event, void* ctx) {
     furi_message_queue_put(event_queue, &action, FuriWaitForever);
 };
 
-static bool input_events_reducer (FlippPomodoroState* state, InputEvent* input_event) {
-    bool keep_running = true;
-    if((input_event->type == InputTypePress) || (input_event->type == InputTypeRepeat)) {
-        switch(input_event->key) {
-        case InputKeyRight:
-            flipp_pomodoro__toggle_stage(state);
-            break;
-        case InputKeyBack:
-            keep_running = false;
-            break;
-        default:
-            break;
-        }
-    }
-    return keep_running;
+static bool is_input_event(Action action) {
+    return action.type == InputEventType;
+}
+
+static bool is_press_or_repeat(InputEvent* input_event) {
+    return (input_event->type == InputTypePress) || (input_event->type == InputTypeRepeat);
+}
+
+static bool is_button_back_pressed(Action action) {
+   return is_input_event(action)
+    && is_press_or_repeat(action.payload)
+    && ((InputEvent*)action.payload)->key == InputKeyBack;
+}
+
+static bool is_button_right_pressed(Action action) {
+    return is_input_event(action)
+    && is_press_or_repeat(action.payload)
+    && ((InputEvent*)action.payload)->key == InputKeyRight;
 }
 
+static bool is_timer_tick(Action action) {
+    return action.type == TimerTickType;
+};
+
 int32_t flipp_pomodoro_main(void* p) {
     UNUSED(p);
     FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(Action));
@@ -279,29 +267,45 @@ int32_t flipp_pomodoro_main(void* p) {
 
 
     bool running = true;
+
+    const int queue_reading_window_tics = 200;
+
     while(running) {
         Action action;
-        if(furi_message_queue_get(event_queue, &action, 200) != FuriStatusOk) {
+        if(furi_message_queue_get(event_queue, &action, queue_reading_window_tics) != FuriStatusOk) {
+            // Queue read is failed
             continue;
         };
 
         if(!action.type) {
+            // No item in queue
             continue;
         }
-        
-        switch (action.type) {
-        case InputEventType:
-            running = input_events_reducer(&state, action.payload);
-            break;
-        case TimerTickType:
+
+        if(is_button_back_pressed(action)) {
+            running = false;
+            continue;
+        };
+
+        if(is_timer_tick(action)) {
             if(flipp_pomodoro__is_stage_expired(&state)) {
+                if(state.stage == Work) {
+                    // REGISTER a deed on work stage complete to get an acheivement
+                    DOLPHIN_DEED(DolphinDeedPluginGameWin);
+                };
+
                 flipp_pomodoro__toggle_stage(&state);
+
+                
+
                 notification_message(notification_app, stage_start_notification_sequence_map[state.stage]);
             };
-            break;
-        default:
-            break;
         }
+
+        if(is_button_right_pressed(action)) {
+            flipp_pomodoro__toggle_stage(&state);
+        };
+
         view_port_update(view_port); // Only re-draw on event
     }
 

+ 9 - 0
flipp_pomodoro_app_i.h

@@ -0,0 +1,9 @@
+#pragma once
+
+/**
+ * Index of dependencies for the main app
+*/
+
+#include <furi.h>
+#include <furi_hal.h>
+#include "helpers/time.h"

+ 21 - 0
helpers/time.c

@@ -0,0 +1,21 @@
+#include <furi.h>
+#include <furi_hal.h>
+#include "time.h"
+
+const int TIME_SECONDS_IN_MINUTE = 60;
+const int TIME_MINUTES_IN_HOUR = 60;
+
+uint32_t time_now() {
+    return furi_hal_rtc_get_timestamp();
+};
+
+TimeDifference time_difference_seconds(uint32_t begin, uint32_t end) {
+    const uint32_t duration_seconds = end - begin;
+
+    uint32_t minutes = (duration_seconds / TIME_MINUTES_IN_HOUR) % TIME_MINUTES_IN_HOUR;
+    uint32_t seconds = duration_seconds % TIME_SECONDS_IN_MINUTE;
+
+    return (TimeDifference){.total_seconds=duration_seconds, .minutes=minutes, .seconds=seconds};
+}
+
+

+ 25 - 0
helpers/time.h

@@ -0,0 +1,25 @@
+#pragma once
+
+#include <furi.h>
+#include <furi_hal.h>
+
+extern const int TIME_SECONDS_IN_MINUTE;
+extern const int TIME_MINUTES_IN_HOUR;
+
+/// @brief Container for a time period
+typedef struct {
+    uint8_t seconds;
+    uint8_t minutes;
+    uint32_t total_seconds;
+} TimeDifference;
+
+/// @brief Time by the moment of calling
+/// @return A timestamp(seconds percision)
+uint32_t time_now();
+
+/// @brief Calculates difference between two provided timestamps
+/// @param begin - start timestamp of the period
+/// @param end - end timestamp of the period to measure
+/// @return TimeDifference struct
+TimeDifference time_difference_seconds(uint32_t begin, uint32_t end);
+