Dolphin_srv timestamp and butthurt; Desktop_srv refactoring (#750)
* dolphin_srv: save timestamp on deed; desktop_srv minor refactoring * dolphin_srv timegated butthurt increse, desktop refactoring * desktop app: update debug screen * remove debug logging * increasing icounter affects butthurt value * Dolphin: correct error message on DolphinStore load Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									1dd96419ab
								
							
						
					
					
						commit
						5dbfe3d90a
					
				| @ -19,7 +19,7 @@ | |||||||
| #include "views/desktop_debug.h" | #include "views/desktop_debug.h" | ||||||
| 
 | 
 | ||||||
| #include "scenes/desktop_scene.h" | #include "scenes/desktop_scene.h" | ||||||
| 
 | #include "helpers/desktop_animation.h" | ||||||
| #include "desktop/desktop_settings/desktop_settings.h" | #include "desktop/desktop_settings/desktop_settings.h" | ||||||
| 
 | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
|  | |||||||
							
								
								
									
										26
									
								
								applications/desktop/helpers/desktop_animation.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								applications/desktop/helpers/desktop_animation.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | |||||||
|  | #include "desktop_animation.h" | ||||||
|  | 
 | ||||||
|  | static const Icon* idle_scenes[] = {&A_Wink_128x64, &A_WatchingTV_128x64}; | ||||||
|  | 
 | ||||||
|  | const Icon* desktop_get_icon() { | ||||||
|  |     uint8_t new = 0; | ||||||
|  | 
 | ||||||
|  | #if 0 | ||||||
|  |     // checking dolphin state here to choose appropriate animation
 | ||||||
|  | 
 | ||||||
|  |     Dolphin* dolphin = furi_record_open("dolphin"); | ||||||
|  |     DolphinStats stats = dolphin_stats(dolphin); | ||||||
|  |     float timediff = fabs(difftime(stats.timestamp, dolphin_state_timestamp())); | ||||||
|  | 
 | ||||||
|  |     FURI_LOG_I("desktop-animation", "background change"); | ||||||
|  |     FURI_LOG_I("desktop-animation", "icounter: %d", stats.icounter); | ||||||
|  |     FURI_LOG_I("desktop-animation", "butthurt: %d", stats.butthurt); | ||||||
|  |     FURI_LOG_I("desktop-animation", "time since deeed: %.0f", timediff); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |     if((random() % 100) > 50) { // temp rnd selection
 | ||||||
|  |         new = random() % COUNT_OF(idle_scenes); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return idle_scenes[new]; | ||||||
|  | } | ||||||
							
								
								
									
										10
									
								
								applications/desktop/helpers/desktop_animation.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								applications/desktop/helpers/desktop_animation.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <furi.h> | ||||||
|  | #include <math.h> | ||||||
|  | #include <assets_icons.h> | ||||||
|  | #include "dolphin/dolphin.h" | ||||||
|  | #include "dolphin/helpers/dolphin_state.h" | ||||||
|  | #include "time.h" | ||||||
|  | 
 | ||||||
|  | const Icon* desktop_get_icon(); | ||||||
| @ -13,6 +13,7 @@ void desktop_scene_locked_on_enter(void* context) { | |||||||
|     desktop_locked_set_callback(locked_view, desktop_scene_locked_callback, desktop); |     desktop_locked_set_callback(locked_view, desktop_scene_locked_callback, desktop); | ||||||
|     desktop_locked_reset_door_pos(locked_view); |     desktop_locked_reset_door_pos(locked_view); | ||||||
|     desktop_locked_update_hint_timeout(locked_view); |     desktop_locked_update_hint_timeout(locked_view); | ||||||
|  |     desktop_locked_set_dolphin_animation(locked_view); | ||||||
| 
 | 
 | ||||||
|     view_port_enabled_set(desktop->lock_viewport, true); |     view_port_enabled_set(desktop->lock_viewport, true); | ||||||
|     osTimerStart(locked_view->timer, 63); |     osTimerStart(locked_view->timer, 63); | ||||||
|  | |||||||
| @ -39,6 +39,7 @@ void desktop_scene_main_on_enter(void* context) { | |||||||
|         desktop_main_unlocked(desktop->main_view); |         desktop_main_unlocked(desktop->main_view); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     desktop_main_switch_dolphin_animation(desktop->main_view); | ||||||
|     view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewMain); |     view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewMain); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -2,8 +2,8 @@ | |||||||
| #include "../desktop_i.h" | #include "../desktop_i.h" | ||||||
| #include "desktop_debug.h" | #include "desktop_debug.h" | ||||||
| 
 | 
 | ||||||
| #include "applications/dolphin/helpers/dolphin_state.h" | #include "dolphin/helpers/dolphin_state.h" | ||||||
| #include "applications/dolphin/dolphin.h" | #include "dolphin/dolphin.h" | ||||||
| 
 | 
 | ||||||
| void desktop_debug_set_callback( | void desktop_debug_set_callback( | ||||||
|     DesktopDebugView* debug_view, |     DesktopDebugView* debug_view, | ||||||
| @ -21,7 +21,7 @@ void desktop_debug_render(Canvas* canvas, void* model) { | |||||||
|     const Version* ver; |     const Version* ver; | ||||||
|     char buffer[64]; |     char buffer[64]; | ||||||
| 
 | 
 | ||||||
|     static const char* headers[] = {"FW Version info:", "Boot Version info:", "Desktop info:"}; |     static const char* headers[] = {"FW Version info:", "Boot Version info:", "Dolphin info:"}; | ||||||
| 
 | 
 | ||||||
|     canvas_set_color(canvas, ColorBlack); |     canvas_set_color(canvas, ColorBlack); | ||||||
|     canvas_set_font(canvas, FontPrimary); |     canvas_set_font(canvas, FontPrimary); | ||||||
| @ -56,7 +56,7 @@ void desktop_debug_render(Canvas* canvas, void* model) { | |||||||
|             "%s [%s]", |             "%s [%s]", | ||||||
|             version_get_version(ver), |             version_get_version(ver), | ||||||
|             version_get_builddate(ver)); |             version_get_builddate(ver)); | ||||||
|         canvas_draw_str(canvas, 5, 33, buffer); |         canvas_draw_str(canvas, 5, 32, buffer); | ||||||
| 
 | 
 | ||||||
|         snprintf( |         snprintf( | ||||||
|             buffer, |             buffer, | ||||||
| @ -68,16 +68,22 @@ void desktop_debug_render(Canvas* canvas, void* model) { | |||||||
| 
 | 
 | ||||||
|         snprintf( |         snprintf( | ||||||
|             buffer, sizeof(buffer), "[%s] %s", version_get_target(ver), version_get_gitbranch(ver)); |             buffer, sizeof(buffer), "[%s] %s", version_get_target(ver), version_get_gitbranch(ver)); | ||||||
|         canvas_draw_str(canvas, 5, 53, buffer); |         canvas_draw_str(canvas, 5, 54, buffer); | ||||||
| 
 | 
 | ||||||
|     } else { |     } else { | ||||||
|         char buffer[64]; |         char buffer[64]; | ||||||
|  |         uint32_t current_lvl = dolphin_state_get_level(m->icounter); | ||||||
|  |         uint32_t remaining = dolphin_state_xp_to_levelup(m->icounter, current_lvl, true); | ||||||
| 
 | 
 | ||||||
|         canvas_set_font(canvas, FontSecondary); |         canvas_set_font(canvas, FontSecondary); | ||||||
|         snprintf(buffer, 64, "Icounter: %ld", m->icounter); |         snprintf(buffer, 64, "Icounter: %ld  Butthurt %ld", m->icounter, m->butthurt); | ||||||
|         canvas_draw_str(canvas, 5, 30, buffer); |         canvas_draw_str(canvas, 5, 23, buffer); | ||||||
|         snprintf(buffer, 64, "Butthurt: %ld", m->butthurt); | 
 | ||||||
|         canvas_draw_str(canvas, 5, 40, buffer); |         snprintf(buffer, 64, "Level: %ld  To level up: %ld", current_lvl, remaining); | ||||||
|  |         canvas_draw_str(canvas, 5, 33, buffer); | ||||||
|  | 
 | ||||||
|  |         snprintf(buffer, 64, "%s", asctime(localtime((const time_t*)&m->timestamp))); | ||||||
|  |         canvas_draw_str(canvas, 5, 43, buffer); | ||||||
|         canvas_draw_str(canvas, 0, 53, "[< >] icounter value   [ok] save"); |         canvas_draw_str(canvas, 0, 53, "[< >] icounter value   [ok] save"); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -151,6 +157,7 @@ void desktop_debug_get_dolphin_data(DesktopDebugView* debug_view) { | |||||||
|         debug_view->view, (DesktopDebugViewModel * model) { |         debug_view->view, (DesktopDebugViewModel * model) { | ||||||
|             model->icounter = stats.icounter; |             model->icounter = stats.icounter; | ||||||
|             model->butthurt = stats.butthurt; |             model->butthurt = stats.butthurt; | ||||||
|  |             model->timestamp = stats.timestamp; | ||||||
|             return true; |             return true; | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ | |||||||
| #include <gui/elements.h> | #include <gui/elements.h> | ||||||
| #include <furi.h> | #include <furi.h> | ||||||
| #include <storage/storage.h> | #include <storage/storage.h> | ||||||
|  | #include <time.h> | ||||||
| 
 | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
|     DesktopDebugEventDeed, |     DesktopDebugEventDeed, | ||||||
| @ -35,6 +36,7 @@ struct DesktopDebugView { | |||||||
| typedef struct { | typedef struct { | ||||||
|     uint32_t icounter; |     uint32_t icounter; | ||||||
|     uint32_t butthurt; |     uint32_t butthurt; | ||||||
|  |     uint64_t timestamp; | ||||||
|     DesktopViewStatsScreens screen; |     DesktopViewStatsScreens screen; | ||||||
| } DesktopDebugViewModel; | } DesktopDebugViewModel; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -2,8 +2,6 @@ | |||||||
| #include "../desktop_i.h" | #include "../desktop_i.h" | ||||||
| #include "desktop_locked.h" | #include "desktop_locked.h" | ||||||
| 
 | 
 | ||||||
| static const Icon* idle_scenes[] = {&A_Wink_128x64, &A_WatchingTV_128x64}; |  | ||||||
| 
 |  | ||||||
| void desktop_locked_set_callback( | void desktop_locked_set_callback( | ||||||
|     DesktopLockedView* locked_view, |     DesktopLockedView* locked_view, | ||||||
|     DesktopLockedViewCallback callback, |     DesktopLockedViewCallback callback, | ||||||
| @ -20,11 +18,11 @@ void locked_view_timer_callback(void* context) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // temporary locked screen animation managment
 | // temporary locked screen animation managment
 | ||||||
| static void desktop_locked_set_scene(DesktopLockedView* locked_view, const Icon* icon_data) { | void desktop_locked_set_dolphin_animation(DesktopLockedView* locked_view) { | ||||||
|     with_view_model( |     with_view_model( | ||||||
|         locked_view->view, (DesktopLockedViewModel * model) { |         locked_view->view, (DesktopLockedViewModel * model) { | ||||||
|             if(model->animation) icon_animation_free(model->animation); |             if(model->animation) icon_animation_free(model->animation); | ||||||
|             model->animation = icon_animation_alloc(icon_data); |             model->animation = icon_animation_alloc(desktop_get_icon()); | ||||||
|             view_tie_icon_animation(locked_view->view, model->animation); |             view_tie_icon_animation(locked_view->view, model->animation); | ||||||
|             return true; |             return true; | ||||||
|         }); |         }); | ||||||
| @ -42,8 +40,8 @@ void desktop_locked_reset_door_pos(DesktopLockedView* locked_view) { | |||||||
|     with_view_model( |     with_view_model( | ||||||
|         locked_view->view, (DesktopLockedViewModel * model) { |         locked_view->view, (DesktopLockedViewModel * model) { | ||||||
|             model->animation_seq_end = false; |             model->animation_seq_end = false; | ||||||
|             model->door_left_x = -57; |             model->door_left_x = DOOR_L_POS; | ||||||
|             model->door_right_x = 115; |             model->door_right_x = DOOR_R_POS; | ||||||
|             return true; |             return true; | ||||||
|         }); |         }); | ||||||
| } | } | ||||||
| @ -57,10 +55,10 @@ void desktop_locked_manage_redraw(DesktopLockedView* locked_view) { | |||||||
|             animation_seq_end = model->animation_seq_end; |             animation_seq_end = model->animation_seq_end; | ||||||
| 
 | 
 | ||||||
|             if(!model->animation_seq_end) { |             if(!model->animation_seq_end) { | ||||||
|                 model->door_left_x = CLAMP(model->door_left_x + 5, 0, -57); |                 model->door_left_x = CLAMP(model->door_left_x + 5, DOOR_L_POS_MAX, DOOR_L_POS); | ||||||
|                 model->door_right_x = CLAMP(model->door_right_x - 5, 115, 60); |                 model->door_right_x = CLAMP(model->door_right_x - 5, DOOR_R_POS, DOOR_R_POS_MIN); | ||||||
|             } else { |             } else { | ||||||
|                 model->hint_expire_at = 0; |                 model->hint_expire_at = !model->hint_expire_at; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             return true; |             return true; | ||||||
| @ -84,7 +82,7 @@ void desktop_locked_reset_counter(DesktopLockedView* locked_view) { | |||||||
| 
 | 
 | ||||||
| void desktop_locked_render(Canvas* canvas, void* model) { | void desktop_locked_render(Canvas* canvas, void* model) { | ||||||
|     DesktopLockedViewModel* m = model; |     DesktopLockedViewModel* m = model; | ||||||
| 
 |     uint32_t now = osKernelGetTickCount(); | ||||||
|     canvas_clear(canvas); |     canvas_clear(canvas); | ||||||
|     canvas_set_color(canvas, ColorBlack); |     canvas_set_color(canvas, ColorBlack); | ||||||
| 
 | 
 | ||||||
| @ -97,7 +95,7 @@ void desktop_locked_render(Canvas* canvas, void* model) { | |||||||
|         canvas_draw_icon_animation(canvas, 0, -3, m->animation); |         canvas_draw_icon_animation(canvas, 0, -3, m->animation); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if(osKernelGetTickCount() < m->hint_expire_at) { |     if(now < m->hint_expire_at) { | ||||||
|         if(!m->animation_seq_end) { |         if(!m->animation_seq_end) { | ||||||
|             canvas_set_font(canvas, FontPrimary); |             canvas_set_font(canvas, FontPrimary); | ||||||
|             elements_multiline_text_framed(canvas, 42, 30, "Locked"); |             elements_multiline_text_framed(canvas, 42, 30, "Locked"); | ||||||
| @ -125,7 +123,6 @@ bool desktop_locked_input(InputEvent* event, void* context) { | |||||||
| 
 | 
 | ||||||
|         if(event->key == InputKeyBack) { |         if(event->key == InputKeyBack) { | ||||||
|             uint32_t press_time = osKernelGetTickCount(); |             uint32_t press_time = osKernelGetTickCount(); | ||||||
| 
 |  | ||||||
|             // check if pressed sequentially
 |             // check if pressed sequentially
 | ||||||
|             if(press_time - locked_view->lock_lastpress > UNLOCK_RST_TIMEOUT) { |             if(press_time - locked_view->lock_lastpress > UNLOCK_RST_TIMEOUT) { | ||||||
|                 locked_view->lock_lastpress = press_time; |                 locked_view->lock_lastpress = press_time; | ||||||
| @ -178,7 +175,6 @@ DesktopLockedView* desktop_locked_alloc() { | |||||||
|     view_set_enter_callback(locked_view->view, desktop_locked_enter); |     view_set_enter_callback(locked_view->view, desktop_locked_enter); | ||||||
|     view_set_exit_callback(locked_view->view, desktop_locked_exit); |     view_set_exit_callback(locked_view->view, desktop_locked_exit); | ||||||
| 
 | 
 | ||||||
|     desktop_locked_set_scene(locked_view, idle_scenes[random() % COUNT_OF(idle_scenes)]); |  | ||||||
|     return locked_view; |     return locked_view; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -9,6 +9,11 @@ | |||||||
| #define UNLOCK_RST_TIMEOUT 300 | #define UNLOCK_RST_TIMEOUT 300 | ||||||
| #define UNLOCK_CNT 2 // 3 actually
 | #define UNLOCK_CNT 2 // 3 actually
 | ||||||
| 
 | 
 | ||||||
|  | #define DOOR_L_POS -57 | ||||||
|  | #define DOOR_L_POS_MAX 0 | ||||||
|  | #define DOOR_R_POS 115 | ||||||
|  | #define DOOR_R_POS_MIN 60 | ||||||
|  | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
|     DesktopLockedEventUnlock, |     DesktopLockedEventUnlock, | ||||||
|     DesktopLockedEventUpdate, |     DesktopLockedEventUpdate, | ||||||
| @ -44,6 +49,7 @@ void desktop_locked_set_callback( | |||||||
|     DesktopLockedViewCallback callback, |     DesktopLockedViewCallback callback, | ||||||
|     void* context); |     void* context); | ||||||
| 
 | 
 | ||||||
|  | void desktop_locked_set_dolphin_animation(DesktopLockedView* locked_view); | ||||||
| void desktop_locked_update_hint_timeout(DesktopLockedView* locked_view); | void desktop_locked_update_hint_timeout(DesktopLockedView* locked_view); | ||||||
| void desktop_locked_reset_counter(DesktopLockedView* locked_view); | void desktop_locked_reset_counter(DesktopLockedView* locked_view); | ||||||
| void desktop_locked_reset_door_pos(DesktopLockedView* locked_view); | void desktop_locked_reset_door_pos(DesktopLockedView* locked_view); | ||||||
|  | |||||||
| @ -2,8 +2,6 @@ | |||||||
| #include "../desktop_i.h" | #include "../desktop_i.h" | ||||||
| #include "desktop_main.h" | #include "desktop_main.h" | ||||||
| 
 | 
 | ||||||
| static const Icon* idle_scenes[] = {&A_Wink_128x64, &A_WatchingTV_128x64}; |  | ||||||
| 
 |  | ||||||
| void desktop_main_set_callback( | void desktop_main_set_callback( | ||||||
|     DesktopMainView* main_view, |     DesktopMainView* main_view, | ||||||
|     DesktopMainViewCallback callback, |     DesktopMainViewCallback callback, | ||||||
| @ -22,38 +20,26 @@ void desktop_main_reset_hint(DesktopMainView* main_view) { | |||||||
|         }); |         }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // temporary main screen animation managment
 | void desktop_main_switch_dolphin_animation(DesktopMainView* main_view) { | ||||||
| static void desktop_main_set_scene(DesktopMainView* main_view, const Icon* icon_data) { |  | ||||||
|     with_view_model( |     with_view_model( | ||||||
|         main_view->view, (DesktopMainViewModel * model) { |         main_view->view, (DesktopMainViewModel * model) { | ||||||
|             if(model->animation) icon_animation_free(model->animation); |             if(model->animation) icon_animation_free(model->animation); | ||||||
|             model->animation = icon_animation_alloc(icon_data); |             model->animation = icon_animation_alloc(desktop_get_icon()); | ||||||
|             view_tie_icon_animation(main_view->view, model->animation); |             view_tie_icon_animation(main_view->view, model->animation); | ||||||
|             return true; |             return true; | ||||||
|         }); |         }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void desktop_scene_handler_switch_scene(DesktopMainView* main_view) { |  | ||||||
|     with_view_model( |  | ||||||
|         main_view->view, (DesktopMainViewModel * model) { |  | ||||||
|             if(icon_animation_is_last_frame(model->animation)) { |  | ||||||
|                 if(model->animation) icon_animation_free(model->animation); |  | ||||||
|                 model->animation = icon_animation_alloc(idle_scenes[model->scene_num]); |  | ||||||
|                 model->scene_num = random() % COUNT_OF(idle_scenes); |  | ||||||
|             } |  | ||||||
|             return true; |  | ||||||
|         }); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void desktop_main_render(Canvas* canvas, void* model) { | void desktop_main_render(Canvas* canvas, void* model) { | ||||||
|     canvas_clear(canvas); |     canvas_clear(canvas); | ||||||
|     DesktopMainViewModel* m = model; |     DesktopMainViewModel* m = model; | ||||||
|  |     uint32_t now = osKernelGetTickCount(); | ||||||
| 
 | 
 | ||||||
|     if(m->animation) { |     if(m->animation) { | ||||||
|         canvas_draw_icon_animation(canvas, 0, -3, m->animation); |         canvas_draw_icon_animation(canvas, 0, -3, m->animation); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if(osKernelGetTickCount() < m->hint_expire_at) { |     if(now < m->hint_expire_at) { | ||||||
|         canvas_set_font(canvas, FontPrimary); |         canvas_set_font(canvas, FontPrimary); | ||||||
|         elements_multiline_text_framed(canvas, 42, 30, "Unlocked"); |         elements_multiline_text_framed(canvas, 42, 30, "Unlocked"); | ||||||
|     } |     } | ||||||
| @ -115,8 +101,6 @@ DesktopMainView* desktop_main_alloc() { | |||||||
|     view_set_enter_callback(main_view->view, desktop_main_enter); |     view_set_enter_callback(main_view->view, desktop_main_enter); | ||||||
|     view_set_exit_callback(main_view->view, desktop_main_exit); |     view_set_exit_callback(main_view->view, desktop_main_exit); | ||||||
| 
 | 
 | ||||||
|     desktop_main_set_scene(main_view, idle_scenes[random() % COUNT_OF(idle_scenes)]); |  | ||||||
| 
 |  | ||||||
|     return main_view; |     return main_view; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -41,3 +41,5 @@ View* desktop_main_get_view(DesktopMainView* main_view); | |||||||
| DesktopMainView* desktop_main_alloc(); | DesktopMainView* desktop_main_alloc(); | ||||||
| 
 | 
 | ||||||
| void desktop_main_free(DesktopMainView* main_view); | void desktop_main_free(DesktopMainView* main_view); | ||||||
|  | 
 | ||||||
|  | void desktop_main_switch_dolphin_animation(DesktopMainView* main_view); | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| #include "dolphin_i.h" | #include "dolphin_i.h" | ||||||
| #include <furi.h> | #include <furi.h> | ||||||
| 
 | #define DOLPHIN_TIMEGATE 86400 // one day
 | ||||||
| #define DOLPHIN_LOCK_EVENT_FLAG (0x1) | #define DOLPHIN_LOCK_EVENT_FLAG (0x1) | ||||||
| 
 | 
 | ||||||
| void dolphin_deed(Dolphin* dolphin, DolphinDeed deed) { | void dolphin_deed(Dolphin* dolphin, DolphinDeed deed) { | ||||||
| @ -77,6 +77,21 @@ void dolphin_event_release(Dolphin* dolphin, DolphinEvent* event) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void dolphin_check_butthurt(DolphinState* state) { | ||||||
|  |     furi_assert(state); | ||||||
|  |     float diff_time = difftime(dolphin_state_get_timestamp(state), dolphin_state_timestamp()); | ||||||
|  | 
 | ||||||
|  | #if 0 | ||||||
|  |     FURI_LOG_I("dolphin-state", "Butthurt check, time since deed %.0f", fabs(diff_time)); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |     if((fabs(diff_time)) > DOLPHIN_TIMEGATE) { | ||||||
|  |         // increase butthurt
 | ||||||
|  |         FURI_LOG_I("dolphin-state", "Increasing butthurt"); | ||||||
|  |         dolphin_state_butthurted(state); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| int32_t dolphin_srv(void* p) { | int32_t dolphin_srv(void* p) { | ||||||
|     Dolphin* dolphin = dolphin_alloc(); |     Dolphin* dolphin = dolphin_alloc(); | ||||||
|     furi_record_create("dolphin", dolphin); |     furi_record_create("dolphin", dolphin); | ||||||
| @ -91,11 +106,13 @@ int32_t dolphin_srv(void* p) { | |||||||
|             } else if(event.type == DolphinEventTypeStats) { |             } else if(event.type == DolphinEventTypeStats) { | ||||||
|                 event.stats->icounter = dolphin_state_get_icounter(dolphin->state); |                 event.stats->icounter = dolphin_state_get_icounter(dolphin->state); | ||||||
|                 event.stats->butthurt = dolphin_state_get_butthurt(dolphin->state); |                 event.stats->butthurt = dolphin_state_get_butthurt(dolphin->state); | ||||||
|  |                 event.stats->timestamp = dolphin_state_get_timestamp(dolphin->state); | ||||||
|             } else if(event.type == DolphinEventTypeFlush) { |             } else if(event.type == DolphinEventTypeFlush) { | ||||||
|                 dolphin_state_save(dolphin->state); |                 dolphin_state_save(dolphin->state); | ||||||
|             } |             } | ||||||
|             dolphin_event_release(dolphin, &event); |             dolphin_event_release(dolphin, &event); | ||||||
|         } else { |         } else { | ||||||
|  |             dolphin_check_butthurt(dolphin->state); | ||||||
|             dolphin_state_save(dolphin->state); |             dolphin_state_save(dolphin->state); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -7,6 +7,7 @@ typedef struct Dolphin Dolphin; | |||||||
| typedef struct { | typedef struct { | ||||||
|     uint32_t icounter; |     uint32_t icounter; | ||||||
|     uint32_t butthurt; |     uint32_t butthurt; | ||||||
|  |     uint64_t timestamp; | ||||||
| } DolphinStats; | } DolphinStats; | ||||||
| 
 | 
 | ||||||
| /** Deed complete notification. Call it on deed completion.
 | /** Deed complete notification. Call it on deed completion.
 | ||||||
|  | |||||||
| @ -25,6 +25,7 @@ typedef struct { | |||||||
|     uint32_t flags; |     uint32_t flags; | ||||||
|     uint32_t icounter; |     uint32_t icounter; | ||||||
|     uint32_t butthurt; |     uint32_t butthurt; | ||||||
|  |     uint64_t timestamp; | ||||||
| } DolphinStoreData; | } DolphinStoreData; | ||||||
| 
 | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
| @ -107,8 +108,12 @@ bool dolphin_state_load(DolphinState* dolphin_state) { | |||||||
| 
 | 
 | ||||||
|     File* file = storage_file_alloc(dolphin_state->fs_api); |     File* file = storage_file_alloc(dolphin_state->fs_api); | ||||||
|     bool load_result = storage_file_open(file, DOLPHIN_STORE_KEY, FSAM_READ, FSOM_OPEN_EXISTING); |     bool load_result = storage_file_open(file, DOLPHIN_STORE_KEY, FSAM_READ, FSOM_OPEN_EXISTING); | ||||||
| 
 |     if(!load_result) { | ||||||
|     if(load_result) { |         FURI_LOG_E( | ||||||
|  |             "dolphin-state", | ||||||
|  |             "Load failed. Storage returned: %s", | ||||||
|  |             storage_file_get_error_desc(file)); | ||||||
|  |     } else { | ||||||
|         uint16_t bytes_count = storage_file_read(file, &store, sizeof(DolphinStore)); |         uint16_t bytes_count = storage_file_read(file, &store, sizeof(DolphinStore)); | ||||||
| 
 | 
 | ||||||
|         if(bytes_count != sizeof(DolphinStore)) { |         if(bytes_count != sizeof(DolphinStore)) { | ||||||
| @ -117,12 +122,8 @@ bool dolphin_state_load(DolphinState* dolphin_state) { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if(!load_result) { |     if(!load_result) { | ||||||
|         FURI_LOG_E( |         FURI_LOG_E("dolphin-state", "DolphinStore size mismatch"); | ||||||
|             "dolphin-state", |  | ||||||
|             "Load failed. Storage returned: %s", |  | ||||||
|             storage_file_get_error_desc(file)); |  | ||||||
|     } else { |     } else { | ||||||
|         FURI_LOG_I("dolphin-state", "State loaded, verifying header"); |  | ||||||
|         if(store.header.magic == DOLPHIN_STORE_HEADER_MAGIC && |         if(store.header.magic == DOLPHIN_STORE_HEADER_MAGIC && | ||||||
|            store.header.version == DOLPHIN_STORE_HEADER_VERSION) { |            store.header.version == DOLPHIN_STORE_HEADER_VERSION) { | ||||||
|             FURI_LOG_I( |             FURI_LOG_I( | ||||||
| @ -150,7 +151,7 @@ bool dolphin_state_load(DolphinState* dolphin_state) { | |||||||
|         } else { |         } else { | ||||||
|             FURI_LOG_E( |             FURI_LOG_E( | ||||||
|                 "dolphin-state", |                 "dolphin-state", | ||||||
|                 "Magic(%d != %d) and Version(%d != %d) mismatch", |                 "Magic(%d != %d) or Version(%d != %d) mismatch", | ||||||
|                 store.header.magic, |                 store.header.magic, | ||||||
|                 DOLPHIN_STORE_HEADER_MAGIC, |                 DOLPHIN_STORE_HEADER_MAGIC, | ||||||
|                 store.header.version, |                 store.header.version, | ||||||
| @ -171,17 +172,45 @@ void dolphin_state_clear(DolphinState* dolphin_state) { | |||||||
|     memset(&dolphin_state->data, 0, sizeof(DolphinStoreData)); |     memset(&dolphin_state->data, 0, sizeof(DolphinStoreData)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | uint64_t dolphin_state_timestamp() { | ||||||
|  |     RTC_TimeTypeDef time; | ||||||
|  |     RTC_DateTypeDef date; | ||||||
|  |     struct tm current; | ||||||
|  | 
 | ||||||
|  |     HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN); | ||||||
|  |     HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN); | ||||||
|  | 
 | ||||||
|  |     current.tm_year = date.Year + 100; | ||||||
|  |     current.tm_mday = date.Date; | ||||||
|  |     current.tm_mon = date.Month - 1; | ||||||
|  | 
 | ||||||
|  |     current.tm_hour = time.Hours; | ||||||
|  |     current.tm_min = time.Minutes; | ||||||
|  |     current.tm_sec = time.Seconds; | ||||||
|  | 
 | ||||||
|  |     return mktime(¤t); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void dolphin_state_on_deed(DolphinState* dolphin_state, DolphinDeed deed) { | void dolphin_state_on_deed(DolphinState* dolphin_state, DolphinDeed deed) { | ||||||
|     const DolphinDeedWeight* deed_weight = dolphin_deed_weight(deed); |     const DolphinDeedWeight* deed_weight = dolphin_deed_weight(deed); | ||||||
|     int32_t icounter = dolphin_state->data.icounter + deed_weight->icounter; |     int32_t icounter = dolphin_state->data.icounter + deed_weight->icounter; | ||||||
|  |     int32_t butthurt = dolphin_state->data.butthurt; | ||||||
| 
 | 
 | ||||||
|     if(icounter >= 0) { |     if(icounter >= 0) { | ||||||
|         dolphin_state->data.icounter = icounter; |         dolphin_state->data.icounter = icounter; | ||||||
|  |         dolphin_state->data.butthurt = MAX(butthurt - deed_weight->icounter, 0); | ||||||
|  |         dolphin_state->data.timestamp = dolphin_state_timestamp(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     dolphin_state->dirty = true; |     dolphin_state->dirty = true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void dolphin_state_butthurted(DolphinState* dolphin_state) { | ||||||
|  |     dolphin_state->data.butthurt++; | ||||||
|  |     dolphin_state->data.timestamp = dolphin_state_timestamp(); | ||||||
|  |     dolphin_state->dirty = true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| uint32_t dolphin_state_get_icounter(DolphinState* dolphin_state) { | uint32_t dolphin_state_get_icounter(DolphinState* dolphin_state) { | ||||||
|     return dolphin_state->data.icounter; |     return dolphin_state->data.icounter; | ||||||
| } | } | ||||||
| @ -190,13 +219,14 @@ uint32_t dolphin_state_get_butthurt(DolphinState* dolphin_state) { | |||||||
|     return dolphin_state->data.butthurt; |     return dolphin_state->data.butthurt; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint32_t dolphin_state_get_level(DolphinState* dolphin_state) { | uint64_t dolphin_state_get_timestamp(DolphinState* dolphin_state) { | ||||||
|     return 0.5f + |     return dolphin_state->data.timestamp; | ||||||
|            sqrtf(1.0f + 8.0f * ((float)dolphin_state->data.icounter / DOLPHIN_LVL_THRESHOLD)) / |  | ||||||
|                2.0f; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint32_t dolphin_state_xp_to_levelup(DolphinState* dolphin_state, uint32_t level, bool remaining) { | uint32_t dolphin_state_get_level(uint32_t icounter) { | ||||||
|     return (DOLPHIN_LVL_THRESHOLD * level * (level + 1) / 2) - |     return 0.5f + sqrtf(1.0f + 8.0f * ((float)icounter / DOLPHIN_LVL_THRESHOLD)) / 2.0f; | ||||||
|            (remaining ? dolphin_state->data.icounter : 0); | } | ||||||
|  | 
 | ||||||
|  | uint32_t dolphin_state_xp_to_levelup(uint32_t icounter, uint32_t level, bool remaining) { | ||||||
|  |     return (DOLPHIN_LVL_THRESHOLD * level * (level + 1) / 2) - (remaining ? icounter : 0); | ||||||
| } | } | ||||||
| @ -3,6 +3,8 @@ | |||||||
| #include "dolphin_deed.h" | #include "dolphin_deed.h" | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
|  | #include <rtc.h> | ||||||
|  | #include <time.h> | ||||||
| 
 | 
 | ||||||
| typedef struct DolphinState DolphinState; | typedef struct DolphinState DolphinState; | ||||||
| 
 | 
 | ||||||
| @ -16,12 +18,18 @@ bool dolphin_state_load(DolphinState* dolphin_state); | |||||||
| 
 | 
 | ||||||
| void dolphin_state_clear(DolphinState* dolphin_state); | void dolphin_state_clear(DolphinState* dolphin_state); | ||||||
| 
 | 
 | ||||||
|  | uint64_t dolphin_state_timestamp(); | ||||||
|  | 
 | ||||||
| void dolphin_state_on_deed(DolphinState* dolphin_state, DolphinDeed deed); | void dolphin_state_on_deed(DolphinState* dolphin_state, DolphinDeed deed); | ||||||
| 
 | 
 | ||||||
|  | void dolphin_state_butthurted(DolphinState* dolphin_state); | ||||||
|  | 
 | ||||||
| uint32_t dolphin_state_get_icounter(DolphinState* dolphin_state); | uint32_t dolphin_state_get_icounter(DolphinState* dolphin_state); | ||||||
| 
 | 
 | ||||||
| uint32_t dolphin_state_get_butthurt(DolphinState* dolphin_state); | uint32_t dolphin_state_get_butthurt(DolphinState* dolphin_state); | ||||||
| 
 | 
 | ||||||
| uint32_t dolphin_state_get_level(DolphinState* dolphin_state); | uint64_t dolphin_state_get_timestamp(DolphinState* dolphin_state); | ||||||
| 
 | 
 | ||||||
| uint32_t dolphin_state_xp_to_levelup(DolphinState* dolphin_state, uint32_t level, bool remaining); | uint32_t dolphin_state_get_level(uint32_t icounter); | ||||||
|  | 
 | ||||||
|  | uint32_t dolphin_state_xp_to_levelup(uint32_t icounter, uint32_t level, bool remaining); | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 its your bedtime
						its your bedtime