2025-12-28 21:32:38 +01:00
|
|
|
#include <duckdb.h>
|
2025-12-29 13:46:15 +01:00
|
|
|
#include <stdint.h>
|
2025-12-28 18:17:59 +01:00
|
|
|
#include <stdio.h>
|
2025-12-28 21:32:38 +01:00
|
|
|
#include <stdlib.h>
|
2026-01-06 22:19:08 +01:00
|
|
|
#include <string.h>
|
2026-01-08 12:34:05 +01:00
|
|
|
#include <sys/stat.h>
|
2025-12-28 21:32:38 +01:00
|
|
|
|
2026-01-19 13:53:30 +01:00
|
|
|
#include "array_utils.h"
|
2026-01-14 20:10:48 +01:00
|
|
|
#include "arrays.h"
|
2026-01-08 12:34:05 +01:00
|
|
|
#include "exit_code.h"
|
2026-01-02 20:01:19 +01:00
|
|
|
#include "lapinfo.h"
|
|
|
|
|
|
2026-01-08 12:34:05 +01:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-29 14:59:04 +01:00
|
|
|
int main(int argc, char **argv) {
|
2026-01-08 21:16:11 +01:00
|
|
|
duckdb_database db;
|
|
|
|
|
duckdb_connection conn;
|
|
|
|
|
duckdb_result lap_count_res;
|
|
|
|
|
LapInfo *session_data = NULL;
|
|
|
|
|
double *lap_timestamps = NULL;
|
|
|
|
|
|
2026-01-08 12:53:49 +01:00
|
|
|
printf("\nHello from HardCompound!\n");
|
2025-12-28 21:32:38 +01:00
|
|
|
|
2025-12-29 14:59:04 +01:00
|
|
|
if (argc < 2) {
|
2025-12-28 21:32:38 +01:00
|
|
|
printf("You need to specify a duckdb file path! Terminating!\n");
|
2026-01-08 21:16:11 +01:00
|
|
|
goto cleanup;
|
2025-12-28 21:32:38 +01:00
|
|
|
}
|
2026-01-08 12:34:05 +01:00
|
|
|
|
|
|
|
|
if (!is_valid_path(argv[1])) {
|
|
|
|
|
printf("The file you gave is not valid. Exiting!");
|
2026-01-08 21:16:11 +01:00
|
|
|
goto cleanup;
|
2026-01-08 12:34:05 +01:00
|
|
|
}
|
|
|
|
|
|
2025-12-29 13:46:15 +01:00
|
|
|
printf("First argument: %s\n", argv[1]);
|
2025-12-28 21:32:38 +01:00
|
|
|
|
2025-12-29 14:59:04 +01:00
|
|
|
if (duckdb_open(argv[1], &db) == DuckDBError) {
|
2025-12-29 13:46:15 +01:00
|
|
|
printf("Error opening duckdb file, terminating!\n");
|
2026-01-08 21:16:11 +01:00
|
|
|
goto cleanup;
|
2025-12-28 21:32:38 +01:00
|
|
|
}
|
|
|
|
|
|
2025-12-29 14:59:04 +01:00
|
|
|
if (duckdb_connect(db, &conn) == DuckDBError) {
|
2025-12-29 13:46:15 +01:00
|
|
|
printf("Error connecting to the duckdb database! Terminating!\n");
|
2026-01-08 21:16:11 +01:00
|
|
|
goto cleanup;
|
2025-12-28 21:32:38 +01:00
|
|
|
}
|
|
|
|
|
|
2026-01-03 20:44:21 +01:00
|
|
|
// 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");
|
2026-01-08 21:16:11 +01:00
|
|
|
goto cleanup;
|
2026-01-03 20:44:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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-03 20:44:21 +01:00
|
|
|
|
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];
|
|
|
|
|
}
|
2026-01-03 20:44:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
duckdb_destroy_data_chunk(&data_chunk);
|
|
|
|
|
duckdb_destroy_result(&lap_count_res);
|
|
|
|
|
|
|
|
|
|
printf("Lap count: %d\n", lap_count);
|
2026-01-08 21:16:11 +01:00
|
|
|
session_data = calloc(lap_count, sizeof(LapInfo));
|
|
|
|
|
lap_timestamps = calloc(lap_count, sizeof(double));
|
2026-01-06 22:19:08 +01:00
|
|
|
|
2026-01-08 12:53:49 +01:00
|
|
|
if (!session_data) {
|
|
|
|
|
printf("Session data failed to allocate!");
|
2026-01-08 21:16:11 +01:00
|
|
|
goto cleanup;
|
2026-01-08 12:53:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!lap_timestamps) {
|
|
|
|
|
printf("Lap timestaps array failed to init!");
|
2026-01-08 21:16:11 +01:00
|
|
|
goto cleanup;
|
2026-01-08 12:53:49 +01:00
|
|
|
}
|
|
|
|
|
|
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) {
|
2026-01-08 21:16:11 +01:00
|
|
|
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-03 20:44:21 +01:00
|
|
|
|
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
|
|
|
|
2026-01-14 20:10:48 +01:00
|
|
|
// throttle
|
|
|
|
|
float_array throttle_data_all;
|
|
|
|
|
float_array_init(&throttle_data_all);
|
|
|
|
|
allocate_array_for_db_data(&throttle_data_all, "Throttle Pos", &conn);
|
|
|
|
|
get_data_from_db("Select value as FLOAT from \"Throttle Pos\"\n", &conn, &throttle_data_all);
|
|
|
|
|
for (int32_t i = 0; i < throttle_data_all.length; ++i) {
|
2026-01-19 13:53:30 +01:00
|
|
|
// printf(" %f", float_array_get(&throttle_data_all, i));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// brake
|
|
|
|
|
float_array brake_data_all;
|
|
|
|
|
float_array_init(&brake_data_all);
|
|
|
|
|
allocate_array_for_db_data(&brake_data_all, "Brake Pos", &conn);
|
|
|
|
|
get_data_from_db("Select value as FLOAT from \"Brake Pos\"\n", &conn, &brake_data_all);
|
|
|
|
|
for (int32_t i = 0; i < brake_data_all.length; ++i) {
|
|
|
|
|
// printf(" %f", float_array_get(&brake_data_all, i));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// steering
|
|
|
|
|
float_array steering_data_all;
|
|
|
|
|
float_array_init(&steering_data_all);
|
|
|
|
|
allocate_array_for_db_data(&steering_data_all, "Steering Pos", &conn);
|
|
|
|
|
get_data_from_db("Select value as FLOAT from \"Steering Pos\"\n", &conn, &steering_data_all);
|
|
|
|
|
for (int32_t i = 0; i < steering_data_all.length; ++i) {
|
|
|
|
|
// printf(" %f", float_array_get(&steering_data_all, i));
|
|
|
|
|
}
|
|
|
|
|
// select avg(((value1+value2+value3+value4)/4)*3.6) as speed from "Wheel Speed"
|
|
|
|
|
// speed
|
|
|
|
|
float_array speed_data_all;
|
|
|
|
|
float_array_init(&speed_data_all);
|
|
|
|
|
allocate_array_for_db_data(&speed_data_all, "Wheel Speed", &conn);
|
|
|
|
|
get_data_from_db("select ((value1+value2+value3+value4)/4)*3.6 as speed from \"Wheel Speed\"", &conn,
|
|
|
|
|
&speed_data_all);
|
|
|
|
|
for (int32_t i = 0; i < speed_data_all.length; ++i) {
|
|
|
|
|
// printf(" %f", float_array_get(&speed_data_all, i));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("\nShutting down HardCompound!\n");
|
2025-12-29 13:46:15 +01:00
|
|
|
|
|
|
|
|
printf("Closing database and any connection.\n");
|
2026-01-08 21:16:11 +01:00
|
|
|
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);
|
2026-01-08 21:16:11 +01:00
|
|
|
goto exit;
|
2025-12-28 18:17:59 +01:00
|
|
|
}
|