forked from malensek/coin-server
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtask.c
More file actions
160 lines (134 loc) · 3.58 KB
/
task.c
File metadata and controls
160 lines (134 loc) · 3.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/*
* Change Log:
* e.g. [DD/MM/YY Writer]: Description of another change
*
* [05/07/23 InhwaS]: issue#2 split the "animals" array and the "adjectives" array into separate files
*
*/
#include "task.h"
#include "logger.h"
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
static size_t ani_idx = 0;
static size_t adj_idx = 0;
void fisher_yates(char *arr[], size_t sz);
size_t read_file(char filename[], char ***array);
char **animals;
char **adjectives;
static size_t adj_sz = 0;
static size_t ani_sz = 0;
/**
* Seeds the random number generator and then sets up task generation data
* structures by shuffling task components.
*/
void task_init(int seed, char* adjective_file, char* animal_file)
{
ani_sz = read_file(animal_file, &animals);
adj_sz = read_file(adjective_file, &adjectives);
LOG("Initializing task generator. %zu animals, %zu adjectives (%zu x %zu = %zu)\n", ani_sz, adj_sz, ani_sz, adj_sz, adj_sz * ani_sz);
assert(ani_sz != 0 && adj_sz != 0);
if (seed == 0) {
seed = time(NULL);
}
LOG("Random seed: %d\n", seed);
srand(seed);
size_t max_ani_len = 0;
for (int i = 0; i < ani_sz; ++i)
{
size_t len = strlen(animals[i]);
if (len > max_ani_len) {
max_ani_len = len;
}
}
LOG("Longest animal length: %zu\n", max_ani_len);
size_t max_adj_len = 0;
for (int i = 0; i < adj_sz; ++i)
{
size_t len = strlen(adjectives[i]);
if (len > max_adj_len) {
max_adj_len = len;
}
}
LOG("Longest adjective length: %zu\n", max_adj_len);
size_t longest_task_len = max_ani_len + max_adj_len + 1;
assert(longest_task_len < MAX_BLOCK_LEN);
LOGP("Shuffling animals.\n");
fisher_yates(animals, ani_sz);
LOGP("Shuffling adjectives.\n");
fisher_yates(adjectives, adj_sz);
LOGP("Task generator ready.\n");
}
void task_generate(char buf[MAX_BLOCK_LEN])
{
sprintf(buf, "%s %s", adjectives[adj_idx++], animals[ani_idx++]);
// roll over animals / adjectives on overflow
if (adj_idx == adj_sz) {
adj_idx = 0;
}
if (ani_idx == ani_sz) {
ani_idx = 0;
}
}
void fisher_yates(char *arr[], size_t sz)
{
for (int i = sz - 1; i > 0; i--) {
int r = rand() % (i + 1);
char *temp = arr[r];
arr[r] = arr[i];
arr[i] = temp;
}
}
void destroy_array(char ***array, size_t size){
if(array == NULL){
return;
}
for(size_t i = 0; i < size; i++){
free(array[i]);
array[i] = NULL;
}
free(array);
}
size_t read_file(char filename[], char ***array){
FILE *file = fopen(filename, "r");
if ( file == NULL ){
perror("fopen for file");
return 0;
}
/* Determine the number of lines in the file */
char buf[MAX_BLOCK_LEN] = { 0 };
int i = 0;
while (fgets(buf, sizeof(buf), file) != NULL) {
i++;
}
*array = malloc(i * sizeof(char *));
/* Read the contents */
fseek(file, 0L, SEEK_SET);
i = 0;
while (fgets(buf, sizeof(buf), file) != NULL) {
strtok(buf, "\r\n");
(*array)[i] = strdup(buf);
i++;
}
fclose(file);
return i;
}
/*
* Prevents memory leaks, freeing everything
*/
void task_destroy() {
// Free each index first
for (int i = 0; i < ani_sz; i++) {
free(animals[i]);
}
// Then free the whole array afterwards
free(animals);
// Same procedures
for (int i = 0; i < adj_sz; i++) {
free(adjectives[i]);
}
free(adjectives);
}