Skip to content

Commit adb461d

Browse files
committed
bring in all the code
1 parent 498f992 commit adb461d

32 files changed

+3620
-0
lines changed

advent_of_code.c

Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
#include "advent_of_code.h"
2+
#include "solvers.h"
3+
4+
void update_results(AdventOfCode* aoc, FuriString* part_1, FuriString* part_2) {
5+
furi_check(furi_mutex_acquire(aoc->model_mutex, FuriWaitForever) == FuriStatusOk);
6+
if(part_1) {
7+
furi_string_set(aoc->model->part_1, part_1);
8+
if(aoc->model->img_1->data) {
9+
free(aoc->model->img_1->data);
10+
aoc->model->img_1->data = NULL;
11+
}
12+
}
13+
if(part_2) {
14+
furi_string_set(aoc->model->part_2, part_2);
15+
if(aoc->model->img_2->data) {
16+
free(aoc->model->img_2->data);
17+
aoc->model->img_2->data = NULL;
18+
}
19+
}
20+
furi_mutex_release(aoc->model_mutex);
21+
view_port_update(aoc->view_port);
22+
};
23+
24+
void update_images(AdventOfCode* aoc, Image* img_1, Image* img_2) {
25+
furi_check(furi_mutex_acquire(aoc->model_mutex, FuriWaitForever) == FuriStatusOk);
26+
27+
if(img_1) {
28+
if(aoc->model->img_1->data) free(aoc->model->img_1->data);
29+
30+
aoc->model->img_1->width = img_1->width;
31+
aoc->model->img_1->height = img_1->height;
32+
33+
size_t size = (size_t)img_1->width * (size_t)img_1->height;
34+
if(img_1->width % 8 > 0) size += img_1->height;
35+
36+
aoc->model->img_1->data = malloc(size);
37+
memcpy(aoc->model->img_1->data, img_1->data, size);
38+
}
39+
40+
if(img_2) {
41+
if(aoc->model->img_2->data) free(aoc->model->img_2->data);
42+
43+
aoc->model->img_2->width = img_2->width;
44+
aoc->model->img_2->height = img_2->height;
45+
46+
size_t size = (size_t)img_2->width * (size_t)img_2->height;
47+
if(img_2->width % 8 > 0) size += img_2->height;
48+
49+
aoc->model->img_2->data = malloc(size);
50+
memcpy(aoc->model->img_2->data, img_2->data, size);
51+
}
52+
53+
furi_mutex_release(aoc->model_mutex);
54+
view_port_update(aoc->view_port);
55+
};
56+
57+
void unimplemented(AdventOfCode* aoc, Stream* file_stream) {
58+
UNUSED(file_stream);
59+
FuriString* str = furi_string_alloc_set("unimplemented");
60+
update_results(aoc, str, str);
61+
furi_string_free(str);
62+
}
63+
64+
static void render_callback(Canvas* canvas, void* ctx) {
65+
FURI_LOG_D(TAG, "Render callback");
66+
67+
AdventOfCode* aoc = ctx;
68+
furi_check(furi_mutex_acquire(aoc->model_mutex, FuriWaitForever) == FuriStatusOk);
69+
int day = aoc->model->day;
70+
FuriString* part_1 = furi_string_alloc_set(aoc->model->part_1);
71+
FuriString* part_2 = furi_string_alloc_set(aoc->model->part_2);
72+
Image* img_1 = aoc->model->img_1;
73+
Image* img_2 = aoc->model->img_2;
74+
furi_mutex_release(aoc->model_mutex);
75+
76+
canvas_clear(canvas);
77+
canvas_set_color(canvas, ColorBlack);
78+
canvas_set_font(canvas, FontPrimary);
79+
canvas_draw_str(canvas, 0, 12, "Advent of Code 2022");
80+
81+
char tmp_str[24];
82+
snprintf(tmp_str, 24, " * Day %d *", day);
83+
canvas_draw_str(canvas, 0, 24, tmp_str);
84+
85+
canvas_set_font(canvas, FontSecondary);
86+
87+
if(img_1->data) {
88+
canvas_draw_bitmap(canvas, 32, 36, img_1->width, img_1->height, img_1->data);
89+
furi_string_set(part_1, "");
90+
} else if(furi_string_size(part_1) == 0) {
91+
furi_string_set(part_1, "calculating...");
92+
}
93+
94+
if(img_2->data) {
95+
canvas_draw_bitmap(canvas, 32, 48, img_2->width, img_2->height, img_2->data);
96+
furi_string_set(part_2, "");
97+
} else if(furi_string_size(part_2) == 0) {
98+
furi_string_set(part_2, "calculating...");
99+
}
100+
101+
snprintf(tmp_str, 24, "Part 1: %s", furi_string_get_cstr(part_1));
102+
canvas_draw_str(canvas, 0, 42, tmp_str);
103+
if(day == 25)
104+
snprintf(tmp_str, 24, "(cont.) %s", furi_string_get_cstr(part_2));
105+
else
106+
snprintf(tmp_str, 24, "Part 2: %s", furi_string_get_cstr(part_2));
107+
canvas_draw_str(canvas, 0, 54, tmp_str);
108+
109+
furi_string_free(part_2);
110+
furi_string_free(part_1);
111+
}
112+
113+
static void input_callback(InputEvent* input_event, void* ctx) {
114+
FURI_LOG_D(TAG, "Input callback");
115+
116+
AdventOfCode* aoc = ctx;
117+
if(input_event->type == InputTypeShort) {
118+
furi_message_queue_put(aoc->input_queue, input_event, 0);
119+
}
120+
}
121+
122+
void advent_of_code_reset_day(AdventOfCode* aoc, int day) {
123+
furi_check(furi_mutex_acquire(aoc->model_mutex, FuriWaitForever) == FuriStatusOk);
124+
aoc->model->day = day;
125+
furi_string_reset(aoc->model->part_1);
126+
if(aoc->model->img_1->data) {
127+
free(aoc->model->img_1->data);
128+
aoc->model->img_1->data = NULL;
129+
}
130+
furi_string_reset(aoc->model->part_2);
131+
if(aoc->model->img_2->data) {
132+
free(aoc->model->img_2->data);
133+
aoc->model->img_2->data = NULL;
134+
}
135+
furi_mutex_release(aoc->model_mutex);
136+
view_port_update(aoc->view_port);
137+
}
138+
139+
AdventOfCode* advent_of_code_alloc() {
140+
AdventOfCode* aoc = malloc(sizeof(AdventOfCode));
141+
142+
AdventOfCodeModel* model = malloc(sizeof(AdventOfCodeModel));
143+
model->day = 0;
144+
model->part_1 = furi_string_alloc();
145+
model->part_2 = furi_string_alloc();
146+
147+
Image* img_1 = malloc(sizeof(Image));
148+
img_1->width = 0;
149+
img_1->height = 0;
150+
img_1->data = NULL;
151+
Image* img_2 = malloc(sizeof(Image));
152+
img_2->width = 0;
153+
img_2->height = 0;
154+
img_2->data = NULL;
155+
156+
model->img_1 = img_1;
157+
model->img_2 = img_2;
158+
159+
aoc->model = model;
160+
161+
aoc->model_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
162+
163+
aoc->input_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
164+
165+
aoc->view_port = view_port_alloc();
166+
view_port_draw_callback_set(aoc->view_port, render_callback, aoc);
167+
view_port_input_callback_set(aoc->view_port, input_callback, aoc);
168+
169+
// Open GUI and register view_port
170+
aoc->gui = furi_record_open(RECORD_GUI);
171+
gui_add_view_port(aoc->gui, aoc->view_port, GuiLayerFullscreen);
172+
173+
return aoc;
174+
}
175+
176+
void advent_of_code_free(AdventOfCode* aoc) {
177+
FURI_LOG_D(TAG, "Freeing");
178+
179+
gui_remove_view_port(aoc->gui, aoc->view_port);
180+
furi_record_close(RECORD_GUI);
181+
view_port_free(aoc->view_port);
182+
183+
furi_message_queue_free(aoc->input_queue);
184+
185+
furi_mutex_free(aoc->model_mutex);
186+
187+
if(aoc->model->img_2->data) free(aoc->model->img_2->data);
188+
free(aoc->model->img_2);
189+
if(aoc->model->img_1->data) free(aoc->model->img_1->data);
190+
free(aoc->model->img_1);
191+
192+
furi_string_free(aoc->model->part_2);
193+
furi_string_free(aoc->model->part_1);
194+
free(aoc->model);
195+
free(aoc);
196+
197+
FURI_LOG_D(TAG, "Free at last");
198+
}
199+
200+
int32_t advent_of_code_2022_app(void* p) {
201+
FURI_LOG_D(TAG, "Starting");
202+
203+
AdventOfCode* aoc = advent_of_code_alloc();
204+
205+
FURI_LOG_D(TAG, "Allocated");
206+
207+
FuriString* file_path;
208+
file_path = furi_string_alloc();
209+
FuriString* file_name;
210+
file_name = furi_string_alloc();
211+
212+
do {
213+
FURI_LOG_D(TAG, "Checking file path");
214+
if(p && strlen(p)) {
215+
FURI_LOG_D(TAG, "File path set");
216+
furi_string_set(file_path, (const char*)p);
217+
} else {
218+
furi_string_set(file_path, ADVENT_OF_CODE_APP_BASE_PATH);
219+
220+
FURI_LOG_D(TAG, "Opening file browser");
221+
222+
DialogsFileBrowserOptions browser_options;
223+
dialog_file_browser_set_basic_options(
224+
&browser_options, ADVENT_OF_CODE_APP_EXTENSION, &I_txt_10px);
225+
browser_options.base_path = ADVENT_OF_CODE_APP_BASE_PATH;
226+
browser_options.hide_ext = false;
227+
228+
DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
229+
bool res = dialog_file_browser_show(dialogs, file_path, file_path, &browser_options);
230+
231+
furi_record_close(RECORD_DIALOGS);
232+
if(!res) {
233+
FURI_LOG_E(TAG, "No file selected");
234+
break;
235+
}
236+
}
237+
238+
path_extract_filename(file_path, file_name, true);
239+
FURI_LOG_D(
240+
TAG,
241+
"Selected file \'%s\' (%s)",
242+
furi_string_get_cstr(file_path),
243+
furi_string_get_cstr(file_name));
244+
245+
Storage* storage = furi_record_open(RECORD_STORAGE);
246+
Stream* file_stream = buffered_file_stream_alloc(storage);
247+
furi_record_close(RECORD_STORAGE);
248+
249+
int day = atoi(furi_string_get_cstr(file_name));
250+
251+
if(day < 1 || day > 25) {
252+
FURI_LOG_E(TAG, "Not a valid day: %d", day);
253+
continue;
254+
}
255+
256+
advent_of_code_reset_day(aoc, day);
257+
258+
if(!buffered_file_stream_open(
259+
file_stream, furi_string_get_cstr(file_path), FSAM_READ, FSOM_OPEN_EXISTING)) {
260+
FURI_LOG_E(TAG, "Unable to open file");
261+
} else {
262+
solvers[day - 1](aoc, file_stream);
263+
}
264+
265+
buffered_file_stream_close(file_stream);
266+
stream_free(file_stream);
267+
268+
InputEvent input;
269+
while(furi_message_queue_get(aoc->input_queue, &input, FuriWaitForever) == FuriStatusOk) {
270+
if(input.key == InputKeyBack) {
271+
break;
272+
}
273+
}
274+
} while(1);
275+
276+
furi_string_free(file_path);
277+
advent_of_code_free(aoc);
278+
279+
return 0;
280+
}

