{
"id": "152",
"prompt": "An adjustable metronome that keeps its own clock in state slots (a phase counter and a beat index 0..3, since locals reset every frame): whenever phase reaches the period, beat 1 plays an accented 1320 Hz square and beats 2-4 a shorter 880 Hz tick. SLOW and FAST buttons change the period by 5 frames per edge-detected tap (clamped 10..90); show the live BPM (3600 / period) and four beat lamps with the accent lamp in red.",
"solution_rl": "fn frame(t: i32) {\n let mut period: i32 = host::display::state_get(0);\n if period == 0 { period = 30; }\n let down: i32 = host::display::pointer_down();\n let prev: i32 = host::display::state_get(1);\n if down == 1 && prev == 0 {\n let px: i32 = host::display::pointer_x();\n let py: i32 = host::display::pointer_y();\n if py >= 400 && py < 460 {\n if px >= 60 && px < 160 { period = period + 5; }\n if px >= 290 && px < 390 { period = period - 5; }\n }\n }\n if period < 10 { period = 10; }\n if period > 90 { period = 90; }\n host::display::state_set(0, period);\n host::display::state_set(1, down);\n let mut phase: i32 = host::display::state_get(2) + 1;\n let mut beat: i32 = host::display::state_get(3);\n if phase >= period {\n phase = 0;\n beat = (beat + 1) % 4;\n if beat == 0 {\n host::audio::tone(1320, 50, 1);\n } else {\n host::audio::tone(880, 35, 1);\n }\n }\n host::display::state_set(2, phase);\n host::display::state_set(3, beat);\n host::display::clear(0x101014);\n host::display::draw_string(60, 40, \"BPM\", 0x808080, 2);\n host::display::draw_number(130, 40, 3600 / period, 0xffffff, 3);\n let mut i: i32 = 0;\n while i < 4 {\n let mut c: i32 = 0x282830;\n if i == beat {\n if i == 0 { c = 0xff5040; } else { c = 0xffff40; }\n }\n host::display::fill_rect(60 + i * 90, 150, 60, 60, c);\n i = i + 1;\n }\n host::display::fill_rect(60, 400, 100, 60, 0x203040);\n host::display::fill_rect(290, 400, 100, 60, 0x203040);\n host::display::draw_string(78, 420, \"SLOW\", 0xffffff, 2);\n host::display::draw_string(308, 420, \"FAST\", 0xffffff, 2);\n host::display::present();\n}\n",
"tags": [
"audio",
"state",
"pointer",
"ui"
]
}