Compare commits

...

7 Commits

4 changed files with 258 additions and 154 deletions

View File

@@ -5,6 +5,7 @@ VENDORDIR = vendor
target ?= linux
profile ?= debug
valgrind ?= false
ifeq ($(target), windows)
CC = x86_64-w64-mingw32-gcc
@@ -56,7 +57,13 @@ $(BUILDDIR)/%.o: $(SRCDIR)/%.c
clean:
rm -rf $(BUILDDIR)
ifeq ($(valgrind), true)
RUN_CMD = valgrind --leak-check=full ./$(BUILDDIR)/$(APPNAME)$(EXT)
else
RUN_CMD = ./$(BUILDDIR)/$(APPNAME)$(EXT)
endif
run: all
./$(BUILDDIR)/$(APPNAME)$(EXT)
$(RUN_CMD) ./data/Circuit.duckdb
.PHONY: all clean run

9
src/exit_code.h Normal file
View File

@@ -0,0 +1,9 @@
typedef enum {
EXIT_OK = 0,
ERR_ARGUMENT = 1,
ERR_FILE = 2,
ERR_DATABASE = 3,
ERR_CONNECTION = 4,
ERR_MEMORY = 5,
ERR_QUERY = 6,
} exit_code;

View File

@@ -2,39 +2,73 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#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;
int32_t iterations = 0;
int32_t number_of_data_points = 0;
duckdb_query(*conn, query, &result);
while (true) {
iterations++;
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
number_of_data_points += row_count;
// set column
duckdb_vector col1 = duckdb_data_chunk_get_vector(data_chunk, 0);
float *col1_data = (float *)duckdb_vector_get_data(col1);
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)) {
// put a switch here based on the info from the struct
((float *)info->data)[info->data_last_index] = col1_data[row];
info->data_last_index++;
// TODO: set info->data_size as capacity at struct creation
printf("%f, ", col1_data[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;
}
// printf("%f, ", ((float *)col1_data)[row]);
} else {
printf("NULL");
}
@@ -43,177 +77,120 @@ void get_data_from_db(const char *query, duckdb_connection *conn, TelemetryInfo
duckdb_destroy_data_chunk(&data_chunk);
}
duckdb_destroy_result(&result);
printf("\nNumber of iterations: %d, number of data points: %d\n", iterations, number_of_data_points);
}
int main(int argc, char **argv) {
printf("Hello from HardCompound!\n");
printf("\nHello from HardCompound!\n");
if (argc < 2) {
printf("You need to specify a duckdb file path! Terminating!\n");
exit(1);
exit(ERR_ARGUMENT);
}
if (!is_valid_path(argv[1])) {
printf("The file you gave is not valid. Exiting!");
exit(ERR_FILE);
}
printf("First argument: %s\n", argv[1]);
duckdb_database db;
if (duckdb_open(argv[1], &db) == DuckDBError) {
printf("Error opening duckdb file, terminating!\n");
exit(2);
exit(ERR_DATABASE);
}
duckdb_connection conn;
if (duckdb_connect(db, &conn) == DuckDBError) {
printf("Error connecting to the duckdb database! Terminating!\n");
exit(3);
duckdb_close(&db);
exit(ERR_CONNECTION);
}
const char *channel_tables[] = {"Ambient Temperature",
"Brake Pos",
"Brake Pos Unfiltered",
"Brake Thickness",
"Brakes Air Temp",
"Brakes Force",
"Brakes Temp",
"Clutch Pos",
"Clutch Pos Unfiltered",
"Clutch RPM",
"Drag",
"Engine Oil Temp",
"Engine RPM",
"Engine Water Temp",
"FFB Output",
"Front3rdDeflection",
"FrontDownForce",
"FrontRideHeight",
"FrontWingHeight",
"Fuel Level",
"G Force Lat",
"G Force Long",
"G Force Vert",
"GPS Latitude",
"GPS Longitude",
"GPS Speed",
"GPS Time",
"Ground Speed",
"Lap Dist",
"Lateral Acceleration",
"Longitudinal Acceleration",
"OverheatingState",
"Path Lateral",
"ReadDownForce",
"Rear3rdDeflection",
"RearRideHeight",
"Regen Rate",
"RideHeights",
"SoC",
"Steered Angle",
"Steering Pos",
"Steering Pos Unfiltered",
"Steering Shaft Torque",
"Susp Pos",
"Throttle Pos",
"Throttle Pos Unfiltered",
"Time Behind Next",
"Total Dist",
"Track Edge",
"Track Temperature",
"Turbo Boost Pressure",
"Tyres Wear",
"TyresCarcassTemp",
"TyresPressure",
"TyresRimTemp",
"TyresRubberTemp",
"TyresTempCentre",
"TyresTempLeft",
"TyresTempRight",
"Virtual Energy",
"Wheel Speed",
"Wind Heading",
"Wind Speed",
"Yaw Rate"};
// get how many laps is in the session and allocate that many LapInfo-s
duckdb_result lap_count_res;
int32_t lap_count = 0;
duckdb_query(conn, "Select count(value) from Lap\n", &lap_count_res);
const int channel_table_count = sizeof(channel_tables) / sizeof(channel_tables[0]);
duckdb_data_chunk data_chunk = duckdb_fetch_chunk(lap_count_res);
if (!data_chunk) {
printf("Error in retrieving laps");
duckdb_disconnect(&conn);
duckdb_close(&db);
exit(ERR_QUERY);
}
const char *event_tables[] = {"ABS",
"ABSLevel",
"AntiStall Activated",
"Best LapTime",
"Best Sector1",
"Best Sector2",
"Brake Bias Rear",
"Brake Migration",
"CloudDarkness",
"Current LapTime",
"Current Sector",
"Current Sector1",
"Current Sector2",
"Engine Max RPM",
"Finish Status",
"FrontFlapActivated",
"FuelMixtureMap",
"Gear",
"Headlights State",
"In Pits",
"Lap",
"Lap Time",
"Last Sector1",
"Last Sector2",
"LastImpactMagnitude",
"LaunchControlActive",
"Minimum Path Wetness",
"OffpathWetness",
"RearFlapActivated",
"RearFlapLegalStatus",
"Sector1 Flag",
"Sector2 Flag",
"Sector3 Flag",
"Speed Limiter",
"SurfaceTypes",
"TC",
"TCCut",
"TCLevel",
"TCSlipAngle",
"TyresCompound",
"WheelsDetached",
"Yellow Flag State"};
// 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);
idx_t row_count = duckdb_data_chunk_get_size(data_chunk); // number of rows from the data chunk
const int event_table_count = sizeof(event_tables) / sizeof(event_tables[0]);
for (idx_t row = 0; row < row_count; row++) {
if (duckdb_validity_row_is_valid(col1_validity, 0)) {
lap_count = col1_data[0];
}
}
LapInfo info = {.lap_number = 0,
.start_time = 0,
.throttle_pos = {.data_last_index = 0,
.data_size = 75000,
.frequency = 50,
.type = FLOAT,
.validity = NULL,
.data = malloc(sizeof(float) * 75000)},
.brake_pos = {.data_last_index = 0,
.data_size = 75000,
.frequency = 50,
.type = FLOAT,
.validity = NULL,
.data = malloc(sizeof(float) * 75000)},
.steering_pos = {.data_last_index = 0,
.data_size = 75000,
.frequency = 50,
.type = FLOAT,
.validity = NULL,
.data = malloc(sizeof(float) * 75000)},
.speed = {.data_last_index = 0,
.data_size = 75000,
.frequency = 50,
.type = FLOAT,
.validity = NULL,
.data = malloc(sizeof(float) * 75000)}};
duckdb_destroy_data_chunk(&data_chunk);
duckdb_destroy_result(&lap_count_res);
get_data_from_db("Select * from \"Throttle Pos\"\n", &conn, &info.throttle_pos);
destroyLapinfo(&info);
printf("Lap count: %d\n", lap_count);
LapInfo *session_data = calloc(lap_count, sizeof(LapInfo));
double *lap_timestamps = calloc(lap_count, sizeof(double));
if (!session_data) {
printf("Session data failed to allocate!");
exit(ERR_MEMORY);
}
if (!lap_timestamps) {
printf("Lap timestaps array failed to init!");
exit(ERR_MEMORY);
}
duckdb_result lap_timestamps_res;
if (duckdb_query(conn, "Select ts as DOUBLE from Lap\n", &lap_timestamps_res) == DuckDBError) {
exit(ERR_QUERY);
}
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);
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");
free(session_data);
printf("Shutting down HardCompound!\n");
printf("Closing database and any connection.\n");
duckdb_disconnect(&conn);
duckdb_close(&db);
return 0;
return EXIT_OK;
}

