test: cover dashboard legacy weight edges
This commit is contained in:
parent
af86895c2e
commit
3e06039890
3 changed files with 78 additions and 9 deletions
|
|
@ -195,8 +195,10 @@ before/at/after the 30-day boundary, valid actual history without `ended_at`,
|
|||
and plan-only exclusion. It covers repeated occurrences, heterogeneous REPS
|
||||
sets, SETS/DURATION, CONTINUOUS/DURATION without fake sets, assistance,
|
||||
unweighted actuals, ordinary heavy sets versus explicit MAX, equal-instant
|
||||
tie-breaks, primary-only catalogue zones, secondary-zone exclusion, and seeded
|
||||
catalogue behavior. Exact and exceeded bounds are asserted for 128 observable
|
||||
tie-breaks (including equal same-session performance points), the legacy
|
||||
unweighted `0.0 kg` prior baseline, primary-only catalogue zones,
|
||||
secondary-zone exclusion, and seeded catalogue behavior. Exact and exceeded
|
||||
bounds are asserted for 128 observable
|
||||
sessions and 4096 Dashboard facts, including the independently truncated totals
|
||||
and `partial` flag. Existing regressions continue to cover malformed legacy
|
||||
timestamps, body-metric selection, responsive rendering, all-history buckets,
|
||||
|
|
|
|||
|
|
@ -441,8 +441,13 @@ by instant and `session_id`.
|
|||
The selected working series currently copies every matching exact-dose set and
|
||||
marks its point as weighted even when the persisted set has no weight, yielding
|
||||
`0.0 kg` for that point. This surprising legacy behavior is characterized, not
|
||||
endorsed or corrected by this tranche. The Core extraction must initially
|
||||
preserve it or explicitly return to contract review before changing semantics.
|
||||
endorsed or corrected by this tranche. The prior-best scan likewise accepts a
|
||||
matching earlier unweighted set as a `0.0 kg` baseline, so a later weighted set
|
||||
can be classified as an improvement. Two selected-series points from the same
|
||||
session and canonical instant compare equal because that final comparator has
|
||||
no set-position tie-break; the preceding fact order is session, entry, kind,
|
||||
then set position. The Core extraction must initially preserve these observed
|
||||
semantics or explicitly return to contract review before changing them.
|
||||
|
||||
The snapshot reads at most 128 observable sessions, 4096 occurrence facts, 128
|
||||
selected performance points, and 256 points for each body metric. Reaching a
|
||||
|
|
|
|||
|
|
@ -1508,6 +1508,36 @@ static bool dashboard_insert_plan_for_exercise(TrainlogDatabase *database,
|
|||
return trainlog_database_insert_session(database, &session) == TRAINLOG_STATUS_OK;
|
||||
}
|
||||
|
||||
static bool dashboard_insert_optional_weight_set(TrainlogDatabase *database,
|
||||
const char *session_id, const char *exercise_id, const char *started_at,
|
||||
bool has_weight, double weight)
|
||||
{
|
||||
TrainlogSetInput set = {10, 0, has_weight, weight};
|
||||
TrainlogSessionExerciseInput occurrence;
|
||||
TrainlogSessionInput session;
|
||||
(void)memset(&occurrence, 0, sizeof(occurrence));
|
||||
(void)memset(&session, 0, sizeof(session));
|
||||
(void)snprintf(occurrence.exercise_id, sizeof(occurrence.exercise_id), "%s",
|
||||
exercise_id);
|
||||
(void)snprintf(occurrence.equipment_id, sizeof(occurrence.equipment_id), "%s",
|
||||
"leg_press");
|
||||
occurrence.recording_mode = TRAINLOG_RECORDING_SETS;
|
||||
occurrence.tracking_mode = TRAINLOG_TRACKING_REPS;
|
||||
occurrence.load_mode = TRAINLOG_LOAD_EXTERNAL;
|
||||
occurrence.target_sets = 1;
|
||||
occurrence.target_reps = 10;
|
||||
occurrence.target_has_weight = true;
|
||||
occurrence.target_weight_kg = 25.0;
|
||||
occurrence.sets = &set;
|
||||
occurrence.set_count = 1U;
|
||||
(void)snprintf(session.session_id, sizeof(session.session_id), "%s", session_id);
|
||||
(void)snprintf(session.started_at, sizeof(session.started_at), "%s", started_at);
|
||||
session.session_type = TRAINLOG_SESSION_TRAINING;
|
||||
session.exercises = &occurrence;
|
||||
session.exercise_count = 1U;
|
||||
return trainlog_database_insert_session(database, &session) == TRAINLOG_STATUS_OK;
|
||||
}
|
||||
|
||||
static bool test_dashboard_characterization_empty_and_window_boundaries(void)
|
||||
{
|
||||
TrainlogDatabase *database = NULL;
|
||||
|
|
@ -1614,6 +1644,11 @@ static bool test_dashboard_characterization_modalities_ties_and_zones(void)
|
|||
"ex_10000000-0000-4000-8000-000000000004", "Assistance", "assistance",
|
||||
TRAINLOG_TRACKING_REPS, TRAINLOG_RECORDING_SETS,
|
||||
(TrainlogExerciseDataFields)0) == TRAINLOG_STATUS_OK);
|
||||
CHECK(trainlog_database_insert_exercise_profiled(database,
|
||||
"ex_10000000-0000-4000-8000-000000000005", "Poids absent antérieur",
|
||||
"poids absent anterieur", TRAINLOG_TRACKING_REPS,
|
||||
TRAINLOG_RECORDING_SETS, (TrainlogExerciseDataFields)0) ==
|
||||
TRAINLOG_STATUS_OK);
|
||||
CHECK(trainlog_database_replace_exercise_body_zones(database,
|
||||
"ex_33333333-3333-4333-8333-333333333333", "chest",
|
||||
primary_secondary, 1U) == TRAINLOG_STATUS_OK);
|
||||
|
|
@ -1675,6 +1710,14 @@ static bool test_dashboard_characterization_modalities_ties_and_zones(void)
|
|||
session.exercises = occurrences;
|
||||
session.exercise_count = 4U;
|
||||
CHECK(trainlog_database_insert_session(database, &session) == TRAINLOG_STATUS_OK);
|
||||
CHECK(dashboard_insert_optional_weight_set(database,
|
||||
"se_32000000-0000-4000-8000-000000000009",
|
||||
"ex_10000000-0000-4000-8000-000000000005", "2026-09-08T08:00:00Z",
|
||||
false, 0.0));
|
||||
CHECK(dashboard_insert_optional_weight_set(database,
|
||||
"se_32000000-0000-4000-8000-000000000010",
|
||||
"ex_10000000-0000-4000-8000-000000000005", "2026-09-09T08:00:00Z",
|
||||
true, 25.0));
|
||||
|
||||
(void)memset(&occurrences[0], 0, sizeof(occurrences[0]));
|
||||
(void)memset(&session, 0, sizeof(session));
|
||||
|
|
@ -1748,10 +1791,10 @@ static bool test_dashboard_characterization_modalities_ties_and_zones(void)
|
|||
app_shell_load_dashboard(&app);
|
||||
CHECK(!app.dashboard.error && !app.dashboard.partial &&
|
||||
!app.dashboard.invalid_data);
|
||||
CHECK(app.dashboard.completed_session_count == 7U);
|
||||
CHECK(app.dashboard.performed_set_count == 8U);
|
||||
CHECK(app.dashboard.completed_session_count == 9U);
|
||||
CHECK(app.dashboard.performed_set_count == 10U);
|
||||
CHECK(app.dashboard.explicit_max_count == 2U);
|
||||
CHECK(app.dashboard.distinct_exercise_count == 6U);
|
||||
CHECK(app.dashboard.distinct_exercise_count == 7U);
|
||||
CHECK(app.dashboard.has_performance);
|
||||
CHECK(strcmp(app.dashboard.exercise.exercise_id,
|
||||
"ex_33333333-3333-4333-8333-333333333333") == 0);
|
||||
|
|
@ -1768,7 +1811,9 @@ static bool test_dashboard_characterization_modalities_ties_and_zones(void)
|
|||
"ex_10000000-0000-4000-8000-000000000000") == 0);
|
||||
for (index = 0U; index < app.dashboard.week_count; ++index)
|
||||
working += app.dashboard.weeks[index].working_improvements;
|
||||
CHECK(working == 2U);
|
||||
/* Existing behavior: a matching earlier unweighted set supplies a 0.0
|
||||
* baseline and therefore makes the later weighted set an improvement. */
|
||||
CHECK(working == 3U);
|
||||
CHECK(app.dashboard.zone_count == 4U);
|
||||
for (index = 0U; index < app.dashboard.zone_count; ++index) {
|
||||
chest = chest || (strcmp(app.dashboard.zones[index].label, "Pectoraux") == 0 &&
|
||||
|
|
@ -1777,9 +1822,26 @@ static bool test_dashboard_characterization_modalities_ties_and_zones(void)
|
|||
app.dashboard.zones[index].count == 2U);
|
||||
unclassified = unclassified ||
|
||||
(strcmp(app.dashboard.zones[index].label, "Non classés") == 0 &&
|
||||
app.dashboard.zones[index].count == 5U);
|
||||
app.dashboard.zones[index].count == 6U);
|
||||
}
|
||||
CHECK(chest && back && unclassified);
|
||||
{
|
||||
TrainlogExercisePerformancePoint left;
|
||||
TrainlogExercisePerformancePoint right;
|
||||
(void)memset(&left, 0, sizeof(left));
|
||||
(void)memset(&right, 0, sizeof(right));
|
||||
(void)snprintf(left.started_at, sizeof(left.started_at), "%s",
|
||||
"2026-09-10T08:00:00Z");
|
||||
(void)snprintf(right.started_at, sizeof(right.started_at), "%s",
|
||||
left.started_at);
|
||||
(void)snprintf(left.session_id, sizeof(left.session_id), "%s",
|
||||
"se_32000000-0000-4000-8000-000000000011");
|
||||
(void)snprintf(right.session_id, sizeof(right.session_id), "%s",
|
||||
left.session_id);
|
||||
left.weight_kg = 10.0;
|
||||
right.weight_kg = 20.0;
|
||||
CHECK(dashboard_performance_time_compare(&left, &right) == 0);
|
||||
}
|
||||
trainlog_database_close(database);
|
||||
dashboard_characterization_restore_clock();
|
||||
return true;
|
||||
|
|
|
|||
Loading…
Reference in a new issue