From 9ad937b29992f38f6110a67070c6f376bf7b03fe Mon Sep 17 00:00:00 2001 From: Randall Winkhart Date: Fri, 24 Jul 2026 19:06:21 -0400 Subject: [PATCH] Initial code commit --- .clang-format | 7 +++ .gitignore | 5 +++ README.md | 20 ++++++++- clangd.zsh | 20 +++++++++ package.json | 41 +++++++++++++++++ resources-base/ATTRIBUTION.md | 8 ++++ resources-base/check.svg | 5 +++ resources-base/clock50x50.svg | 13 ++++++ resources-base/leaf.svg | 37 ++++++++++++++++ resources/check.png | Bin 0 -> 333 bytes resources/clock.png | Bin 0 -> 624 bytes resources/leaf~200w.png | Bin 0 -> 952 bytes resources/leaf~260w.png | Bin 0 -> 1214 bytes src/c/main.c | 80 ++++++++++++++++++++++++++++++++++ wscript | 54 +++++++++++++++++++++++ 15 files changed, 288 insertions(+), 2 deletions(-) create mode 100644 .clang-format create mode 100644 .gitignore create mode 100755 clangd.zsh create mode 100644 package.json create mode 100644 resources-base/ATTRIBUTION.md create mode 100644 resources-base/check.svg create mode 100644 resources-base/clock50x50.svg create mode 100644 resources-base/leaf.svg create mode 100644 resources/check.png create mode 100644 resources/clock.png create mode 100644 resources/leaf~200w.png create mode 100644 resources/leaf~260w.png create mode 100644 src/c/main.c create mode 100644 wscript diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..31aa732 --- /dev/null +++ b/.clang-format @@ -0,0 +1,7 @@ +--- +BasedOnStyle: LLVM +TabWidth: 4 +IndentWidth: 4 +UseTab: ForIndentation +ColumnLimit: 0 +... diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eaf2f4b --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/build +/.clangd +/.lock-waf* +/package-lock.json +/node_modules diff --git a/README.md b/README.md index 01f81a7..83b2979 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,19 @@ -# Stoner-Alarm +# Stoner Alarm +An alarm designed to reliably wake a snoozing stoner. Seize the day (or at least don't get fired)! -An alarm designed to reliably wake a snoozing stoner. \ No newline at end of file +## The Pitch +### Simple +The app only has one page. You can only set one alarm. There is no snooze, there is no weekly schedule, and there is no way to disable the alarm (you'll always have one set - every day- like it or not). +### Persistent +The alarm cannot be stopped until the drowsy stoner completes a thematically appropriate, touch-based game. Play well enough and quickly enough to prove you're awake and defuse the alarm. +#### "What if I just force-close the app in my sleep?" +Then it will schedule itself to re-open ASAP :) +### The Game +The alarm-defusing game requires you to serve some customers at a flower bar. There are three stages, with each stage having its own meter to fill before progressing to the next. +#### The Stages +1. Grind the flower + - Quickly move your finger in a circle to utilize the grinder +2. Fill the bowls + - Drag the ground flower into each bowl +3. Light the bowls + - Swipe in the prompted direction with good reaction time to use the lighter diff --git a/clangd.zsh b/clangd.zsh new file mode 100755 index 0000000..10a19d6 --- /dev/null +++ b/clangd.zsh @@ -0,0 +1,20 @@ +#!/usr/bin/env zsh +echo "CompileFlags: + Add: + [ + -DPBL_DISPLAY_WIDTH=200, + -DPBL_DISPLAY_HEIGHT=228, + -xc, + -nostdinc, + -DPBL_COLOR, + -DPBL_RECT, + -I${HOME}/.pebble-sdk/SDKs/current/sdk-core/pebble/emery/include, + -include$(pwd)/build/include/message_keys.auto.h, + -I$(pwd)/build/emery, + -include${HOME}/.pebble-sdk/SDKs/current/toolchain/arm-none-eabi/arm-none-eabi/include/stdint.h, + -include${HOME}/.pebble-sdk/SDKs/current/toolchain/arm-none-eabi/arm-none-eabi/include/stdlib.h, + -include${HOME}/.pebble-sdk/SDKs/current/toolchain/arm-none-eabi/arm-none-eabi/include/time.h, + -include${HOME}/.pebble-sdk/SDKs/current/toolchain/arm-none-eabi/arm-none-eabi/include/string.h, + -include${HOME}/.pebble-sdk/SDKs/current/toolchain/arm-none-eabi/lib/gcc/arm-none-eabi/14.2.1/include/stddef.h, + -include${HOME}/.pebble-sdk/SDKs/current/toolchain/arm-none-eabi/lib/gcc/arm-none-eabi/14.2.1/include/stdbool.h, + ]" > ./.clangd diff --git a/package.json b/package.json new file mode 100644 index 0000000..a99f112 --- /dev/null +++ b/package.json @@ -0,0 +1,41 @@ +{ + "name": "stoner-alarm", + "author": "RandyTheSilly", + "version": "1.0.0", + "keywords": ["alarm"], + "private": true, + "dependencies": {}, + "pebble": { + "displayName": "Stoner Alarm", + "uuid": "293cd38c-4e8c-46ae-a3dc-c789d7ce93ab", + "sdkVersion": "3", + "enableMultiJS": true, + "targetPlatforms": [ + "emery", + "gabbro" + ], + "watchapp": { + "watchface": false + }, + "messageKeys": [ + ], + "resources": { + "media": [ + { + "file": "leaf.png", + "memoryFormat": "Smallest", + "name": "LEAF", + "spaceOptimization": "storage", + "type": "bitmap" + }, + { + "file": "clock.png", + "memoryFormat": "Smallest", + "name": "CLOCK", + "spaceOptimization": "storage", + "type": "bitmap" + } + ] + } + } +} diff --git a/resources-base/ATTRIBUTION.md b/resources-base/ATTRIBUTION.md new file mode 100644 index 0000000..cb308d2 --- /dev/null +++ b/resources-base/ATTRIBUTION.md @@ -0,0 +1,8 @@ +# Leaf Icon +[marijuana leaf by Rachel Fredericks](https://thenounproject.com/icon/marijuana-leaf-6959339/) (CC BY 3.0) + +# Check Icon +[checkmark by Asmuh](https://thenounproject.com/icon/checkmark-2193586/) (CC BY 3.0) + +# Clock Icon +[pebble-dev/iconography](https://raw.githubusercontent.com/pebble-dev/iconography/refs/heads/master/pebbleos/Pebble_50x50_Alarm_clock.svg) diff --git a/resources-base/check.svg b/resources-base/check.svg new file mode 100644 index 0000000..d7f8b22 --- /dev/null +++ b/resources-base/check.svg @@ -0,0 +1,5 @@ +Created by Asmuhfrom the Noun Project \ No newline at end of file diff --git a/resources-base/clock50x50.svg b/resources-base/clock50x50.svg new file mode 100644 index 0000000..53e7e2b --- /dev/null +++ b/resources-base/clock50x50.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/resources-base/leaf.svg b/resources-base/leaf.svg new file mode 100644 index 0000000..6f17415 --- /dev/null +++ b/resources-base/leaf.svg @@ -0,0 +1,37 @@ + + + + + + diff --git a/resources/check.png b/resources/check.png new file mode 100644 index 0000000000000000000000000000000000000000..583fd76755885bb6a6562a68f1d0503d56640d9d GIT binary patch literal 333 zcmV-T0kZyyP)X1ONa4`Ud100003LNkl#gO@an+`U=7cwE=yKZ^Yw*2CX2F%PNB7l)8laxziP=uc7rb z>b1fQKZv6J3M^YQFwZaIaYBvY1JjXNZfFyjjkKQz&q!c8vd?Q4_(MDnsS=`C_bm3} zeXN(}vroAY#(wL{o~;YkXH|A76Kwp-5O1b#U?(ic4y8hTtd!~4wsj@c)XO7IFA-7= fpdn%u2+8mdil*aJd?F%400000NkvXXu0mjf`3aKC literal 0 HcmV?d00001 diff --git a/resources/clock.png b/resources/clock.png new file mode 100644 index 0000000000000000000000000000000000000000..ef0ec96eecd8caf23e5a9fcb38913a57baeefa06 GIT binary patch literal 624 zcmV-$0+0QPP)nVFfH^kT>?uUqDN5f@cv@?ONNGJ`6!jVg1)^wr(K$^7Qs2jzRzgPH$j z!b!mstf8Alk{>Lhn{_-9z7ND+MC7$>;x$BM?_{Qk=;kpInwZbRl9*4E2#?V{H8V9a z!1p5j!Vp#v!~8A64-Al)h`?j)OvFzj{K+t4h0LEKd_#X?o-`rZL_SkWeC|=t7Kcau zyp)N=gtqw1ilY)S}=BT*d^n8gWUIU;sxT@dXO5m_FPqjf`$-a>9H%NPkTV?fpo<`=M!?=kamM!pAxLDNsIoNOJ{1WBCo-et zS6Zy7Q4$f6`xwMrCJ-{j{l!QdVlER1k=9~lcB;|DWD+BY$gE;y3nKme#ZY4MI_)(2 z5ZPRSa3B4MY_9%bnld^tzEy}V!mOH(*t0{cBqaQte_0T-8jw)X{A-U;=>g%M@MGQu zP6{?7($75+d6Z#9W=L(p3`B-`G$29;m)OpeH6u^5olA72Z@3Js7;0MkgFw^(0000< KMNUMnLSTY0G8bL| literal 0 HcmV?d00001 diff --git a/resources/leaf~200w.png b/resources/leaf~200w.png new file mode 100644 index 0000000000000000000000000000000000000000..471d712c430fd0df4eae9e084157a3d8e78ba463 GIT binary patch literal 952 zcmV;p14sOcP)9j^#8IhLa6awAF1XkU~ehbWmkQ z0ndYIpdpbcpg=4Suwq^%D|+S?j6j+;3r$9{@}WDwtP>yNh`ow9#f`_GZU5)kJ{hOl zT0K@JYs#pdZb6rD6Pk;tJ3z}Vs6RmQ7Bn27^<=~W;#^e2_&=hlfSU6Wp@7<3(R?cE zA(qj4Hi`w*9ipXx?#l?^-O+G})-zGVA!6D^^)X^RH5#`pWeq%zMZ_^WZ@v6JJlt%- z=CU2tKK*`e$P{)@zu$UfmBVNX6RM@B52lbbRkYWI6Mqrvq7!e;FZ^3P2~9qRHM6GV z4C&w<4dvrtrLq7BGm3OlS0{*mv;8Rx4BgtB`3o^yZ1O?x5e{ z`>dBu_7+~5c600)EpV43%jBTb_fAOW&`aeN(CR-k^5a+10aEeXi$uP8;I*Qt2!71N zFP5VCvl>L!>LY;J5Fd6z@jXbWN99ZYj3)Z6bTGXlIYF{nk3=BN4(njQ($iD0D1F|f zvB8@~W!NW5(9UcDn&No7Bifs>Fy0~hU=Mv_N5R`@Cnz&JN9~;_k3zPZ_wWFgmTk7! z!!qDA4yRh_yJ50~qvFxJZ zisCL(Ml4!7OHmDpbwojr-F9j@G)#_FMTsqA3d2@_M{{-}S(nmvgF z*gt8xp*mQ11TNOuhiSGcy})449f7+Nd$2jZ_UH;(aBTsc_K@^Yy399TeG8>e2p6IW z3eK(B7tO87#$KFTCe}GdEPcJHnYZ)iZcST9#>}m3h-vHAlF1EQw?groT9?OqJBE^# a`|}@;Ufnza2?XW<0000mYOUWs<4RxLW+V95TFJKXn+k7LK5~6A)5uiBGlIl0Q?05 zARZy4AnXSTB?$f?fmVSzLNp3o6VQd|6a1dA`h^ltlpt(f;FPjJwh4Aoh+h^gIU$dL zsRsty1m{Gx347vJH~cK;RBOOKFkl}_zmo&L|0n(?uU5?OJc+I$(~M_0jM$FT&Q2=zk4CE;{>GMt!AT90qviX_rL`SW%T$@#@Rg6(z3NR$4?12A6stJx7fl!HS%L4&`Rhp@%G?dj|4pTkJ#ltbc;Ol z6k4e2OrSgcMGM)W4WSBxyw8f+R3%`8oXeWK(?ve}arzi7ZJJ=1fS{fSFu6b-0$q@p zDF)okxU}KET@Pl;#Nu*KphL?Ms*Zsn@`Q8^Xsieb0BDF5Q8|(&pc)`>tZNt>!Z=MP zvIs%D7z+Zza&1=qE!$O^=Lhiax~sk$fF!GtDs2upL+1sAH_MMt?KwD{{A z2werKC*w;nO%OMY%HOaH5R450fE3+-2`(Q3^p zSP4B#5GGWZTzl)qAQzQW351Ylg5?P4&))}&p^+u(b;+>^g1-m?EhgS}xVX4^xAwut zK$v(HujbZPj9tHp`7o9x`YuQx=06Eve%xT&d$ECuR~hI`7@aIdD};?}n~IfN_($u90_h-ZP&pI+U8$Zl(ej_f7HTiRvR|=|lnt(e7S~$2 zagg~87M!O|q&{g~>aHASOaS!9Id+bp+F;DA4Ytah4NQoZm7{ zCcw6=iD$nq`lf79uiPaI6&NGG{VFZ?(B!qrAs!xq<=Q2tF cLS^pt4@rt5(V6T=q5uE@07*qoM6N<$g2gf;p#T5? literal 0 HcmV?d00001 diff --git a/src/c/main.c b/src/c/main.c new file mode 100644 index 0000000..29c1a87 --- /dev/null +++ b/src/c/main.c @@ -0,0 +1,80 @@ +#include + +// layer-age +static Window *s_window; +static BitmapLayer *s_leaf_layer; +static Layer *s_top_bar_layer; +static Layer *s_bottom_bar_layer; + +// bitmaps +static GBitmap *s_leaf_bmp; + +// global vars +static GColor s_bar_color = GColorDarkGreen; + +// constants +static const uint8_t s_edge_bar_height = ((PBL_DISPLAY_HEIGHT / 7) * 2); + +static void game1_window_load() {} + +static void game1_window_unload() {} + +///////////////////////////////// + +static void rect_fill_layer_update_proc(Layer *layer, GContext *ctx) { + graphics_context_set_fill_color(ctx, s_bar_color); + graphics_fill_rect(ctx, layer_get_bounds(layer), 0, GCornerNone); +} + +static void setter_window_load() { + window_set_background_color(s_window, GColorMintGreen); + + // leaf + s_leaf_bmp = gbitmap_create_with_resource(RESOURCE_ID_LEAF); + s_leaf_layer = bitmap_layer_create(GRect(PBL_IF_ROUND_ELSE(0, -4), PBL_IF_ROUND_ELSE(0, 7), PBL_IF_ROUND_ELSE(PBL_DISPLAY_WIDTH, PBL_DISPLAY_WIDTH + 8), PBL_DISPLAY_HEIGHT)); + bitmap_layer_set_alignment(s_leaf_layer, GAlignCenter); + bitmap_layer_set_compositing_mode(s_leaf_layer, GCompOpSet); + bitmap_layer_set_bitmap(s_leaf_layer, s_leaf_bmp); + + // top&bottom bars + s_top_bar_layer = layer_create(GRect(0, 0, PBL_DISPLAY_WIDTH, s_edge_bar_height)); + layer_set_update_proc(s_top_bar_layer, rect_fill_layer_update_proc); + s_bottom_bar_layer = layer_create(GRect(0, PBL_DISPLAY_HEIGHT - s_edge_bar_height, PBL_DISPLAY_WIDTH, s_edge_bar_height)); + layer_set_update_proc(s_bottom_bar_layer, rect_fill_layer_update_proc); + + Layer *window_layer = window_get_root_layer(s_window); + layer_add_child(window_layer, bitmap_layer_get_layer(s_leaf_layer)); + layer_add_child(window_layer, s_top_bar_layer); + layer_add_child(window_layer, s_bottom_bar_layer); +} + +static void setter_window_unload() { + layer_destroy(s_bottom_bar_layer); + layer_destroy(s_top_bar_layer); + bitmap_layer_destroy(s_leaf_layer); + gbitmap_destroy(s_leaf_bmp); +} + +static void init() { + s_window = window_create(); + + switch (launch_reason()) { + case APP_LAUNCH_WAKEUP: + break; // TODO alarm game time! + default: + window_set_window_handlers( + s_window, + (WindowHandlers){.load = setter_window_load, .unload = setter_window_unload}); + window_stack_push(s_window, false); + }; +} + +static void deinit() { + window_destroy(s_window); +} + +int main(void) { + init(); + app_event_loop(); + deinit(); +} diff --git a/wscript b/wscript new file mode 100644 index 0000000..5238bc8 --- /dev/null +++ b/wscript @@ -0,0 +1,54 @@ +# +# This file is the default set of rules to compile a Pebble application. +# +# Feel free to customize this to your needs. +# +import os.path + +top = '.' +out = 'build' + + +def options(ctx): + ctx.load('pebble_sdk') + + +def configure(ctx): + """ + This method is used to configure your build. ctx.load(`pebble_sdk`) automatically configures + a build for each valid platform in `targetPlatforms`. Platform-specific configuration: add your + change after calling ctx.load('pebble_sdk') and make sure to set the correct environment first. + Universal configuration: add your change prior to calling ctx.load('pebble_sdk'). + """ + ctx.load('pebble_sdk') + + +def build(ctx): + ctx.load('pebble_sdk') + + build_worker = os.path.exists('worker_src') + binaries = [] + + cached_env = ctx.env + for platform in ctx.env.TARGET_PLATFORMS: + ctx.env = ctx.all_envs[platform] + ctx.set_group(ctx.env.PLATFORM_NAME) + app_elf = '{}/pebble-app.elf'.format(ctx.env.BUILD_DIR) + ctx.pbl_build(source=ctx.path.ant_glob('src/c/**/*.c'), target=app_elf, bin_type='app') + + if build_worker: + worker_elf = '{}/pebble-worker.elf'.format(ctx.env.BUILD_DIR) + binaries.append({'platform': platform, 'app_elf': app_elf, 'worker_elf': worker_elf}) + ctx.pbl_build(source=ctx.path.ant_glob('worker_src/c/**/*.c'), + target=worker_elf, + bin_type='worker') + else: + binaries.append({'platform': platform, 'app_elf': app_elf}) + ctx.env = cached_env + + ctx.set_group('bundle') + ctx.pbl_bundle(binaries=binaries, + js=ctx.path.ant_glob(['src/pkjs/**/*.js', + 'src/pkjs/**/*.json', + 'src/common/**/*.js']), + js_entry_file='src/pkjs/index.js')