111
src/tables.c Normal file
View File

@@ -0,0 +1,111 @@
const char *channel_tables[] = {"Ambient Temperature",
"Brake Pos",
"Brake Pos Unfiltered",
"Brake Thickness",
"Brakes Air Temp",
"Brakes Force",
"Brakes Temp",
"Clutch Pos",
"Clutch Pos Unfiltered",
"Clutch RPM",
"Drag",
"Engine Oil Temp",
"Engine RPM",
"Engine Water Temp",
"FFB Output",
"Front3rdDeflection",
"FrontDownForce",
"FrontRideHeight",
"FrontWingHeight",
"Fuel Level",
"G Force Lat",
"G Force Long",
"G Force Vert",
"GPS Latitude",
"GPS Longitude",
"GPS Speed",
"GPS Time",
"Ground Speed",
"Lap Dist",
"Lateral Acceleration",
"Longitudinal Acceleration",
"OverheatingState",
"Path Lateral",
"ReadDownForce",
"Rear3rdDeflection",
"RearRideHeight",
"Regen Rate",
"RideHeights",
"SoC",
"Steered Angle",
"Steering Pos",
"Steering Pos Unfiltered",
"Steering Shaft Torque",
"Susp Pos",
"Throttle Pos",
"Throttle Pos Unfiltered",
"Time Behind Next",
"Total Dist",
"Track Edge",
"Track Temperature",
"Turbo Boost Pressure",
"Tyres Wear",
"TyresCarcassTemp",
"TyresPressure",
"TyresRimTemp",
"TyresRubberTemp",
"TyresTempCentre",
"TyresTempLeft",
"TyresTempRight",
"Virtual Energy",
"Wheel Speed",
"Wind Heading",
"Wind Speed",
"Yaw Rate"};
const int channel_table_count = sizeof(channel_tables) / sizeof(channel_tables[0]);
const char *event_tables[] = {"ABS",
"ABSLevel",
"AntiStall Activated",
"Best LapTime",
"Best Sector1",
"Best Sector2",
"Brake Bias Rear",
"Brake Migration",
"CloudDarkness",
"Current LapTime",
"Current Sector",
"Current Sector1",
"Current Sector2",
"Engine Max RPM",
"Finish Status",
"FrontFlapActivated",
"FuelMixtureMap",
"Gear",
"Headlights State",
"In Pits",
"Lap",
"Lap Time",
"Last Sector1",
"Last Sector2",
"LastImpactMagnitude",
"LaunchControlActive",
"Minimum Path Wetness",
"OffpathWetness",
"RearFlapActivated",
"RearFlapLegalStatus",
"Sector1 Flag",
"Sector2 Flag",
"Sector3 Flag",
"Speed Limiter",
"SurfaceTypes",
"TC",
"TCCut",
"TCLevel",
"TCSlipAngle",
"TyresCompound",
"WheelsDetached",
"Yellow Flag State"};
const int event_table_count = sizeof(event_tables) / sizeof(event_tables[0]);