trainlog/tui/include/trainlog/database.h

210 lines
5.5 KiB
C

#ifndef TRAINLOG_DATABASE_H
#define TRAINLOG_DATABASE_H
/**
* @file database.h
* @brief SQLite persistence API for the Trainlog TUI core.
*/
#include <stddef.h>
#include "trainlog/model.h"
#include "trainlog/status.h"
#define TRAINLOG_DATABASE_SCHEMA_VERSION 2
typedef struct TrainlogDatabase TrainlogDatabase;
TrainlogStatus trainlog_database_open(
const char *path,
TrainlogDatabase **output_database
);
void trainlog_database_close(TrainlogDatabase *database);
TrainlogStatus trainlog_database_schema_version(
TrainlogDatabase *database,
int *output_version
);
TrainlogStatus trainlog_database_foreign_keys_enabled(
TrainlogDatabase *database,
int *output_enabled
);
TrainlogStatus trainlog_database_begin(TrainlogDatabase *database);
TrainlogStatus trainlog_database_commit(TrainlogDatabase *database);
TrainlogStatus trainlog_database_rollback(TrainlogDatabase *database);
/**
* @brief Insert one already-normalized canonical exercise row.
*
* Unicode normalization belongs to catalog.c. This lower-level API owns the
* final SQLite uniqueness barrier.
*/
TrainlogStatus trainlog_database_insert_exercise(
TrainlogDatabase *database,
const char *exercise_id,
const char *name,
const char *normalized_name,
TrainlogTrackingMode tracking_mode
);
TrainlogStatus trainlog_database_exercise_count(
TrainlogDatabase *database,
size_t *output_count
);
TrainlogStatus trainlog_database_list_exercises(
TrainlogDatabase *database,
TrainlogExercise *output,
size_t capacity,
size_t *output_count
);
TrainlogStatus trainlog_database_insert_session(
TrainlogDatabase *database,
const TrainlogSessionInput *session
);
TrainlogStatus trainlog_database_session_count(
TrainlogDatabase *database,
size_t *output_count
);
TrainlogStatus trainlog_database_list_sessions(
TrainlogDatabase *database,
TrainlogSessionSummary *output,
size_t capacity,
size_t *output_count
);
TrainlogStatus trainlog_database_insert_body_observation(
TrainlogDatabase *database,
const TrainlogBodyObservationInput *observation
);
TrainlogStatus trainlog_database_list_weight_points(
TrainlogDatabase *database,
TrainlogWeightPoint *output,
size_t capacity,
size_t *output_count
);
/* TRAINLOG_SESSION_DETAILS_API */
#define TRAINLOG_SET_SUMMARY_MAX 1024U
typedef struct TrainlogPersistedExerciseDetail {
char name[TRAINLOG_NAME_MAX + 1U];
TrainlogTrackingMode tracking_mode;
TrainlogLoadMode load_mode;
int rest_seconds;
int target_sets;
int target_reps;
int target_duration_seconds;
int has_target_weight;
double target_weight_kg;
size_t actual_set_count;
char actual_summary[TRAINLOG_SET_SUMMARY_MAX + 1U];
} TrainlogPersistedExerciseDetail;
/**
* @brief Load one session header plus ordered exercise details.
*
* The function is read-only and allocates nothing.
*/
TrainlogStatus trainlog_database_get_session_details(
TrainlogDatabase *database,
const char *session_id,
TrainlogSessionSummary *output_session,
TrainlogPersistedExerciseDetail *output_exercises,
size_t exercise_capacity,
size_t *output_exercise_count
);
/* TRAINLOG_BODY_METRIC_HISTORY_API */
typedef enum TrainlogBodyMetric {
TRAINLOG_BODY_METRIC_WEIGHT = 0,
TRAINLOG_BODY_METRIC_NECK,
TRAINLOG_BODY_METRIC_SHOULDERS,
TRAINLOG_BODY_METRIC_CHEST,
TRAINLOG_BODY_METRIC_WAIST,
TRAINLOG_BODY_METRIC_HIPS,
TRAINLOG_BODY_METRIC_LEFT_ARM,
TRAINLOG_BODY_METRIC_RIGHT_ARM,
TRAINLOG_BODY_METRIC_LEFT_FOREARM,
TRAINLOG_BODY_METRIC_RIGHT_FOREARM,
TRAINLOG_BODY_METRIC_LEFT_THIGH,
TRAINLOG_BODY_METRIC_RIGHT_THIGH,
TRAINLOG_BODY_METRIC_LEFT_CALF,
TRAINLOG_BODY_METRIC_RIGHT_CALF,
TRAINLOG_BODY_METRIC_COUNT
} TrainlogBodyMetric;
typedef struct TrainlogBodyMetricPoint {
char observed_at[TRAINLOG_TIMESTAMP_MAX + 1U];
double value;
} TrainlogBodyMetricPoint;
typedef struct TrainlogBodyPairPoint {
bool found;
char observed_at[TRAINLOG_TIMESTAMP_MAX + 1U];
double left_value;
double right_value;
} TrainlogBodyPairPoint;
TrainlogStatus trainlog_database_list_body_metric_points(
TrainlogDatabase *database,
TrainlogBodyMetric metric,
TrainlogBodyMetricPoint *output,
size_t capacity,
size_t *output_count
);
TrainlogStatus trainlog_database_latest_body_pair(
TrainlogDatabase *database,
TrainlogBodyMetric left_metric,
TrainlogBodyMetric right_metric,
TrainlogBodyPairPoint *output
);
/* TRAINLOG_EXERCISE_PERFORMANCE_API */
typedef struct TrainlogExercisePerformancePoint {
char session_id[TRAINLOG_ID_MAX + 1U];
char started_at[TRAINLOG_TIMESTAMP_MAX + 1U];
TrainlogTrackingMode tracking_mode;
TrainlogLoadMode load_mode;
size_t actual_set_count;
int has_performance;
int metric_value;
int has_weight;
double weight_kg;
} TrainlogExercisePerformancePoint;
/**
* @brief Read newest-first per-session representative performance.
*
* Representative-set semantics:
*
* - no load: greatest successful reps/duration;
* - external load: greatest load, then greatest reps/duration;
* - assistance: lowest assistance, then greatest reps/duration.
*
* A zero-repetition failed attempt is never promoted to representative
* performance. This API does not create or infer a measured maximum.
*/
TrainlogStatus trainlog_database_list_exercise_performance(
TrainlogDatabase *database,
const char *exercise_id,
TrainlogExercisePerformancePoint *output,
size_t capacity,
size_t *output_count
);
#endif