From 3696ca684fa8f95985846eed160b654b146872a4 Mon Sep 17 00:00:00 2001 From: augustin64 Date: Wed, 12 Jul 2023 11:08:40 +0200 Subject: [PATCH] first commit --- .gitignore | 5 ++ Makefile | 19 ++++++ src/db.c | 140 +++++++++++++++++++++++++++++++++++++++++ src/include/colors.h | 15 +++++ src/include/config.h | 7 +++ src/include/db.h | 46 ++++++++++++++ src/include/struct.h | 15 +++++ src/include/tasks.h | 10 +++ src/main.c | 145 +++++++++++++++++++++++++++++++++++++++++++ src/tasks.cpp | 46 ++++++++++++++ 10 files changed, 448 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 src/db.c create mode 100644 src/include/colors.h create mode 100644 src/include/config.h create mode 100644 src/include/db.h create mode 100644 src/include/struct.h create mode 100644 src/include/tasks.h create mode 100644 src/main.c create mode 100644 src/tasks.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7cb4fc6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +takl.sqlite3 +takl + +out +.vscode \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..57b59f2 --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +FLAGS = -g -Wall -Wextra -lsqlite3 +LD_FLAGS = + + +$(shell mkdir -p out) + + +out/%.o: src/%.c + $(CC) -c $(FLAGS) $^ -o $@ + +out/%.o: src/%.cpp + $(CXX) -c $(FLAGS) $^ -o $@ + +takl: out/main.o out/db.o out/tasks.o + $(CXX) $(FLAGS) $(LD_FLAGS) $^ -o $@ + +clean: + rm out -r + rm ./takl \ No newline at end of file diff --git a/src/db.c b/src/db.c new file mode 100644 index 0000000..7179b1e --- /dev/null +++ b/src/db.c @@ -0,0 +1,140 @@ +/* +Fonctions d'interaction avec la base de données +*/ +#include +#include +#include +#include +#include +#include + +#include "include/colors.h" +#include "include/config.h" +#include "include/struct.h" + + +sqlite3* get_db() { + sqlite3* db; + + if (access(DB_FILE, F_OK) != 0) { + // Create DB + sqlite3_open(DB_FILE, &db); + + char* zErrMsg = NULL; + int ret = sqlite3_exec( + db, + "CREATE TABLE tasks ( \ + id INTEGER PRIMARY KEY,\ + text TEXT NOT NULL,\ + done INTEGER, \ + due_to INTEGER \ + );", + NULL, + NULL, + &zErrMsg + ); + + if (ret != SQLITE_OK) { + fprintf(stderr, "(db creation) SQL error: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + } + + sqlite3_close(db); + + printf(GREEN "OK" RESET " Base de données créée\n"); + } + + int ret = sqlite3_open(DB_FILE, &db); + if (ret != SQLITE_OK) { + fprintf(stderr, "(get_db) Unable to open db\n"); + } + + return db; +} + + +int add_task(task_t t) { //TODO + sqlite3* db = get_db(); + + sqlite3_close(db); + (void)t; + return 1; +} + +int update_task(task_t t) { //TODO + (void)t; + return 1; +} + + +void get_task(int id, task_t* t) { + sqlite3* db = get_db(); + sqlite3_stmt* stmt; + + int ret = sqlite3_prepare_v2(db, "SELECT id, text, done, due_to FROM tasks WHERE id=?1;", -1, &stmt, 0); + + if (ret != SQLITE_OK) { + printf("(get_task) failure fetching data\n"); + exit(1); + } + + + char str_id[10]; + sprintf(str_id, "%d", id); + sqlite3_bind_text(stmt, 1, str_id, -1, SQLITE_STATIC); + + ret = sqlite3_step(stmt); + if (ret == SQLITE_ROW) { + t->id = strtol((char*)sqlite3_column_text(stmt, 0), NULL, 10); + t->done = strtol((char*)sqlite3_column_text(stmt, 2), NULL, 10); + t->due_to = strtol((char*)sqlite3_column_text(stmt, 3), NULL, 10); + + char* text = (char*)sqlite3_column_text(stmt, 1); + t->text = malloc(sizeof(char)*(strlen(text)+1)); + strcpy(t->text, text); + } + + sqlite3_finalize(stmt); + sqlite3_close(db); + + // t.id will be (-1) if not found +} + +int list_tasks() { + sqlite3* db = get_db(); + sqlite3_stmt *stmt; + + int ret = sqlite3_prepare_v2(db, "SELECT id, text, done, due_to FROM tasks;", -1, &stmt, NULL); + + if (ret != SQLITE_OK) { + printf("(get_task) failure fetching data\n"); + return 1; + } + + while (sqlite3_step(stmt) == SQLITE_ROW) { + task_t t; + + t.id = strtol((char*)sqlite3_column_text(stmt, 0), NULL, 10); + t.text = (char*)sqlite3_column_text(stmt, 1); + t.done = strtol((char*)sqlite3_column_text(stmt, 2), NULL, 10); + t.due_to = strtol((char*)sqlite3_column_text(stmt, 3), NULL, 10); + //* Warning: t just lives here (particularly t.text) + + if (t.done) { + printf(BOLD GREEN); + } else { + printf(BOLD YELLOW); + } + + printf("[%d]" RESET " %s\n", t.id, t.text); + } + + sqlite3_finalize(stmt); + sqlite3_close(db); + + return 0; +} + +int get_new_task_id() { + return rand()%10000; +} \ No newline at end of file diff --git a/src/include/colors.h b/src/include/colors.h new file mode 100644 index 0000000..ce744e3 --- /dev/null +++ b/src/include/colors.h @@ -0,0 +1,15 @@ +#ifndef DEF_COLORS_H +#define DEF_COLORS_H + +#define RESET "\033[0m" +#define BLACK "\033[30m" /* Black */ +#define RED "\033[31m" /* Red */ +#define GREEN "\033[32m" /* Green */ +#define YELLOW "\033[33m" /* Yellow */ +#define BLUE "\033[34m" /* Blue */ +#define MAGENTA "\033[35m" /* Magenta */ +#define CYAN "\033[36m" /* Cyan */ +#define WHITE "\033[37m" /* White */ +#define BOLD "\033[1m" /* BOLD */ + +#endif \ No newline at end of file diff --git a/src/include/config.h b/src/include/config.h new file mode 100644 index 0000000..3aac598 --- /dev/null +++ b/src/include/config.h @@ -0,0 +1,7 @@ +#ifndef DEF_CONFIG_H +#define DEF_CONFIG_H + +#define VERSION "0.0.0" +#define DB_FILE "takl.sqlite3" + +#endif \ No newline at end of file diff --git a/src/include/db.h b/src/include/db.h new file mode 100644 index 0000000..57e2175 --- /dev/null +++ b/src/include/db.h @@ -0,0 +1,46 @@ +#include "struct.h" + +#ifndef DEF_DB_H +#define DEF_DB_H + +#ifdef __cplusplus +extern "C" { +#endif +/* +Création de la base de données +Arrête le programme en cas d'échec +*/ +void create_db(); + +/* +Ajouter une tâche à la base de données. +Le numéro de tâche ne doit pas déjà être utilisé +Renvoie 0 si il n'y a pas d'erreur +*/ +int add_task(task_t t); + +/* +Mettre à jour une tâche +*/ +int update_task(task_t t); + +/* +Copie la tâche [id] dans *t si elle existe +*/ +void get_task(int id, task_t* t); + +/* +Liste les tâches dans un format prédéfini +*/ +int list_tasks(); + +/* +Renvoie un identifiant de tâche encore non utilisé +*/ +int get_new_task_id(); + + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/src/include/struct.h b/src/include/struct.h new file mode 100644 index 0000000..f607d59 --- /dev/null +++ b/src/include/struct.h @@ -0,0 +1,15 @@ +#include +#include + +#ifndef DEF_STRUCT_H +#define DEF_STRUCT_H + +struct task { + int id; + char* text; + bool done; + time_t due_to; +}; +typedef struct task task_t; + +#endif \ No newline at end of file diff --git a/src/include/tasks.h b/src/include/tasks.h new file mode 100644 index 0000000..738b724 --- /dev/null +++ b/src/include/tasks.h @@ -0,0 +1,10 @@ +#include "struct.h" + +#ifndef DEF_TASKS_H +#define DEF_TASKS_H + +task_t create_task(char* text, time_t due_to); +void print_task(task_t task); + + +#endif \ No newline at end of file diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..178e346 --- /dev/null +++ b/src/main.c @@ -0,0 +1,145 @@ +#include +#include +#include +#include + +#include "include/colors.h" +#include "include/config.h" +#include "include/tasks.h" +#include "include/db.h" + +void help(char* name) { + printf(BLUE "\t-- TaKl " VERSION " --\n" RESET); + printf("Utilisation: %s ( list | info | add | rm | done )\n", name); + printf("\tadd [date]\n"); + printf("\tFormat de la date:\n"); + printf("\t\tRelatif: min+%%d, h+%%d, j+%%d\n"); + printf("\t\tAbsolu: dd/mm (pas de changement d'année pour l'instant\n"); + printf("\tinfo \n"); + printf("\tdone \n"); + printf("\trm \n"); +} + + +time_t parseDateTime(const char* input) { + struct tm date = {0}; // Initialize with zeros + + // Get current time + time_t now = time(NULL); + struct tm* current_time = localtime(&now); + + // Copy current time to 'date' structure + date.tm_year = current_time->tm_year; + date.tm_mon = current_time->tm_mon; + date.tm_mday = current_time->tm_mday; + date.tm_hour = current_time->tm_hour; + date.tm_min = current_time->tm_min; + date.tm_sec = current_time->tm_sec; + + + int offset; + // Accepted formats: min+%d, h+%d, j+%d + if (sscanf(input, "min+%d", &offset)) { + date.tm_min += offset; + return mktime(&date); + } else if (sscanf(input, "h+%d", &offset)) { + date.tm_hour += offset; + return mktime(&date); + } else if (sscanf(input, "j+%d", &offset)) { + date.tm_mday += offset; + return mktime(&date); + } + + // Check if the input format is "dd/mm" + if (sscanf(input, "%d/%d", &date.tm_mday, &date.tm_mon) == 2) { + // Set the year to the current year + date.tm_year = current_time->tm_year; + // Adjust month and day values to be zero-based + date.tm_hour = 0; + date.tm_min = 0; + date.tm_sec = 0; + // Convert 'date' structure to 'time_t' value + return mktime(&date); + } + + return -1; // Return an error value +} + + +int add(int argc, char* argv[]) { + if (argc < 3) { + printf(BOLD YELLOW "Argument manquant\n" RESET); + help(argv[0]); + return 1; // TODO: trouver le bon code d'erreur + } + + time_t due_to = 0; + if (argc > 3) { + due_to = parseDateTime(argv[3]); + + if (due_to == -1) { + printf(BOLD YELLOW "Échéance invalide, la tâche sera créé sans échéance.\n" RESET); + due_to = 0; + } + } + + task_t t = create_task(argv[2], due_to); + + if (add_task(t) != 0) { + printf("Erreur lors de l'ajout à la base de données\n"); + return 1; + } + + printf(BOLD YELLOW "[%d]" RESET " ajoutée\n", t.id); + return 0; +} + + +int info(int argc, char* argv[]) { + if (argc < 3) { + printf(BOLD YELLOW "Argument manquant\n" RESET); + help(argv[0]); + return 1; + } + + int id = strtol(argv[2], NULL, 10); + + task_t t; + t.id = -1; + get_task(id, &t); + + if (t.id == -1) { + printf(BOLD YELLOW "Tâche inexistante. Vérifiez que l'identifiant est bien correct\n" RESET); + exit(1); + } + + print_task(t); + + free(t.text); + return 0; +} + + +int main(int argc, char* argv[]) { + if (argc <= 1) { + help(argv[0]); + return 0; + } + + if (!strcmp(argv[1], "add")) { + return add(argc, argv); + } else if (!strcmp(argv[1], "list")) { + return list_tasks(); + } else if (!strcmp(argv[1], "info")) { + return info(argc, argv); + } else if (!strcmp(argv[1], "done")) { //TODO + printf("Not Implemented\n"); + return 1; + } else if (!strcmp(argv[1], "rm")) { //TODO + printf("Not Implemented\n"); + return 1; + } + + printf(YELLOW "Option invalide " BOLD "%s\n" RESET, argv[1]); + return 1; +} \ No newline at end of file diff --git a/src/tasks.cpp b/src/tasks.cpp new file mode 100644 index 0000000..1dafdb2 --- /dev/null +++ b/src/tasks.cpp @@ -0,0 +1,46 @@ +/* +Fonctions de création/ modification d'objet tâches +*/ +#include +#include +#include + +#include "include/db.h" +#include "include/struct.h" +#include "include/colors.h" + +extern "C" +task_t create_task(char* text, time_t due_to) { + task_t task; + + task.id = get_new_task_id(); + task.text = text; + task.done = false; + task.due_to = due_to; + + return task; +} + +extern "C" +void print_task(task_t task) { + printf(YELLOW "=== Tâche " BOLD "[%d]" RESET YELLOW " ===\n" RESET, task.id); + printf(BOLD "%s\n" RESET, task.text); + + printf("Statut: "); + if (task.done) { + printf(GREEN "Complétée\n" RESET); + } else { + printf(BLUE "À faire\n" RESET); + } + + if (task.due_to != 0) { + struct tm * timeinfo; + char buffer[80]; + + timeinfo = localtime(&task.due_to); + + strftime(buffer,sizeof(buffer),"%d-%m-%Y %H:%M:%S",timeinfo); + + printf("Dûe le %s\n", buffer); + } +} \ No newline at end of file