-
Notifications
You must be signed in to change notification settings - Fork 0
/
Management.cpp
1276 lines (1200 loc) · 46.2 KB
/
Management.cpp
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
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
//
// Created by manue on 30/10/2022.
//
#include "Management.h"
#include <fstream>
#include <sstream>
#include <iostream>
#include <algorithm>
using namespace std;
/*!Construtor sem parâmetros. Constrói um objeto de gestão com capacidade das turmas 0 e com turmas, estudantes, horários e pedidos lidos de ficheiros.
* Complexidade: O(n * m), sendo o par (n, m) o máximo entre n o número de linhas do ficheiro estudantes e m o tamanho de classes, ou n o número de linhas do ficheiro de horários e m o tamanho de schedules, ou n o número de linhas do ficheiro de pedidos e m o tamanho de classes
*/
Management::Management() {
cap = 0;
readClassesFile();
readStudentsFile();
readSchedulesFile();
readRequestsFile();
}
/*!Construtor com parâmetros. Constrói um objeto de gestão com turmas classes_, estudantes students_, horários schedules_, pedidos requests_ e capacidade das turmas cap_.
* Complexidade: O(1)
* @param classes_ turmas
* @param students_ estudantes
* @param schedules_ horários
* @param requests_ pedidos
* @param cap_ capacidade das turmas
*/
Management::Management(const list<UcClass> &classes_, const set<Student> &students_, const vector<ClassSchedule> &schedules_, const queue<Request> &requests_, unsigned cap_) {
classes = classes_;
students = students_;
schedules = schedules_;
requests = requests_;
cap = cap_;
}
/*!Retorna as turmas.
* Complexidade: O(1)
* @return turmas
*/
list<UcClass> Management::getClasses() const {
return classes;
}
/*!Retorna os estudantes.
* Complexidade: O(1)
* @return estudantes
*/
set<Student> Management::getStudents() const {
return students;
}
/*!Retorna os horários.
* Complexidade: O(1)
* @return horários
*/
vector<ClassSchedule> Management::getSchedules() const {
return schedules;
}
/*!Retorna os pedidos.
* Complexidade: O(1)
* @return pedidos
*/
queue<Request> Management::getRequests() const {
return requests;
}
/*!Retorna a capacidade das turmas.
* Complexidade: O(1)
* @return capacidade das turmas
*/
unsigned Management::getCap() const {
return cap;
}
/*!Define as turmas como classes_.
* Complexidade: O(1)
* @param classes_ novas turmas
*/
void Management::setClasses(const list<UcClass> &classes_) {
classes = classes_;
}
/*!Define os estudantes como students_.
* Complexidade: O(1)
* @param students_ novos estudantes
*/
void Management::setStudents(const set<Student> &students_) {
students = students_;
}
/*!Define os horários como schedules_.
* Complexidade: O(1)
* @param schedules_ novos horários
*/
void Management::setSchedules(const vector<ClassSchedule> &schedules_) {
schedules = schedules_;
}
/*!Define os pedidos como requests_.
* Complexidade: O(1)
* @param requests_ novos pedidos
*/
void Management::setRequests(const std::queue<Request> &requests_) {
requests = requests_;
}
/*!Define a capacidade das turmas como cap_.
* Complexidade: O(1)
* @param cap_ nova capacidade das turmas
*/
void Management::setCap(unsigned cap_) {
cap = cap_;
}
/*!Inicia a aplicação e lê o valor a atribuir à capacidade das turmas.
* Complexidade: O(n), sendo n a posição do primeiro input válido introduzido pelo utilizador
*/
void Management::start() {
cout << "\nAntes de iniciar o programa, indique o valor pretendido para a capacidade máxima de uma turma (Cap): ";
cap = readNumber();
}
/*!Apresenta o menu principal. Permite selecionar a opção de listagens, de pedidos ou sair.
* Complexidade: amplamente variável de acordo com o input
* @return 0 se o utilizador pretender sair, 1 caso contrário
*/
int Management::menu() {
cout << "\nMenu Principal:\n1 - Listagens\n2 - Pedidos\n0 - Sair\nSelecione a opção pretendida através do número correspondente." << endl;
int option = readNumber();
set<int> options = {1, 2, 0};
option = validateOption(option, options);
switch (option) {
case 1:
listagens();
break;
case 2:
pedidos();
break;
default:
return 0;
}
return 1;
}
/*!Termina a aplicação, processando os pedidos e atualizando os ficheiros de estudantes e de pedidos.
* Complexidade: amplamente variável de acordo com o tipo de pedidos a processar
*/
void Management::end() {
processarPedidos();
writeStudentsFile();
writeRequestsFile();
}
/*!Lê o ficheiro de turmas.
* Complexidade: O(n), sendo n o número de linhas do ficheiro de turmas
*/
void Management::readClassesFile() {
ifstream in("../Files/classes_per_uc.csv");
if (!in.is_open()) {
cout << "Erro ao abrir o ficheiro classes_per_uc.csv." << endl;
cout << "Verifique se o ficheiro se encontra dentro do diretório Files." << endl;
return;
}
string line;
getline(in, line);
while (getline(in, line)) {
istringstream iss(line);
string field;
vector<string> fields(2);
unsigned f = 0;
while(getline(iss, field, ','))
fields[f++] = field;
string ucCode = fields[0];
string classCode = fields[1];
UcClass ucClass = UcClass(ucCode, classCode);
classes.push_back(ucClass);
}
cout << "Leitura de ficheiro classes_per_uc.csv bem-sucedida." << endl;
}
/*!Lê o ficheiro de estudantes.
* Complexidade: O(n * m), sendo n o número de linhas do ficheiro estudantes e m o tamanho de classes
*/
void Management::readStudentsFile() {
ifstream in("../Files/students_classes.csv");
if (!in.is_open()) {
cout << "Erro ao abrir o ficheiro students_classes.csv." << endl;
cout << "Verifique se o ficheiro se encontra dentro do diretório Files." << endl;
return;
}
string line;
getline(in, line);
while (getline(in, line)) {
istringstream iss(line);
string field;
vector<string> fields(4);
unsigned f = 0;
while(getline(iss, field, ','))
fields[f++] = field;
unsigned studentCode = stoi(fields[0]);
string studentName = fields[1];
string ucCode = fields[2];
string classCode = fields[3];
UcClass ucClass = UcClass(ucCode, classCode);
find(classes.begin(), classes.end(), ucClass)->addStudent();
Student student = Student(studentCode, studentName);
auto it = students.find(student);
if (it != students.end()) {
Student temp = *it;
students.erase(it);
temp.addUcClass(ucClass);
students.insert(temp);
} else {
student.addUcClass(ucClass);
students.insert(student);
}
}
cout << "Leitura de ficheiro students_classes.csv bem-sucedida." << endl;
}
/*!Lê o ficheiro de horários.
* Complexidade: O(n * m), sendo n o número de linhas do ficheiro de horários e m o tamanho de schedules
*/
void Management::readSchedulesFile() {
ifstream in("../Files/classes.csv");
if (!in.is_open()) {
cout << "Erro ao abrir o ficheiro classes.csv." << endl;
cout << "Verifique se o ficheiro se encontra dentro do diretório Files." << endl;
return;
}
string line;
getline(in, line);
while (getline(in, line)) {
istringstream iss(line);
string field;
vector<string> fields(6);
unsigned f = 0;
while(getline(iss, field, ','))
fields[f++] = field;
string classCode = fields[0];
string ucCode = fields[1];
string weekday = fields[2];
float startHour = stof(fields[3]);
float duration = stof(fields[4]);
float endHour = startHour + duration;
string type = fields[5];
UcClass ucClass = UcClass(ucCode, classCode);
Slot slot = Slot(weekday, startHour, endHour, type);
ClassSchedule classSchedule = ClassSchedule(ucClass);
auto it = find(schedules.begin(), schedules.end(), classSchedule);
if (it != schedules.end())
it->addSlot(slot);
else {
classSchedule.addSlot(slot);
schedules.push_back(classSchedule);
}
}
cout << "Leitura de ficheiro classes.csv bem-sucedida." << endl;
}
/*!Lê o ficheiro de pedidos.
* Complexidade: O(n * m), sendo n o número de linhas do ficheiro de pedidos e m o tamanho de classes
*/
void Management::readRequestsFile() {
ifstream in("../Files/requests.csv");
if (!in.is_open())
return;
string line;
getline(in, line);
while (getline(in, line)) {
istringstream iss(line);
string field;
vector<string> fields(6);
unsigned f = 0;
while (getline(iss, field, ','))
fields[f++] = field;
unsigned studentCode = stoi(fields[0]);
string originUcCode = fields[1];
string originClassCode = fields[2];
string destinationUcCode = fields[3];
string destinationClassCode = fields[4];
unsigned type = stoi(fields[5]);
Student student = Student(studentCode);
auto it = students.find(student);
if (it == students.end())
continue;
auto origin = find(classes.begin(), classes.end(), UcClass(originUcCode, originClassCode));
auto destination = find(classes.begin(), classes.end(),UcClass(destinationUcCode, destinationClassCode));
Request request;
switch (type) {
case 1: {
request = Request(*it, *origin, UcClass(), type);
break;
}
case 2: {
request = Request(*it, UcClass(), *destination, type);
break;
}
default:
request = Request(*it, *origin, *destination, type);
}
requests.push(request);
}
cout << "Leitura de ficheiro requests.csv bem-sucedida." << endl;
}
/*!Verifica se str é um número.
* Complexidade: O(n), sendo n o tamanho de str
* @param str string a verificar se é um número
* @return true se str é um número, false caso contrário
*/
bool Management::isNumber(const std::string &str) {
for (const char &ch : str)
if (isalpha(ch))
return false;
return true;
}
/*!Valida uma opção, isto é, verifica se option pertence ao conjunto de opções válidas options. Enquanto a opção for inválida, tenta ler uma opção válida.
* Complexidade: O(n), sendo n a posição do primeiro input válido introduzido pelo utilizador
* @param option opção a validar
* @param options opções válidas
* @return opção válida introduzida pelo utilizador
*/
int Management::validateOption(int option, const set<int> &options) {
while (options.find(option) == options.end()) {
cout << "O número inserido não é uma opção válida. Tente novamente." << endl;
option = readNumber();
}
return option;
}
/*!Verifica se code é um código de uma UC.
* Complexidade: O(n), sendo n o tamanho de classes
* @param code string a verificar se é um código de uma UC
* @return true se code é um código de uma UC, false caso contrário
*/
bool Management::isValidUcCode(const std::string &code) const {
for (const UcClass &ucClass : classes)
if (ucClass.getUcCode() == code)
return true;
return false;
}
/*!Lê uma string do utilizador.
* Complexidade: O(1)
* @return string introduzida pelo utilizador
*/
string Management::readString() {
string s;
cin >> s;
cout << endl;
return s;
}
/*!Lê um número do utilizador, forçando a que seja um número não negativo.
* Complexidade: O(n), sendo n a posição do primeiro input válido introduzido pelo utilizador
* @return número não negativo introduzido pelo utilizador
*/
int Management::readNumber() {
string s = readString();
while (!isNumber(s)) {
cout << "Deve inserir um número. Tente novamente." << endl;
s = readString();
}
int n = stoi(s);
while (n < 0) {
cout << "O número não pode ser negativo. Tente novamente." << endl;
n = readNumber();
}
return n;
}
/*!Lê um estudante através do seu código, forçando a que ele exista.
* Complexidade: O(n * log m), sendo n a posição do primeiro input válido introduzido pelo utilizador e m o tamanho de students
* @return estudante existente introduzido pelo utilizador
*/
Student Management::readStudent() const {
cout << "Número do Estudante: ";
int code = readNumber();
Student student = Student(code);
while (students.find(student) == students.end()) {
cout << "Estudante não encontrado. Tente novamente." << endl;
student = readStudent();
}
student = *students.find(student);
return student;
}
/*!Lê uma UC através do seu código, forçando a que ela exista.
* Complexidade: O(n * m), sendo n a posição do primeiro input válido introduzido pelo utilizador e m o tamanho de classes
* @return UC existente introduzida pelo utilizador
*/
std::string Management::readUc() const {
cout << "Código da UC: ";
string ucCode = readString();
while (!isValidUcCode(ucCode)) {
cout << "UC não encontrada. Tente novamente." << endl;
ucCode = readUc();
}
return ucCode;
}
/*!Lê uma turma através do seu código e do código da UC a que pertence, forçando que ela exista.
* Complexidade: O(n * m), sendo n a posição do primeiro input válido introduzido pelo utilizador e m o tamanho de classes
* @return turma existente introduzida pelo utilizador
*/
UcClass Management::readUcClass() const {
string ucCode = readUc();
cout << "Código da Turma: ";
string classCode = readString();
UcClass ucClass = UcClass(ucCode, classCode);
while (find(classes.begin(), classes.end(), ucClass) == classes.end()) {
cout << "Turma não encontada. Tente novamente." << endl;
ucClass = readUcClass();
}
return ucClass;
}
/*!Compara o número de estudantes de left com o número de estudantes de right.
* Complexidade: O(1)
* @param left turma com a qual comparar número de estudantes de right
* @param right turma com a qual comparar número de estudantes de left
* @return true se o número de estudantes de left for menor do que o número de estudantes de right, false caso contrário
*/
bool Management::sortByStudentsCount(const UcClass &left, const UcClass &right) {
return left.getStudentsCount() < right.getStudentsCount();
}
/*!Compara lexicograficamente o nome de left com o nome de right.
* Complexidade: O(1)
* @param left estudante com o qual comparar o nome de right
* @param right estudante com o qual comparar o nome de left
* @return true se o nome de left for lexicograficamente anterior ao nome de right, false caso contrário
*/
bool Management::sortByName(const Student &left, const Student &right) {
return left.getName() < right.getName();
}
/*!Compara o número de UCs de left com o número de UCs de right.
* Complexidade: O(1)
* @param left estudante com o qual comparar o número de UCs de right
* @param right estudante com o qual comparar o número de UCs de left
* @return true se o número de UCs de left for inferior ao número de UCs de right, false caso contrário
*/
bool Management::sortByUcsCount(const Student &left, const Student &right) {
return left.getUcClasses().size() < right.getUcClasses().size();
}
/*!Lê do utilizador a ordenação pretendida para os estudantes a listar (por código, nome ou número de UCs) e ordena os estudantes como pretendido.
* Complexidade: O(n * log n), sendo n o tamanho de toSort
* @param toSort lista de estudantes a ordenar
*/
void Management::chooseStudentsSort(std::list<Student> &toSort) {
cout << "\nOrdenação:\n1 - Número do Estudante\n2 - Nome do Estudante\n3 - Número de UCs\nSelecione a opção pretendida através do número correspondente." << endl;
int option = readNumber();
set<int> options = {1, 2, 3};
option = validateOption(option, options);
switch (option) {
case 2:
toSort.sort(sortByName);
break;
case 3:
toSort.sort(sortByUcsCount);
break;
default:
toSort.sort();
return;
}
}
/*!Lê do utilizador a ordenação pretendida para as UCs a listar por ocupação (crescente ou decrescente) e imprime-as, com o respetivo número de estudantes, pela ordem pretendida.
* Complexidade: O(n), sendo n o tamanho de sorted
* @param sorted lista de UCs a imprimir
*/
void Management::printStudentsCount(const std::list<UcClass> &sorted) {
cout << "\nOrdenação:\n1 - Crescente\n2 - Decrescente\n0 - Sair\nSelecione a opção pretendida através do número correspondente." << endl;
int option = readNumber();
set<int> options = {1, 2, 0};
option = validateOption(option, options);
switch (option) {
case 1:
for (const UcClass &ucClass : sorted) {
ucClass.print();
cout << ucClass.getStudentsCount() << " alunos" << endl;
cout << endl;
}
break;
case 2:
for (auto it = sorted.rbegin(); it != sorted.rend(); it++) {
(*it).print();
cout << (*it).getStudentsCount() << " alunos" << endl;
cout << endl;
}
break;
default:
return;
}
}
/*!Lê do utilizador a ordenação pretendida para os estudantes a listar (crescente ou decrescente) e imprime o ID de cada um, pela ordem pretendida.
* Complexidade: O(n), sendo n o tamanho de sorted
* @param sorted lista de estudantes a imprimir
*/
void Management::printStudents(const std::list<Student> &sorted) {
cout << "\nOrdenação:\n1 - Crescente\n2 - Decrescente\n0 - Sair\nSelecione a opção pretendida através do número correspondente." << endl;
int option = readNumber();
set<int> options = {1, 2, 0};
option = validateOption(option, options);
switch (option) {
case 1:
for (const Student &student : sorted)
student.printID();
break;
case 2:
for (auto it = sorted.rbegin(); it != sorted.rend(); it++)
(*it).printID();
break;
default:
return;
}
}
/*!Retorna o horário ordenado de um estudante.
* Complexidade: O(n * m), sendo n tamanho de ucClasses do estudante e m o máximo entre o tamanho de schedules e o tamanho de slots do horário
* @param student estudante
* @return horário ordenado do estudante
*/
list<pair<Slot, UcClass>> Management::getStudentSchedule(const Student &student) const {
list<pair<Slot, UcClass>> schedule;
for (const UcClass &ucClass : student.getUcClasses())
for (const Slot &slot : find(schedules.begin(), schedules.end(), ClassSchedule(ucClass))->getSlots())
schedule.emplace_back(slot, ucClass);
schedule.sort();
return schedule;
}
/*!Retorna o horário ordenado de uma turma.
* Complexidade: O(n), sendo n o tamanho de schedules
* @param ucClass turma
* @return horário ordenado da turma
*/
std::list<std::pair<Slot, UcClass>> Management::getClassSchedule(const UcClass &ucClass) const {
list<pair<Slot, UcClass>> schedule;
for (const Slot &slot : find(schedules.begin(), schedules.end(), ClassSchedule(ucClass))->getSlots())
schedule.emplace_back(slot, ucClass);
schedule.sort();
return schedule;
}
/*!Apresenta o menu de listagens. Permite selecionar a opção de listagens pretendida (ocupação de turmas/ano/UC, horário de determinado estudante, esudantes em determinada turma/UC/ano, estudantes com mais de n UCs ou horário de determinada turma) ou sair.
* Complexidade: amplamente variável de acordo com o input
*/
void Management::listagens() const {
cout << "\nMenu de Listagens:\n1 - Ocupação de turmas/ano/UC\n2 - Horário de determinado estudante\n3 - Esudantes em determinada turma/UC/ano\n4 - Estudantes com mais de n UCs\n5 - Horário de determinada turma\n0 - Sair\nSelecione a opção pretendida através do número correspondente." << endl;
int option = readNumber();
set<int> options = {1, 2, 3, 4, 5, 0};
option = validateOption(option, options);
switch (option) {
case 1:
ocupacao();
break;
case 2:
horarioEstudante();
break;
case 3:
estudantes();
break;
case 4:
nUcs();
break;
case 5:
horarioTurma();
break;
default:
return;
}
}
/*!Permite selcionar a consulta de ocupação pretendida (turmas, ano ou UC) ou sair.
* Complexidade: amplamente variável de acordo com o input
*/
void Management::ocupacao() const {
cout << "\nConsulta de Ocupação:\n1 - Turmas\n2 - Ano\n3 - UC\n0 - Sair\nSelecione a opção pretendida através do número correspondente." << endl;
int option = readNumber();
set<int> options = {1, 2, 3, 0};
option = validateOption(option, options);
switch (option) {
case 1:
ocupacaoTurmas();
break;
case 2:
ocupacaoAno();
break;
case 3:
ocupacaoUc();
break;
default:
return;
}
}
/*!Permite selcionar a consulta de ocupação de turmas pretendida (total ou parcial) ou sair.
* Complexidade: amplamente variável de acordo com o input
*/
void Management::ocupacaoTurmas() const {
cout << "\nConsulta de Ocupação de Turmas:\n1 - Total\n2 - Parcial\n0 - Sair\nSelecione a opção pretendida através do número correspondente." << endl;
int option = readNumber();
set<int> options = {1, 2, 0};
option = validateOption(option, options);
switch (option) {
case 1:
ocupacaoTurmasTotal();
break;
case 2:
ocupacaoTurmasParcial();
break;
default:
return;
}
}
/*!Apresenta o menu de consulta de ocupação de turmas total e lê do utilizador a opção pretendida (ordenação por UC, ordenação por ocupação ou sair).
* Complexidade: O(n * log n), sendo n o tamanho de classes
*/
void Management::ocupacaoTurmasTotal() const {
cout << "\nOrdenação:\n1 - Por UC\n2 - Por Ocupação\n0 - Sair\nSelecione a opção pretendida através do número correspondente." << endl;
int option = readNumber();
set<int> options = {1, 2, 0};
option = validateOption(option, options);
list<UcClass> sorted;
for (const UcClass &ucClass : classes)
sorted.push_back(ucClass);
switch (option) {
case 1:
break;
case 2:
sorted.sort(sortByStudentsCount);
break;
default:
return;
}
printStudentsCount(sorted);
}
/*!Apresenta o menu de consulta de ocupação de turmas parcial e lê do utilizador a opção pretendida (todas as turmas de um ano, todas as turmas de uma UC, uma turma de uma UC ou sair).
* Complexidade: amplamente variável de acordo com o input
*/
void Management::ocupacaoTurmasParcial() const {
cout << "\nConsulta de Ocupação de Turmas Parcial:\n1 - Todas as turmas de um ano\n2 - Todas as turmas de uma UC\n3 - Uma turma de uma UC\n0 - Sair\nSelecione a opção pretendida através do número correspondente." << endl;
int option = readNumber();
set<int> options = {1, 2, 3, 0};
switch (option) {
case 1:
ocupacaoTurmasAno();
break;
case 2:
ocupacaoTurmasUc();
break;
case 3:
ocupacaoTurma();
break;
default:
return;
}
}
/*!Imprime a ocupação (número de estudantes) de todas as turmas de um ano.
* Complexidade: O(n), sendo n o tamanho de classes
*/
void Management::ocupacaoTurmasAno() const {
cout << "\nIndique o ano (1, 2 ou 3)" << endl;
int option = readNumber();
set<int> options = {1, 2, 3};
option = validateOption(option, options);
for (const UcClass &ucClass : classes)
if (ucClass.getClassCode()[0] - '0' == option) {
ucClass.print();
cout << ucClass.getStudentsCount() << " alunos" << endl;
cout << endl;
}
}
/*!Imprime a ocupação (número de estudantes) de todas as turmas de uma UC.
* Complexidade: O(n), sendo n o tamanho de classes
*/
void Management::ocupacaoTurmasUc() const {
string ucCode = readUc();
for (const UcClass &ucClass : classes)
if (ucClass.getUcCode() == ucCode)
cout << ucClass.getClassCode() << ": " << ucClass.getStudentsCount() << " alunos" << endl;
}
/*!Imprime a ocupação (número de estudantes) de uma determinada turma de uma UC.
* Complexidade: O(n), sendo n o tamanho de students
*/
void Management::ocupacaoTurma() const {
UcClass ucClass = readUcClass();
unsigned res = 0;
for (const Student &student : students)
if (student.inClass(ucClass))
res += 1;
cout << res << " alunos" << endl;
}
/*!Imprime a ocupação (número de estudantes) de um determinado ano.
* Complexidade: O(n), sendo n o tamanho de students
*/
void Management::ocupacaoAno() const {
cout << "\nIndique o ano (1, 2 ou 3)" << endl;
int option = readNumber();
set<int> options = {1, 2, 3};
option = validateOption(option, options);
unsigned res = 0;
for (const Student &student : students)
if (student.getYears()[option - 1])
res += 1;
cout << res << " alunos" << endl;
}
/*!Imprime a ocupação (número de estudantes) de uma determinada UC.
* Complexidade: O(n), sendo n o tamanho de classes
*/
void Management::ocupacaoUc() const {
string ucCode = readUc();
unsigned res = 0;
for (const UcClass &ucClass : classes)
if (ucClass.getUcCode() == ucCode)
res += ucClass.getStudentsCount();
cout << res << " alunos" << endl;
}
/*!Imprime o horário de um determinado estudante.
* Complexidade: O(n * m), sendo n o tamanho de ucClasses do estudante e m o máximo entre o tamanho de schedules e o tamanho de slots do horário
*/
void Management::horarioEstudante() const {
Student student = readStudent();
student.print();
cout << endl;
list<pair<Slot, UcClass>> schedule = getStudentSchedule(student);
for (const pair<Slot, UcClass> &pair : schedule) {
pair.first.print();
pair.second.print();
cout << endl;
}
}
/*!Apresenta o menu de consulta de estudantes e lê do utilizador a opção pretendida (por turma, por UC, por ano ou sair).
* Complexidade: amplamente variável de acordo com o input
*/
void Management::estudantes() const {
cout << "\nConsulta de Estudantes:\n1 - Turma\n2 - UC\n3 - Ano\n0 - Sair\nSelecione a opção pretendida através do número correspondente." << endl;
int option = readNumber();
set<int> options = {1, 2, 3, 0};
option = validateOption(option, options);
switch (option) {
case 1:
estudantesTurma();
break;
case 2:
estudantesUc();
break;
case 3:
estudantesAno();
break;
default:
return;
}
}
/*!Imprime os estudantes de uma determinada turma de uma UC.
* Complexidade: O(n * log n), sendo n o tamanho de students
*/
void Management::estudantesTurma() const {
UcClass ucClass = readUcClass();
list<Student> sorted;
for (const Student &student : students)
if (student.inClass(ucClass))
sorted.push_back(student);
chooseStudentsSort(sorted);
printStudents(sorted);
}
/*!Imprime os estudantes de uma determinada UC.
* Complexidade: O(n * m), sendo n o tamanho de students e m o tamanho de ucClasses do estudante
*/
void Management::estudantesUc() const {
string ucCode = readUc();
list<Student> sorted;
for (const Student &student : students)
for (const UcClass &ucClass : student.getUcClasses())
if (ucClass.getUcCode() == ucCode)
sorted.push_back(student);
chooseStudentsSort(sorted);
printStudents(sorted);
}
/*!Imprime os estudantes de um determinado ano.
* Complexidade: O(n * log n), sendo n o tamanho de students
*/
void Management::estudantesAno() const {
cout << "\nIndique o ano (1, 2 ou 3)" << endl;
int option = readNumber();
set<int> options = {1, 2, 3};
option = validateOption(option, options);
list<Student> sorted;
for (const Student &student : students)
if (student.getYears()[option - 1])
sorted.push_back(student);
chooseStudentsSort(sorted);
printStudents(sorted);
}
/*!Imprime os estudantes com mais de n UCs pela ordem pretendida.
* Complexidade: O(n * log n), sendo n o tamanho de students
*/
void Management::nUcs() const {
cout << "\nIntroduza o valor de n" << endl;
int n = readNumber();
list<Student> sorted;
for (const Student &student: students)
if (student.getUcClasses().size() > n)
sorted.push_back(student);
chooseStudentsSort(sorted);
printStudents(sorted);
}
/*!Imprime o horário de uma determinada turma de uma UC.
* Complexidade: O(n), sendo n o tamanho de schedules
*/
void Management::horarioTurma() const {
UcClass ucClass = readUcClass();
list<pair<Slot, UcClass>> schedule = getClassSchedule(ucClass);
for (const pair<Slot, UcClass> &pair : schedule) {
pair.first.print();
pair.second.print();
cout << endl;
}
}
/*!Apresenta o menu de pedidos e lê do utilizador a opção pretendida (adicionar pedido, listar pedidos, processar todos os pedidos, ver próximo pedido a processar, processar próximo pedido, remover próximo pedido a processar, remover todos os pedidos ou sair).
* Complexidade: amplamente variável de acordo com o input
*/
void Management::pedidos() {
cout << "\nMenu de Pedidos:\n1 - Adicionar pedido\n2 - Listar pedidos\n3 - Processar todos os pedidos\n4 - Ver próximo pedido a processar\n5 - Processar próximo pedido\n6 - Remover próximo pedido a processar\n7 - Remover todos os pedidos\n0 - Sair\nSelecione a opção pretendida através do número correspondente." << endl;
int option = readNumber();
set<int> options = {1, 2, 3, 4, 5, 6, 7, 0};
option = validateOption(option, options);
switch (option) {
case 1:
adicionarPedido();
break;
case 2:
listarPedidos();
break;
case 3:
processarPedidos();
break;
case 4:
verPedido();
break;
case 5:
forcarPedido();
break;
case 6:
removerPedido();
break;
case 7:
removerPedidos();
break;
default:
return;
}
}
/*!Apresenta o menu de adição de pedidos e lê do utilizador a opção pretendida (remover estudante de turma/UC, adicionar estudante a uma turma/UC, alterar a turma/UC de um estudante, alterar um conjunto de turmas/UCs de um estudante ou sair).
* Complexidade: amplamente variável de acordo com o input
*/
void Management::adicionarPedido() {
cout << "\nTipo do Pedido a Adicionar:\n1 - Remover estudante de turma/UC\n2 - Adicionar estudante a uma turma/UC\n3 - Alterar a turma/UC de um estudante\n4 - Alterar um conjunto de turmas/UCs de um estudante\n0 - Sair\nSelecione a opção pretendida através do número correspondente." << endl;
int option = readNumber();
set<int> options = {1, 2, 3, 4, 0};
option = validateOption(option, options);
switch (option) {
case 1: {
Student student = readStudent();
removerTurma(student);
break;
}
case 2: {
Student student = readStudent();
adicionarTurma(student);
break;
}
case 3: {
Student student = readStudent();
alterarTurma(student);
break;
}
case 4: {
Student student = readStudent();
alterarTurmas(student);
break;
}
default:
return;
}
}
/*!Lê do utilizador um pedido de remoção de um estudante a uma turma.
* Complexidade: O(n), sendo n o tamanho de classes
* @param student estudante a tentar remover de turma
*/
void Management::removerTurma(Student &student) {
UcClass origin = readUcClass();
UcClass destination = UcClass();
if (!student.inClass(origin)) {
cout << "\nO estudante indicado já não frequenta essa turma." << endl;
return;
}
Request request = Request(student, origin, destination, 1);
requests.push(request);
cout << "\nPedido adicionado à fila de pedidos." << endl;
}
/*!Lê do utilizador um pedido de adição de um estudante a uma turma.
* Complexidade: O(n), sendo n o tamanho de classes
* @param student estudante a tentar adiconar a turma
*/
void Management::adicionarTurma(Student &student) {
UcClass origin = UcClass();
UcClass destination = readUcClass();
if (student.inClass(destination)) {
cout << "\nO estudante indicado já frequenta essa turma." << endl;
return;
}
if (student.inUc(destination)) {
cout << "\nO estudante indicado já frequenta essa UC. Um estudante não pode frquentar duas turmas da mesma UC." << endl << "Caso pretenda mudar de turma dentro da mesma UC, deve solicitar um pedido de alteração de turma." << endl;
return;
}
Request request = Request(student, origin, destination, 2);
requests.push(request);
cout << "\nPedido adicionado à fila de pedidos." << endl;
}
/*!Lê do utilizador um pedido de alteração de turma de um estudante.
* Complexidade: O(n), sendo n o tamanho de classes
* @param student estudante a tentar alterar turma
*/
void Management::alterarTurma(Student &student) {
cout << "\nTurma de Origem" << endl;
UcClass origin = readUcClass();
while (!student.inClass(origin)) {
cout << "O estudante indicado não frequenta essa turma. Tente novamente." << endl;
origin = readUcClass();
}
cout << "\nTurma de Destino" << endl;
UcClass destination = readUcClass();
while (origin.getUcCode() != destination.getUcCode()) {
cout << "A UC de destino deve coincidir com a UC de origem. Um estudante só pode mudar de turma dentro da mesma UC. Tente novamente." << endl;
cout << "\nTurma de Destino" << endl;
destination = readUcClass();
}
Request request = Request(student, origin, destination, 3);
requests.push(request);
cout << "\nPedido adicionado à fila de pedidos." << endl;
}
/*!Lê do utilizador um pedido de alteração de um conjunto de turmas de um estudante.
* Complexidade: O(n * m), sendo n o input do utilizador (número de turmas a alterar) e m o tamanho de classes
* @param student estudante a tentar alterar turmas
*/
void Management::alterarTurmas(Student &student) {
cout << "\nIndique o número de UCs a alterar." << endl;
int n = readNumber();
for (int i = 1; i <= n; i++) {
cout << "\nAteração Nº " << i << endl;
alterarTurma(student);
}
}
/*!Lista, por ordem, todos os pedidos na fila de pedidos.
* Complexidade: O(n), sendo n o tamanaho da fila de pedidos.
*/
void Management::listarPedidos() {
if (requests.empty()) {
cout << "\nA fila de pedidos está vazia." << endl;
return;
}
queue<Request> requestsCopy = requests;
unsigned i = 1;
while (!requestsCopy.empty()) {
cout << i++ << ". ";
requestsCopy.front().print();