diff --git a/leaderboards.c b/leaderboards.c new file mode 100644 index 0000000..f94b249 --- /dev/null +++ b/leaderboards.c @@ -0,0 +1,77 @@ + +#include "leaderboards.h" +#include "types.h" +#include "util/vector.h" +#include "util/tree.h" +#include "util/assert.h" +#include + + +System_Leaderboards *lboard_NewSystem(App *super) { + System_Leaderboards *sys = zero_malloc(sizeof(System_Leaderboards)); + sys->super = super; + sys->levelnames = vector_Create(sizeof(char *)); + sys->records = vector_Create(sizeof(tree_Tree *)); + return sys; +} + +void lboard_DeleteSystem(System_Leaderboards *sys) { + // Free level names + for (int i = 0; i < vector_Size(sys->levelnames); i++) { + char *str = *(char **)vector_At(sys->levelnames, i); + free(str); + } + vector_Destroy(sys->levelnames); + + // Free records + for (int i = 0; i < vector_Size(sys->records); i++) { + tree_Tree *tree = *(tree_Tree **)vector_At(sys->levelnames, i); + for (tree_Node *node = tree_FirstNode(tree); node != NULL; node = tree_Node_Next(node)) { + vector_Vector *names = *(vector_Vector **)node->data; + if (names) { + for (int j = 0; j < vector_Size(names); j++) + free(*(void **)vector_At(names, j)); + vector_Destroy(names); + } + } + tree_Destroy(tree); + } + vector_Destroy(sys->records); + + free(sys); +} + + +int lboard_FindLevel(System_Leaderboards *sys, const char *level) { + for (int i = 0; i < vector_Size(sys->levelnames); i++) { + char *str = *(char **)vector_At(sys->levelnames, i); + if (strcmp(str, level) == 0) + return i; + } + return -1; +} + +void lboard_Insert(System_Leaderboards *sys, const char *level, uintptr_t time_millisec, const char *name) { + int indice = lboard_FindLevel(sys, level); + if (indice == -1) { + // Append a new one + char *level_copy = copy_malloc(level); + tree_Tree *empty_tree = tree_Create(sizeof(vector_Vector *)); + vector_Push(sys->levelnames, level_copy); + vector_Push(sys->records, &empty_tree); + ASSERT(vector_Size(sys->levelnames) == vector_Size(sys->records)); + indice = vector_Size(sys->levelnames) - 1; + } + + tree_Tree *tree = *(tree_Tree **)vector_At(sys->records, indice); + + // Insert or find this node + bool added; + tree_Node *node = tree_Insert(tree, time_millisec, &added); + if (added) + // Brand new node, create a new vector of names + *((vector_Vector **)node->data) = vector_Create(sizeof(char *)); + // Insert this name + char *name_copy = copy_malloc(name); + vector_Push(*(vector_Vector **)node->data, &name_copy); +} diff --git a/leaderboards.h b/leaderboards.h new file mode 100644 index 0000000..322d992 --- /dev/null +++ b/leaderboards.h @@ -0,0 +1,42 @@ +#pragma once + +#include "util/vector.h" +#include "util/tree.h" +#include "types.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct _App App; + + +// Leaderboards keep track of level-gametime-username records in leaderboards.txt. +typedef struct { + App *super; + + vector_Vector *levelnames; // vector of allocated char* strings + vector_Vector *records; // vector of tree_Tree* of gametime(milliseconds)->vector of allocated char* strings +} System_Leaderboards; + + +System_Leaderboards *lboard_NewSystem(App *super); +void lboard_DeleteSystem(System_Leaderboards *sys); + +// Find the indice at which this level is located +// Returns -1 if not found +int lboard_FindLevel(System_Leaderboards *sys, const char *level); +// Insert a record. +void lboard_Insert(System_Leaderboards *sys, const char *level, uintptr_t time_millisec, const char *name); + + +// This should only be called on an empty (newly created) leaderboard. +void lboard_LoadFromFile(System_Leaderboards *sys, const char *filename); +void lboard_SaveToFile(System_Leaderboards *sys, const char *filename); + + +#ifdef __cplusplus +} +#endif diff --git a/leaderboards_file.c b/leaderboards_file.c new file mode 100644 index 0000000..2abe05c --- /dev/null +++ b/leaderboards_file.c @@ -0,0 +1,27 @@ + +#include "leaderboards.h" +#include + + +void lboard_LoadFromFile(System_Leaderboards *sys, const char *filename) { + FILE *f = fopen(filename, "r"); + if (!f) { + WARN("failed to open file\"%s\"", filename); + return; + } + + + // Read every line + char linebuf[512]; + memset(linebuf, 0, sizeof(linebuf)); + while (!feof(f) && fgets(linebuf, sizeof(linebuf), f)) { + while (linebuf[strlen(linebuf) - 1] == '\n') + linebuf[strlen(linebuf) - 1] = '\0'; + + // Skip empty lines + if (strlen(linebuf) == 0) + continue; + } +} +void lboard_SaveToFile(System_Leaderboards *sys, const char *filename) { +}