summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/main.c83
-rw-r--r--src/questions.c92
-rw-r--r--src/utils.c34
3 files changed, 209 insertions, 0 deletions
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 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <time.h>
4#include <sys/stat.h>
5#include <sys/types.h>
6
7#include "questions.h"
8#include "utils.h"
9
10int main(void) {
11 srand((unsigned)time(NULL));
12
13 // utwórz katalog data/ jeśli nie istnieje
14 struct stat st = {0};
15 if (stat("data", &st) == -1) {
16#ifdef _WIN32
17 _mkdir("data");
18#else
19 mkdir("data", 0755);
20#endif
21 }
22
23 QuestionSet qs;
24 if (load_questions("data/questions.txt", &qs) != EXIT_SUCCESS) {
25 fprintf(stderr, "Error: cannot load questions file\n");
26 return EXIT_FAILURE;
27 }
28
29 FILE *csv = fopen("data/results.csv", "a");
30 if (!csv) {
31 perror("CSV open");
32 free_questions(&qs);
33 return EXIT_FAILURE;
34 }
35
36 int limit = 0;
37 printf("Time limit (sec, 0 = unlimited): ");
38 if (scanf("%d", &limit) != 1) limit = 0;
39 wait_enter(NULL);
40
41 size_t total = 0, correct = 0;
42 char cont = 'y';
43
44 while (cont == 'y' || cont == 'Y') {
45 const char *g = qs.general[rand_index(qs.general_count)];
46 const char *m = qs.major[rand_index(qs.major_count)];
47
48 print_line();
49 printf("GENERAL:\n%s\n\nMAJOR:\n%s\n", g, m);
50 print_line();
51
52 wait_enter("Press ENTER to start...");
53 time_t start = time(NULL);
54
55 wait_enter("Press ENTER when done...");
56 double duration = difftime(time(NULL), start);
57
58 if (limit > 0 && duration > limit)
59 printf("Time exceeded!\n");
60
61 char ans = ask_yes_no("Correct? (y/n): ");
62 if (ans == 'y' || ans == 'Y') correct++;
63 total++;
64
65 char ts[32];
66 now_str(ts, sizeof(ts));
67 fprintf(csv, "\"%s\",\"%s\",\"%s\",%c,%.0f\n", ts, g, m, ans, duration);
68
69 printf("Score: %zu/%zu (%.1f%%)\n",
70 correct, total,
71 total ? (double)correct / total * 100 : 0.0);
72
73 cont = ask_yes_no("Next? (y/n): ");
74 }
75
76 printf("\nSession score: %.1f%%\n",
77 total ? (double)correct / total * 100 : 0.0);
78
79 fclose(csv);
80 free_questions(&qs);
81
82 return EXIT_SUCCESS;
83}
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 @@
1#include "questions.h"
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5
6#define MAX_LINE 512
7
8static int add_question(char ***arr, size_t *count, const char *text) {
9 char **tmp = realloc(*arr, (*count + 1) * sizeof(char *));
10 if (!tmp)
11 return EXIT_FAILURE;
12 *arr = tmp;
13
14 (*arr)[*count] = malloc(strlen(text) + 1);
15 if (!(*arr)[*count])
16 return EXIT_FAILURE;
17
18 strcpy((*arr)[*count], text);
19 (*count)++;
20 return EXIT_SUCCESS;
21}
22
23int load_questions(const char *filename, QuestionSet *qs) {
24 if (!filename || !qs)
25 return EXIT_FAILURE;
26
27 FILE *f = fopen(filename, "r");
28 if (!f)
29 return EXIT_FAILURE;
30
31 qs->general = NULL;
32 qs->major = NULL;
33 qs->general_count = 0;
34 qs->major_count = 0;
35
36 char line[MAX_LINE];
37 enum { NONE, GENERAL, MAJOR } mode = NONE;
38
39 while (fgets(line, sizeof(line), f)) {
40 line[strcspn(line, "\n")] = '\0';
41 if (line[0] == '\0')
42 continue;
43
44 if (strcmp(line, "#GENERAL") == 0) {
45 mode = GENERAL;
46 continue;
47 }
48 if (strcmp(line, "#MAJOR") == 0) {
49 mode = MAJOR;
50 continue;
51 }
52
53 int res = EXIT_FAILURE;
54 switch (mode) {
55 case GENERAL:
56 res = add_question(&qs->general, &qs->general_count, line);
57 break;
58 case MAJOR:
59 res = add_question(&qs->major, &qs->major_count, line);
60 break;
61 default:
62 continue; // ignore lines before section
63 }
64
65 if (res != EXIT_SUCCESS) {
66 fclose(f);
67 free_questions(qs);
68 return EXIT_FAILURE;
69 }
70 }
71
72 fclose(f);
73 return (qs->general_count && qs->major_count) ? EXIT_SUCCESS : EXIT_FAILURE;
74}
75
76void free_questions(QuestionSet *qs) {
77 if (!qs)
78 return;
79
80 for (size_t i = 0; i < qs->general_count; i++)
81 free(qs->general[i]);
82 for (size_t i = 0; i < qs->major_count; i++)
83 free(qs->major[i]);
84
85 free(qs->general);
86 free(qs->major);
87
88 qs->general = NULL;
89 qs->major = NULL;
90 qs->general_count = 0;
91 qs->major_count = 0;
92}
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 @@
1#include "utils.h"
2#include <stdio.h>
3#include <stdlib.h>
4#include <time.h>
5
6void print_line(void) {
7 printf("--------------------------------------------------\n");
8}
9
10void wait_enter(const char *msg) {
11 if (msg)
12 printf("%s", msg);
13 int c;
14 while ((c = getchar()) != '\n' && c != EOF)
15 ;
16}
17
18char ask_yes_no(const char *msg) {
19 char c = 'n';
20 printf("%s", msg);
21 if (scanf(" %c", &c) != 1)
22 c = 'n';
23 int flush;
24 while ((flush = getchar()) != '\n' && flush != EOF)
25 ;
26 return c;
27}
28
29void now_str(char *buf, size_t size) {
30 time_t t = time(NULL);
31 strftime(buf, size, "%Y-%m-%d %H:%M:%S", localtime(&t));
32}
33
34size_t rand_index(size_t max) { return max ? (size_t)(rand() % max) : 0; }