-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
360 lines (299 loc) · 13.4 KB
/
main.c
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
/* Proyecto 2. Pide Cola
Participantes:
Sandibel Soares
Carlo Herrera
Juan Cuevas
Archivo: main.c
Procesa el input del usuario dado por la línea de comandos.
Proporciona mensajes de ayuda si se introduce mal alguna flag.
Imprime mensajes de bienvenida y despedida.
Dependiendo del input la función main decide qué acción realizar:
Calcular la probabilidad asociada a un carnet.
Calcular la cantidad de carros asociados a una materia.
*/
#include <stdio.h> /* funcion printf */
#include <stdlib.h> /* constantes EXIT_FAILURE, EXIT_SUCCESS */
#include <string.h> /* funciones strlen, strcpy, strcmp */
# include "calc_prob.h" /* funciones calc_prob, car_prob */
# include "files_finder.h" /* funciones find_asignatures, find_students*/
/* Funcion que procesa los argumentos pasados por la linea de comando
Retorna:
-1 si hay errores en los argumentos,
0 si se tiene que calcular la probabilidad asociada a un carnet,
1 si se tiene que calcular la cantidad de carros de una materia
*/
int process_arguments(int argc, char const *argv[], char carnet[10], char course_code[10],\
int *last_cohort, float *p_cohort, float *increase, char root_dir[50]){
int result = -1;
/* Debe haber como minimo dos argumentos: el nombre de archivo y el carnet|codigo_materia */
if (argc <= 1)
{
printf("\033[91;1mError:\033[0m Debe ingresar el carnet de un estudiante o el codigo de una materia\n");
printf("Use %s -h/--help para obtener ayuda\n", argv[0]);
return -1;
}
else if (argc%2 == 1)
{
printf("\033[91;1mError:\033[0m Cantidad de argumentos invalida\n");
printf("Use %s -h/--help para obtener ayuda\n", argv[0]);
return -1;
}
/* Hay que verificar si se pasó un carnet o el codigo de una materia (y que sean validos)*/
/* asumiendo que los carnets siempre tienen 7 caracteres */
if (strlen(argv[1]) == 7)
{
/* si todos los caracteres estan entre [48, 57] (los ascii de 0 hasta 9)
nos estan pasando un carnet
*/
int i;
for (i = 0; i < 7; i++)
{
if (argv[1][i] < 48 || argv[1][i] > 57)
{
printf("\033[91;1mError:\033[0m carnet invalido \n");
printf("Use %s -h/--help para obtener ayuda\n", argv[0]);
return -1;
}
}
strcpy(carnet, argv[1]);
result = 0;
}
/* Asumiendo que los codigos de materia siempre tienen 6 caracteres */
else if (strlen(argv[1]) == 6){
/* Nos estan pasando el codigo de una materia si:
Los dos primeros caracteres estan entre [65, 90] (los ascii de A a Z)
Si el tercer caracter esta entre [65, 90] (A...Z) o [48, 57] (0..9)
El resto de caracteres estan entre [48, 57] (0..9)
*/
int i;
for (i = 0; i < 2; i++)
{
if (argv[1][i] < 65 || argv[1][i] > 90)
{
printf("\033[91;1mError:\033[0m Codigo de materia invalido \n");
printf("Use %s -h/--help para obtener ayuda\n", argv[0]);
return -1;
}
}
if ( (argv[1][2] < 65 || argv[1][2] > 90) && (argv[1][2] < 48 || argv[1][2] > 57))
{
printf("\033[91;1mError:\033[0m Codigo de materia invalido \n");
printf("Use %s -h/--help para obtener ayuda\n", argv[0]);
return -1;
}
for (i = 3; i < 6; i++)
{
if (argv[1][i] < 48 || argv[1][i] > 57)
{
printf("\033[91;1mError:\033[0m Codigo de materia invalido \n");
printf("Use %s -h/--help para obtener ayuda\n", argv[0]);
return -1;
}
}
strcpy(course_code, argv[1]);
result = 1;
}
else
{
printf("\033[91;1mError:\033[0m Carnet o codigo de materia invalido\n");
printf("Use %s -h/--help para obtener ayuda\n", argv[0]);
return -1;
}
/* Se procesan los posibles flags pasados */
int i;
for (i = 2; i < argc; i += 2)
{
if (strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "--cohorte") == 0)
{
if (atoi(argv[i + 1]) == 0)
{
printf("\033[91;1mError:\033[0m La cohorte debe ser un numero entero\n");
printf("Use %s -h/--help para obtener ayuda\n", argv[0]);
return -1;
}
*last_cohort = atoi(argv[i+1]);
}
if (strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "--pcohorte") == 0)
{
if (atof(argv[i + 1]) == 0)
{
printf("\033[91;1mError:\033[0m La probabilidad de cohorte debe ser un numero\n");
printf("Use %s -h/--help para obtener ayuda\n", argv[0]);
return -1;
}
*p_cohort = atof(argv[i+1]);
}
if (strcmp(argv[i], "-i") == 0 || strcmp(argv[i], "--incremento") == 0)
{
if (atof(argv[i + 1]) == 0)
{
printf("\033[91;1mError:\033[0m El incremento debe ser un numero\n");
printf("Use %s -h/--help para obtener ayuda\n", argv[0]);
return -1;
}
*increase = atof(argv[i+1]);
}
if (strcmp(argv[i], "-d") == 0 )
{
strcpy(root_dir, argv[i+1]);
}
}
return result;
}
/* Funcion que imprime mensajes de ayuda con respecto al uso del programa y las flags */
void print_help(char const *argv[]){
printf("\033[93;1mUso:\033[0m %s <carnet|codigo_materia> [opciones]\n", argv[0]);
printf("Calcula la probabilidad de que un estudiante o una seccion pueda subir a la universidad por cola\n");
printf("\033[93;1mOpciones:\033[0m\n");
printf(" \033[92m-c, --cohorte <cohorte>\033[0m\n Cohorte de los estudiantes\n");
printf(" \033[92m-p, --pcohorte <probabilidad>\033[0m\n Probabilidad de tener un carro en la cohorte\n");
printf(" \033[92m-i, --incremento <incremento>\033[0m\n Incremento de la probabilidad por cohorte\n");
printf(" \033[92m-d <directorio>\033[0m\n Directorio donde se encuentran los archivos de los estudiantes\n");
printf("\033[93;1mEjemplos:\033[0m\n");
printf(" %s 20180001 -c 21 -p 0.3 -i 0.04 -d ./DACE\n", argv[0]);
printf(" %s 1234567 -c 21 -p 0.3 -i 0.04 -d ./DACE\n", argv[0]);
printf(" %s 1910056\n", argv[0]);
}
/* Funcion que imprime la bienvenida al programa */
void print_welcome(){
printf("👋 \033[93;1mBienvenido al sistema de análisis de datos de PideCola 3.0\033[0m 👋\n");
printf("💻 \033[93;1mDesarrollado por:\033[0m\n");
printf(" \033[93;1m-\033[0m Sandibel Soares\n");
printf(" \033[93;1m-\033[0m Carlo Herrera\n");
printf(" \033[93;1m-\033[0m Juan Cuevas\n\n");
}
/* Funcion que imprime la despedida al finalizar el programa */
void print_goodbye(){
printf("\n");
printf("👋 \033[93;1mGracias por usar el sistema de análisis de datos de PideCola 3.0\033[0m 👋\n");
printf("\033[93;1mPD:\033[0m Alguien por favor que nos de una cola, nos quedamos en la uni 🥺\n");
}
/* Funcion principal.
Llama a process_arguments para procesar el input
Si no hubo errores, se decide qué acción realizar:
Calcular la probabilidad asociada a un carnet.
Calcular la cantidad de carros asociados a una materia
Si alguna funcion reporta un error se retorna EXIT_FAILURE,
EXIT_SUCCESS de lo contrario.
*/
int main(int argc, char const *argv[])
{
/* Variables */
/* Arreglo de caracteres en donde se guarda el carnet pasado */
char carnet[10];
/* Arreglo de caracteres en donde se guarda el codigo de una materia pasada */
char course_code[10];
/* Ultima corte de la universidad, por defecto la 22 */
int last_cohort = 22;
/* Probabilidad de que la ultima corte tenga un carro, por defecto 3 */
float p_cohort = 3;
/* Incremento de la probabilidad de tener carro con respecto a la ultima corte */
float increase = 4;
/* Ruta a la carpeta principal que contiene todos los archivos de DACE, por defecto "./DACE"*/
char root_dir[100];
strcpy(root_dir, "./DACE");
/* Se comprueba si el usuario esta pidiendo ayuda para el uso del programa */
if (argc == 2 && (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0))
{
print_help(argv);
return EXIT_SUCCESS;
}
/* Se procesan los argumentos pasados por la linea de comandos */
int r = process_arguments(argc, argv, carnet, course_code, \
&last_cohort, &p_cohort, &increase, root_dir);
/* Si r == -1, hay un error en los argumentos pasados y se aborta el program */
if (r == -1)
{
return EXIT_FAILURE;
}
print_welcome();
if (r == 0)
{
/* Si r == 0, significa que hay una consulta por carnet*/
printf("🧮 Vamos a calcular la probabilidad de que el estudiante \033[92;1m%s\033[0m pueda subir a la universidad en cola 🧮\n", carnet);
/* Buscamos las asignaturas qu el estudiante pre-inscribio*/
Queue * asignatures = find_asignatures(root_dir, carnet);
/*Nos aseguramos que find_asignatures nos devolvio una cola */
if (asignatures == NULL)
{
printf("\033[91;1mError:\033[0m Hubo un error al encontrar el comprobante del estudiante con carnet: %s\n", carnet);
return EXIT_FAILURE;
}
if (asignatures->length == 0){
printf("\033[91;1mError:\033[0m El estudiante no inscribio el trimestre\n");
return EXIT_FAILURE;
}
/* Imprimimos lo encotrado */
printf("📚 Asignaturas preinscritas por el estudiante:\n");
print_queue(asignatures);
printf("\033[94;1mTotal de asignaturas preinscritas:\033[0m %d\n", asignatures->length);
/* Variable que usaremos para acceder a la lista de estudiantes de cada material*/
Queue * students;
/* La probabilidad global de que el estudiante pueda asistir a sus materias */
float global_p = 0.0;
/* Probabilidad de la materia que se este analizando */
float course_p = 0.0;
/* Codigo del curso que se analiza */
char * course;
/* Comenzamos a analizar los cursos que estan en la cola provista por find_asignatures*/
while ( asignatures->head != NULL)
{
/* Accedemos al nombre de la materia */
course = (char *)peek(asignatures);
/* Buscamos los estudiantes de la materia */
students = find_students(root_dir, course);
/* Chequeamos que no se haya producido un error al usar la funcion find_students */
if (students == NULL)
{
printf("\033[91;1mError:\033[0m Se produjo un error al buscar la lista de %s\n", course);
return EXIT_FAILURE;
}
/* Revisamos si el estudiante retiro la materia en correccion */
if (search(students, carnet) == FALSE)
{
printf("El estudiante retiro la materia: \033[94;1m%s\033[0m\n", course);
/* Liberamos la memoria del string y del nodo*/
free(course);
dequeue(asignatures);
continue;
}
/* Calculamos la probabilidad de la materia */
course_p = student_prob(students, carnet, p_cohort, increase, last_cohort);
global_p += course_p;
/* Liberamos el string, el nodo de la cola de asignatura y el struct students*/
free(course);
dequeue(asignatures);
free(students);
}
/* La probabilidad maxima es de 100%*/
if(global_p > 100) global_p = 100;
printf("Probabilidad total de asistencia: \033[92;1m%.2f%%\033[0m \n", global_p);
}
else if ( r == 1)
{
/* Si r == 1, significa que es una consulta por codigo de materia*/
printf("🧮 Vamos a calcular la cantidad promedio de carros para la materia \033[92;1m%s\033[0m y si son suficientes para que todos los estudiantes puedan subir 🧮\n", course_code);
/* Buscamos la lista de carnets de los estudiantes inscritos en la materia */
Queue * students = find_students(root_dir, course_code);
/* Revisamos que no se haya producido ningun error en la funcion find_students*/
if (students == NULL)
{
printf("\033[91;1mError:\033[0m Hubo un error al buscar la lista de la materia %s\n", course_code);
return EXIT_FAILURE;
}
if (students->length == 0){
printf("\033[91;1mError:\033[0m No hay una sección abierta de la materia %s\n", course_code);
return EXIT_FAILURE;
}
/*Imprimimos la lista de estudiantes encontrada*/
printf("🎓 Estudiantes inscritos en la materia:\n");
print_queue(students);
printf("\033[94;1mTotal de estudiantes inscritos:\033[0m %d\n", students->length);
/* Calculamos la cantidad de carros esperados y si son suficientes*/
car_prob(students, course_code, p_cohort, increase, last_cohort);
/*liberamos la memoria del struct students*/
free(students);
}
print_goodbye();
return EXIT_SUCCESS;
}