Files
HardCompound/src/main.c

203 lines
5.9 KiB
C
Raw Normal View History

#include <duckdb.h>
2025-12-29 13:46:15 +01:00
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
2026-01-06 22:19:08 +01:00
#include <string.h>
#include <sys/stat.h>
#include "exit_code.h"
#include "lapinfo.h"
bool is_valid_path(const char *path) {
if (path == NULL) {
return false;
}
const char *dot = strrchr(path, '.'); // find the last dot which is for the extension
if (!dot || strcmp(dot, ".duckdb") != 0) {
return false;
}
struct stat path_stat;
if (stat(path, &path_stat) != 0) {
return false; // path does not exist
}
if (!S_ISREG(path_stat.st_mode)) {
return false; // checks if it is a regular file
}
return true;
}
void get_data_from_db(const char *query, duckdb_connection *conn, TelemetryInfo *info) {
duckdb_result result;
duckdb_query(*conn, query, &result);
while (true) {
duckdb_data_chunk data_chunk = duckdb_fetch_chunk(result);
if (!data_chunk) {
break;
}
idx_t row_count = duckdb_data_chunk_get_size(data_chunk); // number of rows from the data chunk
// set column
duckdb_vector col1 = duckdb_data_chunk_get_vector(data_chunk, 0);
void *col1_data = duckdb_vector_get_data(col1);
uint64_t *col1_validity = duckdb_vector_get_validity(col1);
for (idx_t row = 0; row < row_count; row++) {
if (duckdb_validity_row_is_valid(col1_validity, row)) {
switch (info->type) {
case FLOAT:
((float *)info->data)[info->data_last_index] = ((float *)col1_data)[row];
info->data_last_index++;
break;
case BOOL:
((bool *)info->data)[info->data_last_index] = ((bool *)col1_data)[row];
info->data_last_index++;
break;
case DOUBLE:
((double *)info->data)[info->data_last_index] = ((double *)col1_data)[row];
info->data_last_index++;
break;
case INT:
((int32_t *)info->data)[info->data_last_index] = ((int32_t *)col1_data)[row];
info->data_last_index++;
break;
}
} else {
printf("NULL");
}
}
duckdb_destroy_data_chunk(&data_chunk);
}
duckdb_destroy_result(&result);
}
int main(int argc, char **argv) {
duckdb_database db;
duckdb_connection conn;
duckdb_result lap_count_res;
LapInfo *session_data = NULL;
double *lap_timestamps = NULL;
printf("\nHello from HardCompound!\n");
if (argc < 2) {
printf("You need to specify a duckdb file path! Terminating!\n");
goto cleanup;
}
if (!is_valid_path(argv[1])) {
printf("The file you gave is not valid. Exiting!");
goto cleanup;
}
2025-12-29 13:46:15 +01:00
printf("First argument: %s\n", argv[1]);
if (duckdb_open(argv[1], &db) == DuckDBError) {
2025-12-29 13:46:15 +01:00
printf("Error opening duckdb file, terminating!\n");
goto cleanup;
}
if (duckdb_connect(db, &conn) == DuckDBError) {
2025-12-29 13:46:15 +01:00
printf("Error connecting to the duckdb database! Terminating!\n");
goto cleanup;
}
// get how many laps is in the session and allocate that many LapInfo-s
int32_t lap_count = 0;
duckdb_query(conn, "Select count(value) from Lap\n", &lap_count_res);
duckdb_data_chunk data_chunk = duckdb_fetch_chunk(lap_count_res);
if (!data_chunk) {
printf("Error in retrieving laps");
goto cleanup;
}
// set column
duckdb_vector col1 = duckdb_data_chunk_get_vector(data_chunk, 0);
int32_t *col1_data = (int32_t *)duckdb_vector_get_data(col1);
uint64_t *col1_validity = duckdb_vector_get_validity(col1);
2026-01-06 22:19:08 +01:00
idx_t row_count = duckdb_data_chunk_get_size(data_chunk); // number of rows from the data chunk
2026-01-06 22:19:08 +01:00
for (idx_t row = 0; row < row_count; row++) {
if (duckdb_validity_row_is_valid(col1_validity, 0)) {
lap_count = col1_data[0];
}
}
duckdb_destroy_data_chunk(&data_chunk);
duckdb_destroy_result(&lap_count_res);
printf("Lap count: %d\n", lap_count);
session_data = calloc(lap_count, sizeof(LapInfo));
lap_timestamps = calloc(lap_count, sizeof(double));
2026-01-06 22:19:08 +01:00
if (!session_data) {
printf("Session data failed to allocate!");
goto cleanup;
}
if (!lap_timestamps) {
printf("Lap timestaps array failed to init!");
goto cleanup;
}
2026-01-06 22:19:08 +01:00
duckdb_result lap_timestamps_res;
if (duckdb_query(conn, "Select ts as DOUBLE from Lap\n", &lap_timestamps_res) == DuckDBError) {
goto cleanup;
2026-01-06 22:19:08 +01:00
}
int current_index = 0;
while (true) {
duckdb_data_chunk data_chunk_2 = duckdb_fetch_chunk(lap_timestamps_res);
if (!data_chunk_2) {
break;
}
idx_t current_chunk_size = duckdb_data_chunk_get_size(data_chunk_2);
2026-01-06 22:19:08 +01:00
duckdb_vector col2 = duckdb_data_chunk_get_vector(data_chunk_2, 0);
double *ts_data = (double *)duckdb_vector_get_data(col2);
uint64_t *col2_validity = duckdb_vector_get_validity(col2);
for (idx_t row = 0; row < current_chunk_size; row++) {
if (!col2_validity || duckdb_validity_row_is_valid(col2_validity, row)) {
if (current_index < lap_count) {
lap_timestamps[current_index++] = ts_data[row];
}
}
}
duckdb_destroy_data_chunk(&data_chunk_2);
}
duckdb_destroy_result(&lap_timestamps_res);
for (int i = 0; i < lap_count; i++) {
printf("%f, ", lap_timestamps[i]);
}
printf("\n");
2025-12-29 13:46:15 +01:00
// get the per laptime data
2025-12-29 13:46:15 +01:00
printf("Shutting down HardCompound!\n");
printf("Closing database and any connection.\n");
goto cleanup;
exit:
return EXIT_OK;
cleanup:
free(NULL);
free(session_data);
free(lap_timestamps);
2025-12-29 13:46:15 +01:00
duckdb_disconnect(&conn);
duckdb_close(&db);
goto exit;
}