Host C Specs


Directory: src/c/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 30 / 0 / 30
Functions: 100.0% 5 / 0 / 5
Branches: 95.5% 21 / 0 / 22

core/clock/solar.c
Line Branch Exec Source
1 /**
2 * @file solar.c
3 * @brief How the day's light is going, worked out from three plain clock readings.
4 *
5 * @ingroup lib_core
6 */
7 #include "clock/solar.h"
8
9 /// A day's worth of minutes, for wrapping the night span across midnight
10 #define MINUTES_PER_DAY 1440
11
12 /**
13 * @brief Whether all three readings are real minutes of the day, so the maths below is not run on a
14 * missing time. Sunrise and sunset landing on the same minute also count as missing, since that
15 * could be a sun that never sets or one that never rises and there is no telling which.
16 *
17 * @param rise Sunrise, minutes past midnight, or -1 for no data.
18 * @param set Sunset, minutes past midnight, or -1 for no data.
19 * @param now The clock, minutes past midnight, or -1 for no data.
20 * @return True when all three are real readings and the sun both rises and sets.
21 */
22 23 static bool have_all(int rise, int set, int now)
23 {
24 // a reading below zero turns into a huge unsigned one, so each check covers both ends
25 45 return (unsigned)rise < MINUTES_PER_DAY &&
26
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 2 times.
22 (unsigned)set < MINUTES_PER_DAY &&
27
5/6
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✓ Branch 5 taken 3 times.
45 (unsigned)now < MINUTES_PER_DAY &&
28 rise != set;
29 }
30
31 /**
32 * @brief Minutes going forward round the clock from one reading to another.
33 *
34 * Sunset falls after midnight in a high latitude summer, so the daylight can run from 03:00 round
35 * to 00:30. Measuring everything forward from sunrise this way covers that and an ordinary day
36 * with the same maths.
37 *
38 * @param from The earlier reading, minutes past midnight.
39 * @param to The later reading, minutes past midnight.
40 * @return 0 to 1439.
41 */
42 46 static int forward(int from, int to)
43 {
44 46 int minutes = to - from;
45
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 26 times.
46 if (minutes < 0)
46 {
47 20 minutes += MINUTES_PER_DAY;
48 }
49 46 return minutes;
50 }
51
52 9 int solar_day_progress(int rise, int set, int now)
53 {
54
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 6 times.
9 if (!have_all(rise, set, now))
55 {
56 3 return -1;
57 }
58
59 6 int span = forward(rise, set);
60 6 int elapsed = forward(rise, now);
61
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (elapsed > span)
62 {
63 3 return -1; // past sunset and not yet round to sunrise, so it is night
64 }
65 3 return (elapsed * 100) / span;
66 }
67
68 6 int solar_night_progress(int rise, int set, int now)
69 {
70
4/4
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 1 time.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 3 times.
6 if (!have_all(rise, set, now) || forward(rise, now) <= forward(rise, set))
71 {
72 3 return -1;
73 }
74
75 // sunset to the next sunrise, which is whatever the daylight leaves of the day
76 3 int span = MINUTES_PER_DAY - forward(rise, set);
77 3 return (forward(set, now) * 100) / span;
78 }
79
80 8 int solar_next_event(int rise, int set, int now, bool *is_sunrise)
81 {
82
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 6 times.
8 if (!have_all(rise, set, now))
83 {
84 2 return -1;
85 }
86
87
2/2
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
6 if (forward(rise, now) < forward(rise, set))
88 {
89 3 *is_sunrise = false;
90 3 return forward(now, set);
91 }
92 3 *is_sunrise = true;
93 3 return forward(now, rise);
94 }
95