linije

Клон игре Color lines
git clone https://git.sr.ht/~strahinja/linije
Дневник | Датотеке | Референце | ПРОЧИТАЈМЕ | ЛИЦЕНЦА

чување 332a5c17d976bc0eaba96a04b9c2cdc7a181339c
родитељ ca58f46524a0bf0ee04eb4ea7957e0e1c3a7b999
Аутор: Страхиња Радић <sr@strahinja.org>
Датум:   Tue, 25 Aug 2026 18:40:30 +0000

Add timestamps to hall of fame (backwards incompatible with HOF file)

Diffstat:
MTODO.done | 2++
Mhiscore.c | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Mhiscore.h | 12+++++++++---
Mlinije.c | 14++++++++------
измењених датотека: 4, додавања: 89(+), брисања: 15(-)

diff --git a/TODO.done b/TODO.done @@ -1,6 +1,8 @@ Done or canceled todos ====================== +[x] Add timestamps to hall of fame + [x] High score? [x] Updating high score [x] Saving high score to a file diff --git a/hiscore.c b/hiscore.c @@ -13,15 +13,16 @@ #include <stdlib.h> #include <string.h> #include <sys/stat.h> +#include <time.h> int hs_add(struct HiScoreEntry** table, const char* name, const int name_len, - const unsigned long int score) + const unsigned long int score, const char* timestamp) { struct HiScoreEntry* p = NULL; struct HiScoreEntry* q = NULL; - assert((table != NULL) && (*table != NULL)); + assert((table != NULL) && (*table != NULL) && (timestamp != NULL)); p = *table; while (p < *table + HI_SCORE_MAX) @@ -35,7 +36,7 @@ hs_add(struct HiScoreEntry** table, const char* name, const int name_len, hs_assign_ss(q - 1, q); q--; } - hs_assign_ps(name, name_len, score, p); + hs_assign_ps(name, name_len, score, timestamp, p); break; } p++; @@ -45,13 +46,43 @@ hs_add(struct HiScoreEntry** table, const char* name, const int name_len, } int +hs_add_now(struct HiScoreEntry** table, const char* name, const int name_len, + const unsigned long int score) +{ + struct tm* ns = NULL; + char sn[TIMESTAMP_MAX]; + time_t nt; + nt = time(NULL); + if (!(ns = gmtime(&nt))) + { + SDL_LogError(SDL_LOG_CATEGORY_ERROR, "gmtime: %s", + strerror(errno)); + return 1; + } + if (!strftime(sn, TIMESTAMP_MAX, "%Y-%m-%d %H:%M", ns)) + { + SDL_LogError(SDL_LOG_CATEGORY_ERROR, "strftime failed"); + return 1; + } + return hs_add(table, name, name_len, score, sn); +} + +int hs_assign_ps(const char* name, const int name_len, - const unsigned long int score, struct HiScoreEntry* dest) + const unsigned long int score, const char* timestamp, + struct HiScoreEntry* dest) { char* new_name = NULL; assert(dest != NULL); + if (!timestamp) + { + SDL_LogError(SDL_LOG_CATEGORY_ERROR, + "hs_asssign_ps: timestamp is null!"); + return 1; + } + if (!name || !name_len) goto hs_assign_ps_skip_name; @@ -66,6 +97,7 @@ hs_assign_ps(const char* name, const int name_len, } if (!memccpy(dest->name, name, 0, name_len)) dest->name[name_len] = 0; + /*SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "hs_assign_ps: dest->name = {%s} [%d]", dest->name, dest->name_len);*/ @@ -73,6 +105,8 @@ hs_assign_ps(const char* name, const int name_len, hs_assign_ps_skip_name: dest->name_len = name_len; dest->score = score; + if (!memccpy(dest->timestamp, timestamp, 0, TIMESTAMP_MAX)) + dest->timestamp[TIMESTAMP_MAX - 1] = 0; return 0; } @@ -83,6 +117,10 @@ hs_assign_ss(const struct HiScoreEntry* source, struct HiScoreEntry* dest) assert((source != NULL) && (dest != NULL)); + if (!*source->timestamp) + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "hs_asssign_ss: timestamp is empty!"); + if (!source->name) goto hs_assign_ss_skip_name; @@ -101,6 +139,8 @@ hs_assign_ss(const struct HiScoreEntry* source, struct HiScoreEntry* dest) hs_assign_ss_skip_name: dest->name_len = source->name_len; dest->score = source->score; + if (!memccpy(dest->timestamp, source->timestamp, 0, TIMESTAMP_MAX)) + dest->timestamp[TIMESTAMP_MAX - 1] = 0; return 0; } @@ -123,6 +163,7 @@ hs_init(struct HiScoreEntry** table) memccpy(p->name, HI_SCORE_DEFAULT_NAME, 0, HI_SCORE_NAME_MAX); p->name_len = len - 1; p->score = 0; + memccpy(p->timestamp, DEFAULT_TIMESTAMP, 0, TIMESTAMP_MAX); } return 0; @@ -190,6 +231,8 @@ hs_get_hofdir_error: * | name (HI_SCORE_NAME_MAX unsigned chars) | * |-----------------------------------------------------------| * | score 4-byte unsigned long int BE | + * |-----------------------------------------------------------| + * | timestamp (TIMESTAMP_MAX unsigned chars) | * `-----------------------------------------------------------' */ int @@ -197,7 +240,8 @@ hs_load(struct HiScoreEntry** table, const char* hofdir) { FILE* infile = NULL; char* filename = NULL; - char name[HI_SCORE_NAME_MAX + 1]; + char name[HI_SCORE_NAME_MAX]; + char timestamp[TIMESTAMP_MAX]; int filename_size = PATH_MAX + 1; int name_len, i, ib; unsigned long int score; @@ -247,7 +291,17 @@ hs_load(struct HiScoreEntry** table, const char* hofdir) } score |= SETBYTENOF4(byte, ib); } - hs_add(table, name, name_len, score); + if (fread(timestamp, TIMESTAMP_MAX, 1, infile) < 1) + { + if (feof(infile)) + continue; + else + { + fclose(infile); + goto hs_load_error; + } + } + hs_add(table, name, name_len, score, timestamp); i++; } @@ -307,6 +361,16 @@ hs_write(struct HiScoreEntry* table, const char* hofdir) goto hs_write_error; } } + for (i = 0; i < TIMESTAMP_MAX; i++) + { + errno = 0; + byte = p->timestamp[i]; + if (fwrite(&byte, 1, 1, outfile) < 1) + { + fclose(outfile); + goto hs_write_error; + } + } } if (fclose(outfile) == EOF) goto hs_write_error; diff --git a/hiscore.h b/hiscore.h @@ -2,9 +2,11 @@ * any later version. Copyright (C) 2025 Страхиња Радић. * See the file LICENSE for exact copyright and license details. */ +#define DEFAULT_TIMESTAMP "1970-01-01 00:00" #define HI_SCORE_DEFAULT_NAME "Unknown player" #define HI_SCORE_MAX 10 #define HI_SCORE_NAME_MAX 40 +#define TIMESTAMP_MAX 17 #ifndef PATH_MAX #define PATH_MAX _POSIX_PATH_MAX @@ -17,15 +19,19 @@ struct HiScoreEntry { char* name; int name_len; + char timestamp[TIMESTAMP_MAX]; unsigned long int score; }; int hs_add(struct HiScoreEntry** table, const char* name, const int name_len, - const unsigned long int score); + const unsigned long int score, const char* timestamp); +int hs_add_now(struct HiScoreEntry** table, const char* name, + const int name_len, const unsigned long int score); int hs_assign(const struct HiScoreEntry* source, struct HiScoreEntry* dest); -int hs_assign_ss(const struct HiScoreEntry* source, struct HiScoreEntry* dest); int hs_assign_ps(const char* name, const int name_len, - const unsigned long int score, struct HiScoreEntry* dest); + const unsigned long int score, const char* timestamp, + struct HiScoreEntry* dest); +int hs_assign_ss(const struct HiScoreEntry* source, struct HiScoreEntry* dest); char* hs_get_hofdir(void); int hs_init(struct HiScoreEntry** table); int hs_load(struct HiScoreEntry** table, const char* hofdir); diff --git a/linije.c b/linije.c @@ -1265,7 +1265,7 @@ input_name_callback(struct State* state) for (i = 0; i < state->player_name_length; i++) SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "%d", state->player_name[i]); - hs_add(&state->hall_of_fame, state->player_name, + hs_add_now(&state->hall_of_fame, state->player_name, state->player_name_length, state->score); if (hs_write(state->hall_of_fame, hs_get_hofdir())) @@ -1504,11 +1504,11 @@ prepare_hof_dialog(struct State* state, const int show) e = &state->hall_of_fame[i]; repeat_char(&dots, '.', HOF_DIALOG_MAX_LINE_LEN - 4 - e->name_len - - num_size(e->score) - 1); + - num_size(e->score) - 1 - TIMESTAMP_MAX - 1); /* +4 is the number of special characters (the number of visible * characters remains HOF_DIALOG_MAX_LINE_LEN) */ - hof_line_len = HOF_DIALOG_MAX_LINE_LEN + 4; + hof_line_len = HOF_DIALOG_MAX_LINE_LEN + 5; /* For the first HOF_STANDOUT_ENTRIES entries, the number of * special characters increases by 1 */ @@ -1516,9 +1516,11 @@ prepare_hof_dialog(struct State* state, const int show) hof_line_len++; snprintf(hof_text[HOF_SCORES_START_IDX + i], hof_line_len, - "\4%2d. %s%s\4%s\2%s%lu", i + 1, + "\4%2d. %s%s\4%s\2%s%lu %s%s", i + 1, i < HOF_STANDOUT_ENTRIES ? "\1" : "\2", e->name, dots, - i < HOF_STANDOUT_ENTRIES ? "\1" : "", e->score); + i < HOF_STANDOUT_ENTRIES ? "\1" : "", e->score, + i < HOF_STANDOUT_ENTRIES ? "\2" : "\4", + e->timestamp); SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "HOF[%d] = \"%s\" (%ld [vis=%d])\n", i, @@ -1879,7 +1881,7 @@ render_text(struct State* state, const int x, const int y, const int font_width, float tex_w, tex_h; float opacity = TEXT_OPACITY_NORMAL; - assert((font_tex != NULL) && (text != NULL)); + assert((state != NULL) && (font_tex != NULL) && (text != NULL)); assert(state->text_scale_factor != 0.0f); assert(font_width != -1);