configure the number of rolls in main call
This commit is contained in:
parent
fe916af1a5
commit
f78bfe9871
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* Colloscope - A program that generates a colloscope for French 'classes prépas'
|
||||||
|
* Copyright (C) 2024 Alexandre Aboujaib
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef ALGORITHM_H_INCLUDED
|
||||||
|
#define ALGORITHM_H_INCLUDED
|
||||||
|
|
||||||
|
#include "structure.h"
|
||||||
|
|
||||||
|
bool is_equal_date(date d1, date d2);
|
||||||
|
|
||||||
|
int get_date_index(creneau* edt, int len_creneau, date d);
|
||||||
|
|
||||||
|
array get_all_date_index(creneau* edt, int len_edt, date d);
|
||||||
|
|
||||||
|
int get_next_friday(creneau* edt, int len_creneau, date d);
|
||||||
|
|
||||||
|
int get_fst_offset(creneau* edt, date d);
|
||||||
|
|
||||||
|
//bool is_allowed_MP2I(creneau* edt, int len_edt, int grp, date end);
|
||||||
|
|
||||||
|
//int heuristique_MP2I(creneau* edt, int len_edt, int grp, date end);
|
||||||
|
|
||||||
|
colleur *get_colleurs(colleur *cl, int len_cl, date d, int *how_many);
|
||||||
|
|
||||||
|
void add_colle(creneau *edt, colleur *chads, int grp, int id_edt, int id_chad);
|
||||||
|
|
||||||
|
void remove_colle(creneau *edt, int id_edt);
|
||||||
|
|
||||||
|
void move_colle(creneau* edt, int len_edt, int id_src, int id_dest);
|
||||||
|
|
||||||
|
void swap_colle(creneau* edt, int len_edt, int id_src, int id_dest);
|
||||||
|
|
||||||
|
int mem_id(creneau* edt, int len_edt, int grp, char* colleur);
|
||||||
|
|
||||||
|
bool is_overlap(creneau *edt, int len_edt, int id);
|
||||||
|
|
||||||
|
bool is_overlap_creneau(creneau* edt, int len_edt, int id, int grp);
|
||||||
|
|
||||||
|
int free_math_space(creneau *edt, int len_edt, int id);
|
||||||
|
|
||||||
|
void add_colles_for_group_MP2I(int *weeks_len, creneau *edt, int len_edt, colleur *chads, int len_chads, int n_weeks, int grp, topic start_rotation, int mth, int inf, int *skip_count);
|
||||||
|
|
||||||
|
void write_to_file(char *filename, creneau *edt, int len_edt);
|
||||||
|
|
||||||
|
int score(creneau *edt, int len_edt, int grp, int n_weeks);
|
||||||
|
|
||||||
|
int get_colleur_id(colleur* dudes, int n_dudes, char* target);
|
||||||
|
|
||||||
|
char* get_name_from_id(colleur* dudes, int n_dudes, int id);
|
||||||
|
|
||||||
|
topic get_mat_from_id(colleur* dudes, int n_dudes, int id);
|
||||||
|
|
||||||
|
void aux_2(creneau *edt, int len_edt, colleur *chads, int len_chads, int n_groups, int n_weeks, int n_sim, char *outname);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,132 @@
|
||||||
|
/*
|
||||||
|
* Colloscope - A program that generates a colloscope for French 'classes prépas'
|
||||||
|
* Copyright (C) 2024 Alexandre Aboujaib
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "logger.h"
|
||||||
|
#include "structure.h"
|
||||||
|
#include "algorithm.h"
|
||||||
|
|
||||||
|
// gcc -g -Wall -Wextra -Wpedantic main.c -lSDL2 -lSDL2_image -lm -o main
|
||||||
|
// ./main MP2I-creneaux.txt 33 MP2I-colleurs.txt 16 6 15 output.csv
|
||||||
|
|
||||||
|
void print_help()
|
||||||
|
{
|
||||||
|
printf("Colloscope - A program that generates a colloscope for French 'classe prépas'. By Alexandre Aboujaib\n");
|
||||||
|
printf("Licensed under the terms of the GNU GPL version 3 or later.\n\n");
|
||||||
|
printf("Usage: colloscope [-qvh] <creneaux> <n_creneaux> <colleurs> <n_colleurs> <n_weeks> <n_groups> <n_iter> <output>\n\n");
|
||||||
|
printf("Available options :\n");
|
||||||
|
printf(" -q Quiet mode\n");
|
||||||
|
printf(" -v Verbose mode\n");
|
||||||
|
printf(" -h Print this help\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
int offset;
|
||||||
|
bool quiet=false;
|
||||||
|
bool verbose=false;
|
||||||
|
|
||||||
|
if (argc==2 && strcmp(argv[1], "-h")==0)
|
||||||
|
{
|
||||||
|
print_help();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
else if (argc==9 && argv[1][0]!='-')
|
||||||
|
{
|
||||||
|
offset=0;
|
||||||
|
}
|
||||||
|
else if (argc==10 && argv[1][0]=='-')
|
||||||
|
{
|
||||||
|
offset=1;
|
||||||
|
|
||||||
|
for (char *ch=&argv[1][1]; *ch != '\0'; ch++)
|
||||||
|
{
|
||||||
|
switch (*ch)
|
||||||
|
{
|
||||||
|
case 'q':
|
||||||
|
quiet=true; break;
|
||||||
|
case 'v':
|
||||||
|
verbose=true; break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Unknown option '%c'. Available: [-qvh].\n", *ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (quiet && verbose)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "You can't be both quiet and verbose!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "Usage: %s [-qvh] <creneaux> <n_creneaux> <colleurs> <n_colleurs> <n_weeks> <n_groups> <n_iters> <output>\n", argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char* path_creneaux = argv[1+offset];
|
||||||
|
int n_creneaux = str_to_int(argv[2+offset]);
|
||||||
|
char* path_colleurs = argv[3+offset];
|
||||||
|
int n_colleurs = str_to_int(argv[4+offset]);
|
||||||
|
int n_weeks = str_to_int(argv[5+offset]);
|
||||||
|
int n_groups = str_to_int(argv[6+offset]);
|
||||||
|
int n_iter = str_to_int(argv[7+offset]);
|
||||||
|
char* path_output = argv[8+offset];
|
||||||
|
|
||||||
|
|
||||||
|
if (quiet) {
|
||||||
|
create_logger("colloscope.log", LOG_WARN);
|
||||||
|
} else if (verbose) {
|
||||||
|
create_logger("colloscope.log", LOG_DEBUG);
|
||||||
|
} else {
|
||||||
|
create_logger("colloscope.log", LOG_INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
trace("%d %d %d %d", n_creneaux, n_colleurs, n_weeks, n_groups);
|
||||||
|
|
||||||
|
info("Starting");
|
||||||
|
srand(time(NULL));
|
||||||
|
|
||||||
|
//creneau* edt = import_creneaux("file.txt", 76);
|
||||||
|
creneau* edt = import_creneaux_oneweek(path_creneaux, n_creneaux, n_weeks);
|
||||||
|
int len_edt = n_creneaux*n_weeks;
|
||||||
|
|
||||||
|
//colleur* dudes = import_colleurs("some_data.txt", 13, len_creneau);
|
||||||
|
colleur* dudes = import_colleurs_oneweek(path_colleurs, n_colleurs, n_weeks, n_creneaux);
|
||||||
|
|
||||||
|
aux_2(edt, len_edt, dudes, n_colleurs, n_groups, n_weeks, n_iter, path_output);
|
||||||
|
|
||||||
|
for(int i = 0; i < len_edt; i++) {
|
||||||
|
free(edt[i].name);
|
||||||
|
}
|
||||||
|
free(edt);
|
||||||
|
|
||||||
|
for(int i = 0; i < n_colleurs; i++) {
|
||||||
|
free(dudes[i].disp);
|
||||||
|
free(dudes[i].name);
|
||||||
|
}
|
||||||
|
free(dudes);
|
||||||
|
|
||||||
|
destroy_logger();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,485 @@
|
||||||
|
/*
|
||||||
|
* Colloscope - A program that generates a colloscope for French 'classes prépas'
|
||||||
|
* Copyright (C) 2024 Alexandre Aboujaib
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "logger.h"
|
||||||
|
#include "structure.h"
|
||||||
|
|
||||||
|
//static int width = 1200;
|
||||||
|
//static int height = 900;
|
||||||
|
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) {
|
||||||
|
warn("Anomaly detected at lane %d (dates are not sorted in ascending order) :", i);
|
||||||
|
warn("%d %d %d %d", edt[i-1].date.hour, edt[i-1].date.day, edt[i-1].date.month, edt[i-1].date.year);
|
||||||
|
warn("%d %d %d %d", edt[i].date.hour, edt[i].date.day, edt[i].date.month, edt[i].date.year);
|
||||||
|
warn("%d %d %d %d", edt[i+1].date.hour, edt[i+1].date.day, edt[i+1].date.month, edt[i+1].date.year);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
info("No problem detected");
|
||||||
|
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 src with length l1, \0 NOT included, in dest */
|
||||||
|
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;
|
||||||
|
res[colleur_ptr].id = colleur_ptr;
|
||||||
|
} 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';
|
||||||
|
fatal("Wait that's illegal (%s)", 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 {
|
||||||
|
fatal("Oh no (%d)", 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;}
|
||||||
|
|
||||||
|
info("Successfully imported colleurs");
|
||||||
|
fclose(ptr);
|
||||||
|
free(word);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
date increment_date(date d, int inc) {
|
||||||
|
int remaining = inc;
|
||||||
|
date res = d;
|
||||||
|
int delta_day = 0;
|
||||||
|
while(remaining > 0) {
|
||||||
|
res.day++;
|
||||||
|
delta_day = (res.month == 1 || res.month == 3 || res.month == 5 || res.month == 7 || res.month == 8 || res.month == 10 || res.month == 12) - 2*(res.month == 2) + (res.month == 2 && res.year%4 == 0 && res.year%100 != 0);
|
||||||
|
// sweet jesus
|
||||||
|
if(res.day > 30 + delta_day) {
|
||||||
|
res.day = 1;
|
||||||
|
if(res.month == 12) {
|
||||||
|
res.month = 1;
|
||||||
|
res.year++;
|
||||||
|
} else {
|
||||||
|
res.month++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
remaining--;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
creneau* import_creneaux_oneweek(char* filename, int len_file, int n_weeks) {
|
||||||
|
// import creneau data from a file then copy paste it for specified amount of weeks
|
||||||
|
FILE* ptr = fopen(filename, "r");
|
||||||
|
char c = fgetc(ptr);
|
||||||
|
|
||||||
|
creneau* edt = malloc(sizeof(creneau)*len_file*n_weeks);
|
||||||
|
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);
|
||||||
|
|
||||||
|
for(int k = 1; k < n_weeks; k++) {
|
||||||
|
for(int i = 0; i < len_file; i++) {
|
||||||
|
edt[k*len_file+i].date = increment_date(edt[i].date, 7*k);
|
||||||
|
edt[k*len_file+i].group = 0;
|
||||||
|
edt[k*len_file+i].name = malloc(sizeof(char)*35);
|
||||||
|
edt[k*len_file+i].name[0] = 'n';
|
||||||
|
edt[k*len_file+i].name[1] = 'o';
|
||||||
|
edt[k*len_file+i].name[2] = 'n';
|
||||||
|
edt[k*len_file+i].name[3] = 'e';
|
||||||
|
edt[k*len_file+i].name[4] = '\0';
|
||||||
|
edt[k*len_file+i].namelen = 4;
|
||||||
|
edt[k*len_file+i].mat = NOTHING;
|
||||||
|
edt[k*len_file+i].salle.building = 'N';
|
||||||
|
edt[k*len_file+i].salle.id = 0;
|
||||||
|
edt[k*len_file+i].length = edt[i].length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*for(int k = 0; k < len_file*n_weeks; k++) {
|
||||||
|
printf("%d %d %d %d %d %d\n", edt[k].date.hour, edt[k].date.day, edt[k].date.month, edt[k].date.year, edt[k].group, (int)(edt[k].mat));
|
||||||
|
}*/
|
||||||
|
|
||||||
|
if(!is_sorted(edt, n_weeks*len_file)) {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
info("Imported creneaux successfully");
|
||||||
|
return edt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void expand(colleur* guy, int id, int n_weeks) {
|
||||||
|
int len_1st = guy[id].n_disp;
|
||||||
|
date* new = malloc(sizeof(date)*len_1st*n_weeks);
|
||||||
|
|
||||||
|
for(int b = 0; b < len_1st; b++) {
|
||||||
|
new[b] = guy[id].disp[b];
|
||||||
|
}
|
||||||
|
for(int week = 1; week < n_weeks; week++) {
|
||||||
|
for(int i = 0; i < len_1st; i++) {
|
||||||
|
new[week*len_1st+i] = increment_date(guy[id].disp[i], 7*week);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(guy[id].disp);
|
||||||
|
guy[id].n_disp *= n_weeks;
|
||||||
|
guy[id].disp = new;
|
||||||
|
}
|
||||||
|
|
||||||
|
colleur* import_colleurs_oneweek(char* filename, int n_colleurs, int n_weeks, int len_oneweek) {
|
||||||
|
// same as before, but each colleur only set his/her creneaux for the 1st week
|
||||||
|
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';
|
||||||
|
fatal("Wait that's illegal (%s)", word);
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
res[colleur_ptr].disp = malloc(sizeof(date)*len_oneweek);
|
||||||
|
res[colleur_ptr].id = colleur_ptr;
|
||||||
|
} 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 {
|
||||||
|
fatal("Oh no (%d)", 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;}
|
||||||
|
|
||||||
|
for(int c = 0; c < n_colleurs; c++) {
|
||||||
|
expand(res, c, n_weeks);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(ptr);
|
||||||
|
free(word);
|
||||||
|
|
||||||
|
info("Imported colleurs with no problems");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int str_to_int(char* s) {
|
||||||
|
char c = 'e';
|
||||||
|
int i = 0;
|
||||||
|
int buffer = 0;
|
||||||
|
while(c != '\0') {
|
||||||
|
c = s[i];
|
||||||
|
buffer *= 10;
|
||||||
|
if((int)(c) >= 48 && (int)(c) <= 57) {
|
||||||
|
buffer += (int)(c)-48;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return buffer/10;
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* Colloscope - A program that generates a colloscope for French 'classes prépas'
|
||||||
|
* Copyright (C) 2024 Alexandre Aboujaib
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef STRUCTURE_H_INCLUDED
|
||||||
|
#define STRUCTURE_H_INCLUDED
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* Feuilles mortes :
|
||||||
|
|
||||||
|
extern int* stats;
|
||||||
|
extern int* n_colles;
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
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; int id;} colleur;
|
||||||
|
// available creneaux for the colleurs
|
||||||
|
|
||||||
|
typedef struct array {int* a; int len; int memlen;} array;
|
||||||
|
// yes
|
||||||
|
|
||||||
|
|
||||||
|
int date_dist(date d1, date d2);
|
||||||
|
|
||||||
|
bool is_sorted(creneau *edt, int len);
|
||||||
|
|
||||||
|
creneau *import_creneaux(char *filename, int size);
|
||||||
|
|
||||||
|
bool str_equal(char *s1, char *s2);
|
||||||
|
|
||||||
|
void str_copy(char *src, int l1, char *dest);
|
||||||
|
|
||||||
|
colleur *import_colleurs(char *filename, int n_colleurs, int max_available);
|
||||||
|
|
||||||
|
date increment_date(date d, int inc);
|
||||||
|
|
||||||
|
creneau *import_creneaux_oneweek(char *filename, int len_file, int n_weeks);
|
||||||
|
|
||||||
|
void expand(colleur *guy, int id, int n_weeks);
|
||||||
|
|
||||||
|
colleur *import_colleurs_oneweek(char *filename, int n_colleurs, int n_weeks, int len_oneweek);
|
||||||
|
|
||||||
|
int str_to_int(char *s);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue