Skip to content

Commit 94bbf8b

Browse files
authored
Merge pull request #6 from jaylikesbunda/dev
new features added by @jaylikesbunda - added persistent counter for darts smoked with InputKeyUp - added progress to cancer counter - saves data in ext/apps_data/cigarette/stats.txt - red notif led on 'light up' - switch style - skinny cigarette - able to puff extra time once cig runs out which triggers a 'cough' vibration and led Thanks a ton <3
2 parents 6b1e4b2 + 558a3bb commit 94bbf8b

15 files changed

+175
-69
lines changed

flipper_cigarette.c

+175-69
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
#include <assets_icons.h>
1414
#include <gui/elements.h>
1515

16+
#include <storage/storage.h>
17+
#include <toolbox/stream/stream.h>
18+
#include <toolbox/stream/file_stream.h>
19+
#include <flipper_format/flipper_format.h>
1620

1721
/* Magic happens here -- this file is generated by fbt.
1822
* Just set fap_icon_assets in application.fam and #include {APPID}_icons.h */
@@ -29,7 +33,11 @@ static ImagePosition smoke_position = {.x = 0, .y = 0};
2933
typedef struct {
3034
int32_t counter, maxdrags;
3135
bool lit, done;
36+
uint8_t style; // 0 = regular, 1 = skinny
3237
IconAnimation* icon;
38+
NotificationApp* notification;
39+
uint32_t smoke_end; // Tracks when to stop smoke
40+
bool cough_used; // NEW - tracks if cough was used
3341
} Cigarette;
3442

3543
static Cigarette cigarette = {.counter = 0, .maxdrags = 13, .lit = false, .done = false};
@@ -39,112 +47,153 @@ const NotificationMessage message_delay_15 = {
3947
.data.delay.length = 15,
4048
};
4149