advent_of_code.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#pragma once
2+
3+
#include <dialogs/dialogs.h>
4+
#include <gui/gui.h>
5+
#include <lib/toolbox/stream/buffered_file_stream.h>
6+
#include <lib/toolbox/path.h>
7+
8+
#include "m-array.h"
9+
#include "m-bitset.h"
10+
#include "m-dict.h"
11+
12+
#include <advent_of_code_2022_icons.h>
13+
14+
#define TAG "AdventOfCode2022"
15+
16+
#define ADVENT_OF_CODE_APP_BASE_PATH EXT_PATH("advent/2022")
17+
#define ADVENT_OF_CODE_APP_EXTENSION ".txt"
18+
19+
// used more than once
20+
ARRAY_DEF(array_int, int)
21+
ARRAY_DEF(array_string, FuriString*, FURI_STRING_OPLIST)
22+
DICT_DEF2(dict_string_int, FuriString*, FURI_STRING_OPLIST, int, M_DEFAULT_OPLIST)
23+
24+
typedef struct {
25+
uint8_t width;
26+
uint8_t height;
27+
uint8_t* data;
28+
} Image;
29+
30+
typedef struct {
31+
int day;
32+
33+
FuriString* part_1;
34+
FuriString* part_2;
35+
36+
Image* img_1;
37+
Image* img_2;
38+
} AdventOfCodeModel;
39+
40+
typedef struct {
41+
AdventOfCodeModel* model;
42+
FuriMutex** model_mutex;
43+
44+
FuriMessageQueue* input_queue;
45+
46+
ViewPort* view_port;
47+
Gui* gui;
48+
} AdventOfCode;
49+
50+
typedef void (*AdventSolver)(AdventOfCode* aoc, Stream* file_stream);
51+
52+
void update_results(AdventOfCode* aoc, FuriString* part_1, FuriString* part_2);
53+
void update_images(AdventOfCode* aoc, Image* img_1, Image* img_2);

application.fam

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
App(
2+
appid="advent_of_code_2022",
3+
name="Advent of Code 2022",
4+
apptype=FlipperAppType.PLUGIN,
5+
entry_point="advent_of_code_2022_app",
6+
cdefines=["APP_ADVENT_OF_CODE_2022"],
7+
requires=[
8+
"storage",
9+
"gui",
10+
],
11+
stack_size=4 * 1024,
12+
order=30,
13+
fap_icon_assets="icons",
14+
fap_icon="icons/aoc_10px.png",
15+
fap_category="Games",
16+
)

0 commit comments

Comments
 (0)