Ensure no two sides are of the same length (makes selecting the answer really, really annoying lol)

This commit is contained in:
2026-08-13 23:20:37 -04:00
parent a3c6b40bed
commit db3294d89b
2 changed files with 16 additions and 11 deletions
+1 -1
View File
@@ -5,7 +5,7 @@ A habit-correcting alarm for heavy sleepers. Cannot be shut off until you solve
### 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 you solve for theta in a randomized right triangle. Even if you force-close the app, it will re-open itself until you complete the equation.
The alarm cannot be stopped until you solve for theta in a randomized right triangle. Even if you force-close the app, it will re-open itself until you complete the equation. After you successfully disarm the alarm, it will open again (silently, no vibrations) in 9 minutes (standard snooze time) to verify you are still awake by having you solve another triangle. Fail to notice and solve it within a minute? Vibrations will resume and another alarm will be scheduled for 9 minutes after this one is solved. The alarm is not fully disarmed until the second, "awareness" alarm is solved within a minute of it appearing.
## Why Trigonometry?
Because it requires the perfect amount of thought to activate your brain in the morning. If the app gave you a more typical math problem, you could just mindlessly punch it into a calculator. Trigonometry still requires a base amount of thought ("Do I need sine, cosine, or tangent?") before a calculator is of any use.
+15 -10
View File
@@ -45,21 +45,26 @@ RightTriangleLayer *right_triangle_layer_create(GRect frame, GColor color) {
tri->color = color;
// determine angles
tri->angle_A = 90; // right angle at apex
tri->angle_B = 5 + rand() % 81; // acute angle at left base vertex
tri->angle_C = 90 - tri->angle_B; // acute angle at right base vertex
tri->angle_A = 90; // right angle at apex
tri->theta_angle_is_left = rand() % 2;
// choose hypotenuse length randomly
uint16_t min_hyp = (frame.size.w < frame.size.h) ? frame.size.w / 2 : frame.size.h / 2;
uint16_t max_hyp = (frame.size.w < frame.size.h) ? frame.size.w : frame.size.h;
tri->side_a = min_hyp + (rand() % (max_hyp - min_hyp + 1));
// legs: side_b = hyp × sin(B), side_c = hyp × sin(C) = hyp × cos(B)
int32_t sin_B = sin_lookup(((int32_t)tri->angle_B * TRIG_MAX_ANGLE) / 360);
int32_t sin_C = sin_lookup(((int32_t)tri->angle_C * TRIG_MAX_ANGLE) / 360);
tri->side_b = (uint16_t)(((uint32_t)sin_B * tri->side_a) / TRIG_MAX_RATIO);
tri->side_c = (uint16_t)(((uint32_t)sin_C * tri->side_a) / TRIG_MAX_RATIO);
// regenerate until no two sides share a length
do {
tri->angle_B = 5 + rand() % 81; // acute angle at left base vertex
tri->angle_C = 90 - tri->angle_B; // acute angle at right base vertex
// choose hypotenuse length randomly
tri->side_a = min_hyp + (rand() % (max_hyp - min_hyp + 1));
// legs: side_b = hyp × sin(B), side_c = hyp × sin(C) = hyp × cos(B)
int32_t sin_B = sin_lookup(((int32_t)tri->angle_B * TRIG_MAX_ANGLE) / 360);
int32_t sin_C = sin_lookup(((int32_t)tri->angle_C * TRIG_MAX_ANGLE) / 360);
tri->side_b = (uint16_t)(((uint32_t)sin_B * tri->side_a) / TRIG_MAX_RATIO);
tri->side_c = (uint16_t)(((uint32_t)sin_C * tri->side_a) / TRIG_MAX_RATIO);
} while (tri->side_a == tri->side_b || tri->side_a == tri->side_c || tri->side_b == tri->side_c);
// create layer with room for a pointer-sized data slot & store the RightTriangleLayer* there
tri->layer = layer_create_with_data(frame, sizeof(RightTriangleLayer *));