dolphin_state.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. #include "dolphin_state.h"
  2. #include <stdint.h>
  3. #include <storage/storage.h>
  4. #include <furi.h>
  5. #include <math.h>
  6. #include <toolbox/saved_struct.h>
  7. #define TAG "DolphinState"
  8. #define DOLPHIN_STATE_PATH "/int/dolphin.state"
  9. #define DOLPHIN_STATE_HEADER_MAGIC 0xD0
  10. #define DOLPHIN_STATE_HEADER_VERSION 0x01
  11. #define DOLPHIN_LVL_THRESHOLD 20.0f
  12. #define LEVEL2_THRESHOLD 20
  13. #define LEVEL3_THRESHOLD 100
  14. DolphinState* dolphin_state_alloc() {
  15. return furi_alloc(sizeof(DolphinState));
  16. }
  17. void dolphin_state_free(DolphinState* dolphin_state) {
  18. free(dolphin_state);
  19. }
  20. bool dolphin_state_save(DolphinState* dolphin_state) {
  21. if(!dolphin_state->dirty) {
  22. return true;
  23. }
  24. bool result = saved_struct_save(
  25. DOLPHIN_STATE_PATH,
  26. &dolphin_state->data,
  27. sizeof(DolphinStoreData),
  28. DOLPHIN_STATE_HEADER_MAGIC,
  29. DOLPHIN_STATE_HEADER_VERSION);
  30. if(result) {
  31. FURI_LOG_I(TAG, "State saved");
  32. dolphin_state->dirty = false;
  33. } else {
  34. FURI_LOG_E(TAG, "Failed to save state");
  35. }
  36. return result;
  37. }
  38. bool dolphin_state_load(DolphinState* dolphin_state) {
  39. bool loaded = saved_struct_load(
  40. DOLPHIN_STATE_PATH,
  41. &dolphin_state->data,
  42. sizeof(DolphinStoreData),
  43. DOLPHIN_STATE_HEADER_MAGIC,
  44. DOLPHIN_STATE_HEADER_VERSION);
  45. if(!loaded) {
  46. FURI_LOG_W(TAG, "Reset dolphin-state");
  47. memset(dolphin_state, 0, sizeof(*dolphin_state));
  48. dolphin_state->dirty = true;
  49. }
  50. return loaded;
  51. }
  52. uint64_t dolphin_state_timestamp() {
  53. RTC_TimeTypeDef time;
  54. RTC_DateTypeDef date;
  55. struct tm current;
  56. HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN);
  57. HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN);
  58. current.tm_year = date.Year + 100;
  59. current.tm_mday = date.Date;
  60. current.tm_mon = date.Month - 1;
  61. current.tm_hour = time.Hours;
  62. current.tm_min = time.Minutes;
  63. current.tm_sec = time.Seconds;
  64. return mktime(&current);
  65. }
  66. bool dolphin_state_is_levelup(uint32_t icounter) {
  67. return (icounter == LEVEL2_THRESHOLD) || (icounter == LEVEL3_THRESHOLD);
  68. }
  69. uint8_t dolphin_get_level(uint32_t icounter) {
  70. if(icounter <= LEVEL2_THRESHOLD) {
  71. return 1;
  72. } else if(icounter <= LEVEL3_THRESHOLD) {
  73. return 2;
  74. } else {
  75. return 3;
  76. }
  77. }
  78. uint32_t dolphin_state_xp_to_levelup(uint32_t icounter) {
  79. uint32_t threshold = 0;
  80. if(icounter <= LEVEL2_THRESHOLD) {
  81. threshold = LEVEL2_THRESHOLD;
  82. } else if(icounter <= LEVEL3_THRESHOLD) {
  83. threshold = LEVEL3_THRESHOLD;
  84. } else {
  85. threshold = (uint32_t)-1;
  86. }
  87. return threshold - icounter;
  88. }
  89. bool dolphin_state_on_deed(DolphinState* dolphin_state, DolphinDeed deed) {
  90. const DolphinDeedWeight* deed_weight = dolphin_deed_weight(deed);
  91. int32_t icounter = dolphin_state->data.icounter + deed_weight->icounter;
  92. bool level_up = false;
  93. bool mood_changed = false;
  94. if(icounter <= 0) {
  95. icounter = 0;
  96. if(dolphin_state->data.icounter == 0) {
  97. return false;
  98. }
  99. }
  100. uint8_t xp_to_levelup = dolphin_state_xp_to_levelup(dolphin_state->data.icounter);
  101. if(xp_to_levelup) {
  102. level_up = true;
  103. dolphin_state->data.icounter += MIN(xp_to_levelup, deed_weight->icounter);
  104. }
  105. uint32_t new_butthurt =
  106. CLAMP(((int32_t)dolphin_state->data.butthurt) + deed_weight->butthurt, 14, 0);
  107. if(!!dolphin_state->data.butthurt != !!new_butthurt) {
  108. mood_changed = true;
  109. }
  110. dolphin_state->data.butthurt = new_butthurt;
  111. dolphin_state->data.timestamp = dolphin_state_timestamp();
  112. dolphin_state->dirty = true;
  113. return level_up || mood_changed;
  114. }
  115. void dolphin_state_butthurted(DolphinState* dolphin_state) {
  116. dolphin_state->data.butthurt++;
  117. dolphin_state->data.timestamp = dolphin_state_timestamp();
  118. dolphin_state->dirty = true;
  119. }
  120. void dolphin_state_increase_level(DolphinState* dolphin_state) {
  121. ++dolphin_state->data.icounter;
  122. dolphin_state->dirty = true;
  123. }