Compare commits
19 Commits
2e8f90eb3e
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 684f026f2a | |||
| a1f9a9deab | |||
| 3ea5736fb6 | |||
| c6a870a462 | |||
| c5c5f44ec4 | |||
| d4a21df8a8 | |||
| a948ca19fc | |||
| ad85394014 | |||
| 6d8018f21b | |||
| 4864f01af3 | |||
| 70c15db109 | |||
| 6f0fb8cefd | |||
| 53a2194bde | |||
| 25a9dfb349 | |||
| b380f203e3 | |||
| 615d8c7f06 | |||
| f52d081d04 | |||
| abe3a2dbb1 | |||
| 92cf26fcf6 |
9
Makefile
9
Makefile
@@ -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
|
||||
|
||||
@@ -8,6 +8,12 @@ A Le Mans Ultimate telemetry viewer with a hosted database.
|
||||
|
||||
`sudo pacman -S mariadb-libs`
|
||||
|
||||
### Valgrind
|
||||
`sudo pacman -S valgrind`
|
||||
|
||||
## Running:
|
||||
`make run` -> run a linux binary with a sample data
|
||||
`make run valgrind=true` -> run the linux binary with valgrind
|
||||
|
||||
## Compiling:
|
||||
|
||||
@@ -27,4 +33,4 @@ A Le Mans Ultimate telemetry viewer with a hosted database.
|
||||
|
||||
#### Linux (Default):
|
||||
|
||||
`make target=linux`
|
||||
`make target=linux` or just `make`
|
||||
|
||||
56
src/array_utils.c
Normal file
56
src/array_utils.c
Normal file
@@ -0,0 +1,56 @@
|
||||
#include <duckdb.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "arrays.h"
|
||||
|
||||
void allocate_array_for_db_data(float_array *array, const char *table, duckdb_connection *conn) {
|
||||
char query[100];
|
||||
sprintf(query, "Select count(*) from \"%s\"", table);
|
||||
duckdb_result result;
|
||||
duckdb_query(*conn, query, &result);
|
||||
|
||||
duckdb_data_chunk chunk = duckdb_fetch_chunk(result);
|
||||
if (!chunk) {
|
||||
return;
|
||||
}
|
||||
|
||||
duckdb_vector col1 = duckdb_data_chunk_get_vector(chunk, 0);
|
||||
int32_t *col1_data = (int32_t *)duckdb_vector_get_data(col1);
|
||||
uint64_t *col1_validity = duckdb_vector_get_validity(col1);
|
||||
|
||||
if (duckdb_validity_row_is_valid(col1_validity, 0)) {
|
||||
printf("capycity of array: %d\n", col1_data[0]);
|
||||
float_array_allocate(array, col1_data[0]);
|
||||
}
|
||||
duckdb_destroy_data_chunk(&chunk);
|
||||
duckdb_destroy_result(&result);
|
||||
}
|
||||
|
||||
void get_data_from_db(const char *query, duckdb_connection *conn, float_array *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)) {
|
||||
float_array_set(info, ((float *)col1_data)[row], -1);
|
||||
}
|
||||
}
|
||||
|
||||
duckdb_destroy_data_chunk(&data_chunk);
|
||||
}
|
||||
duckdb_destroy_result(&result);
|
||||
}
|
||||
6
src/array_utils.h
Normal file
6
src/array_utils.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#include <duckdb.h>
|
||||
|
||||
#include "arrays.h"
|
||||
|
||||
void allocate_array_for_db_data(float_array *array, const char *table, duckdb_connection *conn);
|
||||
void get_data_from_db(const char *query, duckdb_connection *conn, float_array *info);
|
||||
330
src/arrays.c
Normal file
330
src/arrays.c
Normal file
@@ -0,0 +1,330 @@
|
||||
#include "arrays.h"
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
bool bool_array_get(const bool_array *array, int32_t index) {
|
||||
if (index >= 0 && index < array->length) {
|
||||
return array->items[index];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//@param index: set to -1 to put it at the end of the array
|
||||
void bool_array_set(bool_array *array, const bool value, int32_t index) {
|
||||
if (!array) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (array->capacity <= array->length && index <= 0 && index < array->length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (index == -1) {
|
||||
array->items[array->length - 1] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
array->items[index] = value;
|
||||
}
|
||||
|
||||
char char_array_get(const char_array *array, int32_t index) {
|
||||
if (index >= 0 && index < array->length) {
|
||||
return array->items[index];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
//@param index: set to -1 to put it at the end of the array
|
||||
void char_array_set(char_array *array, const char value, int32_t index) {
|
||||
if (!array) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (array->capacity <= array->length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (index == -1) {
|
||||
array->items[array->length - 1] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
array->items[index] = value;
|
||||
}
|
||||
|
||||
int8_t int8_array_get(const int8_array *array, int32_t index) {
|
||||
if (index >= 0 && index < array->length) {
|
||||
return array->items[index];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//@param index: set to -1 to put it at the end of the array
|
||||
void int8_array_set(int8_array *array, const int8_t value, int32_t index) {
|
||||
if (!array) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (array->capacity <= array->length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (index == -1) {
|
||||
array->items[array->length - 1] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
array->items[index] = value;
|
||||
}
|
||||
|
||||
int16_t int16_array_get(const int16_array *array, int32_t index) {
|
||||
if (index >= 0 && index < array->length) {
|
||||
return array->items[index];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//@param index: set to -1 to put it at the end of the array
|
||||
void int16_array_set(int16_array *array, const int16_t value, int32_t index) {
|
||||
if (!array) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (array->capacity <= array->length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (index == -1) {
|
||||
array->items[array->length - 1] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
array->items[index] = value;
|
||||
}
|
||||
|
||||
int32_t int32_array_get(const int32_array *array, int32_t index) {
|
||||
if (index >= 0 && index < array->length) {
|
||||
return array->items[index];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//@param index: set to -1 to put it at the end of the array
|
||||
void int32_array_set(int32_array *array, const int32_t value, int32_t index) {
|
||||
if (!array) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (array->capacity <= array->length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (index == -1) {
|
||||
array->items[array->length - 1] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
array->items[index] = value;
|
||||
}
|
||||
|
||||
int64_t int64_array_get(const int64_array *array, int32_t index) {
|
||||
if (index >= 0 && index < array->length) {
|
||||
return array->items[index];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//@param index: set to -1 to put it at the end of the array
|
||||
void int64_array_set(int64_array *array, const int64_t value, int32_t index) {
|
||||
if (!array) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (array->capacity <= array->length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (index == -1) {
|
||||
array->items[array->length - 1] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
array->items[index] = value;
|
||||
}
|
||||
|
||||
uint8_t uint8_array_get(const uint8_array *array, int32_t index) {
|
||||
if (index >= 0 && index < array->length) {
|
||||
return array->items[index];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//@param index: set to -1 to put it at the end of the array
|
||||
void uint8_array_set(uint8_array *array, const uint8_t value, int32_t index) {
|
||||
if (!array) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (array->capacity <= array->length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (index == -1) {
|
||||
array->items[array->length - 1] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
array->items[index] = value;
|
||||
}
|
||||
|
||||
uint16_t uint16_array_get(const uint16_array *array, int32_t index) {
|
||||
if (index >= 0 && index < array->length) {
|
||||
return array->items[index];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//@param index: set to -1 to put it at the end of the array
|
||||
void uint16_array_set(uint16_array *array, const uint16_t value, int32_t index) {
|
||||
if (!array) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (array->capacity <= array->length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (index == -1) {
|
||||
array->items[array->length - 1] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
array->items[index] = value;
|
||||
}
|
||||
|
||||
uint32_t uint32_array_get(const uint32_array *array, int32_t index) {
|
||||
if (index >= 0 && index < array->length) {
|
||||
return array->items[index];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//@param index: set to -1 to put it at the end of the array
|
||||
void uint32_array_set(uint32_array *array, const uint32_t value, int32_t index) {
|
||||
if (!array) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (array->capacity <= array->length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (index == -1) {
|
||||
array->items[array->length - 1] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
array->items[index] = value;
|
||||
}
|
||||
|
||||
uint64_t uint64_array_get(const uint64_array *array, int32_t index) {
|
||||
if (index >= 0 && index < array->length) {
|
||||
return array->items[index];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//@param index: set to -1 to put it at the end of the array
|
||||
void uint64_array_set(uint64_array *array, const uint64_t value, int32_t index) {
|
||||
if (!array) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (array->capacity <= array->length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (index == -1) {
|
||||
array->items[array->length - 1] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
array->items[index] = value;
|
||||
}
|
||||
|
||||
float float_array_get(const float_array *array, int32_t index) {
|
||||
if (index >= 0 && index < array->length) {
|
||||
return array->items[index];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//@param index: set to -1 to put it at the end of the array
|
||||
void float_array_set(float_array *array, const float value, int32_t index) {
|
||||
if (!array) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (array->capacity <= array->length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (index == -1) {
|
||||
array->items[array->length - 1] = value;
|
||||
array->length++;
|
||||
return;
|
||||
}
|
||||
|
||||
array->items[index] = value;
|
||||
}
|
||||
|
||||
void float_array_allocate(float_array *array, int32_t capacity) {
|
||||
array->items = calloc(capacity, sizeof(float));
|
||||
array->capacity = capacity;
|
||||
}
|
||||
|
||||
void float_array_init(float_array *array) {
|
||||
array->capacity = 0;
|
||||
array->length = 0;
|
||||
}
|
||||
|
||||
void float_array_free(float_array *array) {
|
||||
free(array->items);
|
||||
float_array_init(array);
|
||||
}
|
||||
|
||||
double double_array_get(const double_array *array, int32_t index) {
|
||||
if (index >= 0 && index < array->length) {
|
||||
return array->items[index];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//@param index: set to -1 to put it at the end of the array
|
||||
void double_array_set(double_array *array, const double value, int32_t index) {
|
||||
if (!array) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (array->capacity <= array->length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (index == -1) {
|
||||
array->items[array->length - 1] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
array->items[index] = value;
|
||||
}
|
||||
123
src/arrays.h
Normal file
123
src/arrays.h
Normal file
@@ -0,0 +1,123 @@
|
||||
#ifndef ARRAYS_H
|
||||
#define ARRAYS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// --- Boolean ---
|
||||
typedef struct {
|
||||
bool *items;
|
||||
int32_t length;
|
||||
int32_t capacity;
|
||||
} bool_array;
|
||||
|
||||
bool bool_array_get(const bool_array *array, int32_t index);
|
||||
void bool_array_set(bool_array *array, const bool value, int32_t index);
|
||||
|
||||
// --- Char (Strings/Bytes) ---
|
||||
typedef struct {
|
||||
char *items;
|
||||
int32_t length;
|
||||
int32_t capacity;
|
||||
} char_array;
|
||||
|
||||
char char_array_get(const char_array *array, int32_t index);
|
||||
void char_array_set(char_array *array, const char value, int32_t index);
|
||||
|
||||
// --- Signed Integers ---
|
||||
typedef struct {
|
||||
int8_t *items;
|
||||
int32_t length;
|
||||
int32_t capacity;
|
||||
} int8_array;
|
||||
|
||||
int8_t int8_array_get(const int8_array *array, int32_t index);
|
||||
void int8_array_set(int8_array *array, const int8_t value, int32_t index);
|
||||
|
||||
typedef struct {
|
||||
int16_t *items;
|
||||
int32_t length;
|
||||
int32_t capacity;
|
||||
} int16_array;
|
||||
|
||||
int16_t int16_array_get(const int16_array *array, int32_t index);
|
||||
void int16_array_set(int16_array *array, const int16_t value, int32_t index);
|
||||
|
||||
typedef struct {
|
||||
int32_t *items;
|
||||
int32_t length;
|
||||
int32_t capacity;
|
||||
} int32_array;
|
||||
|
||||
int32_t int32_array_get(const int32_array *array, int32_t index);
|
||||
void int32_array_set(int32_array *array, const int32_t value, int32_t index);
|
||||
|
||||
typedef struct {
|
||||
int64_t *items;
|
||||
int32_t length;
|
||||
int32_t capacity;
|
||||
} int64_array;
|
||||
|
||||
int64_t int64_array_get(const int64_array *array, int32_t index);
|
||||
void int64_array_set(int64_array *array, const int64_t value, int32_t index);
|
||||
|
||||
// --- Unsigned Integers ---
|
||||
typedef struct {
|
||||
uint8_t *items;
|
||||
int32_t length;
|
||||
int32_t capacity;
|
||||
} uint8_array;
|
||||
|
||||
uint8_t uint8_array_get(const uint8_array *array, int32_t index);
|
||||
void uint8_array_set(uint8_array *array, const uint8_t value, int32_t index);
|
||||
|
||||
typedef struct {
|
||||
uint16_t *items;
|
||||
int32_t length;
|
||||
int32_t capacity;
|
||||
} uint16_array;
|
||||
|
||||
uint16_t uint16_array_get(const uint16_array *array, int32_t index);
|
||||
void uint16_array_set(uint16_array *array, const uint16_t value, int32_t index);
|
||||
|
||||
typedef struct {
|
||||
uint32_t *items;
|
||||
int32_t length;
|
||||
int32_t capacity;
|
||||
} uint32_array;
|
||||
|
||||
uint32_t uint32_array_get(const uint32_array *array, int32_t index);
|
||||
void uint32_array_set(uint32_array *array, const uint32_t value, int32_t index);
|
||||
|
||||
typedef struct {
|
||||
uint64_t *items;
|
||||
int32_t length;
|
||||
int32_t capacity;
|
||||
} uint64_array;
|
||||
|
||||
uint64_t uint64_array_get(const uint64_array *array, int32_t index);
|
||||
void uint64_array_set(uint64_array *array, const uint64_t value, int32_t index);
|
||||
|
||||
// --- Floating Point ---
|
||||
typedef struct {
|
||||
float *items;
|
||||
int32_t length;
|
||||
int32_t capacity;
|
||||
} float_array;
|
||||
|
||||
float float_array_get(const float_array *array, int32_t index);
|
||||
void float_array_set(float_array *array, const float value, int32_t index);
|
||||
void float_array_allocate(float_array *array, int32_t capacity);
|
||||
void float_array_init(float_array *array);
|
||||
void float_array_free(float_array *array);
|
||||
|
||||
typedef struct {
|
||||
double *items;
|
||||
int32_t length;
|
||||
int32_t capacity;
|
||||
} double_array;
|
||||
|
||||
double double_array_get(const double_array *array, int32_t index);
|
||||
void double_array_set(double_array *array, const double value, int32_t index);
|
||||
|
||||
#endif
|
||||
14
src/exit_code.h
Normal file
14
src/exit_code.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef EXIT_CODE_H
|
||||
#define EXIT_CODE_H
|
||||
|
||||
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;
|
||||
|
||||
#endif
|
||||
@@ -3,16 +3,10 @@
|
||||
|
||||
#include "lapinfo.h"
|
||||
|
||||
void free_telemetry_info(TelemetryInfo *t) {
|
||||
free(t->data);
|
||||
free(t->validity);
|
||||
// free(t);
|
||||
}
|
||||
|
||||
void destroyLapinfo(LapInfo *info) {
|
||||
free_telemetry_info(&info->throttle_pos);
|
||||
free_telemetry_info(&info->brake_pos);
|
||||
free_telemetry_info(&info->steering_pos);
|
||||
free_telemetry_info(&info->speed);
|
||||
// free(info);
|
||||
free(info->throttle_pos.items);
|
||||
free(info->brake_pos.items);
|
||||
free(info->steering_pos.items);
|
||||
free(info->speed.items);
|
||||
free(info);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#pragma once
|
||||
#ifndef LAPINFO_H
|
||||
#define LAPINFO_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "arrays.h"
|
||||
|
||||
typedef enum {
|
||||
BOOL,
|
||||
INT,
|
||||
@@ -21,11 +24,13 @@ typedef struct {
|
||||
typedef struct {
|
||||
int lap_number;
|
||||
double start_time;
|
||||
TelemetryInfo throttle_pos; // freq: 50
|
||||
TelemetryInfo brake_pos; // freq: 50
|
||||
TelemetryInfo steering_pos; // freq: 100
|
||||
TelemetryInfo speed;
|
||||
float_array throttle_pos;
|
||||
float_array brake_pos;
|
||||
float_array steering_pos; // freq: 100
|
||||
float_array speed;
|
||||
} LapInfo;
|
||||
|
||||
void free_telemetry_info(TelemetryInfo *t);
|
||||
void destroyLapinfo(LapInfo *info);
|
||||
|
||||
#endif
|
||||
|
||||
342
src/main.c
342
src/main.c
@@ -2,218 +2,194 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "array_utils.h"
|
||||
#include "arrays.h"
|
||||
#include "exit_code.h"
|
||||
#include "lapinfo.h"
|
||||
|
||||
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);
|
||||
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]);
|
||||
} else {
|
||||
printf("NULL");
|
||||
}
|
||||
}
|
||||
|
||||
duckdb_destroy_data_chunk(&data_chunk);
|
||||
bool is_valid_path(const char *path) {
|
||||
if (path == NULL) {
|
||||
return false;
|
||||
}
|
||||
duckdb_destroy_result(&result);
|
||||
printf("\nNumber of iterations: %d, number of data points: %d\n", iterations, number_of_data_points);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
printf("Hello from HardCompound!\n");
|
||||
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");
|
||||
exit(1);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!is_valid_path(argv[1])) {
|
||||
printf("The file you gave is not valid. Exiting!");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
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);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
duckdb_connection conn;
|
||||
if (duckdb_connect(db, &conn) == DuckDBError) {
|
||||
printf("Error connecting to the duckdb database! Terminating!\n");
|
||||
exit(3);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
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
|
||||
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");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
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);
|
||||
session_data = calloc(lap_count, sizeof(LapInfo));
|
||||
lap_timestamps = calloc(lap_count, sizeof(double));
|
||||
|
||||
printf("Shutting down HardCompound!\n");
|
||||
if (!session_data) {
|
||||
printf("Session data failed to allocate!");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!lap_timestamps) {
|
||||
printf("Lap timestaps array failed to init!");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
duckdb_result lap_timestamps_res;
|
||||
if (duckdb_query(conn, "Select ts as DOUBLE from Lap\n", &lap_timestamps_res) == DuckDBError) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
// 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) {
|
||||
// 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");
|
||||
|
||||
printf("Closing database and any connection.\n");
|
||||
goto cleanup;
|
||||
exit:
|
||||
return EXIT_OK;
|
||||
cleanup:
|
||||
free(NULL);
|
||||
free(session_data);
|
||||
free(lap_timestamps);
|
||||
float_array_free(&throttle_data_all);
|
||||
float_array_free(&brake_data_all);
|
||||
float_array_free(&steering_data_all);
|
||||
float_array_free(&speed_data_all);
|
||||
duckdb_disconnect(&conn);
|
||||
duckdb_close(&db);
|
||||
|
||||
return 0;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
111
src/tables.c
Normal file
111
src/tables.c
Normal 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]);
|
||||
Reference in New Issue
Block a user