aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordam <dam@gudinoff>2022-09-28 22:37:22 +0000
committerdam <dam@gudinoff>2022-09-28 22:37:22 +0000
commit8d2f93fe0497c322f2243cad123b70543cab9eac (patch)
tree2974e2a45e382042b8c6108f31509ae846b15980
parent47c212995981145cdf620144c8ce8de7b1e5d634 (diff)
downloadtask-time-tracker-8d2f93fe0497c322f2243cad123b70543cab9eac.tar.zst
task-time-tracker-8d2f93fe0497c322f2243cad123b70543cab9eac.zip
Preparing to store archive as CSV to allow appending to it.
-rw-r--r--main.c73
1 files changed, 55 insertions, 18 deletions
diff --git a/main.c b/main.c
index ec3fb5f..c32df1c 100644
--- a/main.c
+++ b/main.c
@@ -17,14 +17,14 @@
#define MAX_TASK_NAME 58 // Maximum task name length, including null-terminator.
#define FIRST_DAY_OF_WEEK 1 // (0-6, Sunday = 0)
-#define WEEK_DAYS 7 // Why not?
+#define WEEK_DAYS 7 // Just to avoid magic numbers.
#define LOG_FILE_NAME "log.txt"
#define DB_BIN_PATH_NAME "./database.bin"
-#define AR_BIN_PATH_NAME "./archive.bin"
+#define AR_CSV_PATH_NAME "./archive.csv"
typedef struct /*__attribute__((__packed__))*/ {
- int64_t times[7];
+ int64_t times[WEEK_DAYS];
char name[MAX_TASK_NAME];
} task_t; // TODO Rename to task_st
@@ -35,7 +35,7 @@ typedef struct /*__attribute__((__packed__))*/ {
ptrdiff_t active_task;
ptrdiff_t selected_task;
int64_t modified_on;
- int64_t total_times[7];
+ int64_t total_times[WEEK_DAYS];
} database_t; // TODO Rename to database_st
#define DB_FILE_SIGN_STR "TTT:B:01"
@@ -52,6 +52,10 @@ database_t database;
database_t archive;
database_t *db;
+char *string_buffer;
+int size_x, size_y, pos_x, pos_y;
+
+
// Given an UTF8 encoded string, truncate it to length without breaking any UTF8 character.
// The string should have capacity for at least length number of items.
// The terminating null byte ('\0') is included in length.
@@ -254,7 +258,7 @@ bool add_task(database_t *db, task_t *task) {
memcpy(new_task, task, SIZEOF_TASK_T);
// Add task timer values to total timers.
- for (int idx = 0; idx < 7; idx++) {
+ for (int idx = 0; idx < WEEK_DAYS; idx++) {
// db->total_times[idx] += task->times[idx]; TODO
db->total_times[idx] = add_time(db->total_times[idx], task->times[idx]);
}
@@ -270,7 +274,7 @@ bool delete_task(database_t *db, task_t *task) {
assert(task >= db->tasks && task < &db->tasks[db->count]);
// Remove task timer values from total timers.
- for (int idx = 0; idx < 7; idx++) {
+ for (int idx = 0; idx < WEEK_DAYS; idx++) {
// db->total_times[idx] -= task->times[idx]; TODO
db->total_times[idx] = sub_time(db->total_times[idx], task->times[idx]);
}
@@ -470,7 +474,7 @@ bool import_from_csv(database_t *db, const char *path_name) {
&task->times[4],
&task->times[5],
&task->times[6]
- ) != 7) {
+ ) != WEEK_DAYS) {
replace_char(csv_buffer, '\n', ' ');
fprintf(stderr, "Discarding invalid line '%s' and continuing.\n", csv_buffer);
delete_task(db, task);
@@ -478,7 +482,7 @@ bool import_from_csv(database_t *db, const char *path_name) {
}
// Add task timer values to total timers.
- for (int idx = 0; idx < 7; idx++) {
+ for (int idx = 0; idx < WEEK_DAYS; idx++) {
// db->total_times[idx] += task->times[idx]; TODO
db->total_times[idx] = add_time(db->total_times[idx], task->times[idx]);
}
@@ -490,6 +494,41 @@ bool import_from_csv(database_t *db, const char *path_name) {
return true;
}
+bool append_to_csv(task_t *task, const char *path_name) {
+ assert(task != NULL);
+ assert(path_name != NULL);
+
+ FILE *file = fopen(path_name, "a+");
+ if (file == NULL) {
+ fprintf(stderr, "Failed to open file '%s' while appending to CSV: %s.\n", path_name, strerror(errno));
+ return false;
+ }
+
+ char last_char;
+ fseek(file, -1, SEEK_END);
+ fread(&last_char, sizeof(char), 1, file);
+ if (last_char != '\n') {
+ fprintf(file, "\n");
+ }
+
+ char name[MAX_TASK_NAME];
+ memcpy(name, task->name, MAX_TASK_NAME);
+ replace_char(name, ',', ' ');
+ fprintf(file, "%s,%" PRId64 ",%" PRId64 ",%" PRId64 ",%" PRId64 ",%" PRId64 ",%" PRId64 ",%" PRId64 "\n",
+ name,
+ task->times[0],
+ task->times[1],
+ task->times[2],
+ task->times[3],
+ task->times[4],
+ task->times[5],
+ task->times[6]
+ );
+
+ fclose(file);
+ return true;
+}
+
void update_timers(database_t *db) {
// Get current UTC time.
@@ -535,7 +574,7 @@ void update_total_timers(database_t *db) {
int64_t *d4 = &db->total_times[4];
int64_t *d5 = &db->total_times[5];
int64_t *d6 = &db->total_times[6];
- memset(db->total_times, 7, sizeof(int64_t));
+ memset(db->total_times, WEEK_DAYS, sizeof(int64_t));
for (size_t idx = 0; idx < db->count; idx++) {
int64_t *times = db->tasks[idx].times;
@@ -623,8 +662,6 @@ void prototype(test_et level) {
}
-char *string_buffer;
-int size_x, size_y, pos_x, pos_y;
#define NUM_OF_COLUMNS 9
@@ -1114,14 +1151,14 @@ int main(int argc, char *argv[]) {
case KEY_BACKSPACE:
if (db == &database) {
- if (load_database(&archive, AR_BIN_PATH_NAME) == false) {
- store_database(&archive, AR_BIN_PATH_NAME);
+ if (load_database(&archive, AR_CSV_PATH_NAME) == false) {
+ store_database(&archive, AR_CSV_PATH_NAME);
}
db = &archive;
db->active_task = -1; // TODO This should not be necessary.
}
else {
- store_database(&archive, AR_BIN_PATH_NAME);
+ store_database(&archive, AR_CSV_PATH_NAME);
reset_database(&archive);
db = &database;
}
@@ -1138,15 +1175,15 @@ int main(int argc, char *argv[]) {
// instead of loading adding and storing every single time.
// If the archive was in CSV, we could simply append to it. Let's do this!
if (db == &database) {
- if (load_database(&archive, AR_BIN_PATH_NAME) == false) {
- store_database(&archive, AR_BIN_PATH_NAME);
+ if (load_database(&archive, AR_CSV_PATH_NAME) == false) {
+ store_database(&archive, AR_CSV_PATH_NAME);
}
}
database_t *target = (db == &database ? &archive : &database);
add_task(target, selected_task);
delete_task(db, selected_task);
if (db == &database) {
- store_database(&archive, AR_BIN_PATH_NAME);
+ store_database(&archive, AR_CSV_PATH_NAME);
reset_database(&archive);
}
break;
@@ -1210,7 +1247,7 @@ int main(int argc, char *argv[]) {
update_timers(&database);
store_database(&database, DB_BIN_PATH_NAME);
if (db == &archive) {
- store_database(&archive, AR_BIN_PATH_NAME);
+ store_database(&archive, AR_CSV_PATH_NAME);
}
free_memory();
endwin();