From a2afca302c68b8b5d7c3bec13378180b60a3ac17 Mon Sep 17 00:00:00 2001 From: Filip Wandzio Date: Sun, 1 Mar 2026 11:29:12 +0100 Subject: Scaffold project Signed-off-by: Filip Wandzio --- src/main.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/questions.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/utils.c | 34 +++++++++++++++++++++ 3 files changed, 209 insertions(+) create mode 100644 src/main.c create mode 100644 src/questions.c create mode 100644 src/utils.c (limited to 'src') diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..33d4b39 --- /dev/null +++ b/src/main.c @@ -0,0 +1,83 @@ +#include +#include +#include +#include +#include + +#include "questions.h" +#include "utils.h" + +int main(void) { + srand((unsigned)time(NULL)); + + // utwórz katalog data/ jeśli nie istnieje + struct stat st = {0}; + if (stat("data", &st) == -1) { +#ifdef _WIN32 + _mkdir("data"); +#else + mkdir("data", 0755); +#endif + } + + QuestionSet qs; + if (load_questions("data/questions.txt", &qs) != EXIT_SUCCESS) { + fprintf(stderr, "Error: cannot load questions file\n"); + return EXIT_FAILURE; + } + + FILE *csv = fopen("data/results.csv", "a"); + if (!csv) { + perror("CSV open"); + free_questions(&qs); + return EXIT_FAILURE; + } + + int limit = 0; + printf("Time limit (sec, 0 = unlimited): "); + if (scanf("%d", &limit) != 1) limit = 0; + wait_enter(NULL); + + size_t total = 0, correct = 0; + char cont = 'y'; + + while (cont == 'y' || cont == 'Y') { + const char *g = qs.general[rand_index(qs.general_count)]; + const char *m = qs.major[rand_index(qs.major_count)]; + + print_line(); + printf("GENERAL:\n%s\n\nMAJOR:\n%s\n", g, m); + print_line(); + + wait_enter("Press ENTER to start..."); + time_t start = time(NULL); + + wait_enter("Press ENTER when done..."); + double duration = difftime(time(NULL), start); + + if (limit > 0 && duration > limit) + printf("Time exceeded!\n"); + + char ans = ask_yes_no("Correct? (y/n): "); + if (ans == 'y' || ans == 'Y') correct++; + total++; + + char ts[32]; + now_str(ts, sizeof(ts)); + fprintf(csv, "\"%s\",\"%s\",\"%s\",%c,%.0f\n", ts, g, m, ans, duration); + + printf("Score: %zu/%zu (%.1f%%)\n", + correct, total, + total ? (double)correct / total * 100 : 0.0); + + cont = ask_yes_no("Next? (y/n): "); + } + + printf("\nSession score: %.1f%%\n", + total ? (double)correct / total * 100 : 0.0); + + fclose(csv); + free_questions(&qs); + + return EXIT_SUCCESS; +} diff --git a/src/questions.c b/src/questions.c new file mode 100644 index 0000000..88671a7 --- /dev/null +++ b/src/questions.c @@ -0,0 +1,92 @@ +#include "questions.h" +#include +#include +#include + +#define MAX_LINE 512 + +static int add_question(char ***arr, size_t *count, const char *text) { + char **tmp = realloc(*arr, (*count + 1) * sizeof(char *)); + if (!tmp) + return EXIT_FAILURE; + *arr = tmp; + + (*arr)[*count] = malloc(strlen(text) + 1); + if (!(*arr)[*count]) + return EXIT_FAILURE; + + strcpy((*arr)[*count], text); + (*count)++; + return EXIT_SUCCESS; +} + +int load_questions(const char *filename, QuestionSet *qs) { + if (!filename || !qs) + return EXIT_FAILURE; + + FILE *f = fopen(filename, "r"); + if (!f) + return EXIT_FAILURE; + + qs->general = NULL; + qs->major = NULL; + qs->general_count = 0; + qs->major_count = 0; + + char line[MAX_LINE]; + enum { NONE, GENERAL, MAJOR } mode = NONE; + + while (fgets(line, sizeof(line), f)) { + line[strcspn(line, "\n")] = '\0'; + if (line[0] == '\0') + continue; + + if (strcmp(line, "#GENERAL") == 0) { + mode = GENERAL; + continue; + } + if (strcmp(line, "#MAJOR") == 0) { + mode = MAJOR; + continue; + } + + int res = EXIT_FAILURE; + switch (mode) { + case GENERAL: + res = add_question(&qs->general, &qs->general_count, line); + break; + case MAJOR: + res = add_question(&qs->major, &qs->major_count, line); + break; + default: + continue; // ignore lines before section + } + + if (res != EXIT_SUCCESS) { + fclose(f); + free_questions(qs); + return EXIT_FAILURE; + } + } + + fclose(f); + return (qs->general_count && qs->major_count) ? EXIT_SUCCESS : EXIT_FAILURE; +} + +void free_questions(QuestionSet *qs) { + if (!qs) + return; + + for (size_t i = 0; i < qs->general_count; i++) + free(qs->general[i]); + for (size_t i = 0; i < qs->major_count; i++) + free(qs->major[i]); + + free(qs->general); + free(qs->major); + + qs->general = NULL; + qs->major = NULL; + qs->general_count = 0; + qs->major_count = 0; +} diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..c139929 --- /dev/null +++ b/src/utils.c @@ -0,0 +1,34 @@ +#include "utils.h" +#include +#include +#include + +void print_line(void) { + printf("--------------------------------------------------\n"); +} + +void wait_enter(const char *msg) { + if (msg) + printf("%s", msg); + int c; + while ((c = getchar()) != '\n' && c != EOF) + ; +} + +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; +} + +void now_str(char *buf, size_t size) { + time_t t = time(NULL); + strftime(buf, size, "%Y-%m-%d %H:%M:%S", localtime(&t)); +} + +size_t rand_index(size_t max) { return max ? (size_t)(rand() % max) : 0; } -- cgit v1.2.3