colloscope/structure.c

256 lines
7.6 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include <unistd.h>
#include <time.h>
typedef enum topic {NOTHING, MATH, PHYSICS, ENGLISH, FRENCH, INFO} topic;
// colles subjects
typedef struct date {int hour; int day; int month; int year;} date; /* format is {hour, day, month, year} */
// nothing to say here
typedef struct room {char building; int id;} room;
// rooms
// building can be C, M, R or V
typedef struct creneau {int length; date date; int group; char* name; int namelen; topic mat; room salle;} creneau;
// one créneau de colle
// /!\ creneau has to be sorted by ascending dates
// with edt being a creneau*, it is required to have edt[0] be a Monday and edt[len(edt)-1] has to be a Friday
typedef struct colleur {char* name; int namelen; topic mat; date* disp; int n_disp;} colleur;
// available creneaux for the colleurs
typedef struct array {int* a; int len; int memlen;} array;
// yes
//static int width = 1200;
//static int height = 900;
int* stats;
int* n_colles;
int date_dist(date d1, date d2) { /* returns distance between d1 and d2 in days
if d2 is sooner than d1, it will return -1 */
if(d2.month == d1.month && d2.year == d1.year) {
if(d2.day < d1.day) {
return -1;
}
return d2.day - d1.day;
} else {
int is_31 = 0;
if(d1.month == 1 || d1.month == 3 || d1.month == 5 || d1.month == 7 || d1.month == 8 || d1.month == 10 || d1.month == 12) {
is_31 = 1;
} else {
is_31 = (d1.month == 2)*(-2) + (d1.month == 2 && d1.year%4 == 0 && d1.year%100 != 0);
}
if(d2.month - d1.month < 0 && d2.year <= d1.year) {
return -1;
} else if(d2.month - d1.month == 1 && d2.year == d1.year) {
return d2.day + (30 + is_31 - d1.day);
} else {
date copy;
copy.day = d1.day;
copy.month = d1.month;
copy.year = d1.year;
copy.month = (copy.month + 1);
if(copy.month == 13) {
copy.month = 1;
copy.year += 1;
}
return (30 + is_31 + date_dist(copy, d2));
}
}
}
bool is_sorted(creneau* edt, int len) {
for(int i = 1; i < len; i++) {
if(date_dist(edt[i-1].date, edt[i].date) == -1) {
printf("Anomaly detected at lane %d (dates are not sorted in ascending order)\n", i);
return false;
}
}
printf("No problem detected\n");
return true;
}
creneau* import_creneaux(char* filename, int size) {
// import creneau data from a file
// see file.txt for an example
FILE* ptr = fopen(filename, "r");
char c = fgetc(ptr);
creneau* edt = malloc(sizeof(creneau)*size);
int i = 0;
int to_fill = 0;
int buffer = 0;
while(c != EOF && c != '$') {
if((int)(c) >= 48 && (int)(c) <= 57) {
buffer *= 10;
buffer += (int)(c) - 48;
} else {
if(to_fill == 0) {
//printf("%d\n", i);
edt[i].date.hour = buffer;
edt[i].group = 0;
edt[i].name = malloc(sizeof(char)*35);
edt[i].name[0] = 'n';
edt[i].name[1] = 'o';
edt[i].name[2] = 'n';
edt[i].name[3] = 'e';
edt[i].name[4] = '\0';
edt[i].namelen = 4;
edt[i].mat = NOTHING;
edt[i].salle.building = 'N';
edt[i].salle.id = 0;
edt[i].length = 1;
} else if(to_fill == 1) {
edt[i].date.day = buffer;
} else if(to_fill == 2) {
edt[i].date.month = buffer;
} else if(to_fill == 3) {
edt[i].date.year = buffer;
} else {
edt[i].length++;
}
to_fill++;
buffer = 0;
if(c == '\n') {
i++;
to_fill = 0;
}
}
c = fgetc(ptr);
}
fclose(ptr);
if(!is_sorted(edt, size)) {
assert(0);
}
return edt;
}
bool str_equal(char* s1, char* s2) {
// note : s1 and s2 must be valid strings (aka have \0 at the end)
if((int)(s1[0]) == 0 || (int)(s2[0]) == 0) {
return ((int)(s1[0]) == 0 && (int)(s2[0]) == 0);
} else if(s1[0] != s2[0]) {
return false;
}
return str_equal(&s1[1], &s2[1]);
}
void str_copy(char* src, int l1, char* dest) {
/* put the word length as l1, \0 NOT included in l1 */
for(int i = 0; i < l1; i++) {
dest[i] = src[i];
}
dest[l1] = '\0';
}
colleur* import_colleurs(char* filename, int n_colleurs, int max_available) {
/*
file has the following format :
name
mat
dates (date*)
-
name2
mat2
dates2
-
name3
...
$
*/
FILE* ptr = fopen(filename, "r");
char c = fgetc(ptr);
// {char* name; int namelen; topic mat; date* disp; int n_disp;}
colleur* res = malloc(sizeof(colleur)*n_colleurs);
char* word = malloc(sizeof(char)*30);
int wordlen = 0;
int buffer = 0;
int date_ptr = 0;
int current = 0; // 0 = name, 1 = mat, 2+ = dates
int colleur_ptr = 0;
while(c != EOF && c != '$') {
if(c == '\n') {
if(current == 0) {
word[wordlen] = '\0';
res[colleur_ptr].name = malloc(sizeof(char)*30);
str_copy(word, wordlen, res[colleur_ptr].name);
res[colleur_ptr].namelen = wordlen;
} else if(current == 1) {
if(word[0] == 'M') { // math
res[colleur_ptr].mat = MATH;
} else if(word[0] == 'P') { // physics
res[colleur_ptr].mat = PHYSICS;
} else if(word[0] == 'E') { // english
res[colleur_ptr].mat = ENGLISH;
} else if(word[0] == 'I') { // info
res[colleur_ptr].mat = INFO;
} else {
word[wordlen] = '\0';
printf("Wait that's illegal (%s)\n", word);
assert(0);
}
res[colleur_ptr].disp = malloc(sizeof(date)*max_available);
} else {
res[colleur_ptr].disp[current-2].year = buffer;
}
current++;
wordlen = 0;
buffer = 0;
date_ptr = 0;
} else if(c == '+') {
res[colleur_ptr].n_disp = current-2;
current = 0;
colleur_ptr++;
c = fgetc(ptr); // always a '\n', this to avoid some seg fault
} else {
if(current <= 1) {
word[wordlen] = c;
wordlen++;
} else {
if((int)(c) >= 48 && (int)(c) <= 57) {
buffer *= 10;
buffer += (int)(c) - 48;
} else {
if(date_ptr == 0) {
res[colleur_ptr].disp[current-2].hour = buffer;
} else if(date_ptr == 1) {
res[colleur_ptr].disp[current-2].day = buffer;
} else if(date_ptr == 2) {
res[colleur_ptr].disp[current-2].month = buffer;
} else {
printf("Oh no (%d)\n", date_ptr);
assert(0);
}
buffer = 0;
date_ptr++;
}
}
}
//printf("%c", c);
c = fgetc(ptr);
}
// {char* name; int namelen; topic mat; date* disp; int n_disp;}
printf("Successfully imported colleurs\n");
fclose(ptr);
free(word);
return res;
}