42-
static const NotificationSequence vibr1 = {
43-
&message_note_ds4,
44-
&message_delay_15,
45-
&message_sound_off,
46-
47-
&message_note_a5,
48-
&message_delay_15,
49-
&message_sound_off,
50-
50+
static const NotificationSequence sequence_puff = {
5151
&message_vibro_on,
52-
&message_delay_25,
52+
&message_delay_50,
5353
&message_vibro_off,
54-
5554
NULL,
5655
};
5756

58-
// Light up
59-
static const NotificationSequence vibr2 = {
60-
&message_note_ds2,
61-
&message_delay_25,
62-
&message_sound_off,
63-
57+
static const NotificationSequence sequence_light_up = {
58+
&message_red_255,
59+
&message_vibro_on,
60+
&message_delay_100,
61+
&message_vibro_off,
62+
&message_red_0,
63+
NULL,
64+
};
65+
static const NotificationSequence sequence_cough = {
66+
&message_red_255,
6467
&message_vibro_on,
65-
&message_delay_15,
68+
&message_delay_100,
6669
&message_vibro_off,
70+
&message_red_0,
71+
&message_delay_50,
72+
&message_delay_50,
73+
&message_delay_50,
74+
&message_delay_50,
75+
&message_vibro_on,
76+
&message_delay_50,
77+
&message_vibro_off,
78+
&message_delay_50,
79+
&message_delay_50,
80+
&message_red_255,
81+
&message_delay_25,
82+
&message_red_0,
6783

6884
NULL,
6985
};
7086

87+
typedef struct {
88+
uint32_t total_smokes;
89+
bool visible;
90+
Storage* storage;
91+
} StatsView;
92+
93+
static StatsView stats_view = {.total_smokes = 0, .visible = false};
94+
7195
static void app_draw_callback(Canvas* canvas, void* ctx) {
7296
UNUSED(ctx);
73-
7497
canvas_clear(canvas);
7598

99+
if(stats_view.visible) {
100+
char buffer[64];
101+
// 1 cig in app = 15 IRL cigs (one pack)
102+
// 14.7% cancer risk after 20 years of 15/day
103+
float cancer_pct = (stats_view.total_smokes * 15.0f) / (15 * 365 * 20) * 14.7f;
104+
if(cancer_pct > 100.0f)
105+
cancer_pct = 100.0f;
106+
107+
snprintf(buffer, sizeof(buffer), "darts smoked: %lu", stats_view.total_smokes);
108+
canvas_draw_str_aligned(canvas, 64, 27, AlignCenter, AlignCenter, buffer);
109+
110+
if(cancer_pct >= 100.0f) {
111+
canvas_draw_str_aligned(canvas, 64, 34, AlignCenter, AlignCenter, "YOU DIED OF CANCER");
112+
canvas_draw_str_aligned(canvas, 64, 44, AlignCenter, AlignCenter, "RIP BOZO");
113+
} else {
114+
snprintf(buffer, sizeof(buffer), "progress to cancer: %.1f%%", (double)cancer_pct);
115+
canvas_draw_str_aligned(canvas, 64, 40, AlignCenter, AlignCenter, buffer);
116+
117+
if(cancer_pct >= 50.0f && cancer_pct < 100.0f) {
118+
canvas_draw_str_aligned(canvas, 64, 44, AlignCenter, AlignCenter, "SEEK HELP IMMEDIATELY");
119+
}
120+
}
121+
122+
elements_button_down(canvas, "back");
123+
return;
124+
}
76125

77-
if (cigarette.lit == true && cigarette.done == false){
126+
// Draw smoke only when smoke_end is active
127+
if (cigarette.smoke_end) {
128+
canvas_draw_icon_animation(canvas, smoke_position.x, smoke_position.y, cigarette.icon);
129+
} else if (cigarette.lit && !cigarette.done) {
78130
elements_button_right(canvas, "puff");
79131
canvas_draw_icon_animation(canvas, smoke_position.x, smoke_position.y, cigarette.icon);
80132
}
81133

82-
if (cigarette.lit == false && cigarette.done == false)
134+
if (cigarette.lit == false && cigarette.done == false) {
83135
elements_button_center(canvas, "light up");
136+
canvas_draw_str_aligned(canvas, 64, 15, AlignCenter, AlignCenter, "< switch style >");
137+
}
84138

85-
if (cigarette.done == true){
86-
elements_button_left(canvas, "another one");
87-
139+
if (cigarette.done == true) {
140+
elements_button_left(canvas, "another one");
88141
}
89142

90143
// TODO: open about-view
91144
//elements_button_down(canvas, "about");
92145

93-
94-
95-
// Cigarette
146+
// Cigarette icon selection based on style
147+
const Icon* current_icon = NULL;
96148
switch(cigarette.counter) {
97149
case 0:
98-
canvas_draw_icon(canvas, image_position.x, image_position.y, &I_cigarette0_115x25);
150+
current_icon = (cigarette.style == 0) ? &I_cigarette0_115x25 : &I_skinny0_112x20;
99151
break;
100152
case 1:
101-
canvas_draw_icon(canvas, image_position.x, image_position.y, &I_cigarette1_115x25);
153+
current_icon = (cigarette.style == 0) ? &I_cigarette1_115x25 : &I_skinny1_112x20;
102154
break;
103155
case 2:
104-
canvas_draw_icon(canvas, image_position.x, image_position.y, &I_cigarette2_115x25);
156+
current_icon = (cigarette.style == 0) ? &I_cigarette2_115x25 : &I_skinny2_112x20;
105157
break;
106158
case 3:
107-
canvas_draw_icon(canvas, image_position.x, image_position.y, &I_cigarette3_115x25);
159+
current_icon = (cigarette.style == 0) ? &I_cigarette3_115x25 : &I_skinny3_112x20;
108160
break;
109161
case 4:
110-
canvas_draw_icon(canvas, image_position.x, image_position.y, &I_cigarette4_115x25);
162+
current_icon = (cigarette.style == 0) ? &I_cigarette4_115x25 : &I_skinny4_112x20;
111163
break;
112164
case 5:
113-
canvas_draw_icon(canvas, image_position.x, image_position.y, &I_cigarette5_115x25);
165+
current_icon = (cigarette.style == 0) ? &I_cigarette5_115x25 : &I_skinny5_112x20;
114166
break;
115167
case 6:
116-
canvas_draw_icon(canvas, image_position.x, image_position.y, &I_cigarette6_115x25);
168+
current_icon = (cigarette.style == 0) ? &I_cigarette6_115x25 : &I_skinny6_112x20;
117169
break;
118170
case 7:
119-
canvas_draw_icon(canvas, image_position.x, image_position.y, &I_cigarette7_115x25);
171+
current_icon = (cigarette.style == 0) ? &I_cigarette7_115x25 : &I_skinny7_112x20;
120172
break;
121173
case 8:
122-
canvas_draw_icon(canvas, image_position.x, image_position.y, &I_cigarette8_115x25);
174+
current_icon = (cigarette.style == 0) ? &I_cigarette8_115x25 : &I_skinny8_112x20;
123175
break;
124176
case 9:
125-
canvas_draw_icon(canvas, image_position.x, image_position.y, &I_cigarette9_115x25);
177+
current_icon = (cigarette.style == 0) ? &I_cigarette9_115x25 : &I_skinny9_112x20;
126178
break;
127179
case 10:
128-
canvas_draw_icon(canvas, image_position.x, image_position.y, &I_cigarette10_115x25);
180+
current_icon = (cigarette.style == 0) ? &I_cigarette10_115x25 : &I_skinny10_112x20;
129181
break;
130182
case 11:
131-
canvas_draw_icon(canvas, image_position.x, image_position.y, &I_cigarette11_115x25);
183+
current_icon = (cigarette.style == 0) ? &I_cigarette11_115x25 : &I_skinny11_112x20;
132184
break;
133185
case 12:
134-
canvas_draw_icon(canvas, image_position.x, image_position.y, &I_cigarette12_115x25);
186+
current_icon = (cigarette.style == 0) ? &I_cigarette12_115x25 : &I_skinny12_112x20;
135187
break;
136188
case 13:
137-
canvas_draw_icon(canvas, image_position.x, image_position.y, &I_cigarette13_115x25);
189+
current_icon = (cigarette.style == 0) ? &I_cigarette13_115x25 : &I_skinny13_112x20;
138190
cigarette.done = true;
139191
break;
140192
default:
141-
canvas_draw_icon(canvas, image_position.x, image_position.y, &I_cigarette0_115x25);
193+
current_icon = (cigarette.style == 0) ? &I_cigarette13_115x25 : &I_skinny13_112x20;
142194
break;
143-
144195
}
145-
146-
147-
196+
canvas_draw_icon(canvas, image_position.x, image_position.y, current_icon);
148197
}
149198

150199
static void app_input_callback(InputEvent* input_event, void* ctx) {
@@ -169,49 +218,96 @@ int32_t cigarette_main(void* p) {
169218
Gui* gui = furi_record_open(RECORD_GUI);
170219
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
171220

172-
NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
221+
cigarette.notification = furi_record_open(RECORD_NOTIFICATION);
222+
223+
stats_view.storage = furi_record_open(RECORD_STORAGE);
224+
225+
// Load stats
226+
FlipperFormat* ff_load = flipper_format_file_alloc(stats_view.storage);
227+
storage_common_mkdir(stats_view.storage, "/ext/apps_data/cigarette");
228+
if(flipper_format_file_open_existing(ff_load, "/ext/apps_data/cigarette/stats.txt")) {
229+
flipper_format_read_uint32(ff_load, "total", &stats_view.total_smokes, 1);
230+
}
231+
flipper_format_free(ff_load);
173232

174233
InputEvent event;
175234

176235
bool running = true;
177236
while(running) {
237+
// Check if smoke needs to stop
238+
if(cigarette.smoke_end && furi_get_tick() >= cigarette.smoke_end) {
239+
icon_animation_stop(cigarette.icon);
240+
cigarette.smoke_end = 0;
241+
}
242+
178243
if(furi_message_queue_get(event_queue, &event, 100) == FuriStatusOk) {
179244
if((event.type == InputTypePress) || (event.type == InputTypeRepeat)) {
180245
switch(event.key) {
181246
case InputKeyLeft:
182-
cigarette.counter = 0;
183-
cigarette.lit = 0;
184-
cigarette.done = false;
185-
smoke_position.x = 0;
186-
image_position.x = 12;
187-
icon_animation_stop(cigarette.icon);
247+
if(!stats_view.visible && !cigarette.lit && !cigarette.done) {
248+
// Cycle through styles
249+
cigarette.style = (cigarette.style - 1 + 2) % 2;
250+
} else if(cigarette.done) {
251+
// Reset positions when getting new cig
252+
stats_view.total_smokes++;
253+
cigarette.counter = 0;
254+
cigarette.lit = false;
255+
cigarette.done = false;
256+
cigarette.cough_used = false; // RESET FLAG
257+
smoke_position.x = 0; // Reset smoke position
258+
image_position.x = 12; // Reset cig position
259+
icon_animation_stop(cigarette.icon);
260+
}
188261
break;
189262
case InputKeyRight:
190-
if (cigarette.counter < cigarette.maxdrags && cigarette.lit == true){
191-
cigarette.counter += 1;
192-
smoke_position.x += 5;
193-
image_position.x += 5;
194-
notification_message(notification, &vibr2);
263+
if(!stats_view.visible && !cigarette.lit && !cigarette.done) {
264+
cigarette.style = (cigarette.style + 1) % 2;
265+
} else if (cigarette.lit) {
266+
if(!cigarette.done) {
267+
cigarette.counter++;
268+
if(cigarette.counter > cigarette.maxdrags) {
269+
// Secret cough with 1s smoke
270+
icon_animation_start(cigarette.icon);
271+
cigarette.smoke_end = furi_get_tick() + 1000;
272+
notification_message(cigarette.notification, &sequence_cough);
273+
cigarette.counter = cigarette.maxdrags;
274+
} else {
275+
if(cigarette.counter == cigarette.maxdrags) {
276+
cigarette.done = true;
277+
}
278+
notification_message(cigarette.notification, &sequence_puff);
279+
smoke_position.x += 5;
280+
image_position.x += 5;
281+
}
282+
} else {
283+
if(!cigarette.cough_used) { // CHECK FLAG
284+
// Cough puff with reset smoke position
285+
smoke_position.x = image_position.x -3; // Start from cig tip
286+
icon_animation_start(cigarette.icon);
287+
cigarette.smoke_end = furi_get_tick() + 1000;
288+
notification_message(cigarette.notification, &sequence_cough);
289+
cigarette.cough_used = true; // SET FLAG
290+
}
291+
}
195292
}
196293
break;
197294
case InputKeyUp:
198-
// image_position.y -= 2;
295+
if(event.type == InputTypePress) {
296+
stats_view.visible = !stats_view.visible;
297+
}
199298
break;
200299
case InputKeyDown:
201-
// image_position.y += 2;
300+
if(stats_view.visible) {
301+
stats_view.visible = false;
302+
}
202303
break;
203304
case InputKeyOk:
204-
// Light Cigarette - play lighter animation
205-
if (cigarette.counter == 0){
206-
if (cigarette.lit == false){
207-
cigarette.lit = true;
208-
notification_message(notification, &vibr1);
209-
210-
}
305+
if (cigarette.counter == 0 && !cigarette.lit) {
306+
cigarette.lit = true;
307+
notification_message(cigarette.notification, &sequence_light_up);
211308
icon_animation_start(cigarette.icon);
309+
notification_message(cigarette.notification, &sequence_blink_red_10);
212310
}
213-
214-
215311
break;
216312
default:
217313
running = false;
@@ -223,6 +319,16 @@ int32_t cigarette_main(void* p) {
223319
}
224320

225321
view_port_enabled_set(view_port, false);
322+
323+
// Save stats before exit
324+
FlipperFormat* ff_save = flipper_format_file_alloc(stats_view.storage);
325+
if(flipper_format_file_open_always(ff_save, "/ext/apps_data/cigarette/stats.txt")) {
326+
flipper_format_write_header_cstr(ff_save, "CigaretteStats", 1);
327+
flipper_format_write_uint32(ff_save, "total", &stats_view.total_smokes, 1);
328+
}
329+
flipper_format_free(ff_save);
330+
furi_record_close(RECORD_STORAGE);
331+
226332
gui_remove_view_port(gui, view_port);
227333
view_port_free(view_port);
228334
furi_message_queue_free(event_queue);

images/skinny/skinny0_112x20.png

300 Bytes
Loading

images/skinny/skinny10_112x20.png

289 Bytes
Loading

images/skinny/skinny11_112x20.png

288 Bytes
Loading

images/skinny/skinny12_112x20.png

281 Bytes
Loading

images/skinny/skinny13_112x20.png

277 Bytes
Loading

images/skinny/skinny1_112x20.png

310 Bytes
Loading

images/skinny/skinny2_112x20.png

308 Bytes
Loading

images/skinny/skinny3_112x20.png

306 Bytes
Loading

images/skinny/skinny4_112x20.png

306 Bytes
Loading

images/skinny/skinny5_112x20.png

303 Bytes
Loading

images/skinny/skinny6_112x20.png

298 Bytes
Loading

images/skinny/skinny7_112x20.png

295 Bytes
Loading

images/skinny/skinny8_112x20.png

293 Bytes
Loading

images/skinny/skinny9_112x20.png

291 Bytes
Loading

0 commit comments

Comments
 (0)