dolphin_state.c 3.5 KB

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