From 9e9c1b21569faeabd33716e4153a881e2eed7134 Mon Sep 17 00:00:00 2001 From: Filip Wandzio Date: Sun, 1 Mar 2026 17:45:00 +0100 Subject: Separate quiz logic from main function fo dedicated module Signed-off-by: Filip Wandzio --- src/utils.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 104 insertions(+), 21 deletions(-) (limited to 'src/utils.c') diff --git a/src/utils.c b/src/utils.c index c139929..2e26e8e 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,34 +1,117 @@ #include "utils.h" +#include #include #include #include -void print_line(void) { - printf("--------------------------------------------------\n"); +#define SEPARATOR_CHAR '-' +#define SEPARATOR_WIDTH 50 +#define NEWLINE_CHAR '\n' +#define INPUT_BUFFER_SIZE 16 +#define TIME_FORMAT_STRING "%Y-%m-%d %H:%M:%S" +#define ASK_YES_NO_PROMPT "Please enter 'y' or 'n': " + +/** Clear leftover input from stdin */ +static void flush_stdin(void) +{ + int input_char; + do + input_char = getchar(); + while (input_char != NEWLINE_CHAR && input_char != EOF); +} + +/** Print a horizontal separator line for the quiz UI */ +static void print_separator_line(void) +{ + for (size_t current_column = 0; current_column < SEPARATOR_WIDTH; + ++current_column) + putchar(SEPARATOR_CHAR); + + putchar(NEWLINE_CHAR); } -void wait_enter(const char *msg) { - if (msg) - printf("%s", msg); - int c; - while ((c = getchar()) != '\n' && c != EOF) - ; +/** Print a horizontal separator line */ +void print_line(void) +{ + print_separator_line(); } -char ask_yes_no(const char *msg) { - char c = 'n'; - printf("%s", msg); - if (scanf(" %c", &c) != 1) - c = 'n'; - int flush; - while ((flush = getchar()) != '\n' && flush != EOF) - ; - return c; +/** + * Pause until the user presses ENTER + * + * @param prompt Optional message to display before waiting + */ +void wait_for_enter(const char* prompt) +{ + if (prompt != NULL) + fputs(prompt, stdout); + + flush_stdin(); +} + +/** + * Ask a yes/no question and return a boolean answer + * + * @param prompt Question message to display + * @return true if user answered 'y' or 'Y', false if 'n', default false + */ +bool ask_yes_no(const char* prompt) +{ + char input_line[INPUT_BUFFER_SIZE]; + + while (1) { + if (prompt != NULL) + fputs(prompt, stdout); + + if (fgets(input_line, sizeof(input_line), stdin) == NULL) + return false; + + const char first_char = input_line[0]; + + if (first_char == 'y' || first_char == 'Y') + return true; + + if (first_char == 'n' || first_char == 'N') + return false; + + fputs(ASK_YES_NO_PROMPT, stdout); + } } -void now_str(char *buf, size_t size) { - time_t t = time(NULL); - strftime(buf, size, "%Y-%m-%d %H:%M:%S", localtime(&t)); +/** + * Get the current timestamp for recording when a question was answered + * + * @param answer_time_buffer Buffer to store the formatted timestamp + * @param buffer_capacity Size of the buffer in bytes + */ +void get_answer_timestamp(char* answer_time_buffer, + const size_t buffer_capacity) +{ + if (answer_time_buffer == NULL || buffer_capacity == 0) + return; + + const time_t current_time = time(NULL); + const struct tm* local_time = localtime(¤t_time); + if (local_time != NULL) + strftime(answer_time_buffer, + buffer_capacity, + TIME_FORMAT_STRING, + local_time); } -size_t rand_index(size_t max) { return max ? (size_t)(rand() % max) : 0; } +/** + * Get a random question index in the quiz (thread-safe) + * + * @param seed Pointer to an unsigned int seed (per-thread) + * @param total_questions Number of questions in the current quiz session + * @return Random index in the range [0, total_questions-1] + */ +size_t get_random_question_index(unsigned int* seed, + const size_t total_questions) +{ + if (total_questions == 0 || seed == NULL) + return 0; + + const unsigned long random_value = (unsigned long)rand_r(seed); + return random_value % total_questions; +} -- cgit v1.2.3