1 /*
2 File rules.cpp
3 */
4 
5 /***************************************************************************
6                           rules.cpp  -  description
7                              -------------------
8     begin                : 2002
9     copyright            : (C) 2002 by Lalescu Liviu
10     email                : Please see https://lalescu.ro/liviu/ for details about contacting Liviu Lalescu (in particular, you can find here the e-mail address)
11  ***************************************************************************/
12 
13 /***************************************************************************
14  *                                                                         *
15  *   This program is free software: you can redistribute it and/or modify  *
16  *   it under the terms of the GNU Affero General Public License as        *
17  *   published by the Free Software Foundation, either version 3 of the    *
18  *   License, or (at your option) any later version.                       *
19  *                                                                         *
20  ***************************************************************************/
21 
22 #include "timetable_defs.h"
23 #include "rules.h"
24 
25 #include <QDir>
26 
27 #include <algorithm>
28 #include <iostream>
29 using namespace std;
30 
31 #include <QTextStream>
32 #include <QFile>
33 #include <QFileInfo>
34 
35 #include <QDate>
36 #include <QTime>
37 #include <QLocale>
38 
39 #include <QString>
40 
41 #include <QXmlStreamReader>
42 
43 #include <QTranslator>
44 
45 #include <QtAlgorithms>
46 #include <QtGlobal>
47 
48 #include <QSet>
49 #include <QHash>
50 
51 #include <list>
52 #include <iterator>
53 
54 //#include <QApplication>
55 #ifndef FET_COMMAND_LINE
56 #include <QProgressDialog>
57 #endif
58 
59 #if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
60 #include <QRegularExpression>
61 #include <QRegularExpressionMatch>
62 #else
63 #include <QRegExp>
64 #endif
65 
66 #include "messageboxes.h"
67 
68 #include "lockunlock.h"
69 
70 //static bool toSkipTime[MAX_TIME_CONSTRAINTS];
71 //static bool toSkipSpace[MAX_SPACE_CONSTRAINTS];
72 
73 //extern QApplication* pqapplication;
74 
75 extern bool students_schedule_ready;
76 extern bool rooms_schedule_ready;
77 extern bool teachers_schedule_ready;
78 
FakeString()79 FakeString::FakeString()
80 {
81 }
82 
operator =(const QString & other)83 void FakeString::operator=(const QString& other)
84 {
85 	Q_UNUSED(other);
86 }
87 
operator =(const char * str)88 void FakeString::operator=(const char* str)
89 {
90 	Q_UNUSED(str);
91 }
92 
operator +=(const QString & other)93 void FakeString::operator+=(const QString& other)
94 {
95 	Q_UNUSED(other);
96 }
97 
operator +=(const char * str)98 void FakeString::operator+=(const char* str)
99 {
100 	Q_UNUSED(str);
101 }
102 
103 
init()104 void Rules::init() //initializes the rules (empty, but with default hours and days)
105 {
106 	//keep the current mode, do not change it.
107 
108 	//defaults
109 	this->institutionName=tr("Default institution");
110 	this->comments=tr("Default comments");
111 
112 	//default for Finland
113 	this->nTerms=5;
114 	this->nDaysPerTerm=5;
115 
116 	this->nDaysPerWeek=5;
117 	this->daysOfTheWeek.clear();
118 	this->daysOfTheWeek.append(tr("Monday"));
119 	this->daysOfTheWeek.append(tr("Tuesday"));
120 	this->daysOfTheWeek.append(tr("Wednesday"));
121 	this->daysOfTheWeek.append(tr("Thursday"));
122 	this->daysOfTheWeek.append(tr("Friday"));
123 
124 	this->nHoursPerDay=12;
125 	this->hoursOfTheDay.clear();
126 	this->hoursOfTheDay.append(tr("08:00", "Hour name"));
127 	this->hoursOfTheDay.append(tr("09:00", "Hour name"));
128 	this->hoursOfTheDay.append(tr("10:00", "Hour name"));
129 	this->hoursOfTheDay.append(tr("11:00", "Hour name"));
130 	this->hoursOfTheDay.append(tr("12:00", "Hour name"));
131 	this->hoursOfTheDay.append(tr("13:00", "Hour name"));
132 	this->hoursOfTheDay.append(tr("14:00", "Hour name"));
133 	this->hoursOfTheDay.append(tr("15:00", "Hour name"));
134 	this->hoursOfTheDay.append(tr("16:00", "Hour name"));
135 	this->hoursOfTheDay.append(tr("17:00", "Hour name"));
136 	this->hoursOfTheDay.append(tr("18:00", "Hour name"));
137 	this->hoursOfTheDay.append(tr("19:00", "Hour name"));
138 
139 	permanentStudentsHash.clear();
140 
141 	activitiesPointerHash.clear();
142 	bctSet.clear();
143 	btSet.clear();
144 	bcsSet.clear();
145 	apstHash.clear();
146 	aprHash.clear();
147 	mdbaHash.clear();
148 	tnatHash.clear();
149 	ssnatHash.clear();
150 
151 	this->initialized=true;
152 }
153 
computeInternalStructure(QWidget * parent)154 bool Rules::computeInternalStructure(QWidget* parent)
155 {
156 	//To fix a bug reported by Frans on forum, on 7 May 2010.
157 	//If user generates, then changes some activities (changes teachers of them), then tries to generate but FET cannot precompute in generate_pre.cpp,
158 	//then if user views the timetable, the timetable of a teacher contains activities of other teacher.
159 	//The bug appeared because it is possible to compute internal structure, so internal activities change the teacher, but the timetables remain the same,
160 	//with the same activities indexes.
161 	teachers_schedule_ready=false;
162 	students_schedule_ready=false;
163 	rooms_schedule_ready=false;
164 
165 	//The order is important - firstly the teachers, subjects, activity tags and students.
166 	//After that, the buildings.
167 	//After that, the rooms.
168 	//After that, the activities.
169 	//After that, the time constraints.
170 	//After that, the space constraints.
171 
172 	//kill augmented students sets
173 	QList<StudentsYear*> ayears;
174 	QList<StudentsGroup*> agroups;
175 	QList<StudentsSubgroup*> asubgroups;
176 	for(StudentsYear* year : qAsConst(augmentedYearsList)){
177 		if(!ayears.contains(year))
178 			ayears.append(year);
179 		for(StudentsGroup* group : qAsConst(year->groupsList)){
180 			if(!agroups.contains(group))
181 				agroups.append(group);
182 			for(StudentsSubgroup* subgroup : qAsConst(group->subgroupsList)){
183 				if(!asubgroups.contains(subgroup))
184 					asubgroups.append(subgroup);
185 			}
186 		}
187 	}
188 	for(StudentsYear* year : qAsConst(ayears)){
189 		assert(year!=nullptr);
190 		delete year;
191 	}
192 	for(StudentsGroup* group : qAsConst(agroups)){
193 		assert(group!=nullptr);
194 		delete group;
195 	}
196 	for(StudentsSubgroup* subgroup : qAsConst(asubgroups)){
197 		assert(subgroup!=nullptr);
198 		delete subgroup;
199 	}
200 	augmentedYearsList.clear();
201 	//////////////////
202 
203 	//copy list of students sets into augmented list
204 	QHash<QString, StudentsSet*> augmentedHash;
205 
206 	for(StudentsYear* y : qAsConst(yearsList)){
207 		StudentsYear* ay=new StudentsYear();
208 		ay->name=y->name;
209 		ay->numberOfStudents=y->numberOfStudents;
210 
211 		//2020-09-04 - this is not really important
212 		ay->divisions=y->divisions;
213 		ay->separator=y->separator;
214 
215 		ay->groupsList.clear();
216 		augmentedYearsList << ay;
217 
218 		assert(!augmentedHash.contains(ay->name));
219 		augmentedHash.insert(ay->name, ay);
220 
221 		for(StudentsGroup* g : qAsConst(y->groupsList)){
222 			if(augmentedHash.contains(g->name)){
223 				StudentsSet* tmpg=augmentedHash.value(g->name);
224 				assert(tmpg->type==STUDENTS_GROUP);
225 				ay->groupsList<<((StudentsGroup*)tmpg);
226 			}
227 			else{
228 				StudentsGroup* ag=new StudentsGroup();
229 				ag->name=g->name;
230 				ag->numberOfStudents=g->numberOfStudents;
231 				ag->subgroupsList.clear();
232 				ay->groupsList << ag;
233 
234 				assert(!augmentedHash.contains(ag->name));
235 				augmentedHash.insert(ag->name, ag);
236 
237 				for(StudentsSubgroup* s : qAsConst(g->subgroupsList)){
238 					if(augmentedHash.contains(s->name)){
239 						StudentsSet* tmps=augmentedHash.value(s->name);
240 						assert(tmps->type==STUDENTS_SUBGROUP);
241 						ag->subgroupsList<<((StudentsSubgroup*)tmps);
242 					}
243 					else{
244 						StudentsSubgroup* as=new StudentsSubgroup();
245 						as->name=s->name;
246 						as->numberOfStudents=s->numberOfStudents;
247 						ag->subgroupsList << as;
248 
249 						assert(!augmentedHash.contains(as->name));
250 						augmentedHash.insert(as->name, as);
251 					}
252 				}
253 			}
254 		}
255 	}
256 
257 	/////////
258 	for(int i=0; i<this->augmentedYearsList.size(); i++){
259 		StudentsYear* sty=this->augmentedYearsList[i];
260 
261 		//if this year has no groups, insert something to simulate the whole year
262 		if(sty->groupsList.count()==0){
263 			StudentsGroup* tmpGroup = new StudentsGroup();
264 			tmpGroup->name = sty->name+" "+tr("Automatic Group", "Please keep the translation short. It is used when a year contains no groups and an automatic group "
265 			 "is added in the year, in the timetable (when viewing the students timetable from FET and also in the html timetables for students groups or subgroups)"
266 			 ". In the empty year there will be added a group with name = yearName+a space character+your translation of 'Automatic Group'.");
267 			tmpGroup->numberOfStudents = sty->numberOfStudents;
268 			sty->groupsList << tmpGroup;
269 		}
270 
271 		for(int j=0; j<sty->groupsList.size(); j++){
272 			StudentsGroup* stg=sty->groupsList[j];
273 
274 			//if this group has no subgroups, insert something to simulate the whole group
275 			if(stg->subgroupsList.size()==0){
276 				StudentsSubgroup* tmpSubgroup = new StudentsSubgroup();
277 				tmpSubgroup->name = stg->name+" "+tr("Automatic Subgroup", "Please keep the translation short. It is used when a group contains no subgroups and an automatic subgroup "
278 				 "is added in the group, in the timetable (when viewing the students timetable from FET and also in the html timetables for students subgroups)"
279 				 ". In the empty group there will be added a subgroup with name = groupName+a space character+your translation of 'Automatic Subgroup'.");
280 				tmpSubgroup->numberOfStudents=stg->numberOfStudents;
281 				stg->subgroupsList << tmpSubgroup;
282 			}
283 		}
284 	}
285 	//////////
286 
287 	QSet<StudentsGroup*> allGroupsSet;
288 	QSet<StudentsSubgroup*> allSubgroupsSet;
289 	QList<StudentsGroup*> allGroupsList;
290 	QList<StudentsSubgroup*> allSubgroupsList;
291 
292 	for(int i=0; i<this->augmentedYearsList.size(); i++){
293 		StudentsYear* sty=this->augmentedYearsList.at(i);
294 		sty->indexInAugmentedYearsList=i;
295 
296 		for(int j=0; j<sty->groupsList.size(); j++){
297 			StudentsGroup* stg=sty->groupsList.at(j);
298 			if(!allGroupsSet.contains(stg)){
299 				allGroupsSet.insert(stg);
300 				allGroupsList.append(stg);
301 				stg->indexInInternalGroupsList=allGroupsSet.count()-1;
302 			}
303 
304 			for(int k=0; k<stg->subgroupsList.size(); k++)
305 				if(!allSubgroupsSet.contains(stg->subgroupsList.at(k))){
306 					allSubgroupsSet.insert(stg->subgroupsList.at(k));
307 					allSubgroupsList.append(stg->subgroupsList.at(k));
308 					stg->subgroupsList.at(k)->indexInInternalSubgroupsList=allSubgroupsSet.count()-1;
309 				}
310 		}
311 	}
312 	int tmpNSubgroups=allSubgroupsList.count();
313 	if(tmpNSubgroups>MAX_TOTAL_SUBGROUPS){
314 		RulesImpossible::warning(parent, tr("FET information"),
315 		 tr("You have too many total subgroups. You need to increase the variable MAX_TOTAL_SUBGROUPS (which is currently %1).")
316 		 .arg(MAX_TOTAL_SUBGROUPS));
317 		return false;
318 	}
319 	this->internalSubgroupsList.resize(tmpNSubgroups);
320 
321 	int counter=0;
322 	for(int i=0; i<this->activitiesList.size(); i++){
323 		Activity* act=this->activitiesList.at(i);
324 		if(act->active)
325 			counter++;
326 	}
327 	if(counter>MAX_ACTIVITIES){
328 		RulesImpossible::warning(parent, tr("FET information"),
329 		 tr("You have too many active activities. You need to increase the variable MAX_ACTIVITIES (which is currently %1).")
330 		 .arg(MAX_ACTIVITIES));
331 		return false;
332 	}
333 
334 	if(this->buildingsList.size()>MAX_BUILDINGS){
335 		RulesImpossible::warning(parent, tr("FET information"),
336 		 tr("You have too many buildings. You need to increase the variable MAX_BUILDINGS (which is currently %1).")
337 		 .arg(MAX_BUILDINGS));
338 		return false;
339 	}
340 
341 	if(this->roomsList.size()>MAX_ROOMS){
342 		RulesImpossible::warning(parent, tr("FET information"),
343 		 tr("You have too many rooms. You need to increase the variable MAX_ROOMS (which is currently %1).")
344 		 .arg(MAX_ROOMS));
345 		return false;
346 	}
347 
348 	assert(this->initialized);
349 
350 	//days and hours
351 	assert(this->nHoursPerDay>0);
352 	assert(this->nDaysPerWeek>0);
353 	this->nHoursPerWeek=this->nHoursPerDay*this->nDaysPerWeek;
354 
355 	//teachers
356 	int i;
357 	Teacher* tch;
358 	this->nInternalTeachers=this->teachersList.size();
359 	this->internalTeachersList.resize(this->nInternalTeachers);
360 	for(i=0; i<this->teachersList.size(); i++){
361 		tch=teachersList[i];
362 		this->internalTeachersList[i]=tch;
363 	}
364 	assert(i==this->nInternalTeachers);
365 
366 	teachersHash.clear();
367 	for(int i=0; i<nInternalTeachers; i++)
368 		teachersHash.insert(internalTeachersList[i]->name, i);
369 
370 	//subjects
371 	Subject* sbj;
372 	this->nInternalSubjects=this->subjectsList.size();
373 	this->internalSubjectsList.resize(this->nInternalSubjects);
374 	for(i=0; i<this->subjectsList.size(); i++){
375 		sbj=this->subjectsList[i];
376 		this->internalSubjectsList[i]=sbj;
377 	}
378 	assert(i==this->nInternalSubjects);
379 
380 	subjectsHash.clear();
381 	for(int i=0; i<nInternalSubjects; i++)
382 		subjectsHash.insert(internalSubjectsList[i]->name, i);
383 
384 	//activity tags
385 	ActivityTag* at;
386 	this->nInternalActivityTags=this->activityTagsList.size();
387 	this->internalActivityTagsList.resize(this->nInternalActivityTags);
388 	for(i=0; i<this->activityTagsList.size(); i++){
389 		at=this->activityTagsList[i];
390 		this->internalActivityTagsList[i]=at;
391 	}
392 	assert(i==this->nInternalActivityTags);
393 
394 	activityTagsHash.clear();
395 	for(int i=0; i<nInternalActivityTags; i++)
396 		activityTagsHash.insert(internalActivityTagsList[i]->name, i);
397 
398 	//students
399 	this->nInternalSubgroups=0;
400 	for(int i=0; i<allSubgroupsList.count(); i++){
401 		assert(allSubgroupsList.at(i)->indexInInternalSubgroupsList==i);
402 		this->internalSubgroupsList[this->nInternalSubgroups]=allSubgroupsList.at(i);
403 		this->nInternalSubgroups++;
404 	}
405 
406 	this->internalGroupsList.clear();
407 	for(int i=0; i<allGroupsList.count(); i++){
408 		assert(allGroupsList.at(i)->indexInInternalGroupsList==i);
409 		this->internalGroupsList.append(allGroupsList.at(i));
410 	}
411 
412 	studentsHash.clear();
413 	for(StudentsYear* year : qAsConst(augmentedYearsList)){
414 		studentsHash.insert(year->name, year);
415 		for(StudentsGroup* group : qAsConst(year->groupsList)){
416 			studentsHash.insert(group->name, group);
417 			for(StudentsSubgroup* subgroup : qAsConst(group->subgroupsList))
418 				studentsHash.insert(subgroup->name, subgroup);
419 		}
420 	}
421 
422 	assert(this->nInternalSubgroups==tmpNSubgroups);
423 
424 	//buildings
425 	internalBuildingsList.resize(buildingsList.size());
426 	this->nInternalBuildings=0;
427 	assert(this->buildingsList.size()<=MAX_BUILDINGS);
428 	for(int i=0; i<this->buildingsList.size(); i++){
429 		Building* bu=this->buildingsList[i];
430 		bu->computeInternalStructure(*this);
431 	}
432 
433 	for(int i=0; i<this->buildingsList.size(); i++){
434 		Building* bu=this->buildingsList[i];
435 		this->internalBuildingsList[this->nInternalBuildings++]=bu;
436 	}
437 	assert(this->nInternalBuildings==this->buildingsList.size());
438 
439 	buildingsHash.clear();
440 	for(int i=0; i<nInternalBuildings; i++)
441 		buildingsHash.insert(internalBuildingsList[i]->name, i);
442 
443 	//rooms
444 	internalRoomsList.resize(roomsList.size());
445 	this->nInternalRooms=0;
446 	assert(this->roomsList.size()<=MAX_ROOMS);
447 	for(int i=0; i<this->roomsList.size(); i++){
448 		Room* rm=this->roomsList[i];
449 		rm->computeInternalStructure(*this);
450 	}
451 
452 	for(int i=0; i<this->roomsList.size(); i++){
453 		Room* rm=this->roomsList[i];
454 		this->internalRoomsList[this->nInternalRooms++]=rm;
455 	}
456 	assert(this->nInternalRooms==this->roomsList.size());
457 
458 	roomsHash.clear();
459 	for(int i=0; i<nInternalRooms; i++)
460 		roomsHash.insert(internalRoomsList[i]->name, i);
461 
462 	for(int i=0; i<nInternalRooms; i++){
463 		Room* rm=internalRoomsList[i];
464 
465 		if(rm->isVirtual){
466 			if(rm->realRoomsSetsList.count()==0){
467 				RulesImpossible::warning(parent, tr("FET information"), tr("Virtual room %1 has 0 sets of real rooms to choose"
468 				 " from. The number of sets of real rooms must be at least 2. Please correct this.").arg(rm->name));
469 				return false;
470 			}
471 			if(rm->realRoomsSetsList.count()==1){
472 				RulesImpossible::warning(parent, tr("FET information"), tr("Virtual room %1 has only 1 set of real rooms to choose"
473 				 " from. The number of sets of real rooms must be at least 2. Please correct this.").arg(rm->name));
474 				return false;
475 			}
476 
477 			int i=0;
478 			for(const QStringList& tl : qAsConst(rm->realRoomsSetsList)){
479 				if(tl.count()==0){
480 					RulesImpossible::warning(parent, tr("FET information"), tr("Virtual room %1, in set number %2, has 0 real rooms"
481 					 " to choose from. The number of real rooms from each set must be at least 1. Please correct this.").arg(rm->name).arg(i+1));
482 					return false;
483 				}
484 
485 				QStringList tl2;
486 				QSet<QString> ts;
487 				for(const QString& t : qAsConst(tl))
488 					if(!ts.contains(t))
489 						ts.insert(t);
490 					else
491 						tl2.append(t);
492 				if(!tl2.isEmpty()){
493 					RulesImpossible::warning(parent, tr("FET information"), tr("Virtual room %1, in set number %2, has these duplicate real rooms names: %3."
494 					 " Please correct this.").arg(rm->name).arg(i+1).arg(tl2.join(", ")));
495 					return false;
496 				}
497 
498 				for(const QString& rr : qAsConst(tl)){
499 					int rri=roomsHash.value(rr, -1);
500 
501 					if(rri==-1){
502 						RulesImpossible::warning(parent, tr("FET information"),
503 						 tr("The virtual room %1 contains the unrecognized real room %2 in the sets of real rooms - please correct this.").arg(rm->name).arg(rr));
504 
505 						return false;
506 					}
507 
508 					assert(rri>=0);
509 					if(internalRoomsList[rri]->isVirtual==true){
510 						RulesImpossible::warning(parent, tr("FET information"), tr("Virtual room %1, in set number %2, contains the virtual room"
511 						 " %3 - please correct this (a virtual room can only contain sets with real rooms).").arg(rm->name).arg(i+1).arg(rr));
512 						return false;
513 					}
514 				}
515 
516 				i++;
517 			}
518 		}
519 
520 		rm->computeInternalStructureRealRoomsSetsList(*this);
521 	}
522 
523 	//activities
524 	int range=0;
525 	for(Activity* act : qAsConst(this->activitiesList))
526 		if(act->active)
527 			range++;
528 	QProgressDialog progress(parent);
529 	progress.setWindowTitle(tr("Computing internal structure", "Title of a progress dialog"));
530 	progress.setLabelText(tr("Processing internally the activities ... please wait"));
531 	progress.setRange(0, qMax(range, 1));
532 	progress.setModal(true);
533 	int ttt=0;
534 
535 	Activity* act;
536 	counter=0;
537 
538 	this->inactiveActivities.clear();
539 
540 	for(int i=0; i<this->activitiesList.size(); i++){
541 		act=this->activitiesList[i];
542 		if(act->active){
543 			progress.setValue(ttt);
544 			//pqapplication->processEvents();
545 			if(progress.wasCanceled()){
546 				progress.setValue(range);
547 				RulesImpossible::warning(parent, tr("FET information"), tr("Canceled"));
548 				return false;
549 			}
550 			ttt++;
551 
552 			counter++;
553 			act->computeInternalStructure(*this);
554 		}
555 		else
556 			inactiveActivities.insert(act->id);
557 	}
558 
559 	progress.setValue(qMax(range, 1));
560 
561 	for(int i=0; i<nInternalSubgroups; i++)
562 		internalSubgroupsList[i]->activitiesForSubgroup.clear();
563 	for(int i=0; i<nInternalTeachers; i++)
564 		internalTeachersList[i]->activitiesForTeacher.clear();
565 
566 	assert(counter<=MAX_ACTIVITIES);
567 	this->nInternalActivities=counter;
568 	this->internalActivitiesList.resize(this->nInternalActivities);
569 	int activei=0;
570 	for(int ai=0; ai<this->activitiesList.size(); ai++){
571 		act=this->activitiesList[ai];
572 		if(act->active){
573 			this->internalActivitiesList[activei]=*act;
574 
575 			for(int j=0; j<act->iSubgroupsList.count(); j++){
576 				int k=act->iSubgroupsList.at(j);
577 				//The test below takes time
578 				//assert(!internalSubgroupsList[k]->activitiesForSubgroup.contains(activei));
579 				internalSubgroupsList[k]->activitiesForSubgroup.append(activei);
580 			}
581 
582 			for(int j=0; j<act->iTeachersList.count(); j++){
583 				int k=act->iTeachersList.at(j);
584 				//The test below takes time
585 				//assert(!internalTeachersList[k]->activitiesForTeacher.contains(activei));
586 				internalTeachersList[k]->activitiesForTeacher.append(activei);
587 			}
588 
589 			activei++;
590 		}
591 	}
592 
593 	activitiesHash.clear();
594 	for(int i=0; i<nInternalActivities; i++){
595 		assert(!activitiesHash.contains(internalActivitiesList[i].id));
596 		activitiesHash.insert(internalActivitiesList[i].id, i);
597 	}
598 
599 	//activities list for each subject - used for subjects timetable - in order for students and teachers
600 	activitiesForSubjectList.resize(nInternalSubjects);
601 	activitiesForSubjectSet.resize(nInternalSubjects);
602 	for(int sb=0; sb<nInternalSubjects; sb++){
603 		activitiesForSubjectList[sb].clear();
604 		activitiesForSubjectSet[sb].clear();
605 	}
606 
607 	for(int i=0; i<this->augmentedYearsList.size(); i++){
608 		StudentsYear* sty=this->augmentedYearsList[i];
609 
610 		for(int j=0; j<sty->groupsList.size(); j++){
611 			StudentsGroup* stg=sty->groupsList[j];
612 
613 			for(int k=0; k<stg->subgroupsList.size(); k++){
614 				StudentsSubgroup* sts=stg->subgroupsList[k];
615 
616 				for(int ai : qAsConst(internalSubgroupsList[sts->indexInInternalSubgroupsList]->activitiesForSubgroup))
617 					if(!activitiesForSubjectSet[internalActivitiesList[ai].subjectIndex].contains(ai)){
618 						activitiesForSubjectList[internalActivitiesList[ai].subjectIndex].append(ai);
619 						activitiesForSubjectSet[internalActivitiesList[ai].subjectIndex].insert(ai);
620 					}
621 			}
622 		}
623 	}
624 
625 	for(int i=0; i<nInternalTeachers; i++){
626 		for(int ai : qAsConst(internalTeachersList[i]->activitiesForTeacher))
627 			if(!activitiesForSubjectSet[internalActivitiesList[ai].subjectIndex].contains(ai)){
628 				activitiesForSubjectList[internalActivitiesList[ai].subjectIndex].append(ai);
629 				activitiesForSubjectSet[internalActivitiesList[ai].subjectIndex].insert(ai);
630 			}
631 	}
632 
633 	//for activities without students or teachers
634 	for(int ai=0; ai<nInternalActivities; ai++){
635 		int si=internalActivitiesList[ai].subjectIndex;
636 		if(!activitiesForSubjectSet[si].contains(ai)){
637 			activitiesForSubjectList[si].append(ai);
638 			activitiesForSubjectSet[si].insert(ai);
639 		}
640 	}
641 	/////////////////////////////////////////////////////////////////
642 
643 	//activities list for each activity tag - used for activity tags timetable - in order for students and teachers
644 	activitiesForActivityTagList.resize(nInternalActivityTags);
645 	activitiesForActivityTagSet.resize(nInternalActivityTags);
646 	for(int a=0; a<nInternalActivityTags; a++){
647 		activitiesForActivityTagList[a].clear();
648 		activitiesForActivityTagSet[a].clear();
649 	}
650 
651 	for(int i=0; i<this->augmentedYearsList.size(); i++){
652 		StudentsYear* sty=this->augmentedYearsList[i];
653 
654 		for(int j=0; j<sty->groupsList.size(); j++){
655 			StudentsGroup* stg=sty->groupsList[j];
656 
657 			for(int k=0; k<stg->subgroupsList.size(); k++){
658 				StudentsSubgroup* sts=stg->subgroupsList[k];
659 
660 				for(int ai : qAsConst(internalSubgroupsList[sts->indexInInternalSubgroupsList]->activitiesForSubgroup))
661 					for(int activityTagInt : qAsConst(internalActivitiesList[ai].iActivityTagsSet))
662 						if(!activitiesForActivityTagSet[activityTagInt].contains(ai)){
663 							activitiesForActivityTagList[activityTagInt].append(ai);
664 							activitiesForActivityTagSet[activityTagInt].insert(ai);
665 						}
666 			}
667 		}
668 	}
669 
670 	for(int i=0; i<nInternalTeachers; i++){
671 		for(int ai : qAsConst(internalTeachersList[i]->activitiesForTeacher))
672 			for(int activityTagInt : qAsConst(internalActivitiesList[ai].iActivityTagsSet))
673 				if(!activitiesForActivityTagSet[activityTagInt].contains(ai)){
674 					activitiesForActivityTagList[activityTagInt].append(ai);
675 					activitiesForActivityTagSet[activityTagInt].insert(ai);
676 				}
677 	}
678 
679 	//for activities without students or teachers
680 	for(int ai=0; ai<nInternalActivities; ai++){
681 		for(int ati : qAsConst(internalActivitiesList[ai].iActivityTagsSet)){
682 			if(!activitiesForActivityTagSet[ati].contains(ai)){
683 				activitiesForActivityTagList[ati].append(ai);
684 				activitiesForActivityTagSet[ati].insert(ai);
685 			}
686 		}
687 	}
688 	/////////////////////////////////////////////////////////////////
689 
690 	bool ok=true;
691 
692 	//time constraints
693 	//progress.reset();
694 
695 	bool skipInactiveTimeConstraints=false;
696 
697 	TimeConstraint* tctr;
698 
699 	QSet<int> toSkipTimeSet;
700 
701 	int _c=0;
702 
703 	for(int tctrindex=0; tctrindex<this->timeConstraintsList.size(); tctrindex++){
704 		tctr=this->timeConstraintsList[tctrindex];
705 
706 		if(!tctr->active){
707 			toSkipTimeSet.insert(tctrindex);
708 		}
709 		else if(tctr->hasInactiveActivities(*this)){
710 			//toSkipTime[tctrindex]=true;
711 			toSkipTimeSet.insert(tctrindex);
712 
713 			if(!skipInactiveTimeConstraints){
714 				QString s=tr("The following time constraint is ignored, because it refers to inactive activities:");
715 				s+="\n";
716 				s+=tctr->getDetailedDescription(*this);
717 
718 				int t=RulesConstraintIgnored::mediumConfirmation(parent, tr("FET information"), s,
719 				 tr("Skip rest"), tr("See next"), QString(),
720  				 1, 0 );
721 
722 				if(t==0)
723 					skipInactiveTimeConstraints=true;
724 			}
725 		}
726 		else{
727 			//toSkipTime[tctrindex]=false;
728 			_c++;
729 		}
730 	}
731 
732 	internalTimeConstraintsList.resize(_c);
733 
734 	progress.setLabelText(tr("Processing internally the time constraints ... please wait"));
735 	progress.setRange(0, qMax(timeConstraintsList.size(), 1));
736 	ttt=0;
737 
738 	//assert(this->timeConstraintsList.size()<=MAX_TIME_CONSTRAINTS);
739 	int tctri=0;
740 
741 	for(int tctrindex=0; tctrindex<this->timeConstraintsList.size(); tctrindex++){
742 		progress.setValue(ttt);
743 		//pqapplication->processEvents();
744 		if(progress.wasCanceled()){
745 			progress.setValue(timeConstraintsList.size());
746 			RulesImpossible::warning(parent, tr("FET information"), tr("Canceled"));
747 			return false;
748 		}
749 		ttt++;
750 
751 		tctr=this->timeConstraintsList[tctrindex];
752 
753 		if(toSkipTimeSet.contains(tctrindex))
754 			continue;
755 
756 		if(!tctr->computeInternalStructure(parent, *this)){
757 			//assert(0);
758 			ok=false;
759 			continue;
760 		}
761 		this->internalTimeConstraintsList[tctri++]=tctr;
762 	}
763 
764 	progress.setValue(qMax(timeConstraintsList.size(), 1));
765 
766 	this->nInternalTimeConstraints=tctri;
767 	if(VERBOSE){
768 		cout<<_c<<" time constraints after first pass (after removing inactive ones)"<<endl;
769 		cout<<"  "<<this->nInternalTimeConstraints<<" time constraints after second pass (after removing wrong ones)"<<endl;
770 	}
771 	assert(_c>=this->nInternalTimeConstraints); //because some constraints may have toSkipTime false, but computeInternalStructure also false
772 	//assert(this->nInternalTimeConstraints<=MAX_TIME_CONSTRAINTS);
773 
774 	//space constraints
775 	//progress.reset();
776 
777 	bool skipInactiveSpaceConstraints=false;
778 
779 	SpaceConstraint* sctr;
780 
781 	QSet<int> toSkipSpaceSet;
782 
783 	_c=0;
784 
785 	for(int sctrindex=0; sctrindex<this->spaceConstraintsList.size(); sctrindex++){
786 		sctr=this->spaceConstraintsList[sctrindex];
787 
788 		if(!sctr->active){
789 			toSkipSpaceSet.insert(sctrindex);
790 		}
791 		else if(sctr->hasInactiveActivities(*this)){
792 			//toSkipSpace[sctrindex]=true;
793 			toSkipSpaceSet.insert(sctrindex);
794 
795 			if(!skipInactiveSpaceConstraints){
796 				QString s=tr("The following space constraint is ignored, because it refers to inactive activities:");
797 				s+="\n";
798 				s+=sctr->getDetailedDescription(*this);
799 
800 				int t=RulesConstraintIgnored::mediumConfirmation(parent, tr("FET information"), s,
801 				 tr("Skip rest"), tr("See next"), QString(),
802  				 1, 0 );
803 
804 				if(t==0)
805 					skipInactiveSpaceConstraints=true;
806 			}
807 		}
808 		else{
809 			_c++;
810 			//toSkipSpace[sctrindex]=false;
811 		}
812 	}
813 
814 	internalSpaceConstraintsList.resize(_c);
815 
816 	progress.setLabelText(tr("Processing internally the space constraints ... please wait"));
817 	progress.setRange(0, qMax(spaceConstraintsList.size(), 1));
818 	ttt=0;
819 	//assert(this->spaceConstraintsList.size()<=MAX_SPACE_CONSTRAINTS);
820 
821 	int sctri=0;
822 
823 	for(int sctrindex=0; sctrindex<this->spaceConstraintsList.size(); sctrindex++){
824 		progress.setValue(ttt);
825 		//pqapplication->processEvents();
826 		if(progress.wasCanceled()){
827 			progress.setValue(spaceConstraintsList.size());
828 			RulesImpossible::warning(parent, tr("FET information"), tr("Canceled"));
829 			return false;
830 		}
831 		ttt++;
832 
833 		sctr=this->spaceConstraintsList[sctrindex];
834 
835 		if(toSkipSpaceSet.contains(sctrindex))
836 			continue;
837 
838 		if(!sctr->computeInternalStructure(parent, *this)){
839 			//assert(0);
840 			ok=false;
841 			continue;
842 		}
843 		this->internalSpaceConstraintsList[sctri++]=sctr;
844 	}
845 
846 	progress.setValue(qMax(spaceConstraintsList.size(), 1));
847 
848 	this->nInternalSpaceConstraints=sctri;
849 	if(VERBOSE){
850 		cout<<_c<<" space constraints after first pass (after removing inactive ones)"<<endl;
851 		cout<<"  "<<this->nInternalSpaceConstraints<<" space constraints after second pass (after removing wrong ones)"<<endl;
852 	}
853 	assert(_c>=this->nInternalSpaceConstraints); //because some constraints may have toSkipSpace false, but computeInternalStructure also false
854 	//assert(this->nInternalSpaceConstraints<=MAX_SPACE_CONSTRAINTS);
855 
856 	//group activities in initial order
857 	if(groupActivitiesInInitialOrderList.count()>0){
858 		QStringList fetBugs;
859 		QStringList userErrors;
860 
861 		QSet<int> visitedIds;
862 		for(int j=0; j<groupActivitiesInInitialOrderList.count(); j++){
863 			GroupActivitiesInInitialOrderItem* item=groupActivitiesInInitialOrderList[j];
864 
865 			if(!item->active)
866 				continue;
867 
868 			if(item->ids.count()<2){
869 				fetBugs.append(tr("All 'group activities in the initial order for timetable generation' items should contain at least two activities ids."
870 				 " This is not true for item number %1. Please report potential bug.").arg(j+1));
871 			}
872 
873 			item->indices.clear();
874 			for(int id : qAsConst(item->ids)){
875 				if(visitedIds.contains(id)){
876 					userErrors.append(tr("All 'group activities in the initial order for timetable generation' items should have different activities ids."
877 					 " (Each activity id must appear at most once in all the items.) This is not true for item number %1 and activity id %2.").arg(j+1).arg(id));
878 				}
879 				else{
880 					visitedIds.insert(id);
881 					int index=activitiesHash.value(id, -1);
882 					if(index>=0)
883 						item->indices.append(index);
884 				}
885 			}
886 
887 			if(!fetBugs.isEmpty() || !userErrors.isEmpty()){
888 				RulesImpossible::warning(parent, tr("FET information"), fetBugs.join("\n\n")+userErrors.join("\n\n"));
889 				return false;
890 			}
891 		}
892 	}
893 
894 	//done.
895 	this->internalStructureComputed=ok;
896 
897 	return ok;
898 }
899 
kill()900 void Rules::kill() //clears memory for the rules, destroys them
901 {
902 	//Teachers
903 	for(Teacher* tch : qAsConst(teachersList))
904 		delete tch;
905 	teachersList.clear();
906 	//while(!teachersList.isEmpty())
907 	//	delete teachersList.takeFirst();
908 
909 	//Subjects
910 	for(Subject* sbj : qAsConst(subjectsList))
911 		delete sbj;
912 	subjectsList.clear();
913 	//while(!subjectsList.isEmpty())
914 	//	delete subjectsList.takeFirst();
915 
916 	//Activity tags
917 	for(ActivityTag* at : qAsConst(activityTagsList))
918 		delete at;
919 	activityTagsList.clear();
920 	//while(!activityTagsList.isEmpty())
921 	//	delete activityTagsList.takeFirst();
922 
923 	//Years
924 	/*while(!yearsList.isEmpty())
925 		delete yearsList.takeFirst();*/
926 
927 	//students sets
928 	QSet<StudentsYear*> iyears;
929 	QSet<StudentsGroup*> igroups;
930 	QSet<StudentsSubgroup*> isubgroups;
931 	for(StudentsYear* year : qAsConst(yearsList)){
932 		if(!iyears.contains(year))
933 			iyears.insert(year);
934 		for(StudentsGroup* group : qAsConst(year->groupsList)){
935 			if(!igroups.contains(group))
936 				igroups.insert(group);
937 			for(StudentsSubgroup* subgroup : qAsConst(group->subgroupsList)){
938 				if(!isubgroups.contains(subgroup))
939 					isubgroups.insert(subgroup);
940 			}
941 		}
942 	}
943 	for(StudentsYear* year : qAsConst(iyears)){
944 		assert(year!=nullptr);
945 		delete year;
946 	}
947 	for(StudentsGroup* group : qAsConst(igroups)){
948 		assert(group!=nullptr);
949 		delete group;
950 	}
951 	for(StudentsSubgroup* subgroup : qAsConst(isubgroups)){
952 		assert(subgroup!=nullptr);
953 		delete subgroup;
954 	}
955 	yearsList.clear();
956 
957 	permanentStudentsHash.clear();
958 	//////////////////
959 
960 	//kill augmented students sets
961 	QList<StudentsYear*> ayears;
962 	QList<StudentsGroup*> agroups;
963 	QList<StudentsSubgroup*> asubgroups;
964 	for(StudentsYear* year : qAsConst(augmentedYearsList)){
965 		if(!ayears.contains(year))
966 			ayears.append(year);
967 		for(StudentsGroup* group : qAsConst(year->groupsList)){
968 			if(!agroups.contains(group))
969 				agroups.append(group);
970 			for(StudentsSubgroup* subgroup : qAsConst(group->subgroupsList)){
971 				if(!asubgroups.contains(subgroup))
972 					asubgroups.append(subgroup);
973 			}
974 		}
975 	}
976 	for(StudentsYear* year : qAsConst(ayears)){
977 		assert(year!=nullptr);
978 		delete year;
979 	}
980 	for(StudentsGroup* group : qAsConst(agroups)){
981 		assert(group!=nullptr);
982 		delete group;
983 	}
984 	for(StudentsSubgroup* subgroup : qAsConst(asubgroups)){
985 		assert(subgroup!=nullptr);
986 		delete subgroup;
987 	}
988 	augmentedYearsList.clear();
989 	//////////////////
990 
991 	//Activities
992 	for(Activity* act : qAsConst(activitiesList))
993 		delete act;
994 	activitiesList.clear();
995 	//while(!activitiesList.isEmpty())
996 	//	delete activitiesList.takeFirst();
997 
998 	//Time constraints
999 	for(TimeConstraint* tc : qAsConst(timeConstraintsList))
1000 		delete tc;
1001 	timeConstraintsList.clear();
1002 	//while(!timeConstraintsList.isEmpty())
1003 	//	delete timeConstraintsList.takeFirst();
1004 
1005 	//Space constraints
1006 	for(SpaceConstraint* sc : qAsConst(spaceConstraintsList))
1007 		delete sc;
1008 	spaceConstraintsList.clear();
1009 	//while(!spaceConstraintsList.isEmpty())
1010 	//	delete spaceConstraintsList.takeFirst();
1011 
1012 	//Buildings
1013 	for(Building* bu : qAsConst(buildingsList))
1014 		delete bu;
1015 	buildingsList.clear();
1016 	//while(!buildingsList.isEmpty())
1017 	//	delete buildingsList.takeFirst();
1018 
1019 	//Rooms
1020 	for(Room* rm : qAsConst(roomsList))
1021 		delete rm;
1022 	roomsList.clear();
1023 	//while(!roomsList.isEmpty())
1024 	//	delete roomsList.takeFirst();
1025 
1026 	for(GroupActivitiesInInitialOrderItem* ga : qAsConst(groupActivitiesInInitialOrderList))
1027 		delete ga;
1028 	groupActivitiesInInitialOrderList.clear();
1029 	//while(!groupActivitiesInInitialOrderList.isEmpty())
1030 	//	delete groupActivitiesInInitialOrderList.takeFirst();
1031 
1032 	activitiesPointerHash.clear();
1033 	bctSet.clear();
1034 	btSet.clear();
1035 	bcsSet.clear();
1036 	apstHash.clear();
1037 	aprHash.clear();
1038 	mdbaHash.clear();
1039 	tnatHash.clear();
1040 	ssnatHash.clear();
1041 
1042 	teachersHash.clear();
1043 	subjectsHash.clear();
1044 	activityTagsHash.clear();
1045 	studentsHash.clear();
1046 	buildingsHash.clear();
1047 	roomsHash.clear();
1048 	activitiesHash.clear();
1049 
1050 	//done
1051 	this->internalStructureComputed=false;
1052 	this->initialized=false;
1053 
1054 	teachers_schedule_ready=false;
1055 	students_schedule_ready=false;
1056 	rooms_schedule_ready=false;
1057 }
1058 
Rules()1059 Rules::Rules()
1060 {
1061 	this->initialized=false;
1062 	this->modified=false;
1063 }
1064 
~Rules()1065 Rules::~Rules()
1066 {
1067 	if(this->initialized)
1068 		this->kill();
1069 }
1070 
setMode(int newMode)1071 void Rules::setMode(int newMode)
1072 {
1073 	if(newMode==mode)
1074 		return;
1075 
1076 	if(newMode==OFFICIAL || newMode==BLOCK_PLANNING || newMode==TERMS){
1077 		for(Teacher* tch : qAsConst(teachersList))
1078 			tch->morningsAfternoonsBehavior=TEACHER_MORNINGS_AFTERNOONS_BEHAVIOR_NOT_INITIALIZED;
1079 	}
1080 	else if(newMode==MORNINGS_AFTERNOONS){
1081 		for(Teacher* tch : qAsConst(teachersList))
1082 			if(tch->morningsAfternoonsBehavior==TEACHER_MORNINGS_AFTERNOONS_BEHAVIOR_NOT_INITIALIZED)
1083 				tch->morningsAfternoonsBehavior=TEACHER_UNRESTRICTED_MORNINGS_AFTERNOONS;
1084 	}
1085 	else{
1086 		assert(0);
1087 	}
1088 
1089 	this->mode=newMode;
1090 
1091 	this->internalStructureComputed=false;
1092 	setRulesModifiedAndOtherThings(this);
1093 
1094 	teachers_schedule_ready=false;
1095 	students_schedule_ready=false;
1096 	rooms_schedule_ready=false;
1097 }
1098 
setTerms(int numberOfTerms,int numberOfDaysPerTerm)1099 void Rules::setTerms(int numberOfTerms, int numberOfDaysPerTerm)
1100 {
1101 	assert(this->mode==TERMS);
1102 
1103 	this->nTerms=numberOfTerms;
1104 	this->nDaysPerTerm=numberOfDaysPerTerm;
1105 
1106 	this->internalStructureComputed=false;
1107 	setRulesModifiedAndOtherThings(this);
1108 
1109 	teachers_schedule_ready=false;
1110 	students_schedule_ready=false;
1111 	rooms_schedule_ready=false;
1112 }
1113 
setInstitutionName(const QString & newInstitutionName)1114 void Rules::setInstitutionName(const QString& newInstitutionName)
1115 {
1116 	this->institutionName=newInstitutionName;
1117 	this->internalStructureComputed=false;
1118 	setRulesModifiedAndOtherThings(this);
1119 }
1120 
setComments(const QString & newComments)1121 void Rules::setComments(const QString& newComments)
1122 {
1123 	this->comments=newComments;
1124 	this->internalStructureComputed=false;
1125 	setRulesModifiedAndOtherThings(this);
1126 }
1127 
addTeacher(Teacher * teacher)1128 bool Rules::addTeacher(Teacher* teacher)
1129 {
1130 	for(int i=0; i<this->teachersList.size(); i++){
1131 		Teacher* tch=this->teachersList[i];
1132 		if(tch->name==teacher->name)
1133 			return false;
1134 	}
1135 
1136 	this->internalStructureComputed=false;
1137 	setRulesModifiedAndOtherThings(this);
1138 
1139 	teachers_schedule_ready=false;
1140 	students_schedule_ready=false;
1141 	rooms_schedule_ready=false;
1142 
1143 	this->teachersList.append(teacher);
1144 	return true;
1145 }
1146 
addTeacherFast(Teacher * teacher)1147 bool Rules::addTeacherFast(Teacher* teacher)
1148 {
1149 	this->internalStructureComputed=false;
1150 	setRulesModifiedAndOtherThings(this);
1151 
1152 	teachers_schedule_ready=false;
1153 	students_schedule_ready=false;
1154 	rooms_schedule_ready=false;
1155 
1156 	this->teachersList.append(teacher);
1157 	return true;
1158 }
1159 
searchTeacher(const QString & teacherName)1160 int Rules::searchTeacher(const QString& teacherName)
1161 {
1162 	for(int i=0; i<this->teachersList.size(); i++)
1163 		if(this->teachersList.at(i)->name==teacherName)
1164 			return i;
1165 
1166 	return -1;
1167 }
1168 
removeTeacher(const QString & teacherName)1169 bool Rules::removeTeacher(const QString& teacherName)
1170 {
1171 	QList<int> idsToBeRemoved;
1172 	for(Activity* act : qAsConst(activitiesList)){
1173 		bool t=act->removeTeacher(teacherName);
1174 		if(t && act->teachersNames.count()==0)
1175 			idsToBeRemoved.append(act->id);
1176 	}
1177 	removeActivities(idsToBeRemoved, false);
1178 
1179 	for(int i=0; i<this->teachersList.size(); i++)
1180 		if(this->teachersList.at(i)->name==teacherName){
1181 			Teacher* tch=this->teachersList[i];
1182 			this->teachersList.removeAt(i);
1183 			delete tch;
1184 			break;
1185 		}
1186 
1187 	updateConstraintsAfterRemoval();
1188 
1189 	this->internalStructureComputed=false;
1190 	setRulesModifiedAndOtherThings(this);
1191 
1192 	teachers_schedule_ready=false;
1193 	students_schedule_ready=false;
1194 	rooms_schedule_ready=false;
1195 
1196 	return true;
1197 }
1198 
modifyTeacher(const QString & initialTeacherName,const QString & finalTeacherName)1199 bool Rules::modifyTeacher(const QString& initialTeacherName, const QString& finalTeacherName)
1200 {
1201 	assert(this->searchTeacher(finalTeacherName)==-1);
1202 	assert(this->searchTeacher(initialTeacherName)>=0);
1203 
1204 	for(int i=0; i<this->activitiesList.size(); i++)
1205 		this->activitiesList.at(i)->renameTeacher(initialTeacherName, finalTeacherName);
1206 
1207 	for(TimeConstraint* ctr : qAsConst(timeConstraintsList)){
1208 		if(ctr->type==CONSTRAINT_TEACHER_NOT_AVAILABLE_TIMES){
1209 			ConstraintTeacherNotAvailableTimes* crt_constraint=(ConstraintTeacherNotAvailableTimes*)ctr;
1210 			if(initialTeacherName == crt_constraint->teacher)
1211 				crt_constraint->teacher=finalTeacherName;
1212 		}
1213 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_GAPS_PER_WEEK){
1214 			ConstraintTeacherMaxGapsPerWeek* crt_constraint=(ConstraintTeacherMaxGapsPerWeek*)ctr;
1215 			if(initialTeacherName == crt_constraint->teacherName)
1216 				crt_constraint->teacherName=finalTeacherName;
1217 		}
1218 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_GAPS_PER_DAY){
1219 			ConstraintTeacherMaxGapsPerDay* crt_constraint=(ConstraintTeacherMaxGapsPerDay*)ctr;
1220 			if(initialTeacherName == crt_constraint->teacherName)
1221 				crt_constraint->teacherName=finalTeacherName;
1222 		}
1223 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_GAPS_PER_MORNING_AND_AFTERNOON){
1224 			ConstraintTeacherMaxGapsPerMorningAndAfternoon* crt_constraint=(ConstraintTeacherMaxGapsPerMorningAndAfternoon*)ctr;
1225 			if(initialTeacherName == crt_constraint->teacherName)
1226 				crt_constraint->teacherName=finalTeacherName;
1227 		}
1228 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_HOURS_DAILY){
1229 			ConstraintTeacherMaxHoursDaily* crt_constraint=(ConstraintTeacherMaxHoursDaily*)ctr;
1230 			if(initialTeacherName == crt_constraint->teacherName)
1231 				crt_constraint->teacherName=finalTeacherName;
1232 		}
1233 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_HOURS_CONTINUOUSLY){
1234 			ConstraintTeacherMaxHoursContinuously* crt_constraint=(ConstraintTeacherMaxHoursContinuously*)ctr;
1235 			if(initialTeacherName == crt_constraint->teacherName)
1236 				crt_constraint->teacherName=finalTeacherName;
1237 		}
1238 		else if(ctr->type==CONSTRAINT_TEACHER_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
1239 			ConstraintTeacherActivityTagMaxHoursContinuously* crt_constraint=(ConstraintTeacherActivityTagMaxHoursContinuously*)ctr;
1240 			if(initialTeacherName == crt_constraint->teacherName)
1241 				crt_constraint->teacherName=finalTeacherName;
1242 		}
1243 		else if(ctr->type==CONSTRAINT_TEACHER_ACTIVITY_TAG_MAX_HOURS_DAILY){
1244 			ConstraintTeacherActivityTagMaxHoursDaily* crt_constraint=(ConstraintTeacherActivityTagMaxHoursDaily*)ctr;
1245 			if(initialTeacherName == crt_constraint->teacherName)
1246 				crt_constraint->teacherName=finalTeacherName;
1247 		}
1248 		else if(ctr->type==CONSTRAINT_TEACHER_ACTIVITY_TAG_MIN_HOURS_DAILY){
1249 			ConstraintTeacherActivityTagMinHoursDaily* crt_constraint=(ConstraintTeacherActivityTagMinHoursDaily*)ctr;
1250 			if(initialTeacherName == crt_constraint->teacherName)
1251 				crt_constraint->teacherName=finalTeacherName;
1252 		}
1253 		else if(ctr->type==CONSTRAINT_TEACHER_MIN_HOURS_DAILY){
1254 			ConstraintTeacherMinHoursDaily* crt_constraint=(ConstraintTeacherMinHoursDaily*)ctr;
1255 			if(initialTeacherName == crt_constraint->teacherName)
1256 				crt_constraint->teacherName=finalTeacherName;
1257 		}
1258 		else if(ctr->type==CONSTRAINT_TEACHER_MIN_GAPS_BETWEEN_ORDERED_PAIR_OF_ACTIVITY_TAGS){
1259 			ConstraintTeacherMinGapsBetweenOrderedPairOfActivityTags* crt_constraint=(ConstraintTeacherMinGapsBetweenOrderedPairOfActivityTags*)ctr;
1260 			if(initialTeacherName == crt_constraint->teacher)
1261 				crt_constraint->teacher=finalTeacherName;
1262 		}
1263 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_DAYS_PER_WEEK){
1264 			ConstraintTeacherMaxDaysPerWeek* crt_constraint=(ConstraintTeacherMaxDaysPerWeek*)ctr;
1265 			if(initialTeacherName == crt_constraint->teacherName)
1266 				crt_constraint->teacherName=finalTeacherName;
1267 		}
1268 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_THREE_CONSECUTIVE_DAYS){
1269 			ConstraintTeacherMaxThreeConsecutiveDays* crt_constraint=(ConstraintTeacherMaxThreeConsecutiveDays*)ctr;
1270 			if(initialTeacherName == crt_constraint->teacherName)
1271 				crt_constraint->teacherName=finalTeacherName;
1272 		}
1273 		else if(ctr->type==CONSTRAINT_TEACHER_MIN_DAYS_PER_WEEK){
1274 			ConstraintTeacherMinDaysPerWeek* crt_constraint=(ConstraintTeacherMinDaysPerWeek*)ctr;
1275 			if(initialTeacherName == crt_constraint->teacherName)
1276 				crt_constraint->teacherName=finalTeacherName;
1277 		}
1278 		else if(ctr->type==CONSTRAINT_TEACHER_INTERVAL_MAX_DAYS_PER_WEEK){
1279 			ConstraintTeacherIntervalMaxDaysPerWeek* crt_constraint=(ConstraintTeacherIntervalMaxDaysPerWeek*)ctr;
1280 			if(initialTeacherName == crt_constraint->teacherName)
1281 				crt_constraint->teacherName=finalTeacherName;
1282 		}
1283 		else if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_TIME_SLOTS){
1284 			ConstraintActivitiesPreferredTimeSlots* crt_constraint=(ConstraintActivitiesPreferredTimeSlots*)ctr;
1285 			if(initialTeacherName == crt_constraint->p_teacherName)
1286 				crt_constraint->p_teacherName=finalTeacherName;
1287 		}
1288 		else if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_STARTING_TIMES){
1289 			ConstraintActivitiesPreferredStartingTimes* crt_constraint=(ConstraintActivitiesPreferredStartingTimes*)ctr;
1290 			if(initialTeacherName == crt_constraint->teacherName)
1291 				crt_constraint->teacherName=finalTeacherName;
1292 		}
1293 		else if(ctr->type==CONSTRAINT_ACTIVITIES_END_STUDENTS_DAY){
1294 			ConstraintActivitiesEndStudentsDay* crt_constraint=(ConstraintActivitiesEndStudentsDay*)ctr;
1295 			if(initialTeacherName == crt_constraint->teacherName)
1296 				crt_constraint->teacherName=finalTeacherName;
1297 		}
1298 		else if(ctr->type==CONSTRAINT_ACTIVITIES_END_TEACHERS_DAY){
1299 			ConstraintActivitiesEndTeachersDay* crt_constraint=(ConstraintActivitiesEndTeachersDay*)ctr;
1300 			if(initialTeacherName == crt_constraint->teacherName)
1301 				crt_constraint->teacherName=finalTeacherName;
1302 		}
1303 		else if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_TIME_SLOTS){
1304 			ConstraintSubactivitiesPreferredTimeSlots* crt_constraint=(ConstraintSubactivitiesPreferredTimeSlots*)ctr;
1305 			if(initialTeacherName == crt_constraint->p_teacherName)
1306 				crt_constraint->p_teacherName=finalTeacherName;
1307 		}
1308 		else if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_STARTING_TIMES){
1309 			ConstraintSubactivitiesPreferredStartingTimes* crt_constraint=(ConstraintSubactivitiesPreferredStartingTimes*)ctr;
1310 			if(initialTeacherName == crt_constraint->teacherName)
1311 				crt_constraint->teacherName=finalTeacherName;
1312 		}
1313 		//2017-02-07
1314 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_SPAN_PER_DAY){
1315 			ConstraintTeacherMaxSpanPerDay* crt_constraint=(ConstraintTeacherMaxSpanPerDay*)ctr;
1316 			if(initialTeacherName == crt_constraint->teacherName)
1317 				crt_constraint->teacherName=finalTeacherName;
1318 		}
1319 		else if(ctr->type==CONSTRAINT_TEACHER_MIN_RESTING_HOURS){
1320 			ConstraintTeacherMinRestingHours* crt_constraint=(ConstraintTeacherMinRestingHours*)ctr;
1321 			if(initialTeacherName == crt_constraint->teacherName)
1322 				crt_constraint->teacherName=finalTeacherName;
1323 		}
1324 
1325 		//mornings-afternoons
1326 		else if(ctr->type==CONSTRAINT_TEACHER_AFTERNOONS_EARLY_MAX_BEGINNINGS_AT_SECOND_HOUR){
1327 			ConstraintTeacherAfternoonsEarlyMaxBeginningsAtSecondHour* crt_constraint=(ConstraintTeacherAfternoonsEarlyMaxBeginningsAtSecondHour*)ctr;
1328 			if(initialTeacherName == crt_constraint->teacherName)
1329 				crt_constraint->teacherName=finalTeacherName;
1330 		}
1331 		else if(ctr->type==CONSTRAINT_TEACHER_MORNINGS_EARLY_MAX_BEGINNINGS_AT_SECOND_HOUR){
1332 			ConstraintTeacherMorningsEarlyMaxBeginningsAtSecondHour* crt_constraint=(ConstraintTeacherMorningsEarlyMaxBeginningsAtSecondHour*)ctr;
1333 			if(initialTeacherName == crt_constraint->teacherName)
1334 				crt_constraint->teacherName=finalTeacherName;
1335 		}
1336 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_GAPS_PER_REAL_DAY){
1337 			ConstraintTeacherMaxGapsPerRealDay* crt_constraint=(ConstraintTeacherMaxGapsPerRealDay*)ctr;
1338 			if(initialTeacherName == crt_constraint->teacherName)
1339 				crt_constraint->teacherName=finalTeacherName;
1340 		}
1341 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_GAPS_PER_WEEK_FOR_REAL_DAYS){
1342 			ConstraintTeacherMaxGapsPerWeekForRealDays* crt_constraint=(ConstraintTeacherMaxGapsPerWeekForRealDays*)ctr;
1343 			if(initialTeacherName == crt_constraint->teacherName)
1344 				crt_constraint->teacherName=finalTeacherName;
1345 		}
1346 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_ZERO_GAPS_PER_AFTERNOON){
1347 			ConstraintTeacherMaxZeroGapsPerAfternoon* crt_constraint=(ConstraintTeacherMaxZeroGapsPerAfternoon*)ctr;
1348 			if(initialTeacherName == crt_constraint->teacherName)
1349 				crt_constraint->teacherName=finalTeacherName;
1350 		}
1351 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_HOURS_DAILY_REAL_DAYS){
1352 			ConstraintTeacherMaxHoursDailyRealDays* crt_constraint=(ConstraintTeacherMaxHoursDailyRealDays*)ctr;
1353 			if(initialTeacherName == crt_constraint->teacherName)
1354 				crt_constraint->teacherName=finalTeacherName;
1355 		}
1356 		else if(ctr->type==CONSTRAINT_TEACHER_ACTIVITY_TAG_MAX_HOURS_DAILY_REAL_DAYS){
1357 			ConstraintTeacherActivityTagMaxHoursDailyRealDays* crt_constraint=(ConstraintTeacherActivityTagMaxHoursDailyRealDays*)ctr;
1358 			if(initialTeacherName == crt_constraint->teacherName)
1359 				crt_constraint->teacherName=finalTeacherName;
1360 		}
1361 		//2020-06-28
1362 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_HOURS_PER_ALL_AFTERNOONS){
1363 			ConstraintTeacherMaxHoursPerAllAfternoons* crt_constraint=(ConstraintTeacherMaxHoursPerAllAfternoons*)ctr;
1364 			if(initialTeacherName == crt_constraint->teacherName)
1365 				crt_constraint->teacherName=finalTeacherName;
1366 		}
1367 		//
1368 		else if(ctr->type==CONSTRAINT_TEACHER_MIN_HOURS_PER_MORNING){
1369 			ConstraintTeacherMinHoursPerMorning* crt_constraint=(ConstraintTeacherMinHoursPerMorning*)ctr;
1370 			if(initialTeacherName == crt_constraint->teacherName)
1371 				crt_constraint->teacherName=finalTeacherName;
1372 		}
1373 		else if(ctr->type==CONSTRAINT_TEACHER_MIN_HOURS_DAILY_REAL_DAYS){
1374 			ConstraintTeacherMinHoursDailyRealDays* crt_constraint=(ConstraintTeacherMinHoursDailyRealDays*)ctr;
1375 			if(initialTeacherName == crt_constraint->teacherName)
1376 				crt_constraint->teacherName=finalTeacherName;
1377 		}
1378 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_REAL_DAYS_PER_WEEK){
1379 			ConstraintTeacherMaxRealDaysPerWeek* crt_constraint=(ConstraintTeacherMaxRealDaysPerWeek*)ctr;
1380 			if(initialTeacherName == crt_constraint->teacherName)
1381 				crt_constraint->teacherName=finalTeacherName;
1382 		}
1383 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_AFTERNOONS_PER_WEEK){
1384 			ConstraintTeacherMaxAfternoonsPerWeek* crt_constraint=(ConstraintTeacherMaxAfternoonsPerWeek*)ctr;
1385 			if(initialTeacherName == crt_constraint->teacherName)
1386 				crt_constraint->teacherName=finalTeacherName;
1387 		}
1388 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_TWO_ACTIVITY_TAGS_PER_DAY_FROM_N1N2N3){
1389 			ConstraintTeacherMaxTwoActivityTagsPerDayFromN1N2N3* crt_constraint=(ConstraintTeacherMaxTwoActivityTagsPerDayFromN1N2N3*)ctr;
1390 			if(initialTeacherName == crt_constraint->teacherName)
1391 				crt_constraint->teacherName=finalTeacherName;
1392 		}
1393 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_MORNINGS_PER_WEEK){
1394 			ConstraintTeacherMaxMorningsPerWeek* crt_constraint=(ConstraintTeacherMaxMorningsPerWeek*)ctr;
1395 			if(initialTeacherName == crt_constraint->teacherName)
1396 				crt_constraint->teacherName=finalTeacherName;
1397 		}
1398 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_TWO_CONSECUTIVE_MORNINGS){
1399 			ConstraintTeacherMaxTwoConsecutiveMornings* crt_constraint=(ConstraintTeacherMaxTwoConsecutiveMornings*)ctr;
1400 			if(initialTeacherName == crt_constraint->teacherName)
1401 				crt_constraint->teacherName=finalTeacherName;
1402 		}
1403 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_TWO_CONSECUTIVE_AFTERNOONS){
1404 			ConstraintTeacherMaxTwoConsecutiveAfternoons* crt_constraint=(ConstraintTeacherMaxTwoConsecutiveAfternoons*)ctr;
1405 			if(initialTeacherName == crt_constraint->teacherName)
1406 				crt_constraint->teacherName=finalTeacherName;
1407 		}
1408 		else if(ctr->type==CONSTRAINT_TEACHER_MIN_REAL_DAYS_PER_WEEK){
1409 			ConstraintTeacherMinRealDaysPerWeek* crt_constraint=(ConstraintTeacherMinRealDaysPerWeek*)ctr;
1410 			if(initialTeacherName == crt_constraint->teacherName)
1411 				crt_constraint->teacherName=finalTeacherName;
1412 		}
1413 		else if(ctr->type==CONSTRAINT_TEACHER_MIN_MORNINGS_PER_WEEK){
1414 			ConstraintTeacherMinMorningsPerWeek* crt_constraint=(ConstraintTeacherMinMorningsPerWeek*)ctr;
1415 			if(initialTeacherName == crt_constraint->teacherName)
1416 				crt_constraint->teacherName=finalTeacherName;
1417 		}
1418 		else if(ctr->type==CONSTRAINT_TEACHER_MIN_AFTERNOONS_PER_WEEK){
1419 			ConstraintTeacherMinAfternoonsPerWeek* crt_constraint=(ConstraintTeacherMinAfternoonsPerWeek*)ctr;
1420 			if(initialTeacherName == crt_constraint->teacherName)
1421 				crt_constraint->teacherName=finalTeacherName;
1422 		}
1423 
1424 		else if(ctr->type==CONSTRAINT_TEACHER_MORNING_INTERVAL_MAX_DAYS_PER_WEEK){
1425 			ConstraintTeacherMorningIntervalMaxDaysPerWeek* crt_constraint=(ConstraintTeacherMorningIntervalMaxDaysPerWeek*)ctr;
1426 			if(initialTeacherName == crt_constraint->teacherName)
1427 				crt_constraint->teacherName=finalTeacherName;
1428 		}
1429 		else if(ctr->type==CONSTRAINT_TEACHER_AFTERNOON_INTERVAL_MAX_DAYS_PER_WEEK){
1430 			ConstraintTeacherAfternoonIntervalMaxDaysPerWeek* crt_constraint=(ConstraintTeacherAfternoonIntervalMaxDaysPerWeek*)ctr;
1431 			if(initialTeacherName == crt_constraint->teacherName)
1432 				crt_constraint->teacherName=finalTeacherName;
1433 		}
1434 
1435 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_SPAN_PER_REAL_DAY){
1436 			ConstraintTeacherMaxSpanPerRealDay* crt_constraint=(ConstraintTeacherMaxSpanPerRealDay*)ctr;
1437 			if(initialTeacherName == crt_constraint->teacherName)
1438 				crt_constraint->teacherName=finalTeacherName;
1439 		}
1440 		else if(ctr->type==CONSTRAINT_TEACHER_MIN_RESTING_HOURS_BETWEEN_MORNING_AND_AFTERNOON){
1441 			ConstraintTeacherMinRestingHoursBetweenMorningAndAfternoon* crt_constraint=(ConstraintTeacherMinRestingHoursBetweenMorningAndAfternoon*)ctr;
1442 			if(initialTeacherName == crt_constraint->teacherName)
1443 				crt_constraint->teacherName=finalTeacherName;
1444 		}
1445 	}
1446 
1447 	for(SpaceConstraint* ctr : qAsConst(spaceConstraintsList)){
1448 		if(ctr->type==CONSTRAINT_TEACHER_ROOM_NOT_AVAILABLE_TIMES){
1449 			ConstraintTeacherRoomNotAvailableTimes* crt_constraint=(ConstraintTeacherRoomNotAvailableTimes*)ctr;
1450 			if(initialTeacherName == crt_constraint->teacherName)
1451 				crt_constraint->teacherName=finalTeacherName;
1452 		}
1453 		else if(ctr->type==CONSTRAINT_TEACHER_HOME_ROOM){
1454 			ConstraintTeacherHomeRoom* crt_constraint=(ConstraintTeacherHomeRoom*)ctr;
1455 			if(initialTeacherName == crt_constraint->teacherName)
1456 				crt_constraint->teacherName=finalTeacherName;
1457 		}
1458 		else if(ctr->type==CONSTRAINT_TEACHER_HOME_ROOMS){
1459 			ConstraintTeacherHomeRooms* crt_constraint=(ConstraintTeacherHomeRooms*)ctr;
1460 			if(initialTeacherName == crt_constraint->teacherName)
1461 				crt_constraint->teacherName=finalTeacherName;
1462 		}
1463 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_BUILDING_CHANGES_PER_DAY){
1464 			ConstraintTeacherMaxBuildingChangesPerDay* crt_constraint=(ConstraintTeacherMaxBuildingChangesPerDay*)ctr;
1465 			if(initialTeacherName == crt_constraint->teacherName)
1466 				crt_constraint->teacherName=finalTeacherName;
1467 		}
1468 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_BUILDING_CHANGES_PER_WEEK){
1469 			ConstraintTeacherMaxBuildingChangesPerWeek* crt_constraint=(ConstraintTeacherMaxBuildingChangesPerWeek*)ctr;
1470 			if(initialTeacherName == crt_constraint->teacherName)
1471 				crt_constraint->teacherName=finalTeacherName;
1472 		}
1473 		else if(ctr->type==CONSTRAINT_TEACHER_MIN_GAPS_BETWEEN_BUILDING_CHANGES){
1474 			ConstraintTeacherMinGapsBetweenBuildingChanges* crt_constraint=(ConstraintTeacherMinGapsBetweenBuildingChanges*)ctr;
1475 			if(initialTeacherName == crt_constraint->teacherName)
1476 				crt_constraint->teacherName=finalTeacherName;
1477 		}
1478 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_ROOM_CHANGES_PER_DAY){
1479 			ConstraintTeacherMaxRoomChangesPerDay* crt_constraint=(ConstraintTeacherMaxRoomChangesPerDay*)ctr;
1480 			if(initialTeacherName == crt_constraint->teacherName)
1481 				crt_constraint->teacherName=finalTeacherName;
1482 		}
1483 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_ROOM_CHANGES_PER_WEEK){
1484 			ConstraintTeacherMaxRoomChangesPerWeek* crt_constraint=(ConstraintTeacherMaxRoomChangesPerWeek*)ctr;
1485 			if(initialTeacherName == crt_constraint->teacherName)
1486 				crt_constraint->teacherName=finalTeacherName;
1487 		}
1488 		else if(ctr->type==CONSTRAINT_TEACHER_MIN_GAPS_BETWEEN_ROOM_CHANGES){
1489 			ConstraintTeacherMinGapsBetweenRoomChanges* crt_constraint=(ConstraintTeacherMinGapsBetweenRoomChanges*)ctr;
1490 			if(initialTeacherName == crt_constraint->teacherName)
1491 				crt_constraint->teacherName=finalTeacherName;
1492 		}
1493 
1494 		//mornings-afternoons
1495 		else if(ctr->type==CONSTRAINT_TEACHER_MAX_ROOM_CHANGES_PER_REAL_DAY){
1496 			ConstraintTeacherMaxRoomChangesPerRealDay* crt_constraint=(ConstraintTeacherMaxRoomChangesPerRealDay*)ctr;
1497 			if(initialTeacherName == crt_constraint->teacherName)
1498 				crt_constraint->teacherName=finalTeacherName;
1499 		}
1500 	}
1501 
1502 	int t=0;
1503 	for(int i=0; i<this->teachersList.size(); i++){
1504 		Teacher* tch=this->teachersList[i];
1505 
1506 		if(tch->name==initialTeacherName){
1507 			tch->name=finalTeacherName;
1508 			t++;
1509 		}
1510 	}
1511 	assert(t==1);
1512 
1513 	if(tnatHash.contains(initialTeacherName)){
1514 		QSet<ConstraintTeacherNotAvailableTimes*> cs=tnatHash.value(initialTeacherName);
1515 		tnatHash.remove(initialTeacherName);
1516 		assert(!tnatHash.contains(finalTeacherName));
1517 		tnatHash.insert(finalTeacherName, cs);
1518 	}
1519 
1520 	this->internalStructureComputed=false;
1521 	setRulesModifiedAndOtherThings(this);
1522 
1523 	teachers_schedule_ready=false;
1524 	students_schedule_ready=false;
1525 	rooms_schedule_ready=false;
1526 
1527 	return true;
1528 }
1529 
sortTeachersAlphabetically()1530 void Rules::sortTeachersAlphabetically()
1531 {
1532 	std::stable_sort(this->teachersList.begin(), this->teachersList.end(), teachersAscending);
1533 
1534 	this->internalStructureComputed=false;
1535 	setRulesModifiedAndOtherThings(this);
1536 
1537 	teachers_schedule_ready=false;
1538 	students_schedule_ready=false;
1539 	rooms_schedule_ready=false;
1540 }
1541 
addSubject(Subject * subject)1542 bool Rules::addSubject(Subject* subject)
1543 {
1544 	for(int i=0; i<this->subjectsList.size(); i++){
1545 		Subject* sbj=this->subjectsList[i];
1546 		if(sbj->name==subject->name)
1547 			return false;
1548 	}
1549 
1550 	this->internalStructureComputed=false;
1551 	setRulesModifiedAndOtherThings(this);
1552 
1553 	teachers_schedule_ready=false;
1554 	students_schedule_ready=false;
1555 	rooms_schedule_ready=false;
1556 
1557 	this->subjectsList << subject;
1558 	return true;
1559 }
1560 
addSubjectFast(Subject * subject)1561 bool Rules::addSubjectFast(Subject* subject)
1562 {
1563 	this->internalStructureComputed=false;
1564 	setRulesModifiedAndOtherThings(this);
1565 
1566 	teachers_schedule_ready=false;
1567 	students_schedule_ready=false;
1568 	rooms_schedule_ready=false;
1569 
1570 	this->subjectsList << subject;
1571 	return true;
1572 }
1573 
searchSubject(const QString & subjectName)1574 int Rules::searchSubject(const QString& subjectName)
1575 {
1576 	for(int i=0; i<this->subjectsList.size(); i++)
1577 		if(this->subjectsList.at(i)->name == subjectName)
1578 			return i;
1579 
1580 	return -1;
1581 }
1582 
removeSubject(const QString & subjectName)1583 bool Rules::removeSubject(const QString& subjectName)
1584 {
1585 	//check the qualified subjects for teachers
1586 	for(Teacher* tch : qAsConst(teachersList)){
1587 		if(tch->qualifiedSubjectsHash.contains(subjectName)){
1588 			std::list<QString>::iterator it=tch->qualifiedSubjectsHash.value(subjectName);
1589 			assert((*it)==subjectName);
1590 
1591 			tch->qualifiedSubjectsList.erase(it);
1592 
1593 			tch->qualifiedSubjectsHash.remove(subjectName);
1594 		}
1595 	}
1596 
1597 	QList<int> idsToBeRemoved;
1598 	for(Activity* act : qAsConst(activitiesList)){
1599 		if(act->subjectName==subjectName)
1600 			idsToBeRemoved.append(act->id);
1601 	}
1602 	removeActivities(idsToBeRemoved, false);
1603 
1604 	//remove the subject from the list
1605 	for(int i=0; i<this->subjectsList.size(); i++)
1606 		if(this->subjectsList[i]->name==subjectName){
1607 			Subject* sbj=this->subjectsList[i];
1608 			this->subjectsList.removeAt(i);
1609 			delete sbj;
1610 			break;
1611 		}
1612 
1613 	updateConstraintsAfterRemoval();
1614 
1615 	this->internalStructureComputed=false;
1616 	setRulesModifiedAndOtherThings(this);
1617 
1618 	teachers_schedule_ready=false;
1619 	students_schedule_ready=false;
1620 	rooms_schedule_ready=false;
1621 
1622 	return true;
1623 }
1624 
modifySubject(const QString & initialSubjectName,const QString & finalSubjectName)1625 bool Rules::modifySubject(const QString& initialSubjectName, const QString& finalSubjectName)
1626 {
1627 	assert(this->searchSubject(finalSubjectName)==-1);
1628 	assert(this->searchSubject(initialSubjectName)>=0);
1629 
1630 	//check the qualified subjects for teachers
1631 	for(Teacher* tch : qAsConst(teachersList)){
1632 		if(tch->qualifiedSubjectsHash.contains(initialSubjectName)){
1633 			std::list<QString>::iterator it=tch->qualifiedSubjectsHash.value(initialSubjectName);
1634 			assert((*it)==initialSubjectName);
1635 
1636 			(*it)=finalSubjectName;
1637 
1638 			tch->qualifiedSubjectsHash.remove(initialSubjectName);
1639 			tch->qualifiedSubjectsHash.insert(finalSubjectName, it);
1640 		}
1641 	}
1642 
1643 	//check the activities
1644 	for(int i=0; i<this->activitiesList.size(); i++){
1645 		Activity* act=this->activitiesList[i];
1646 
1647 		if( act->subjectName == initialSubjectName)
1648 			act->subjectName=finalSubjectName;
1649 	}
1650 
1651 	//modify the time constraints related to this subject
1652 	for(TimeConstraint* ctr : qAsConst(timeConstraintsList)){
1653 		if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_TIME_SLOTS){
1654 			ConstraintActivitiesPreferredTimeSlots* crt_constraint=(ConstraintActivitiesPreferredTimeSlots*)ctr;
1655 			if(initialSubjectName == crt_constraint->p_subjectName)
1656 				crt_constraint->p_subjectName=finalSubjectName;
1657 		}
1658 		else if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_STARTING_TIMES){
1659 			ConstraintActivitiesPreferredStartingTimes* crt_constraint=(ConstraintActivitiesPreferredStartingTimes*)ctr;
1660 			if(initialSubjectName == crt_constraint->subjectName)
1661 				crt_constraint->subjectName=finalSubjectName;
1662 		}
1663 		else if(ctr->type==CONSTRAINT_ACTIVITIES_END_STUDENTS_DAY){
1664 			ConstraintActivitiesEndStudentsDay* crt_constraint=(ConstraintActivitiesEndStudentsDay*)ctr;
1665 			if(initialSubjectName == crt_constraint->subjectName)
1666 				crt_constraint->subjectName=finalSubjectName;
1667 		}
1668 		else if(ctr->type==CONSTRAINT_ACTIVITIES_END_TEACHERS_DAY){
1669 			ConstraintActivitiesEndTeachersDay* crt_constraint=(ConstraintActivitiesEndTeachersDay*)ctr;
1670 			if(initialSubjectName == crt_constraint->subjectName)
1671 				crt_constraint->subjectName=finalSubjectName;
1672 		}
1673 		else if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_TIME_SLOTS){
1674 			ConstraintSubactivitiesPreferredTimeSlots* crt_constraint=(ConstraintSubactivitiesPreferredTimeSlots*)ctr;
1675 			if(initialSubjectName == crt_constraint->p_subjectName)
1676 				crt_constraint->p_subjectName=finalSubjectName;
1677 		}
1678 		else if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_STARTING_TIMES){
1679 			ConstraintSubactivitiesPreferredStartingTimes* crt_constraint=(ConstraintSubactivitiesPreferredStartingTimes*)ctr;
1680 			if(initialSubjectName == crt_constraint->subjectName)
1681 				crt_constraint->subjectName=finalSubjectName;
1682 		}
1683 	}
1684 
1685 	//modify the space constraints related to this subject
1686 	for(SpaceConstraint* ctr : qAsConst(spaceConstraintsList)){
1687 		if(ctr->type==CONSTRAINT_SUBJECT_PREFERRED_ROOM){
1688 			ConstraintSubjectPreferredRoom* c=(ConstraintSubjectPreferredRoom*)ctr;
1689 			if(c->subjectName == initialSubjectName)
1690 				c->subjectName=finalSubjectName;
1691 		}
1692 		else if(ctr->type==CONSTRAINT_SUBJECT_PREFERRED_ROOMS){
1693 			ConstraintSubjectPreferredRooms* c=(ConstraintSubjectPreferredRooms*)ctr;
1694 			if(c->subjectName == initialSubjectName)
1695 				c->subjectName=finalSubjectName;
1696 		}
1697 		else if(ctr->type==CONSTRAINT_SUBJECT_ACTIVITY_TAG_PREFERRED_ROOM){
1698 			ConstraintSubjectActivityTagPreferredRoom* c=(ConstraintSubjectActivityTagPreferredRoom*)ctr;
1699 			if(c->subjectName == initialSubjectName)
1700 				c->subjectName=finalSubjectName;
1701 		}
1702 		else if(ctr->type==CONSTRAINT_SUBJECT_ACTIVITY_TAG_PREFERRED_ROOMS){
1703 			ConstraintSubjectActivityTagPreferredRooms* c=(ConstraintSubjectActivityTagPreferredRooms*)ctr;
1704 			if(c->subjectName == initialSubjectName)
1705 				c->subjectName=finalSubjectName;
1706 		}
1707 	}
1708 
1709 	//rename the subject in the list
1710 	int t=0;
1711 	for(int i=0; i<this->subjectsList.size(); i++){
1712 		Subject* sbj=this->subjectsList[i];
1713 
1714 		if(sbj->name==initialSubjectName){
1715 			t++;
1716 			sbj->name=finalSubjectName;
1717 		}
1718 	}
1719 	assert(t==1);
1720 
1721 	this->internalStructureComputed=false;
1722 	setRulesModifiedAndOtherThings(this);
1723 
1724 	teachers_schedule_ready=false;
1725 	students_schedule_ready=false;
1726 	rooms_schedule_ready=false;
1727 
1728 	return true;
1729 }
1730 
sortSubjectsAlphabetically()1731 void Rules::sortSubjectsAlphabetically()
1732 {
1733 	std::stable_sort(this->subjectsList.begin(), this->subjectsList.end(), subjectsAscending);
1734 
1735 	this->internalStructureComputed=false;
1736 	setRulesModifiedAndOtherThings(this);
1737 
1738 	teachers_schedule_ready=false;
1739 	students_schedule_ready=false;
1740 	rooms_schedule_ready=false;
1741 }
1742 
addActivityTag(ActivityTag * activityTag)1743 bool Rules::addActivityTag(ActivityTag* activityTag)
1744 {
1745 	for(int i=0; i<this->activityTagsList.size(); i++){
1746 		ActivityTag* sbt=this->activityTagsList[i];
1747 
1748 		if(sbt->name==activityTag->name)
1749 			return false;
1750 	}
1751 
1752 	this->internalStructureComputed=false;
1753 	setRulesModifiedAndOtherThings(this);
1754 
1755 	teachers_schedule_ready=false;
1756 	students_schedule_ready=false;
1757 	rooms_schedule_ready=false;
1758 
1759 	this->activityTagsList << activityTag;
1760 	return true;
1761 }
1762 
addActivityTagFast(ActivityTag * activityTag)1763 bool Rules::addActivityTagFast(ActivityTag* activityTag)
1764 {
1765 	this->internalStructureComputed=false;
1766 	setRulesModifiedAndOtherThings(this);
1767 
1768 	teachers_schedule_ready=false;
1769 	students_schedule_ready=false;
1770 	rooms_schedule_ready=false;
1771 
1772 	this->activityTagsList << activityTag;
1773 	return true;
1774 }
1775 
searchActivityTag(const QString & activityTagName)1776 int Rules::searchActivityTag(const QString& activityTagName)
1777 {
1778 	for(int i=0; i<this->activityTagsList.size(); i++)
1779 		if(this->activityTagsList.at(i)->name==activityTagName)
1780 			return i;
1781 
1782 	return -1;
1783 }
1784 
removeActivityTag(const QString & activityTagName)1785 bool Rules::removeActivityTag(const QString& activityTagName)
1786 {
1787 	for(Activity* act : qAsConst(activitiesList))
1788 		if(act->activityTagsNames.contains(activityTagName))
1789 			act->activityTagsNames.removeAll(activityTagName);
1790 
1791 	//remove the activity tag from the list
1792 	for(int i=0; i<this->activityTagsList.size(); i++)
1793 		if(this->activityTagsList[i]->name==activityTagName){
1794 			ActivityTag* sbt=this->activityTagsList[i];
1795 			this->activityTagsList.removeAt(i);
1796 			delete sbt;
1797 			break;
1798 		}
1799 
1800 	updateConstraintsAfterRemoval();
1801 
1802 	this->internalStructureComputed=false;
1803 	setRulesModifiedAndOtherThings(this);
1804 
1805 	teachers_schedule_ready=false;
1806 	students_schedule_ready=false;
1807 	rooms_schedule_ready=false;
1808 
1809 	return true;
1810 }
1811 
modifyActivityTag(const QString & initialActivityTagName,const QString & finalActivityTagName)1812 bool Rules::modifyActivityTag(const QString& initialActivityTagName, const QString& finalActivityTagName)
1813 {
1814 	assert(this->searchActivityTag(finalActivityTagName)==-1);
1815 	assert(this->searchActivityTag(initialActivityTagName)>=0);
1816 
1817 	//check the activities first
1818 	for(int i=0; i<this->activitiesList.size(); i++){
1819 		Activity* act=this->activitiesList[i];
1820 
1821 		for(int kk=0; kk<act->activityTagsNames.count(); kk++)
1822 			if(act->activityTagsNames.at(kk)==initialActivityTagName)
1823 				act->activityTagsNames[kk]=finalActivityTagName;
1824 	}
1825 
1826 	//modify the time constraints related to this activity tag
1827 	for(TimeConstraint* ctr : qAsConst(timeConstraintsList)){
1828 		if(ctr->type==CONSTRAINT_TEACHER_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
1829 			ConstraintTeacherActivityTagMaxHoursContinuously* crt_constraint=(ConstraintTeacherActivityTagMaxHoursContinuously*)ctr;
1830 			if(initialActivityTagName == crt_constraint->activityTagName)
1831 				crt_constraint->activityTagName=finalActivityTagName;
1832 		}
1833 		else if(ctr->type==CONSTRAINT_TEACHER_ACTIVITY_TAG_MAX_HOURS_DAILY){
1834 			ConstraintTeacherActivityTagMaxHoursDaily* crt_constraint=(ConstraintTeacherActivityTagMaxHoursDaily*)ctr;
1835 			if(initialActivityTagName == crt_constraint->activityTagName)
1836 				crt_constraint->activityTagName=finalActivityTagName;
1837 		}
1838 		else if(ctr->type==CONSTRAINT_TEACHER_ACTIVITY_TAG_MIN_HOURS_DAILY){
1839 			ConstraintTeacherActivityTagMinHoursDaily* crt_constraint=(ConstraintTeacherActivityTagMinHoursDaily*)ctr;
1840 			if(initialActivityTagName == crt_constraint->activityTagName)
1841 				crt_constraint->activityTagName=finalActivityTagName;
1842 		}
1843 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_GAPS_BETWEEN_ORDERED_PAIR_OF_ACTIVITY_TAGS){
1844 			ConstraintStudentsSetMinGapsBetweenOrderedPairOfActivityTags* crt_constraint=(ConstraintStudentsSetMinGapsBetweenOrderedPairOfActivityTags*)ctr;
1845 			if(initialActivityTagName == crt_constraint->firstActivityTag)
1846 				crt_constraint->firstActivityTag=finalActivityTagName;
1847 			if(initialActivityTagName == crt_constraint->secondActivityTag)
1848 				crt_constraint->secondActivityTag=finalActivityTagName;
1849 		}
1850 		else if(ctr->type==CONSTRAINT_STUDENTS_MIN_GAPS_BETWEEN_ORDERED_PAIR_OF_ACTIVITY_TAGS){
1851 			ConstraintStudentsMinGapsBetweenOrderedPairOfActivityTags* crt_constraint=(ConstraintStudentsMinGapsBetweenOrderedPairOfActivityTags*)ctr;
1852 			if(initialActivityTagName == crt_constraint->firstActivityTag)
1853 				crt_constraint->firstActivityTag=finalActivityTagName;
1854 			if(initialActivityTagName == crt_constraint->secondActivityTag)
1855 				crt_constraint->secondActivityTag=finalActivityTagName;
1856 		}
1857 		else if(ctr->type==CONSTRAINT_TEACHER_MIN_GAPS_BETWEEN_ORDERED_PAIR_OF_ACTIVITY_TAGS){
1858 			ConstraintTeacherMinGapsBetweenOrderedPairOfActivityTags* crt_constraint=(ConstraintTeacherMinGapsBetweenOrderedPairOfActivityTags*)ctr;
1859 			if(initialActivityTagName == crt_constraint->firstActivityTag)
1860 				crt_constraint->firstActivityTag=finalActivityTagName;
1861 			if(initialActivityTagName == crt_constraint->secondActivityTag)
1862 				crt_constraint->secondActivityTag=finalActivityTagName;
1863 		}
1864 		else if(ctr->type==CONSTRAINT_TEACHERS_MIN_GAPS_BETWEEN_ORDERED_PAIR_OF_ACTIVITY_TAGS){
1865 			ConstraintTeachersMinGapsBetweenOrderedPairOfActivityTags* crt_constraint=(ConstraintTeachersMinGapsBetweenOrderedPairOfActivityTags*)ctr;
1866 			if(initialActivityTagName == crt_constraint->firstActivityTag)
1867 				crt_constraint->firstActivityTag=finalActivityTagName;
1868 			if(initialActivityTagName == crt_constraint->secondActivityTag)
1869 				crt_constraint->secondActivityTag=finalActivityTagName;
1870 		}
1871 		else if(ctr->type==CONSTRAINT_TEACHERS_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
1872 			ConstraintTeachersActivityTagMaxHoursContinuously* crt_constraint=(ConstraintTeachersActivityTagMaxHoursContinuously*)ctr;
1873 			if(initialActivityTagName == crt_constraint->activityTagName)
1874 				crt_constraint->activityTagName=finalActivityTagName;
1875 		}
1876 		else if(ctr->type==CONSTRAINT_TEACHERS_ACTIVITY_TAG_MAX_HOURS_DAILY){
1877 			ConstraintTeachersActivityTagMaxHoursDaily* crt_constraint=(ConstraintTeachersActivityTagMaxHoursDaily*)ctr;
1878 			if(initialActivityTagName == crt_constraint->activityTagName)
1879 				crt_constraint->activityTagName=finalActivityTagName;
1880 		}
1881 		else if(ctr->type==CONSTRAINT_TEACHERS_ACTIVITY_TAG_MIN_HOURS_DAILY){
1882 			ConstraintTeachersActivityTagMinHoursDaily* crt_constraint=(ConstraintTeachersActivityTagMinHoursDaily*)ctr;
1883 			if(initialActivityTagName == crt_constraint->activityTagName)
1884 				crt_constraint->activityTagName=finalActivityTagName;
1885 		}
1886 		else if(ctr->type==CONSTRAINT_STUDENTS_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
1887 			ConstraintStudentsActivityTagMaxHoursContinuously* crt_constraint=(ConstraintStudentsActivityTagMaxHoursContinuously*)ctr;
1888 			if(initialActivityTagName == crt_constraint->activityTagName)
1889 				crt_constraint->activityTagName=finalActivityTagName;
1890 		}
1891 		else if(ctr->type==CONSTRAINT_STUDENTS_ACTIVITY_TAG_MAX_HOURS_DAILY){
1892 			ConstraintStudentsActivityTagMaxHoursDaily* crt_constraint=(ConstraintStudentsActivityTagMaxHoursDaily*)ctr;
1893 			if(initialActivityTagName == crt_constraint->activityTagName)
1894 				crt_constraint->activityTagName=finalActivityTagName;
1895 		}
1896 		else if(ctr->type==CONSTRAINT_STUDENTS_ACTIVITY_TAG_MIN_HOURS_DAILY){
1897 			ConstraintStudentsActivityTagMinHoursDaily* crt_constraint=(ConstraintStudentsActivityTagMinHoursDaily*)ctr;
1898 			if(initialActivityTagName == crt_constraint->activityTagName)
1899 				crt_constraint->activityTagName=finalActivityTagName;
1900 		}
1901 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
1902 			ConstraintStudentsSetActivityTagMaxHoursContinuously* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursContinuously*)ctr;
1903 			if(initialActivityTagName == crt_constraint->activityTagName)
1904 				crt_constraint->activityTagName=finalActivityTagName;
1905 		}
1906 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_DAILY){
1907 			ConstraintStudentsSetActivityTagMaxHoursDaily* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursDaily*)ctr;
1908 			if(initialActivityTagName == crt_constraint->activityTagName)
1909 				crt_constraint->activityTagName=finalActivityTagName;
1910 		}
1911 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MIN_HOURS_DAILY){
1912 			ConstraintStudentsSetActivityTagMinHoursDaily* crt_constraint=(ConstraintStudentsSetActivityTagMinHoursDaily*)ctr;
1913 			if(initialActivityTagName == crt_constraint->activityTagName)
1914 				crt_constraint->activityTagName=finalActivityTagName;
1915 		}
1916 		else if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_TIME_SLOTS){
1917 			ConstraintActivitiesPreferredTimeSlots* crt_constraint=(ConstraintActivitiesPreferredTimeSlots*)ctr;
1918 			if(initialActivityTagName == crt_constraint->p_activityTagName)
1919 				crt_constraint->p_activityTagName=finalActivityTagName;
1920 		}
1921 		else if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_STARTING_TIMES){
1922 			ConstraintActivitiesPreferredStartingTimes* crt_constraint=(ConstraintActivitiesPreferredStartingTimes*)ctr;
1923 			if(initialActivityTagName == crt_constraint->activityTagName)
1924 				crt_constraint->activityTagName=finalActivityTagName;
1925 		}
1926 		else if(ctr->type==CONSTRAINT_ACTIVITIES_END_STUDENTS_DAY){
1927 			ConstraintActivitiesEndStudentsDay* crt_constraint=(ConstraintActivitiesEndStudentsDay*)ctr;
1928 			if(initialActivityTagName == crt_constraint->activityTagName)
1929 				crt_constraint->activityTagName=finalActivityTagName;
1930 		}
1931 		else if(ctr->type==CONSTRAINT_ACTIVITIES_END_TEACHERS_DAY){
1932 			ConstraintActivitiesEndTeachersDay* crt_constraint=(ConstraintActivitiesEndTeachersDay*)ctr;
1933 			if(initialActivityTagName == crt_constraint->activityTagName)
1934 				crt_constraint->activityTagName=finalActivityTagName;
1935 		}
1936 		else if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_TIME_SLOTS){
1937 			ConstraintSubactivitiesPreferredTimeSlots* crt_constraint=(ConstraintSubactivitiesPreferredTimeSlots*)ctr;
1938 			if(initialActivityTagName == crt_constraint->p_activityTagName)
1939 				crt_constraint->p_activityTagName=finalActivityTagName;
1940 		}
1941 		else if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_STARTING_TIMES){
1942 			ConstraintSubactivitiesPreferredStartingTimes* crt_constraint=(ConstraintSubactivitiesPreferredStartingTimes*)ctr;
1943 			if(initialActivityTagName == crt_constraint->activityTagName)
1944 				crt_constraint->activityTagName=finalActivityTagName;
1945 		}
1946 		else if(ctr->type==CONSTRAINT_ACTIVITY_TAGS_NOT_OVERLAPPING){
1947 			ConstraintActivityTagsNotOverlapping* crt_constraint=(ConstraintActivityTagsNotOverlapping*)ctr;
1948 			int cnt=0;
1949 			for(int i=0; i<crt_constraint->activityTagsNames.count(); i++){
1950 				if(crt_constraint->activityTagsNames.at(i)==initialActivityTagName){
1951 					crt_constraint->activityTagsNames[i]=finalActivityTagName;
1952 					cnt++;
1953 				}
1954 			}
1955 			assert(cnt<=1);
1956 		}
1957 
1958 		//mornings-afternoons
1959 		else if(ctr->type==CONSTRAINT_TEACHER_ACTIVITY_TAG_MAX_HOURS_DAILY_REAL_DAYS){
1960 			ConstraintTeacherActivityTagMaxHoursDailyRealDays* crt_constraint=(ConstraintTeacherActivityTagMaxHoursDailyRealDays*)ctr;
1961 			if(initialActivityTagName == crt_constraint->activityTagName)
1962 				crt_constraint->activityTagName=finalActivityTagName;
1963 		}
1964 		else if(ctr->type==CONSTRAINT_TEACHERS_ACTIVITY_TAG_MAX_HOURS_DAILY_REAL_DAYS){
1965 			ConstraintTeachersActivityTagMaxHoursDailyRealDays* crt_constraint=(ConstraintTeachersActivityTagMaxHoursDailyRealDays*)ctr;
1966 			if(initialActivityTagName == crt_constraint->activityTagName)
1967 				crt_constraint->activityTagName=finalActivityTagName;
1968 		}
1969 		else if(ctr->type==CONSTRAINT_STUDENTS_ACTIVITY_TAG_MAX_HOURS_DAILY_REAL_DAYS){
1970 			ConstraintStudentsActivityTagMaxHoursDailyRealDays* crt_constraint=(ConstraintStudentsActivityTagMaxHoursDailyRealDays*)ctr;
1971 			if(initialActivityTagName == crt_constraint->activityTagName)
1972 				crt_constraint->activityTagName=finalActivityTagName;
1973 		}
1974 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_DAILY_REAL_DAYS){
1975 			ConstraintStudentsSetActivityTagMaxHoursDailyRealDays* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursDailyRealDays*)ctr;
1976 			if(initialActivityTagName == crt_constraint->activityTagName)
1977 				crt_constraint->activityTagName=finalActivityTagName;
1978 		}
1979 	}
1980 
1981 	//modify the space constraints related to this activity tag
1982 	for(SpaceConstraint* ctr : qAsConst(spaceConstraintsList)){
1983 		if(ctr->type==CONSTRAINT_SUBJECT_ACTIVITY_TAG_PREFERRED_ROOM){
1984 			ConstraintSubjectActivityTagPreferredRoom* c=(ConstraintSubjectActivityTagPreferredRoom*)ctr;
1985 			if(c->activityTagName == initialActivityTagName)
1986 				c->activityTagName=finalActivityTagName;
1987 		}
1988 		else if(ctr->type==CONSTRAINT_SUBJECT_ACTIVITY_TAG_PREFERRED_ROOMS){
1989 			ConstraintSubjectActivityTagPreferredRooms* c=(ConstraintSubjectActivityTagPreferredRooms*)ctr;
1990 			if(c->activityTagName == initialActivityTagName)
1991 				c->activityTagName=finalActivityTagName;
1992 		}
1993 		else if(ctr->type==CONSTRAINT_ACTIVITY_TAG_PREFERRED_ROOM){
1994 			ConstraintActivityTagPreferredRoom* c=(ConstraintActivityTagPreferredRoom*)ctr;
1995 			if(c->activityTagName == initialActivityTagName)
1996 				c->activityTagName=finalActivityTagName;
1997 		}
1998 		else if(ctr->type==CONSTRAINT_ACTIVITY_TAG_PREFERRED_ROOMS){
1999 			ConstraintActivityTagPreferredRooms* c=(ConstraintActivityTagPreferredRooms*)ctr;
2000 			if(c->activityTagName == initialActivityTagName)
2001 				c->activityTagName=finalActivityTagName;
2002 		}
2003 	}
2004 
2005 	//rename the activity tag in the list
2006 	int t=0;
2007 
2008 	for(int i=0; i<this->activityTagsList.size(); i++){
2009 		ActivityTag* sbt=this->activityTagsList[i];
2010 
2011 		if(sbt->name==initialActivityTagName){
2012 			t++;
2013 			sbt->name=finalActivityTagName;
2014 		}
2015 	}
2016 
2017 	assert(t==1);
2018 
2019 	this->internalStructureComputed=false;
2020 	setRulesModifiedAndOtherThings(this);
2021 
2022 	teachers_schedule_ready=false;
2023 	students_schedule_ready=false;
2024 	rooms_schedule_ready=false;
2025 
2026 	return true;
2027 }
2028 
sortActivityTagsAlphabetically()2029 void Rules::sortActivityTagsAlphabetically()
2030 {
2031 	std::stable_sort(this->activityTagsList.begin(), this->activityTagsList.end(), activityTagsAscending);
2032 
2033 	this->internalStructureComputed=false;
2034 	setRulesModifiedAndOtherThings(this);
2035 
2036 	teachers_schedule_ready=false;
2037 	students_schedule_ready=false;
2038 	rooms_schedule_ready=false;
2039 }
2040 
setsShareStudents(const QString & studentsSet1,const QString & studentsSet2)2041 bool Rules::setsShareStudents(const QString& studentsSet1, const QString& studentsSet2)
2042 {
2043 	StudentsSet* s1=this->searchStudentsSet(studentsSet1);
2044 	StudentsSet* s2=this->searchStudentsSet(studentsSet2);
2045 	assert(s1!=nullptr);
2046 	assert(s2!=nullptr);
2047 
2048 	QSet<QString> downwardSets1;
2049 
2050 	if(s1->type==STUDENTS_YEAR){
2051 		StudentsYear* year1=(StudentsYear*)s1;
2052 		downwardSets1.insert(year1->name);
2053 		for(StudentsGroup* group1 : qAsConst(year1->groupsList)){
2054 			downwardSets1.insert(group1->name);
2055 			for(StudentsSubgroup* subgroup1 : qAsConst(group1->subgroupsList))
2056 				downwardSets1.insert(subgroup1->name);
2057 		}
2058 	}
2059 	else if(s1->type==STUDENTS_GROUP){
2060 		StudentsGroup* group1=(StudentsGroup*)s1;
2061 		downwardSets1.insert(group1->name);
2062 		for(StudentsSubgroup* subgroup1 : qAsConst(group1->subgroupsList))
2063 			downwardSets1.insert(subgroup1->name);
2064 	}
2065 	else if(s1->type==STUDENTS_SUBGROUP){
2066 		StudentsSubgroup* subgroup1=(StudentsSubgroup*)s1;
2067 		downwardSets1.insert(subgroup1->name);
2068 	}
2069 	else
2070 		assert(0);
2071 
2072 	if(s2->type==STUDENTS_YEAR){
2073 		StudentsYear* year2=(StudentsYear*)s2;
2074 		if(downwardSets1.contains(year2->name))
2075 			return true;
2076 		for(StudentsGroup* group2 : qAsConst(year2->groupsList)){
2077 			if(downwardSets1.contains(group2->name))
2078 				return true;
2079 			for(StudentsSubgroup* subgroup2 : qAsConst(group2->subgroupsList))
2080 				if(downwardSets1.contains(subgroup2->name))
2081 					return true;
2082 		}
2083 	}
2084 	else if(s2->type==STUDENTS_GROUP){
2085 		StudentsGroup* group2=(StudentsGroup*)s2;
2086 		if(downwardSets1.contains(group2->name))
2087 			return true;
2088 		for(StudentsSubgroup* subgroup2 : qAsConst(group2->subgroupsList))
2089 			if(downwardSets1.contains(subgroup2->name))
2090 				return true;
2091 	}
2092 	else if(s2->type==STUDENTS_SUBGROUP){
2093 		StudentsSubgroup* subgroup2=(StudentsSubgroup*)s2;
2094 		if(downwardSets1.contains(subgroup2->name))
2095 			return true;
2096 	}
2097 	else
2098 		assert(0);
2099 
2100 	return false;
2101 
2102 }
2103 
augmentedSetsShareStudentsFaster(const QString & studentsSet1,const QString & studentsSet2)2104 bool Rules::augmentedSetsShareStudentsFaster(const QString& studentsSet1, const QString& studentsSet2)
2105 {
2106 	//StudentsSet* s1=this->searchStudentsSet(studentsSet1);
2107 	StudentsSet* s1=studentsHash.value(studentsSet1, nullptr);
2108 	//StudentsSet* s2=this->searchStudentsSet(studentsSet2);
2109 	StudentsSet* s2=studentsHash.value(studentsSet2, nullptr);
2110 	assert(s1!=nullptr);
2111 	assert(s2!=nullptr);
2112 
2113 	QSet<QString> downwardSets1;
2114 
2115 	if(s1->type==STUDENTS_YEAR){
2116 		StudentsYear* year1=(StudentsYear*)s1;
2117 		downwardSets1.insert(year1->name);
2118 		for(StudentsGroup* group1 : qAsConst(year1->groupsList)){
2119 			downwardSets1.insert(group1->name);
2120 			for(StudentsSubgroup* subgroup1 : qAsConst(group1->subgroupsList))
2121 				downwardSets1.insert(subgroup1->name);
2122 		}
2123 	}
2124 	else if(s1->type==STUDENTS_GROUP){
2125 		StudentsGroup* group1=(StudentsGroup*)s1;
2126 		downwardSets1.insert(group1->name);
2127 		for(StudentsSubgroup* subgroup1 : qAsConst(group1->subgroupsList))
2128 			downwardSets1.insert(subgroup1->name);
2129 	}
2130 	else if(s1->type==STUDENTS_SUBGROUP){
2131 		StudentsSubgroup* subgroup1=(StudentsSubgroup*)s1;
2132 		downwardSets1.insert(subgroup1->name);
2133 	}
2134 	else
2135 		assert(0);
2136 
2137 	if(s2->type==STUDENTS_YEAR){
2138 		StudentsYear* year2=(StudentsYear*)s2;
2139 		if(downwardSets1.contains(year2->name))
2140 			return true;
2141 		for(StudentsGroup* group2 : qAsConst(year2->groupsList)){
2142 			if(downwardSets1.contains(group2->name))
2143 				return true;
2144 			for(StudentsSubgroup* subgroup2 : qAsConst(group2->subgroupsList))
2145 				if(downwardSets1.contains(subgroup2->name))
2146 					return true;
2147 		}
2148 	}
2149 	else if(s2->type==STUDENTS_GROUP){
2150 		StudentsGroup* group2=(StudentsGroup*)s2;
2151 		if(downwardSets1.contains(group2->name))
2152 			return true;
2153 		for(StudentsSubgroup* subgroup2 : qAsConst(group2->subgroupsList))
2154 			if(downwardSets1.contains(subgroup2->name))
2155 				return true;
2156 	}
2157 	else if(s2->type==STUDENTS_SUBGROUP){
2158 		StudentsSubgroup* subgroup2=(StudentsSubgroup*)s2;
2159 		if(downwardSets1.contains(subgroup2->name))
2160 			return true;
2161 	}
2162 	else
2163 		assert(0);
2164 
2165 	return false;
2166 
2167 }
2168 
computePermanentStudentsHash()2169 void Rules::computePermanentStudentsHash()
2170 {
2171 	//The commented tests are good, but bring a somewhat slowdown.
2172 	permanentStudentsHash.clear();
2173 
2174 	for(StudentsYear* year : qAsConst(yearsList)){
2175 		assert(!permanentStudentsHash.contains(year->name));
2176 		permanentStudentsHash.insert(year->name, year);
2177 
2178 		//QSet<QString> groupsInYear;
2179 
2180 		for(StudentsGroup* group : qAsConst(year->groupsList)){
2181 			//assert(!groupsInYear.contains(group->name));
2182 			//groupsInYear.insert(group->name);
2183 
2184 			if(!permanentStudentsHash.contains(group->name))
2185 				permanentStudentsHash.insert(group->name, group);
2186 			else
2187 				assert(permanentStudentsHash.value(group->name)==group);
2188 
2189 			//QSet<QString> subgroupsInGroup;
2190 
2191 			for(StudentsSubgroup* subgroup : qAsConst(group->subgroupsList)){
2192 				//assert(!subgroupsInGroup.contains(subgroup->name));
2193 				//subgroupsInGroup.insert(subgroup->name);
2194 
2195 				if(!permanentStudentsHash.contains(subgroup->name))
2196 					permanentStudentsHash.insert(subgroup->name, subgroup);
2197 				else
2198 					assert(permanentStudentsHash.value(subgroup->name)==subgroup);
2199 			}
2200 		}
2201 	}
2202 }
2203 
searchStudentsSet(const QString & setName)2204 StudentsSet* Rules::searchStudentsSet(const QString& setName)
2205 {
2206 	return permanentStudentsHash.value(setName, nullptr);
2207 
2208 	/*for(int i=0; i<this->yearsList.size(); i++){
2209 		StudentsYear* sty=this->yearsList[i];
2210 		if(sty->name==setName)
2211 			return sty;
2212 		for(int j=0; j<sty->groupsList.size(); j++){
2213 			StudentsGroup* stg=sty->groupsList[j];
2214 			if(stg->name==setName)
2215 				return stg;
2216 			for(int k=0; k<stg->subgroupsList.size(); k++){
2217 				StudentsSubgroup* sts=stg->subgroupsList[k];
2218 				if(sts->name==setName)
2219 					return sts;
2220 			}
2221 		}
2222 	}
2223 	return nullptr;*/
2224 }
2225 
searchAugmentedStudentsSet(const QString & setName)2226 StudentsSet* Rules::searchAugmentedStudentsSet(const QString& setName)
2227 {
2228 	for(int i=0; i<this->augmentedYearsList.size(); i++){
2229 		StudentsYear* sty=this->augmentedYearsList[i];
2230 		if(sty->name==setName)
2231 			return sty;
2232 		for(int j=0; j<sty->groupsList.size(); j++){
2233 			StudentsGroup* stg=sty->groupsList[j];
2234 			if(stg->name==setName)
2235 				return stg;
2236 			for(int k=0; k<stg->subgroupsList.size(); k++){
2237 				StudentsSubgroup* sts=stg->subgroupsList[k];
2238 				if(sts->name==setName)
2239 					return sts;
2240 			}
2241 		}
2242 	}
2243 	return nullptr;
2244 }
2245 
addYear(StudentsYear * year)2246 bool Rules::addYear(StudentsYear* year)
2247 {
2248 	//already existing?
2249 	for(StudentsYear* ty : qAsConst(yearsList))
2250 		if(ty->name==year->name)
2251 			return false;
2252 	//if(this->searchStudentsSet(year->name)!=nullptr)
2253 	//	return false;
2254 	this->yearsList << year;
2255 
2256 	assert(!permanentStudentsHash.contains(year->name));
2257 	permanentStudentsHash.insert(year->name, year);
2258 
2259 	this->internalStructureComputed=false;
2260 	setRulesModifiedAndOtherThings(this);
2261 
2262 	teachers_schedule_ready=false;
2263 	students_schedule_ready=false;
2264 	rooms_schedule_ready=false;
2265 
2266 	return true;
2267 }
2268 
addYearFast(StudentsYear * year)2269 bool Rules::addYearFast(StudentsYear* year)
2270 {
2271 	this->yearsList << year;
2272 	this->internalStructureComputed=false;
2273 	setRulesModifiedAndOtherThings(this);
2274 
2275 	teachers_schedule_ready=false;
2276 	students_schedule_ready=false;
2277 	rooms_schedule_ready=false;
2278 
2279 	return true;
2280 }
2281 
2282 /*bool Rules::removeYear(const QString& yearName)
2283 {
2284 	return removeYear(yearName, true);
2285 }
2286 
2287 bool Rules::emptyYear(const QString& yearName)
2288 {
2289 	return removeYear(yearName, false);
2290 }*/
2291 
removeYear(const QString & yearName)2292 bool Rules::removeYear(const QString& yearName/*, bool removeAlsoThisYear*/)
2293 {
2294 	const bool removeAlsoThisYear=true;
2295 
2296 	StudentsYear* yearPointer=nullptr;
2297 	for(StudentsYear* ty : qAsConst(this->yearsList)){
2298 		if(ty->name==yearName){
2299 			yearPointer=ty;
2300 			break;
2301 		}
2302 	}
2303 
2304 	assert(yearPointer!=nullptr);
2305 
2306 	//pointers
2307 	QSet<StudentsSet*> tmpSet;
2308 	for(StudentsYear* year : qAsConst(yearsList))
2309 		if(year->name!=yearName){
2310 			tmpSet.insert(year);
2311 			for(StudentsGroup* group : qAsConst(year->groupsList)){
2312 				tmpSet.insert(group);
2313 				for(StudentsSubgroup* subgroup : qAsConst(group->subgroupsList))
2314 					tmpSet.insert(subgroup);
2315 			}
2316 		}
2317 
2318 	QSet<StudentsSet*> toBeRemoved;
2319 	if(removeAlsoThisYear)
2320 		toBeRemoved.insert(yearPointer);
2321 	for(StudentsGroup* group : qAsConst(yearPointer->groupsList)){
2322 		assert(!toBeRemoved.contains(group));
2323 		if(!tmpSet.contains(group))
2324 			toBeRemoved.insert(group);
2325 		for(StudentsSubgroup* subgroup : qAsConst(group->subgroupsList)){
2326 			//assert(!toBeRemoved.contains(subgroup));
2327 			if(!tmpSet.contains(subgroup) && !toBeRemoved.contains(subgroup))
2328 				toBeRemoved.insert(subgroup);
2329 		}
2330 	}
2331 
2332 	updateActivitiesWhenRemovingStudents(toBeRemoved, false);
2333 
2334 	if(removeAlsoThisYear){
2335 		for(int i=0; i<yearsList.count(); i++)
2336 			if(yearsList.at(i)==yearPointer){
2337 				yearsList.removeAt(i);
2338 				break;
2339 			}
2340 	}
2341 	else{
2342 		yearPointer->groupsList.clear();
2343 	}
2344 
2345 	for(StudentsSet* studentsSet : qAsConst(toBeRemoved)){
2346 		assert(permanentStudentsHash.contains(studentsSet->name));
2347 		permanentStudentsHash.remove(studentsSet->name);
2348 
2349 		delete studentsSet;
2350 	}
2351 
2352 	if(toBeRemoved.count()>0)
2353 		updateConstraintsAfterRemoval();
2354 
2355 	this->internalStructureComputed=false;
2356 	setRulesModifiedAndOtherThings(this);
2357 
2358 	teachers_schedule_ready=false;
2359 	students_schedule_ready=false;
2360 	rooms_schedule_ready=false;
2361 
2362 	return true;
2363 }
2364 
removeYearPointerAfterSplit(StudentsYear * yearPointer)2365 bool Rules::removeYearPointerAfterSplit(StudentsYear* yearPointer)
2366 {
2367 	assert(yearPointer!=nullptr);
2368 
2369 	//names
2370 	QSet<StudentsSet*> toBeRemoved;
2371 
2372 	//Not here, because there exists another pointer (to the new year) with the same name,
2373 	//and I don't want to remove the activities with this year name
2374 	//toBeRemoved.insert(yearPointer);
2375 	for(StudentsGroup* group : qAsConst(yearPointer->groupsList)){
2376 		assert(!toBeRemoved.contains(group));
2377 		if(!permanentStudentsHash.contains(group->name))
2378 			toBeRemoved.insert(group);
2379 		for(StudentsSubgroup* subgroup : qAsConst(group->subgroupsList)){
2380 			//assert(!toBeRemoved.contains(subgroup));
2381 			if(!permanentStudentsHash.contains(subgroup->name) && !toBeRemoved.contains(subgroup))
2382 				toBeRemoved.insert(subgroup);
2383 		}
2384 	}
2385 
2386 	updateActivitiesWhenRemovingStudents(toBeRemoved, false);
2387 
2388 	toBeRemoved.insert(yearPointer);
2389 	for(StudentsSet* studentsSet : qAsConst(toBeRemoved))
2390 		delete studentsSet;
2391 
2392 	if(toBeRemoved.count()>1)
2393 		updateConstraintsAfterRemoval();
2394 
2395 	this->internalStructureComputed=false;
2396 	setRulesModifiedAndOtherThings(this);
2397 
2398 	teachers_schedule_ready=false;
2399 	students_schedule_ready=false;
2400 	rooms_schedule_ready=false;
2401 
2402 	return true;
2403 }
2404 
searchYear(const QString & yearName)2405 int Rules::searchYear(const QString& yearName)
2406 {
2407 	for(int i=0; i<this->yearsList.size(); i++)
2408 		if(this->yearsList[i]->name==yearName)
2409 			return i;
2410 
2411 	return -1;
2412 }
2413 
searchAugmentedYear(const QString & yearName)2414 int Rules::searchAugmentedYear(const QString& yearName)
2415 {
2416 	for(int i=0; i<this->augmentedYearsList.size(); i++)
2417 		if(this->augmentedYearsList[i]->name==yearName)
2418 			return i;
2419 
2420 	return -1;
2421 }
2422 
modifyStudentsSet(const QString & initialStudentsSetName,const QString & finalStudentsSetName,int finalNumberOfStudents)2423 bool Rules::modifyStudentsSet(const QString& initialStudentsSetName, const QString& finalStudentsSetName, int finalNumberOfStudents)
2424 {
2425 	StudentsSet* studentsSet=searchStudentsSet(initialStudentsSetName);
2426 	assert(studentsSet!=nullptr);
2427 	if(initialStudentsSetName!=finalStudentsSetName)
2428 		assert(searchStudentsSet(finalStudentsSetName)==nullptr);
2429 	int initialNumberOfStudents=studentsSet->numberOfStudents;
2430 
2431 	for(Activity* act : qAsConst(activitiesList))
2432 		act->renameStudents(*this, initialStudentsSetName, finalStudentsSetName, initialNumberOfStudents, finalNumberOfStudents);
2433 
2434 	if(initialStudentsSetName!=finalStudentsSetName){
2435 		for(TimeConstraint* ctr : qAsConst(timeConstraintsList)){
2436 			if(ctr->type==CONSTRAINT_STUDENTS_SET_NOT_AVAILABLE_TIMES){
2437 				ConstraintStudentsSetNotAvailableTimes* crt_constraint=(ConstraintStudentsSetNotAvailableTimes*)ctr;
2438 				if(initialStudentsSetName == crt_constraint->students)
2439 					crt_constraint->students=finalStudentsSetName;
2440 			}
2441 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_DAILY){
2442 				ConstraintStudentsSetMaxHoursDaily* crt_constraint=(ConstraintStudentsSetMaxHoursDaily*)ctr;
2443 				if(initialStudentsSetName == crt_constraint->students)
2444 					crt_constraint->students=finalStudentsSetName;
2445 			}
2446 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_DAYS_PER_WEEK){
2447 				ConstraintStudentsSetMaxDaysPerWeek* crt_constraint=(ConstraintStudentsSetMaxDaysPerWeek*)ctr;
2448 				if(initialStudentsSetName == crt_constraint->students)
2449 					crt_constraint->students=finalStudentsSetName;
2450 			}
2451 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_INTERVAL_MAX_DAYS_PER_WEEK){
2452 				ConstraintStudentsSetIntervalMaxDaysPerWeek* crt_constraint=(ConstraintStudentsSetIntervalMaxDaysPerWeek*)ctr;
2453 				if(initialStudentsSetName == crt_constraint->students)
2454 					crt_constraint->students=finalStudentsSetName;
2455 			}
2456 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_CONTINUOUSLY){
2457 				ConstraintStudentsSetMaxHoursContinuously* crt_constraint=(ConstraintStudentsSetMaxHoursContinuously*)ctr;
2458 				if(initialStudentsSetName == crt_constraint->students)
2459 					crt_constraint->students=finalStudentsSetName;
2460 			}
2461 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
2462 				ConstraintStudentsSetActivityTagMaxHoursContinuously* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursContinuously*)ctr;
2463 				if(initialStudentsSetName == crt_constraint->students)
2464 					crt_constraint->students=finalStudentsSetName;
2465 			}
2466 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_DAILY){
2467 				ConstraintStudentsSetActivityTagMaxHoursDaily* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursDaily*)ctr;
2468 				if(initialStudentsSetName == crt_constraint->students)
2469 					crt_constraint->students=finalStudentsSetName;
2470 			}
2471 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MIN_HOURS_DAILY){
2472 				ConstraintStudentsSetActivityTagMinHoursDaily* crt_constraint=(ConstraintStudentsSetActivityTagMinHoursDaily*)ctr;
2473 				if(initialStudentsSetName == crt_constraint->students)
2474 					crt_constraint->students=finalStudentsSetName;
2475 			}
2476 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_HOURS_DAILY){
2477 				ConstraintStudentsSetMinHoursDaily* crt_constraint=(ConstraintStudentsSetMinHoursDaily*)ctr;
2478 				if(initialStudentsSetName == crt_constraint->students)
2479 					crt_constraint->students=finalStudentsSetName;
2480 			}
2481 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_GAPS_BETWEEN_ORDERED_PAIR_OF_ACTIVITY_TAGS){
2482 				ConstraintStudentsSetMinGapsBetweenOrderedPairOfActivityTags* crt_constraint=(ConstraintStudentsSetMinGapsBetweenOrderedPairOfActivityTags*)ctr;
2483 				if(initialStudentsSetName == crt_constraint->students)
2484 					crt_constraint->students=finalStudentsSetName;
2485 			}
2486 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_EARLY_MAX_BEGINNINGS_AT_SECOND_HOUR){
2487 				ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour* crt_constraint=(ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour*)ctr;
2488 				if(initialStudentsSetName == crt_constraint->students)
2489 					crt_constraint->students=finalStudentsSetName;
2490 			}
2491 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_WEEK){
2492 				ConstraintStudentsSetMaxGapsPerWeek* crt_constraint=(ConstraintStudentsSetMaxGapsPerWeek*)ctr;
2493 				if(initialStudentsSetName == crt_constraint->students)
2494 					crt_constraint->students=finalStudentsSetName;
2495 			}
2496 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_DAY){
2497 				ConstraintStudentsSetMaxGapsPerDay* crt_constraint=(ConstraintStudentsSetMaxGapsPerDay*)ctr;
2498 				if(initialStudentsSetName == crt_constraint->students)
2499 					crt_constraint->students=finalStudentsSetName;
2500 			}
2501 			else if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_TIME_SLOTS){
2502 				ConstraintActivitiesPreferredTimeSlots* crt_constraint=(ConstraintActivitiesPreferredTimeSlots*)ctr;
2503 				if(initialStudentsSetName == crt_constraint->p_studentsName)
2504 					crt_constraint->p_studentsName=finalStudentsSetName;
2505 			}
2506 			else if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_STARTING_TIMES){
2507 				ConstraintActivitiesPreferredStartingTimes* crt_constraint=(ConstraintActivitiesPreferredStartingTimes*)ctr;
2508 				if(initialStudentsSetName == crt_constraint->studentsName)
2509 					crt_constraint->studentsName=finalStudentsSetName;
2510 			}
2511 			else if(ctr->type==CONSTRAINT_ACTIVITIES_END_STUDENTS_DAY){
2512 				ConstraintActivitiesEndStudentsDay* crt_constraint=(ConstraintActivitiesEndStudentsDay*)ctr;
2513 				if(initialStudentsSetName == crt_constraint->studentsName)
2514 					crt_constraint->studentsName=finalStudentsSetName;
2515 			}
2516 			else if(ctr->type==CONSTRAINT_ACTIVITIES_END_TEACHERS_DAY){
2517 				ConstraintActivitiesEndTeachersDay* crt_constraint=(ConstraintActivitiesEndTeachersDay*)ctr;
2518 				if(initialStudentsSetName == crt_constraint->studentsName)
2519 					crt_constraint->studentsName=finalStudentsSetName;
2520 			}
2521 			else if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_TIME_SLOTS){
2522 				ConstraintSubactivitiesPreferredTimeSlots* crt_constraint=(ConstraintSubactivitiesPreferredTimeSlots*)ctr;
2523 				if(initialStudentsSetName == crt_constraint->p_studentsName)
2524 					crt_constraint->p_studentsName=finalStudentsSetName;
2525 			}
2526 			else if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_STARTING_TIMES){
2527 				ConstraintSubactivitiesPreferredStartingTimes* crt_constraint=(ConstraintSubactivitiesPreferredStartingTimes*)ctr;
2528 				if(initialStudentsSetName == crt_constraint->studentsName)
2529 					crt_constraint->studentsName=finalStudentsSetName;
2530 			}
2531 			//2017-02-07
2532 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_SPAN_PER_DAY){
2533 				ConstraintStudentsSetMaxSpanPerDay* crt_constraint=(ConstraintStudentsSetMaxSpanPerDay*)ctr;
2534 				if(initialStudentsSetName == crt_constraint->students)
2535 					crt_constraint->students=finalStudentsSetName;
2536 			}
2537 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_RESTING_HOURS){
2538 				ConstraintStudentsSetMinRestingHours* crt_constraint=(ConstraintStudentsSetMinRestingHours*)ctr;
2539 				if(initialStudentsSetName == crt_constraint->students)
2540 					crt_constraint->students=finalStudentsSetName;
2541 			}
2542 
2543 			//mornings-afternoons
2544 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_DAILY_REAL_DAYS){
2545 				ConstraintStudentsSetMaxHoursDailyRealDays* crt_constraint=(ConstraintStudentsSetMaxHoursDailyRealDays*)ctr;
2546 				if(initialStudentsSetName == crt_constraint->students)
2547 					crt_constraint->students=finalStudentsSetName;
2548 			}
2549 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_REAL_DAYS_PER_WEEK){
2550 				ConstraintStudentsSetMaxRealDaysPerWeek* crt_constraint=(ConstraintStudentsSetMaxRealDaysPerWeek*)ctr;
2551 				if(initialStudentsSetName == crt_constraint->students)
2552 					crt_constraint->students=finalStudentsSetName;
2553 			}
2554 			//2020-06-25
2555 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_AFTERNOONS_PER_WEEK){
2556 				ConstraintStudentsSetMaxAfternoonsPerWeek* crt_constraint=(ConstraintStudentsSetMaxAfternoonsPerWeek*)ctr;
2557 				if(initialStudentsSetName == crt_constraint->students)
2558 					crt_constraint->students=finalStudentsSetName;
2559 			}
2560 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_MORNINGS_PER_WEEK){
2561 				ConstraintStudentsSetMaxMorningsPerWeek* crt_constraint=(ConstraintStudentsSetMaxMorningsPerWeek*)ctr;
2562 				if(initialStudentsSetName == crt_constraint->students)
2563 					crt_constraint->students=finalStudentsSetName;
2564 			}
2565 			//2020-06-26
2566 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_AFTERNOONS_PER_WEEK){
2567 				ConstraintStudentsSetMinAfternoonsPerWeek* crt_constraint=(ConstraintStudentsSetMinAfternoonsPerWeek*)ctr;
2568 				if(initialStudentsSetName == crt_constraint->students)
2569 					crt_constraint->students=finalStudentsSetName;
2570 			}
2571 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_MORNINGS_PER_WEEK){
2572 				ConstraintStudentsSetMinMorningsPerWeek* crt_constraint=(ConstraintStudentsSetMinMorningsPerWeek*)ctr;
2573 				if(initialStudentsSetName == crt_constraint->students)
2574 					crt_constraint->students=finalStudentsSetName;
2575 			}
2576 			//
2577 
2578 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MORNING_INTERVAL_MAX_DAYS_PER_WEEK){
2579 				ConstraintStudentsSetMorningIntervalMaxDaysPerWeek* crt_constraint=(ConstraintStudentsSetMorningIntervalMaxDaysPerWeek*)ctr;
2580 				if(initialStudentsSetName == crt_constraint->students)
2581 					crt_constraint->students=finalStudentsSetName;
2582 			}
2583 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_AFTERNOON_INTERVAL_MAX_DAYS_PER_WEEK){
2584 				ConstraintStudentsSetAfternoonIntervalMaxDaysPerWeek* crt_constraint=(ConstraintStudentsSetAfternoonIntervalMaxDaysPerWeek*)ctr;
2585 				if(initialStudentsSetName == crt_constraint->students)
2586 					crt_constraint->students=finalStudentsSetName;
2587 			}
2588 
2589 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_DAILY_REAL_DAYS){
2590 				ConstraintStudentsSetActivityTagMaxHoursDailyRealDays* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursDailyRealDays*)ctr;
2591 				if(initialStudentsSetName == crt_constraint->students)
2592 					crt_constraint->students=finalStudentsSetName;
2593 			}
2594 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_HOURS_PER_MORNING){
2595 				ConstraintStudentsSetMinHoursPerMorning* crt_constraint=(ConstraintStudentsSetMinHoursPerMorning*)ctr;
2596 				if(initialStudentsSetName == crt_constraint->students)
2597 					crt_constraint->students=finalStudentsSetName;
2598 			}
2599 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_AFTERNOONS_EARLY_MAX_BEGINNINGS_AT_SECOND_HOUR){
2600 				ConstraintStudentsSetAfternoonsEarlyMaxBeginningsAtSecondHour* crt_constraint=(ConstraintStudentsSetAfternoonsEarlyMaxBeginningsAtSecondHour*)ctr;
2601 				if(initialStudentsSetName == crt_constraint->students)
2602 					crt_constraint->students=finalStudentsSetName;
2603 			}
2604 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MORNINGS_EARLY_MAX_BEGINNINGS_AT_SECOND_HOUR){
2605 				ConstraintStudentsSetMorningsEarlyMaxBeginningsAtSecondHour* crt_constraint=(ConstraintStudentsSetMorningsEarlyMaxBeginningsAtSecondHour*)ctr;
2606 				if(initialStudentsSetName == crt_constraint->students)
2607 					crt_constraint->students=finalStudentsSetName;
2608 			}
2609 			//2020-06-28
2610 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_PER_ALL_AFTERNOONS){
2611 				ConstraintStudentsSetMaxHoursPerAllAfternoons* crt_constraint=(ConstraintStudentsSetMaxHoursPerAllAfternoons*)ctr;
2612 				if(initialStudentsSetName == crt_constraint->students)
2613 					crt_constraint->students=finalStudentsSetName;
2614 			}
2615 			//
2616 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_REAL_DAY){
2617 				ConstraintStudentsSetMaxGapsPerRealDay* crt_constraint=(ConstraintStudentsSetMaxGapsPerRealDay*)ctr;
2618 				if(initialStudentsSetName == crt_constraint->students)
2619 					crt_constraint->students=finalStudentsSetName;
2620 			}
2621 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_WEEK_FOR_REAL_DAYS){
2622 				ConstraintStudentsSetMaxGapsPerWeekForRealDays* crt_constraint=(ConstraintStudentsSetMaxGapsPerWeekForRealDays*)ctr;
2623 				if(initialStudentsSetName == crt_constraint->students)
2624 					crt_constraint->students=finalStudentsSetName;
2625 			}
2626 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_SPAN_PER_REAL_DAY){
2627 				ConstraintStudentsSetMaxSpanPerRealDay* crt_constraint=(ConstraintStudentsSetMaxSpanPerRealDay*)ctr;
2628 				if(initialStudentsSetName == crt_constraint->students)
2629 					crt_constraint->students=finalStudentsSetName;
2630 			}
2631 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_RESTING_HOURS_BETWEEN_MORNING_AND_AFTERNOON){
2632 				ConstraintStudentsSetMinRestingHoursBetweenMorningAndAfternoon* crt_constraint=(ConstraintStudentsSetMinRestingHoursBetweenMorningAndAfternoon*)ctr;
2633 				if(initialStudentsSetName == crt_constraint->students)
2634 					crt_constraint->students=finalStudentsSetName;
2635 			}
2636 		}
2637 
2638 		for(SpaceConstraint* ctr : qAsConst(spaceConstraintsList)){
2639 			if(ctr->type==CONSTRAINT_STUDENTS_SET_HOME_ROOM){
2640 				ConstraintStudentsSetHomeRoom* crt_constraint=(ConstraintStudentsSetHomeRoom*)ctr;
2641 				if(initialStudentsSetName == crt_constraint->studentsName)
2642 					crt_constraint->studentsName=finalStudentsSetName;
2643 			}
2644 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_HOME_ROOMS){
2645 				ConstraintStudentsSetHomeRooms* crt_constraint=(ConstraintStudentsSetHomeRooms*)ctr;
2646 				if(initialStudentsSetName == crt_constraint->studentsName)
2647 					crt_constraint->studentsName=finalStudentsSetName;
2648 			}
2649 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_BUILDING_CHANGES_PER_DAY){
2650 				ConstraintStudentsSetMaxBuildingChangesPerDay* crt_constraint=(ConstraintStudentsSetMaxBuildingChangesPerDay*)ctr;
2651 				if(initialStudentsSetName == crt_constraint->studentsName)
2652 					crt_constraint->studentsName=finalStudentsSetName;
2653 			}
2654 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_BUILDING_CHANGES_PER_WEEK){
2655 				ConstraintStudentsSetMaxBuildingChangesPerWeek* crt_constraint=(ConstraintStudentsSetMaxBuildingChangesPerWeek*)ctr;
2656 				if(initialStudentsSetName == crt_constraint->studentsName)
2657 					crt_constraint->studentsName=finalStudentsSetName;
2658 			}
2659 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_GAPS_BETWEEN_BUILDING_CHANGES){
2660 				ConstraintStudentsSetMinGapsBetweenBuildingChanges* crt_constraint=(ConstraintStudentsSetMinGapsBetweenBuildingChanges*)ctr;
2661 				if(initialStudentsSetName == crt_constraint->studentsName)
2662 					crt_constraint->studentsName=finalStudentsSetName;
2663 			}
2664 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_ROOM_CHANGES_PER_DAY){
2665 				ConstraintStudentsSetMaxRoomChangesPerDay* crt_constraint=(ConstraintStudentsSetMaxRoomChangesPerDay*)ctr;
2666 				if(initialStudentsSetName == crt_constraint->studentsName)
2667 					crt_constraint->studentsName=finalStudentsSetName;
2668 			}
2669 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_ROOM_CHANGES_PER_WEEK){
2670 				ConstraintStudentsSetMaxRoomChangesPerWeek* crt_constraint=(ConstraintStudentsSetMaxRoomChangesPerWeek*)ctr;
2671 				if(initialStudentsSetName == crt_constraint->studentsName)
2672 					crt_constraint->studentsName=finalStudentsSetName;
2673 			}
2674 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_GAPS_BETWEEN_ROOM_CHANGES){
2675 				ConstraintStudentsSetMinGapsBetweenRoomChanges* crt_constraint=(ConstraintStudentsSetMinGapsBetweenRoomChanges*)ctr;
2676 				if(initialStudentsSetName == crt_constraint->studentsName)
2677 					crt_constraint->studentsName=finalStudentsSetName;
2678 			}
2679 
2680 			//mornings-afternoons
2681 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_ROOM_CHANGES_PER_REAL_DAY){
2682 				ConstraintStudentsSetMaxRoomChangesPerRealDay* crt_constraint=(ConstraintStudentsSetMaxRoomChangesPerRealDay*)ctr;
2683 				if(initialStudentsSetName == crt_constraint->studentsName)
2684 					crt_constraint->studentsName=finalStudentsSetName;
2685 			}
2686 		}
2687 	}
2688 
2689 	assert(studentsSet->name==initialStudentsSetName);
2690 	assert(studentsSet->numberOfStudents==initialNumberOfStudents);
2691 	studentsSet->name=finalStudentsSetName;
2692 	studentsSet->numberOfStudents=finalNumberOfStudents;
2693 
2694 	assert(permanentStudentsHash.contains(initialStudentsSetName));
2695 	if(initialStudentsSetName!=finalStudentsSetName){
2696 		permanentStudentsHash.remove(initialStudentsSetName);
2697 		permanentStudentsHash.insert(studentsSet->name, studentsSet);
2698 
2699 		if(ssnatHash.contains(initialStudentsSetName)){
2700 			QSet<ConstraintStudentsSetNotAvailableTimes*> cs=ssnatHash.value(initialStudentsSetName);
2701 			ssnatHash.remove(initialStudentsSetName);
2702 			assert(!ssnatHash.contains(finalStudentsSetName));
2703 			ssnatHash.insert(finalStudentsSetName, cs);
2704 		}
2705 	}
2706 
2707 	this->internalStructureComputed=false;
2708 	setRulesModifiedAndOtherThings(this);
2709 
2710 	teachers_schedule_ready=false;
2711 	students_schedule_ready=false;
2712 	rooms_schedule_ready=false;
2713 
2714 	return true;
2715 }
2716 
2717 //by Volker Dirr (start) - very similar to Liviu's modifyStudentsSet
modifyStudentsSets(const QHash<QString,QString> & oldAndNewStudentsSetNames)2718 bool Rules::modifyStudentsSets(const QHash<QString, QString>& oldAndNewStudentsSetNames){
2719 	if(oldAndNewStudentsSetNames.isEmpty())
2720 		return true;
2721 
2722 	for(Activity* act : qAsConst(activitiesList)){
2723 		for(int i=0; i<act->studentsNames.count(); i++)
2724 			if(oldAndNewStudentsSetNames.contains(act->studentsNames.at(i)))
2725 				act->studentsNames[i]=oldAndNewStudentsSetNames.value(act->studentsNames.at(i));
2726 	}
2727 
2728 	for(TimeConstraint* ctr : qAsConst(timeConstraintsList)){
2729 		if(ctr->type==CONSTRAINT_STUDENTS_SET_NOT_AVAILABLE_TIMES){
2730 			ConstraintStudentsSetNotAvailableTimes* crt_constraint=(ConstraintStudentsSetNotAvailableTimes*)ctr;
2731 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2732 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2733 		}
2734 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_DAILY){
2735 			ConstraintStudentsSetMaxHoursDaily* crt_constraint=(ConstraintStudentsSetMaxHoursDaily*)ctr;
2736 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2737 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2738 		}
2739 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_DAYS_PER_WEEK){
2740 			ConstraintStudentsSetMaxDaysPerWeek* crt_constraint=(ConstraintStudentsSetMaxDaysPerWeek*)ctr;
2741 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2742 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2743 		}
2744 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_INTERVAL_MAX_DAYS_PER_WEEK){
2745 			ConstraintStudentsSetIntervalMaxDaysPerWeek* crt_constraint=(ConstraintStudentsSetIntervalMaxDaysPerWeek*)ctr;
2746 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2747 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2748 		}
2749 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_CONTINUOUSLY){
2750 			ConstraintStudentsSetMaxHoursContinuously* crt_constraint=(ConstraintStudentsSetMaxHoursContinuously*)ctr;
2751 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2752 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2753 		}
2754 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
2755 			ConstraintStudentsSetActivityTagMaxHoursContinuously* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursContinuously*)ctr;
2756 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2757 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2758 		}
2759 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_DAILY){
2760 			ConstraintStudentsSetActivityTagMaxHoursDaily* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursDaily*)ctr;
2761 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2762 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2763 		}
2764 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MIN_HOURS_DAILY){
2765 			ConstraintStudentsSetActivityTagMinHoursDaily* crt_constraint=(ConstraintStudentsSetActivityTagMinHoursDaily*)ctr;
2766 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2767 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2768 		}
2769 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_HOURS_DAILY){
2770 			ConstraintStudentsSetMinHoursDaily* crt_constraint=(ConstraintStudentsSetMinHoursDaily*)ctr;
2771 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2772 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2773 		}
2774 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_GAPS_BETWEEN_ORDERED_PAIR_OF_ACTIVITY_TAGS){
2775 			ConstraintStudentsSetMinGapsBetweenOrderedPairOfActivityTags* crt_constraint=(ConstraintStudentsSetMinGapsBetweenOrderedPairOfActivityTags*)ctr;
2776 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2777 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2778 		}
2779 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_EARLY_MAX_BEGINNINGS_AT_SECOND_HOUR){
2780 			ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour* crt_constraint=(ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour*)ctr;
2781 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2782 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2783 		}
2784 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_WEEK){
2785 			ConstraintStudentsSetMaxGapsPerWeek* crt_constraint=(ConstraintStudentsSetMaxGapsPerWeek*)ctr;
2786 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2787 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2788 		}
2789 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_DAY){
2790 			ConstraintStudentsSetMaxGapsPerDay* crt_constraint=(ConstraintStudentsSetMaxGapsPerDay*)ctr;
2791 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2792 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2793 		}
2794 		else if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_TIME_SLOTS){
2795 			ConstraintActivitiesPreferredTimeSlots* crt_constraint=(ConstraintActivitiesPreferredTimeSlots*)ctr;
2796 			if(oldAndNewStudentsSetNames.contains(crt_constraint->p_studentsName))
2797 				crt_constraint->p_studentsName=oldAndNewStudentsSetNames.value(crt_constraint->p_studentsName);
2798 		}
2799 		else if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_STARTING_TIMES){
2800 			ConstraintActivitiesPreferredStartingTimes* crt_constraint=(ConstraintActivitiesPreferredStartingTimes*)ctr;
2801 			if(oldAndNewStudentsSetNames.contains(crt_constraint->studentsName))
2802 				crt_constraint->studentsName=oldAndNewStudentsSetNames.value(crt_constraint->studentsName);
2803 		}
2804 		else if(ctr->type==CONSTRAINT_ACTIVITIES_END_STUDENTS_DAY){
2805 			ConstraintActivitiesEndStudentsDay* crt_constraint=(ConstraintActivitiesEndStudentsDay*)ctr;
2806 			if(oldAndNewStudentsSetNames.contains(crt_constraint->studentsName))
2807 				crt_constraint->studentsName=oldAndNewStudentsSetNames.value(crt_constraint->studentsName);
2808 		}
2809 		else if(ctr->type==CONSTRAINT_ACTIVITIES_END_TEACHERS_DAY){
2810 			ConstraintActivitiesEndTeachersDay* crt_constraint=(ConstraintActivitiesEndTeachersDay*)ctr;
2811 			if(oldAndNewStudentsSetNames.contains(crt_constraint->studentsName))
2812 				crt_constraint->studentsName=oldAndNewStudentsSetNames.value(crt_constraint->studentsName);
2813 		}
2814 		else if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_TIME_SLOTS){
2815 			ConstraintSubactivitiesPreferredTimeSlots* crt_constraint=(ConstraintSubactivitiesPreferredTimeSlots*)ctr;
2816 			if(oldAndNewStudentsSetNames.contains(crt_constraint->p_studentsName))
2817 				crt_constraint->p_studentsName=oldAndNewStudentsSetNames.value(crt_constraint->p_studentsName);
2818 		}
2819 		else if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_STARTING_TIMES){
2820 			ConstraintSubactivitiesPreferredStartingTimes* crt_constraint=(ConstraintSubactivitiesPreferredStartingTimes*)ctr;
2821 			if(oldAndNewStudentsSetNames.contains(crt_constraint->studentsName))
2822 				crt_constraint->studentsName=oldAndNewStudentsSetNames.value(crt_constraint->studentsName);
2823 		}
2824 		//2017-02-07
2825 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_SPAN_PER_DAY){
2826 			ConstraintStudentsSetMaxSpanPerDay* crt_constraint=(ConstraintStudentsSetMaxSpanPerDay*)ctr;
2827 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2828 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2829 		}
2830 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_RESTING_HOURS){
2831 			ConstraintStudentsSetMinRestingHours* crt_constraint=(ConstraintStudentsSetMinRestingHours*)ctr;
2832 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2833 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2834 		}
2835 
2836 		//mornings-afternoons
2837 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_DAILY_REAL_DAYS){
2838 			ConstraintStudentsSetMaxHoursDailyRealDays* crt_constraint=(ConstraintStudentsSetMaxHoursDailyRealDays*)ctr;
2839 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2840 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2841 		}
2842 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_REAL_DAYS_PER_WEEK){
2843 			ConstraintStudentsSetMaxRealDaysPerWeek* crt_constraint=(ConstraintStudentsSetMaxRealDaysPerWeek*)ctr;
2844 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2845 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2846 		}
2847 		//2020-06-25
2848 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_AFTERNOONS_PER_WEEK){
2849 			ConstraintStudentsSetMaxAfternoonsPerWeek* crt_constraint=(ConstraintStudentsSetMaxAfternoonsPerWeek*)ctr;
2850 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2851 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2852 		}
2853 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_MORNINGS_PER_WEEK){
2854 			ConstraintStudentsSetMaxMorningsPerWeek* crt_constraint=(ConstraintStudentsSetMaxMorningsPerWeek*)ctr;
2855 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2856 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2857 		}
2858 		//2020-06-26
2859 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_AFTERNOONS_PER_WEEK){
2860 			ConstraintStudentsSetMinAfternoonsPerWeek* crt_constraint=(ConstraintStudentsSetMinAfternoonsPerWeek*)ctr;
2861 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2862 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2863 		}
2864 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_MORNINGS_PER_WEEK){
2865 			ConstraintStudentsSetMinMorningsPerWeek* crt_constraint=(ConstraintStudentsSetMinMorningsPerWeek*)ctr;
2866 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2867 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2868 		}
2869 		//
2870 
2871 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MORNING_INTERVAL_MAX_DAYS_PER_WEEK){
2872 			ConstraintStudentsSetMorningIntervalMaxDaysPerWeek* crt_constraint=(ConstraintStudentsSetMorningIntervalMaxDaysPerWeek*)ctr;
2873 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2874 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2875 		}
2876 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_AFTERNOON_INTERVAL_MAX_DAYS_PER_WEEK){
2877 			ConstraintStudentsSetAfternoonIntervalMaxDaysPerWeek* crt_constraint=(ConstraintStudentsSetAfternoonIntervalMaxDaysPerWeek*)ctr;
2878 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2879 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2880 		}
2881 
2882 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_DAILY_REAL_DAYS){
2883 			ConstraintStudentsSetActivityTagMaxHoursDailyRealDays* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursDailyRealDays*)ctr;
2884 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2885 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2886 		}
2887 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_HOURS_PER_MORNING){
2888 			ConstraintStudentsSetMinHoursPerMorning* crt_constraint=(ConstraintStudentsSetMinHoursPerMorning*)ctr;
2889 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2890 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2891 		}
2892 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_AFTERNOONS_EARLY_MAX_BEGINNINGS_AT_SECOND_HOUR){
2893 			ConstraintStudentsSetAfternoonsEarlyMaxBeginningsAtSecondHour* crt_constraint=(ConstraintStudentsSetAfternoonsEarlyMaxBeginningsAtSecondHour*)ctr;
2894 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2895 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2896 		}
2897 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MORNINGS_EARLY_MAX_BEGINNINGS_AT_SECOND_HOUR){
2898 			ConstraintStudentsSetMorningsEarlyMaxBeginningsAtSecondHour* crt_constraint=(ConstraintStudentsSetMorningsEarlyMaxBeginningsAtSecondHour*)ctr;
2899 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2900 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2901 		}
2902 		//2020-06-28
2903 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_PER_ALL_AFTERNOONS){
2904 			ConstraintStudentsSetMaxHoursPerAllAfternoons* crt_constraint=(ConstraintStudentsSetMaxHoursPerAllAfternoons*)ctr;
2905 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2906 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2907 		}
2908 		//
2909 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_REAL_DAY){
2910 			ConstraintStudentsSetMaxGapsPerRealDay* crt_constraint=(ConstraintStudentsSetMaxGapsPerRealDay*)ctr;
2911 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2912 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2913 		}
2914 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_WEEK_FOR_REAL_DAYS){
2915 			ConstraintStudentsSetMaxGapsPerWeekForRealDays* crt_constraint=(ConstraintStudentsSetMaxGapsPerWeekForRealDays*)ctr;
2916 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2917 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2918 		}
2919 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_SPAN_PER_REAL_DAY){
2920 			ConstraintStudentsSetMaxSpanPerRealDay* crt_constraint=(ConstraintStudentsSetMaxSpanPerRealDay*)ctr;
2921 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2922 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2923 		}
2924 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_RESTING_HOURS_BETWEEN_MORNING_AND_AFTERNOON){
2925 			ConstraintStudentsSetMinRestingHoursBetweenMorningAndAfternoon* crt_constraint=(ConstraintStudentsSetMinRestingHoursBetweenMorningAndAfternoon*)ctr;
2926 			if(oldAndNewStudentsSetNames.contains(crt_constraint->students))
2927 				crt_constraint->students=oldAndNewStudentsSetNames.value(crt_constraint->students);
2928 		}
2929 	}
2930 
2931 	for(SpaceConstraint* ctr : qAsConst(spaceConstraintsList)){
2932 		if(ctr->type==CONSTRAINT_STUDENTS_SET_HOME_ROOM){
2933 			ConstraintStudentsSetHomeRoom* crt_constraint=(ConstraintStudentsSetHomeRoom*)ctr;
2934 			if(oldAndNewStudentsSetNames.contains(crt_constraint->studentsName))
2935 				crt_constraint->studentsName=oldAndNewStudentsSetNames.value(crt_constraint->studentsName);
2936 		}
2937 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_HOME_ROOMS){
2938 			ConstraintStudentsSetHomeRooms* crt_constraint=(ConstraintStudentsSetHomeRooms*)ctr;
2939 			if(oldAndNewStudentsSetNames.contains(crt_constraint->studentsName))
2940 				crt_constraint->studentsName=oldAndNewStudentsSetNames.value(crt_constraint->studentsName);
2941 		}
2942 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_BUILDING_CHANGES_PER_DAY){
2943 			ConstraintStudentsSetMaxBuildingChangesPerDay* crt_constraint=(ConstraintStudentsSetMaxBuildingChangesPerDay*)ctr;
2944 			if(oldAndNewStudentsSetNames.contains(crt_constraint->studentsName))
2945 				crt_constraint->studentsName=oldAndNewStudentsSetNames.value(crt_constraint->studentsName);
2946 		}
2947 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_BUILDING_CHANGES_PER_WEEK){
2948 			ConstraintStudentsSetMaxBuildingChangesPerWeek* crt_constraint=(ConstraintStudentsSetMaxBuildingChangesPerWeek*)ctr;
2949 			if(oldAndNewStudentsSetNames.contains(crt_constraint->studentsName))
2950 				crt_constraint->studentsName=oldAndNewStudentsSetNames.value(crt_constraint->studentsName);
2951 		}
2952 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_GAPS_BETWEEN_BUILDING_CHANGES){
2953 			ConstraintStudentsSetMinGapsBetweenBuildingChanges* crt_constraint=(ConstraintStudentsSetMinGapsBetweenBuildingChanges*)ctr;
2954 			if(oldAndNewStudentsSetNames.contains(crt_constraint->studentsName))
2955 				crt_constraint->studentsName=oldAndNewStudentsSetNames.value(crt_constraint->studentsName);
2956 		}
2957 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_ROOM_CHANGES_PER_DAY){
2958 			ConstraintStudentsSetMaxRoomChangesPerDay* crt_constraint=(ConstraintStudentsSetMaxRoomChangesPerDay*)ctr;
2959 			if(oldAndNewStudentsSetNames.contains(crt_constraint->studentsName))
2960 				crt_constraint->studentsName=oldAndNewStudentsSetNames.value(crt_constraint->studentsName);
2961 		}
2962 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_ROOM_CHANGES_PER_WEEK){
2963 			ConstraintStudentsSetMaxRoomChangesPerWeek* crt_constraint=(ConstraintStudentsSetMaxRoomChangesPerWeek*)ctr;
2964 			if(oldAndNewStudentsSetNames.contains(crt_constraint->studentsName))
2965 				crt_constraint->studentsName=oldAndNewStudentsSetNames.value(crt_constraint->studentsName);
2966 		}
2967 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_GAPS_BETWEEN_ROOM_CHANGES){
2968 			ConstraintStudentsSetMinGapsBetweenRoomChanges* crt_constraint=(ConstraintStudentsSetMinGapsBetweenRoomChanges*)ctr;
2969 			if(oldAndNewStudentsSetNames.contains(crt_constraint->studentsName))
2970 				crt_constraint->studentsName=oldAndNewStudentsSetNames.value(crt_constraint->studentsName);
2971 		}
2972 
2973 		//mornings-afternoons
2974 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_ROOM_CHANGES_PER_REAL_DAY){
2975 			ConstraintStudentsSetMaxRoomChangesPerRealDay* crt_constraint=(ConstraintStudentsSetMaxRoomChangesPerRealDay*)ctr;
2976 			if(oldAndNewStudentsSetNames.contains(crt_constraint->studentsName))
2977 				crt_constraint->studentsName=oldAndNewStudentsSetNames.value(crt_constraint->studentsName);
2978 		}
2979 	}
2980 
2981 	QHash<QString, QString>::const_iterator i=oldAndNewStudentsSetNames.constBegin();
2982 	while(i!=oldAndNewStudentsSetNames.constEnd()) {
2983 		StudentsSet* studentsSet=searchStudentsSet(i.key());
2984 		assert(studentsSet!=nullptr);
2985 		studentsSet->name=i.value();
2986 
2987 		assert(permanentStudentsHash.contains(i.key()));
2988 		permanentStudentsHash.remove(i.key());
2989 		permanentStudentsHash.insert(studentsSet->name, studentsSet);
2990 
2991 		assert(i.key()!=i.value());
2992 		if(ssnatHash.contains(i.key())){
2993 			QSet<ConstraintStudentsSetNotAvailableTimes*> cs=ssnatHash.value(i.key());
2994 			ssnatHash.remove(i.key());
2995 			assert(!ssnatHash.contains(i.value()));
2996 			ssnatHash.insert(i.value(), cs);
2997 		}
2998 		i++;
2999 	}
3000 
3001 	this->internalStructureComputed=false;
3002 	setRulesModifiedAndOtherThings(this);
3003 
3004 	teachers_schedule_ready=false;
3005 	students_schedule_ready=false;
3006 	rooms_schedule_ready=false;
3007 
3008 	return true;
3009 }
3010 //by Volker Dirr (end) - very similar to Liviu's modifyStudentsSet
3011 
sortYearsAlphabetically()3012 void Rules::sortYearsAlphabetically()
3013 {
3014 	std::stable_sort(this->yearsList.begin(), this->yearsList.end(), yearsAscending);
3015 
3016 	this->internalStructureComputed=false;
3017 	setRulesModifiedAndOtherThings(this);
3018 
3019 	teachers_schedule_ready=false;
3020 	students_schedule_ready=false;
3021 	rooms_schedule_ready=false;
3022 }
3023 
addGroup(const QString & yearName,StudentsGroup * group)3024 bool Rules::addGroup(const QString& yearName, StudentsGroup* group)
3025 {
3026 	StudentsYear* sty=nullptr;
3027 	for(int i=0; i<this->yearsList.size(); i++){
3028 		sty=yearsList[i];
3029 		if(sty->name==yearName)
3030 			break;
3031 	}
3032 	assert(sty);
3033 
3034 	for(int i=0; i<sty->groupsList.size(); i++){
3035 		StudentsGroup* stg=sty->groupsList[i];
3036 		if(stg->name==group->name)
3037 			return false;
3038 	}
3039 
3040 	sty->groupsList << group; //append
3041 
3042 	if(!permanentStudentsHash.contains(group->name))
3043 		permanentStudentsHash.insert(group->name, group);
3044 
3045 	this->internalStructureComputed=false;
3046 	setRulesModifiedAndOtherThings(this);
3047 
3048 	teachers_schedule_ready=false;
3049 	students_schedule_ready=false;
3050 	rooms_schedule_ready=false;
3051 
3052 	return true;
3053 }
3054 
addGroupFast(StudentsYear * year,StudentsGroup * group)3055 bool Rules::addGroupFast(StudentsYear* year, StudentsGroup* group)
3056 {
3057 	year->groupsList << group; //append
3058 
3059 	this->internalStructureComputed=false;
3060 	setRulesModifiedAndOtherThings(this);
3061 
3062 	teachers_schedule_ready=false;
3063 	students_schedule_ready=false;
3064 	rooms_schedule_ready=false;
3065 
3066 	return true;
3067 }
3068 
removeGroup(const QString & yearName,const QString & groupName)3069 bool Rules::removeGroup(const QString& yearName, const QString& groupName)
3070 {
3071 	StudentsYear* yearPointer=nullptr;
3072 	for(StudentsYear* ty : qAsConst(this->yearsList)){
3073 		if(ty->name==yearName){
3074 			yearPointer=ty;
3075 			break;
3076 		}
3077 	}
3078 
3079 	assert(yearPointer!=nullptr);
3080 
3081 	StudentsGroup* groupPointer=nullptr;
3082 	for(StudentsGroup* tg : qAsConst(yearPointer->groupsList)){
3083 		if(tg->name==groupName){
3084 			groupPointer=tg;
3085 			break;
3086 		}
3087 	}
3088 
3089 	assert(groupPointer!=nullptr);
3090 
3091 	//pointers
3092 	QSet<StudentsSet*> tmpSet;
3093 	for(StudentsYear* year : qAsConst(yearsList)){
3094 		if(year->name!=yearName){
3095 			//tmpSet.insert(year); useless
3096 			for(StudentsGroup* group : qAsConst(year->groupsList)){
3097 				if(group->name==groupName) //we shall not purge groupName, because it still exists in the current year
3098 					tmpSet.insert(group);
3099 				for(StudentsSubgroup* subgroup : qAsConst(group->subgroupsList))
3100 					tmpSet.insert(subgroup);
3101 			}
3102 		}
3103 		else{
3104 			for(StudentsGroup* group : qAsConst(year->groupsList))
3105 				if(group->name!=groupName){
3106 					//tmpSet.insert(group); //useless
3107 					for(StudentsSubgroup* subgroup : qAsConst(group->subgroupsList))
3108 						tmpSet.insert(subgroup);
3109 				}
3110 		}
3111 	}
3112 
3113 	QSet<StudentsSet*> toBeRemoved;
3114 	if(!tmpSet.contains(groupPointer))
3115 		toBeRemoved.insert(groupPointer);
3116 	for(StudentsSubgroup* subgroup : qAsConst(groupPointer->subgroupsList)){
3117 		assert(!toBeRemoved.contains(subgroup));
3118 		if(!tmpSet.contains(subgroup))
3119 			toBeRemoved.insert(subgroup);
3120 	}
3121 
3122 	updateActivitiesWhenRemovingStudents(toBeRemoved, false);
3123 
3124 	for(int i=0; i<yearPointer->groupsList.count(); i++)
3125 		if(yearPointer->groupsList.at(i)==groupPointer){
3126 			yearPointer->groupsList.removeAt(i);
3127 			break;
3128 		}
3129 
3130 	for(StudentsSet* studentsSet : qAsConst(toBeRemoved)){
3131 		assert(permanentStudentsHash.contains(studentsSet->name));
3132 		permanentStudentsHash.remove(studentsSet->name);
3133 
3134 		delete studentsSet;
3135 	}
3136 
3137 	if(toBeRemoved.count()>0)
3138 		updateConstraintsAfterRemoval();
3139 
3140 	this->internalStructureComputed=false;
3141 	setRulesModifiedAndOtherThings(this);
3142 
3143 	teachers_schedule_ready=false;
3144 	students_schedule_ready=false;
3145 	rooms_schedule_ready=false;
3146 
3147 	return true;
3148 }
3149 
purgeGroup(const QString & groupName)3150 bool Rules::purgeGroup(const QString& groupName)
3151 {
3152 	StudentsGroup* groupPointer=nullptr;
3153 	for(StudentsYear* year : qAsConst(yearsList)){
3154 		int j=-1;
3155 		for(int i=0; i<year->groupsList.count(); i++){
3156 			if(year->groupsList.at(i)->name==groupName){
3157 				j=i;
3158 				if(groupPointer==nullptr)
3159 					groupPointer=year->groupsList.at(i);
3160 				else
3161 					assert(groupPointer==year->groupsList.at(i));
3162 				break;
3163 			}
3164 		}
3165 		if(j>=0)
3166 			year->groupsList.removeAt(j);
3167 	}
3168 
3169 	assert(groupPointer!=nullptr);
3170 
3171 	//pointers
3172 	QSet<StudentsSet*> tmpSet;
3173 	for(StudentsYear* year : qAsConst(yearsList))
3174 		for(StudentsGroup* group : qAsConst(year->groupsList))
3175 			for(StudentsSubgroup* subgroup : qAsConst(group->subgroupsList))
3176 				tmpSet.insert(subgroup);
3177 
3178 	QSet<StudentsSet*> toBeRemoved;
3179 	if(!tmpSet.contains(groupPointer))
3180 		toBeRemoved.insert(groupPointer);
3181 	else
3182 		assert(0);
3183 	for(StudentsSubgroup* subgroup : qAsConst(groupPointer->subgroupsList)){
3184 		assert(!toBeRemoved.contains(subgroup));
3185 		if(!tmpSet.contains(subgroup))
3186 			toBeRemoved.insert(subgroup);
3187 	}
3188 
3189 	updateActivitiesWhenRemovingStudents(toBeRemoved, false);
3190 
3191 	for(StudentsSet* studentsSet : qAsConst(toBeRemoved)){
3192 		assert(permanentStudentsHash.contains(studentsSet->name));
3193 		permanentStudentsHash.remove(studentsSet->name);
3194 
3195 		delete studentsSet;
3196 	}
3197 
3198 	if(toBeRemoved.count()>0)
3199 		updateConstraintsAfterRemoval();
3200 
3201 	this->internalStructureComputed=false;
3202 	setRulesModifiedAndOtherThings(this);
3203 
3204 	teachers_schedule_ready=false;
3205 	students_schedule_ready=false;
3206 	rooms_schedule_ready=false;
3207 
3208 	return true;
3209 }
3210 
searchGroup(const QString & yearName,const QString & groupName)3211 int Rules::searchGroup(const QString& yearName, const QString& groupName)
3212 {
3213 	StudentsYear* sty=nullptr;
3214 	for(StudentsYear* ty : qAsConst(yearsList))
3215 		if(ty->name==yearName){
3216 			sty=ty;
3217 			break;
3218 		}
3219 	assert(sty!=nullptr);
3220 
3221 	for(int i=0; i<sty->groupsList.size(); i++)
3222 		if(sty->groupsList[i]->name==groupName)
3223 			return i;
3224 
3225 	return -1;
3226 }
3227 
searchAugmentedGroup(const QString & yearName,const QString & groupName)3228 int Rules::searchAugmentedGroup(const QString& yearName, const QString& groupName)
3229 {
3230 	StudentsYear* sty=nullptr;
3231 	for(StudentsYear* ty : qAsConst(augmentedYearsList))
3232 		if(ty->name==yearName){
3233 			sty=ty;
3234 			break;
3235 		}
3236 	assert(sty!=nullptr);
3237 
3238 	for(int i=0; i<sty->groupsList.size(); i++)
3239 		if(sty->groupsList[i]->name==groupName)
3240 			return i;
3241 
3242 	return -1;
3243 }
3244 
sortGroupsAlphabetically(const QString & yearName)3245 void Rules::sortGroupsAlphabetically(const QString& yearName)
3246 {
3247 	StudentsYear* sty=this->yearsList[this->searchYear(yearName)];
3248 	assert(sty);
3249 
3250 	std::stable_sort(sty->groupsList.begin(), sty->groupsList.end(), groupsAscending);
3251 
3252 	this->internalStructureComputed=false;
3253 	setRulesModifiedAndOtherThings(this);
3254 
3255 	teachers_schedule_ready=false;
3256 	students_schedule_ready=false;
3257 	rooms_schedule_ready=false;
3258 }
3259 
addSubgroup(const QString & yearName,const QString & groupName,StudentsSubgroup * subgroup)3260 bool Rules::addSubgroup(const QString& yearName, const QString& groupName, StudentsSubgroup* subgroup)
3261 {
3262 	StudentsYear* sty=this->yearsList.at(this->searchYear(yearName));
3263 	assert(sty);
3264 	StudentsGroup* stg=sty->groupsList.at(this->searchGroup(yearName, groupName));
3265 	assert(stg);
3266 
3267 	for(int i=0; i<stg->subgroupsList.size(); i++){
3268 		StudentsSubgroup* sts=stg->subgroupsList[i];
3269 		if(sts->name==subgroup->name)
3270 			return false;
3271 	}
3272 
3273 	stg->subgroupsList << subgroup; //append
3274 
3275 	if(!permanentStudentsHash.contains(subgroup->name))
3276 		permanentStudentsHash.insert(subgroup->name, subgroup);
3277 
3278 	this->internalStructureComputed=false;
3279 	setRulesModifiedAndOtherThings(this);
3280 
3281 	teachers_schedule_ready=false;
3282 	students_schedule_ready=false;
3283 	rooms_schedule_ready=false;
3284 
3285 	return true;
3286 }
3287 
addSubgroupFast(StudentsYear * year,StudentsGroup * group,StudentsSubgroup * subgroup)3288 bool Rules::addSubgroupFast(StudentsYear* year, StudentsGroup* group, StudentsSubgroup* subgroup)
3289 {
3290 	Q_UNUSED(year);
3291 
3292 	group->subgroupsList << subgroup; //append
3293 
3294 	this->internalStructureComputed=false;
3295 	setRulesModifiedAndOtherThings(this);
3296 
3297 	teachers_schedule_ready=false;
3298 	students_schedule_ready=false;
3299 	rooms_schedule_ready=false;
3300 
3301 	return true;
3302 }
3303 
removeSubgroup(const QString & yearName,const QString & groupName,const QString & subgroupName)3304 bool Rules::removeSubgroup(const QString& yearName, const QString& groupName, const QString& subgroupName)
3305 {
3306 	StudentsYear* yearPointer=nullptr;
3307 	for(StudentsYear* ty : qAsConst(this->yearsList)){
3308 		if(ty->name==yearName){
3309 			yearPointer=ty;
3310 			break;
3311 		}
3312 	}
3313 
3314 	assert(yearPointer!=nullptr);
3315 
3316 	StudentsGroup* groupPointer=nullptr;
3317 	for(StudentsGroup* tg : qAsConst(yearPointer->groupsList)){
3318 		if(tg->name==groupName){
3319 			groupPointer=tg;
3320 			break;
3321 		}
3322 	}
3323 
3324 	assert(groupPointer!=nullptr);
3325 
3326 	StudentsSubgroup* subgroupPointer=nullptr;
3327 	for(StudentsSubgroup* ts : qAsConst(groupPointer->subgroupsList)){
3328 		if(ts->name==subgroupName){
3329 			subgroupPointer=ts;
3330 			break;
3331 		}
3332 	}
3333 
3334 	assert(subgroupPointer!=nullptr);
3335 
3336 	//pointers
3337 	QSet<StudentsSet*> toBeRemoved;
3338 	toBeRemoved.insert(subgroupPointer);
3339 	for(StudentsYear* year : qAsConst(yearsList))
3340 		for(StudentsGroup* group : qAsConst(year->groupsList))
3341 			for(StudentsSubgroup* subgroup : qAsConst(group->subgroupsList))
3342 				if(subgroup->name==subgroupName && (year->name!=yearName || group->name!=groupName))
3343 					toBeRemoved.remove(subgroupPointer);
3344 
3345 	updateActivitiesWhenRemovingStudents(toBeRemoved, false);
3346 
3347 	for(int i=0; i<groupPointer->subgroupsList.count(); i++)
3348 		if(groupPointer->subgroupsList.at(i)==subgroupPointer){
3349 			groupPointer->subgroupsList.removeAt(i);
3350 			break;
3351 		}
3352 
3353 	for(StudentsSet* studentsSet : qAsConst(toBeRemoved)){
3354 		assert(permanentStudentsHash.contains(studentsSet->name));
3355 		permanentStudentsHash.remove(studentsSet->name);
3356 
3357 		delete studentsSet;
3358 	}
3359 
3360 	if(toBeRemoved.count()>0)
3361 		updateConstraintsAfterRemoval();
3362 
3363 	this->internalStructureComputed=false;
3364 	setRulesModifiedAndOtherThings(this);
3365 
3366 	teachers_schedule_ready=false;
3367 	students_schedule_ready=false;
3368 	rooms_schedule_ready=false;
3369 
3370 	return true;
3371 }
3372 
purgeSubgroup(const QString & subgroupName)3373 bool Rules::purgeSubgroup(const QString& subgroupName)
3374 {
3375 	StudentsSubgroup* subgroupPointer=nullptr;
3376 	for(StudentsYear* year : qAsConst(yearsList))
3377 		for(StudentsGroup* group : qAsConst(year->groupsList)){
3378 			int j=-1;
3379 			for(int i=0; i<group->subgroupsList.count(); i++){
3380 				if(group->subgroupsList.at(i)->name==subgroupName){
3381 					j=i;
3382 					if(subgroupPointer==nullptr)
3383 						subgroupPointer=group->subgroupsList.at(i);
3384 					else
3385 						assert(subgroupPointer==group->subgroupsList.at(i));
3386 					break;
3387 				}
3388 			}
3389 			if(j>=0)
3390 				group->subgroupsList.removeAt(j);
3391 		}
3392 
3393 	assert(subgroupPointer!=nullptr);
3394 
3395 	//pointers
3396 	QSet<StudentsSet*> toBeRemoved;
3397 	toBeRemoved.insert(subgroupPointer);
3398 
3399 	updateActivitiesWhenRemovingStudents(toBeRemoved, false);
3400 
3401 	for(StudentsSet* studentsSet : qAsConst(toBeRemoved)){
3402 		assert(permanentStudentsHash.contains(studentsSet->name));
3403 		permanentStudentsHash.remove(studentsSet->name);
3404 
3405 		delete studentsSet;
3406 	}
3407 
3408 	if(toBeRemoved.count()>0)
3409 		updateConstraintsAfterRemoval();
3410 
3411 	this->internalStructureComputed=false;
3412 	setRulesModifiedAndOtherThings(this);
3413 
3414 	teachers_schedule_ready=false;
3415 	students_schedule_ready=false;
3416 	rooms_schedule_ready=false;
3417 
3418 	return true;
3419 }
3420 
searchSubgroup(const QString & yearName,const QString & groupName,const QString & subgroupName)3421 int Rules::searchSubgroup(const QString& yearName, const QString& groupName, const QString& subgroupName)
3422 {
3423 	StudentsYear* sty=nullptr;
3424 	for(StudentsYear* ty : qAsConst(yearsList))
3425 		if(ty->name==yearName){
3426 			sty=ty;
3427 			break;
3428 		}
3429 	assert(sty!=nullptr);
3430 
3431 	StudentsGroup* stg=nullptr;
3432 	for(StudentsGroup* tg : qAsConst(sty->groupsList))
3433 		if(tg->name==groupName){
3434 			stg=tg;
3435 			break;
3436 		}
3437 	assert(stg!=nullptr);
3438 
3439 	for(int i=0; i<stg->subgroupsList.size(); i++)
3440 		if(stg->subgroupsList[i]->name==subgroupName)
3441 			return i;
3442 
3443 	return -1;
3444 }
3445 
searchAugmentedSubgroup(const QString & yearName,const QString & groupName,const QString & subgroupName)3446 int Rules::searchAugmentedSubgroup(const QString& yearName, const QString& groupName, const QString& subgroupName)
3447 {
3448 	StudentsYear* sty=nullptr;
3449 	for(StudentsYear* ty : qAsConst(augmentedYearsList))
3450 		if(ty->name==yearName){
3451 			sty=ty;
3452 			break;
3453 		}
3454 	assert(sty!=nullptr);
3455 
3456 	StudentsGroup* stg=nullptr;
3457 	for(StudentsGroup* tg : qAsConst(sty->groupsList))
3458 		if(tg->name==groupName){
3459 			stg=tg;
3460 			break;
3461 		}
3462 	assert(stg!=nullptr);
3463 
3464 	for(int i=0; i<stg->subgroupsList.size(); i++)
3465 		if(stg->subgroupsList[i]->name==subgroupName)
3466 			return i;
3467 
3468 	return -1;
3469 }
3470 
sortSubgroupsAlphabetically(const QString & yearName,const QString & groupName)3471 void Rules::sortSubgroupsAlphabetically(const QString& yearName, const QString& groupName)
3472 {
3473 	StudentsYear* sty=this->yearsList.at(this->searchYear(yearName));
3474 	assert(sty);
3475 	StudentsGroup* stg=sty->groupsList.at(this->searchGroup(yearName, groupName));
3476 	assert(stg);
3477 
3478 	std::stable_sort(stg->subgroupsList.begin(), stg->subgroupsList.end(), subgroupsAscending);
3479 
3480 	this->internalStructureComputed=false;
3481 	setRulesModifiedAndOtherThings(this);
3482 
3483 	teachers_schedule_ready=false;
3484 	students_schedule_ready=false;
3485 	rooms_schedule_ready=false;
3486 }
3487 
addSimpleActivityFast(QWidget * parent,int _id,int _activityGroupId,const QStringList & _teachersNames,const QString & _subjectName,const QStringList & _activityTagsNames,const QStringList & _studentsNames,int _duration,int _totalDuration,bool _active,bool _computeNTotalStudents,int _nTotalStudents,int _computedNumberOfStudents)3488 bool Rules::addSimpleActivityFast(
3489 	QWidget* parent,
3490 	int _id,
3491 	int _activityGroupId,
3492 	const QStringList& _teachersNames,
3493 	const QString& _subjectName,
3494 	const QStringList& _activityTagsNames,
3495 	const QStringList& _studentsNames,
3496 	int _duration,
3497 	int _totalDuration,
3498 	bool _active,
3499 	bool _computeNTotalStudents,
3500 	int _nTotalStudents,
3501 	int _computedNumberOfStudents)
3502 {
3503 	//check for duplicates - idea and code by Volker Dirr
3504 	int t=QStringList(_teachersNames).removeDuplicates();
3505 	if(t>0)
3506 		RulesReconcilableMessage::warning(parent, tr("FET warning"), tr("Activity with Id=%1 contains %2 duplicate teachers - please correct that")
3507 		 .arg(_id).arg(t));
3508 
3509 	t=QStringList(_studentsNames).removeDuplicates();
3510 	if(t>0)
3511 		RulesReconcilableMessage::warning(parent, tr("FET warning"), tr("Activity with Id=%1 contains %2 duplicate students sets - please correct that")
3512 		 .arg(_id).arg(t));
3513 
3514 	t=QStringList(_activityTagsNames).removeDuplicates();
3515 	if(t>0)
3516 		RulesReconcilableMessage::warning(parent, tr("FET warning"), tr("Activity with Id=%1 contains %2 duplicate activity tags - please correct that")
3517 		 .arg(_id).arg(t));
3518 
3519 	Activity *act=new Activity(*this, _id, _activityGroupId, _teachersNames, _subjectName, _activityTagsNames,
3520 		_studentsNames, _duration, _totalDuration, _active, _computeNTotalStudents, _nTotalStudents, _computedNumberOfStudents);
3521 
3522 	this->activitiesList << act; //append
3523 
3524 	assert(!activitiesPointerHash.contains(act->id));
3525 	activitiesPointerHash.insert(act->id, act);
3526 
3527 	this->internalStructureComputed=false;
3528 	setRulesModifiedAndOtherThings(this);
3529 
3530 	teachers_schedule_ready=false;
3531 	students_schedule_ready=false;
3532 	rooms_schedule_ready=false;
3533 
3534 	return true;
3535 }
3536 
addSplitActivityFast(QWidget * parent,int _firstActivityId,int _activityGroupId,const QStringList & _teachersNames,const QString & _subjectName,const QStringList & _activityTagsNames,const QStringList & _studentsNames,int _nSplits,int _totalDuration,QList<int> _durations,QList<bool> _active,int _minDayDistance,double _weightPercentage,bool _consecutiveIfSameDay,bool _computeNTotalStudents,int _nTotalStudents,int _computedNumberOfStudents)3537 bool Rules::addSplitActivityFast(
3538 	QWidget* parent,
3539 	int _firstActivityId,
3540 	int _activityGroupId,
3541 	const QStringList& _teachersNames,
3542 	const QString& _subjectName,
3543 	const QStringList& _activityTagsNames,
3544 	const QStringList& _studentsNames,
3545 	int _nSplits,
3546 	int _totalDuration,
3547 	QList<int> _durations,
3548 	QList<bool> _active,
3549 	int _minDayDistance,
3550 	double _weightPercentage,
3551 	bool _consecutiveIfSameDay,
3552 	bool _computeNTotalStudents,
3553 	int _nTotalStudents,
3554 	int _computedNumberOfStudents)
3555 {
3556 	//check for duplicates - idea and code by Volker Dirr
3557 	int t=QStringList(_teachersNames).removeDuplicates();
3558 	if(t>0)
3559 		RulesReconcilableMessage::warning(parent, tr("FET warning"), tr("Activities with group_Id=%1 contain %2 duplicate teachers - please correct that")
3560 		 .arg(_activityGroupId).arg(t));
3561 
3562 	t=QStringList(_studentsNames).removeDuplicates();
3563 	if(t>0)
3564 		RulesReconcilableMessage::warning(parent, tr("FET warning"), tr("Activities with group_Id=%1 contain %2 duplicate students sets - please correct that")
3565 		 .arg(_activityGroupId).arg(t));
3566 
3567 	t=QStringList(_activityTagsNames).removeDuplicates();
3568 	if(t>0)
3569 		RulesReconcilableMessage::warning(parent, tr("FET warning"), tr("Activities with group_Id=%1 contain %2 duplicate activity tags - please correct that")
3570 		 .arg(_activityGroupId).arg(t));
3571 
3572 	assert(_firstActivityId==_activityGroupId);
3573 
3574 	QList<int> acts;
3575 
3576 	acts.clear();
3577 	for(int i=0; i<_nSplits; i++){
3578 		Activity *act=new Activity(*this, _firstActivityId+i, _activityGroupId,
3579 		 _teachersNames, _subjectName, _activityTagsNames, _studentsNames,
3580 		 _durations[i], _totalDuration, _active[i], _computeNTotalStudents, _nTotalStudents, _computedNumberOfStudents);
3581 
3582 		this->activitiesList << act; //append
3583 
3584 		assert(!activitiesPointerHash.contains(act->id));
3585 		activitiesPointerHash.insert(act->id, act);
3586 
3587 		acts.append(_firstActivityId+i);
3588 	}
3589 
3590 	if(_minDayDistance>0){
3591 		TimeConstraint *constr=new ConstraintMinDaysBetweenActivities(_weightPercentage, _consecutiveIfSameDay, _nSplits, acts, _minDayDistance);
3592 		bool tmp=this->addTimeConstraint(constr);
3593 		assert(tmp);
3594 	}
3595 
3596 	this->internalStructureComputed=false;
3597 	setRulesModifiedAndOtherThings(this);
3598 
3599 	teachers_schedule_ready=false;
3600 	students_schedule_ready=false;
3601 	rooms_schedule_ready=false;
3602 
3603 	return true;
3604 }
3605 
3606 /*void Rules::removeActivity(int _id)
3607 {
3608 	QList<int> tmpList;
3609 	tmpList.append(_id);
3610 	removeActivities(tmpList, true);
3611 }*/
3612 
removeActivity(int _id,int _activityGroupId)3613 void Rules::removeActivity(int _id, int _activityGroupId)
3614 {
3615 	QList<int> tmpList;
3616 	for(Activity* act : qAsConst(activitiesList))
3617 		if(_id==act->id || (_activityGroupId>0 && _activityGroupId==act->activityGroupId))
3618 			tmpList.append(act->id);
3619 	removeActivities(tmpList, true);
3620 }
3621 
removeActivities(const QList<int> & _idsList,bool updateConstraints)3622 void Rules::removeActivities(const QList<int>& _idsList, bool updateConstraints)
3623 {
3624 	if(_idsList.count()==0)
3625 		return;
3626 
3627 #if QT_VERSION >= QT_VERSION_CHECK(5,14,0)
3628 	QSet<int> _removedIdsSet=QSet<int>(_idsList.begin(), _idsList.end());
3629 #else
3630 	QSet<int> _removedIdsSet=_idsList.toSet();
3631 #endif
3632 
3633 	QSet<int> _groupIdsSet;
3634 	for(Activity* act : qAsConst(activitiesList))
3635 		if(act->activityGroupId>0 && _removedIdsSet.contains(act->id))
3636 			_groupIdsSet.insert(act->activityGroupId);
3637 	for(Activity* act : qAsConst(activitiesList))
3638 		if(act->activityGroupId>0 && _groupIdsSet.contains(act->activityGroupId))
3639 			_removedIdsSet.insert(act->id);
3640 
3641 	ActivitiesList newActivitiesList;
3642 	ActivitiesList toBeRemoved;
3643 
3644 	for(int i=0; i<activitiesList.count(); i++){
3645 		int id=activitiesList.at(i)->id;
3646 		if(!_removedIdsSet.contains(id)){
3647 			newActivitiesList.append(activitiesList[i]);
3648 		}
3649 		else{
3650 			toBeRemoved.append(activitiesList[i]);
3651 
3652 			assert(activitiesPointerHash.contains(id));
3653 			activitiesPointerHash.remove(id);
3654 
3655 			if(mdbaHash.contains(id)){
3656 				int t=mdbaHash.remove(id);
3657 				assert(t==1);
3658 			}
3659 		}
3660 	}
3661 
3662 	for(Activity* act : qAsConst(toBeRemoved))
3663 		delete act;
3664 	toBeRemoved.clear();
3665 	//while(!toBeRemoved.isEmpty())
3666 	//	delete toBeRemoved.takeFirst();
3667 
3668 	activitiesList=newActivitiesList;
3669 
3670 	updateGroupActivitiesInInitialOrderAfterRemoval();
3671 	if(updateConstraints)
3672 		updateConstraintsAfterRemoval();
3673 
3674 	this->internalStructureComputed=false;
3675 	setRulesModifiedAndOtherThings(this);
3676 
3677 	teachers_schedule_ready=false;
3678 	students_schedule_ready=false;
3679 	rooms_schedule_ready=false;
3680 }
3681 
modifyActivity(int _id,int _activityGroupId,const QStringList & _teachersNames,const QString & _subjectName,const QStringList & _activityTagsNames,const QStringList & _studentsNames,int _nSplits,int _totalDuration,QList<int> _durations,QList<bool> _active,bool _computeNTotalStudents,int _nTotalStudents)3682 void Rules::modifyActivity(
3683 	int _id,
3684 	int _activityGroupId,
3685 	const QStringList& _teachersNames,
3686 	const QString& _subjectName,
3687 	const QStringList& _activityTagsNames,
3688 	const QStringList& _studentsNames,
3689 	//int _nTotalStudents,
3690 	int _nSplits,
3691 	int _totalDuration,
3692 	QList<int> _durations,
3693 	//int _parities[],
3694 	QList<bool> _active,
3695 	bool _computeNTotalStudents,
3696 	int _nTotalStudents)
3697 {
3698 	int i=0;
3699 	for(int j=0; j<this->activitiesList.size(); j++){
3700 		Activity* act=this->activitiesList[j];
3701 		if((_activityGroupId==0 && act->id==_id) || (_activityGroupId!=0 && act->activityGroupId==_activityGroupId)){
3702 			act->teachersNames=_teachersNames;
3703 			act->subjectName=_subjectName;
3704 			act->activityTagsNames=_activityTagsNames;
3705 			act->studentsNames=_studentsNames;
3706 			act->duration=_durations[i];
3707 			//act->parity=_parities[i];
3708 			act->active=_active[i];
3709 			act->totalDuration=_totalDuration;
3710 			act->computeNTotalStudents=_computeNTotalStudents;
3711 			act->nTotalStudents=_nTotalStudents;
3712 			i++;
3713 		}
3714 	}
3715 
3716 	assert(i==_nSplits);
3717 
3718 	this->internalStructureComputed=false;
3719 	setRulesModifiedAndOtherThings(this);
3720 
3721 	teachers_schedule_ready=false;
3722 	students_schedule_ready=false;
3723 	rooms_schedule_ready=false;
3724 }
3725 
modifySubactivity(int _id,int _activityGroupId,const QStringList & _teachersNames,const QString & _subjectName,const QStringList & _activityTagsNames,const QStringList & _studentsNames,int _duration,bool _active,bool _computeNTotalStudents,int _nTotalStudents)3726 void Rules::modifySubactivity(
3727 	int _id,
3728 	int _activityGroupId,
3729 	const QStringList& _teachersNames,
3730 	const QString& _subjectName,
3731 	const QStringList& _activityTagsNames,
3732 	const QStringList& _studentsNames,
3733 	int _duration,
3734 	bool _active,
3735 	bool _computeNTotalStudents,
3736 	int _nTotalStudents)
3737 {
3738 	QList<Activity*> actsList;
3739 	Activity* crtAct=nullptr;
3740 
3741 	for(Activity* act : qAsConst(this->activitiesList)){
3742 		if(act->id==_id && act->activityGroupId==_activityGroupId){
3743 			crtAct=act;
3744 			//actsList.append(act);
3745 		}
3746 		else if(act->activityGroupId!=0 && _activityGroupId!=0 && act->activityGroupId==_activityGroupId){
3747 			actsList.append(act);
3748 		}
3749 	}
3750 
3751 	assert(crtAct!=nullptr);
3752 
3753 	int td=0;
3754 	for(Activity* act : qAsConst(actsList))
3755 		td+=act->duration;
3756 	td+=_duration; //crtAct->duration;
3757 	for(Activity* act : qAsConst(actsList))
3758 		act->totalDuration=td;
3759 
3760 	crtAct->teachersNames=_teachersNames;
3761 	crtAct->subjectName=_subjectName;
3762 	crtAct->activityTagsNames=_activityTagsNames;
3763 	crtAct->studentsNames=_studentsNames;
3764 	crtAct->duration=_duration;
3765 	crtAct->totalDuration=td;
3766 	crtAct->active=_active;
3767 	crtAct->computeNTotalStudents=_computeNTotalStudents;
3768 	crtAct->nTotalStudents=_nTotalStudents;
3769 
3770 	this->internalStructureComputed=false;
3771 	setRulesModifiedAndOtherThings(this);
3772 
3773 	teachers_schedule_ready=false;
3774 	students_schedule_ready=false;
3775 	rooms_schedule_ready=false;
3776 }
3777 
addRoom(Room * rm)3778 bool Rules::addRoom(Room* rm)
3779 {
3780 	if(this->searchRoom(rm->name) >= 0)
3781 		return false;
3782 	this->roomsList << rm; //append
3783 	this->internalStructureComputed=false;
3784 	setRulesModifiedAndOtherThings(this);
3785 
3786 	teachers_schedule_ready=false;
3787 	students_schedule_ready=false;
3788 	rooms_schedule_ready=false;
3789 
3790 	return true;
3791 }
3792 
addRoomFast(Room * rm)3793 bool Rules::addRoomFast(Room* rm)
3794 {
3795 	this->roomsList << rm; //append
3796 	this->internalStructureComputed=false;
3797 	setRulesModifiedAndOtherThings(this);
3798 
3799 	teachers_schedule_ready=false;
3800 	students_schedule_ready=false;
3801 	rooms_schedule_ready=false;
3802 
3803 	return true;
3804 }
3805 
searchRoom(const QString & roomName)3806 int Rules::searchRoom(const QString& roomName)
3807 {
3808 	for(int i=0; i<this->roomsList.size(); i++)
3809 		if(this->roomsList[i]->name==roomName)
3810 			return i;
3811 
3812 	return -1;
3813 }
3814 
removeRoom(const QString & roomName)3815 bool Rules::removeRoom(const QString& roomName)
3816 {
3817 	int i=this->searchRoom(roomName);
3818 	if(i<0)
3819 		return false;
3820 
3821 	Room* searchedRoom=this->roomsList[i];
3822 	assert(searchedRoom->name==roomName);
3823 
3824 	//the real room to be removed may be found in some virtual rooms' sets
3825 	if(searchedRoom->isVirtual==false){
3826 		for(Room* r : qAsConst(roomsList)){
3827 			if(r->isVirtual==true){
3828 				for(int j=0; j<r->realRoomsSetsList.count(); j++){
3829 					QStringList& sl=r->realRoomsSetsList[j];
3830 					if(sl.contains(roomName)){
3831 						int t=sl.removeAll(roomName);
3832 						assert(t==1);
3833 					}
3834 				}
3835 			}
3836 		}
3837 	}
3838 
3839 	for(SpaceConstraint* ctr : qAsConst(spaceConstraintsList)){
3840 		if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOM){
3841 			ConstraintActivityPreferredRoom* c=(ConstraintActivityPreferredRoom*)ctr;
3842 
3843 			if(c->preferredRealRoomsNames.contains(roomName))
3844 				c->preferredRealRoomsNames.removeAll(roomName);
3845 		}
3846 	}
3847 
3848 	delete this->roomsList[i];
3849 	this->roomsList.removeAt(i);
3850 
3851 	updateConstraintsAfterRemoval();
3852 
3853 	this->internalStructureComputed=false;
3854 	setRulesModifiedAndOtherThings(this);
3855 
3856 	teachers_schedule_ready=false;
3857 	students_schedule_ready=false;
3858 	rooms_schedule_ready=false;
3859 
3860 	return true;
3861 }
3862 
modifyRoom(const QString & initialRoomName,const QString & finalRoomName,const QString & building,int capacity)3863 bool Rules::modifyRoom(const QString& initialRoomName, const QString& finalRoomName, const QString& building, int capacity)
3864 {
3865 	int i=this->searchRoom(initialRoomName);
3866 	if(i<0)
3867 		return false;
3868 
3869 	Room* searchedRoom=this->roomsList[i];
3870 	assert(searchedRoom->name==initialRoomName);
3871 
3872 	//the real room to be renamed may be found in some virtual rooms' sets
3873 	if(initialRoomName!=finalRoomName){
3874 		if(searchedRoom->isVirtual==false){
3875 			for(Room* r : qAsConst(roomsList)){
3876 				if(r->isVirtual==true){
3877 					for(int j=0; j<r->realRoomsSetsList.count(); j++){
3878 						QStringList& sl=r->realRoomsSetsList[j];
3879 						for(int k=0; k<sl.count(); k++){
3880 							if(sl[k]==initialRoomName){
3881 								sl[k]=finalRoomName;
3882 							}
3883 						}
3884 					}
3885 				}
3886 			}
3887 		}
3888 	}
3889 
3890 	for(SpaceConstraint* ctr : qAsConst(spaceConstraintsList)){
3891 		if(ctr->type==CONSTRAINT_ROOM_NOT_AVAILABLE_TIMES){
3892 			ConstraintRoomNotAvailableTimes* crna=(ConstraintRoomNotAvailableTimes*)ctr;
3893 			if(crna->room==initialRoomName)
3894 				crna->room=finalRoomName;
3895 		}
3896 		else if(ctr->type==CONSTRAINT_TEACHER_ROOM_NOT_AVAILABLE_TIMES){
3897 			ConstraintTeacherRoomNotAvailableTimes* crna=(ConstraintTeacherRoomNotAvailableTimes*)ctr;
3898 			if(crna->room==initialRoomName)
3899 				crna->room=finalRoomName;
3900 		}
3901 		else if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOM){
3902 			ConstraintActivityPreferredRoom* c=(ConstraintActivityPreferredRoom*)ctr;
3903 			if(c->roomName==initialRoomName)
3904 				c->roomName=finalRoomName;
3905 
3906 			for(int i=0; i<c->preferredRealRoomsNames.count(); i++)
3907 				if(c->preferredRealRoomsNames.at(i)==initialRoomName)
3908 					c->preferredRealRoomsNames[i]=finalRoomName;
3909 		}
3910 		else if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOMS){
3911 			ConstraintActivityPreferredRooms* c=(ConstraintActivityPreferredRooms*)ctr;
3912 			int t=0;
3913 			for(QStringList::iterator it=c->roomsNames.begin(); it!=c->roomsNames.end(); it++){
3914 				if((*it)==initialRoomName){
3915 					*it=finalRoomName;
3916 					t++;
3917 				}
3918 			}
3919 			assert(t<=1);
3920 		}
3921 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_HOME_ROOM){
3922 			ConstraintStudentsSetHomeRoom* c=(ConstraintStudentsSetHomeRoom*)ctr;
3923 			if(c->roomName==initialRoomName)
3924 				c->roomName=finalRoomName;
3925 		}
3926 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_HOME_ROOMS){
3927 			ConstraintStudentsSetHomeRooms* c=(ConstraintStudentsSetHomeRooms*)ctr;
3928 			int t=0;
3929 			for(QStringList::iterator it=c->roomsNames.begin(); it!=c->roomsNames.end(); it++){
3930 				if((*it)==initialRoomName){
3931 					*it=finalRoomName;
3932 					t++;
3933 				}
3934 			}
3935 			assert(t<=1);
3936 		}
3937 		else if(ctr->type==CONSTRAINT_TEACHER_HOME_ROOM){
3938 			ConstraintTeacherHomeRoom* c=(ConstraintTeacherHomeRoom*)ctr;
3939 			if(c->roomName==initialRoomName)
3940 				c->roomName=finalRoomName;
3941 		}
3942 		else if(ctr->type==CONSTRAINT_TEACHER_HOME_ROOMS){
3943 			ConstraintTeacherHomeRooms* c=(ConstraintTeacherHomeRooms*)ctr;
3944 			int t=0;
3945 			for(QStringList::iterator it=c->roomsNames.begin(); it!=c->roomsNames.end(); it++){
3946 				if((*it)==initialRoomName){
3947 					*it=finalRoomName;
3948 					t++;
3949 				}
3950 			}
3951 			assert(t<=1);
3952 		}
3953 		else if(ctr->type==CONSTRAINT_SUBJECT_PREFERRED_ROOM){
3954 			ConstraintSubjectPreferredRoom* c=(ConstraintSubjectPreferredRoom*)ctr;
3955 			if(c->roomName==initialRoomName)
3956 				c->roomName=finalRoomName;
3957 		}
3958 		else if(ctr->type==CONSTRAINT_SUBJECT_PREFERRED_ROOMS){
3959 			ConstraintSubjectPreferredRooms* c=(ConstraintSubjectPreferredRooms*)ctr;
3960 			int t=0;
3961 			for(QStringList::iterator it=c->roomsNames.begin(); it!=c->roomsNames.end(); it++){
3962 				if((*it)==initialRoomName){
3963 					*it=finalRoomName;
3964 					t++;
3965 				}
3966 			}
3967 			assert(t<=1);
3968 		}
3969 		else if(ctr->type==CONSTRAINT_SUBJECT_ACTIVITY_TAG_PREFERRED_ROOM){
3970 			ConstraintSubjectActivityTagPreferredRoom* c=(ConstraintSubjectActivityTagPreferredRoom*)ctr;
3971 			if(c->roomName==initialRoomName)
3972 				c->roomName=finalRoomName;
3973 		}
3974 		else if(ctr->type==CONSTRAINT_SUBJECT_ACTIVITY_TAG_PREFERRED_ROOMS){
3975 			ConstraintSubjectActivityTagPreferredRooms* c=(ConstraintSubjectActivityTagPreferredRooms*)ctr;
3976 			int t=0;
3977 			for(QStringList::iterator it=c->roomsNames.begin(); it!=c->roomsNames.end(); it++){
3978 				if((*it)==initialRoomName){
3979 					*it=finalRoomName;
3980 					t++;
3981 				}
3982 			}
3983 			assert(t<=1);
3984 		}
3985 		else if(ctr->type==CONSTRAINT_ACTIVITY_TAG_PREFERRED_ROOM){
3986 			ConstraintActivityTagPreferredRoom* c=(ConstraintActivityTagPreferredRoom*)ctr;
3987 			if(c->roomName==initialRoomName)
3988 				c->roomName=finalRoomName;
3989 		}
3990 		else if(ctr->type==CONSTRAINT_ACTIVITY_TAG_PREFERRED_ROOMS){
3991 			ConstraintActivityTagPreferredRooms* c=(ConstraintActivityTagPreferredRooms*)ctr;
3992 			int t=0;
3993 			for(QStringList::iterator it=c->roomsNames.begin(); it!=c->roomsNames.end(); it++){
3994 				if((*it)==initialRoomName){
3995 					*it=finalRoomName;
3996 					t++;
3997 				}
3998 			}
3999 			assert(t<=1);
4000 		}
4001 	}
4002 
4003 	searchedRoom->name=finalRoomName;
4004 	searchedRoom->building=building;
4005 	searchedRoom->capacity=capacity;
4006 
4007 	this->internalStructureComputed=false;
4008 	setRulesModifiedAndOtherThings(this);
4009 
4010 	teachers_schedule_ready=false;
4011 	students_schedule_ready=false;
4012 	rooms_schedule_ready=false;
4013 
4014 	return true;
4015 }
4016 
sortRoomsAlphabetically()4017 void Rules::sortRoomsAlphabetically()
4018 {
4019 	std::stable_sort(this->roomsList.begin(), this->roomsList.end(), roomsAscending);
4020 
4021 	this->internalStructureComputed=false;
4022 	setRulesModifiedAndOtherThings(this);
4023 
4024 	teachers_schedule_ready=false;
4025 	students_schedule_ready=false;
4026 	rooms_schedule_ready=false;
4027 }
4028 
addBuilding(Building * bu)4029 bool Rules::addBuilding(Building* bu)
4030 {
4031 	if(this->searchBuilding(bu->name) >= 0)
4032 		return false;
4033 	this->buildingsList << bu; //append
4034 	this->internalStructureComputed=false;
4035 	setRulesModifiedAndOtherThings(this);
4036 
4037 	teachers_schedule_ready=false;
4038 	students_schedule_ready=false;
4039 	rooms_schedule_ready=false;
4040 
4041 	return true;
4042 }
4043 
addBuildingFast(Building * bu)4044 bool Rules::addBuildingFast(Building* bu)
4045 {
4046 	this->buildingsList << bu; //append
4047 	this->internalStructureComputed=false;
4048 	setRulesModifiedAndOtherThings(this);
4049 
4050 	teachers_schedule_ready=false;
4051 	students_schedule_ready=false;
4052 	rooms_schedule_ready=false;
4053 
4054 	return true;
4055 }
4056 
searchBuilding(const QString & buildingName)4057 int Rules::searchBuilding(const QString& buildingName)
4058 {
4059 	for(int i=0; i<this->buildingsList.size(); i++)
4060 		if(this->buildingsList[i]->name==buildingName)
4061 			return i;
4062 
4063 	return -1;
4064 }
4065 
removeBuilding(const QString & buildingName)4066 bool Rules::removeBuilding(const QString& buildingName)
4067 {
4068 	for(Room* rm : qAsConst(this->roomsList))
4069 		if(rm->building==buildingName)
4070 			rm->building="";
4071 
4072 	int i=this->searchBuilding(buildingName);
4073 	if(i<0)
4074 		return false;
4075 
4076 	Building* searchedBuilding=this->buildingsList[i];
4077 	assert(searchedBuilding->name==buildingName);
4078 
4079 	delete this->buildingsList[i];
4080 	this->buildingsList.removeAt(i);
4081 
4082 	this->internalStructureComputed=false;
4083 	setRulesModifiedAndOtherThings(this);
4084 
4085 	teachers_schedule_ready=false;
4086 	students_schedule_ready=false;
4087 	rooms_schedule_ready=false;
4088 
4089 	return true;
4090 }
4091 
modifyBuilding(const QString & initialBuildingName,const QString & finalBuildingName)4092 bool Rules::modifyBuilding(const QString& initialBuildingName, const QString& finalBuildingName)
4093 {
4094 	for(Room* rm : qAsConst(roomsList))
4095 		if(rm->building==initialBuildingName)
4096 			rm->building=finalBuildingName;
4097 
4098 	int i=this->searchBuilding(initialBuildingName);
4099 	if(i<0)
4100 		return false;
4101 
4102 	Building* searchedBuilding=this->buildingsList[i];
4103 	assert(searchedBuilding->name==initialBuildingName);
4104 	searchedBuilding->name=finalBuildingName;
4105 
4106 	this->internalStructureComputed=false;
4107 	setRulesModifiedAndOtherThings(this);
4108 
4109 	teachers_schedule_ready=false;
4110 	students_schedule_ready=false;
4111 	rooms_schedule_ready=false;
4112 
4113 	return true;
4114 }
4115 
sortBuildingsAlphabetically()4116 void Rules::sortBuildingsAlphabetically()
4117 {
4118 	std::stable_sort(this->buildingsList.begin(), this->buildingsList.end(), buildingsAscending);
4119 
4120 	this->internalStructureComputed=false;
4121 	setRulesModifiedAndOtherThings(this);
4122 
4123 	teachers_schedule_ready=false;
4124 	students_schedule_ready=false;
4125 	rooms_schedule_ready=false;
4126 }
4127 
addTimeConstraint(TimeConstraint * ctr)4128 bool Rules::addTimeConstraint(TimeConstraint* ctr)
4129 {
4130 	bool ok=true;
4131 
4132 	//TODO: improve this
4133 
4134 	//check if this constraint is already added, for ConstraintActivityPreferredStartingTime
4135 	if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_STARTING_TIME){
4136 		ConstraintActivityPreferredStartingTime* c=(ConstraintActivityPreferredStartingTime*) ctr;
4137 		QSet<ConstraintActivityPreferredStartingTime*> cs=apstHash.value(c->activityId, QSet<ConstraintActivityPreferredStartingTime*>());
4138 		for(ConstraintActivityPreferredStartingTime* oldc : qAsConst(cs)){
4139 			if((*oldc)==(*c)){
4140 				ok=false;
4141 				break;
4142 			}
4143 		}
4144 
4145 		/*int i;
4146 		for(i=0; i<this->timeConstraintsList.size(); i++){
4147 			TimeConstraint* ctr2=this->timeConstraintsList[i];
4148 			if(ctr2->type==CONSTRAINT_ACTIVITY_PREFERRED_STARTING_TIME)
4149 				if(
4150 				 *((ConstraintActivityPreferredStartingTime*)ctr2)
4151 				 ==
4152 				 *((ConstraintActivityPreferredStartingTime*)ctr)
4153 				)
4154 					break;
4155 		}
4156 
4157 		if(i<this->timeConstraintsList.size())
4158 			ok=false;*/
4159 	}
4160 
4161 	//check if this constraint is already added, for ConstraintMinDaysBetweenActivities
4162 	else if(ctr->type==CONSTRAINT_MIN_DAYS_BETWEEN_ACTIVITIES){
4163 		ConstraintMinDaysBetweenActivities* c=(ConstraintMinDaysBetweenActivities*) ctr;
4164 		for(int aid : qAsConst(c->activitiesId)){
4165 			QSet<ConstraintMinDaysBetweenActivities*> cs=mdbaHash.value(aid, QSet<ConstraintMinDaysBetweenActivities*>());
4166 			for(ConstraintMinDaysBetweenActivities* oldc : qAsConst(cs)){
4167 				if((*oldc)==(*c)){
4168 					ok=false;
4169 					break;
4170 				}
4171 			}
4172 			if(!ok)
4173 				break;
4174 		}
4175 
4176 		/*int i;
4177 		for(i=0; i<this->timeConstraintsList.size(); i++){
4178 			TimeConstraint* ctr2=this->timeConstraintsList[i];
4179 			if(ctr2->type==CONSTRAINT_MIN_DAYS_BETWEEN_ACTIVITIES)
4180 				if(
4181 				 *((ConstraintMinDaysBetweenActivities*)ctr2)
4182 				 ==
4183 				 *((ConstraintMinDaysBetweenActivities*)ctr)
4184 				 )
4185 					break;
4186 		}
4187 
4188 		if(i<this->timeConstraintsList.size())
4189 			ok=false;*/
4190 	}
4191 
4192 	else if(ctr->type==CONSTRAINT_STUDENTS_SET_NOT_AVAILABLE_TIMES){
4193 		ConstraintStudentsSetNotAvailableTimes* c=(ConstraintStudentsSetNotAvailableTimes*) ctr;
4194 		QSet<ConstraintStudentsSetNotAvailableTimes*> cs=ssnatHash.value(c->students, QSet<ConstraintStudentsSetNotAvailableTimes*>());
4195 		for(ConstraintStudentsSetNotAvailableTimes* oldc : qAsConst(cs)){
4196 			if(oldc->students==c->students){
4197 				ok=false;
4198 				break;
4199 			}
4200 		}
4201 
4202 		/*int i;
4203 		ConstraintStudentsSetNotAvailableTimes* ssna=(ConstraintStudentsSetNotAvailableTimes*)ctr;
4204 		for(i=0; i<this->timeConstraintsList.size(); i++){
4205 			TimeConstraint* ctr2=this->timeConstraintsList[i];
4206 			if(ctr2->type==CONSTRAINT_STUDENTS_SET_NOT_AVAILABLE_TIMES) {
4207 				ConstraintStudentsSetNotAvailableTimes* ssna2=(ConstraintStudentsSetNotAvailableTimes*)ctr2;
4208 				if(ssna->students==ssna2->students)
4209 					break;
4210 			}
4211 		}
4212 
4213 		if(i<this->timeConstraintsList.size())
4214 			ok=false;*/
4215 	}
4216 
4217 	else if(ctr->type==CONSTRAINT_TEACHER_NOT_AVAILABLE_TIMES){
4218 		ConstraintTeacherNotAvailableTimes* c=(ConstraintTeacherNotAvailableTimes*) ctr;
4219 		QSet<ConstraintTeacherNotAvailableTimes*> cs=tnatHash.value(c->teacher, QSet<ConstraintTeacherNotAvailableTimes*>());
4220 		for(ConstraintTeacherNotAvailableTimes* oldc : qAsConst(cs)){
4221 			if(oldc->teacher==c->teacher){
4222 				ok=false;
4223 				break;
4224 			}
4225 		}
4226 
4227 		/*int i;
4228 		ConstraintTeacherNotAvailableTimes* tna=(ConstraintTeacherNotAvailableTimes*)ctr;
4229 		for(i=0; i<this->timeConstraintsList.size(); i++){
4230 			TimeConstraint* ctr2=this->timeConstraintsList[i];
4231 			if(ctr2->type==CONSTRAINT_TEACHER_NOT_AVAILABLE_TIMES) {
4232 				ConstraintTeacherNotAvailableTimes* tna2=(ConstraintTeacherNotAvailableTimes*)ctr2;
4233 				if(tna->teacher==tna2->teacher)
4234 					break;
4235 			}
4236 		}
4237 
4238 		if(i<this->timeConstraintsList.size())
4239 			ok=false;*/
4240 	}
4241 
4242 	else if(ctr->type==CONSTRAINT_BREAK_TIMES){
4243 		//ConstraintBreakTimes* c=(ConstraintBreakTimes*) ctr;
4244 		QSet<ConstraintBreakTimes*> cs=btSet;
4245 		if(cs.count()>0)
4246 			ok=false;
4247 		/*int i;
4248 		for(i=0; i<this->timeConstraintsList.size(); i++){
4249 			TimeConstraint* ctr2=this->timeConstraintsList[i];
4250 			if(ctr2->type==CONSTRAINT_BREAK_TIMES)
4251 				break;
4252 		}
4253 
4254 		if(i<this->timeConstraintsList.size())
4255 			ok=false;*/
4256 	}
4257 
4258 	else if(ctr->type==CONSTRAINT_BASIC_COMPULSORY_TIME){
4259 		//ConstraintBasicCompulsoryTime* c=(ConstraintBasicCompulsoryTime*) ctr;
4260 		QSet<ConstraintBasicCompulsoryTime*> cs=bctSet;
4261 		if(cs.count()>0)
4262 			ok=false;
4263 		/*int i;
4264 		for(i=0; i<this->timeConstraintsList.size(); i++){
4265 			TimeConstraint* ctr2=this->timeConstraintsList[i];
4266 			if(ctr2->type==CONSTRAINT_BASIC_COMPULSORY_TIME)
4267 				break;
4268 		}
4269 
4270 		if(i<this->timeConstraintsList.size())
4271 			ok=false;*/
4272 	}
4273 
4274 	if(ok){
4275 		this->timeConstraintsList << ctr; //append
4276 
4277 		if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_STARTING_TIME){
4278 			ConstraintActivityPreferredStartingTime* c=(ConstraintActivityPreferredStartingTime*) ctr;
4279 			QSet<ConstraintActivityPreferredStartingTime*> cs=apstHash.value(c->activityId, QSet<ConstraintActivityPreferredStartingTime*>());
4280 			assert(!cs.contains(c));
4281 			cs.insert(c);
4282 			apstHash.insert(c->activityId, cs);
4283 		}
4284 
4285 		else if(ctr->type==CONSTRAINT_MIN_DAYS_BETWEEN_ACTIVITIES){
4286 			ConstraintMinDaysBetweenActivities* c=(ConstraintMinDaysBetweenActivities*) ctr;
4287 			for(int aid : qAsConst(c->activitiesId)){
4288 				QSet<ConstraintMinDaysBetweenActivities*> cs=mdbaHash.value(aid, QSet<ConstraintMinDaysBetweenActivities*>());
4289 				assert(!cs.contains(c));
4290 				cs.insert(c);
4291 				mdbaHash.insert(aid, cs);
4292 			}
4293 		}
4294 
4295 		else if(ctr->type==CONSTRAINT_TEACHER_NOT_AVAILABLE_TIMES){
4296 			ConstraintTeacherNotAvailableTimes* c=(ConstraintTeacherNotAvailableTimes*) ctr;
4297 			QSet<ConstraintTeacherNotAvailableTimes*> cs=tnatHash.value(c->teacher, QSet<ConstraintTeacherNotAvailableTimes*>());
4298 			assert(!cs.contains(c));
4299 			cs.insert(c);
4300 			tnatHash.insert(c->teacher, cs);
4301 		}
4302 
4303 		else if(ctr->type==CONSTRAINT_STUDENTS_SET_NOT_AVAILABLE_TIMES){
4304 			ConstraintStudentsSetNotAvailableTimes* c=(ConstraintStudentsSetNotAvailableTimes*) ctr;
4305 			QSet<ConstraintStudentsSetNotAvailableTimes*> cs=ssnatHash.value(c->students, QSet<ConstraintStudentsSetNotAvailableTimes*>());
4306 			assert(!cs.contains(c));
4307 			cs.insert(c);
4308 			ssnatHash.insert(c->students, cs);
4309 		}
4310 		else if(ctr->type==CONSTRAINT_BASIC_COMPULSORY_TIME){
4311 			ConstraintBasicCompulsoryTime* c=(ConstraintBasicCompulsoryTime*) ctr;
4312 			QSet<ConstraintBasicCompulsoryTime*> &cs=bctSet;
4313 			assert(!cs.contains(c));
4314 			cs.insert(c);
4315 		}
4316 		else if(ctr->type==CONSTRAINT_BREAK_TIMES){
4317 			ConstraintBreakTimes* c=(ConstraintBreakTimes*) ctr;
4318 			QSet<ConstraintBreakTimes*> &cs=btSet;
4319 			assert(!cs.contains(c));
4320 			cs.insert(c);
4321 		}
4322 
4323 		this->internalStructureComputed=false;
4324 		setRulesModifiedAndOtherThings(this);
4325 		return true;
4326 	}
4327 	else
4328 		return false;
4329 }
4330 
removeTimeConstraint(TimeConstraint * ctr)4331 bool Rules::removeTimeConstraint(TimeConstraint* ctr)
4332 {
4333 	for(int i=0; i<this->timeConstraintsList.size(); i++){
4334 		if(this->timeConstraintsList[i]==ctr){
4335 			if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_STARTING_TIME){
4336 				ConstraintActivityPreferredStartingTime* c=(ConstraintActivityPreferredStartingTime*) ctr;
4337 				QSet<ConstraintActivityPreferredStartingTime*> cs=apstHash.value(c->activityId, QSet<ConstraintActivityPreferredStartingTime*>());
4338 				assert(cs.contains(c));
4339 				cs.remove(c);
4340 				if(!cs.isEmpty()){
4341 					apstHash.insert(c->activityId, cs);
4342 				}
4343 				else{
4344 					int t=apstHash.remove(c->activityId);
4345 					assert(t==1);
4346 				}
4347 			}
4348 
4349 			else if(ctr->type==CONSTRAINT_MIN_DAYS_BETWEEN_ACTIVITIES){
4350 				ConstraintMinDaysBetweenActivities* c=(ConstraintMinDaysBetweenActivities*) ctr;
4351 				for(int aid : qAsConst(c->activitiesId)){
4352 					QSet<ConstraintMinDaysBetweenActivities*> cs=mdbaHash.value(aid, QSet<ConstraintMinDaysBetweenActivities*>());
4353 					assert(cs.contains(c));
4354 					cs.remove(c);
4355 					if(!cs.isEmpty()){
4356 						mdbaHash.insert(aid, cs);
4357 					}
4358 					else{
4359 						int t=mdbaHash.remove(aid);
4360 						assert(t==1);
4361 					}
4362 				}
4363 			}
4364 
4365 			else if(ctr->type==CONSTRAINT_TEACHER_NOT_AVAILABLE_TIMES){
4366 				ConstraintTeacherNotAvailableTimes* c=(ConstraintTeacherNotAvailableTimes*) ctr;
4367 				QSet<ConstraintTeacherNotAvailableTimes*> cs=tnatHash.value(c->teacher, QSet<ConstraintTeacherNotAvailableTimes*>());
4368 				assert(cs.contains(c));
4369 				cs.remove(c);
4370 				if(!cs.isEmpty()){
4371 					assert(0);
4372 					tnatHash.insert(c->teacher, cs);
4373 				}
4374 				else{
4375 					int t=tnatHash.remove(c->teacher);
4376 					assert(t==1);
4377 				}
4378 			}
4379 
4380 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_NOT_AVAILABLE_TIMES){
4381 				ConstraintStudentsSetNotAvailableTimes* c=(ConstraintStudentsSetNotAvailableTimes*) ctr;
4382 				QSet<ConstraintStudentsSetNotAvailableTimes*> cs=ssnatHash.value(c->students, QSet<ConstraintStudentsSetNotAvailableTimes*>());
4383 				assert(cs.contains(c));
4384 				cs.remove(c);
4385 				if(!cs.isEmpty()){
4386 					assert(0);
4387 					ssnatHash.insert(c->students, cs);
4388 				}
4389 				else{
4390 					int t=ssnatHash.remove(c->students);
4391 					assert(t==1);
4392 				}
4393 			}
4394 			else if(ctr->type==CONSTRAINT_BASIC_COMPULSORY_TIME){
4395 				ConstraintBasicCompulsoryTime* c=(ConstraintBasicCompulsoryTime*) ctr;
4396 				QSet<ConstraintBasicCompulsoryTime*> &cs=bctSet;
4397 				assert(cs.contains(c));
4398 				cs.remove(c);
4399 			}
4400 			else if(ctr->type==CONSTRAINT_BREAK_TIMES){
4401 				ConstraintBreakTimes* c=(ConstraintBreakTimes*) ctr;
4402 				QSet<ConstraintBreakTimes*> &cs=btSet;
4403 				assert(cs.contains(c));
4404 				cs.remove(c);
4405 			}
4406 
4407 			delete ctr;
4408 			this->timeConstraintsList.removeAt(i);
4409 			this->internalStructureComputed=false;
4410 			setRulesModifiedAndOtherThings(this);
4411 
4412 			return true;
4413 		}
4414 	}
4415 
4416 	return false;
4417 }
4418 
removeTimeConstraints(QList<TimeConstraint * > _tcl)4419 bool Rules::removeTimeConstraints(QList<TimeConstraint*> _tcl)
4420 {
4421 #if QT_VERSION >= QT_VERSION_CHECK(5,14,0)
4422 	QSet<TimeConstraint*> _tcs=QSet<TimeConstraint*>(_tcl.begin(), _tcl.end());
4423 #else
4424 	QSet<TimeConstraint*> _tcs=_tcl.toSet();
4425 #endif
4426 	QList<TimeConstraint*> remaining;
4427 
4428 	for(int i=0; i<this->timeConstraintsList.size(); i++){
4429 		TimeConstraint* ctr=timeConstraintsList[i];
4430 		if(_tcs.contains(ctr)){
4431 			if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_STARTING_TIME){
4432 				ConstraintActivityPreferredStartingTime* c=(ConstraintActivityPreferredStartingTime*) ctr;
4433 				QSet<ConstraintActivityPreferredStartingTime*> cs=apstHash.value(c->activityId, QSet<ConstraintActivityPreferredStartingTime*>());
4434 				assert(cs.contains(c));
4435 				cs.remove(c);
4436 				if(!cs.isEmpty()){
4437 					apstHash.insert(c->activityId, cs);
4438 				}
4439 				else{
4440 					int t=apstHash.remove(c->activityId);
4441 					assert(t==1);
4442 				}
4443 			}
4444 
4445 			else if(ctr->type==CONSTRAINT_MIN_DAYS_BETWEEN_ACTIVITIES){
4446 				ConstraintMinDaysBetweenActivities* c=(ConstraintMinDaysBetweenActivities*) ctr;
4447 				for(int aid : qAsConst(c->activitiesId)){
4448 					QSet<ConstraintMinDaysBetweenActivities*> cs=mdbaHash.value(aid, QSet<ConstraintMinDaysBetweenActivities*>());
4449 					assert(cs.contains(c));
4450 					cs.remove(c);
4451 					if(!cs.isEmpty()){
4452 						mdbaHash.insert(aid, cs);
4453 					}
4454 					else{
4455 						int t=mdbaHash.remove(aid);
4456 						assert(t==1);
4457 					}
4458 				}
4459 			}
4460 
4461 			else if(ctr->type==CONSTRAINT_TEACHER_NOT_AVAILABLE_TIMES){
4462 				ConstraintTeacherNotAvailableTimes* c=(ConstraintTeacherNotAvailableTimes*) ctr;
4463 				QSet<ConstraintTeacherNotAvailableTimes*> cs=tnatHash.value(c->teacher, QSet<ConstraintTeacherNotAvailableTimes*>());
4464 				assert(cs.contains(c));
4465 				cs.remove(c);
4466 				if(!cs.isEmpty()){
4467 					assert(0);
4468 					tnatHash.insert(c->teacher, cs);
4469 				}
4470 				else{
4471 					int t=tnatHash.remove(c->teacher);
4472 					assert(t==1);
4473 				}
4474 			}
4475 
4476 			else if(ctr->type==CONSTRAINT_STUDENTS_SET_NOT_AVAILABLE_TIMES){
4477 				ConstraintStudentsSetNotAvailableTimes* c=(ConstraintStudentsSetNotAvailableTimes*) ctr;
4478 				QSet<ConstraintStudentsSetNotAvailableTimes*> cs=ssnatHash.value(c->students, QSet<ConstraintStudentsSetNotAvailableTimes*>());
4479 				assert(cs.contains(c));
4480 				cs.remove(c);
4481 				if(!cs.isEmpty()){
4482 					assert(0);
4483 					ssnatHash.insert(c->students, cs);
4484 				}
4485 				else{
4486 					int t=ssnatHash.remove(c->students);
4487 					assert(t==1);
4488 				}
4489 			}
4490 			else if(ctr->type==CONSTRAINT_BASIC_COMPULSORY_TIME){
4491 				ConstraintBasicCompulsoryTime* c=(ConstraintBasicCompulsoryTime*) ctr;
4492 				QSet<ConstraintBasicCompulsoryTime*> &cs=bctSet;
4493 				assert(cs.contains(c));
4494 				cs.remove(c);
4495 			}
4496 			else if(ctr->type==CONSTRAINT_BREAK_TIMES){
4497 				ConstraintBreakTimes* c=(ConstraintBreakTimes*) ctr;
4498 				QSet<ConstraintBreakTimes*> &cs=btSet;
4499 				assert(cs.contains(c));
4500 				cs.remove(c);
4501 			}
4502 
4503 			//_tcs.remove(ctr);
4504 			delete ctr;
4505 		}
4506 		else
4507 			remaining.append(ctr);
4508 	}
4509 
4510 	bool ok;
4511 	assert(timeConstraintsList.count()<=remaining.count()+_tcs.count());
4512 	if(timeConstraintsList.count()==remaining.count()+_tcs.count())
4513 		ok=true;
4514 	else
4515 		ok=false;
4516 
4517 	if(remaining.count()!=timeConstraintsList.count()){
4518 		timeConstraintsList=remaining;
4519 
4520 		this->internalStructureComputed=false;
4521 		setRulesModifiedAndOtherThings(this);
4522 	}
4523 
4524 	return ok;
4525 }
4526 
addSpaceConstraint(SpaceConstraint * ctr)4527 bool Rules::addSpaceConstraint(SpaceConstraint* ctr)
4528 {
4529 	bool ok=true;
4530 
4531 	//TODO: check if this constraint is already added...(if any possibility of duplicates)
4532 	if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOM){
4533 		ConstraintActivityPreferredRoom* c=(ConstraintActivityPreferredRoom*) ctr;
4534 		QSet<ConstraintActivityPreferredRoom*> cs=aprHash.value(c->activityId, QSet<ConstraintActivityPreferredRoom*>());
4535 		for(ConstraintActivityPreferredRoom* oldc : qAsConst(cs)){
4536 			if((*oldc)==(*c)){
4537 				ok=false;
4538 				break;
4539 			}
4540 		}
4541 
4542 		/*int i;
4543 		for(i=0; i<this->spaceConstraintsList.size(); i++){
4544 			SpaceConstraint* ctr2=this->spaceConstraintsList[i];
4545 			if(ctr2->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOM)
4546 				if(
4547 				 *((ConstraintActivityPreferredRoom*)ctr2)
4548 				 ==
4549 				 *((ConstraintActivityPreferredRoom*)ctr)
4550 				)
4551 					break;
4552 		}
4553 
4554 		if(i<this->spaceConstraintsList.size())
4555 			ok=false;*/
4556 	}
4557 /*	else if(ctr->type==CONSTRAINT_ROOM_NOT_AVAILABLE_TIMES){
4558 		int i;
4559 		ConstraintRoomNotAvailableTimes* c=(ConstraintRoomNotAvailableTimes*)ctr;
4560 		for(i=0; i<this->spaceConstraintsList.size(); i++){
4561 			SpaceConstraint* ctr2=this->spaceConstraintsList[i];
4562 			if(ctr2->type==CONSTRAINT_ROOM_NOT_AVAILABLE_TIMES){
4563 				ConstraintRoomNotAvailableTimes* c2=(ConstraintRoomNotAvailableTimes*)ctr2;
4564 				if(c->room==c2->room)
4565 					break;
4566 			}
4567 		}
4568 
4569 		if(i<this->spaceConstraintsList.size())
4570 			ok=false;
4571 	}*/
4572 	else if(ctr->type==CONSTRAINT_BASIC_COMPULSORY_SPACE){
4573 		//ConstraintBasicCompulsorySpace* c=(ConstraintBasicCompulsorySpace*) ctr;
4574 		QSet<ConstraintBasicCompulsorySpace*> cs=bcsSet;
4575 		if(cs.count()>0)
4576 			ok=false;
4577 		/*int i;
4578 		for(i=0; i<this->spaceConstraintsList.size(); i++){
4579 			SpaceConstraint* ctr2=this->spaceConstraintsList[i];
4580 			if(ctr2->type==CONSTRAINT_BASIC_COMPULSORY_SPACE)
4581 				break;
4582 		}
4583 
4584 		if(i<this->spaceConstraintsList.size())
4585 			ok=false;*/
4586 	}
4587 
4588 	if(ok){
4589 		this->spaceConstraintsList << ctr; //append
4590 
4591 		if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOM){
4592 			ConstraintActivityPreferredRoom* c=(ConstraintActivityPreferredRoom*) ctr;
4593 			QSet<ConstraintActivityPreferredRoom*> cs=aprHash.value(c->activityId, QSet<ConstraintActivityPreferredRoom*>());
4594 			assert(!cs.contains(c));
4595 			cs.insert(c);
4596 			aprHash.insert(c->activityId, cs);
4597 		}
4598 		else if(ctr->type==CONSTRAINT_BASIC_COMPULSORY_SPACE){
4599 			ConstraintBasicCompulsorySpace* c=(ConstraintBasicCompulsorySpace*) ctr;
4600 			QSet<ConstraintBasicCompulsorySpace*> &cs=bcsSet;
4601 			assert(!cs.contains(c));
4602 			cs.insert(c);
4603 		}
4604 
4605 		this->internalStructureComputed=false;
4606 		setRulesModifiedAndOtherThings(this);
4607 		return true;
4608 	}
4609 	else
4610 		return false;
4611 }
4612 
removeSpaceConstraint(SpaceConstraint * ctr)4613 bool Rules::removeSpaceConstraint(SpaceConstraint* ctr)
4614 {
4615 	for(int i=0; i<this->spaceConstraintsList.size(); i++){
4616 		if(this->spaceConstraintsList[i]==ctr){
4617 			if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOM){
4618 				ConstraintActivityPreferredRoom* c=(ConstraintActivityPreferredRoom*) ctr;
4619 				QSet<ConstraintActivityPreferredRoom*> cs=aprHash.value(c->activityId, QSet<ConstraintActivityPreferredRoom*>());
4620 				assert(cs.contains(c));
4621 				cs.remove(c);
4622 				aprHash.insert(c->activityId, cs);
4623 			}
4624 
4625 			else if(ctr->type==CONSTRAINT_BASIC_COMPULSORY_SPACE){
4626 				ConstraintBasicCompulsorySpace* c=(ConstraintBasicCompulsorySpace*) ctr;
4627 				QSet<ConstraintBasicCompulsorySpace*> &cs=bcsSet;
4628 				assert(cs.contains(c));
4629 				cs.remove(c);
4630 			}
4631 
4632 			delete ctr;
4633 			this->spaceConstraintsList.removeAt(i);
4634 			this->internalStructureComputed=false;
4635 			setRulesModifiedAndOtherThings(this);
4636 
4637 			return true;
4638 		}
4639 	}
4640 
4641 	return false;
4642 }
4643 
removeSpaceConstraints(QList<SpaceConstraint * > _scl)4644 bool Rules::removeSpaceConstraints(QList<SpaceConstraint*> _scl)
4645 {
4646 #if QT_VERSION >= QT_VERSION_CHECK(5,14,0)
4647 	QSet<SpaceConstraint*> _scs=QSet<SpaceConstraint*>(_scl.begin(), _scl.end());
4648 #else
4649 	QSet<SpaceConstraint*> _scs=_scl.toSet();
4650 #endif
4651 	QList<SpaceConstraint*> remaining;
4652 
4653 	for(int i=0; i<this->spaceConstraintsList.size(); i++){
4654 		SpaceConstraint* ctr=spaceConstraintsList[i];
4655 		if(_scs.contains(ctr)){
4656 			if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOM){
4657 				ConstraintActivityPreferredRoom* c=(ConstraintActivityPreferredRoom*) ctr;
4658 				QSet<ConstraintActivityPreferredRoom*> cs=aprHash.value(c->activityId, QSet<ConstraintActivityPreferredRoom*>());
4659 				assert(cs.contains(c));
4660 				cs.remove(c);
4661 				aprHash.insert(c->activityId, cs);
4662 			}
4663 
4664 			else if(ctr->type==CONSTRAINT_BASIC_COMPULSORY_SPACE){
4665 				ConstraintBasicCompulsorySpace* c=(ConstraintBasicCompulsorySpace*) ctr;
4666 				QSet<ConstraintBasicCompulsorySpace*> &cs=bcsSet;
4667 				assert(cs.contains(c));
4668 				cs.remove(c);
4669 			}
4670 
4671 			//_scs.remove(ctr);
4672 			delete ctr;
4673 		}
4674 		else
4675 			remaining.append(ctr);
4676 	}
4677 
4678 	bool ok;
4679 	assert(spaceConstraintsList.count()<=remaining.count()+_scs.count());
4680 	if(spaceConstraintsList.count()==remaining.count()+_scs.count())
4681 		ok=true;
4682 	else
4683 		ok=false;
4684 
4685 	if(remaining.count()!=spaceConstraintsList.count()){
4686 		spaceConstraintsList=remaining;
4687 
4688 		this->internalStructureComputed=false;
4689 		setRulesModifiedAndOtherThings(this);
4690 	}
4691 
4692 	return ok;
4693 }
4694 
updateGroupActivitiesInInitialOrderAfterRemoval()4695 void Rules::updateGroupActivitiesInInitialOrderAfterRemoval()
4696 {
4697 	GroupActivitiesInInitialOrderList newList;
4698 	GroupActivitiesInInitialOrderList toBeRemovedList;
4699 
4700 	for(GroupActivitiesInInitialOrderItem* item : qAsConst(groupActivitiesInInitialOrderList)){
4701 		item->removeUseless(*this);
4702 		if(item->ids.count()<2)
4703 			toBeRemovedList.append(item);
4704 		else
4705 			newList.append(item);
4706 	}
4707 
4708 	groupActivitiesInInitialOrderList=newList;
4709 
4710 	for(GroupActivitiesInInitialOrderItem* ga : qAsConst(toBeRemovedList))
4711 		delete ga;
4712 	toBeRemovedList.clear();
4713 	//while(!toBeRemovedList.isEmpty())
4714 	//	delete toBeRemovedList.takeFirst();
4715 }
4716 
updateActivitiesWhenRemovingStudents(const QSet<StudentsSet * > & studentsSets,bool updateConstraints)4717 void Rules::updateActivitiesWhenRemovingStudents(const QSet<StudentsSet*>& studentsSets, bool updateConstraints)
4718 {
4719 	if(studentsSets.count()==0)
4720 		return;
4721 
4722 	QList<int> toBeRemovedIds;
4723 
4724 	QHash<QString, int> numberOfStudentsPerSet;
4725 
4726 	for(StudentsSet* studentsSet : qAsConst(studentsSets))
4727 		numberOfStudentsPerSet.insert(studentsSet->name, studentsSet->numberOfStudents);
4728 
4729 	for(Activity* act : qAsConst(activitiesList)){
4730 		QStringList newStudents;
4731 		for(const QString& st : qAsConst(act->studentsNames)){
4732 			if(!numberOfStudentsPerSet.contains(st)){
4733 				newStudents.append(st);
4734 			}
4735 			else{
4736 				if(act->computeNTotalStudents){
4737 					act->nTotalStudents-=numberOfStudentsPerSet.value(st);
4738 					assert(act->nTotalStudents>=0);
4739 				}
4740 			}
4741 		}
4742 		if(act->studentsNames.count()>0 && newStudents.count()==0)
4743 			toBeRemovedIds.append(act->id);
4744 		act->studentsNames=newStudents;
4745 	}
4746 
4747 	removeActivities(toBeRemovedIds, updateConstraints);
4748 }
4749 
updateConstraintsAfterRemoval()4750 void Rules::updateConstraintsAfterRemoval()
4751 {
4752 	bool recomputeTime=false;
4753 	bool recomputeSpace=false;
4754 
4755 	QSet<int> existingActivitiesIds;
4756 	QSet<QString> existingTeachersNames;
4757 	//QSet<QString> existingStudentsNames;
4758 	QSet<QString> existingSubjectsNames;
4759 	QSet<QString> existingActivityTagsNames;
4760 	QSet<QString> existingRoomsNames;
4761 
4762 	QList<TimeConstraint*> toBeRemovedTime;
4763 	QList<SpaceConstraint*> toBeRemovedSpace;
4764 
4765 	for(Activity* act : qAsConst(activitiesList))
4766 		existingActivitiesIds.insert(act->id);
4767 
4768 	for(Teacher* tch : qAsConst(teachersList))
4769 		existingTeachersNames.insert(tch->name);
4770 
4771 	for(Subject* sbj : qAsConst(subjectsList))
4772 		existingSubjectsNames.insert(sbj->name);
4773 
4774 	for(ActivityTag* at : qAsConst(activityTagsList))
4775 		existingActivityTagsNames.insert(at->name);
4776 
4777 	for(Room* rm : qAsConst(roomsList))
4778 		existingRoomsNames.insert(rm->name);
4779 
4780 	for(TimeConstraint* tc : qAsConst(timeConstraintsList)){
4781 		if(tc->type==CONSTRAINT_TEACHER_NOT_AVAILABLE_TIMES){
4782 			ConstraintTeacherNotAvailableTimes* c=(ConstraintTeacherNotAvailableTimes*)tc;
4783 			if(!existingTeachersNames.contains(c->teacher))
4784 				toBeRemovedTime.append(tc);
4785 		}
4786 		else if(tc->type==CONSTRAINT_STUDENTS_SET_NOT_AVAILABLE_TIMES){
4787 			ConstraintStudentsSetNotAvailableTimes* c=(ConstraintStudentsSetNotAvailableTimes*)tc;
4788 			if(!permanentStudentsHash.contains(c->students))
4789 				toBeRemovedTime.append(tc);
4790 		}
4791 		else if(tc->type==CONSTRAINT_ACTIVITIES_SAME_STARTING_TIME){
4792 			ConstraintActivitiesSameStartingTime* c=(ConstraintActivitiesSameStartingTime*)tc;
4793 			c->removeUseless(*this);
4794 			if(c->n_activities<2)
4795 				toBeRemovedTime.append(tc);
4796 		}
4797 		else if(tc->type==CONSTRAINT_ACTIVITIES_NOT_OVERLAPPING){
4798 			ConstraintActivitiesNotOverlapping* c=(ConstraintActivitiesNotOverlapping*)tc;
4799 			c->removeUseless(*this);
4800 			if(c->n_activities<2)
4801 				toBeRemovedTime.append(tc);
4802 		}
4803 		else if(tc->type==CONSTRAINT_ACTIVITY_TAGS_NOT_OVERLAPPING){
4804 			ConstraintActivityTagsNotOverlapping* c=(ConstraintActivityTagsNotOverlapping*)tc;
4805 
4806 			QStringList atl;
4807 			for(const QString& at : qAsConst(c->activityTagsNames))
4808 				if(existingActivityTagsNames.contains(at))
4809 					atl.append(at);
4810 			c->activityTagsNames=atl;
4811 
4812 			if(c->activityTagsNames.count()<2)
4813 				toBeRemovedTime.append(tc);
4814 		}
4815 		else if(tc->type==CONSTRAINT_MIN_DAYS_BETWEEN_ACTIVITIES){
4816 			ConstraintMinDaysBetweenActivities* c=(ConstraintMinDaysBetweenActivities*)tc;
4817 			c->removeUseless(*this);
4818 			if(c->n_activities<2)
4819 				toBeRemovedTime.append(tc);
4820 		}
4821 		else if(tc->type==CONSTRAINT_MAX_DAYS_BETWEEN_ACTIVITIES){
4822 			ConstraintMaxDaysBetweenActivities* c=(ConstraintMaxDaysBetweenActivities*)tc;
4823 			c->removeUseless(*this);
4824 			if(c->n_activities<2)
4825 				toBeRemovedTime.append(tc);
4826 		}
4827 		else if(tc->type==CONSTRAINT_MIN_GAPS_BETWEEN_ACTIVITIES){
4828 			ConstraintMinGapsBetweenActivities* c=(ConstraintMinGapsBetweenActivities*)tc;
4829 			c->removeUseless(*this);
4830 			if(c->n_activities<2)
4831 				toBeRemovedTime.append(tc);
4832 		}
4833 		else if(tc->type==CONSTRAINT_MAX_GAPS_BETWEEN_ACTIVITIES){
4834 			ConstraintMaxGapsBetweenActivities* c=(ConstraintMaxGapsBetweenActivities*)tc;
4835 			c->removeUseless(*this);
4836 			if(c->n_activities<2)
4837 				toBeRemovedTime.append(tc);
4838 		}
4839 		else if(tc->type==CONSTRAINT_TEACHER_MAX_HOURS_DAILY){
4840 			ConstraintTeacherMaxHoursDaily* c=(ConstraintTeacherMaxHoursDaily*)tc;
4841 			if(!existingTeachersNames.contains(c->teacherName))
4842 				toBeRemovedTime.append(tc);
4843 		}
4844 		else if(tc->type==CONSTRAINT_TEACHER_MAX_HOURS_CONTINUOUSLY){
4845 			ConstraintTeacherMaxHoursContinuously* c=(ConstraintTeacherMaxHoursContinuously*)tc;
4846 			if(!existingTeachersNames.contains(c->teacherName))
4847 				toBeRemovedTime.append(tc);
4848 		}
4849 		else if(tc->type==CONSTRAINT_TEACHERS_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
4850 			ConstraintTeachersActivityTagMaxHoursContinuously* c=(ConstraintTeachersActivityTagMaxHoursContinuously*)tc;
4851 			if(!existingActivityTagsNames.contains(c->activityTagName))
4852 				toBeRemovedTime.append(tc);
4853 		}
4854 		else if(tc->type==CONSTRAINT_TEACHER_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
4855 			ConstraintTeacherActivityTagMaxHoursContinuously* c=(ConstraintTeacherActivityTagMaxHoursContinuously*)tc;
4856 			if(!existingActivityTagsNames.contains(c->activityTagName) || !existingTeachersNames.contains(c->teacherName))
4857 				toBeRemovedTime.append(tc);
4858 		}
4859 		else if(tc->type==CONSTRAINT_TEACHER_MAX_DAYS_PER_WEEK){
4860 			ConstraintTeacherMaxDaysPerWeek* c=(ConstraintTeacherMaxDaysPerWeek*)tc;
4861 			if(!existingTeachersNames.contains(c->teacherName))
4862 				toBeRemovedTime.append(tc);
4863 		}
4864 		else if(tc->type==CONSTRAINT_TEACHER_MAX_THREE_CONSECUTIVE_DAYS){
4865 			ConstraintTeacherMaxThreeConsecutiveDays* c=(ConstraintTeacherMaxThreeConsecutiveDays*)tc;
4866 			if(!existingTeachersNames.contains(c->teacherName))
4867 				toBeRemovedTime.append(tc);
4868 		}
4869 		else if(tc->type==CONSTRAINT_TEACHER_MIN_DAYS_PER_WEEK){
4870 			ConstraintTeacherMinDaysPerWeek* c=(ConstraintTeacherMinDaysPerWeek*)tc;
4871 			if(!existingTeachersNames.contains(c->teacherName))
4872 				toBeRemovedTime.append(tc);
4873 		}
4874 		else if(tc->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_WEEK){
4875 			ConstraintStudentsSetMaxGapsPerWeek* c=(ConstraintStudentsSetMaxGapsPerWeek*)tc;
4876 			if(!permanentStudentsHash.contains(c->students))
4877 				toBeRemovedTime.append(tc);
4878 		}
4879 		else if(tc->type==CONSTRAINT_TEACHER_MAX_GAPS_PER_WEEK){
4880 			ConstraintTeacherMaxGapsPerWeek* c=(ConstraintTeacherMaxGapsPerWeek*)tc;
4881 			if(!existingTeachersNames.contains(c->teacherName))
4882 				toBeRemovedTime.append(tc);
4883 		}
4884 		else if(tc->type==CONSTRAINT_TEACHER_MAX_GAPS_PER_DAY){
4885 			ConstraintTeacherMaxGapsPerDay* c=(ConstraintTeacherMaxGapsPerDay*)tc;
4886 			if(!existingTeachersNames.contains(c->teacherName))
4887 				toBeRemovedTime.append(tc);
4888 		}
4889 		else if(tc->type==CONSTRAINT_TEACHER_MAX_GAPS_PER_MORNING_AND_AFTERNOON){
4890 			ConstraintTeacherMaxGapsPerMorningAndAfternoon* c=(ConstraintTeacherMaxGapsPerMorningAndAfternoon*)tc;
4891 			if(!existingTeachersNames.contains(c->teacherName))
4892 				toBeRemovedTime.append(tc);
4893 		}
4894 		else if(tc->type==CONSTRAINT_STUDENTS_SET_EARLY_MAX_BEGINNINGS_AT_SECOND_HOUR){
4895 			ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour* c=(ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour*)tc;
4896 			if(!permanentStudentsHash.contains(c->students))
4897 				toBeRemovedTime.append(tc);
4898 		}
4899 		else if(tc->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_DAILY){
4900 			ConstraintStudentsSetMaxHoursDaily* c=(ConstraintStudentsSetMaxHoursDaily*)tc;
4901 			if(!permanentStudentsHash.contains(c->students))
4902 				toBeRemovedTime.append(tc);
4903 		}
4904 		else if(tc->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_CONTINUOUSLY){
4905 			ConstraintStudentsSetMaxHoursContinuously* c=(ConstraintStudentsSetMaxHoursContinuously*)tc;
4906 			if(!permanentStudentsHash.contains(c->students))
4907 				toBeRemovedTime.append(tc);
4908 		}
4909 		else if(tc->type==CONSTRAINT_STUDENTS_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
4910 			ConstraintStudentsActivityTagMaxHoursContinuously* c=(ConstraintStudentsActivityTagMaxHoursContinuously*)tc;
4911 			if(!existingActivityTagsNames.contains(c->activityTagName))
4912 				toBeRemovedTime.append(tc);
4913 		}
4914 		else if(tc->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
4915 			ConstraintStudentsSetActivityTagMaxHoursContinuously* c=(ConstraintStudentsSetActivityTagMaxHoursContinuously*)tc;
4916 			if(!existingActivityTagsNames.contains(c->activityTagName) || !permanentStudentsHash.contains(c->students))
4917 				toBeRemovedTime.append(tc);
4918 		}
4919 		else if(tc->type==CONSTRAINT_STUDENTS_SET_MIN_HOURS_DAILY){
4920 			ConstraintStudentsSetMinHoursDaily* c=(ConstraintStudentsSetMinHoursDaily*)tc;
4921 			if(!permanentStudentsHash.contains(c->students))
4922 				toBeRemovedTime.append(tc);
4923 		}
4924 		else if(tc->type==CONSTRAINT_STUDENTS_SET_MIN_GAPS_BETWEEN_ORDERED_PAIR_OF_ACTIVITY_TAGS){
4925 			ConstraintStudentsSetMinGapsBetweenOrderedPairOfActivityTags* c=(ConstraintStudentsSetMinGapsBetweenOrderedPairOfActivityTags*)tc;
4926 			if(!permanentStudentsHash.contains(c->students) ||
4927 			 !existingActivityTagsNames.contains(c->firstActivityTag) ||
4928 			 !existingActivityTagsNames.contains(c->secondActivityTag))
4929 				toBeRemovedTime.append(tc);
4930 		}
4931 		else if(tc->type==CONSTRAINT_STUDENTS_MIN_GAPS_BETWEEN_ORDERED_PAIR_OF_ACTIVITY_TAGS){
4932 			ConstraintStudentsMinGapsBetweenOrderedPairOfActivityTags* c=(ConstraintStudentsMinGapsBetweenOrderedPairOfActivityTags*)tc;
4933 			if(!existingActivityTagsNames.contains(c->firstActivityTag) ||
4934 			 !existingActivityTagsNames.contains(c->secondActivityTag))
4935 				toBeRemovedTime.append(tc);
4936 		}
4937 		else if(tc->type==CONSTRAINT_TEACHER_MIN_GAPS_BETWEEN_ORDERED_PAIR_OF_ACTIVITY_TAGS){
4938 			ConstraintTeacherMinGapsBetweenOrderedPairOfActivityTags* c=(ConstraintTeacherMinGapsBetweenOrderedPairOfActivityTags*)tc;
4939 			if(!existingTeachersNames.contains(c->teacher) ||
4940 			 !existingActivityTagsNames.contains(c->firstActivityTag) ||
4941 			 !existingActivityTagsNames.contains(c->secondActivityTag))
4942 				toBeRemovedTime.append(tc);
4943 		}
4944 		else if(tc->type==CONSTRAINT_TEACHERS_MIN_GAPS_BETWEEN_ORDERED_PAIR_OF_ACTIVITY_TAGS){
4945 			ConstraintTeachersMinGapsBetweenOrderedPairOfActivityTags* c=(ConstraintTeachersMinGapsBetweenOrderedPairOfActivityTags*)tc;
4946 			if(!existingActivityTagsNames.contains(c->firstActivityTag) ||
4947 			 !existingActivityTagsNames.contains(c->secondActivityTag))
4948 				toBeRemovedTime.append(tc);
4949 		}
4950 		else if(tc->type==CONSTRAINT_ACTIVITY_PREFERRED_STARTING_TIME){
4951 			ConstraintActivityPreferredStartingTime* c=(ConstraintActivityPreferredStartingTime*)tc;
4952 			if(!existingActivitiesIds.contains(c->activityId)){
4953 				toBeRemovedTime.append(tc);
4954 				recomputeTime=true;
4955 			}
4956 		}
4957 		else if(tc->type==CONSTRAINT_ACTIVITY_PREFERRED_TIME_SLOTS){
4958 			ConstraintActivityPreferredTimeSlots* c=(ConstraintActivityPreferredTimeSlots*)tc;
4959 			if(!existingActivitiesIds.contains(c->p_activityId))
4960 				toBeRemovedTime.append(tc);
4961 		}
4962 		else if(tc->type==CONSTRAINT_ACTIVITY_PREFERRED_STARTING_TIMES){
4963 			ConstraintActivityPreferredStartingTimes* c=(ConstraintActivityPreferredStartingTimes*)tc;
4964 			if(!existingActivitiesIds.contains(c->activityId))
4965 				toBeRemovedTime.append(tc);
4966 		}
4967 		else if(tc->type==CONSTRAINT_ACTIVITIES_PREFERRED_TIME_SLOTS){
4968 			ConstraintActivitiesPreferredTimeSlots* c=(ConstraintActivitiesPreferredTimeSlots*)tc;
4969 			if( (c->p_teacherName!="" && !existingTeachersNames.contains(c->p_teacherName)) ||
4970 			 (c->p_studentsName!="" && !permanentStudentsHash.contains(c->p_studentsName)) ||
4971 			 (c->p_subjectName!="" && !existingSubjectsNames.contains(c->p_subjectName)) ||
4972 			 (c->p_activityTagName!="" && !existingActivityTagsNames.contains(c->p_activityTagName)) )
4973 				toBeRemovedTime.append(tc);
4974 		}
4975 		else if(tc->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_TIME_SLOTS){
4976 			ConstraintSubactivitiesPreferredTimeSlots* c=(ConstraintSubactivitiesPreferredTimeSlots*)tc;
4977 			if( (c->p_teacherName!="" && !existingTeachersNames.contains(c->p_teacherName)) ||
4978 			 (c->p_studentsName!="" && !permanentStudentsHash.contains(c->p_studentsName)) ||
4979 			 (c->p_subjectName!="" && !existingSubjectsNames.contains(c->p_subjectName)) ||
4980 			 (c->p_activityTagName!="" && !existingActivityTagsNames.contains(c->p_activityTagName)) )
4981 				toBeRemovedTime.append(tc);
4982 		}
4983 		else if(tc->type==CONSTRAINT_ACTIVITIES_PREFERRED_STARTING_TIMES){
4984 			ConstraintActivitiesPreferredStartingTimes* c=(ConstraintActivitiesPreferredStartingTimes*)tc;
4985 			if( (c->teacherName!="" && !existingTeachersNames.contains(c->teacherName)) ||
4986 			 (c->studentsName!="" && !permanentStudentsHash.contains(c->studentsName)) ||
4987 			 (c->subjectName!="" && !existingSubjectsNames.contains(c->subjectName)) ||
4988 			 (c->activityTagName!="" && !existingActivityTagsNames.contains(c->activityTagName)) )
4989 				toBeRemovedTime.append(tc);
4990 		}
4991 		else if(tc->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_STARTING_TIMES){
4992 			ConstraintSubactivitiesPreferredStartingTimes* c=(ConstraintSubactivitiesPreferredStartingTimes*)tc;
4993 			if( (c->teacherName!="" && !existingTeachersNames.contains(c->teacherName)) ||
4994 			 (c->studentsName!="" && !permanentStudentsHash.contains(c->studentsName)) ||
4995 			 (c->subjectName!="" && !existingSubjectsNames.contains(c->subjectName)) ||
4996 			 (c->activityTagName!="" && !existingActivityTagsNames.contains(c->activityTagName)) )
4997 				toBeRemovedTime.append(tc);
4998 		}
4999 		else if(tc->type==CONSTRAINT_ACTIVITIES_SAME_STARTING_HOUR){
5000 			ConstraintActivitiesSameStartingHour* c=(ConstraintActivitiesSameStartingHour*)tc;
5001 			c->removeUseless(*this);
5002 			if(c->n_activities<2)
5003 				toBeRemovedTime.append(tc);
5004 		}
5005 		else if(tc->type==CONSTRAINT_ACTIVITIES_SAME_STARTING_DAY){
5006 			ConstraintActivitiesSameStartingDay* c=(ConstraintActivitiesSameStartingDay*)tc;
5007 			c->removeUseless(*this);
5008 			if(c->n_activities<2)
5009 				toBeRemovedTime.append(tc);
5010 		}
5011 		else if(tc->type==CONSTRAINT_TWO_ACTIVITIES_CONSECUTIVE){
5012 			ConstraintTwoActivitiesConsecutive* c=(ConstraintTwoActivitiesConsecutive*)tc;
5013 			if( !existingActivitiesIds.contains(c->firstActivityId) ||
5014 			 !existingActivitiesIds.contains(c->secondActivityId) )
5015 				toBeRemovedTime.append(tc);
5016 		}
5017 		else if(tc->type==CONSTRAINT_TWO_ACTIVITIES_GROUPED){
5018 			ConstraintTwoActivitiesGrouped* c=(ConstraintTwoActivitiesGrouped*)tc;
5019 			if( !existingActivitiesIds.contains(c->firstActivityId) ||
5020 			 !existingActivitiesIds.contains(c->secondActivityId) )
5021 				toBeRemovedTime.append(tc);
5022 		}
5023 		else if(tc->type==CONSTRAINT_THREE_ACTIVITIES_GROUPED){
5024 			ConstraintThreeActivitiesGrouped* c=(ConstraintThreeActivitiesGrouped*)tc;
5025 			if( !existingActivitiesIds.contains(c->firstActivityId) ||
5026 			 !existingActivitiesIds.contains(c->secondActivityId) ||
5027 			 !existingActivitiesIds.contains(c->thirdActivityId) )
5028 				toBeRemovedTime.append(tc);
5029 		}
5030 		else if(tc->type==CONSTRAINT_TWO_ACTIVITIES_ORDERED){
5031 			ConstraintTwoActivitiesOrdered* c=(ConstraintTwoActivitiesOrdered*)tc;
5032 			if( !existingActivitiesIds.contains(c->firstActivityId) ||
5033 			 !existingActivitiesIds.contains(c->secondActivityId) )
5034 				toBeRemovedTime.append(tc);
5035 		}
5036 		else if(tc->type==CONSTRAINT_TWO_SETS_OF_ACTIVITIES_ORDERED){
5037 			ConstraintTwoSetsOfActivitiesOrdered* c=(ConstraintTwoSetsOfActivitiesOrdered*)tc;
5038 			c->removeUseless(*this);
5039 			if(c->firstActivitiesIdsList.isEmpty() || c->secondActivitiesIdsList.isEmpty())
5040 				toBeRemovedTime.append(tc);
5041 		}
5042 		else if(tc->type==CONSTRAINT_TWO_ACTIVITIES_ORDERED_IF_SAME_DAY){
5043 			ConstraintTwoActivitiesOrderedIfSameDay* c=(ConstraintTwoActivitiesOrderedIfSameDay*)tc;
5044 			if( !existingActivitiesIds.contains(c->firstActivityId) ||
5045 			 !existingActivitiesIds.contains(c->secondActivityId) )
5046 				toBeRemovedTime.append(tc);
5047 		}
5048 		else if(tc->type==CONSTRAINT_ACTIVITY_ENDS_STUDENTS_DAY){
5049 			ConstraintActivityEndsStudentsDay* c=(ConstraintActivityEndsStudentsDay*)tc;
5050 			if(!existingActivitiesIds.contains(c->activityId))
5051 				toBeRemovedTime.append(tc);
5052 		}
5053 		else if(tc->type==CONSTRAINT_ACTIVITY_ENDS_TEACHERS_DAY){
5054 			ConstraintActivityEndsTeachersDay* c=(ConstraintActivityEndsTeachersDay*)tc;
5055 			if(!existingActivitiesIds.contains(c->activityId))
5056 				toBeRemovedTime.append(tc);
5057 		}
5058 		else if(tc->type==CONSTRAINT_TEACHER_MIN_HOURS_DAILY){
5059 			ConstraintTeacherMinHoursDaily* c=(ConstraintTeacherMinHoursDaily*)tc;
5060 			if(!existingTeachersNames.contains(c->teacherName))
5061 				toBeRemovedTime.append(tc);
5062 		}
5063 		else if(tc->type==CONSTRAINT_TEACHER_INTERVAL_MAX_DAYS_PER_WEEK){
5064 			ConstraintTeacherIntervalMaxDaysPerWeek* c=(ConstraintTeacherIntervalMaxDaysPerWeek*)tc;
5065 			if(!existingTeachersNames.contains(c->teacherName))
5066 				toBeRemovedTime.append(tc);
5067 		}
5068 		else if(tc->type==CONSTRAINT_STUDENTS_SET_INTERVAL_MAX_DAYS_PER_WEEK){
5069 			ConstraintStudentsSetIntervalMaxDaysPerWeek* c=(ConstraintStudentsSetIntervalMaxDaysPerWeek*)tc;
5070 			if(!permanentStudentsHash.contains(c->students))
5071 				toBeRemovedTime.append(tc);
5072 		}
5073 		else if(tc->type==CONSTRAINT_ACTIVITIES_END_STUDENTS_DAY){
5074 			ConstraintActivitiesEndStudentsDay* c=(ConstraintActivitiesEndStudentsDay*)tc;
5075 			if( (c->teacherName!="" && !existingTeachersNames.contains(c->teacherName)) ||
5076 			 (c->studentsName!="" && !permanentStudentsHash.contains(c->studentsName)) ||
5077 			 (c->subjectName!="" && !existingSubjectsNames.contains(c->subjectName)) ||
5078 			 (c->activityTagName!="" && !existingActivityTagsNames.contains(c->activityTagName)) )
5079 				toBeRemovedTime.append(tc);
5080 		}
5081 		else if(tc->type==CONSTRAINT_ACTIVITIES_END_TEACHERS_DAY){
5082 			ConstraintActivitiesEndTeachersDay* c=(ConstraintActivitiesEndTeachersDay*)tc;
5083 			if( (c->teacherName!="" && !existingTeachersNames.contains(c->teacherName)) ||
5084 			 (c->studentsName!="" && !permanentStudentsHash.contains(c->studentsName)) ||
5085 			 (c->subjectName!="" && !existingSubjectsNames.contains(c->subjectName)) ||
5086 			 (c->activityTagName!="" && !existingActivityTagsNames.contains(c->activityTagName)) )
5087 				toBeRemovedTime.append(tc);
5088 		}
5089 		else if(tc->type==CONSTRAINT_TEACHERS_ACTIVITY_TAG_MAX_HOURS_DAILY){
5090 			ConstraintTeachersActivityTagMaxHoursDaily* c=(ConstraintTeachersActivityTagMaxHoursDaily*)tc;
5091 			if(!existingActivityTagsNames.contains(c->activityTagName))
5092 				toBeRemovedTime.append(tc);
5093 		}
5094 		else if(tc->type==CONSTRAINT_TEACHER_ACTIVITY_TAG_MAX_HOURS_DAILY){
5095 			ConstraintTeacherActivityTagMaxHoursDaily* c=(ConstraintTeacherActivityTagMaxHoursDaily*)tc;
5096 			if(!existingActivityTagsNames.contains(c->activityTagName) || !existingTeachersNames.contains(c->teacherName))
5097 				toBeRemovedTime.append(tc);
5098 		}
5099 		else if(tc->type==CONSTRAINT_STUDENTS_ACTIVITY_TAG_MAX_HOURS_DAILY){
5100 			ConstraintStudentsActivityTagMaxHoursDaily* c=(ConstraintStudentsActivityTagMaxHoursDaily*)tc;
5101 			if(!existingActivityTagsNames.contains(c->activityTagName))
5102 				toBeRemovedTime.append(tc);
5103 		}
5104 		else if(tc->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_DAILY){
5105 			ConstraintStudentsSetActivityTagMaxHoursDaily* c=(ConstraintStudentsSetActivityTagMaxHoursDaily*)tc;
5106 			if(!existingActivityTagsNames.contains(c->activityTagName) || !permanentStudentsHash.contains(c->students))
5107 				toBeRemovedTime.append(tc);
5108 		}
5109 		else if(tc->type==CONSTRAINT_TEACHERS_ACTIVITY_TAG_MIN_HOURS_DAILY){
5110 			ConstraintTeachersActivityTagMinHoursDaily* c=(ConstraintTeachersActivityTagMinHoursDaily*)tc;
5111 			if(!existingActivityTagsNames.contains(c->activityTagName))
5112 				toBeRemovedTime.append(tc);
5113 		}
5114 		else if(tc->type==CONSTRAINT_TEACHER_ACTIVITY_TAG_MIN_HOURS_DAILY){
5115 			ConstraintTeacherActivityTagMinHoursDaily* c=(ConstraintTeacherActivityTagMinHoursDaily*)tc;
5116 			if(!existingActivityTagsNames.contains(c->activityTagName) || !existingTeachersNames.contains(c->teacherName))
5117 				toBeRemovedTime.append(tc);
5118 		}
5119 		else if(tc->type==CONSTRAINT_STUDENTS_ACTIVITY_TAG_MIN_HOURS_DAILY){
5120 			ConstraintStudentsActivityTagMinHoursDaily* c=(ConstraintStudentsActivityTagMinHoursDaily*)tc;
5121 			if(!existingActivityTagsNames.contains(c->activityTagName))
5122 				toBeRemovedTime.append(tc);
5123 		}
5124 		else if(tc->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MIN_HOURS_DAILY){
5125 			ConstraintStudentsSetActivityTagMinHoursDaily* c=(ConstraintStudentsSetActivityTagMinHoursDaily*)tc;
5126 			if(!existingActivityTagsNames.contains(c->activityTagName) || !permanentStudentsHash.contains(c->students))
5127 				toBeRemovedTime.append(tc);
5128 		}
5129 		else if(tc->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_DAY){
5130 			ConstraintStudentsSetMaxGapsPerDay* c=(ConstraintStudentsSetMaxGapsPerDay*)tc;
5131 			if(!permanentStudentsHash.contains(c->students))
5132 				toBeRemovedTime.append(tc);
5133 		}
5134 		else if(tc->type==CONSTRAINT_ACTIVITIES_OCCUPY_MAX_TIME_SLOTS_FROM_SELECTION){
5135 			ConstraintActivitiesOccupyMaxTimeSlotsFromSelection* c=(ConstraintActivitiesOccupyMaxTimeSlotsFromSelection*)tc;
5136 			c->removeUseless(*this);
5137 			if(c->activitiesIds.count()<1)
5138 				toBeRemovedTime.append(tc);
5139 		}
5140 		else if(tc->type==CONSTRAINT_ACTIVITIES_OCCUPY_MIN_TIME_SLOTS_FROM_SELECTION){
5141 			ConstraintActivitiesOccupyMinTimeSlotsFromSelection* c=(ConstraintActivitiesOccupyMinTimeSlotsFromSelection*)tc;
5142 			c->removeUseless(*this);
5143 			if(c->activitiesIds.count()<1)
5144 				toBeRemovedTime.append(tc);
5145 		}
5146 		else if(tc->type==CONSTRAINT_ACTIVITIES_MAX_SIMULTANEOUS_IN_SELECTED_TIME_SLOTS){
5147 			ConstraintActivitiesMaxSimultaneousInSelectedTimeSlots* c=(ConstraintActivitiesMaxSimultaneousInSelectedTimeSlots*)tc;
5148 			c->removeUseless(*this);
5149 			if(c->activitiesIds.count()<1)
5150 				toBeRemovedTime.append(tc);
5151 		}
5152 		else if(tc->type==CONSTRAINT_ACTIVITIES_MIN_SIMULTANEOUS_IN_SELECTED_TIME_SLOTS){
5153 			ConstraintActivitiesMinSimultaneousInSelectedTimeSlots* c=(ConstraintActivitiesMinSimultaneousInSelectedTimeSlots*)tc;
5154 			c->removeUseless(*this);
5155 			if(c->activitiesIds.count()<1)
5156 				toBeRemovedTime.append(tc);
5157 		}
5158 		//2020-05-02
5159 		else if(tc->type==CONSTRAINT_MAX_TOTAL_ACTIVITIES_FROM_SET_IN_SELECTED_TIME_SLOTS){
5160 			ConstraintMaxTotalActivitiesFromSetInSelectedTimeSlots* c=(ConstraintMaxTotalActivitiesFromSetInSelectedTimeSlots*)tc;
5161 			c->removeUseless(*this);
5162 			if(c->activitiesIds.count()<1)
5163 				toBeRemovedTime.append(tc);
5164 		}
5165 		else if(tc->type==CONSTRAINT_ACTIVITIES_MAX_IN_A_TERM){
5166 			ConstraintActivitiesMaxInATerm* c=(ConstraintActivitiesMaxInATerm*)tc;
5167 			c->removeUseless(*this);
5168 			if(c->activitiesIds.count()<1)
5169 				toBeRemovedTime.append(tc);
5170 		}
5171 		else if(tc->type==CONSTRAINT_ACTIVITIES_OCCUPY_MAX_TERMS){
5172 			ConstraintActivitiesOccupyMaxTerms* c=(ConstraintActivitiesOccupyMaxTerms*)tc;
5173 			c->removeUseless(*this);
5174 			if(c->activitiesIds.count()<1)
5175 				toBeRemovedTime.append(tc);
5176 		}
5177 		else if(tc->type==CONSTRAINT_STUDENTS_SET_MAX_DAYS_PER_WEEK){
5178 			ConstraintStudentsSetMaxDaysPerWeek* c=(ConstraintStudentsSetMaxDaysPerWeek*)tc;
5179 			if(!permanentStudentsHash.contains(c->students))
5180 				toBeRemovedTime.append(tc);
5181 		}
5182 		//2017-02-07
5183 		else if(tc->type==CONSTRAINT_TEACHER_MAX_SPAN_PER_DAY){
5184 			ConstraintTeacherMaxSpanPerDay* c=(ConstraintTeacherMaxSpanPerDay*)tc;
5185 			if(!existingTeachersNames.contains(c->teacherName))
5186 				toBeRemovedTime.append(tc);
5187 		}
5188 		else if(tc->type==CONSTRAINT_TEACHER_MIN_RESTING_HOURS){
5189 			ConstraintTeacherMinRestingHours* c=(ConstraintTeacherMinRestingHours*)tc;
5190 			if(!existingTeachersNames.contains(c->teacherName))
5191 				toBeRemovedTime.append(tc);
5192 		}
5193 		else if(tc->type==CONSTRAINT_STUDENTS_SET_MAX_SPAN_PER_DAY){
5194 			ConstraintStudentsSetMaxSpanPerDay* c=(ConstraintStudentsSetMaxSpanPerDay*)tc;
5195 			if(!permanentStudentsHash.contains(c->students))
5196 				toBeRemovedTime.append(tc);
5197 		}
5198 		else if(tc->type==CONSTRAINT_STUDENTS_SET_MIN_RESTING_HOURS){
5199 			ConstraintStudentsSetMinRestingHours* c=(ConstraintStudentsSetMinRestingHours*)tc;
5200 			if(!permanentStudentsHash.contains(c->students))
5201 				toBeRemovedTime.append(tc);
5202 		}
5203 
5204 		//mornings-afternoons
5205 		else if(tc->type==CONSTRAINT_TEACHER_MAX_HOURS_DAILY_REAL_DAYS){
5206 			ConstraintTeacherMaxHoursDailyRealDays* c=(ConstraintTeacherMaxHoursDailyRealDays*)tc;
5207 			if(!existingTeachersNames.contains(c->teacherName))
5208 				toBeRemovedTime.append(tc);
5209 		}
5210 		else if(tc->type==CONSTRAINT_TEACHER_MAX_REAL_DAYS_PER_WEEK){
5211 			ConstraintTeacherMaxRealDaysPerWeek* c=(ConstraintTeacherMaxRealDaysPerWeek*)tc;
5212 			if(!existingTeachersNames.contains(c->teacherName))
5213 				toBeRemovedTime.append(tc);
5214 		}
5215 		else if(tc->type==CONSTRAINT_TEACHER_MAX_AFTERNOONS_PER_WEEK){
5216 			ConstraintTeacherMaxAfternoonsPerWeek* c=(ConstraintTeacherMaxAfternoonsPerWeek*)tc;
5217 			if(!existingTeachersNames.contains(c->teacherName))
5218 				toBeRemovedTime.append(tc);
5219 		}
5220 		else if(tc->type==CONSTRAINT_TEACHER_MAX_TWO_ACTIVITY_TAGS_PER_DAY_FROM_N1N2N3){
5221 			ConstraintTeacherMaxTwoActivityTagsPerDayFromN1N2N3* c=(ConstraintTeacherMaxTwoActivityTagsPerDayFromN1N2N3*)tc;
5222 			if(!existingTeachersNames.contains(c->teacherName))
5223 				toBeRemovedTime.append(tc);
5224 		}
5225 		else if(tc->type==CONSTRAINT_TEACHER_MAX_MORNINGS_PER_WEEK){
5226 			ConstraintTeacherMaxMorningsPerWeek* c=(ConstraintTeacherMaxMorningsPerWeek*)tc;
5227 			if(!existingTeachersNames.contains(c->teacherName))
5228 				toBeRemovedTime.append(tc);
5229 		}
5230 		else if(tc->type==CONSTRAINT_TEACHER_MAX_TWO_CONSECUTIVE_MORNINGS){
5231 			ConstraintTeacherMaxTwoConsecutiveMornings* c=(ConstraintTeacherMaxTwoConsecutiveMornings*)tc;
5232 			if(!existingTeachersNames.contains(c->teacherName))
5233 				toBeRemovedTime.append(tc);
5234 		}
5235 		else if(tc->type==CONSTRAINT_TEACHER_MAX_TWO_CONSECUTIVE_AFTERNOONS){
5236 			ConstraintTeacherMaxTwoConsecutiveAfternoons* c=(ConstraintTeacherMaxTwoConsecutiveAfternoons*)tc;
5237 			if(!existingTeachersNames.contains(c->teacherName))
5238 				toBeRemovedTime.append(tc);
5239 		}
5240 		else if(tc->type==CONSTRAINT_TEACHER_MIN_REAL_DAYS_PER_WEEK){
5241 			ConstraintTeacherMinRealDaysPerWeek* c=(ConstraintTeacherMinRealDaysPerWeek*)tc;
5242 			if(!existingTeachersNames.contains(c->teacherName))
5243 				toBeRemovedTime.append(tc);
5244 		}
5245 		else if(tc->type==CONSTRAINT_TEACHER_MIN_MORNINGS_PER_WEEK){
5246 			ConstraintTeacherMinMorningsPerWeek* c=(ConstraintTeacherMinMorningsPerWeek*)tc;
5247 			if(!existingTeachersNames.contains(c->teacherName))
5248 				toBeRemovedTime.append(tc);
5249 		}
5250 		else if(tc->type==CONSTRAINT_TEACHER_MIN_AFTERNOONS_PER_WEEK){
5251 			ConstraintTeacherMinAfternoonsPerWeek* c=(ConstraintTeacherMinAfternoonsPerWeek*)tc;
5252 			if(!existingTeachersNames.contains(c->teacherName))
5253 				toBeRemovedTime.append(tc);
5254 		}
5255 		//2020-06-28
5256 		else if(tc->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_PER_ALL_AFTERNOONS){
5257 			ConstraintStudentsSetMaxHoursPerAllAfternoons* c=(ConstraintStudentsSetMaxHoursPerAllAfternoons*)tc;
5258 			if(!permanentStudentsHash.contains(c->students))
5259 				toBeRemovedTime.append(tc);
5260 		}
5261 		//
5262 		else if(tc->type==CONSTRAINT_TEACHER_AFTERNOONS_EARLY_MAX_BEGINNINGS_AT_SECOND_HOUR){
5263 			ConstraintTeacherAfternoonsEarlyMaxBeginningsAtSecondHour* c=(ConstraintTeacherAfternoonsEarlyMaxBeginningsAtSecondHour*)tc;
5264 			if(!existingTeachersNames.contains(c->teacherName))
5265 				toBeRemovedTime.append(tc);
5266 		}
5267 		else if(tc->type==CONSTRAINT_TEACHER_MORNINGS_EARLY_MAX_BEGINNINGS_AT_SECOND_HOUR){
5268 			ConstraintTeacherMorningsEarlyMaxBeginningsAtSecondHour* c=(ConstraintTeacherMorningsEarlyMaxBeginningsAtSecondHour*)tc;
5269 			if(!existingTeachersNames.contains(c->teacherName))
5270 				toBeRemovedTime.append(tc);
5271 		}
5272 		else if(tc->type==CONSTRAINT_TEACHER_MAX_GAPS_PER_REAL_DAY){
5273 			ConstraintTeacherMaxGapsPerRealDay* c=(ConstraintTeacherMaxGapsPerRealDay*)tc;
5274 			if(!existingTeachersNames.contains(c->teacherName))
5275 				toBeRemovedTime.append(tc);
5276 		}
5277 		else if(tc->type==CONSTRAINT_TEACHER_MAX_GAPS_PER_WEEK_FOR_REAL_DAYS){
5278 			ConstraintTeacherMaxGapsPerWeekForRealDays* c=(ConstraintTeacherMaxGapsPerWeekForRealDays*)tc;
5279 			if(!existingTeachersNames.contains(c->teacherName))
5280 				toBeRemovedTime.append(tc);
5281 		}
5282 		else if(tc->type==CONSTRAINT_TEACHER_MAX_ZERO_GAPS_PER_AFTERNOON){
5283 			ConstraintTeacherMaxZeroGapsPerAfternoon* c=(ConstraintTeacherMaxZeroGapsPerAfternoon*)tc;
5284 			if(!existingTeachersNames.contains(c->teacherName))
5285 				toBeRemovedTime.append(tc);
5286 		}
5287 		else if(tc->type==CONSTRAINT_STUDENTS_SET_AFTERNOONS_EARLY_MAX_BEGINNINGS_AT_SECOND_HOUR){
5288 			ConstraintStudentsSetAfternoonsEarlyMaxBeginningsAtSecondHour* c=(ConstraintStudentsSetAfternoonsEarlyMaxBeginningsAtSecondHour*)tc;
5289 			if(!permanentStudentsHash.contains(c->students))
5290 				toBeRemovedTime.append(tc);
5291 		}
5292 		else if(tc->type==CONSTRAINT_STUDENTS_SET_MORNINGS_EARLY_MAX_BEGINNINGS_AT_SECOND_HOUR){
5293 			ConstraintStudentsSetMorningsEarlyMaxBeginningsAtSecondHour* c=(ConstraintStudentsSetMorningsEarlyMaxBeginningsAtSecondHour*)tc;
5294 			if(!permanentStudentsHash.contains(c->students))
5295 				toBeRemovedTime.append(tc);
5296 		}
5297 		else if(tc->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_DAILY_REAL_DAYS){
5298 			ConstraintStudentsSetMaxHoursDailyRealDays* c=(ConstraintStudentsSetMaxHoursDailyRealDays*)tc;
5299 			if(!permanentStudentsHash.contains(c->students))
5300 				toBeRemovedTime.append(tc);
5301 		}
5302 		else if(tc->type==CONSTRAINT_STUDENTS_SET_MIN_HOURS_PER_MORNING){
5303 			ConstraintStudentsSetMinHoursPerMorning* c=(ConstraintStudentsSetMinHoursPerMorning*)tc;
5304 			if(!permanentStudentsHash.contains(c->students))
5305 				toBeRemovedTime.append(tc);
5306 		}
5307 		//2020-06-28
5308 		else if(tc->type==CONSTRAINT_TEACHER_MAX_HOURS_PER_ALL_AFTERNOONS){
5309 			ConstraintTeacherMaxHoursPerAllAfternoons* c=(ConstraintTeacherMaxHoursPerAllAfternoons*)tc;
5310 			if(!existingTeachersNames.contains(c->teacherName))
5311 				toBeRemovedTime.append(tc);
5312 		}
5313 		//
5314 		else if(tc->type==CONSTRAINT_TEACHER_MIN_HOURS_PER_MORNING){
5315 			ConstraintTeacherMinHoursPerMorning* c=(ConstraintTeacherMinHoursPerMorning*)tc;
5316 			if(!existingTeachersNames.contains(c->teacherName))
5317 				toBeRemovedTime.append(tc);
5318 		}
5319 		else if(tc->type==CONSTRAINT_TEACHER_MIN_HOURS_DAILY_REAL_DAYS){
5320 			ConstraintTeacherMinHoursDailyRealDays* c=(ConstraintTeacherMinHoursDailyRealDays*)tc;
5321 			if(!existingTeachersNames.contains(c->teacherName))
5322 				toBeRemovedTime.append(tc);
5323 		}
5324 
5325 		else if(tc->type==CONSTRAINT_TEACHER_MORNING_INTERVAL_MAX_DAYS_PER_WEEK){
5326 			ConstraintTeacherMorningIntervalMaxDaysPerWeek* c=(ConstraintTeacherMorningIntervalMaxDaysPerWeek*)tc;
5327 			if(!existingTeachersNames.contains(c->teacherName))
5328 				toBeRemovedTime.append(tc);
5329 		}
5330 		else if(tc->type==CONSTRAINT_TEACHER_AFTERNOON_INTERVAL_MAX_DAYS_PER_WEEK){
5331 			ConstraintTeacherAfternoonIntervalMaxDaysPerWeek* c=(ConstraintTeacherAfternoonIntervalMaxDaysPerWeek*)tc;
5332 			if(!existingTeachersNames.contains(c->teacherName))
5333 				toBeRemovedTime.append(tc);
5334 		}
5335 
5336 		else if(tc->type==CONSTRAINT_STUDENTS_SET_MORNING_INTERVAL_MAX_DAYS_PER_WEEK){
5337 			ConstraintStudentsSetMorningIntervalMaxDaysPerWeek* c=(ConstraintStudentsSetMorningIntervalMaxDaysPerWeek*)tc;
5338 			if(!permanentStudentsHash.contains(c->students))
5339 				toBeRemovedTime.append(tc);
5340 		}
5341 		else if(tc->type==CONSTRAINT_STUDENTS_SET_AFTERNOON_INTERVAL_MAX_DAYS_PER_WEEK){
5342 			ConstraintStudentsSetAfternoonIntervalMaxDaysPerWeek* c=(ConstraintStudentsSetAfternoonIntervalMaxDaysPerWeek*)tc;
5343 			if(!permanentStudentsHash.contains(c->students))
5344 				toBeRemovedTime.append(tc);
5345 		}
5346 
5347 		else if(tc->type==CONSTRAINT_TEACHERS_ACTIVITY_TAG_MAX_HOURS_DAILY_REAL_DAYS){
5348 			ConstraintTeachersActivityTagMaxHoursDailyRealDays* c=(ConstraintTeachersActivityTagMaxHoursDailyRealDays*)tc;
5349 			if(!existingActivityTagsNames.contains(c->activityTagName))
5350 				toBeRemovedTime.append(tc);
5351 		}
5352 		else if(tc->type==CONSTRAINT_TEACHER_ACTIVITY_TAG_MAX_HOURS_DAILY_REAL_DAYS){
5353 			ConstraintTeacherActivityTagMaxHoursDailyRealDays* c=(ConstraintTeacherActivityTagMaxHoursDailyRealDays*)tc;
5354 			if(!existingActivityTagsNames.contains(c->activityTagName) || !existingTeachersNames.contains(c->teacherName))
5355 				toBeRemovedTime.append(tc);
5356 		}
5357 		else if(tc->type==CONSTRAINT_STUDENTS_ACTIVITY_TAG_MAX_HOURS_DAILY_REAL_DAYS){
5358 			ConstraintStudentsActivityTagMaxHoursDailyRealDays* c=(ConstraintStudentsActivityTagMaxHoursDailyRealDays*)tc;
5359 			if(!existingActivityTagsNames.contains(c->activityTagName))
5360 				toBeRemovedTime.append(tc);
5361 		}
5362 		else if(tc->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_DAILY_REAL_DAYS){
5363 			ConstraintStudentsSetActivityTagMaxHoursDailyRealDays* c=(ConstraintStudentsSetActivityTagMaxHoursDailyRealDays*)tc;
5364 			if(!existingActivityTagsNames.contains(c->activityTagName) || !permanentStudentsHash.contains(c->students))
5365 				toBeRemovedTime.append(tc);
5366 		}
5367 		else if(tc->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_REAL_DAY){
5368 			ConstraintStudentsSetMaxGapsPerRealDay* c=(ConstraintStudentsSetMaxGapsPerRealDay*)tc;
5369 			if(!permanentStudentsHash.contains(c->students))
5370 				toBeRemovedTime.append(tc);
5371 		}
5372 		else if(tc->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_WEEK_FOR_REAL_DAYS){
5373 			ConstraintStudentsSetMaxGapsPerWeekForRealDays* c=(ConstraintStudentsSetMaxGapsPerWeekForRealDays*)tc;
5374 			if(!permanentStudentsHash.contains(c->students))
5375 				toBeRemovedTime.append(tc);
5376 		}
5377 		else if(tc->type==CONSTRAINT_STUDENTS_SET_MAX_REAL_DAYS_PER_WEEK){
5378 			ConstraintStudentsSetMaxRealDaysPerWeek* c=(ConstraintStudentsSetMaxRealDaysPerWeek*)tc;
5379 			if(!permanentStudentsHash.contains(c->students))
5380 				toBeRemovedTime.append(tc);
5381 		}
5382 		//2020-06-25
5383 		else if(tc->type==CONSTRAINT_STUDENTS_SET_MAX_AFTERNOONS_PER_WEEK){
5384 			ConstraintStudentsSetMaxAfternoonsPerWeek* c=(ConstraintStudentsSetMaxAfternoonsPerWeek*)tc;
5385 			if(!permanentStudentsHash.contains(c->students))
5386 				toBeRemovedTime.append(tc);
5387 		}
5388 		else if(tc->type==CONSTRAINT_STUDENTS_SET_MAX_MORNINGS_PER_WEEK){
5389 			ConstraintStudentsSetMaxMorningsPerWeek* c=(ConstraintStudentsSetMaxMorningsPerWeek*)tc;
5390 			if(!permanentStudentsHash.contains(c->students))
5391 				toBeRemovedTime.append(tc);
5392 		}
5393 		//2020-06-26
5394 		else if(tc->type==CONSTRAINT_STUDENTS_SET_MIN_AFTERNOONS_PER_WEEK){
5395 			ConstraintStudentsSetMinAfternoonsPerWeek* c=(ConstraintStudentsSetMinAfternoonsPerWeek*)tc;
5396 			if(!permanentStudentsHash.contains(c->students))
5397 				toBeRemovedTime.append(tc);
5398 		}
5399 		else if(tc->type==CONSTRAINT_STUDENTS_SET_MIN_MORNINGS_PER_WEEK){
5400 			ConstraintStudentsSetMinMorningsPerWeek* c=(ConstraintStudentsSetMinMorningsPerWeek*)tc;
5401 			if(!permanentStudentsHash.contains(c->students))
5402 				toBeRemovedTime.append(tc);
5403 		}
5404 		//
5405 		else if(tc->type==CONSTRAINT_TEACHER_MAX_SPAN_PER_REAL_DAY){
5406 			ConstraintTeacherMaxSpanPerRealDay* c=(ConstraintTeacherMaxSpanPerRealDay*)tc;
5407 			if(!existingTeachersNames.contains(c->teacherName))
5408 				toBeRemovedTime.append(tc);
5409 		}
5410 		else if(tc->type==CONSTRAINT_STUDENTS_SET_MAX_SPAN_PER_REAL_DAY){
5411 			ConstraintStudentsSetMaxSpanPerRealDay* c=(ConstraintStudentsSetMaxSpanPerRealDay*)tc;
5412 			if(!permanentStudentsHash.contains(c->students))
5413 				toBeRemovedTime.append(tc);
5414 		}
5415 		//
5416 		else if(tc->type==CONSTRAINT_TEACHER_MIN_RESTING_HOURS_BETWEEN_MORNING_AND_AFTERNOON){
5417 			ConstraintTeacherMinRestingHoursBetweenMorningAndAfternoon* c=(ConstraintTeacherMinRestingHoursBetweenMorningAndAfternoon*)tc;
5418 			if(!existingTeachersNames.contains(c->teacherName))
5419 				toBeRemovedTime.append(tc);
5420 		}
5421 		else if(tc->type==CONSTRAINT_STUDENTS_SET_MIN_RESTING_HOURS_BETWEEN_MORNING_AND_AFTERNOON){
5422 			ConstraintStudentsSetMinRestingHoursBetweenMorningAndAfternoon* c=(ConstraintStudentsSetMinRestingHoursBetweenMorningAndAfternoon*)tc;
5423 			if(!permanentStudentsHash.contains(c->students))
5424 				toBeRemovedTime.append(tc);
5425 		}
5426 	}
5427 
5428 	for(SpaceConstraint* sc : qAsConst(spaceConstraintsList)){
5429 		if(sc->type==CONSTRAINT_ROOM_NOT_AVAILABLE_TIMES){
5430 			ConstraintRoomNotAvailableTimes* c=(ConstraintRoomNotAvailableTimes*)sc;
5431 			if(!existingRoomsNames.contains(c->room))
5432 				toBeRemovedSpace.append(sc);
5433 		}
5434 		else if(sc->type==CONSTRAINT_TEACHER_ROOM_NOT_AVAILABLE_TIMES){
5435 			ConstraintTeacherRoomNotAvailableTimes* c=(ConstraintTeacherRoomNotAvailableTimes*)sc;
5436 			if(!existingTeachersNames.contains(c->teacherName) || !existingRoomsNames.contains(c->room))
5437 				toBeRemovedSpace.append(sc);
5438 		}
5439 		else if(sc->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOM){
5440 			ConstraintActivityPreferredRoom* c=(ConstraintActivityPreferredRoom*)sc;
5441 			if(!existingActivitiesIds.contains(c->activityId) || !existingRoomsNames.contains(c->roomName)){
5442 				toBeRemovedSpace.append(sc);
5443 				recomputeSpace=true;
5444 			}
5445 		}
5446 		else if(sc->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOMS){
5447 			ConstraintActivityPreferredRooms* c=(ConstraintActivityPreferredRooms*)sc;
5448 			if(!existingActivitiesIds.contains(c->activityId))
5449 				toBeRemovedSpace.append(sc);
5450 			else{
5451 				QStringList newRooms;
5452 				for(const QString& room : qAsConst(c->roomsNames))
5453 					if(existingRoomsNames.contains(room))
5454 						newRooms.append(room);
5455 				c->roomsNames=newRooms;
5456 				if(c->roomsNames.count()==0)
5457 					toBeRemovedSpace.append(sc);
5458 			}
5459 		}
5460 		else if(sc->type==CONSTRAINT_STUDENTS_SET_HOME_ROOM){
5461 			ConstraintStudentsSetHomeRoom* c=(ConstraintStudentsSetHomeRoom*)sc;
5462 			if(!permanentStudentsHash.contains(c->studentsName) || !existingRoomsNames.contains(c->roomName))
5463 				toBeRemovedSpace.append(sc);
5464 		}
5465 		else if(sc->type==CONSTRAINT_STUDENTS_SET_HOME_ROOMS){
5466 			ConstraintStudentsSetHomeRooms* c=(ConstraintStudentsSetHomeRooms*)sc;
5467 			if(!permanentStudentsHash.contains(c->studentsName))
5468 				toBeRemovedSpace.append(sc);
5469 			else{
5470 				QStringList newRooms;
5471 				for(const QString& room : qAsConst(c->roomsNames))
5472 					if(existingRoomsNames.contains(room))
5473 						newRooms.append(room);
5474 				c->roomsNames=newRooms;
5475 				if(c->roomsNames.count()==0)
5476 					toBeRemovedSpace.append(sc);
5477 			}
5478 		}
5479 		else if(sc->type==CONSTRAINT_TEACHER_HOME_ROOM){
5480 			ConstraintTeacherHomeRoom* c=(ConstraintTeacherHomeRoom*)sc;
5481 			if(!existingTeachersNames.contains(c->teacherName) || !existingRoomsNames.contains(c->roomName))
5482 				toBeRemovedSpace.append(sc);
5483 		}
5484 		else if(sc->type==CONSTRAINT_TEACHER_HOME_ROOMS){
5485 			ConstraintTeacherHomeRooms* c=(ConstraintTeacherHomeRooms*)sc;
5486 			if(!existingTeachersNames.contains(c->teacherName))
5487 				toBeRemovedSpace.append(sc);
5488 			else{
5489 				QStringList newRooms;
5490 				for(const QString& room : qAsConst(c->roomsNames))
5491 					if(existingRoomsNames.contains(room))
5492 						newRooms.append(room);
5493 				c->roomsNames=newRooms;
5494 				if(c->roomsNames.count()==0)
5495 					toBeRemovedSpace.append(sc);
5496 			}
5497 		}
5498 		else if(sc->type==CONSTRAINT_SUBJECT_PREFERRED_ROOM){
5499 			ConstraintSubjectPreferredRoom* c=(ConstraintSubjectPreferredRoom*)sc;
5500 			if(!existingSubjectsNames.contains(c->subjectName) || !existingRoomsNames.contains(c->roomName))
5501 				toBeRemovedSpace.append(sc);
5502 		}
5503 		else if(sc->type==CONSTRAINT_SUBJECT_PREFERRED_ROOMS){
5504 			ConstraintSubjectPreferredRooms* c=(ConstraintSubjectPreferredRooms*)sc;
5505 			if(!existingSubjectsNames.contains(c->subjectName))
5506 				toBeRemovedSpace.append(sc);
5507 			else{
5508 				QStringList newRooms;
5509 				for(const QString& room : qAsConst(c->roomsNames))
5510 					if(existingRoomsNames.contains(room))
5511 						newRooms.append(room);
5512 				c->roomsNames=newRooms;
5513 				if(c->roomsNames.count()==0)
5514 					toBeRemovedSpace.append(sc);
5515 			}
5516 		}
5517 		else if(sc->type==CONSTRAINT_SUBJECT_ACTIVITY_TAG_PREFERRED_ROOM){
5518 			ConstraintSubjectActivityTagPreferredRoom* c=(ConstraintSubjectActivityTagPreferredRoom*)sc;
5519 			if(!existingSubjectsNames.contains(c->subjectName) || !existingActivityTagsNames.contains(c->activityTagName) ||
5520 			 !existingRoomsNames.contains(c->roomName))
5521 				toBeRemovedSpace.append(sc);
5522 		}
5523 		else if(sc->type==CONSTRAINT_SUBJECT_ACTIVITY_TAG_PREFERRED_ROOMS){
5524 			ConstraintSubjectActivityTagPreferredRooms* c=(ConstraintSubjectActivityTagPreferredRooms*)sc;
5525 			if(!existingSubjectsNames.contains(c->subjectName) || !existingActivityTagsNames.contains(c->activityTagName))
5526 				toBeRemovedSpace.append(sc);
5527 			else{
5528 				QStringList newRooms;
5529 				for(const QString& room : qAsConst(c->roomsNames))
5530 					if(existingRoomsNames.contains(room))
5531 						newRooms.append(room);
5532 				c->roomsNames=newRooms;
5533 				if(c->roomsNames.count()==0)
5534 					toBeRemovedSpace.append(sc);
5535 			}
5536 		}
5537 		else if(sc->type==CONSTRAINT_ACTIVITY_TAG_PREFERRED_ROOM){
5538 			ConstraintActivityTagPreferredRoom* c=(ConstraintActivityTagPreferredRoom*)sc;
5539 			if(!existingActivityTagsNames.contains(c->activityTagName) || !existingRoomsNames.contains(c->roomName))
5540 				toBeRemovedSpace.append(sc);
5541 		}
5542 		else if(sc->type==CONSTRAINT_ACTIVITY_TAG_PREFERRED_ROOMS){
5543 			ConstraintActivityTagPreferredRooms* c=(ConstraintActivityTagPreferredRooms*)sc;
5544 			if(!existingActivityTagsNames.contains(c->activityTagName))
5545 				toBeRemovedSpace.append(sc);
5546 			else{
5547 				QStringList newRooms;
5548 				for(const QString& room : qAsConst(c->roomsNames))
5549 					if(existingRoomsNames.contains(room))
5550 						newRooms.append(room);
5551 				c->roomsNames=newRooms;
5552 				if(c->roomsNames.count()==0)
5553 					toBeRemovedSpace.append(sc);
5554 			}
5555 		}
5556 		else if(sc->type==CONSTRAINT_STUDENTS_SET_MAX_BUILDING_CHANGES_PER_DAY){
5557 			ConstraintStudentsSetMaxBuildingChangesPerDay* c=(ConstraintStudentsSetMaxBuildingChangesPerDay*)sc;
5558 			if(!permanentStudentsHash.contains(c->studentsName))
5559 				toBeRemovedSpace.append(sc);
5560 		}
5561 		else if(sc->type==CONSTRAINT_STUDENTS_SET_MAX_BUILDING_CHANGES_PER_WEEK){
5562 			ConstraintStudentsSetMaxBuildingChangesPerWeek* c=(ConstraintStudentsSetMaxBuildingChangesPerWeek*)sc;
5563 			if(!permanentStudentsHash.contains(c->studentsName))
5564 				toBeRemovedSpace.append(sc);
5565 		}
5566 		else if(sc->type==CONSTRAINT_STUDENTS_SET_MIN_GAPS_BETWEEN_BUILDING_CHANGES){
5567 			ConstraintStudentsSetMinGapsBetweenBuildingChanges* c=(ConstraintStudentsSetMinGapsBetweenBuildingChanges*)sc;
5568 			if(!permanentStudentsHash.contains(c->studentsName))
5569 				toBeRemovedSpace.append(sc);
5570 		}
5571 		else if(sc->type==CONSTRAINT_TEACHER_MAX_BUILDING_CHANGES_PER_DAY){
5572 			ConstraintTeacherMaxBuildingChangesPerDay* c=(ConstraintTeacherMaxBuildingChangesPerDay*)sc;
5573 			if(!existingTeachersNames.contains(c->teacherName))
5574 				toBeRemovedSpace.append(sc);
5575 		}
5576 		else if(sc->type==CONSTRAINT_TEACHER_MAX_BUILDING_CHANGES_PER_WEEK){
5577 			ConstraintTeacherMaxBuildingChangesPerWeek* c=(ConstraintTeacherMaxBuildingChangesPerWeek*)sc;
5578 			if(!existingTeachersNames.contains(c->teacherName))
5579 				toBeRemovedSpace.append(sc);
5580 		}
5581 		else if(sc->type==CONSTRAINT_TEACHER_MIN_GAPS_BETWEEN_BUILDING_CHANGES){
5582 			ConstraintTeacherMinGapsBetweenBuildingChanges* c=(ConstraintTeacherMinGapsBetweenBuildingChanges*)sc;
5583 			if(!existingTeachersNames.contains(c->teacherName))
5584 				toBeRemovedSpace.append(sc);
5585 		}
5586 		else if(sc->type==CONSTRAINT_STUDENTS_SET_MAX_ROOM_CHANGES_PER_DAY){
5587 			ConstraintStudentsSetMaxRoomChangesPerDay* c=(ConstraintStudentsSetMaxRoomChangesPerDay*)sc;
5588 			if(!permanentStudentsHash.contains(c->studentsName))
5589 				toBeRemovedSpace.append(sc);
5590 		}
5591 		else if(sc->type==CONSTRAINT_STUDENTS_SET_MAX_ROOM_CHANGES_PER_WEEK){
5592 			ConstraintStudentsSetMaxRoomChangesPerWeek* c=(ConstraintStudentsSetMaxRoomChangesPerWeek*)sc;
5593 			if(!permanentStudentsHash.contains(c->studentsName))
5594 				toBeRemovedSpace.append(sc);
5595 		}
5596 		else if(sc->type==CONSTRAINT_STUDENTS_SET_MIN_GAPS_BETWEEN_ROOM_CHANGES){
5597 			ConstraintStudentsSetMinGapsBetweenRoomChanges* c=(ConstraintStudentsSetMinGapsBetweenRoomChanges*)sc;
5598 			if(!permanentStudentsHash.contains(c->studentsName))
5599 				toBeRemovedSpace.append(sc);
5600 		}
5601 		else if(sc->type==CONSTRAINT_TEACHER_MAX_ROOM_CHANGES_PER_DAY){
5602 			ConstraintTeacherMaxRoomChangesPerDay* c=(ConstraintTeacherMaxRoomChangesPerDay*)sc;
5603 			if(!existingTeachersNames.contains(c->teacherName))
5604 				toBeRemovedSpace.append(sc);
5605 		}
5606 		else if(sc->type==CONSTRAINT_TEACHER_MAX_ROOM_CHANGES_PER_WEEK){
5607 			ConstraintTeacherMaxRoomChangesPerWeek* c=(ConstraintTeacherMaxRoomChangesPerWeek*)sc;
5608 			if(!existingTeachersNames.contains(c->teacherName))
5609 				toBeRemovedSpace.append(sc);
5610 		}
5611 		else if(sc->type==CONSTRAINT_TEACHER_MIN_GAPS_BETWEEN_ROOM_CHANGES){
5612 			ConstraintTeacherMinGapsBetweenRoomChanges* c=(ConstraintTeacherMinGapsBetweenRoomChanges*)sc;
5613 			if(!existingTeachersNames.contains(c->teacherName))
5614 				toBeRemovedSpace.append(sc);
5615 		}
5616 		else if(sc->type==CONSTRAINT_ACTIVITIES_OCCUPY_MAX_DIFFERENT_ROOMS){
5617 			ConstraintActivitiesOccupyMaxDifferentRooms* c=(ConstraintActivitiesOccupyMaxDifferentRooms*)sc;
5618 			c->removeUseless(*this);
5619 			if(c->activitiesIds.count()<2)
5620 				toBeRemovedSpace.append(sc);
5621 		}
5622 		else if(sc->type==CONSTRAINT_ACTIVITIES_SAME_ROOM_IF_CONSECUTIVE){
5623 			ConstraintActivitiesSameRoomIfConsecutive* c=(ConstraintActivitiesSameRoomIfConsecutive*)sc;
5624 			c->removeUseless(*this);
5625 			if(c->activitiesIds.count()<2)
5626 				toBeRemovedSpace.append(sc);
5627 		}
5628 
5629 		//mornings-afternoons
5630 		else if(sc->type==CONSTRAINT_STUDENTS_SET_MAX_ROOM_CHANGES_PER_REAL_DAY){
5631 			ConstraintStudentsSetMaxRoomChangesPerRealDay* c=(ConstraintStudentsSetMaxRoomChangesPerRealDay*)sc;
5632 			if(!permanentStudentsHash.contains(c->studentsName))
5633 				toBeRemovedSpace.append(sc);
5634 		}
5635 		else if(sc->type==CONSTRAINT_TEACHER_MAX_ROOM_CHANGES_PER_REAL_DAY){
5636 			ConstraintTeacherMaxRoomChangesPerRealDay* c=(ConstraintTeacherMaxRoomChangesPerRealDay*)sc;
5637 			if(!existingTeachersNames.contains(c->teacherName))
5638 				toBeRemovedSpace.append(sc);
5639 		}
5640 	}
5641 
5642 	bool t;
5643 	if(toBeRemovedTime.count()>0){
5644 		t=removeTimeConstraints(toBeRemovedTime);
5645 		assert(t);
5646 	}
5647 	if(toBeRemovedSpace.count()>0){
5648 		t=removeSpaceConstraints(toBeRemovedSpace);
5649 		assert(t);
5650 	}
5651 
5652 	if(recomputeTime){
5653 		LockUnlock::computeLockedUnlockedActivitiesOnlyTime();
5654 	}
5655 	if(recomputeSpace){
5656 		LockUnlock::computeLockedUnlockedActivitiesOnlySpace();
5657 	}
5658 	if(recomputeTime || recomputeSpace){
5659 		LockUnlock::increaseCommunicationSpinBox();
5660 	}
5661 }
5662 
read(QWidget * parent,const QString & fileName,bool commandLine,QString commandLineDirectory)5663 bool Rules::read(QWidget* parent, const QString& fileName, bool commandLine, QString commandLineDirectory) //commandLineDirectory has trailing FILE_SEP
5664 {
5665 	QFile file(fileName);
5666 	if(!file.open(QIODevice::ReadOnly)){
5667 		//cout<<"Could not open file - not existing or in use\n";
5668 		RulesIrreconcilableMessage::warning(parent, tr("FET warning"), tr("Could not open file - not existing or in use"));
5669 		return false;
5670 	}
5671 
5672 	xmlReaderNumberOfUnrecognizedFields=0;
5673 
5674 	unrecognizedXmlTags.clear();
5675 	unrecognizedXmlLineNumbers.clear();
5676 	unrecognizedXmlColumnNumbers.clear();
5677 
5678 	QXmlStreamReader xmlReader(&file);
5679 
5680 	////////////////////////////////////////
5681 
5682 	if(!commandLine){
5683 		//logging part
5684 		QDir dir;
5685 		bool t=true;
5686 		if(!dir.exists(OUTPUT_DIR+FILE_SEP+"logs"))
5687 			t=dir.mkpath(OUTPUT_DIR+FILE_SEP+"logs");
5688 		if(!t){
5689 			RulesIrreconcilableMessage::warning(parent, tr("FET warning"), tr("Cannot create or use directory %1 - cannot continue").arg(QDir::toNativeSeparators(OUTPUT_DIR+FILE_SEP+"logs")));
5690 			return false;
5691 		}
5692 		assert(t);
5693 	}
5694 	else{
5695 		QDir dir;
5696 		bool t=true;
5697 		if(!dir.exists(commandLineDirectory+"logs"))
5698 			t=dir.mkpath(commandLineDirectory+"logs");
5699 		if(!t){
5700 			RulesIrreconcilableMessage::warning(parent, tr("FET warning"), tr("Cannot create or use directory %1 - cannot continue").arg(QDir::toNativeSeparators(commandLineDirectory+"logs")));
5701 			return false;
5702 		}
5703 		assert(t);
5704 	}
5705 
5706 	FakeString xmlReadingLog;
5707 	xmlReadingLog="";
5708 
5709 	QDate dat=QDate::currentDate();
5710 	QTime tim=QTime::currentTime();
5711 	QLocale loc(FET_LANGUAGE);
5712 	QString sTime=loc.toString(dat, QLocale::ShortFormat)+" "+loc.toString(tim, QLocale::ShortFormat);
5713 
5714 	QString reducedXmlLog="";
5715 	reducedXmlLog+="Log generated by FET "+FET_VERSION+" on "+sTime+"\n\n";
5716 	QString shortFileName=fileName.right(fileName.length()-fileName.lastIndexOf(FILE_SEP)-1);
5717 	reducedXmlLog+="Reading file "+shortFileName+"\n";
5718 	QFileInfo fileinfo(fileName);
5719 	reducedXmlLog+="Complete file name, including path: "+QDir::toNativeSeparators(fileinfo.absoluteFilePath())+"\n";
5720 	reducedXmlLog+="\n";
5721 
5722 	QString tmp;
5723 	if(commandLine)
5724 		tmp=commandLineDirectory+"logs"+FILE_SEP+XML_PARSING_LOG_FILENAME;
5725 	else
5726 		tmp=OUTPUT_DIR+FILE_SEP+"logs"+FILE_SEP+XML_PARSING_LOG_FILENAME;
5727 	QFile file2(tmp);
5728 	bool canWriteLogFile=true;
5729 	if(!file2.open(QIODevice::WriteOnly)){
5730 		QString s=tr("FET cannot open the log file %1 for writing. This might mean that you don't"
5731 			" have write permissions in this location. You can continue operation, but you might not be able to save the generated timetables"
5732 			" as html files").arg(QDir::toNativeSeparators(tmp))+
5733 			"\n\n"+tr("A solution is to remove that file (if it exists already) or set its permissions to allow writing")+
5734 			"\n\n"+tr("Please report possible bug");
5735 		IrreconcilableCriticalMessage::critical(parent, tr("FET critical"), s);
5736 		canWriteLogFile=false;
5737 	}
5738 	QTextStream logStream;
5739 	if(canWriteLogFile){
5740 		logStream.setDevice(&file2);
5741 #if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
5742 		logStream.setEncoding(QStringConverter::Utf8);
5743 #else
5744 		logStream.setCodec("UTF-8");
5745 #endif
5746 		logStream.setGenerateByteOrderMark(true);
5747 	}
5748 
5749 	bool okAbove3_12_17=true;
5750 	bool version5AndAbove=false;
5751 	bool warning=false;
5752 
5753 	bool version6AndAbove=false;
5754 	bool probably5Morocco=false;
5755 	bool probably5Algeria=false;
5756 	bool probably5MA=false;
5757 
5758 	bool probably5BP=false;
5759 
5760 	bool probably5Terms=false;
5761 
5762 	QString file_version;
5763 
5764 	if(xmlReader.readNextStartElement()){
5765 		xmlReadingLog+=" Found "+xmlReader.name().toString()+" tag\n";
5766 
5767 		bool okfetTag;
5768 		if(xmlReader.name()==QString("fet") || xmlReader.name()==QString("FET")) //the new tag is fet, the old tag - FET
5769 			okfetTag=true;
5770 		else
5771 			okfetTag=false;
5772 
5773 		if(!okfetTag)
5774 			okAbove3_12_17=false;
5775 		else{
5776 			assert(xmlReader.isStartElement());
5777 			assert(okAbove3_12_17==true);
5778 			/*QDomDocumentType dt=doc.doctype();
5779 			if(dt.isNull() || dt.name()!="FET")
5780 				okAbove3_12_17=false;
5781 			else*/
5782 			int filev[3], fetv[3];
5783 			QString fileVersionSuffix;
5784 
5785 			assert(xmlReader.name()==QString("fet") || xmlReader.name()==QString("FET"));
5786 			QString version=xmlReader.attributes().value("version").toString();
5787 			file_version=version;
5788 
5789 /*			QDomAttr a=elem1.attributeNode("version");
5790 
5791 			QString version=a.value();
5792 			file_version=version;*/
5793 
5794 #if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
5795 			QRegularExpression fileVerReCap("^(\\d+)\\.(\\d+)\\.(\\d+)(.*)$");
5796 			QRegularExpressionMatch match=fileVerReCap.match(file_version);
5797 			filev[0]=filev[1]=filev[2]=-1;
5798 			if(!match.hasMatch()){
5799 				RulesReconcilableMessage::warning(parent, tr("FET warning"), tr("File contains a version numbering scheme which"
5800 				" is not matched by v.v.va (3 numbers separated by points, followed by any string a, which may be empty). File will be opened, but you are advised"
5801 				" to check the version of the .fet file (in the beginning of the file). If this is a FET bug, please report it")+"\n\n"+
5802 				tr("If you are opening a file older than FET format version 5, it will be converted to latest FET data format"));
5803 				if(VERBOSE){
5804 					cout<<"Opened file version not matched by regexp"<<endl;
5805 				}
5806 			}
5807 			else{
5808 				bool ok;
5809 				filev[0]=match.captured(1).toInt(&ok);
5810 				assert(ok);
5811 				filev[1]=match.captured(2).toInt(&ok);
5812 				assert(ok);
5813 				filev[2]=match.captured(3).toInt(&ok);
5814 				assert(ok);
5815 				fileVersionSuffix=match.captured(4);
5816 				if(VERBOSE){
5817 					cout<<"Opened file version matched by regexp: major="<<filev[0]<<", minor="<<filev[1]<<", revision="<<filev[2];
5818 					cout<<", additional text="<<qPrintable(match.captured(4))<<"."<<endl;
5819 				}
5820 			}
5821 
5822 			QRegularExpression fetVerReCap("^(\\d+)\\.(\\d+)\\.(\\d+)(.*)$");
5823 			match=fetVerReCap.match(FET_VERSION);
5824 
5825 			fetv[0]=fetv[1]=fetv[2]=-1;
5826 			if(!match.hasMatch()){
5827 				RulesReconcilableMessage::warning(parent, tr("FET warning"), tr("FET version does not respect the format v.v.va"
5828 				" (3 numbers separated by points, followed by any string a, which may be empty). This is probably a bug in FET - please report it"));
5829 				if(VERBOSE){
5830 					cout<<"FET version not matched by regexp"<<endl;
5831 				}
5832 			}
5833 			else{
5834 				bool ok;
5835 				fetv[0]=match.captured(1).toInt(&ok);
5836 				assert(ok);
5837 				fetv[1]=match.captured(2).toInt(&ok);
5838 				assert(ok);
5839 				fetv[2]=match.captured(3).toInt(&ok);
5840 				assert(ok);
5841 				if(VERBOSE){
5842 					cout<<"FET version matched by regexp: major="<<fetv[0]<<", minor="<<fetv[1]<<", revision="<<fetv[2];
5843 					cout<<", additional text="<<qPrintable(match.captured(4))<<"."<<endl;
5844 				}
5845 			}
5846 #else
5847 			QRegExp fileVerReCap("^(\\d+)\\.(\\d+)\\.(\\d+)(.*)$");
5848 			int tfile=fileVerReCap.indexIn(file_version);
5849 			filev[0]=filev[1]=filev[2]=-1;
5850 			if(tfile!=0){
5851 				RulesReconcilableMessage::warning(parent, tr("FET warning"), tr("File contains a version numbering scheme which"
5852 				" is not matched by v.v.va (3 numbers separated by points, followed by any string a, which may be empty). File will be opened, but you are advised"
5853 				" to check the version of the .fet file (in the beginning of the file). If this is a FET bug, please report it")+"\n\n"+
5854 				tr("If you are opening a file older than FET format version 5, it will be converted to latest FET data format"));
5855 				if(VERBOSE){
5856 					cout<<"Opened file version not matched by regexp"<<endl;
5857 				}
5858 			}
5859 			else{
5860 				bool ok;
5861 				filev[0]=fileVerReCap.cap(1).toInt(&ok);
5862 				assert(ok);
5863 				filev[1]=fileVerReCap.cap(2).toInt(&ok);
5864 				assert(ok);
5865 				filev[2]=fileVerReCap.cap(3).toInt(&ok);
5866 				assert(ok);
5867 				fileVersionSuffix=fileVerReCap.cap(4);
5868 				if(VERBOSE){
5869 					cout<<"Opened file version matched by regexp: major="<<filev[0]<<", minor="<<filev[1]<<", revision="<<filev[2];
5870 					cout<<", additional text="<<qPrintable(fileVerReCap.cap(4))<<"."<<endl;
5871 				}
5872 			}
5873 
5874 			QRegExp fetVerReCap("^(\\d+)\\.(\\d+)\\.(\\d+)(.*)$");
5875 			int tfet=fetVerReCap.indexIn(FET_VERSION);
5876 			fetv[0]=fetv[1]=fetv[2]=-1;
5877 			if(tfet!=0){
5878 				RulesReconcilableMessage::warning(parent, tr("FET warning"), tr("FET version does not respect the format v.v.va"
5879 				" (3 numbers separated by points, followed by any string a, which may be empty). This is probably a bug in FET - please report it"));
5880 				if(VERBOSE){
5881 					cout<<"FET version not matched by regexp"<<endl;
5882 				}
5883 			}
5884 			else{
5885 				bool ok;
5886 				fetv[0]=fetVerReCap.cap(1).toInt(&ok);
5887 				assert(ok);
5888 				fetv[1]=fetVerReCap.cap(2).toInt(&ok);
5889 				assert(ok);
5890 				fetv[2]=fetVerReCap.cap(3).toInt(&ok);
5891 				assert(ok);
5892 				if(VERBOSE){
5893 					cout<<"FET version matched by regexp: major="<<fetv[0]<<", minor="<<fetv[1]<<", revision="<<fetv[2];
5894 					cout<<", additional text="<<qPrintable(fetVerReCap.cap(4))<<"."<<endl;
5895 				}
5896 			}
5897 #endif
5898 
5899 			if(filev[0]>=0 && fetv[0]>=0 && filev[1]>=0 && fetv[1]>=0 && filev[2]>=0 && fetv[2]>=0){
5900 				if(filev[0]>fetv[0] || (filev[0]==fetv[0] && filev[1]>fetv[1]) || (filev[0]==fetv[0]&&filev[1]==fetv[1]&&filev[2]>fetv[2])){
5901 					warning=true;
5902 				}
5903 			}
5904 
5905 			if(filev[0]>=5 || (filev[0]==-1 && filev[1]==-1 && filev[2]==-1))
5906 			//if major is >= 5 or major cannot be read
5907 				version5AndAbove=true;
5908 
5909 			if(filev[0]>=6 || (filev[0]==-1 && filev[1]==-1 && filev[2]==-1))
5910 			//if major is >= 6 or major cannot be read
5911 				version6AndAbove=true;
5912 
5913 			if(version5AndAbove && !version6AndAbove){
5914 				if(fileVersionSuffix==QString("-ma") || (fileVersionSuffix.length()>3 && fileVersionSuffix.startsWith(QString("-ma"))
5915 				 && ((fileVersionSuffix[3]>='0' && fileVersionSuffix[3]<='9') || fileVersionSuffix[3]=='-' || fileVersionSuffix[3]=='_' )))
5916 					probably5MA=true;
5917 				else if(fileVersionSuffix==QString("-morocco") || (fileVersionSuffix.length()>8 && fileVersionSuffix.startsWith(QString("-morocco"))
5918 				 && ((fileVersionSuffix[8]>='0' && fileVersionSuffix[8]<='9') || fileVersionSuffix[8]=='-' || fileVersionSuffix[8]=='_' )))
5919 					probably5Morocco=true;
5920 				else if(fileVersionSuffix==QString("-algeria") || (fileVersionSuffix.length()>8 && fileVersionSuffix.startsWith(QString("-algeria"))
5921 				 && ((fileVersionSuffix[8]>='0' && fileVersionSuffix[8]<='9') || fileVersionSuffix[8]=='-' || fileVersionSuffix[8]=='_' )))
5922 					probably5Algeria=true;
5923 
5924 				//maybe block-planning
5925 				else if(fileVersionSuffix==QString("-bp") || (fileVersionSuffix.length()>3 && fileVersionSuffix.startsWith(QString("-bp"))
5926 				 && ((fileVersionSuffix[3]>='0' && fileVersionSuffix[3]<='9') || fileVersionSuffix[3]=='-' || fileVersionSuffix[3]=='_' )))
5927 					probably5BP=true;
5928 
5929 				//maybe terms
5930 				else if(fileVersionSuffix==QString("-mathmake") || (fileVersionSuffix.length()>9 && fileVersionSuffix.startsWith(QString("-mathmake"))
5931 				 && ((fileVersionSuffix[9]>='0' && fileVersionSuffix[9]<='9') || fileVersionSuffix[9]=='-' || fileVersionSuffix[9]=='_' )))
5932 					probably5Terms=true;
5933 			}
5934 		}
5935 	}
5936 	else{
5937 		okAbove3_12_17=false;
5938 	}
5939 	if(!okAbove3_12_17){
5940 		if(VERBOSE){
5941 			cout<<"Invalid fet 3.12.17 or above input file"<<endl;
5942 		}
5943 		file.close();
5944 		file2.close();
5945 		RulesIrreconcilableMessage::warning(parent, tr("FET warning"), tr("File is incorrect...it cannot be opened"));
5946 		return false;
5947 	}
5948 
5949 	if(!version5AndAbove){
5950 		RulesReconcilableMessage::warning(parent, tr("FET information"),
5951 		 tr("Opening older file - it will be converted to latest format, automatically "
5952 		 "assigning weight percentages to constraints and dropping parity for activities. "
5953 		 "You are advised to make a backup of your old file before saving in new format.\n\n"
5954 		 "Please note that the default weight percentage of constraints min days between activities "
5955 		 "will be 95% (mainly satisfied, not always) and 'force consecutive if same day' will be set to true "
5956 		 "(meaning that if the activities are in the same day, they will be placed continuously, in a bigger duration activity). "
5957 		 "If you want, you can modify this percent to be 100%, manually in the fet input file "
5958 		 "or from the interface"));
5959 	}
5960 	else if(!version6AndAbove){
5961 		QString s="";
5962 		if(probably5MA)
5963 			s=tr("Opening an older file - it will be converted to the latest format. FET detected that this file was generated with a custom FET-5-MA version for mornings-afternoons,"
5964 			 " because the file version contains the string '-ma'. Some constraints will be renamed. The new style will refer to half days as 'days' and to real days as 'real days'."
5965 			 " Please be very careful and check once more the list of your constraints. If this is not true, please report the bug.");
5966 		else if(probably5Morocco)
5967 			s=tr("Opening an older file - it will be converted to the latest format. FET detected that this file was generated with a custom FET-5-Morocco version for mornings-afternoons,"
5968 			 " because the file version contains the string '-morocco'. Some constraints will be renamed. The new style will refer to half days as 'days' and to real days as 'real days'."
5969 			 " Please be very careful and check once more the list of your constraints. If this is not true, please report the bug.");
5970 		else if(probably5Algeria)
5971 			s=tr("Opening an older file - it will be converted to the latest format. FET detected that this file was generated with a custom FET-5-Algeria version for mornings-afternoons,"
5972 			 " because the file version contains the string '-algeria'. Some constraints will be renamed. The new style will refer to half days as 'days' and to real days as 'real days'."
5973 			 " Please be very careful and check once more the list of your constraints. If this is not true, please report the bug.");
5974 		else if(probably5BP)
5975 			s=tr("Opening an older file - it will be converted to the latest format. FET detected that this file was generated with a custom FET-5-BP (block-planning) version,"
5976 			 " because the file version contains the string '-bp'. Please be very careful and check once more the list of your constraints. If this is not true, please report the bug.");
5977 		else if(probably5Terms)
5978 			s=tr("Opening an older file - it will be converted to the latest format. FET detected that this file was generated with a custom FET-5-mathmake (terms) version,"
5979 			 " because the file version contains the string '-mathmake'. Please be very careful and check once more the list of your constraints. If this is not true, please report the bug.");
5980 		else
5981 			s=tr("Opening an older file - it will be converted to the latest format. FET detected that this file was generated with a FET-5 version."
5982 			" After opening, please check your constraints. If this is not true, please report the bug.");
5983 		s+="\n\n";
5984 		s+=tr("It is advisable to keep a backup copy of your old file.");
5985 		RulesReconcilableMessage::warning(parent, tr("FET information"), s);
5986 	}
5987 
5988 	if(warning){
5989 		RulesReconcilableMessage::warning(parent, tr("FET information"),
5990 		 tr("Opening a file generated with a newer version than your current FET software ... file will be opened but it is recommended to update your FET software to the latest version")
5991 		 +"\n\n"+tr("Your FET version: %1, file version: %2").arg(FET_VERSION).arg(file_version));
5992 	}
5993 
5994 	//Clear old rules, initialize new rules
5995 	if(this->initialized)
5996 		this->kill();
5997 	this->init();
5998 
5999 	int oldMode=this->mode;
6000 	this->mode=OFFICIAL;
6001 	if(probably5Morocco || probably5Algeria || probably5MA)
6002 		this->mode=MORNINGS_AFTERNOONS;
6003 	else if(probably5BP)
6004 		this->mode=BLOCK_PLANNING;
6005 	else if(probably5Terms)
6006 		this->mode=TERMS;
6007 
6008 	this->institutionName=tr("Default institution");
6009 	this->comments=tr("Default comments");
6010 
6011 	//default for terms (Finland)
6012 	this->nTerms=5;
6013 	this->nDaysPerTerm=5;
6014 
6015 	this->nDaysPerWeek=5;
6016 	this->daysOfTheWeek.clear();
6017 	this->daysOfTheWeek.append(tr("Monday"));
6018 	this->daysOfTheWeek.append(tr("Tuesday"));
6019 	this->daysOfTheWeek.append(tr("Wednesday"));
6020 	this->daysOfTheWeek.append(tr("Thursday"));
6021 	this->daysOfTheWeek.append(tr("Friday"));
6022 
6023 	this->nHoursPerDay=12;
6024 	this->hoursOfTheDay.clear();
6025 	this->hoursOfTheDay.append(tr("08:00", "Hour name"));
6026 	this->hoursOfTheDay.append(tr("09:00", "Hour name"));
6027 	this->hoursOfTheDay.append(tr("10:00", "Hour name"));
6028 	this->hoursOfTheDay.append(tr("11:00", "Hour name"));
6029 	this->hoursOfTheDay.append(tr("12:00", "Hour name"));
6030 	this->hoursOfTheDay.append(tr("13:00", "Hour name"));
6031 	this->hoursOfTheDay.append(tr("14:00", "Hour name"));
6032 	this->hoursOfTheDay.append(tr("15:00", "Hour name"));
6033 	this->hoursOfTheDay.append(tr("16:00", "Hour name"));
6034 	this->hoursOfTheDay.append(tr("17:00", "Hour name"));
6035 	this->hoursOfTheDay.append(tr("18:00", "Hour name"));
6036 	this->hoursOfTheDay.append(tr("19:00", "Hour name"));
6037 
6038 	bool skipDeprecatedConstraints=false;
6039 
6040 	bool skipDuplicatedStudentsSets=false;
6041 
6042 	assert(xmlReader.isStartElement() && (xmlReader.name()==QString("fet") || xmlReader.name()==QString("FET")));
6043 	while(xmlReader.readNextStartElement()){
6044 		xmlReadingLog+="  Found "+xmlReader.name().toString()+" tag\n";
6045 		if(xmlReader.name()==QString("Mode")){
6046 			QString text=xmlReader.readElementText();
6047 			if(text=="Official")
6048 				this->mode=OFFICIAL;
6049 			else if(text=="Mornings_Afternoons")
6050 				this->mode=MORNINGS_AFTERNOONS;
6051 			else if(text=="Block_Planning")
6052 				this->mode=BLOCK_PLANNING;
6053 			else if(text=="Terms")
6054 				this->mode=TERMS;
6055 			else
6056 				xmlReader.raiseError(tr("Incorrect mode - it has to be %1, %2, %3, or %4.").arg("Official").arg("Mornings_Afternoons").arg("Block_Planning").arg("Terms"));
6057 			xmlReadingLog+="  Found mode="+text+"\n";
6058 			reducedXmlLog+="Read mode="+text+"\n";
6059 		}
6060 		else if(xmlReader.name()==QString("Institution_Name")){
6061 			QString text=xmlReader.readElementText();
6062 			this->institutionName=text;
6063 			xmlReadingLog+="  Found institution name="+this->institutionName+"\n";
6064 			reducedXmlLog+="Read institution name="+this->institutionName+"\n";
6065 		}
6066 		else if(xmlReader.name()==QString("Comments")){
6067 			QString text=xmlReader.readElementText();
6068 			this->comments=text;
6069 			xmlReadingLog+="  Found comments="+this->comments+"\n";
6070 			reducedXmlLog+="Read comments="+this->comments+"\n";
6071 		}
6072 		else if(xmlReader.name()==QString("Number_of_Terms")){
6073 			QString text=xmlReader.readElementText();
6074 			this->nTerms=text.toInt();
6075 			xmlReadingLog+="  Found number of terms="+QString::number(this->nTerms)+"\n";
6076 			reducedXmlLog+="Read number of terms="+QString::number(this->nTerms)+"\n";
6077 
6078 			if(nTerms<=0){
6079 				xmlReader.raiseError(tr("%1 is incorrect").arg("Number_of_Terms"));
6080 			}
6081 			else if(nTerms>MAX_DAYS_PER_WEEK){
6082 				xmlReader.raiseError(tr("%1 is too large. Maximum allowed is %2.").arg("Number_of_Terms").arg(MAX_DAYS_PER_WEEK));
6083 			}
6084 			else{
6085 				assert(nTerms>0 && nTerms<=MAX_DAYS_PER_WEEK);
6086 			}
6087 		}
6088 		else if(xmlReader.name()==QString("Number_of_Days_Per_Term")){
6089 			QString text=xmlReader.readElementText();
6090 			this->nDaysPerTerm=text.toInt();
6091 			xmlReadingLog+="  Found number of days per term="+QString::number(this->nDaysPerTerm)+"\n";
6092 			reducedXmlLog+="Read number of days per term="+QString::number(this->nDaysPerTerm)+"\n";
6093 
6094 			if(nDaysPerTerm<=0){
6095 				xmlReader.raiseError(tr("%1 is incorrect").arg("Number_of_Days_Per_Term"));
6096 			}
6097 			else if(nDaysPerTerm>MAX_DAYS_PER_WEEK){
6098 				xmlReader.raiseError(tr("%1 is too large. Maximum allowed is %2.").arg("Number_of_Days_Per_Term").arg(MAX_DAYS_PER_WEEK));
6099 			}
6100 			else{
6101 				assert(nDaysPerTerm>0 && nDaysPerTerm<=MAX_DAYS_PER_WEEK);
6102 			}
6103 		}
6104 		else if(xmlReader.name()==QString("Days_List")){
6105 			this->daysOfTheWeek.clear();
6106 			int tmp=0;
6107 			bool numberWasFound=false;
6108 			assert(xmlReader.isStartElement());
6109 			QString numberString="Number_of_Days", dayString="Name";
6110 			while(xmlReader.readNextStartElement()){
6111 				xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
6112 				if(xmlReader.name()==QString("Number") || xmlReader.name()==QString("Number_of_Days") ){
6113 					numberString=xmlReader.name().toString();
6114 					QString text=xmlReader.readElementText();
6115 					this->nDaysPerWeek=text.toInt();
6116 					numberWasFound=true;
6117 					xmlReadingLog+="   Found the number of days per week = "+
6118 					 CustomFETString::number(this->nDaysPerWeek)+"\n";
6119 					reducedXmlLog+="Added "+
6120 					 CustomFETString::number(this->nDaysPerWeek)+" days per week\n";
6121 					if(nDaysPerWeek<=0){
6122 						xmlReader.raiseError(tr("%1 is incorrect").arg(numberString));
6123 					}
6124 					else if(nDaysPerWeek>MAX_DAYS_PER_WEEK){
6125 						xmlReader.raiseError(tr("%1 is too large. Maximum allowed is %2.").arg(numberString).arg(MAX_DAYS_PER_WEEK));
6126 					}
6127 					else{
6128 						assert(this->nDaysPerWeek>0 && nDaysPerWeek<=MAX_DAYS_PER_WEEK);
6129 					}
6130 				}
6131 				//old .fet XML format
6132 				else if(xmlReader.name()==QString("Name")){
6133 					dayString=xmlReader.name().toString();
6134 					if(tmp>=MAX_DAYS_PER_WEEK){
6135 						xmlReader.raiseError(tr("Too many %1 items. Maximum allowed is %2.").arg(dayString).arg(MAX_DAYS_PER_WEEK));
6136 						xmlReader.skipCurrentElement();
6137 					}
6138 					else{
6139 						QString text=xmlReader.readElementText();
6140 						//this->daysOfTheWeek[tmp]=text;
6141 						this->daysOfTheWeek.append(text);
6142 						xmlReadingLog+="   Found day "+this->daysOfTheWeek[tmp]+"\n";
6143 						tmp++;
6144 					}
6145 				}
6146 				//end old .fet XML format
6147 				else if(xmlReader.name()==QString("Day")){
6148 					assert(xmlReader.isStartElement());
6149 					while(xmlReader.readNextStartElement()){
6150 						xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
6151 						if(xmlReader.name()==QString("Name")){
6152 							dayString=xmlReader.name().toString();
6153 							if(tmp>=MAX_DAYS_PER_WEEK){
6154 								xmlReader.raiseError(tr("Too many %1 items. Maximum allowed is %2.").arg(dayString).arg(MAX_DAYS_PER_WEEK));
6155 								xmlReader.skipCurrentElement();
6156 							}
6157 							else{
6158 								QString text=xmlReader.readElementText();
6159 								this->daysOfTheWeek.append(text);
6160 								//this->daysOfTheWeek[tmp]=text;
6161 								xmlReadingLog+="   Found day "+this->daysOfTheWeek[tmp]+"\n";
6162 								tmp++;
6163 							}
6164 						}
6165 						else{
6166 							unrecognizedXmlTags.append(xmlReader.name().toString());
6167 							unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
6168 							unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
6169 
6170 							xmlReader.skipCurrentElement();
6171 							xmlReaderNumberOfUnrecognizedFields++;
6172 						}
6173 					}
6174 				}
6175 				else{
6176 					unrecognizedXmlTags.append(xmlReader.name().toString());
6177 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
6178 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
6179 
6180 					xmlReader.skipCurrentElement();
6181 					xmlReaderNumberOfUnrecognizedFields++;
6182 				}
6183 			}
6184 			if(!xmlReader.error()){
6185 				if(!numberWasFound){
6186 					xmlReader.raiseError(tr("%1 not found").arg(numberString));
6187 				}
6188 				else{
6189 					if(!(tmp==nDaysPerWeek))
6190 						xmlReader.raiseError(tr("%1: %2 and the number of %3 read do not correspond").arg("Days_List").arg(numberString).arg(dayString));
6191 					else
6192 						assert(tmp==this->nDaysPerWeek);
6193 				}
6194 			}
6195 		}
6196 		else if(xmlReader.name()==QString("Hours_List")){
6197 			this->hoursOfTheDay.clear();
6198 			int tmp=0;
6199 			bool numberWasFound=false;
6200 			assert(xmlReader.isStartElement());
6201 			QString numberString="Number_of_Hours", hourString="Name";
6202 			while(xmlReader.readNextStartElement()){
6203 				xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
6204 				if(xmlReader.name()==QString("Number") || xmlReader.name()==QString("Number_of_Hours")){
6205 					numberString=xmlReader.name().toString();
6206 					QString text=xmlReader.readElementText();
6207 					this->nHoursPerDay=text.toInt();
6208 					numberWasFound=true;
6209 					xmlReadingLog+="   Found the number of hours per day = "+
6210 					 CustomFETString::number(this->nHoursPerDay)+"\n";
6211 					reducedXmlLog+="Added "+
6212 					 CustomFETString::number(this->nHoursPerDay)+" hours per day\n";
6213 					if(nHoursPerDay<=0){
6214 						xmlReader.raiseError(tr("%1 is incorrect").arg(numberString));
6215 					}
6216 					else if(nHoursPerDay>MAX_HOURS_PER_DAY){
6217 						xmlReader.raiseError(tr("%1 is too large. Maximum allowed is %2.").arg("Number").arg(MAX_HOURS_PER_DAY));
6218 					}
6219 					else{
6220 						assert(this->nHoursPerDay>0 && nHoursPerDay<=MAX_HOURS_PER_DAY);
6221 					}
6222 				}
6223 				//old .fet XML format
6224 				else if(xmlReader.name()==QString("Name")){
6225 					hourString=xmlReader.name().toString();
6226 					if(tmp>=MAX_HOURS_PER_DAY){
6227 						xmlReader.raiseError(tr("Too many %1 items. Maximum allowed is %2.").arg(hourString).arg(MAX_HOURS_PER_DAY));
6228 						xmlReader.skipCurrentElement();
6229 					}
6230 					else{
6231 						QString text=xmlReader.readElementText();
6232 						//this->hoursOfTheDay[tmp]=text;
6233 						this->hoursOfTheDay.append(text);
6234 						xmlReadingLog+="   Found hour "+this->hoursOfTheDay[tmp]+"\n";
6235 						tmp++;
6236 					}
6237 				}
6238 				//end old .fet XML format
6239 				else if(xmlReader.name()==QString("Hour")){
6240 					assert(xmlReader.isStartElement());
6241 					while(xmlReader.readNextStartElement()){
6242 						xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
6243 						if(xmlReader.name()==QString("Name")){
6244 							hourString=xmlReader.name().toString();
6245 							if(tmp>=MAX_HOURS_PER_DAY){
6246 								xmlReader.raiseError(tr("Too many %1 items. Maximum allowed is %2.").arg(hourString).arg(MAX_HOURS_PER_DAY));
6247 								xmlReader.skipCurrentElement();
6248 							}
6249 							else{
6250 								QString text=xmlReader.readElementText();
6251 								//this->hoursOfTheDay[tmp]=text;
6252 								this->hoursOfTheDay.append(text);
6253 								xmlReadingLog+="    Found hour "+this->hoursOfTheDay[tmp]+"\n";
6254 								tmp++;
6255 							}
6256 						}
6257 						else{
6258 							unrecognizedXmlTags.append(xmlReader.name().toString());
6259 							unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
6260 							unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
6261 
6262 							xmlReader.skipCurrentElement();
6263 							xmlReaderNumberOfUnrecognizedFields++;
6264 						}
6265 					}
6266 				}
6267 				else{
6268 					unrecognizedXmlTags.append(xmlReader.name().toString());
6269 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
6270 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
6271 
6272 					xmlReader.skipCurrentElement();
6273 					xmlReaderNumberOfUnrecognizedFields++;
6274 				}
6275 			}
6276 			if(!xmlReader.error()){
6277 				if(!numberWasFound){
6278 					xmlReader.raiseError(tr("%1 not found").arg(numberString));
6279 				}
6280 				else{
6281 					if(numberString=="Number"){
6282 						//some older files contain also the end of day hour, so tmp==nHoursPerDay+1 in this case
6283 						if(!(tmp==nHoursPerDay || tmp==nHoursPerDay+1))
6284 							xmlReader.raiseError(tr("%1: %2 and the number of %3 read do not correspond").arg("Hours_List").arg(numberString).arg(hourString));
6285 						else
6286 							assert(tmp==nHoursPerDay || tmp==nHoursPerDay+1);
6287 					}
6288 					else{
6289 						assert(numberString=="Number_of_Hours");
6290 						if(!(tmp==nHoursPerDay))
6291 							xmlReader.raiseError(tr("%1: %2 and the number of %3 read do not correspond").arg("Hours_List").arg(numberString).arg(hourString));
6292 						else
6293 							assert(tmp==nHoursPerDay);
6294 					}
6295 				}
6296 			}
6297 		}
6298 		else if(xmlReader.name()==QString("Teachers_List")){
6299 			QSet<QString> teachersRead;
6300 
6301 			QSet<QString> subjectsRead; //we assume that the reading of the subjects is done before the reading of the teachers
6302 			for(Subject* sbj : qAsConst(subjectsList))
6303 				subjectsRead.insert(sbj->name);
6304 
6305 			int tmp=0;
6306 			assert(xmlReader.isStartElement());
6307 			while(xmlReader.readNextStartElement()){
6308 				xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
6309 				if(xmlReader.name()==QString("Teacher")){
6310 					Teacher* teacher=new Teacher();
6311 
6312 					if(probably5Morocco)
6313 						teacher->morningsAfternoonsBehavior=TEACHER_MORNING_OR_EXCLUSIVELY_AFTERNOON;
6314 					else if(probably5Algeria)
6315 						teacher->morningsAfternoonsBehavior=TEACHER_UNRESTRICTED_MORNINGS_AFTERNOONS;
6316 
6317 					assert(xmlReader.isStartElement());
6318 					while(xmlReader.readNextStartElement()){
6319 						xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
6320 						if(xmlReader.name()==QString("Name")){
6321 							QString text=xmlReader.readElementText();
6322 							teacher->name=text;
6323 							xmlReadingLog+="    Read teacher name: "+teacher->name+"\n";
6324 						}
6325 						else if(xmlReader.name()==QString("Mornings_Afternoons_Behavior")){
6326 							//it is best to allow to read the teacher mornings-afternoons behavior even if the mode is not Mornings-Afternoons
6327 							if(1 || this->mode==MORNINGS_AFTERNOONS){
6328 								QString text=xmlReader.readElementText();
6329 								if(text=="Unrestricted")
6330 									teacher->morningsAfternoonsBehavior=TEACHER_UNRESTRICTED_MORNINGS_AFTERNOONS;
6331 								else if(text=="Exclusive")
6332 									teacher->morningsAfternoonsBehavior=TEACHER_MORNING_OR_EXCLUSIVELY_AFTERNOON;
6333 								else if(text=="One day exception")
6334 									teacher->morningsAfternoonsBehavior=TEACHER_ONE_DAY_EXCEPTION;
6335 								else if(text=="Two days exception")
6336 									teacher->morningsAfternoonsBehavior=TEACHER_TWO_DAYS_EXCEPTION;
6337 								else if(text=="Three days exception")
6338 									teacher->morningsAfternoonsBehavior=TEACHER_THREE_DAYS_EXCEPTION;
6339 								else if(text=="Four days exception")
6340 									teacher->morningsAfternoonsBehavior=TEACHER_FOUR_DAYS_EXCEPTION;
6341 								else if(text=="Five days exception")
6342 									teacher->morningsAfternoonsBehavior=TEACHER_FIVE_DAYS_EXCEPTION;
6343 								xmlReadingLog+="    Read teacher mornings afternoons behavior: "+QString::number(teacher->morningsAfternoonsBehavior)+"\n";
6344 							}
6345 							else{
6346 								unrecognizedXmlTags.append(xmlReader.name().toString());
6347 								unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
6348 								unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
6349 
6350 								xmlReader.skipCurrentElement();
6351 								xmlReaderNumberOfUnrecognizedFields++;
6352 							}
6353 						}
6354 						else if(xmlReader.name()==QString("Target_Number_of_Hours")){
6355 							QString text=xmlReader.readElementText();
6356 							teacher->targetNumberOfHours=text.toInt();
6357 							xmlReadingLog+="    Read teacher target number of hours: "+CustomFETString::number(teacher->targetNumberOfHours)+"\n";
6358 						}
6359 						else if(xmlReader.name()==QString("Qualified_Subjects")){
6360 							assert(xmlReader.isStartElement());
6361 							while(xmlReader.readNextStartElement()){
6362 								xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
6363 								if(xmlReader.name()==QString("Qualified_Subject")){
6364 									QString text=xmlReader.readElementText();
6365 									if(teacher->qualifiedSubjectsHash.contains(text)){
6366 										xmlReader.raiseError(tr("The teacher %1 has duplicate qualified subject %2.").arg(teacher->name).arg(text));
6367 									}
6368 									else if(!subjectsRead.contains(text)){
6369 										xmlReader.raiseError(tr("The teacher %1 has attached an inexistent qualified subject %2."
6370 										 " Please note that starting with FET version %3 the list of subjects (tag <Subjects_List> in the .fet XML file)"
6371 										 " must appear before the list of teachers (tag <Teachers_List> in the .fet XML file)", "Please keep <Subjects_List> and"
6372 										 " <Teachers_List> untranslated, as in the original English string")
6373 										 .arg(teacher->name).arg(text).arg("5.30.0"));
6374 									}
6375 									else{
6376 										teacher->qualifiedSubjectsList.push_back(text);
6377 										teacher->qualifiedSubjectsHash.insert(text, std::prev(teacher->qualifiedSubjectsList.end()));
6378 									}
6379 								}
6380 								else{
6381 									unrecognizedXmlTags.append(xmlReader.name().toString());
6382 									unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
6383 									unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
6384 
6385 									xmlReader.skipCurrentElement();
6386 									xmlReaderNumberOfUnrecognizedFields++;
6387 								}
6388 							}
6389 						}
6390 						else if(xmlReader.name()==QString("Comments")){
6391 							QString text=xmlReader.readElementText();
6392 							teacher->comments=text;
6393 							xmlReadingLog+="    Crt. teacher comments="+teacher->comments+"\n";
6394 						}
6395 						else{
6396 							unrecognizedXmlTags.append(xmlReader.name().toString());
6397 							unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
6398 							unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
6399 
6400 							xmlReader.skipCurrentElement();
6401 							xmlReaderNumberOfUnrecognizedFields++;
6402 						}
6403 					}
6404 					bool tmp2=teachersRead.contains(teacher->name);
6405 					if(tmp2){
6406 						RulesReconcilableMessage::warning(parent, tr("FET warning"),
6407 						 tr("Duplicate teacher %1 found - ignoring").arg(teacher->name));
6408 						xmlReadingLog+="   Teacher not added - duplicate\n";
6409 
6410 						delete teacher;
6411 					}
6412 					else{
6413 						teachersRead.insert(teacher->name);
6414 						this->addTeacherFast(teacher);
6415 						tmp++;
6416 						xmlReadingLog+="   Teacher added\n";
6417 					}
6418 				}
6419 				else{
6420 					unrecognizedXmlTags.append(xmlReader.name().toString());
6421 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
6422 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
6423 
6424 					xmlReader.skipCurrentElement();
6425 					xmlReaderNumberOfUnrecognizedFields++;
6426 				}
6427 			}
6428 			if(!(tmp==this->teachersList.size()))
6429 				xmlReader.raiseError(tr("%1 is incorrect").arg("Teachers_List"));
6430 			else{
6431 				assert(tmp==this->teachersList.size());
6432 				xmlReadingLog+="  Added "+CustomFETString::number(tmp)+" teachers\n";
6433 				reducedXmlLog+="Added "+CustomFETString::number(tmp)+" teachers\n";
6434 			}
6435 		}
6436 		//start 2021-03-20
6437 		else if(xmlReader.name()==QString("Exception_Teachers_One_Day_List")){
6438 			//this tag is met only in the old FET Morocco files.
6439 			bool reportMoroccoTeachers=true;
6440 
6441 			this->mode=MORNINGS_AFTERNOONS;
6442 
6443 			for(Teacher* tch : qAsConst(teachersList))
6444 				if(tch->morningsAfternoonsBehavior==TEACHER_UNRESTRICTED_MORNINGS_AFTERNOONS ||
6445 				 tch->morningsAfternoonsBehavior==TEACHER_MORNINGS_AFTERNOONS_BEHAVIOR_NOT_INITIALIZED)
6446 					tch->morningsAfternoonsBehavior=TEACHER_MORNING_OR_EXCLUSIVELY_AFTERNOON;
6447 
6448 			if(reportMoroccoTeachers && !probably5Morocco){
6449 				RulesReconcilableMessage::information(parent, tr("FET information"),
6450 				 tr("You are opening an old Morocco file. All the teachers will have mornings afternoons behavior"
6451 				 " 'Exclusive mornings/afternoons' by default, and the exceptions will be recognized correctly."
6452 				 " If this is a mistake and your file is not an old Morocco file, please report the bug.")+QString(" ")+
6453 				 tr("(The program detected this because your file contains the section %1.)").arg("'Exception_Teachers_One_Day_List'")+
6454 				 QString("\n\n")+
6455 				 tr("Please note that if you save now your file, you won't be able to open it correctly again later using"
6456 				 " the old version of FET Morocco."));
6457 				reportMoroccoTeachers=false;
6458 			}
6459 
6460 			int tmp=0;
6461 			assert(xmlReader.isStartElement());
6462 			while(xmlReader.readNextStartElement()){
6463 				xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
6464 
6465 				if(xmlReader.name()==QString("Teacher")){
6466 					QString t;
6467 
6468 					if(xmlReader.readNext()==QXmlStreamReader::Characters){
6469 						t=xmlReader.text().toString();
6470 						xmlReader.skipCurrentElement();
6471 					}
6472 					else{
6473 						assert(xmlReader.isStartElement());
6474 						do{
6475 							xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
6476 							if(xmlReader.name()==QString("Name")){ //old style
6477 								t=xmlReader.readElementText();
6478 							}
6479 							else{
6480 								unrecognizedXmlTags.append(xmlReader.name().toString());
6481 								unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
6482 								unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
6483 
6484 								xmlReader.skipCurrentElement();
6485 								xmlReaderNumberOfUnrecognizedFields++;
6486 							}
6487 						}
6488 						while(xmlReader.readNextStartElement());
6489 					}
6490 
6491 					tmp++;
6492 					//this->exceptionTeachersList.append(t);
6493 					teachersList.at(searchTeacher(t))->morningsAfternoonsBehavior=TEACHER_ONE_DAY_EXCEPTION;
6494 				}
6495 				else{
6496 					unrecognizedXmlTags.append(xmlReader.name().toString());
6497 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
6498 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
6499 
6500 					xmlReader.skipCurrentElement();
6501 					xmlReaderNumberOfUnrecognizedFields++;
6502 				}
6503 			}
6504 			xmlReadingLog+="  Added "+QString::number(tmp)+" exception 1 teachers\n";
6505 			reducedXmlLog+="Added "+QString::number(tmp)+" exception 1 teachers\n";
6506 		}
6507 		else if(xmlReader.name()==QString("Exception_Teachers_Two_Days_List")){
6508 			int tmp=0;
6509 			assert(xmlReader.isStartElement());
6510 			while(xmlReader.readNextStartElement()){
6511 				xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
6512 
6513 				if(xmlReader.name()==QString("Teacher")){
6514 					QString t;
6515 
6516 					if(xmlReader.readNext()==QXmlStreamReader::Characters){
6517 						t=xmlReader.text().toString();
6518 						xmlReader.skipCurrentElement();
6519 					}
6520 					else{
6521 						assert(xmlReader.isStartElement());
6522 						do{
6523 							xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
6524 							if(xmlReader.name()==QString("Name")){ //old style
6525 								t=xmlReader.readElementText();
6526 							}
6527 							else{
6528 								unrecognizedXmlTags.append(xmlReader.name().toString());
6529 								unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
6530 								unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
6531 
6532 								xmlReader.skipCurrentElement();
6533 								xmlReaderNumberOfUnrecognizedFields++;
6534 							}
6535 						}
6536 						while(xmlReader.readNextStartElement());
6537 					}
6538 
6539 					tmp++;
6540 					//this->exceptionTeachers2List.append(t);
6541 					teachersList.at(searchTeacher(t))->morningsAfternoonsBehavior=TEACHER_TWO_DAYS_EXCEPTION;
6542 				}
6543 				else{
6544 					unrecognizedXmlTags.append(xmlReader.name().toString());
6545 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
6546 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
6547 
6548 					xmlReader.skipCurrentElement();
6549 					xmlReaderNumberOfUnrecognizedFields++;
6550 				}
6551 			}
6552 			xmlReadingLog+="  Added "+QString::number(tmp)+" exception 2 teachers\n";
6553 			reducedXmlLog+="Added "+QString::number(tmp)+" exception 2 teachers\n";
6554 		}
6555 		else if(xmlReader.name()==QString("Exception_Teachers_Three_Days_List")){
6556 			int tmp=0;
6557 			assert(xmlReader.isStartElement());
6558 			while(xmlReader.readNextStartElement()){
6559 				xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
6560 
6561 				if(xmlReader.name()==QString("Teacher")){
6562 					QString t;
6563 
6564 					if(xmlReader.readNext()==QXmlStreamReader::Characters){
6565 						t=xmlReader.text().toString();
6566 						xmlReader.skipCurrentElement();
6567 					}
6568 					else{
6569 						assert(xmlReader.isStartElement());
6570 						do{
6571 							xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
6572 							if(xmlReader.name()==QString("Name")){ //old style
6573 								t=xmlReader.readElementText();
6574 							}
6575 							else{
6576 								unrecognizedXmlTags.append(xmlReader.name().toString());
6577 								unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
6578 								unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
6579 
6580 								xmlReader.skipCurrentElement();
6581 								xmlReaderNumberOfUnrecognizedFields++;
6582 							}
6583 						}
6584 						while(xmlReader.readNextStartElement());
6585 					}
6586 
6587 					tmp++;
6588 					//this->exceptionTeachers3List.append(t);
6589 					teachersList.at(searchTeacher(t))->morningsAfternoonsBehavior=TEACHER_THREE_DAYS_EXCEPTION;
6590 				}
6591 				else{
6592 					unrecognizedXmlTags.append(xmlReader.name().toString());
6593 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
6594 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
6595 
6596 					xmlReader.skipCurrentElement();
6597 					xmlReaderNumberOfUnrecognizedFields++;
6598 				}
6599 			}
6600 			xmlReadingLog+="  Added "+QString::number(tmp)+" exception 3 teachers\n";
6601 			reducedXmlLog+="Added "+QString::number(tmp)+" exception 3 teachers\n";
6602 		}
6603 		else if(xmlReader.name()==QString("Exception_Teachers_Four_Days_List")){
6604 			int tmp=0;
6605 			assert(xmlReader.isStartElement());
6606 			while(xmlReader.readNextStartElement()){
6607 				xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
6608 
6609 				if(xmlReader.name()==QString("Teacher")){
6610 					QString t;
6611 
6612 					if(xmlReader.readNext()==QXmlStreamReader::Characters){
6613 						t=xmlReader.text().toString();
6614 						xmlReader.skipCurrentElement();
6615 					}
6616 					else{
6617 						assert(xmlReader.isStartElement());
6618 						do{
6619 							xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
6620 							if(xmlReader.name()==QString("Name")){ //old style
6621 								t=xmlReader.readElementText();
6622 							}
6623 							else{
6624 								unrecognizedXmlTags.append(xmlReader.name().toString());
6625 								unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
6626 								unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
6627 
6628 								xmlReader.skipCurrentElement();
6629 								xmlReaderNumberOfUnrecognizedFields++;
6630 							}
6631 						}
6632 						while(xmlReader.readNextStartElement());
6633 					}
6634 
6635 					tmp++;
6636 					//this->exceptionTeachers4List.append(t);
6637 					teachersList.at(searchTeacher(t))->morningsAfternoonsBehavior=TEACHER_FOUR_DAYS_EXCEPTION;
6638 				}
6639 				else{
6640 					unrecognizedXmlTags.append(xmlReader.name().toString());
6641 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
6642 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
6643 
6644 					xmlReader.skipCurrentElement();
6645 					xmlReaderNumberOfUnrecognizedFields++;
6646 				}
6647 			}
6648 			xmlReadingLog+="  Added "+QString::number(tmp)+" exception 4 teachers\n";
6649 			reducedXmlLog+="Added "+QString::number(tmp)+" exception 4 teachers\n";
6650 		}
6651 		else if(xmlReader.name()==QString("Exception_Teachers_Five_Days_List")){
6652 			int tmp=0;
6653 			assert(xmlReader.isStartElement());
6654 			while(xmlReader.readNextStartElement()){
6655 				xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
6656 
6657 				if(xmlReader.name()==QString("Teacher")){
6658 					QString t;
6659 
6660 					if(xmlReader.readNext()==QXmlStreamReader::Characters){
6661 						t=xmlReader.text().toString();
6662 						xmlReader.skipCurrentElement();
6663 					}
6664 					else{
6665 						assert(xmlReader.isStartElement());
6666 						do{
6667 							xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
6668 							if(xmlReader.name()==QString("Name")){ //old style
6669 								t=xmlReader.readElementText();
6670 							}
6671 							else{
6672 								unrecognizedXmlTags.append(xmlReader.name().toString());
6673 								unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
6674 								unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
6675 
6676 								xmlReader.skipCurrentElement();
6677 								xmlReaderNumberOfUnrecognizedFields++;
6678 							}
6679 						}
6680 						while(xmlReader.readNextStartElement());
6681 					}
6682 
6683 					tmp++;
6684 					//this->exceptionTeachers5List.append(t);
6685 					teachersList.at(searchTeacher(t))->morningsAfternoonsBehavior=TEACHER_FIVE_DAYS_EXCEPTION;
6686 				}
6687 				else{
6688 					unrecognizedXmlTags.append(xmlReader.name().toString());
6689 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
6690 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
6691 
6692 					xmlReader.skipCurrentElement();
6693 					xmlReaderNumberOfUnrecognizedFields++;
6694 				}
6695 			}
6696 			xmlReadingLog+="  Added "+QString::number(tmp)+" exception 5 teachers\n";
6697 			reducedXmlLog+="Added "+QString::number(tmp)+" exception 5 teachers\n";
6698 		}
6699 		//end 2021-03-20
6700 		else if(xmlReader.name()==QString("Subjects_List")){
6701 			QSet<QString> subjectsRead;
6702 
6703 			int tmp=0;
6704 			assert(xmlReader.isStartElement());
6705 			while(xmlReader.readNextStartElement()){
6706 				xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
6707 				if(xmlReader.name()==QString("Subject")){
6708 					Subject* subject=new Subject();
6709 					assert(xmlReader.isStartElement());
6710 					while(xmlReader.readNextStartElement()){
6711 						xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
6712 						if(xmlReader.name()==QString("Name")){
6713 							QString text=xmlReader.readElementText();
6714 							subject->name=text;
6715 							xmlReadingLog+="    Read subject name: "+subject->name+"\n";
6716 						}
6717 						else if(xmlReader.name()==QString("Comments")){
6718 							QString text=xmlReader.readElementText();
6719 							subject->comments=text;
6720 							xmlReadingLog+="    Crt. subject comments="+subject->comments+"\n";
6721 						}
6722 						else{
6723 							unrecognizedXmlTags.append(xmlReader.name().toString());
6724 							unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
6725 							unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
6726 
6727 							xmlReader.skipCurrentElement();
6728 							xmlReaderNumberOfUnrecognizedFields++;
6729 						}
6730 					}
6731 					bool tmp2=subjectsRead.contains(subject->name);
6732 					if(tmp2){
6733 						RulesReconcilableMessage::warning(parent, tr("FET warning"),
6734 						 tr("Duplicate subject %1 found - ignoring").arg(subject->name));
6735 						xmlReadingLog+="   Subject not added - duplicate\n";
6736 
6737 						delete subject;
6738 					}
6739 					else{
6740 						subjectsRead.insert(subject->name);
6741 						this->addSubjectFast(subject);
6742 						tmp++;
6743 						xmlReadingLog+="   Subject inserted\n";
6744 					}
6745 				}
6746 				else{
6747 					unrecognizedXmlTags.append(xmlReader.name().toString());
6748 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
6749 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
6750 
6751 					xmlReader.skipCurrentElement();
6752 					xmlReaderNumberOfUnrecognizedFields++;
6753 				}
6754 			}
6755 			if(!(tmp==this->subjectsList.size()))
6756 				xmlReader.raiseError(tr("%1 is incorrect").arg("Subjects_List"));
6757 			else{
6758 				assert(tmp==this->subjectsList.size());
6759 				xmlReadingLog+="  Added "+CustomFETString::number(tmp)+" subjects\n";
6760 				reducedXmlLog+="Added "+CustomFETString::number(tmp)+" subjects\n";
6761 			}
6762 		}
6763 		else if(xmlReader.name()==QString("Subject_Tags_List")){
6764 			QSet<QString> activityTagsRead;
6765 
6766 			RulesReconcilableMessage::information(parent, tr("FET information"), tr("Your file contains subject tags list"
6767 			  ", which is named in versions>=5.5.0 activity tags list"));
6768 
6769 			int tmp=0;
6770 			assert(xmlReader.isStartElement());
6771 			while(xmlReader.readNextStartElement()){
6772 				xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
6773 				if(xmlReader.name()==QString("Subject_Tag")){
6774 					ActivityTag* activityTag=new ActivityTag();
6775 					assert(xmlReader.isStartElement());
6776 					while(xmlReader.readNextStartElement()){
6777 						xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
6778 						if(xmlReader.name()==QString("Name")){
6779 							QString text=xmlReader.readElementText();
6780 							activityTag->name=text;
6781 							xmlReadingLog+="    Read activity tag name: "+activityTag->name+"\n";
6782 						}
6783 						else if(xmlReader.name()==QString("Comments")){
6784 							QString text=xmlReader.readElementText();
6785 							activityTag->comments=text;
6786 							xmlReadingLog+="    Crt. activity tag comments="+activityTag->comments+"\n";
6787 						}
6788 						else{
6789 							unrecognizedXmlTags.append(xmlReader.name().toString());
6790 							unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
6791 							unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
6792 
6793 							xmlReader.skipCurrentElement();
6794 							xmlReaderNumberOfUnrecognizedFields++;
6795 						}
6796 					}
6797 					bool tmp2=activityTagsRead.contains(activityTag->name);
6798 					if(tmp2){
6799 						RulesReconcilableMessage::warning(parent, tr("FET warning"),
6800 						 tr("Duplicate activity tag %1 found - ignoring").arg(activityTag->name));
6801 						xmlReadingLog+="   Activity tag not added - duplicate\n";
6802 
6803 						delete activityTag;
6804 					}
6805 					else{
6806 						activityTagsRead.insert(activityTag->name);
6807 						addActivityTagFast(activityTag);
6808 						tmp++;
6809 						xmlReadingLog+="   Activity tag inserted\n";
6810 					}
6811 				}
6812 				else{
6813 					unrecognizedXmlTags.append(xmlReader.name().toString());
6814 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
6815 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
6816 
6817 					xmlReader.skipCurrentElement();
6818 					xmlReaderNumberOfUnrecognizedFields++;
6819 				}
6820 			}
6821 			if(!(tmp==this->activityTagsList.size()))
6822 				xmlReader.raiseError(tr("%1 is incorrect").arg("Subject_Tags_List"));
6823 			else{
6824 				assert(tmp==this->activityTagsList.size());
6825 				xmlReadingLog+="  Added "+CustomFETString::number(tmp)+" activity tags\n";
6826 				reducedXmlLog+="Added "+CustomFETString::number(tmp)+" activity tags\n";
6827 			}
6828 		}
6829 		else if(xmlReader.name()==QString("Activity_Tags_List")){
6830 			QSet<QString> activityTagsRead;
6831 
6832 			int tmp=0;
6833 			assert(xmlReader.isStartElement());
6834 			while(xmlReader.readNextStartElement()){
6835 				xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
6836 				if(xmlReader.name()==QString("Activity_Tag")){
6837 					ActivityTag* activityTag=new ActivityTag();
6838 					assert(xmlReader.isStartElement());
6839 					while(xmlReader.readNextStartElement()){
6840 						xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
6841 						if(xmlReader.name()==QString("Name")){
6842 							QString text=xmlReader.readElementText();
6843 							activityTag->name=text;
6844 							xmlReadingLog+="    Read activity tag name: "+activityTag->name+"\n";
6845 						}
6846 						else if(xmlReader.name()==QString("Printable")){
6847 							QString text=xmlReader.readElementText();
6848 							if(text=="true")
6849 								activityTag->printable=true;
6850 							else
6851 								activityTag->printable=false;
6852 							xmlReadingLog+="    Read activity tag printable="+text+"\n";
6853 						}
6854 						else if(xmlReader.name()==QString("Comments")){
6855 							QString text=xmlReader.readElementText();
6856 							activityTag->comments=text;
6857 							xmlReadingLog+="    Crt. activity tag comments="+activityTag->comments+"\n";
6858 						}
6859 						else{
6860 							unrecognizedXmlTags.append(xmlReader.name().toString());
6861 							unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
6862 							unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
6863 
6864 							xmlReader.skipCurrentElement();
6865 							xmlReaderNumberOfUnrecognizedFields++;
6866 						}
6867 					}
6868 					bool tmp2=activityTagsRead.contains(activityTag->name);
6869 					if(tmp2){
6870 						RulesReconcilableMessage::warning(parent, tr("FET warning"),
6871 						 tr("Duplicate activity tag %1 found - ignoring").arg(activityTag->name));
6872 						xmlReadingLog+="   Activity tag not added - duplicate\n";
6873 
6874 						delete activityTag;
6875 					}
6876 					else{
6877 						activityTagsRead.insert(activityTag->name);
6878 						addActivityTagFast(activityTag);
6879 						tmp++;
6880 						xmlReadingLog+="   Activity tag inserted\n";
6881 					}
6882 				}
6883 				else{
6884 					unrecognizedXmlTags.append(xmlReader.name().toString());
6885 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
6886 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
6887 
6888 					xmlReader.skipCurrentElement();
6889 					xmlReaderNumberOfUnrecognizedFields++;
6890 				}
6891 			}
6892 			if(!(tmp==this->activityTagsList.size()))
6893 				xmlReader.raiseError(tr("%1 is incorrect").arg("Activity_Tags_List"));
6894 			else{
6895 				assert(tmp==this->activityTagsList.size());
6896 				xmlReadingLog+="  Added "+CustomFETString::number(tmp)+" activity tags\n";
6897 				reducedXmlLog+="Added "+CustomFETString::number(tmp)+" activity tags\n";
6898 			}
6899 		}
6900 		else if(xmlReader.name()==QString("Students_List")){
6901 			QSet<StudentsSet*> allAllocatedStudentsSets;
6902 
6903 			bool okStudents=true;
6904 
6905 			//permanentStudentsHash.clear();
6906 
6907 			QHash<QString, StudentsSet*> currentStudentsHash;
6908 
6909 			int tsgr=0;
6910 			int tgr=0;
6911 
6912 			int ny=0;
6913 			assert(xmlReader.isStartElement());
6914 			while(xmlReader.readNextStartElement()){
6915 				xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
6916 				if(xmlReader.name()==QString("Year")){
6917 					StudentsYear* sty=new StudentsYear();
6918 					allAllocatedStudentsSets.insert(sty);
6919 					int ng=0;
6920 
6921 					//sty->divisions.clear();
6922 					//sty->separator="";
6923 					int readCategories=-1;
6924 					int metCategories=0;
6925 
6926 					QSet<QString> groupsInYear;
6927 
6928 					bool tmp2=this->addYearFast(sty);
6929 					assert(tmp2==true);
6930 					ny++;
6931 
6932 					assert(xmlReader.isStartElement());
6933 					while(xmlReader.readNextStartElement()){
6934 						xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
6935 						if(xmlReader.name()==QString("Name")){
6936 							QString text=xmlReader.readElementText();
6937 							if(!skipDuplicatedStudentsSets){
6938 								QString nn=text;
6939 								//StudentsSet* ss=this->searchStudentsSet(nn);
6940 								StudentsSet* ss=currentStudentsHash.value(nn, nullptr);
6941 								if(ss!=nullptr){
6942 									QString str;
6943 
6944 									if(ss->type==STUDENTS_YEAR)
6945 										str=tr("Trying to add year %1, which is already added as another year.").arg(nn);
6946 									else if(ss->type==STUDENTS_GROUP)
6947 										str=tr("Trying to add year %1, which is already added as another group.").arg(nn);
6948 									else if(ss->type==STUDENTS_SUBGROUP)
6949 										str=tr("Trying to add year %1, which is already added as another subgroup.").arg(nn);
6950 
6951 									xmlReader.raiseError(str);
6952 									okStudents=false;
6953 
6954 									//int t=1;
6955 
6956 									/*str=tr("Could not read file - XML parse error at line %1, column %2:\n%3", "The error description is %3")
6957 									 .arg(xmlReader.lineNumber()).arg(xmlReader.columnNumber()).arg(str);
6958 
6959 									int t=RulesIrreconcilableMessage::warning(parent, tr("FET warning"), str,
6960 									 tr("Skip rest"), tr("See next"), QString(),
6961 									 1, 0 );
6962 
6963 									if(okStudents){
6964 										//xmlReader.raiseError(tr("Students structure error(s)."));
6965 										okStudents=false;
6966 									}*/
6967 
6968 									/*if(t==0)
6969 										skipDuplicatedStudentsSets=true;*/
6970 								}
6971 							}
6972 
6973 							sty->name=text;
6974 							if(!currentStudentsHash.contains(sty->name))
6975 								currentStudentsHash.insert(sty->name, sty);
6976 							xmlReadingLog+="    Read year name: "+sty->name+"\n";
6977 						}
6978 						else if(xmlReader.name()==QString("Number_of_Students")){
6979 							QString text=xmlReader.readElementText();
6980 							sty->numberOfStudents=text.toInt();
6981 							xmlReadingLog+="    Read year number of students: "+CustomFETString::number(sty->numberOfStudents)+"\n";
6982 						}
6983 						else if(xmlReader.name()==QString("Comments")){
6984 							QString text=xmlReader.readElementText();
6985 							sty->comments=text;
6986 							xmlReadingLog+="    Crt. year comments="+sty->comments+"\n";
6987 						}
6988 
6989 						//2020-09-03
6990 						else if(xmlReader.name()==QString("Number_of_Categories")){
6991 							QString text=xmlReader.readElementText();
6992 							readCategories=text.toInt();
6993 							xmlReadingLog+="    Read number of categories: "+CustomFETString::number(readCategories)+"\n";
6994 						}
6995 						else if(xmlReader.name()==QString("Category")){
6996 							xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
6997 
6998 							metCategories++;
6999 
7000 							int readDivisions=-1;
7001 							int metDivisions=0;
7002 							QStringList divisionsTL;
7003 
7004 							assert(xmlReader.isStartElement());
7005 							while(xmlReader.readNextStartElement()){
7006 								xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
7007 								if(xmlReader.name()==QString("Number_of_Divisions")){
7008 									QString text=xmlReader.readElementText();
7009 									readDivisions=text.toInt();
7010 									xmlReadingLog+="     Read number of divisions: "+CustomFETString::number(readDivisions)+"\n";
7011 								}
7012 								else if(xmlReader.name()==QString("Division")){
7013 									xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
7014 
7015 									metDivisions++;
7016 
7017 									QString text=xmlReader.readElementText();
7018 									divisionsTL.append(text);
7019 									xmlReadingLog+="     Read new division: "+divisionsTL.last()+"\n";
7020 								}
7021 								else{
7022 									unrecognizedXmlTags.append(xmlReader.name().toString());
7023 									unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
7024 									unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
7025 
7026 									xmlReader.skipCurrentElement();
7027 									xmlReaderNumberOfUnrecognizedFields++;
7028 								}
7029 							}
7030 
7031 							if(readDivisions==-1){
7032 								if(metDivisions==0){
7033 									//ok
7034 								}
7035 								else{
7036 									xmlReader.raiseError(tr("The specified number of divisions was not found, but there were found specified the divisions."));
7037 									okStudents=false;
7038 								}
7039 							}
7040 							else if(readDivisions!=metDivisions){
7041 								xmlReader.raiseError(tr("The specified number of divisions is not equal with the met number of divisions."));
7042 								okStudents=false;
7043 							}
7044 							else{
7045 								sty->divisions.append(divisionsTL);
7046 							}
7047 						}
7048 						else if(xmlReader.name()==QString("Separator")){
7049 							QString text=xmlReader.readElementText();
7050 							sty->separator=text;
7051 							xmlReadingLog+="    Read year separator="+sty->separator+"\n";
7052 						}
7053 
7054 						else if(xmlReader.name()==QString("Group")){
7055 							QSet<StudentsSubgroup*> allocatedSubgroups;
7056 
7057 							StudentsGroup* stg=new StudentsGroup();
7058 							allAllocatedStudentsSets.insert(stg);
7059 							int ns=0;
7060 
7061 							QSet<QString> subgroupsInGroup;
7062 
7063 							/*bool tmp4=this->addGroupFast(sty, stg);
7064 							assert(tmp4==true);
7065 							ng++;*/
7066 
7067 							assert(xmlReader.isStartElement());
7068 							while(xmlReader.readNextStartElement()){
7069 								xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
7070 								if(xmlReader.name()==QString("Name")){
7071 									QString text=xmlReader.readElementText();
7072 									if(!skipDuplicatedStudentsSets){
7073 										QString nn=text;
7074 										StudentsSet* ss=currentStudentsHash.value(nn, nullptr);
7075 										if(ss!=nullptr){
7076 											QString str;
7077 											bool haveError=false;
7078 
7079 											if(ss->type==STUDENTS_YEAR){
7080 												str=tr("Trying to add group %1, which is already added as another year.").arg(nn);
7081 												haveError=true;
7082 											}
7083 											else if(ss->type==STUDENTS_GROUP){
7084 												if(groupsInYear.contains(nn)){
7085 													str=tr("Trying to add group %1 in year %2 but it is already added.").arg(nn).arg(sty->name);
7086 													haveError=true;
7087 												}
7088 												else{
7089 													str="";
7090 													assert(haveError==false);
7091 												}
7092 											}
7093 											else if(ss->type==STUDENTS_SUBGROUP){
7094 												str=tr("Trying to add group %1, which is already added as another subgroup.").arg(nn);
7095 												haveError=true;
7096 											}
7097 
7098 											//int t=1;
7099 											if(haveError){
7100 												xmlReader.raiseError(str);
7101 												okStudents=false;
7102 
7103 												/*str=tr("Could not read file - XML parse error at line %1, column %2:\n%3", "The error description is %3")
7104 												 .arg(xmlReader.lineNumber()).arg(xmlReader.columnNumber()).arg(str);
7105 
7106 												t=RulesIrreconcilableMessage::warning(parent, tr("FET warning"), str,
7107 												 tr("Skip rest"), tr("See next"), QString(),
7108 												 1, 0 );
7109 
7110 												if(okStudents){
7111 													//xmlReader.raiseError(tr("Students structure error(s)."));
7112 													okStudents=false;
7113 												}*/
7114 											}
7115 
7116 											//if(t==0)
7117 											//	skipDuplicatedStudentsSets=true;
7118 										}
7119 									}
7120 
7121 									groupsInYear.insert(text);
7122 
7123 									if(currentStudentsHash.contains(text)){
7124 										for(StudentsSubgroup* sts : qAsConst(allocatedSubgroups)){
7125 											assert(currentStudentsHash.contains(sts->name));
7126 											currentStudentsHash.remove(sts->name);
7127 
7128 											assert(allAllocatedStudentsSets.contains(sts));
7129 											allAllocatedStudentsSets.remove(sts);
7130 											delete sts;
7131 										}
7132 										allocatedSubgroups.clear(); //not really needed
7133 
7134 										assert(allAllocatedStudentsSets.contains(stg));
7135 										allAllocatedStudentsSets.remove(stg);
7136 										delete stg;
7137 
7138 										if(okStudents){
7139 											assert(currentStudentsHash.value(text)->type==STUDENTS_GROUP);
7140 											stg=(StudentsGroup*)(currentStudentsHash.value(text));
7141 
7142 											bool tmp4=this->addGroupFast(sty, stg);
7143 											assert(tmp4==true);
7144 											//ng++;
7145 										}
7146 
7147 										xmlReader.skipCurrentElement();
7148 										break;
7149 									}
7150 
7151 									bool tmp4=this->addGroupFast(sty, stg);
7152 									assert(tmp4==true);
7153 									ng++;
7154 
7155 									stg->name=text;
7156 									if(!currentStudentsHash.contains(stg->name))
7157 										currentStudentsHash.insert(stg->name, stg);
7158 									xmlReadingLog+="     Read group name: "+stg->name+"\n";
7159 								}
7160 								else if(xmlReader.name()==QString("Number_of_Students")){
7161 									QString text=xmlReader.readElementText();
7162 									stg->numberOfStudents=text.toInt();
7163 									xmlReadingLog+="     Read group number of students: "+CustomFETString::number(stg->numberOfStudents)+"\n";
7164 								}
7165 								else if(xmlReader.name()==QString("Comments")){
7166 									QString text=xmlReader.readElementText();
7167 									stg->comments=text;
7168 									xmlReadingLog+="    Crt. group comments="+stg->comments+"\n";
7169 								}
7170 								else if(xmlReader.name()==QString("Subgroup")){
7171 									StudentsSubgroup* sts=new StudentsSubgroup();
7172 									allAllocatedStudentsSets.insert(sts);
7173 
7174 									/*bool tmp6=this->addSubgroupFast(sty, stg, sts);
7175 									assert(tmp6==true);
7176 									ns++;*/
7177 
7178 									assert(xmlReader.isStartElement());
7179 									while(xmlReader.readNextStartElement()){
7180 										xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
7181 										if(xmlReader.name()==QString("Name")){
7182 											QString text=xmlReader.readElementText();
7183 											if(!skipDuplicatedStudentsSets){
7184 												QString nn=text;
7185 												StudentsSet* ss=currentStudentsHash.value(nn, nullptr);
7186 												if(ss!=nullptr){
7187 													QString str;
7188 													bool haveError=false;
7189 
7190 													if(ss->type==STUDENTS_YEAR){
7191 														str=tr("Trying to add subgroup %1, which is already added as another year.").arg(nn);
7192 														haveError=true;
7193 													}
7194 													else if(ss->type==STUDENTS_GROUP){
7195 														str=tr("Trying to add subgroup %1, which is already added as another group.").arg(nn);
7196 														haveError=true;
7197 													}
7198 													else if(ss->type==STUDENTS_SUBGROUP){
7199 														if(subgroupsInGroup.contains(nn)){
7200 															str=tr("Trying to add subgroup %1 in year %2, group %3 but it is already added.").arg(nn).arg(sty->name).arg(stg->name);
7201 															haveError=true;
7202 														}
7203 														else{
7204 															str="";
7205 															assert(haveError==false);
7206 														}
7207 													}
7208 
7209 													//int t=1;
7210 													if(haveError){
7211 														xmlReader.raiseError(str);
7212 														okStudents=false;
7213 
7214 														/*str=tr("Could not read file - XML parse error at line %1, column %2:\n%3", "The error description is %3")
7215 														 .arg(xmlReader.lineNumber()).arg(xmlReader.columnNumber()).arg(str);
7216 
7217 														t=RulesIrreconcilableMessage::warning(parent, tr("FET warning"), str,
7218 														 tr("Skip rest"), tr("See next"), QString(),
7219 														 1, 0 );
7220 
7221 														if(okStudents){
7222 															//xmlReader.raiseError(tr("Students structure error(s)."));
7223 															okStudents=false;
7224 														}*/
7225 													}
7226 
7227 													//if(t==0)
7228 													//	skipDuplicatedStudentsSets=true;
7229 												}
7230 											}
7231 
7232 											subgroupsInGroup.insert(text);
7233 
7234 											if(currentStudentsHash.contains(text)){
7235 												assert(allAllocatedStudentsSets.contains(sts));
7236 												allAllocatedStudentsSets.remove(sts);
7237 												delete sts;
7238 
7239 												if(okStudents){
7240 													assert(currentStudentsHash.value(text)->type==STUDENTS_SUBGROUP);
7241 													sts=(StudentsSubgroup*)(currentStudentsHash.value(text));
7242 
7243 													bool tmp6=this->addSubgroupFast(sty, stg, sts);
7244 													assert(tmp6==true);
7245 													//ns++;
7246 												}
7247 
7248 												xmlReader.skipCurrentElement();
7249 												break;
7250 											}
7251 											else{
7252 												allocatedSubgroups.insert(sts);
7253 											}
7254 
7255 											bool tmp6=this->addSubgroupFast(sty, stg, sts);
7256 											assert(tmp6==true);
7257 											ns++;
7258 
7259 											sts->name=text;
7260 											if(!currentStudentsHash.contains(sts->name))
7261 												currentStudentsHash.insert(sts->name, sts);
7262 											xmlReadingLog+="     Read subgroup name: "+sts->name+"\n";
7263 										}
7264 										else if(xmlReader.name()==QString("Number_of_Students")){
7265 											QString text=xmlReader.readElementText();
7266 											sts->numberOfStudents=text.toInt();
7267 											xmlReadingLog+="     Read subgroup number of students: "+CustomFETString::number(sts->numberOfStudents)+"\n";
7268 										}
7269 										else if(xmlReader.name()==QString("Comments")){
7270 											QString text=xmlReader.readElementText();
7271 											sts->comments=text;
7272 											xmlReadingLog+="    Crt. subgroup comments="+sts->comments+"\n";
7273 										}
7274 										else{
7275 											unrecognizedXmlTags.append(xmlReader.name().toString());
7276 											unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
7277 											unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
7278 
7279 											xmlReader.skipCurrentElement();
7280 											xmlReaderNumberOfUnrecognizedFields++;
7281 										}
7282 									}
7283 								}
7284 								else{
7285 									unrecognizedXmlTags.append(xmlReader.name().toString());
7286 									unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
7287 									unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
7288 
7289 									xmlReader.skipCurrentElement();
7290 									xmlReaderNumberOfUnrecognizedFields++;
7291 								}
7292 							}
7293 							if(ns == stg->subgroupsList.size()){
7294 								xmlReadingLog+="    Added "+CustomFETString::number(ns)+" subgroups\n";
7295 								tsgr+=ns;
7296 								//reducedXmlLog+="		Added "+CustomFETString::number(ns)+" subgroups\n";
7297 							}
7298 						}
7299 						else{
7300 							unrecognizedXmlTags.append(xmlReader.name().toString());
7301 							unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
7302 							unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
7303 
7304 							xmlReader.skipCurrentElement();
7305 							xmlReaderNumberOfUnrecognizedFields++;
7306 						}
7307 					}
7308 					if(ng == sty->groupsList.size()){
7309 						xmlReadingLog+="   Added "+CustomFETString::number(ng)+" groups\n";
7310 						tgr+=ng;
7311 						//reducedXmlLog+="	Added "+CustomFETString::number(ng)+" groups\n";
7312 					}
7313 
7314 					if(readCategories==-1){
7315 						if(metCategories==0){
7316 							//ok
7317 						}
7318 						else{
7319 							xmlReader.raiseError(tr("The specified number of categories was not found, but there were found specified the categories."));
7320 							okStudents=false;
7321 						}
7322 					}
7323 					else if(readCategories!=metCategories){
7324 						xmlReader.raiseError(tr("The specified number of categories is not equal with the met number of categories."));
7325 						okStudents=false;
7326 					}
7327 					else{
7328 						//ok
7329 					}
7330 				}
7331 				else{
7332 					unrecognizedXmlTags.append(xmlReader.name().toString());
7333 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
7334 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
7335 
7336 					xmlReader.skipCurrentElement();
7337 					xmlReaderNumberOfUnrecognizedFields++;
7338 				}
7339 			}
7340 			xmlReadingLog+="  Added "+CustomFETString::number(ny)+" years\n";
7341 			reducedXmlLog+="Added "+CustomFETString::number(ny)+" students years\n";
7342 			//reducedXmlLog+="Added "+CustomFETString::number(tgr)+" students groups (see note below)\n";
7343 			reducedXmlLog+="Added "+CustomFETString::number(tgr)+" students groups\n";
7344 			//reducedXmlLog+="Added "+CustomFETString::number(tsgr)+" students subgroups (see note below)\n";
7345 			reducedXmlLog+="Added "+CustomFETString::number(tsgr)+" students subgroups\n";
7346 			assert(this->yearsList.size()==ny);
7347 
7348 			if(okStudents){
7349 				//This is redundant, but I make this an additional test, just in case anything was wrong.
7350 				computePermanentStudentsHash();
7351 				assert(permanentStudentsHash==currentStudentsHash);
7352 			}
7353 			else{
7354 				for(StudentsSet* studentsSet : qAsConst(allAllocatedStudentsSets))
7355 					delete studentsSet;
7356 				yearsList.clear();
7357 			}
7358 		}
7359 		else if(xmlReader.name()==QString("Activities_List")){
7360 			QSet<QString> allTeachers;
7361 			QHash<QString, int> studentsSetsCount;
7362 			QSet<QString> allSubjects;
7363 			QSet<QString> allActivityTags;
7364 
7365 			for(Teacher* tch : qAsConst(this->teachersList))
7366 				allTeachers.insert(tch->name);
7367 
7368 			for(Subject* sbj : qAsConst(this->subjectsList))
7369 				allSubjects.insert(sbj->name);
7370 
7371 			for(ActivityTag* at : qAsConst(this->activityTagsList))
7372 				allActivityTags.insert(at->name);
7373 
7374 			for(StudentsYear* year : qAsConst(this->yearsList)){
7375 				if(!studentsSetsCount.contains(year->name))
7376 					studentsSetsCount.insert(year->name, year->numberOfStudents);
7377 				else if(studentsSetsCount.value(year->name)!=year->numberOfStudents){
7378 					//cout<<"Mistake: year "<<qPrintable(year->name)<<" appears in more places with different number of students"<<endl;
7379 				}
7380 
7381 				for(StudentsGroup* group : qAsConst(year->groupsList)){
7382 					if(!studentsSetsCount.contains(group->name))
7383 						studentsSetsCount.insert(group->name, group->numberOfStudents);
7384 					else if(studentsSetsCount.value(group->name)!=group->numberOfStudents){
7385 						//cout<<"Mistake: group "<<qPrintable(group->name)<<" appears in more places with different number of students"<<endl;
7386 					}
7387 
7388 					for(StudentsSubgroup* subgroup : qAsConst(group->subgroupsList)){
7389 						if(!studentsSetsCount.contains(subgroup->name))
7390 							studentsSetsCount.insert(subgroup->name, subgroup->numberOfStudents);
7391 						else if(studentsSetsCount.value(subgroup->name)!=subgroup->numberOfStudents){
7392 							//cout<<"Mistake: subgroup "<<qPrintable(subgroup->name)<<" appears in more places with different number of students"<<endl;
7393 						}
7394 					}
7395 				}
7396 			}
7397 
7398 			//int nchildrennodes=elem2.childNodes().length();
7399 
7400 			/*QProgressDialog progress(parent);
7401 			progress.setLabelText(tr("Loading activities ... please wait"));
7402 			progress.setRange(0, nchildrennodes);
7403 			progress.setModal(true);*/
7404 			//progress.setCancelButton(parent);
7405 
7406 			//int ttt=0;
7407 
7408 			int na=0;
7409 			assert(xmlReader.isStartElement());
7410 			while(xmlReader.readNextStartElement()){
7411 
7412 				/*progress.setValue(ttt);
7413 				pqapplication->processEvents();
7414 				if(progress.wasCanceled()){
7415 					QMessageBox::information(parent, tr("FET information"), tr("Interrupted - only partial file was loaded"));
7416 					return true;
7417 				}
7418 
7419 				ttt++;*/
7420 
7421 				xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
7422 				if(xmlReader.name()==QString("Activity")){
7423 					bool correct=true;
7424 
7425 					QString cm=QString(""); //comments
7426 					QString tn="";
7427 					QStringList tl;
7428 					QString sjn="";
7429 					QString atn="";
7430 					QStringList atl;
7431 					QString stn="";
7432 					QStringList stl;
7433 					//int p=PARITY_NOT_INITIALIZED;
7434 					int td=-1;
7435 					int d=-1;
7436 					int id=-1;
7437 					int gid=-1;
7438 					bool ac=true;
7439 					int nos=-1;
7440 					bool cnos=true;
7441 
7442 					QSet<QString> _teachersSet;
7443 					QSet<QString> _studentsSet;
7444 					QSet<QString> _activityTagsSet;
7445 					int _duplicateTeachersCount=0;
7446 					int _duplicateStudentsCount=0;
7447 					int _duplicateActivityTagsCount=0;
7448 
7449 					assert(xmlReader.isStartElement());
7450 					while(xmlReader.readNextStartElement()){
7451 						xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
7452 						if(xmlReader.name()==QString("Weekly")){
7453 							xmlReader.skipCurrentElement();
7454 							xmlReadingLog+="    Current activity is weekly - ignoring tag\n";
7455 							//assert(p==PARITY_NOT_INITIALIZED);
7456 							//p=PARITY_WEEKLY;
7457 						}
7458 						//old tag
7459 						else if(xmlReader.name()==QString("Biweekly")){
7460 							xmlReader.skipCurrentElement();
7461 							xmlReadingLog+="    Current activity is fortnightly - ignoring tag\n";
7462 							//assert(p==PARITY_NOT_INITIALIZED);
7463 							//p=PARITY_FORTNIGHTLY;
7464 						}
7465 						else if(xmlReader.name()==QString("Fortnightly")){
7466 							xmlReader.skipCurrentElement();
7467 							xmlReadingLog+="    Current activity is fortnightly - ignoring tag\n";
7468 							//assert(p==PARITY_NOT_INITIALIZED);
7469 							//p=PARITY_FORTNIGHTLY;
7470 						}
7471 						else if(xmlReader.name()==QString("Active")){
7472 							QString text=xmlReader.readElementText();
7473 							if(text=="yes" || text=="true" || text=="1"){
7474 								ac=true;
7475 								xmlReadingLog+="	Current activity is active\n";
7476 							}
7477 							else{
7478 								if(!(text=="no" || text=="false" || text=="0")){
7479 									RulesReconcilableMessage::warning(parent, tr("FET warning"),
7480 									 tr("Found activity active tag which is not 'true', 'false', 'yes', 'no', '1' or '0'."
7481 									 " The activity will be considered not active",
7482 									 "Instructions for translators: please leave the 'true', 'false', 'yes' and 'no' fields untranslated, as they are in English"));
7483 								}
7484 								//assert(text=="no" || text=="false" || text=="0");
7485 								ac=false;
7486 								xmlReadingLog+="	Current activity is not active\n";
7487 							}
7488 						}
7489 						else if(xmlReader.name()==QString("Comments")){
7490 							QString text=xmlReader.readElementText();
7491 							cm=text;
7492 							xmlReadingLog+="    Crt. activity comments="+cm+"\n";
7493 						}
7494 						else if(xmlReader.name()==QString("Teacher")){
7495 							QString text=xmlReader.readElementText();
7496 							tn=text;
7497 							xmlReadingLog+="    Crt. activity teacher="+tn+"\n";
7498 
7499 							if(_teachersSet.contains(tn))
7500 								_duplicateTeachersCount++;
7501 							else
7502 								_teachersSet.insert(tn);
7503 
7504 							tl.append(tn);
7505 							if(!allTeachers.contains(tn))
7506 							//if(this->searchTeacher(tn)<0)
7507 								correct=false;
7508 						}
7509 						else if(xmlReader.name()==QString("Subject")){
7510 							QString text=xmlReader.readElementText();
7511 							sjn=text;
7512 							xmlReadingLog+="    Crt. activity subject="+sjn+"\n";
7513 							if(!allSubjects.contains(sjn))
7514 							//if(this->searchSubject(sjn)<0)
7515 								correct=false;
7516 						}
7517 						else if(xmlReader.name()==QString("Subject_Tag")){
7518 							QString text=xmlReader.readElementText();
7519 							atn=text;
7520 							xmlReadingLog+="    Crt. activity activity_tag="+atn+"\n";
7521 
7522 							if(_activityTagsSet.contains(atn))
7523 								_duplicateActivityTagsCount++;
7524 							else
7525 								_activityTagsSet.insert(atn);
7526 
7527 
7528 							if(atn!="")
7529 								atl.append(atn);
7530 							if(atn!="" && !allActivityTags.contains(atn))
7531 							//if(atn!="" && this->searchActivityTag(atn)<0)
7532 								correct=false;
7533 						}
7534 						else if(xmlReader.name()==QString("Activity_Tag")){
7535 							QString text=xmlReader.readElementText();
7536 							atn=text;
7537 							xmlReadingLog+="    Crt. activity activity_tag="+atn+"\n";
7538 
7539 							if(_activityTagsSet.contains(atn))
7540 								_duplicateActivityTagsCount++;
7541 							else
7542 								_activityTagsSet.insert(atn);
7543 
7544 							if(atn!="")
7545 								atl.append(atn);
7546 							if(atn!="" && !allActivityTags.contains(atn))
7547 							//if(atn!="" && this->searchActivityTag(atn)<0)
7548 								correct=false;
7549 						}
7550 						else if(xmlReader.name()==QString("Students")){
7551 							QString text=xmlReader.readElementText();
7552 							stn=text;
7553 							xmlReadingLog+="    Crt. activity students+="+stn+"\n";
7554 
7555 							if(_studentsSet.contains(stn))
7556 								_duplicateStudentsCount++;
7557 							else
7558 								_studentsSet.insert(stn);
7559 
7560 							stl.append(stn);
7561 							if(!studentsSetsCount.contains(stn))
7562 							//if(this->searchStudentsSet(stn)==nullptr)
7563 								correct=false;
7564 						}
7565 						else if(xmlReader.name()==QString("Duration")){
7566 							QString text=xmlReader.readElementText();
7567 							d=text.toInt();
7568 							xmlReadingLog+="    Crt. activity duration="+CustomFETString::number(d)+"\n";
7569 						}
7570 						else if(xmlReader.name()==QString("Total_Duration")){
7571 							QString text=xmlReader.readElementText();
7572 							td=text.toInt();
7573 							xmlReadingLog+="    Crt. activity total duration="+CustomFETString::number(td)+"\n";
7574 						}
7575 						else if(xmlReader.name()==QString("Id")){
7576 							QString text=xmlReader.readElementText();
7577 							id=text.toInt();
7578 							xmlReadingLog+="    Crt. activity id="+CustomFETString::number(id)+"\n";
7579 						}
7580 						else if(xmlReader.name()==QString("Activity_Group_Id")){
7581 							QString text=xmlReader.readElementText();
7582 							gid=text.toInt();
7583 							xmlReadingLog+="    Crt. activity group id="+CustomFETString::number(gid)+"\n";
7584 						}
7585 						else if(xmlReader.name()==QString("Number_Of_Students")){
7586 							QString text=xmlReader.readElementText();
7587 							cnos=false;
7588 							nos=text.toInt();
7589 							xmlReadingLog+="    Crt. activity number of students="+CustomFETString::number(nos)+"\n";
7590 						}
7591 						else{
7592 							unrecognizedXmlTags.append(xmlReader.name().toString());
7593 							unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
7594 							unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
7595 
7596 							xmlReader.skipCurrentElement();
7597 							xmlReaderNumberOfUnrecognizedFields++;
7598 						}
7599 					}
7600 					if(id<0)
7601 						xmlReader.raiseError(tr("%1 is incorrect").arg("Id"));
7602 					else if(activitiesPointerHash.contains(id))
7603 						xmlReader.raiseError(tr("%1 is incorrect (already existing)").arg("Id")); //duplicate Id
7604 					else if(gid<0)
7605 						xmlReader.raiseError(tr("%1 is incorrect").arg("Activity_Group_Id"));
7606 					else if(d<=0)
7607 						xmlReader.raiseError(tr("%1 is incorrect").arg("Duration"));
7608 					else if(_duplicateTeachersCount>0)
7609 						xmlReader.raiseError(tr("Activity with Id=%1 contains %2 duplicate teachers - please correct that").arg(id).arg(_duplicateTeachersCount));
7610 					else if(_duplicateStudentsCount>0)
7611 						xmlReader.raiseError(tr("Activity with Id=%1 contains %2 duplicate students sets - please correct that").arg(id).arg(_duplicateStudentsCount));
7612 					else if(_duplicateActivityTagsCount>0)
7613 						xmlReader.raiseError(tr("Activity with Id=%1 contains %2 duplicate activity tags - please correct that").arg(id).arg(_duplicateActivityTagsCount));
7614 					else if(correct){
7615 						assert(id>=0 && gid>=0);
7616 						assert(d>0);
7617 						if(td<0)
7618 							td=d;
7619 
7620 						if(cnos==true){
7621 							assert(nos==-1);
7622 							int _ns=0;
7623 							for(const QString& _s : qAsConst(stl)){
7624 								assert(studentsSetsCount.contains(_s));
7625 								_ns+=studentsSetsCount.value(_s);
7626 							}
7627 							this->addSimpleActivityFast(parent, id, gid, tl, sjn, atl, stl,
7628 								d, td, ac, cnos, nos, _ns);
7629 						}
7630 						else{
7631 							this->addSimpleActivityFast(parent, id, gid, tl, sjn, atl, stl,
7632 								d, td, ac, cnos, nos, nos);
7633 						}
7634 
7635 						this->activitiesList[this->activitiesList.count()-1]->comments=cm;
7636 
7637 						na++;
7638 						xmlReadingLog+="   Added the activity\n";
7639 					}
7640 					else{
7641 						xmlReader.raiseError(tr("The activity with id=%1 contains incorrect data").arg(id));
7642 						/*xmlReadingLog+="   Activity with id ="+CustomFETString::number(id)+" contains invalid data - skipping\n";
7643 						RulesReconcilableMessage::warning(parent, tr("FET information"),
7644 						 tr("Activity with id=%1 contains invalid data - skipping").arg(id));*/
7645 					}
7646 				}
7647 				else{
7648 					unrecognizedXmlTags.append(xmlReader.name().toString());
7649 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
7650 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
7651 
7652 					xmlReader.skipCurrentElement();
7653 					xmlReaderNumberOfUnrecognizedFields++;
7654 				}
7655 			}
7656 			xmlReadingLog+="  Added "+CustomFETString::number(na)+" activities\n";
7657 			reducedXmlLog+="Added "+CustomFETString::number(na)+" activities\n";
7658 		}
7659 		else if(xmlReader.name()==QString("Equipments_List")){
7660 			RulesReconcilableMessage::warning(parent, tr("FET warning"),
7661 			 tr("File contains deprecated equipments list - will be ignored"));
7662 			xmlReader.skipCurrentElement();
7663 			//NOT! xmlReaderNumberOfUnrecognizedFields++; because this entry was once allowed
7664 		}
7665 		else if(xmlReader.name()==QString("Buildings_List")){
7666 			QSet<QString> buildingsRead;
7667 
7668 			int tmp=0;
7669 			assert(xmlReader.isStartElement());
7670 			while(xmlReader.readNextStartElement()){
7671 				xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
7672 				if(xmlReader.name()==QString("Building")){
7673 					Building* bu=new Building();
7674 					bu->name="";
7675 
7676 					assert(xmlReader.isStartElement());
7677 					while(xmlReader.readNextStartElement()){
7678 						xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
7679 						if(xmlReader.name()==QString("Name")){
7680 							QString text=xmlReader.readElementText();
7681 							bu->name=text;
7682 							xmlReadingLog+="    Read building name: "+bu->name+"\n";
7683 						}
7684 						else if(xmlReader.name()==QString("Comments")){
7685 							QString text=xmlReader.readElementText();
7686 							bu->comments=text;
7687 							xmlReadingLog+="    Crt. building comments="+bu->comments+"\n";
7688 						}
7689 						else{
7690 							unrecognizedXmlTags.append(xmlReader.name().toString());
7691 							unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
7692 							unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
7693 
7694 							xmlReader.skipCurrentElement();
7695 							xmlReaderNumberOfUnrecognizedFields++;
7696 						}
7697 					}
7698 
7699 					bool tmp2=buildingsRead.contains(bu->name);
7700 					if(tmp2){
7701 						RulesReconcilableMessage::warning(parent, tr("FET warning"),
7702 						 tr("Duplicate building %1 found - ignoring").arg(bu->name));
7703 						xmlReadingLog+="   Building not added - duplicate\n";
7704 
7705 						delete bu;
7706 					}
7707 					else{
7708 						buildingsRead.insert(bu->name);
7709 						addBuildingFast(bu);
7710 						tmp++;
7711 						xmlReadingLog+="   Building inserted\n";
7712 					}
7713 				}
7714 				else{
7715 					unrecognizedXmlTags.append(xmlReader.name().toString());
7716 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
7717 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
7718 
7719 					xmlReader.skipCurrentElement();
7720 					xmlReaderNumberOfUnrecognizedFields++;
7721 				}
7722 			}
7723 			if(!(tmp==this->buildingsList.size()))
7724 				xmlReader.raiseError(tr("%1 is incorrect").arg("Buildings_List"));
7725 			else{
7726 				assert(tmp==this->buildingsList.size());
7727 				xmlReadingLog+="  Added "+CustomFETString::number(tmp)+" buildings\n";
7728 				reducedXmlLog+="Added "+CustomFETString::number(tmp)+" buildings\n";
7729 			}
7730 		}
7731 		else if(xmlReader.name()==QString("Rooms_List")){
7732 			QSet<QString> roomsRead;
7733 
7734 			int tmp=0;
7735 			assert(xmlReader.isStartElement());
7736 			while(xmlReader.readNextStartElement()){
7737 				xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
7738 				if(xmlReader.name()==QString("Room")){
7739 					Room* rm=new Room();
7740 					rm->name="";
7741 					rm->capacity=MAX_ROOM_CAPACITY; //infinite, if not specified
7742 					rm->building="";
7743 					rm->isVirtual=false;
7744 					rm->realRoomsSetsList.clear();
7745 					int specifiedNumberOfSetsOfRooms=-1;
7746 					int metNumberOfSetsOfRooms=0;
7747 					bool correct=true;
7748 					assert(xmlReader.isStartElement());
7749 					while(xmlReader.readNextStartElement()){
7750 						xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
7751 						if(xmlReader.name()==QString("Name")){
7752 							QString text=xmlReader.readElementText();
7753 							rm->name=text;
7754 							xmlReadingLog+="    Read room name: "+rm->name+"\n";
7755 						}
7756 						else if(xmlReader.name()==QString("Type")){
7757 							//rm->type=text;
7758 							xmlReader.skipCurrentElement();
7759 							xmlReadingLog+="    Ignoring old tag room type:\n";
7760 						}
7761 						else if(xmlReader.name()==QString("Capacity")){
7762 							QString text=xmlReader.readElementText();
7763 							rm->capacity=text.toInt();
7764 							xmlReadingLog+="    Read room capacity: "+CustomFETString::number(rm->capacity)+"\n";
7765 						}
7766 						else if(xmlReader.name()==QString("Virtual")){
7767 							QString text=xmlReader.readElementText();
7768 							if(text=="true"){
7769 								rm->isVirtual=true;
7770 							}
7771 						}
7772 						else if(xmlReader.name()==QString("Number_of_Sets_of_Real_Rooms")){
7773 							QString text=xmlReader.readElementText();
7774 							specifiedNumberOfSetsOfRooms=text.toInt();
7775 						}
7776 						else if(xmlReader.name()==QString("Set_of_Real_Rooms")){
7777 							metNumberOfSetsOfRooms++;
7778 
7779 							QStringList rl;
7780 
7781 							int metNumberOfRooms=0;
7782 							int specifiedNumberOfRooms=-1;
7783 							assert(xmlReader.isStartElement());
7784 							while(xmlReader.readNextStartElement()){
7785 								if(xmlReader.name()==QString("Number_of_Real_Rooms")){
7786 									QString text=xmlReader.readElementText();
7787 									specifiedNumberOfRooms=text.toInt();
7788 								}
7789 								else if(xmlReader.name()==QString("Real_Room")){
7790 									metNumberOfRooms++;
7791 									QString text=xmlReader.readElementText();
7792 									rl.append(text);
7793 								}
7794 								else{
7795 									unrecognizedXmlTags.append(xmlReader.name().toString());
7796 									unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
7797 									unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
7798 
7799 									xmlReader.skipCurrentElement();
7800 									xmlReaderNumberOfUnrecognizedFields++;
7801 								}
7802 							}
7803 
7804 							if(specifiedNumberOfRooms==-1){
7805 								xmlReader.raiseError(tr("The specified number of real rooms was not found in the input file"
7806 								 " for the virtual room %1, for the set of real rooms number %2").arg(rm->name).arg(metNumberOfSetsOfRooms));
7807 								correct=false;
7808 							}
7809 							else if(metNumberOfRooms!=specifiedNumberOfRooms){
7810 								xmlReader.raiseError(tr("The specified number of real rooms is not equal with the met number of real rooms"
7811 								 " for the virtual room %1").arg(rm->name));
7812 								correct=false;
7813 							}
7814 							else{
7815 								rm->realRoomsSetsList.append(rl);
7816 							}
7817 						}
7818 						else if(xmlReader.name()==QString("Equipment")){
7819 							//rm->addEquipment(text);
7820 							xmlReader.skipCurrentElement();
7821 							xmlReadingLog+="    Ignoring old tag - room equipment:\n";
7822 						}
7823 						else if(xmlReader.name()==QString("Building")){
7824 							QString text=xmlReader.readElementText();
7825 							rm->building=text;
7826 							xmlReadingLog+="    Read room building:\n"+rm->building;
7827 						}
7828 						else if(xmlReader.name()==QString("Comments")){
7829 							QString text=xmlReader.readElementText();
7830 							rm->comments=text;
7831 							xmlReadingLog+="    Crt. room comments="+rm->comments+"\n";
7832 						}
7833 						else{
7834 							unrecognizedXmlTags.append(xmlReader.name().toString());
7835 							unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
7836 							unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
7837 
7838 							xmlReader.skipCurrentElement();
7839 							xmlReaderNumberOfUnrecognizedFields++;
7840 						}
7841 					}
7842 
7843 					if(!correct)
7844 						delete rm;
7845 
7846 					if(correct){
7847 						if(rm->isVirtual){
7848 							if(specifiedNumberOfSetsOfRooms==-1){
7849 								xmlReader.raiseError(tr("The specified number of sets of real rooms was not found in the input file"
7850 								 " for the virtual room %1").arg(rm->name));
7851 								correct=false;
7852 
7853 								delete rm;
7854 							}
7855 							else if(metNumberOfSetsOfRooms!=specifiedNumberOfSetsOfRooms){
7856 								xmlReader.raiseError(tr("The specified number of sets of real rooms is not equal with the met number of sets of real rooms"
7857 								 " for the virtual room %1").arg(rm->name));
7858 								correct=false;
7859 
7860 								delete rm;
7861 							}
7862 						}
7863 					}
7864 
7865 					if(correct){
7866 						bool tmp2=roomsRead.contains(rm->name);
7867 						if(tmp2){
7868 							RulesReconcilableMessage::warning(parent, tr("FET warning"),
7869 							 tr("Duplicate room %1 found - ignoring").arg(rm->name));
7870 							xmlReadingLog+="   Room not added - duplicate\n";
7871 
7872 							delete rm;
7873 						}
7874 						else{
7875 							roomsRead.insert(rm->name);
7876 							addRoomFast(rm);
7877 							tmp++;
7878 							xmlReadingLog+="   Room inserted\n";
7879 						}
7880 					}
7881 				}
7882 				else{
7883 					unrecognizedXmlTags.append(xmlReader.name().toString());
7884 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
7885 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
7886 
7887 					xmlReader.skipCurrentElement();
7888 					xmlReaderNumberOfUnrecognizedFields++;
7889 				}
7890 			}
7891 			if(!(tmp==this->roomsList.size()))
7892 				xmlReader.raiseError(tr("%1 is incorrect").arg("Rooms_List"));
7893 			else{
7894 				assert(tmp==this->roomsList.size());
7895 				xmlReadingLog+="  Added "+CustomFETString::number(tmp)+" rooms\n";
7896 				reducedXmlLog+="Added "+CustomFETString::number(tmp)+" rooms\n";
7897 			}
7898 		}
7899 		else if(xmlReader.name()==QString("Time_Constraints_List")){
7900 			bool reportMaxBeginningsAtSecondHourChange=true;
7901 			bool reportMaxGapsChange=true;
7902 			bool reportStudentsSetNotAvailableChange=true;
7903 			bool reportTeacherNotAvailableChange=true;
7904 			bool reportBreakChange=true;
7905 
7906 			bool reportActivityPreferredTimeChange=true;
7907 
7908 			bool reportActivityPreferredTimesChange=true;
7909 			bool reportActivitiesPreferredTimesChange=true;
7910 
7911 			bool reportUnspecifiedPermanentlyLockedTime=true;
7912 
7913 			bool reportUnspecifiedDayOrHourPreferredStartingTime=true;
7914 
7915 			bool reportMA5OldTimeConstraintsChange=true;
7916 
7917 #if 0
7918 			bool reportIncorrectMinDays=true;
7919 #endif
7920 
7921 			bool seeNextWarnNotAddedTimeConstraint=true;
7922 
7923 			int nc=0;
7924 			TimeConstraint *crt_constraint;
7925 			assert(xmlReader.isStartElement());
7926 
7927 			while(xmlReader.readNextStartElement()){
7928 				xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
7929 				crt_constraint=nullptr;
7930 				if(xmlReader.name()==QString("ConstraintBasicCompulsoryTime")){
7931 					crt_constraint=readBasicCompulsoryTime(xmlReader, xmlReadingLog);
7932 				}
7933 				else if(xmlReader.name()==QString("ConstraintTeacherNotAvailable")){
7934 					if(reportTeacherNotAvailableChange){
7935 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
7936 						 tr("File contains constraint teacher not available, which is old (it was improved in FET 5.5.0), and will be converted"
7937 						 " to the similar constraint of this type, constraint teacher not available times (a matrix)."),
7938 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
7939 						if(t==0)
7940 							reportTeacherNotAvailableChange=false;
7941 					}
7942 
7943 					crt_constraint=readTeacherNotAvailable(xmlReader, xmlReadingLog);
7944 				}
7945 				else if(xmlReader.name()==QString("ConstraintTeacherNotAvailableTimes")){
7946 					crt_constraint=readTeacherNotAvailableTimes(xmlReader, xmlReadingLog);
7947 				}
7948 				else if((version6AndAbove || (!probably5Morocco && !probably5Algeria && !probably5MA))
7949 				 && xmlReader.name()==QString("ConstraintTeacherMaxDaysPerWeek")){
7950 					crt_constraint=readTeacherMaxDaysPerWeek(xmlReader, xmlReadingLog);
7951 				}
7952 				else if((version6AndAbove || (!probably5Morocco && !probably5Algeria && !probably5MA))
7953 				 && xmlReader.name()==QString("ConstraintTeachersMaxDaysPerWeek")){
7954 					crt_constraint=readTeachersMaxDaysPerWeek(xmlReader, xmlReadingLog);
7955 				}
7956 
7957 				else if((version6AndAbove || (!probably5Morocco && !probably5Algeria && !probably5MA))
7958 				 && xmlReader.name()==QString("ConstraintTeacherMinDaysPerWeek")){
7959 					crt_constraint=readTeacherMinDaysPerWeek(xmlReader, xmlReadingLog);
7960 				}
7961 				else if((version6AndAbove || (!probably5Morocco && !probably5Algeria && !probably5MA))
7962 				 && xmlReader.name()==QString("ConstraintTeachersMinDaysPerWeek")){
7963 					crt_constraint=readTeachersMinDaysPerWeek(xmlReader, xmlReadingLog);
7964 				}
7965 
7966 				else if(xmlReader.name()==QString("ConstraintTeacherIntervalMaxDaysPerWeek")){
7967 					crt_constraint=readTeacherIntervalMaxDaysPerWeek(parent, xmlReader, xmlReadingLog);
7968 				}
7969 				else if(xmlReader.name()==QString("ConstraintTeachersIntervalMaxDaysPerWeek")){
7970 					crt_constraint=readTeachersIntervalMaxDaysPerWeek(parent, xmlReader, xmlReadingLog);
7971 				}
7972 				else if((version6AndAbove || (!probably5Morocco && !probably5Algeria && !probably5MA))
7973 				 && xmlReader.name()==QString("ConstraintStudentsSetMaxDaysPerWeek")){
7974 					crt_constraint=readStudentsSetMaxDaysPerWeek(parent, xmlReader, xmlReadingLog);
7975 				}
7976 				else if((version6AndAbove || (!probably5Morocco && !probably5Algeria && !probably5MA))
7977 				 && xmlReader.name()==QString("ConstraintStudentsMaxDaysPerWeek")){
7978 					crt_constraint=readStudentsMaxDaysPerWeek(parent, xmlReader, xmlReadingLog);
7979 				}
7980 				else if(xmlReader.name()==QString("ConstraintStudentsSetIntervalMaxDaysPerWeek")){
7981 					crt_constraint=readStudentsSetIntervalMaxDaysPerWeek(parent, xmlReader, xmlReadingLog);
7982 				}
7983 				else if(xmlReader.name()==QString("ConstraintStudentsIntervalMaxDaysPerWeek")){
7984 					crt_constraint=readStudentsIntervalMaxDaysPerWeek(parent, xmlReader, xmlReadingLog);
7985 				}
7986 				else if(xmlReader.name()==QString("ConstraintStudentsSetNotAvailable")){
7987 					if(reportStudentsSetNotAvailableChange){
7988 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
7989 						 tr("File contains constraint students set not available, which is old (it was improved in FET 5.5.0), and will be converted"
7990 						 " to the similar constraint of this type, constraint students set not available times (a matrix)."),
7991 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
7992 						if(t==0)
7993 							reportStudentsSetNotAvailableChange=false;
7994 					}
7995 
7996 					crt_constraint=readStudentsSetNotAvailable(xmlReader, xmlReadingLog);
7997 				}
7998 				else if(xmlReader.name()==QString("ConstraintStudentsSetNotAvailableTimes")){
7999 					crt_constraint=readStudentsSetNotAvailableTimes(xmlReader, xmlReadingLog);
8000 				}
8001 				else if(xmlReader.name()==QString("ConstraintMinNDaysBetweenActivities")){
8002 					crt_constraint=readMinNDaysBetweenActivities(parent, xmlReader, xmlReadingLog);
8003 				}
8004 				else if(xmlReader.name()==QString("ConstraintMinDaysBetweenActivities")){
8005 					crt_constraint=readMinDaysBetweenActivities(parent, xmlReader, xmlReadingLog);
8006 				}
8007 				else if(xmlReader.name()==QString("ConstraintMaxDaysBetweenActivities")){
8008 					crt_constraint=readMaxDaysBetweenActivities(xmlReader, xmlReadingLog);
8009 				}
8010 				else if(xmlReader.name()==QString("ConstraintMinGapsBetweenActivities")){
8011 					crt_constraint=readMinGapsBetweenActivities(xmlReader, xmlReadingLog);
8012 				}
8013 				else if(xmlReader.name()==QString("ConstraintMaxGapsBetweenActivities")){
8014 					crt_constraint=readMaxGapsBetweenActivities(xmlReader, xmlReadingLog);
8015 				}
8016 				else if(xmlReader.name()==QString("ConstraintActivitiesNotOverlapping")){
8017 					crt_constraint=readActivitiesNotOverlapping(xmlReader, xmlReadingLog);
8018 				}
8019 				else if(xmlReader.name()==QString("ConstraintActivityTagsNotOverlapping")){
8020 					crt_constraint=readActivityTagsNotOverlapping(xmlReader, xmlReadingLog);
8021 				}
8022 				else if(xmlReader.name()==QString("ConstraintActivitiesSameStartingTime")){
8023 					crt_constraint=readActivitiesSameStartingTime(xmlReader, xmlReadingLog);
8024 				}
8025 				else if(xmlReader.name()==QString("ConstraintActivitiesSameStartingHour")){
8026 					crt_constraint=readActivitiesSameStartingHour(xmlReader, xmlReadingLog);
8027 				}
8028 				else if(xmlReader.name()==QString("ConstraintActivitiesSameStartingDay")){
8029 					crt_constraint=readActivitiesSameStartingDay(xmlReader, xmlReadingLog);
8030 				}
8031 				else if((version6AndAbove || (!probably5Morocco && !probably5Algeria && !probably5MA))
8032 				 && xmlReader.name()==QString("ConstraintTeachersMaxHoursDaily")){
8033 					crt_constraint=readTeachersMaxHoursDaily(xmlReader, xmlReadingLog);
8034 				}
8035 				else if((version6AndAbove || (!probably5Morocco && !probably5Algeria && !probably5MA))
8036 				 && xmlReader.name()==QString("ConstraintTeacherMaxHoursDaily")){
8037 					crt_constraint=readTeacherMaxHoursDaily(xmlReader, xmlReadingLog);
8038 				}
8039 				else if(xmlReader.name()==QString("ConstraintTeachersMaxHoursContinuously")){
8040 					crt_constraint=readTeachersMaxHoursContinuously(xmlReader, xmlReadingLog);
8041 				}
8042 				else if(xmlReader.name()==QString("ConstraintTeacherMaxHoursContinuously")){
8043 					crt_constraint=readTeacherMaxHoursContinuously(xmlReader, xmlReadingLog);
8044 				}
8045 				else if(xmlReader.name()==QString("ConstraintTeacherActivityTagMaxHoursContinuously")){
8046 					crt_constraint=readTeacherActivityTagMaxHoursContinuously(xmlReader, xmlReadingLog);
8047 				}
8048 				else if(xmlReader.name()==QString("ConstraintTeachersActivityTagMaxHoursContinuously")){
8049 					crt_constraint=readTeachersActivityTagMaxHoursContinuously(xmlReader, xmlReadingLog);
8050 				}
8051 
8052 				else if((version6AndAbove || (!probably5Morocco && !probably5Algeria && !probably5MA))
8053 				 && xmlReader.name()==QString("ConstraintTeacherActivityTagMaxHoursDaily")){
8054 					crt_constraint=readTeacherActivityTagMaxHoursDaily(xmlReader, xmlReadingLog);
8055 				}
8056 				else if((version6AndAbove || (!probably5Morocco && !probably5Algeria && !probably5MA))
8057 				 && xmlReader.name()==QString("ConstraintTeachersActivityTagMaxHoursDaily")){
8058 					crt_constraint=readTeachersActivityTagMaxHoursDaily(xmlReader, xmlReadingLog);
8059 				}
8060 
8061 				else if(xmlReader.name()==QString("ConstraintTeacherActivityTagMinHoursDaily")){
8062 					crt_constraint=readTeacherActivityTagMinHoursDaily(xmlReader, xmlReadingLog);
8063 				}
8064 				else if(xmlReader.name()==QString("ConstraintTeachersActivityTagMinHoursDaily")){
8065 					crt_constraint=readTeachersActivityTagMinHoursDaily(xmlReader, xmlReadingLog);
8066 				}
8067 
8068 				else if(xmlReader.name()==QString("ConstraintTeachersMinHoursDaily")){
8069 					crt_constraint=readTeachersMinHoursDaily(parent, xmlReader, xmlReadingLog);
8070 				}
8071 				else if(xmlReader.name()==QString("ConstraintTeacherMinHoursDaily")){
8072 					crt_constraint=readTeacherMinHoursDaily(parent, xmlReader, xmlReadingLog);
8073 				}
8074 				else if((xmlReader.name()==QString("ConstraintTeachersSubgroupsMaxHoursDaily")
8075 				 //TODO: erase the line below. It is only kept for compatibility with older versions
8076 				 || xmlReader.name()==QString("ConstraintTeachersSubgroupsNoMoreThanXHoursDaily")) && !skipDeprecatedConstraints){
8077 					int t=RulesReconcilableMessage::warning(parent, tr("FET warning"),
8078 					 tr("File contains deprecated constraint teachers subgroups max hours daily - will be ignored"),
8079 					 tr("Skip rest"), tr("See next"), QString(),
8080 					 1, 0 );
8081 
8082 					if(t==0)
8083 						skipDeprecatedConstraints=true;
8084 					crt_constraint=nullptr;
8085 					xmlReader.skipCurrentElement();
8086 				}
8087 				else if(xmlReader.name()==QString("ConstraintStudentsNHoursDaily") && !skipDeprecatedConstraints){
8088 					int t=RulesReconcilableMessage::warning(parent, tr("FET warning"),
8089 					 tr("File contains deprecated constraint students n hours daily - will be ignored"),
8090 					 tr("Skip rest"), tr("See next"), QString(),
8091 					 1, 0 );
8092 
8093 					if(t==0)
8094 						skipDeprecatedConstraints=true;
8095 					crt_constraint=nullptr;
8096 					xmlReader.skipCurrentElement();
8097 				}
8098 				else if(xmlReader.name()==QString("ConstraintStudentsSetNHoursDaily") && !skipDeprecatedConstraints){
8099 					int t=RulesReconcilableMessage::warning(parent, tr("FET warning"),
8100 					 tr("File contains deprecated constraint students set n hours daily - will be ignored"),
8101 					 tr("Skip rest"), tr("See next"), QString(),
8102 					 1, 0 );
8103 
8104 					if(t==0)
8105 						skipDeprecatedConstraints=true;
8106 					crt_constraint=nullptr;
8107 					xmlReader.skipCurrentElement();
8108 				}
8109 				else if((version6AndAbove || (!probably5Morocco && !probably5Algeria && !probably5MA))
8110 				 && xmlReader.name()==QString("ConstraintStudentsMaxHoursDaily")){
8111 					crt_constraint=readStudentsMaxHoursDaily(xmlReader, xmlReadingLog);
8112 				}
8113 				else if((version6AndAbove || (!probably5Morocco && !probably5Algeria && !probably5MA))
8114 				 && xmlReader.name()==QString("ConstraintStudentsSetMaxHoursDaily")){
8115 					crt_constraint=readStudentsSetMaxHoursDaily(xmlReader, xmlReadingLog);
8116 				}
8117 				else if(xmlReader.name()==QString("ConstraintStudentsMaxHoursContinuously")){
8118 					crt_constraint=readStudentsMaxHoursContinuously(xmlReader, xmlReadingLog);
8119 				}
8120 				else if(xmlReader.name()==QString("ConstraintStudentsSetMaxHoursContinuously")){
8121 					crt_constraint=readStudentsSetMaxHoursContinuously(xmlReader, xmlReadingLog);
8122 				}
8123 				else if(xmlReader.name()==QString("ConstraintStudentsSetActivityTagMaxHoursContinuously")){
8124 					crt_constraint=readStudentsSetActivityTagMaxHoursContinuously(xmlReader, xmlReadingLog);
8125 				}
8126 				else if(xmlReader.name()==QString("ConstraintStudentsActivityTagMaxHoursContinuously")){
8127 					crt_constraint=readStudentsActivityTagMaxHoursContinuously(xmlReader, xmlReadingLog);
8128 				}
8129 
8130 				else if((version6AndAbove || (!probably5Morocco && !probably5Algeria && !probably5MA))
8131 				 && xmlReader.name()==QString("ConstraintStudentsSetActivityTagMaxHoursDaily")){
8132 					crt_constraint=readStudentsSetActivityTagMaxHoursDaily(xmlReader, xmlReadingLog);
8133 				}
8134 				else if((version6AndAbove || (!probably5Morocco && !probably5Algeria && !probably5MA))
8135 				 && xmlReader.name()==QString("ConstraintStudentsActivityTagMaxHoursDaily")){
8136 					crt_constraint=readStudentsActivityTagMaxHoursDaily(xmlReader, xmlReadingLog);
8137 				}
8138 
8139 				else if(xmlReader.name()==QString("ConstraintStudentsSetActivityTagMinHoursDaily")){
8140 					crt_constraint=readStudentsSetActivityTagMinHoursDaily(xmlReader, xmlReadingLog);
8141 				}
8142 				else if(xmlReader.name()==QString("ConstraintStudentsActivityTagMinHoursDaily")){
8143 					crt_constraint=readStudentsActivityTagMinHoursDaily(xmlReader, xmlReadingLog);
8144 				}
8145 
8146 				else if(xmlReader.name()==QString("ConstraintStudentsMinHoursDaily")){
8147 					crt_constraint=readStudentsMinHoursDaily(parent, xmlReader, xmlReadingLog);
8148 				}
8149 				else if(xmlReader.name()==QString("ConstraintStudentsSetMinHoursDaily")){
8150 					crt_constraint=readStudentsSetMinHoursDaily(parent, xmlReader, xmlReadingLog);
8151 				}
8152 				else if(xmlReader.name()==QString("ConstraintStudentsSetMinGapsBetweenOrderedPairOfActivityTags")){
8153 					crt_constraint=readStudentsSetMinGapsBetweenOrderedPairOfActivityTags(xmlReader, xmlReadingLog);
8154 				}
8155 				else if(xmlReader.name()==QString("ConstraintStudentsMinGapsBetweenOrderedPairOfActivityTags")){
8156 					crt_constraint=readStudentsMinGapsBetweenOrderedPairOfActivityTags(xmlReader, xmlReadingLog);
8157 				}
8158 				else if(xmlReader.name()==QString("ConstraintTeacherMinGapsBetweenOrderedPairOfActivityTags")){
8159 					crt_constraint=readTeacherMinGapsBetweenOrderedPairOfActivityTags(xmlReader, xmlReadingLog);
8160 				}
8161 				else if(xmlReader.name()==QString("ConstraintTeachersMinGapsBetweenOrderedPairOfActivityTags")){
8162 					crt_constraint=readTeachersMinGapsBetweenOrderedPairOfActivityTags(xmlReader, xmlReadingLog);
8163 				}
8164 				else if(xmlReader.name()==QString("ConstraintActivityPreferredTime")){
8165 					if(reportActivityPreferredTimeChange){
8166 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8167 						 tr("File contains old constraint type activity preferred time, which will be converted"
8168 						 " to the newer similar constraint of this type, constraint activity preferred STARTING time."
8169 						 " This improvement is done in versions 5.5.9 and above"),
8170 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8171 						if(t==0)
8172 							reportActivityPreferredTimeChange=false;
8173 					}
8174 
8175 					crt_constraint=readActivityPreferredTime(parent, xmlReader, xmlReadingLog,
8176 						reportUnspecifiedPermanentlyLockedTime, reportUnspecifiedDayOrHourPreferredStartingTime);
8177 				}
8178 
8179 				else if(xmlReader.name()==QString("ConstraintActivityPreferredStartingTime")){
8180 					crt_constraint=readActivityPreferredStartingTime(parent, xmlReader, xmlReadingLog,
8181 						reportUnspecifiedPermanentlyLockedTime, reportUnspecifiedDayOrHourPreferredStartingTime);
8182 				}
8183 				else if(xmlReader.name()==QString("ConstraintActivityEndsStudentsDay")){
8184 					crt_constraint=readActivityEndsStudentsDay(xmlReader, xmlReadingLog);
8185 				}
8186 				else if(xmlReader.name()==QString("ConstraintActivitiesEndStudentsDay")){
8187 					crt_constraint=readActivitiesEndStudentsDay(xmlReader, xmlReadingLog);
8188 				}
8189 				else if(xmlReader.name()==QString("ConstraintActivityEndsTeachersDay")){
8190 					crt_constraint=readActivityEndsTeachersDay(xmlReader, xmlReadingLog);
8191 				}
8192 				else if(xmlReader.name()==QString("ConstraintActivitiesEndTeachersDay")){
8193 					crt_constraint=readActivitiesEndTeachersDay(xmlReader, xmlReadingLog);
8194 				}
8195 				//old, with 2 and 3
8196 				else if(xmlReader.name()==QString("Constraint2ActivitiesConsecutive")){
8197 					crt_constraint=read2ActivitiesConsecutive(xmlReader, xmlReadingLog);
8198 				}
8199 				else if(xmlReader.name()==QString("Constraint2ActivitiesGrouped")){
8200 					crt_constraint=read2ActivitiesGrouped(xmlReader, xmlReadingLog);
8201 				}
8202 				else if(xmlReader.name()==QString("Constraint3ActivitiesGrouped")){
8203 					crt_constraint=read3ActivitiesGrouped(xmlReader, xmlReadingLog);
8204 				}
8205 				else if(xmlReader.name()==QString("Constraint2ActivitiesOrdered")){
8206 					crt_constraint=read2ActivitiesOrdered(xmlReader, xmlReadingLog);
8207 				}
8208 				//end old
8209 				else if(xmlReader.name()==QString("ConstraintTwoActivitiesConsecutive")){
8210 					crt_constraint=readTwoActivitiesConsecutive(xmlReader, xmlReadingLog);
8211 				}
8212 				else if(xmlReader.name()==QString("ConstraintTwoActivitiesGrouped")){
8213 					crt_constraint=readTwoActivitiesGrouped(xmlReader, xmlReadingLog);
8214 				}
8215 				else if(xmlReader.name()==QString("ConstraintThreeActivitiesGrouped")){
8216 					crt_constraint=readThreeActivitiesGrouped(xmlReader, xmlReadingLog);
8217 				}
8218 				else if(xmlReader.name()==QString("ConstraintTwoActivitiesOrdered")){
8219 					crt_constraint=readTwoActivitiesOrdered(xmlReader, xmlReadingLog);
8220 				}
8221 				else if(xmlReader.name()==QString("ConstraintTwoSetsOfActivitiesOrdered")){
8222 					crt_constraint=readTwoSetsOfActivitiesOrdered(xmlReader, xmlReadingLog);
8223 				}
8224 				else if(xmlReader.name()==QString("ConstraintTwoActivitiesOrderedIfSameDay")){
8225 					crt_constraint=readTwoActivitiesOrderedIfSameDay(xmlReader, xmlReadingLog);
8226 				}
8227 				else if(xmlReader.name()==QString("ConstraintActivityEndsDay") && !skipDeprecatedConstraints ){
8228 					int t=RulesReconcilableMessage::warning(parent, tr("FET warning"),
8229 					 tr("File contains deprecated constraint activity ends day - will be ignored"),
8230 					 tr("Skip rest"), tr("See next"), QString(),
8231 					 1, 0 );
8232 
8233 					if(t==0)
8234 						skipDeprecatedConstraints=true;
8235 					crt_constraint=nullptr;
8236 					xmlReader.skipCurrentElement();
8237 				}
8238 				else if(xmlReader.name()==QString("ConstraintActivityPreferredTimes")){
8239 					if(reportActivityPreferredTimesChange){
8240 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8241 						 tr("Your file contains old constraint activity preferred times, which will be converted to"
8242 						 " new equivalent constraint activity preferred starting times. Beginning with FET-5.5.9 it is possible"
8243 						 " to specify: 1. the starting times of an activity (constraint activity preferred starting times)"
8244 						 " or: 2. the accepted time slots (constraint activity preferred time slots)."
8245 						 " If what you need is type 2 of this constraint, you will have to add it by yourself from the interface."),
8246 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8247 						if(t==0)
8248 							reportActivityPreferredTimesChange=false;
8249 					}
8250 
8251 					crt_constraint=readActivityPreferredTimes(xmlReader, xmlReadingLog);
8252 				}
8253 				else if(xmlReader.name()==QString("ConstraintActivityPreferredTimeSlots")){
8254 					crt_constraint=readActivityPreferredTimeSlots(xmlReader, xmlReadingLog);
8255 				}
8256 				else if(xmlReader.name()==QString("ConstraintActivityPreferredStartingTimes")){
8257 					crt_constraint=readActivityPreferredStartingTimes(xmlReader, xmlReadingLog);
8258 				}
8259 				else if(xmlReader.name()==QString("ConstraintBreak")){
8260 					if(reportBreakChange){
8261 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8262 						 tr("File contains constraint break, which is old (it was improved in FET 5.5.0), and will be converted"
8263 						 " to the similar constraint of this type, constraint break times (a matrix)."),
8264 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8265 						if(t==0)
8266 							reportBreakChange=false;
8267 					}
8268 
8269 					crt_constraint=readBreak(xmlReader, xmlReadingLog);
8270 				}
8271 				else if(xmlReader.name()==QString("ConstraintBreakTimes")){
8272 					crt_constraint=readBreakTimes(xmlReader, xmlReadingLog);
8273 				}
8274 				else if(xmlReader.name()==QString("ConstraintTeachersNoGaps")){
8275 					crt_constraint=readTeachersNoGaps(xmlReader, xmlReadingLog);
8276 				}
8277 				else if(xmlReader.name()==QString("ConstraintTeachersMaxGapsPerWeek")){
8278 					crt_constraint=readTeachersMaxGapsPerWeek(xmlReader, xmlReadingLog);
8279 				}
8280 				else if(xmlReader.name()==QString("ConstraintTeacherMaxGapsPerWeek")){
8281 					crt_constraint=readTeacherMaxGapsPerWeek(xmlReader, xmlReadingLog);
8282 				}
8283 				else if(xmlReader.name()==QString("ConstraintTeachersMaxGapsPerDay")){
8284 					crt_constraint=readTeachersMaxGapsPerDay(xmlReader, xmlReadingLog);
8285 				}
8286 				else if(xmlReader.name()==QString("ConstraintTeacherMaxGapsPerDay")){
8287 					crt_constraint=readTeacherMaxGapsPerDay(xmlReader, xmlReadingLog);
8288 				}
8289 				else if(xmlReader.name()==QString("ConstraintTeachersMaxGapsPerMorningAndAfternoon")){
8290 					crt_constraint=readTeachersMaxGapsPerMorningAndAfternoon(xmlReader, xmlReadingLog);
8291 				}
8292 				else if(xmlReader.name()==QString("ConstraintTeacherMaxGapsPerMorningAndAfternoon")){
8293 					crt_constraint=readTeacherMaxGapsPerMorningAndAfternoon(xmlReader, xmlReadingLog);
8294 				}
8295 				else if(xmlReader.name()==QString("ConstraintStudentsNoGaps")){
8296 					if(reportMaxGapsChange){
8297 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8298 						 tr("File contains constraint students no gaps, which is old (it was improved in FET 5.5.0), and will be converted"
8299 						 " to the similar constraint of this type, constraint students max gaps per week,"
8300 						 " with max gaps=0. If you like, you can modify this constraint to allow"
8301 						 " more gaps per week (normally not accepted in schools)"),
8302 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8303 						if(t==0)
8304 							reportMaxGapsChange=false;
8305 					}
8306 
8307 					crt_constraint=readStudentsNoGaps(xmlReader, xmlReadingLog);
8308 				}
8309 				else if(xmlReader.name()==QString("ConstraintStudentsSetNoGaps")){
8310 					if(reportMaxGapsChange){
8311 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8312 						 tr("File contains constraint students set no gaps, which is old (it was improved in FET 5.5.0), and will be converted"
8313 						 " to the similar constraint of this type, constraint students set max gaps per week,"
8314 						 " with max gaps=0. If you like, you can modify this constraint to allow"
8315 						 " more gaps per week (normally not accepted in schools)"),
8316 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8317 						if(t==0)
8318 							reportMaxGapsChange=false;
8319 					}
8320 
8321 					crt_constraint=readStudentsSetNoGaps(xmlReader, xmlReadingLog);
8322 				}
8323 				else if(xmlReader.name()==QString("ConstraintStudentsMaxGapsPerWeek")){
8324 					crt_constraint=readStudentsMaxGapsPerWeek(xmlReader, xmlReadingLog);
8325 				}
8326 				else if(xmlReader.name()==QString("ConstraintStudentsSetMaxGapsPerWeek")){
8327 					crt_constraint=readStudentsSetMaxGapsPerWeek(xmlReader, xmlReadingLog);
8328 				}
8329 
8330 				else if(xmlReader.name()==QString("ConstraintStudentsMaxGapsPerDay")){
8331 					crt_constraint=readStudentsMaxGapsPerDay(xmlReader, xmlReadingLog);
8332 				}
8333 				else if(xmlReader.name()==QString("ConstraintStudentsSetMaxGapsPerDay")){
8334 					crt_constraint=readStudentsSetMaxGapsPerDay(xmlReader, xmlReadingLog);
8335 				}
8336 
8337 				else if(xmlReader.name()==QString("ConstraintStudentsEarly")){
8338 					if(reportMaxBeginningsAtSecondHourChange){
8339 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8340 						 tr("File contains constraint students early, which is old (it was improved in FET 5.5.0), and will be converted"
8341 						 " to the similar constraint of this type, constraint students early max beginnings at second hour,"
8342 						 " with max beginnings=0. If you like, you can modify this constraint to allow"
8343 						 " more beginnings at second available hour (above 0 - this will make the timetable easier)"),
8344 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8345  						if(t==0)
8346 							reportMaxBeginningsAtSecondHourChange=false;
8347 					}
8348 
8349 					crt_constraint=readStudentsEarly(xmlReader, xmlReadingLog);
8350 				}
8351 				else if(xmlReader.name()==QString("ConstraintStudentsEarlyMaxBeginningsAtSecondHour")){
8352 					crt_constraint=readStudentsEarlyMaxBeginningsAtSecondHour(xmlReader, xmlReadingLog);
8353 				}
8354 				else if(xmlReader.name()==QString("ConstraintStudentsSetEarly")){
8355 					if(reportMaxBeginningsAtSecondHourChange){
8356 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8357 						 tr("File contains constraint students set early, which is old (it was improved in FET 5.5.0), and will be converted"
8358 						 " to the similar constraint of this type, constraint students set early max beginnings at second hour,"
8359 						 " with max beginnings=0. If you like, you can modify this constraint to allow"
8360 						 " more beginnings at second available hour (above 0 - this will make the timetable easier)"),
8361 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8362 						if(t==0)
8363 							reportMaxBeginningsAtSecondHourChange=false;
8364 					}
8365 
8366 					crt_constraint=readStudentsSetEarly(xmlReader, xmlReadingLog);
8367 				}
8368 				else if(xmlReader.name()==QString("ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour")){
8369 					crt_constraint=readStudentsSetEarlyMaxBeginningsAtSecondHour(xmlReader, xmlReadingLog);
8370 				}
8371 				else if(xmlReader.name()==QString("ConstraintActivitiesPreferredTimes")){
8372 					if(reportActivitiesPreferredTimesChange){
8373 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8374 						 tr("Your file contains old constraint activities preferred times, which will be converted to"
8375 						 " new equivalent constraint activities preferred starting times. Beginning with FET-5.5.9 it is possible"
8376 						 " to specify: 1. the starting times of several activities (constraint activities preferred starting times)"
8377 						 " or: 2. the accepted time slots (constraint activities preferred time slots)."
8378 						 " If what you need is type 2 of this constraint, you will have to add it by yourself from the interface."),
8379 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8380 						if(t==0)
8381 							reportActivitiesPreferredTimesChange=false;
8382 					}
8383 
8384 					crt_constraint=readActivitiesPreferredTimes(xmlReader, xmlReadingLog);
8385 				}
8386 				else if(xmlReader.name()==QString("ConstraintActivitiesPreferredTimeSlots")){
8387 					crt_constraint=readActivitiesPreferredTimeSlots(xmlReader, xmlReadingLog);
8388 				}
8389 				else if(xmlReader.name()==QString("ConstraintActivitiesPreferredStartingTimes")){
8390 					crt_constraint=readActivitiesPreferredStartingTimes(xmlReader, xmlReadingLog);
8391 				}
8392 ////////////////
8393 				else if(xmlReader.name()==QString("ConstraintSubactivitiesPreferredTimeSlots")){
8394 					crt_constraint=readSubactivitiesPreferredTimeSlots(xmlReader, xmlReadingLog);
8395 				}
8396 				else if(xmlReader.name()==QString("ConstraintSubactivitiesPreferredStartingTimes")){
8397 					crt_constraint=readSubactivitiesPreferredStartingTimes(xmlReader, xmlReadingLog);
8398 				}
8399 ////////////////2011-09-25
8400 				else if(xmlReader.name()==QString("ConstraintActivitiesOccupyMaxTimeSlotsFromSelection")){
8401 					crt_constraint=readActivitiesOccupyMaxTimeSlotsFromSelection(xmlReader, xmlReadingLog);
8402 				}
8403 ////////////////
8404 ////////////////2019-11-16
8405 				else if(xmlReader.name()==QString("ConstraintActivitiesOccupyMinTimeSlotsFromSelection")){
8406 					crt_constraint=readActivitiesOccupyMinTimeSlotsFromSelection(xmlReader, xmlReadingLog);
8407 				}
8408 ////////////////
8409 ////////////////2011-09-30
8410 				else if(xmlReader.name()==QString("ConstraintActivitiesMaxSimultaneousInSelectedTimeSlots")){
8411 					crt_constraint=readActivitiesMaxSimultaneousInSelectedTimeSlots(xmlReader, xmlReadingLog);
8412 				}
8413 ////////////////
8414 ////////////////2019-11-16
8415 				else if(xmlReader.name()==QString("ConstraintActivitiesMinSimultaneousInSelectedTimeSlots")){
8416 					crt_constraint=readActivitiesMinSimultaneousInSelectedTimeSlots(xmlReader, xmlReadingLog);
8417 				}
8418 ////////////////
8419 ////////////////2020-05-02
8420 				else if(xmlReader.name()==QString("ConstraintMaxTotalActivitiesFromSetInSelectedTimeSlots")){
8421 					crt_constraint=readMaxTotalActivitiesFromSetInSelectedTimeSlots(xmlReader, xmlReadingLog);
8422 				}
8423 ////////////////
8424 ////////////////2020-01-14
8425 				else if(xmlReader.name()==QString("ConstraintActivitiesMaxInATerm")){
8426 					crt_constraint=readActivitiesMaxInATerm(xmlReader, xmlReadingLog);
8427 				}
8428 ////////////////
8429 ////////////////2020-01-14
8430 				else if(xmlReader.name()==QString("ConstraintActivitiesOccupyMaxTerms")){
8431 					crt_constraint=readActivitiesOccupyMaxTerms(xmlReader, xmlReadingLog);
8432 				}
8433 ////////////////
8434 
8435 				else if(xmlReader.name()==QString("ConstraintTeachersSubjectTagsMaxHoursContinuously") && !skipDeprecatedConstraints){
8436 					int t=RulesReconcilableMessage::warning(parent, tr("FET warning"),
8437 					 tr("File contains deprecated constraint teachers subject tags max hours continuously - will be ignored"),
8438 					 tr("Skip rest"), tr("See next"), QString(),
8439 					 1, 0 );
8440 
8441 					if(t==0)
8442 						skipDeprecatedConstraints=true;
8443 					crt_constraint=nullptr;
8444 					xmlReader.skipCurrentElement();
8445 				}
8446 				else if(xmlReader.name()==QString("ConstraintTeachersSubjectTagMaxHoursContinuously") && !skipDeprecatedConstraints){
8447 					int t=RulesReconcilableMessage::warning(parent, tr("FET warning"),
8448 					 tr("File contains deprecated constraint teachers subject tag max hours continuously - will be ignored"),
8449 					 tr("Skip rest"), tr("See next"), QString(),
8450 					 1, 0 );
8451 
8452 					if(t==0)
8453 						skipDeprecatedConstraints=true;
8454 					crt_constraint=nullptr;
8455 					xmlReader.skipCurrentElement();
8456 				}
8457 				/////////begin 2017-02-07
8458 				else if((version6AndAbove || (!probably5Morocco && !probably5Algeria && !probably5MA))
8459 				 && xmlReader.name()==QString("ConstraintTeacherMaxSpanPerDay")){
8460 					crt_constraint=readTeacherMaxSpanPerDay(xmlReader, xmlReadingLog);
8461 				}
8462 				else if((version6AndAbove || (!probably5Morocco && !probably5Algeria && !probably5MA))
8463 				 && xmlReader.name()==QString("ConstraintTeachersMaxSpanPerDay")){
8464 					crt_constraint=readTeachersMaxSpanPerDay(xmlReader, xmlReadingLog);
8465 				}
8466 				else if((version6AndAbove || (!probably5Morocco && !probably5Algeria && !probably5MA))
8467 				 && xmlReader.name()==QString("ConstraintStudentsSetMaxSpanPerDay")){
8468 					crt_constraint=readStudentsSetMaxSpanPerDay(xmlReader, xmlReadingLog);
8469 				}
8470 				else if((version6AndAbove || (!probably5Morocco && !probably5Algeria && !probably5MA))
8471 				 && xmlReader.name()==QString("ConstraintStudentsMaxSpanPerDay")){
8472 					crt_constraint=readStudentsMaxSpanPerDay(xmlReader, xmlReadingLog);
8473 				}
8474 				else if(xmlReader.name()==QString("ConstraintTeacherMinRestingHours")){
8475 					crt_constraint=readTeacherMinRestingHours(xmlReader, xmlReadingLog);
8476 				}
8477 				else if(xmlReader.name()==QString("ConstraintTeachersMinRestingHours")){
8478 					crt_constraint=readTeachersMinRestingHours(xmlReader, xmlReadingLog);
8479 				}
8480 				else if(xmlReader.name()==QString("ConstraintStudentsSetMinRestingHours")){
8481 					crt_constraint=readStudentsSetMinRestingHours(xmlReader, xmlReadingLog);
8482 				}
8483 				else if(xmlReader.name()==QString("ConstraintStudentsMinRestingHours")){
8484 					crt_constraint=readStudentsMinRestingHours(xmlReader, xmlReadingLog);
8485 				}
8486 
8487 				/////////  end 2017-02-07
8488 				//mornings-afternoons
8489 
8490 				else if((!version6AndAbove && (probably5Morocco || probably5Algeria || probably5MA))
8491 				 && xmlReader.name()==QString("ConstraintTeacherMaxDaysPerWeek")){
8492 					if(reportMA5OldTimeConstraintsChange){
8493 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8494 						  tr("Your file was detected as an old FET-5 MA, Morocco, or Algeria file, and"
8495 						  " contains a constraint of type teacher max days per week, which will be converted"
8496 						  " to a constraint of type teacher max real days per week."),
8497 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8498 						if(t==0)
8499 							reportMA5OldTimeConstraintsChange=false;
8500 					}
8501 					crt_constraint=readOldMATeacherMaxDaysPerWeek(xmlReader, xmlReadingLog);
8502 				}
8503 				else if(xmlReader.name()==QString("ConstraintTeacherMaxRealDaysPerWeek")){
8504 					crt_constraint=readTeacherMaxRealDaysPerWeek(xmlReader, xmlReadingLog);
8505 				}
8506 
8507 				else if((!version6AndAbove && (probably5Morocco || probably5Algeria || probably5MA))
8508 				 && xmlReader.name()==QString("ConstraintTeachersMaxDaysPerWeek")){
8509 					if(reportMA5OldTimeConstraintsChange){
8510 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8511 						  tr("Your file was detected as an old FET-5 MA, Morocco, or Algeria file, and"
8512 						  " contains a constraint of type teachers max days per week, which will be converted"
8513 						  " to a constraint of type teachers max real days per week."),
8514 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8515 						if(t==0)
8516 							reportMA5OldTimeConstraintsChange=false;
8517 					}
8518 					crt_constraint=readOldMATeachersMaxDaysPerWeek(xmlReader, xmlReadingLog);
8519 				}
8520 				else if(xmlReader.name()==QString("ConstraintTeachersMaxRealDaysPerWeek")){
8521 					crt_constraint=readTeachersMaxRealDaysPerWeek(xmlReader, xmlReadingLog);
8522 				}
8523 
8524 				else if(xmlReader.name()==QString("ConstraintTeacherMaxAfternoonsPerWeek")){
8525 					crt_constraint=readTeacherMaxAfternoonsPerWeek(xmlReader, xmlReadingLog);
8526 				}
8527 				else if(xmlReader.name()==QString("ConstraintTeachersMaxAfternoonsPerWeek")){
8528 					crt_constraint=readTeachersMaxAfternoonsPerWeek(xmlReader, xmlReadingLog);
8529 				}
8530 
8531 				else if(xmlReader.name()==QString("ConstraintTeacherMaxTwoActivityTagsPerDayFromN1N2N3")){
8532 					crt_constraint=readTeacherMaxTwoActivityTagsPerDayFromN1N2N3(xmlReader, xmlReadingLog);
8533 				}
8534 				else if(xmlReader.name()==QString("ConstraintTeachersMaxTwoActivityTagsPerDayFromN1N2N3")){
8535 					crt_constraint=readTeachersMaxTwoActivityTagsPerDayFromN1N2N3(xmlReader, xmlReadingLog);
8536 				}
8537 
8538 				else if(xmlReader.name()==QString("ConstraintTeacherMaxMorningsPerWeek")){
8539 					crt_constraint=readTeacherMaxMorningsPerWeek(xmlReader, xmlReadingLog);
8540 				}
8541 				else if(xmlReader.name()==QString("ConstraintTeachersMaxMorningsPerWeek")){
8542 					crt_constraint=readTeachersMaxMorningsPerWeek(xmlReader, xmlReadingLog);
8543 				}
8544 
8545 				else if(xmlReader.name()==QString("ConstraintTeacherMaxTwoConsecutiveMornings")){
8546 					crt_constraint=readTeacherMaxTwoConsecutiveMornings(xmlReader, xmlReadingLog);
8547 				}
8548 				else if(xmlReader.name()==QString("ConstraintTeachersMaxTwoConsecutiveMornings")){
8549 					crt_constraint=readTeachersMaxTwoConsecutiveMornings(xmlReader, xmlReadingLog);
8550 				}
8551 				else if(xmlReader.name()==QString("ConstraintTeacherMaxTwoConsecutiveAfternoons")){
8552 					crt_constraint=readTeacherMaxTwoConsecutiveAfternoons(xmlReader, xmlReadingLog);
8553 				}
8554 				else if(xmlReader.name()==QString("ConstraintTeachersMaxTwoConsecutiveAfternoons")){
8555 					crt_constraint=readTeachersMaxTwoConsecutiveAfternoons(xmlReader, xmlReadingLog);
8556 				}
8557 
8558 				else if((!version6AndAbove && (probably5Morocco || probably5Algeria || probably5MA))
8559 				 && xmlReader.name()==QString("ConstraintTeacherMinDaysPerWeek")){
8560 					if(reportMA5OldTimeConstraintsChange){
8561 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8562 						  tr("Your file was detected as an old FET-5 MA, Morocco, or Algeria file, and"
8563 						  " contains a constraint of type teacher min days per week, which will be converted"
8564 						  " to a constraint of type teacher min real days per week."),
8565 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8566 						if(t==0)
8567 							reportMA5OldTimeConstraintsChange=false;
8568 					}
8569 					crt_constraint=readOldMATeacherMinDaysPerWeek(xmlReader, xmlReadingLog);
8570 				}
8571 				else if(xmlReader.name()==QString("ConstraintTeacherMinRealDaysPerWeek")){
8572 					crt_constraint=readTeacherMinRealDaysPerWeek(xmlReader, xmlReadingLog);
8573 				}
8574 
8575 				else if((!version6AndAbove && (probably5Morocco || probably5Algeria || probably5MA))
8576 				 && xmlReader.name()==QString("ConstraintTeachersMinDaysPerWeek")){
8577 					if(reportMA5OldTimeConstraintsChange){
8578 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8579 						  tr("Your file was detected as an old FET-5 MA, Morocco, or Algeria file, and"
8580 						  " contains a constraint of type teachers min days per week, which will be converted"
8581 						  " to a constraint of type teachers min real days per week."),
8582 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8583 						if(t==0)
8584 							reportMA5OldTimeConstraintsChange=false;
8585 					}
8586 					crt_constraint=readOldMATeachersMinDaysPerWeek(xmlReader, xmlReadingLog);
8587 				}
8588 				else if(xmlReader.name()==QString("ConstraintTeachersMinRealDaysPerWeek")){
8589 					crt_constraint=readTeachersMinRealDaysPerWeek(xmlReader, xmlReadingLog);
8590 				}
8591 
8592 				else if(xmlReader.name()==QString("ConstraintTeacherMinMorningsPerWeek")){
8593 					crt_constraint=readTeacherMinMorningsPerWeek(xmlReader, xmlReadingLog);
8594 				}
8595 				else if(xmlReader.name()==QString("ConstraintTeachersMinMorningsPerWeek")){
8596 					crt_constraint=readTeachersMinMorningsPerWeek(xmlReader, xmlReadingLog);
8597 				}
8598 				else if(xmlReader.name()==QString("ConstraintTeacherMinAfternoonsPerWeek")){
8599 					crt_constraint=readTeacherMinAfternoonsPerWeek(xmlReader, xmlReadingLog);
8600 				}
8601 				else if(xmlReader.name()==QString("ConstraintTeachersMinAfternoonsPerWeek")){
8602 					crt_constraint=readTeachersMinAfternoonsPerWeek(xmlReader, xmlReadingLog);
8603 				}
8604 
8605 				else if(xmlReader.name()==QString("ConstraintTeacherMorningIntervalMaxDaysPerWeek")){
8606 					crt_constraint=readTeacherMorningIntervalMaxDaysPerWeek(parent, xmlReader, xmlReadingLog);
8607 				}
8608 				else if(xmlReader.name()==QString("ConstraintTeachersMorningIntervalMaxDaysPerWeek")){
8609 					crt_constraint=readTeachersMorningIntervalMaxDaysPerWeek(parent, xmlReader, xmlReadingLog);
8610 				}
8611 
8612 				else if(xmlReader.name()==QString("ConstraintTeacherAfternoonIntervalMaxDaysPerWeek")){
8613 					crt_constraint=readTeacherAfternoonIntervalMaxDaysPerWeek(parent, xmlReader, xmlReadingLog);
8614 				}
8615 				else if(xmlReader.name()==QString("ConstraintTeachersAfternoonIntervalMaxDaysPerWeek")){
8616 					crt_constraint=readTeachersAfternoonIntervalMaxDaysPerWeek(parent, xmlReader, xmlReadingLog);
8617 				}
8618 
8619 				else if((!version6AndAbove && (probably5Morocco || probably5Algeria || probably5MA))
8620 				 && xmlReader.name()==QString("ConstraintStudentsSetMaxDaysPerWeek")){
8621 					if(reportMA5OldTimeConstraintsChange){
8622 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8623 						  tr("Your file was detected as an old FET-5 MA, Morocco, or Algeria file, and"
8624 						  " contains a constraint of type students set max days per week, which will be converted"
8625 						  " to a constraint of type students set max real days per week."),
8626 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8627 						if(t==0)
8628 							reportMA5OldTimeConstraintsChange=false;
8629 					}
8630 					crt_constraint=readOldMAStudentsSetMaxDaysPerWeek(parent, xmlReader, xmlReadingLog);
8631 				}
8632 				else if(xmlReader.name()==QString("ConstraintStudentsSetMaxRealDaysPerWeek")){
8633 					crt_constraint=readStudentsSetMaxRealDaysPerWeek(parent, xmlReader, xmlReadingLog);
8634 				}
8635 
8636 				else if((!version6AndAbove && (probably5Morocco || probably5Algeria || probably5MA))
8637 				 && xmlReader.name()==QString("ConstraintStudentsMaxDaysPerWeek")){
8638 					if(reportMA5OldTimeConstraintsChange){
8639 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8640 						  tr("Your file was detected as an old FET-5 MA, Morocco, or Algeria file, and"
8641 						  " contains a constraint of type students max days per week, which will be converted"
8642 						  " to a constraint of type students max real days per week."),
8643 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8644 						if(t==0)
8645 							reportMA5OldTimeConstraintsChange=false;
8646 					}
8647 					crt_constraint=readOldMAStudentsMaxDaysPerWeek(parent, xmlReader, xmlReadingLog);
8648 				}
8649 				else if(xmlReader.name()==QString("ConstraintStudentsMaxRealDaysPerWeek")){
8650 					crt_constraint=readStudentsMaxRealDaysPerWeek(parent, xmlReader, xmlReadingLog);
8651 				}
8652 				//2020-06-25
8653 				else if(xmlReader.name()==QString("ConstraintStudentsSetMaxAfternoonsPerWeek")){
8654 					crt_constraint=readStudentsSetMaxAfternoonsPerWeek(parent, xmlReader, xmlReadingLog);
8655 				}
8656 				else if(xmlReader.name()==QString("ConstraintStudentsMaxAfternoonsPerWeek")){
8657 					crt_constraint=readStudentsMaxAfternoonsPerWeek(parent, xmlReader, xmlReadingLog);
8658 				}
8659 
8660 				else if(xmlReader.name()==QString("ConstraintStudentsSetMaxMorningsPerWeek")){
8661 					crt_constraint=readStudentsSetMaxMorningsPerWeek(parent, xmlReader, xmlReadingLog);
8662 				}
8663 				else if(xmlReader.name()==QString("ConstraintStudentsMaxMorningsPerWeek")){
8664 					crt_constraint=readStudentsMaxMorningsPerWeek(parent, xmlReader, xmlReadingLog);
8665 				}
8666 				//2020-06-26
8667 				else if(xmlReader.name()==QString("ConstraintStudentsSetMinAfternoonsPerWeek")){
8668 					crt_constraint=readStudentsSetMinAfternoonsPerWeek(parent, xmlReader, xmlReadingLog);
8669 				}
8670 				else if(xmlReader.name()==QString("ConstraintStudentsMinAfternoonsPerWeek")){
8671 					crt_constraint=readStudentsMinAfternoonsPerWeek(parent, xmlReader, xmlReadingLog);
8672 				}
8673 
8674 				else if(xmlReader.name()==QString("ConstraintStudentsSetMinMorningsPerWeek")){
8675 					crt_constraint=readStudentsSetMinMorningsPerWeek(parent, xmlReader, xmlReadingLog);
8676 				}
8677 				else if(xmlReader.name()==QString("ConstraintStudentsMinMorningsPerWeek")){
8678 					crt_constraint=readStudentsMinMorningsPerWeek(parent, xmlReader, xmlReadingLog);
8679 				}
8680 				//
8681 
8682 				else if(xmlReader.name()==QString("ConstraintStudentsSetMorningIntervalMaxDaysPerWeek")){
8683 					crt_constraint=readStudentsSetMorningIntervalMaxDaysPerWeek(parent, xmlReader, xmlReadingLog);
8684 				}
8685 				else if(xmlReader.name()==QString("ConstraintStudentsMorningIntervalMaxDaysPerWeek")){
8686 					crt_constraint=readStudentsMorningIntervalMaxDaysPerWeek(parent, xmlReader, xmlReadingLog);
8687 				}
8688 				else if(xmlReader.name()==QString("ConstraintStudentsSetAfternoonIntervalMaxDaysPerWeek")){
8689 					crt_constraint=readStudentsSetAfternoonIntervalMaxDaysPerWeek(parent, xmlReader, xmlReadingLog);
8690 				}
8691 				else if(xmlReader.name()==QString("ConstraintStudentsAfternoonIntervalMaxDaysPerWeek")){
8692 					crt_constraint=readStudentsAfternoonIntervalMaxDaysPerWeek(parent, xmlReader, xmlReadingLog);
8693 				}
8694 
8695 				else if((!version6AndAbove && (probably5Morocco || probably5Algeria || probably5MA))
8696 				 && xmlReader.name()==QString("ConstraintTeachersMaxHoursDaily")){
8697 					if(reportMA5OldTimeConstraintsChange){
8698 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8699 						  tr("Your file was detected as an old FET-5 MA, Morocco, or Algeria file, and"
8700 						  " contains a constraint of type teachers max hours daily, which will be converted"
8701 						  " to a constraint of type teachers max hours daily real days."),
8702 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8703 						if(t==0)
8704 							reportMA5OldTimeConstraintsChange=false;
8705 					}
8706 					crt_constraint=readOldMATeachersMaxHoursDaily(xmlReader, xmlReadingLog);
8707 				}
8708 				else if(xmlReader.name()==QString("ConstraintTeachersMaxHoursDailyRealDays")){
8709 					crt_constraint=readTeachersMaxHoursDailyRealDays(xmlReader, xmlReadingLog);
8710 				}
8711 
8712 				else if((!version6AndAbove && (probably5Morocco || probably5Algeria || probably5MA))
8713 				 && xmlReader.name()==QString("ConstraintTeacherMaxHoursDaily")){
8714 					if(reportMA5OldTimeConstraintsChange){
8715 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8716 						  tr("Your file was detected as an old FET-5 MA, Morocco, or Algeria file, and"
8717 						  " contains a constraint of type teacher max hours daily, which will be converted"
8718 						  " to a constraint of type teacher max hours daily real days."),
8719 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8720 						if(t==0)
8721 							reportMA5OldTimeConstraintsChange=false;
8722 					}
8723 					crt_constraint=readOldMATeacherMaxHoursDaily(xmlReader, xmlReadingLog);
8724 				}
8725 				else if(xmlReader.name()==QString("ConstraintTeacherMaxHoursDailyRealDays")){
8726 					crt_constraint=readTeacherMaxHoursDailyRealDays(xmlReader, xmlReadingLog);
8727 				}
8728 
8729 				else if((!version6AndAbove && (probably5Morocco || probably5Algeria || probably5MA))
8730 				 && xmlReader.name()==QString("ConstraintTeachersMaxHoursDailyHalfDays")){
8731 					if(reportMA5OldTimeConstraintsChange){
8732 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8733 						  tr("Your file was detected as an old FET-5 MA, Morocco, or Algeria file, and"
8734 						  " contains a constraint of type teachers max hours daily for half days, which will be converted"
8735 						  " to a constraint of type teachers max hours daily."),
8736 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8737 						if(t==0)
8738 							reportMA5OldTimeConstraintsChange=false;
8739 					}
8740 					crt_constraint=readOldMATeachersMaxHoursDailyHalfDays(xmlReader, xmlReadingLog);
8741 				}
8742 				else if((!version6AndAbove && (probably5Morocco || probably5Algeria || probably5MA))
8743 				 && xmlReader.name()==QString("ConstraintTeacherMaxHoursDailyHalfDays")){
8744 					if(reportMA5OldTimeConstraintsChange){
8745 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8746 						  tr("Your file was detected as an old FET-5 MA, Morocco, or Algeria file, and"
8747 						  " contains a constraint of type teacher max hours daily for half days, which will be converted"
8748 						  " to a constraint of type teacher max hours daily."),
8749 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8750 						if(t==0)
8751 							reportMA5OldTimeConstraintsChange=false;
8752 					}
8753 					crt_constraint=readOldMATeacherMaxHoursDailyHalfDays(xmlReader, xmlReadingLog);
8754 				}
8755 
8756 				else if((!version6AndAbove && (probably5Morocco || probably5Algeria || probably5MA))
8757 				 && xmlReader.name()==QString("ConstraintTeacherActivityTagMaxHoursDaily")){
8758 					if(reportMA5OldTimeConstraintsChange){
8759 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8760 						  tr("Your file was detected as an old FET-5 MA, Morocco, or Algeria file, and"
8761 						  " contains a constraint of type teacher activity tag max hours daily, which will be converted"
8762 						  " to a constraint of type teacher activity tag max hours daily real days."),
8763 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8764 						if(t==0)
8765 							reportMA5OldTimeConstraintsChange=false;
8766 					}
8767 					crt_constraint=readOldMATeacherActivityTagMaxHoursDaily(xmlReader, xmlReadingLog);
8768 				}
8769 				else if(xmlReader.name()==QString("ConstraintTeacherActivityTagMaxHoursDailyRealDays")){
8770 					crt_constraint=readTeacherActivityTagMaxHoursDailyRealDays(xmlReader, xmlReadingLog);
8771 				}
8772 
8773 				else if((!version6AndAbove && (probably5Morocco || probably5Algeria || probably5MA))
8774 				 && xmlReader.name()==QString("ConstraintTeachersActivityTagMaxHoursDaily")){
8775 					if(reportMA5OldTimeConstraintsChange){
8776 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8777 						  tr("Your file was detected as an old FET-5 MA, Morocco, or Algeria file, and"
8778 						  " contains a constraint of type teachers activity tag max hours daily, which will be converted"
8779 						  " to a constraint of type teachers activity tag max hours daily real days."),
8780 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8781 						if(t==0)
8782 							reportMA5OldTimeConstraintsChange=false;
8783 					}
8784 					crt_constraint=readOldMATeachersActivityTagMaxHoursDaily(xmlReader, xmlReadingLog);
8785 				}
8786 				else if(xmlReader.name()==QString("ConstraintTeachersActivityTagMaxHoursDailyRealDays")){
8787 					crt_constraint=readTeachersActivityTagMaxHoursDailyRealDays(xmlReader, xmlReadingLog);
8788 				}
8789 
8790 				//2020-06-28
8791 				else if(xmlReader.name()==QString("ConstraintTeacherMaxHoursPerAllAfternoons")){
8792 					crt_constraint=readTeacherMaxHoursPerAllAfternoons(xmlReader, xmlReadingLog);
8793 				}
8794 				else if(xmlReader.name()==QString("ConstraintTeachersMaxHoursPerAllAfternoons")){
8795 					crt_constraint=readTeachersMaxHoursPerAllAfternoons(xmlReader, xmlReadingLog);
8796 				}
8797 				//2020-06-28
8798 				else if(xmlReader.name()==QString("ConstraintStudentsSetMaxHoursPerAllAfternoons")){
8799 					crt_constraint=readStudentsSetMaxHoursPerAllAfternoons(xmlReader, xmlReadingLog);
8800 				}
8801 				else if(xmlReader.name()==QString("ConstraintStudentsMaxHoursPerAllAfternoons")){
8802 					crt_constraint=readStudentsMaxHoursPerAllAfternoons(xmlReader, xmlReadingLog);
8803 				}
8804 				//
8805 
8806 				else if(xmlReader.name()==QString("ConstraintTeachersMinHoursDailyRealDays")){
8807 					crt_constraint=readTeachersMinHoursDailyRealDays(parent, xmlReader, xmlReadingLog);
8808 				}
8809 				else if(xmlReader.name()==QString("ConstraintTeacherMinHoursDailyRealDays")){
8810 					crt_constraint=readTeacherMinHoursDailyRealDays(parent, xmlReader, xmlReadingLog);
8811 				}
8812 				else if(xmlReader.name()==QString("ConstraintTeachersMinHoursPerMorning")){
8813 					crt_constraint=readTeachersMinHoursPerMorning(parent, xmlReader, xmlReadingLog);
8814 				}
8815 				else if(xmlReader.name()==QString("ConstraintTeacherMinHoursPerMorning")){
8816 					crt_constraint=readTeacherMinHoursPerMorning(parent, xmlReader, xmlReadingLog);
8817 				}
8818 
8819 				else if((!version6AndAbove && (probably5Morocco || probably5Algeria || probably5MA))
8820 				 && xmlReader.name()==QString("ConstraintStudentsMaxHoursDaily")){
8821 					if(reportMA5OldTimeConstraintsChange){
8822 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8823 						  tr("Your file was detected as an old FET-5 MA, Morocco, or Algeria file, and"
8824 						  " contains a constraint of type students max hours daily, which will be converted"
8825 						  " to a constraint of type students max hours daily real days."),
8826 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8827 						if(t==0)
8828 							reportMA5OldTimeConstraintsChange=false;
8829 					}
8830 					crt_constraint=readOldMAStudentsMaxHoursDaily(xmlReader, xmlReadingLog);
8831 				}
8832 				else if(xmlReader.name()==QString("ConstraintStudentsMaxHoursDailyRealDays")){
8833 					crt_constraint=readStudentsMaxHoursDailyRealDays(xmlReader, xmlReadingLog);
8834 				}
8835 
8836 				else if((!version6AndAbove && (probably5Morocco || probably5Algeria || probably5MA))
8837 				 && xmlReader.name()==QString("ConstraintStudentsSetMaxHoursDaily")){
8838 					if(reportMA5OldTimeConstraintsChange){
8839 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8840 						  tr("Your file was detected as an old FET-5 MA, Morocco, or Algeria file, and"
8841 						  " contains a constraint of type student set max hours daily, which will be converted"
8842 						  " to a constraint of type students set max hours daily real days."),
8843 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8844 						if(t==0)
8845 							reportMA5OldTimeConstraintsChange=false;
8846 					}
8847 					crt_constraint=readOldMAStudentsSetMaxHoursDaily(xmlReader, xmlReadingLog);
8848 				}
8849 				else if(xmlReader.name()==QString("ConstraintStudentsSetMaxHoursDailyRealDays")){
8850 					crt_constraint=readStudentsSetMaxHoursDailyRealDays(xmlReader, xmlReadingLog);
8851 				}
8852 
8853 				else if((!version6AndAbove && (probably5Morocco || probably5Algeria || probably5MA))
8854 				 && xmlReader.name()==QString("ConstraintStudentsSetActivityTagMaxHoursDaily")){
8855 					if(reportMA5OldTimeConstraintsChange){
8856 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8857 						  tr("Your file was detected as an old FET-5 MA, Morocco, or Algeria file, and"
8858 						  " contains a constraint of type student set activity tag max hours daily, which will be converted"
8859 						  " to a constraint of type students set activity tag max hours daily real days."),
8860 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8861 						if(t==0)
8862 							reportMA5OldTimeConstraintsChange=false;
8863 					}
8864 					crt_constraint=readOldMAStudentsSetActivityTagMaxHoursDaily(xmlReader, xmlReadingLog);
8865 				}
8866 				else if(xmlReader.name()==QString("ConstraintStudentsSetActivityTagMaxHoursDailyRealDays")){
8867 					crt_constraint=readStudentsSetActivityTagMaxHoursDailyRealDays(xmlReader, xmlReadingLog);
8868 				}
8869 
8870 				else if((!version6AndAbove && (probably5Morocco || probably5Algeria || probably5MA))
8871 				 && xmlReader.name()==QString("ConstraintStudentsActivityTagMaxHoursDaily")){
8872 					if(reportMA5OldTimeConstraintsChange){
8873 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8874 						  tr("Your file was detected as an old FET-5 MA, Morocco, or Algeria file, and"
8875 						  " contains a constraint of type students activity tag max hours daily, which will be converted"
8876 						  " to a constraint of type students activity tag max hours daily real days."),
8877 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8878 						if(t==0)
8879 							reportMA5OldTimeConstraintsChange=false;
8880 					}
8881 					crt_constraint=readOldMAStudentsActivityTagMaxHoursDaily(xmlReader, xmlReadingLog);
8882 				}
8883 				else if(xmlReader.name()==QString("ConstraintStudentsActivityTagMaxHoursDailyRealDays")){
8884 					crt_constraint=readStudentsActivityTagMaxHoursDailyRealDays(xmlReader, xmlReadingLog);
8885 				}
8886 
8887 				else if(xmlReader.name()==QString("ConstraintStudentsMinHoursPerMorning")){
8888 					crt_constraint=readStudentsMinHoursPerMorning(parent, xmlReader, xmlReadingLog);
8889 				}
8890 				else if(xmlReader.name()==QString("ConstraintStudentsSetMinHoursPerMorning")){
8891 					crt_constraint=readStudentsSetMinHoursPerMorning(parent, xmlReader, xmlReadingLog);
8892 				}
8893 
8894 				else if(xmlReader.name()==QString("ConstraintTeachersAfternoonsEarlyMaxBeginningsAtSecondHour")){
8895 					crt_constraint=readTeachersAfternoonsEarlyMaxBeginningsAtSecondHour(xmlReader, xmlReadingLog);
8896 				}
8897 				else if(xmlReader.name()==QString("ConstraintTeacherAfternoonsEarlyMaxBeginningsAtSecondHour")){
8898 					crt_constraint=readTeacherAfternoonsEarlyMaxBeginningsAtSecondHour(xmlReader, xmlReadingLog);
8899 				}
8900 				else if(xmlReader.name()==QString("ConstraintTeachersMorningsEarlyMaxBeginningsAtSecondHour")){
8901 					crt_constraint=readTeachersMorningsEarlyMaxBeginningsAtSecondHour(xmlReader, xmlReadingLog);
8902 				}
8903 				else if(xmlReader.name()==QString("ConstraintTeacherMorningsEarlyMaxBeginningsAtSecondHour")){
8904 					crt_constraint=readTeacherMorningsEarlyMaxBeginningsAtSecondHour(xmlReader, xmlReadingLog);
8905 				}
8906 				else if(xmlReader.name()==QString("ConstraintTeachersMaxGapsPerRealDay")){
8907 					crt_constraint=readTeachersMaxGapsPerRealDay(xmlReader, xmlReadingLog);
8908 				}
8909 				else if(xmlReader.name()==QString("ConstraintTeacherMaxGapsPerRealDay")){
8910 					crt_constraint=readTeacherMaxGapsPerRealDay(xmlReader, xmlReadingLog);
8911 				}
8912 				else if(xmlReader.name()==QString("ConstraintTeacherMaxZeroGapsPerAfternoon")){
8913 					crt_constraint=readTeacherMaxZeroGapsPerAfternoon(xmlReader, xmlReadingLog);
8914 				}
8915 				else if(xmlReader.name()==QString("ConstraintTeachersMaxZeroGapsPerAfternoon")){
8916 					crt_constraint=readTeachersMaxZeroGapsPerAfternoon(xmlReader, xmlReadingLog);
8917 				}
8918 
8919 				else if(xmlReader.name()==QString("ConstraintStudentsMaxGapsPerRealDay")){
8920 					crt_constraint=readStudentsMaxGapsPerRealDay(xmlReader, xmlReadingLog);
8921 				}
8922 				else if(xmlReader.name()==QString("ConstraintStudentsSetMaxGapsPerRealDay")){
8923 					crt_constraint=readStudentsSetMaxGapsPerRealDay(xmlReader, xmlReadingLog);
8924 				}
8925 
8926 				else if(xmlReader.name()==QString("ConstraintTeachersMaxGapsPerWeekForRealDays")){
8927 					crt_constraint=readTeachersMaxGapsPerWeekForRealDays(xmlReader, xmlReadingLog);
8928 				}
8929 				else if(xmlReader.name()==QString("ConstraintTeacherMaxGapsPerWeekForRealDays")){
8930 					crt_constraint=readTeacherMaxGapsPerWeekForRealDays(xmlReader, xmlReadingLog);
8931 				}
8932 				else if(xmlReader.name()==QString("ConstraintStudentsMaxGapsPerWeekForRealDays")){
8933 					crt_constraint=readStudentsMaxGapsPerWeekForRealDays(xmlReader, xmlReadingLog);
8934 				}
8935 				else if(xmlReader.name()==QString("ConstraintStudentsSetMaxGapsPerWeekForRealDays")){
8936 					crt_constraint=readStudentsSetMaxGapsPerWeekForRealDays(xmlReader, xmlReadingLog);
8937 				}
8938 
8939 				//////////
8940 				else if(xmlReader.name()==QString("ConstraintStudentsAfternoonsEarlyMaxBeginningsAtSecondHour")){
8941 					crt_constraint=readStudentsAfternoonsEarlyMaxBeginningsAtSecondHour(xmlReader, xmlReadingLog);
8942 				}
8943 				else if(xmlReader.name()==QString("ConstraintStudentsSetAfternoonsEarlyMaxBeginningsAtSecondHour")){
8944 					crt_constraint=readStudentsSetAfternoonsEarlyMaxBeginningsAtSecondHour(xmlReader, xmlReadingLog);
8945 				}
8946 				//////////
8947 				else if(xmlReader.name()==QString("ConstraintStudentsMorningsEarlyMaxBeginningsAtSecondHour")){
8948 					crt_constraint=readStudentsMorningsEarlyMaxBeginningsAtSecondHour(xmlReader, xmlReadingLog);
8949 				}
8950 				else if(xmlReader.name()==QString("ConstraintStudentsSetMorningsEarlyMaxBeginningsAtSecondHour")){
8951 					crt_constraint=readStudentsSetMorningsEarlyMaxBeginningsAtSecondHour(xmlReader, xmlReadingLog);
8952 				}
8953 				//////////
8954 
8955 				else if((!version6AndAbove && (probably5Morocco || probably5Algeria || probably5MA))
8956 				 && xmlReader.name()==QString("ConstraintTeacherMaxSpanPerDay")){
8957 					if(reportMA5OldTimeConstraintsChange){
8958 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8959 						  tr("Your file was detected as an old FET-5 MA, Morocco, or Algeria file, and"
8960 						  " contains a constraint of type teacher max span per day, which will be converted"
8961 						  " to a constraint of type teacher max span per real day."),
8962 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8963 						if(t==0)
8964 							reportMA5OldTimeConstraintsChange=false;
8965 					}
8966 					crt_constraint=readOldMATeacherMaxSpanPerDay(xmlReader, xmlReadingLog);
8967 				}
8968 				else if(xmlReader.name()==QString("ConstraintTeacherMaxSpanPerRealDay")){
8969 					crt_constraint=readTeacherMaxSpanPerRealDay(xmlReader, xmlReadingLog);
8970 				}
8971 
8972 				else if((!version6AndAbove && (probably5Morocco || probably5Algeria || probably5MA))
8973 				 && xmlReader.name()==QString("ConstraintTeachersMaxSpanPerDay")){
8974 					if(reportMA5OldTimeConstraintsChange){
8975 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8976 						  tr("Your file was detected as an old FET-5 MA, Morocco, or Algeria file, and"
8977 						  " contains a constraint of type teachers max span per day, which will be converted"
8978 						  " to a constraint of type teachers max span per real day."),
8979 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8980 						if(t==0)
8981 							reportMA5OldTimeConstraintsChange=false;
8982 					}
8983 					crt_constraint=readOldMATeachersMaxSpanPerDay(xmlReader, xmlReadingLog);
8984 				}
8985 				else if(xmlReader.name()==QString("ConstraintTeachersMaxSpanPerRealDay")){
8986 					crt_constraint=readTeachersMaxSpanPerRealDay(xmlReader, xmlReadingLog);
8987 				}
8988 
8989 				else if((!version6AndAbove && (probably5Morocco || probably5Algeria || probably5MA))
8990 				 && xmlReader.name()==QString("ConstraintStudentsSetMaxSpanPerDay")){
8991 					if(reportMA5OldTimeConstraintsChange){
8992 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
8993 						  tr("Your file was detected as an old FET-5 MA, Morocco, or Algeria file, and"
8994 						  " contains a constraint of type students set max span per day, which will be converted"
8995 						  " to a constraint of type students set max span per real day."),
8996 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
8997 						if(t==0)
8998 							reportMA5OldTimeConstraintsChange=false;
8999 					}
9000 					crt_constraint=readOldMAStudentsSetMaxSpanPerDay(xmlReader, xmlReadingLog);
9001 				}
9002 				else if(xmlReader.name()==QString("ConstraintStudentsSetMaxSpanPerRealDay")){
9003 					crt_constraint=readStudentsSetMaxSpanPerRealDay(xmlReader, xmlReadingLog);
9004 				}
9005 
9006 				else if((!version6AndAbove && (probably5Morocco || probably5Algeria || probably5MA))
9007 				 && xmlReader.name()==QString("ConstraintStudentsMaxSpanPerDay")){
9008 					if(reportMA5OldTimeConstraintsChange){
9009 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
9010 						  tr("Your file was detected as an old FET-5 MA, Morocco, or Algeria file, and"
9011 						  " contains a constraint of type students max span per day, which will be converted"
9012 						  " to a constraint of type students max span per real day."),
9013 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
9014 						if(t==0)
9015 							reportMA5OldTimeConstraintsChange=false;
9016 					}
9017 					crt_constraint=readOldMAStudentsMaxSpanPerDay(xmlReader, xmlReadingLog);
9018 				}
9019 				else if(xmlReader.name()==QString("ConstraintStudentsMaxSpanPerRealDay")){
9020 					crt_constraint=readStudentsMaxSpanPerRealDay(xmlReader, xmlReadingLog);
9021 				}
9022 
9023 				//
9024 				else if(xmlReader.name()==QString("ConstraintTeacherMinRestingHoursBetweenMorningAndAfternoon")){
9025 					crt_constraint=readTeacherMinRestingHoursBetweenMorningAndAfternoon(xmlReader, xmlReadingLog);
9026 				}
9027 				else if(xmlReader.name()==QString("ConstraintTeachersMinRestingHoursBetweenMorningAndAfternoon")){
9028 					crt_constraint=readTeachersMinRestingHoursBetweenMorningAndAfternoon(xmlReader, xmlReadingLog);
9029 				}
9030 				else if(xmlReader.name()==QString("ConstraintStudentsSetMinRestingHoursBetweenMorningAndAfternoon")){
9031 					crt_constraint=readStudentsSetMinRestingHoursBetweenMorningAndAfternoon(xmlReader, xmlReadingLog);
9032 				}
9033 				else if(xmlReader.name()==QString("ConstraintStudentsMinRestingHoursBetweenMorningAndAfternoon")){
9034 					crt_constraint=readStudentsMinRestingHoursBetweenMorningAndAfternoon(xmlReader, xmlReadingLog);
9035 				}
9036 				//
9037 				else if(xmlReader.name()==QString("ConstraintTeacherMaxThreeConsecutiveDays")){
9038 					crt_constraint=readTeacherMaxThreeConsecutiveDays(parent, xmlReader, xmlReadingLog);
9039 				}
9040 				else if(xmlReader.name()==QString("ConstraintTeachersMaxThreeConsecutiveDays")){
9041 					crt_constraint=readTeachersMaxThreeConsecutiveDays(parent, xmlReader, xmlReadingLog);
9042 				}
9043 				//
9044 				else{
9045 					unrecognizedXmlTags.append(xmlReader.name().toString());
9046 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
9047 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
9048 
9049 					xmlReader.skipCurrentElement();
9050 					xmlReaderNumberOfUnrecognizedFields++;
9051 				}
9052 
9053 //corruptConstraintTime:
9054 				//here we skip an invalid constraint or add a valid one
9055 				if(crt_constraint!=nullptr){
9056 					assert(crt_constraint!=nullptr);
9057 					bool tmp=this->addTimeConstraint(crt_constraint);
9058 					if(!tmp){
9059 						if(seeNextWarnNotAddedTimeConstraint){
9060 							int t=RulesReconcilableMessage::warning(parent, tr("FET information"),
9061 							 tr("Constraint\n%1\nnot added - must be a duplicate").
9062 							 arg(crt_constraint->getDetailedDescription(*this)), tr("Skip rest"), tr("See next"), QString(""), 1, 0);
9063 							if(t==0)
9064 								seeNextWarnNotAddedTimeConstraint=false;
9065 						}
9066 						delete crt_constraint;
9067 					}
9068 					else
9069 						nc++;
9070 				}
9071 			}
9072 			xmlReadingLog+="  Added "+CustomFETString::number(nc)+" time constraints\n";
9073 			reducedXmlLog+="Added "+CustomFETString::number(nc)+" time constraints\n";
9074 		}
9075 		else if(xmlReader.name()==QString("Space_Constraints_List")){
9076 			bool reportRoomNotAvailableChange=true;
9077 
9078 			bool reportUnspecifiedPermanentlyLockedSpace=true;
9079 
9080 			bool seeNextWarnNotAddedSpaceConstraint=true;
9081 
9082 			bool reportMA5OldSpaceConstraintsChange=true;
9083 
9084 			int nc=0;
9085 			SpaceConstraint *crt_constraint;
9086 
9087 			assert(xmlReader.isStartElement());
9088 			while(xmlReader.readNextStartElement()){
9089 				xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
9090 				crt_constraint=nullptr;
9091 				if(xmlReader.name()==QString("ConstraintBasicCompulsorySpace")){
9092 					crt_constraint=readBasicCompulsorySpace(xmlReader, xmlReadingLog);
9093 				}
9094 				else if(xmlReader.name()==QString("ConstraintRoomNotAvailable")){
9095 					if(reportRoomNotAvailableChange){
9096 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
9097 						 tr("File contains constraint room not available, which is old (it was improved in FET 5.5.0), and will be converted"
9098 						 " to the similar constraint of this type, constraint room not available times (a matrix)."),
9099 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
9100 						if(t==0)
9101 							reportRoomNotAvailableChange=false;
9102 					}
9103 
9104 					crt_constraint=readRoomNotAvailable(xmlReader, xmlReadingLog);
9105 				}
9106 				else if(xmlReader.name()==QString("ConstraintRoomNotAvailableTimes")){
9107 					crt_constraint=readRoomNotAvailableTimes(xmlReader, xmlReadingLog);
9108 				}
9109 				else if(xmlReader.name()==QString("ConstraintTeacherRoomNotAvailableTimes")){
9110 					crt_constraint=readTeacherRoomNotAvailableTimes(xmlReader, xmlReadingLog);
9111 				}
9112 				else if(xmlReader.name()==QString("ConstraintRoomTypeNotAllowedSubjects") && !skipDeprecatedConstraints){
9113 
9114 					int t=RulesReconcilableMessage::warning(parent, tr("FET warning"),
9115 					 tr("File contains deprecated constraint room type not allowed subjects - will be ignored"),
9116 					 tr("Skip rest"), tr("See next"), QString(),
9117 					 1, 0);
9118 
9119 					if(t==0)
9120 						skipDeprecatedConstraints=true;
9121 					crt_constraint=nullptr;
9122 					xmlReader.skipCurrentElement();
9123 				}
9124 				else if(xmlReader.name()==QString("ConstraintSubjectRequiresEquipments") && !skipDeprecatedConstraints){
9125 
9126 					int t=RulesReconcilableMessage::warning(parent, tr("FET warning"),
9127 					 tr("File contains deprecated constraint subject requires equipments - will be ignored"),
9128 					 tr("Skip rest"), tr("See next"), QString(),
9129 					 1, 0);
9130 
9131 					if(t==0)
9132 						skipDeprecatedConstraints=true;
9133 
9134 					crt_constraint=nullptr;
9135 					xmlReader.skipCurrentElement();
9136 				}
9137 				else if(xmlReader.name()==QString("ConstraintSubjectSubjectTagRequireEquipments") && !skipDeprecatedConstraints){
9138 
9139 					int t=RulesReconcilableMessage::warning(parent, tr("FET warning"),
9140 					 tr("File contains deprecated constraint subject tag requires equipments - will be ignored"),
9141 					 tr("Skip rest"), tr("See next"), QString(),
9142 					 1, 0);
9143 
9144 					if(t==0)
9145 						skipDeprecatedConstraints=true;
9146 					crt_constraint=nullptr;
9147 					xmlReader.skipCurrentElement();
9148 				}
9149 				else if(xmlReader.name()==QString("ConstraintTeacherRequiresRoom") && !skipDeprecatedConstraints){
9150 
9151 					int t=RulesReconcilableMessage::warning(parent, tr("FET warning"),
9152 					 tr("File contains deprecated constraint teacher requires room - will be ignored"),
9153 					 tr("Skip rest"), tr("See next"), QString(),
9154 					 1, 0);
9155 
9156 					if(t==0)
9157 						skipDeprecatedConstraints=true;
9158 					crt_constraint=nullptr;
9159 					xmlReader.skipCurrentElement();
9160 				}
9161 				else if(xmlReader.name()==QString("ConstraintTeacherSubjectRequireRoom") && !skipDeprecatedConstraints){
9162 
9163 					int t=RulesReconcilableMessage::warning(parent, tr("FET warning"),
9164 					 tr("File contains deprecated constraint teacher subject require room - will be ignored"),
9165 					 tr("Skip rest"), tr("See next"), QString(),
9166 					 1, 0);
9167 
9168 					if(t==0)
9169 						skipDeprecatedConstraints=true;
9170 					crt_constraint=nullptr;
9171 					xmlReader.skipCurrentElement();
9172 				}
9173 				else if(xmlReader.name()==QString("ConstraintMinimizeNumberOfRoomsForStudents") && !skipDeprecatedConstraints){
9174 
9175 					int t=RulesReconcilableMessage::warning(parent, tr("FET warning"),
9176 					 tr("File contains deprecated constraint minimize number of rooms for students - will be ignored"),
9177 					 tr("Skip rest"), tr("See next"), QString(),
9178 					 1, 0);
9179 
9180 					if(t==0)
9181 						skipDeprecatedConstraints=true;
9182 					crt_constraint=nullptr;
9183 					xmlReader.skipCurrentElement();
9184 				}
9185 				else if(xmlReader.name()==QString("ConstraintMinimizeNumberOfRoomsForTeachers") && !skipDeprecatedConstraints){
9186 
9187 					int t=RulesReconcilableMessage::warning(parent, tr("FET warning"),
9188 					 tr("File contains deprecated constraint minimize number of rooms for teachers - will be ignored"),
9189 					 tr("Skip rest"), tr("See next"), QString(),
9190 					 1, 0);
9191 
9192 					if(t==0)
9193 						skipDeprecatedConstraints=true;
9194 					crt_constraint=nullptr;
9195 					xmlReader.skipCurrentElement();
9196 				}
9197 				else if(xmlReader.name()==QString("ConstraintActivityPreferredRoom")){
9198 					crt_constraint=readActivityPreferredRoom(parent, xmlReader, xmlReadingLog, reportUnspecifiedPermanentlyLockedSpace);
9199 				}
9200 				else if(xmlReader.name()==QString("ConstraintActivityPreferredRooms")){
9201 					crt_constraint=readActivityPreferredRooms(xmlReader, xmlReadingLog);
9202 				}
9203 				else if(xmlReader.name()==QString("ConstraintActivitiesSameRoom") && !skipDeprecatedConstraints){
9204 
9205 					int t=RulesReconcilableMessage::warning(parent, tr("FET warning"),
9206 					 tr("File contains deprecated constraint activities same room - will be ignored"),
9207 					 tr("Skip rest"), tr("See next"), QString(),
9208 					 1, 0);
9209 
9210 					if(t==0)
9211 						skipDeprecatedConstraints=true;
9212 					crt_constraint=nullptr;
9213 					xmlReader.skipCurrentElement();
9214 				}
9215 				else if(xmlReader.name()==QString("ConstraintSubjectPreferredRoom")){
9216 					crt_constraint=readSubjectPreferredRoom(xmlReader, xmlReadingLog);
9217 				}
9218 				else if(xmlReader.name()==QString("ConstraintSubjectPreferredRooms")){
9219 					crt_constraint=readSubjectPreferredRooms(xmlReader, xmlReadingLog);
9220 				}
9221 				else if(xmlReader.name()==QString("ConstraintSubjectSubjectTagPreferredRoom")){
9222 					crt_constraint=readSubjectSubjectTagPreferredRoom(xmlReader, xmlReadingLog);
9223 				}
9224 				else if(xmlReader.name()==QString("ConstraintSubjectSubjectTagPreferredRooms")){
9225 					crt_constraint=readSubjectSubjectTagPreferredRooms(xmlReader, xmlReadingLog);
9226 				}
9227 				else if(xmlReader.name()==QString("ConstraintSubjectActivityTagPreferredRoom")){
9228 					crt_constraint=readSubjectActivityTagPreferredRoom(xmlReader, xmlReadingLog);
9229 				}
9230 				else if(xmlReader.name()==QString("ConstraintSubjectActivityTagPreferredRooms")){
9231 					crt_constraint=readSubjectActivityTagPreferredRooms(xmlReader, xmlReadingLog);
9232 				}
9233 				//added 6 apr 2009
9234 				else if(xmlReader.name()==QString("ConstraintActivityTagPreferredRoom")){
9235 					crt_constraint=readActivityTagPreferredRoom(xmlReader, xmlReadingLog);
9236 				}
9237 				else if(xmlReader.name()==QString("ConstraintActivityTagPreferredRooms")){
9238 					crt_constraint=readActivityTagPreferredRooms(xmlReader, xmlReadingLog);
9239 				}
9240 				else if(xmlReader.name()==QString("ConstraintStudentsSetHomeRoom")){
9241 					crt_constraint=readStudentsSetHomeRoom(xmlReader, xmlReadingLog);
9242 				}
9243 				else if(xmlReader.name()==QString("ConstraintStudentsSetHomeRooms")){
9244 					crt_constraint=readStudentsSetHomeRooms(xmlReader, xmlReadingLog);
9245 				}
9246 				else if(xmlReader.name()==QString("ConstraintTeacherHomeRoom")){
9247 					crt_constraint=readTeacherHomeRoom(xmlReader, xmlReadingLog);
9248 				}
9249 				else if(xmlReader.name()==QString("ConstraintTeacherHomeRooms")){
9250 					crt_constraint=readTeacherHomeRooms(xmlReader, xmlReadingLog);
9251 				}
9252 				else if(xmlReader.name()==QString("ConstraintMaxBuildingChangesPerDayForTeachers") && !skipDeprecatedConstraints){
9253 
9254 					int t=RulesReconcilableMessage::warning(parent, tr("FET warning"),
9255 					 tr("File contains deprecated constraint max building changes per day for teachers - will be ignored"),
9256 					 tr("Skip rest"), tr("See next"), QString(),
9257 					 1, 0);
9258 
9259 					if(t==0)
9260 						skipDeprecatedConstraints=true;
9261 					crt_constraint=nullptr;
9262 					xmlReader.skipCurrentElement();
9263 				}
9264 				else if(xmlReader.name()==QString("ConstraintMaxBuildingChangesPerDayForStudents") && !skipDeprecatedConstraints){
9265 
9266 					int t=RulesReconcilableMessage::warning(parent, tr("FET warning"),
9267 					 tr("File contains deprecated constraint max building changes per day for students - will be ignored"),
9268 					 tr("Skip rest"), tr("See next"), QString(),
9269 					 1, 0);
9270 
9271 					if(t==0)
9272 						skipDeprecatedConstraints=true;
9273 					crt_constraint=nullptr;
9274 					xmlReader.skipCurrentElement();
9275 				}
9276 				else if(xmlReader.name()==QString("ConstraintMaxRoomChangesPerDayForTeachers") && !skipDeprecatedConstraints){
9277 
9278 					int t=RulesReconcilableMessage::warning(parent, tr("FET warning"),
9279 					 tr("File contains deprecated constraint max room changes per day for teachers - will be ignored"),
9280 					 tr("Skip rest"), tr("See next"), QString(),
9281 					 1, 0);
9282 
9283 					if(t==0)
9284 						skipDeprecatedConstraints=true;
9285 					crt_constraint=nullptr;
9286 					xmlReader.skipCurrentElement();
9287 				}
9288 				else if(xmlReader.name()==QString("ConstraintMaxRoomChangesPerDayForStudents") && !skipDeprecatedConstraints){
9289 
9290 					int t=RulesReconcilableMessage::warning(parent, tr("FET warning"),
9291 					 tr("File contains deprecated constraint max room changes per day for students - will be ignored"),
9292 					 tr("Skip rest"), tr("See next"), QString(),
9293 					 1, 0);
9294 
9295 					if(t==0)
9296 						skipDeprecatedConstraints=true;
9297 
9298 					crt_constraint=nullptr;
9299 					xmlReader.skipCurrentElement();
9300 				}
9301 				else if(xmlReader.name()==QString("ConstraintTeacherMaxBuildingChangesPerDay")){
9302 					crt_constraint=readTeacherMaxBuildingChangesPerDay(xmlReader, xmlReadingLog);
9303 				}
9304 				else if(xmlReader.name()==QString("ConstraintTeachersMaxBuildingChangesPerDay")){
9305 					crt_constraint=readTeachersMaxBuildingChangesPerDay(xmlReader, xmlReadingLog);
9306 				}
9307 				else if(xmlReader.name()==QString("ConstraintTeacherMaxBuildingChangesPerWeek")){
9308 					crt_constraint=readTeacherMaxBuildingChangesPerWeek(xmlReader, xmlReadingLog);
9309 				}
9310 				else if(xmlReader.name()==QString("ConstraintTeachersMaxBuildingChangesPerWeek")){
9311 					crt_constraint=readTeachersMaxBuildingChangesPerWeek(xmlReader, xmlReadingLog);
9312 				}
9313 				else if(xmlReader.name()==QString("ConstraintTeacherMinGapsBetweenBuildingChanges")){
9314 					crt_constraint=readTeacherMinGapsBetweenBuildingChanges(xmlReader, xmlReadingLog);
9315 				}
9316 				else if(xmlReader.name()==QString("ConstraintTeachersMinGapsBetweenBuildingChanges")){
9317 					crt_constraint=readTeachersMinGapsBetweenBuildingChanges(xmlReader, xmlReadingLog);
9318 				}
9319 				else if(xmlReader.name()==QString("ConstraintStudentsSetMaxBuildingChangesPerDay")){
9320 					crt_constraint=readStudentsSetMaxBuildingChangesPerDay(xmlReader, xmlReadingLog);
9321 				}
9322 				else if(xmlReader.name()==QString("ConstraintStudentsMaxBuildingChangesPerDay")){
9323 					crt_constraint=readStudentsMaxBuildingChangesPerDay(xmlReader, xmlReadingLog);
9324 				}
9325 				else if(xmlReader.name()==QString("ConstraintStudentsSetMaxBuildingChangesPerWeek")){
9326 					crt_constraint=readStudentsSetMaxBuildingChangesPerWeek(xmlReader, xmlReadingLog);
9327 				}
9328 				else if(xmlReader.name()==QString("ConstraintStudentsMaxBuildingChangesPerWeek")){
9329 					crt_constraint=readStudentsMaxBuildingChangesPerWeek(xmlReader, xmlReadingLog);
9330 				}
9331 				else if(xmlReader.name()==QString("ConstraintStudentsSetMinGapsBetweenBuildingChanges")){
9332 					crt_constraint=readStudentsSetMinGapsBetweenBuildingChanges(xmlReader, xmlReadingLog);
9333 				}
9334 				else if(xmlReader.name()==QString("ConstraintStudentsMinGapsBetweenBuildingChanges")){
9335 					crt_constraint=readStudentsMinGapsBetweenBuildingChanges(xmlReader, xmlReadingLog);
9336 				}
9337 				//2019-11-14
9338 				else if((version6AndAbove || (!probably5Morocco && !probably5Algeria && !probably5MA))
9339 				 && xmlReader.name()==QString("ConstraintTeacherMaxRoomChangesPerDay")){
9340 					crt_constraint=readTeacherMaxRoomChangesPerDay(xmlReader, xmlReadingLog);
9341 				}
9342 				else if((version6AndAbove || (!probably5Morocco && !probably5Algeria && !probably5MA))
9343 				 && xmlReader.name()==QString("ConstraintTeachersMaxRoomChangesPerDay")){
9344 					crt_constraint=readTeachersMaxRoomChangesPerDay(xmlReader, xmlReadingLog);
9345 				}
9346 				else if(xmlReader.name()==QString("ConstraintTeacherMaxRoomChangesPerWeek")){
9347 					crt_constraint=readTeacherMaxRoomChangesPerWeek(xmlReader, xmlReadingLog);
9348 				}
9349 				else if(xmlReader.name()==QString("ConstraintTeachersMaxRoomChangesPerWeek")){
9350 					crt_constraint=readTeachersMaxRoomChangesPerWeek(xmlReader, xmlReadingLog);
9351 				}
9352 				else if(xmlReader.name()==QString("ConstraintTeacherMinGapsBetweenRoomChanges")){
9353 					crt_constraint=readTeacherMinGapsBetweenRoomChanges(xmlReader, xmlReadingLog);
9354 				}
9355 				else if(xmlReader.name()==QString("ConstraintTeachersMinGapsBetweenRoomChanges")){
9356 					crt_constraint=readTeachersMinGapsBetweenRoomChanges(xmlReader, xmlReadingLog);
9357 				}
9358 				else if((version6AndAbove || (!probably5Morocco && !probably5Algeria && !probably5MA))
9359 				 && xmlReader.name()==QString("ConstraintStudentsSetMaxRoomChangesPerDay")){
9360 					crt_constraint=readStudentsSetMaxRoomChangesPerDay(xmlReader, xmlReadingLog);
9361 				}
9362 				else if((version6AndAbove || (!probably5Morocco && !probably5Algeria && !probably5MA))
9363 				 && xmlReader.name()==QString("ConstraintStudentsMaxRoomChangesPerDay")){
9364 					crt_constraint=readStudentsMaxRoomChangesPerDay(xmlReader, xmlReadingLog);
9365 				}
9366 				else if(xmlReader.name()==QString("ConstraintStudentsSetMaxRoomChangesPerWeek")){
9367 					crt_constraint=readStudentsSetMaxRoomChangesPerWeek(xmlReader, xmlReadingLog);
9368 				}
9369 				else if(xmlReader.name()==QString("ConstraintStudentsMaxRoomChangesPerWeek")){
9370 					crt_constraint=readStudentsMaxRoomChangesPerWeek(xmlReader, xmlReadingLog);
9371 				}
9372 				else if(xmlReader.name()==QString("ConstraintStudentsSetMinGapsBetweenRoomChanges")){
9373 					crt_constraint=readStudentsSetMinGapsBetweenRoomChanges(xmlReader, xmlReadingLog);
9374 				}
9375 				else if(xmlReader.name()==QString("ConstraintStudentsMinGapsBetweenRoomChanges")){
9376 					crt_constraint=readStudentsMinGapsBetweenRoomChanges(xmlReader, xmlReadingLog);
9377 				}
9378 ////////////////2012-04-29
9379 				else if(xmlReader.name()==QString("ConstraintActivitiesOccupyMaxDifferentRooms")){
9380 					crt_constraint=readActivitiesOccupyMaxDifferentRooms(xmlReader, xmlReadingLog);
9381 				}
9382 ////////////////
9383 ////////////////2013-09-14
9384 				else if(xmlReader.name()==QString("ConstraintActivitiesSameRoomIfConsecutive")){
9385 					crt_constraint=readActivitiesSameRoomIfConsecutive(xmlReader, xmlReadingLog);
9386 				}
9387 ////////////////
9388 
9389 				//mornings-afternoons
9390 				else if((!version6AndAbove && (probably5Morocco || probably5Algeria || probably5MA))
9391 				 && xmlReader.name()==QString("ConstraintTeacherMaxRoomChangesPerDay")){
9392 					if(reportMA5OldSpaceConstraintsChange){
9393 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
9394 						  tr("Your file was detected as an old FET-5 MA, Morocco, or Algeria file, and"
9395 						  " contains a constraint of type teacher max room changes per day, which will be converted"
9396 						  " to a constraint of type teacher max room changes per real day."),
9397 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
9398 						if(t==0)
9399 							reportMA5OldSpaceConstraintsChange=false;
9400 					}
9401 					crt_constraint=readOldMATeacherMaxRoomChangesPerDay(xmlReader, xmlReadingLog);
9402 				}
9403 				else if(xmlReader.name()==QString("ConstraintTeacherMaxRoomChangesPerRealDay")){
9404 					crt_constraint=readTeacherMaxRoomChangesPerRealDay(xmlReader, xmlReadingLog);
9405 				}
9406 
9407 				else if((!version6AndAbove && (probably5Morocco || probably5Algeria || probably5MA))
9408 				 && xmlReader.name()==QString("ConstraintTeachersMaxRoomChangesPerDay")){
9409 					if(reportMA5OldSpaceConstraintsChange){
9410 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
9411 						  tr("Your file was detected as an old FET-5 MA, Morocco, or Algeria file, and"
9412 						  " contains a constraint of type teachers max room changes per day, which will be converted"
9413 						  " to a constraint of type teachers max room changes per real day."),
9414 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
9415 						if(t==0)
9416 							reportMA5OldSpaceConstraintsChange=false;
9417 					}
9418 					crt_constraint=readOldMATeachersMaxRoomChangesPerDay(xmlReader, xmlReadingLog);
9419 				}
9420 				else if(xmlReader.name()==QString("ConstraintTeachersMaxRoomChangesPerRealDay")){
9421 					crt_constraint=readTeachersMaxRoomChangesPerRealDay(xmlReader, xmlReadingLog);
9422 				}
9423 
9424 				else if((!version6AndAbove && (probably5Morocco || probably5Algeria || probably5MA))
9425 				 && xmlReader.name()==QString("ConstraintStudentsSetMaxRoomChangesPerDay")){
9426 					if(reportMA5OldSpaceConstraintsChange){
9427 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
9428 						  tr("Your file was detected as an old FET-5 MA, Morocco, or Algeria file, and"
9429 						  " contains a constraint of type students set max room changes per day, which will be converted"
9430 						  " to a constraint of type students set max room changes per real day."),
9431 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
9432 						if(t==0)
9433 							reportMA5OldSpaceConstraintsChange=false;
9434 					}
9435 					crt_constraint=readOldMAStudentsSetMaxRoomChangesPerDay(xmlReader, xmlReadingLog);
9436 				}
9437 				else if(xmlReader.name()==QString("ConstraintStudentsSetMaxRoomChangesPerRealDay")){
9438 					crt_constraint=readStudentsSetMaxRoomChangesPerRealDay(xmlReader, xmlReadingLog);
9439 				}
9440 
9441 				else if((!version6AndAbove && (probably5Morocco || probably5Algeria || probably5MA))
9442 				 && xmlReader.name()==QString("ConstraintStudentsMaxRoomChangesPerDay")){
9443 					if(reportMA5OldSpaceConstraintsChange){
9444 						int t=RulesReconcilableMessage::information(parent, tr("FET information"),
9445 						  tr("Your file was detected as an old FET-5 MA, Morocco, or Algeria file, and"
9446 						  " contains a constraint of type students max room changes per day, which will be converted"
9447 						  " to a constraint of type students max room changes per real day."),
9448 						  tr("Skip rest"), tr("See next"), QString(), 1, 0 );
9449 						if(t==0)
9450 							reportMA5OldSpaceConstraintsChange=false;
9451 					}
9452 					crt_constraint=readOldMAStudentsMaxRoomChangesPerDay(xmlReader, xmlReadingLog);
9453 				}
9454 				else if(xmlReader.name()==QString("ConstraintStudentsMaxRoomChangesPerRealDay")){
9455 					crt_constraint=readStudentsMaxRoomChangesPerRealDay(xmlReader, xmlReadingLog);
9456 				}
9457 
9458 				else{
9459 					unrecognizedXmlTags.append(xmlReader.name().toString());
9460 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
9461 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
9462 
9463 					xmlReader.skipCurrentElement();
9464 					xmlReaderNumberOfUnrecognizedFields++;
9465 				}
9466 
9467 //corruptConstraintSpace:
9468 				//here we skip an invalid constraint or add a valid one
9469 				if(crt_constraint!=nullptr){
9470 					assert(crt_constraint!=nullptr);
9471 
9472 					bool tmp=this->addSpaceConstraint(crt_constraint);
9473 					if(!tmp){
9474 						if(seeNextWarnNotAddedSpaceConstraint){
9475 							int t=RulesReconcilableMessage::warning(parent, tr("FET information"),
9476 							 tr("Constraint\n%1\nnot added - must be a duplicate").
9477 							 arg(crt_constraint->getDetailedDescription(*this)), tr("Skip rest"), tr("See next"), QString(""), 1, 0);
9478 							if(t==0)
9479 								seeNextWarnNotAddedSpaceConstraint=false;
9480 						}
9481 						delete crt_constraint;
9482 					}
9483 					else
9484 						nc++;
9485 				}
9486 			}
9487 			xmlReadingLog+="  Added "+CustomFETString::number(nc)+" space constraints\n";
9488 			reducedXmlLog+="Added "+CustomFETString::number(nc)+" space constraints\n";
9489 		}
9490 		else if(xmlReader.name()==QString("Timetable_Generation_Options_List")){
9491 			int tgol=0;
9492 			assert(xmlReader.isStartElement());
9493 			while(xmlReader.readNextStartElement()){
9494 				xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
9495 
9496 				if(xmlReader.name()==QString("GroupActivitiesInInitialOrder")){
9497 					tgol++;
9498 					GroupActivitiesInInitialOrderItem* item=new GroupActivitiesInInitialOrderItem();
9499 					int nActs=-1;
9500 					assert(xmlReader.isStartElement());
9501 					while(xmlReader.readNextStartElement()){
9502 						xmlReadingLog+="   Found "+xmlReader.name().toString()+" tag\n";
9503 
9504 						if(xmlReader.name()==QString("Number_of_Activities")){
9505 							QString text=xmlReader.readElementText();
9506 							nActs=text.toInt();
9507 							xmlReadingLog+="    Read n_activities="+CustomFETString::number(nActs)+"\n";
9508 						}
9509 						else if(xmlReader.name()==QString("Activity_Id")){
9510 							QString text=xmlReader.readElementText();
9511 							int id=text.toInt();
9512 							xmlReadingLog+="    Activity id="+CustomFETString::number(id)+"\n";
9513 							item->ids.append(id);
9514 						}
9515 						else if(xmlReader.name()==QString("Active")){
9516 							QString text=xmlReader.readElementText();
9517 							if(text=="false"){
9518 								item->active=false;
9519 							}
9520 						}
9521 						else if(xmlReader.name()==QString("Comments")){
9522 							QString text=xmlReader.readElementText();
9523 							item->comments=text;
9524 						}
9525 						else{
9526 							unrecognizedXmlTags.append(xmlReader.name().toString());
9527 							unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
9528 							unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
9529 
9530 							xmlReader.skipCurrentElement();
9531 							xmlReaderNumberOfUnrecognizedFields++;
9532 						}
9533 					}
9534 					if(!(nActs==item->ids.count())){
9535 						xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Activities").arg("Activity_Id"));
9536 						delete item;
9537 					}
9538 					else{
9539 						assert(nActs==item->ids.count());
9540 						groupActivitiesInInitialOrderList.append(item);
9541 					}
9542 				}
9543 				else{
9544 					unrecognizedXmlTags.append(xmlReader.name().toString());
9545 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
9546 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
9547 
9548 					xmlReader.skipCurrentElement();
9549 					xmlReaderNumberOfUnrecognizedFields++;
9550 				}
9551 			}
9552 			xmlReadingLog+="  Added "+CustomFETString::number(tgol)+" timetable generation options\n";
9553 			reducedXmlLog+="Added "+CustomFETString::number(tgol)+" timetable generation options\n";
9554 		}
9555 		else{
9556 			unrecognizedXmlTags.append(xmlReader.name().toString());
9557 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
9558 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
9559 
9560 			xmlReader.skipCurrentElement();
9561 			xmlReaderNumberOfUnrecognizedFields++;
9562 		}
9563 	}
9564 
9565 	if(xmlReader.error()){
9566 		RulesIrreconcilableMessage::warning(parent, tr("FET warning"),
9567 		 tr("Could not read file - XML parse error at line %1, column %2:\n%3", "The error description is %3")
9568 		 .arg(xmlReader.lineNumber())
9569 		 .arg(xmlReader.columnNumber())
9570 		 .arg(xmlReader.errorString()));
9571 
9572 		file.close();
9573 		this->mode=oldMode;
9574 		return false;
9575 	}
9576 	file.close();
9577 
9578 	if(unrecognizedXmlTags.count()>0){
9579 		QString s;
9580 		if(unrecognizedXmlTags.count()>=2){
9581 			s+=tr("There are %1 unrecognized XML tags in your input file. They are written below. Your file will be opened, but"
9582 			 " these tags will be ignored and they probably represent mistakes in your input file:", "You can assume that %1 is at least 2")
9583 			 .arg(unrecognizedXmlTags.count());
9584 		}
9585 		else{
9586 			assert(unrecognizedXmlTags.count()==1);
9587 			s+=tr("There is an unrecognized XML tag in your input file. It is written below. Your file will be opened, but"
9588 			 " this tag will be ignored and it probably represents a mistake in your input file:");
9589 		}
9590 		s+="\n\n";
9591 
9592 		for(int i=0; i<unrecognizedXmlTags.count(); i++){
9593 			s+=tr("Line %1, column %2: %3", "%3 is the unrecognized XML tag which is met in the .fet input file in line %1, column %2")
9594 			 .arg(unrecognizedXmlLineNumbers.at(i)).arg(unrecognizedXmlColumnNumbers.at(i)).arg(unrecognizedXmlTags.at(i));
9595 			s+="\n";
9596 		}
9597 		s.chop(1);
9598 
9599 		RulesReconcilableMessage::warning(parent, tr("FET information"), s);
9600 	}
9601 
9602 	this->internalStructureComputed=false;
9603 
9604 	/*reducedXmlLog+="\n";
9605 	reducedXmlLog+="Note: if you have overlapping students sets (years or groups), a group or a subgroup may be counted more than once. "
9606 		"A unique group name is counted once for each year it belongs to and a unique subgroup name is counted once for each year+group it belongs to.\n";*/
9607 
9608 	if(xmlReaderNumberOfUnrecognizedFields>0){
9609 		xmlReadingLog+="  Warning: There were "+CustomFETString::number(xmlReaderNumberOfUnrecognizedFields)+" unrecognized fields in the input file\n";
9610 
9611 		reducedXmlLog+="\n";
9612 		reducedXmlLog+="Warning: There were "+CustomFETString::number(xmlReaderNumberOfUnrecognizedFields)+" unrecognized fields in the input file\n";
9613 	}
9614 
9615 	if(canWriteLogFile){
9616 		//logStream<<xmlReadingLog;
9617 		logStream<<reducedXmlLog;
9618 	}
9619 
9620 	if(file2.error()>0){
9621 		IrreconcilableCriticalMessage::critical(parent, tr("FET critical"),
9622 		 tr("Saving of logging gave error code %1, which means you cannot see the log of reading the file. Please check your disk free space")
9623 		 .arg(file2.error()));
9624 	}
9625 
9626 	if(canWriteLogFile)
9627 		file2.close();
9628 
9629 	////////////////////////////////////////
9630 
9631 	return true;
9632 }
9633 
write(QWidget * parent,const QString & filename)9634 bool Rules::write(QWidget* parent, const QString& filename)
9635 {
9636 	assert(this->initialized);
9637 
9638 	//QString s;
9639 
9640 	bool exists=false;
9641 	QString filenameTmp=filename;
9642 	if(QFile::exists(filenameTmp)){
9643 		exists=true;
9644 
9645 		filenameTmp.append(QString(".tmp"));
9646 
9647 		if(QFile::exists(filenameTmp)){
9648 			int i=1;
9649 			for(;;){
9650 				QString t2=filenameTmp+CustomFETString::number(i);
9651 				if(!QFile::exists(t2)){
9652 					filenameTmp=t2;
9653 					break;
9654 				}
9655 				i++;
9656 			}
9657 		}
9658 	}
9659 
9660 	assert(!QFile::exists(filenameTmp));
9661 
9662 	QFile file(filenameTmp);
9663 	if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate)){
9664 		IrreconcilableCriticalMessage::critical(parent, tr("FET critical"),
9665 		 tr("Cannot open %1 for writing ... please check write permissions of the selected directory or your disk free space. Saving of file aborted").arg(QFileInfo(filenameTmp).fileName()));
9666 
9667 		return false;
9668 	}
9669 
9670 	QTextStream tos(&file);
9671 
9672 #if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
9673 	tos.setEncoding(QStringConverter::Utf8);
9674 #else
9675 	tos.setCodec("UTF-8");
9676 #endif
9677 	tos.setGenerateByteOrderMark(true);
9678 	//tos.setEncoding(QTextStream::UnicodeUTF8);
9679 
9680 	tos<<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n";
9681 
9682 //	tos<<"<!DOCTYPE FET><FET version=\""+FET_VERSION+"\">\n\n";
9683 	tos<<"<fet version=\""+FET_VERSION+"\">\n\n";
9684 
9685 	QString ms;
9686 	if(this->mode==OFFICIAL)
9687 		ms="Official";
9688 	else if(this->mode==MORNINGS_AFTERNOONS)
9689 		ms="Mornings_Afternoons";
9690 	else if(this->mode==BLOCK_PLANNING)
9691 		ms="Block_Planning";
9692 	else if(this->mode==TERMS)
9693 		ms="Terms";
9694 	else
9695 		assert(0);
9696 	tos<<"<Mode>"+ms+"</Mode>\n\n";
9697 
9698 	//the institution name and the comments
9699 	tos<<"<Institution_Name>"+protect(this->institutionName)+"</Institution_Name>\n\n";
9700 	tos<<"<Comments>"+protect(this->comments)+"</Comments>\n\n";
9701 
9702 	//for terms (Finland)
9703 	if(this->mode==TERMS){
9704 		tos<<"<Number_of_Terms>"+CustomFETString::number(this->nTerms)+"</Number_of_Terms>\n\n";
9705 		tos<<"<Number_of_Days_Per_Term>"+CustomFETString::number(this->nDaysPerTerm)+"</Number_of_Days_Per_Term>\n\n";
9706 	}
9707 
9708 	//the days and the hours
9709 	tos<<"<Days_List>\n<Number_of_Days>"+CustomFETString::number(this->nDaysPerWeek)+"</Number_of_Days>\n";
9710 	for(int i=0; i<this->nDaysPerWeek; i++){
9711 		tos<<"<Day>\n";
9712 		tos<<"	<Name>"+protect(this->daysOfTheWeek[i])+"</Name>\n";
9713 		tos<<"</Day>\n";
9714 	}
9715 	tos<<"</Days_List>\n\n";
9716 
9717 	tos<<"<Hours_List>\n<Number_of_Hours>"+CustomFETString::number(this->nHoursPerDay)+"</Number_of_Hours>\n";
9718 	for(int i=0; i<this->nHoursPerDay; i++){
9719 		tos<<"<Hour>\n";
9720 		tos<<"	<Name>"+protect(this->hoursOfTheDay[i])+"</Name>\n";
9721 		tos<<"</Hour>\n";
9722 	}
9723 	tos<<"</Hours_List>\n\n";
9724 
9725 	//subjects list - should be before teachers list, because each teacher has a list of associated qualified subjects
9726 	tos << "<Subjects_List>\n";
9727 	for(int i=0; i<this->subjectsList.size(); i++){
9728 		Subject* sbj=this->subjectsList[i];
9729 		tos << sbj->getXmlDescription();
9730 	}
9731 	tos << "</Subjects_List>\n\n";
9732 
9733 	//activity tags list
9734 	tos << "<Activity_Tags_List>\n";
9735 	for(int i=0; i<this->activityTagsList.size(); i++){
9736 		ActivityTag* stg=this->activityTagsList[i];
9737 		tos << stg->getXmlDescription();
9738 	}
9739 	tos << "</Activity_Tags_List>\n\n";
9740 
9741 	//teachers list
9742 	tos << "<Teachers_List>\n";
9743 	for(int i=0; i<this->teachersList.size(); i++){
9744 		Teacher* tch=this->teachersList[i];
9745 		tos << tch->getXmlDescription(*this);
9746 	}
9747 	tos << "</Teachers_List>\n\n";
9748 
9749 	//students list
9750 	tos<<"<Students_List>\n";
9751 	for(int i=0; i<this->yearsList.size(); i++){
9752 		StudentsYear* sty=this->yearsList[i];
9753 		tos << sty->getXmlDescription();
9754 	}
9755 	tos<<"</Students_List>\n\n";
9756 
9757 	//activities list
9758 	tos << "<Activities_List>\n";
9759 	for(int i=0; i<this->activitiesList.size(); i++){
9760 		Activity* act=this->activitiesList[i];
9761 		tos << act->getXmlDescription(*this);
9762 		tos << "\n";
9763 	}
9764 	tos << "</Activities_List>\n\n";
9765 
9766 	//buildings list
9767 	tos << "<Buildings_List>\n";
9768 	for(int i=0; i<this->buildingsList.size(); i++){
9769 		Building* bu=this->buildingsList[i];
9770 		tos << bu->getXmlDescription();
9771 	}
9772 	tos << "</Buildings_List>\n\n";
9773 
9774 	//rooms list
9775 	tos << "<Rooms_List>\n";
9776 	for(int i=0; i<this->roomsList.size(); i++){
9777 		Room* rm=this->roomsList[i];
9778 		tos << rm->getXmlDescription();
9779 	}
9780 	tos << "</Rooms_List>\n\n";
9781 
9782 	//time constraints list
9783 	tos << "<Time_Constraints_List>\n";
9784 	for(int i=0; i<this->timeConstraintsList.size(); i++){
9785 		TimeConstraint* ctr=this->timeConstraintsList[i];
9786 		tos << ctr->getXmlDescription(*this);
9787 	}
9788 	tos << "</Time_Constraints_List>\n\n";
9789 
9790 	//constraints list
9791 	tos << "<Space_Constraints_List>\n";
9792 	for(int i=0; i<this->spaceConstraintsList.size(); i++){
9793 		SpaceConstraint* ctr=this->spaceConstraintsList[i];
9794 		tos << ctr->getXmlDescription(*this);
9795 	}
9796 	tos << "</Space_Constraints_List>\n\n";
9797 
9798 	if(groupActivitiesInInitialOrderList.count()>0){
9799 		tos << "<Timetable_Generation_Options_List>\n";
9800 		for(int i=0; i<groupActivitiesInInitialOrderList.count(); i++){
9801 			GroupActivitiesInInitialOrderItem* item=groupActivitiesInInitialOrderList[i];
9802 			tos << item->getXmlDescription(*this);
9803 		}
9804 		tos << "</Timetable_Generation_Options_List>\n\n";
9805 	}
9806 
9807 //	tos<<"</FET>\n";
9808 	tos<<"</fet>\n";
9809 
9810 	//tos<<s;
9811 
9812 	if(file.error()>0){
9813 		IrreconcilableCriticalMessage::critical(parent, tr("FET critical"),
9814 		 tr("Saved file gave error code %1, which means saving is compromised. Please check your disk free space")
9815 		 .arg(file.error()));
9816 
9817 		file.close();
9818 		return false;
9819 	}
9820 
9821 	file.close();
9822 
9823 	if(exists){
9824 		bool tf=QFile::remove(filename);
9825 		assert(tf);
9826 		tf=QFile::rename(filenameTmp, filename);
9827 		assert(tf);
9828 	}
9829 
9830 	return true;
9831 }
9832 
activateTeacher(const QString & teacherName)9833 int Rules::activateTeacher(const QString& teacherName)
9834 {
9835 	int count=0;
9836 	for(int i=0; i<this->activitiesList.size(); i++){
9837 		Activity* act=this->activitiesList[i];
9838 		if(act->searchTeacher(teacherName)){
9839 			if(!act->active)
9840 				count++;
9841 			act->active=true;
9842 		}
9843 	}
9844 
9845 	this->internalStructureComputed=false;
9846 	setRulesModifiedAndOtherThings(this);
9847 
9848 	teachers_schedule_ready=false;
9849 	students_schedule_ready=false;
9850 	rooms_schedule_ready=false;
9851 
9852 	return count;
9853 }
9854 
activateStudents(const QString & studentsName)9855 int Rules::activateStudents(const QString& studentsName)
9856 {
9857 	QSet<QString> allSets;
9858 
9859 	StudentsSet* studentsSet=this->searchStudentsSet(studentsName);
9860 	assert(studentsSet!=nullptr);
9861 	if(studentsSet->type==STUDENTS_SUBGROUP)
9862 		allSets.insert(studentsName);
9863 	else if(studentsSet->type==STUDENTS_GROUP){
9864 		allSets.insert(studentsName);
9865 		StudentsGroup* g=(StudentsGroup*)studentsSet;
9866 		for(StudentsSubgroup* s : qAsConst(g->subgroupsList))
9867 			allSets.insert(s->name);
9868 	}
9869 	else if(studentsSet->type==STUDENTS_YEAR){
9870 		allSets.insert(studentsName);
9871 		StudentsYear* y=(StudentsYear*)studentsSet;
9872 		for(StudentsGroup* g : qAsConst(y->groupsList)){
9873 			allSets.insert(g->name);
9874 			for(StudentsSubgroup* s : qAsConst(g->subgroupsList))
9875 				allSets.insert(s->name);
9876 		}
9877 	}
9878 
9879 	int count=0;
9880 	for(int i=0; i<this->activitiesList.size(); i++){
9881 		Activity* act=this->activitiesList[i];
9882 		if(!act->active){
9883 			for(const QString& studentsSetName : qAsConst(act->studentsNames)){
9884 				if(allSets.contains(studentsSetName)){
9885 					count++;
9886 					act->active=true;
9887 					break;
9888 				}
9889 			}
9890 		}
9891 	}
9892 
9893 	this->internalStructureComputed=false;
9894 	setRulesModifiedAndOtherThings(this);
9895 
9896 	teachers_schedule_ready=false;
9897 	students_schedule_ready=false;
9898 	rooms_schedule_ready=false;
9899 
9900 	return count;
9901 }
9902 
activateSubject(const QString & subjectName)9903 int Rules::activateSubject(const QString& subjectName)
9904 {
9905 	int count=0;
9906 	for(int i=0; i<this->activitiesList.size(); i++){
9907 		Activity* act=this->activitiesList[i];
9908 		if(act->subjectName==subjectName){
9909 			if(!act->active)
9910 				count++;
9911 			act->active=true;
9912 		}
9913 	}
9914 
9915 	this->internalStructureComputed=false;
9916 	setRulesModifiedAndOtherThings(this);
9917 
9918 	teachers_schedule_ready=false;
9919 	students_schedule_ready=false;
9920 	rooms_schedule_ready=false;
9921 
9922 	return count;
9923 }
9924 
activateActivityTag(const QString & activityTagName)9925 int Rules::activateActivityTag(const QString& activityTagName)
9926 {
9927 	int count=0;
9928 	for(int i=0; i<this->activitiesList.size(); i++){
9929 		Activity* act=this->activitiesList[i];
9930 		if(act->activityTagsNames.contains(activityTagName)){
9931 			if(!act->active)
9932 				count++;
9933 			act->active=true;
9934 		}
9935 	}
9936 
9937 	this->internalStructureComputed=false;
9938 	setRulesModifiedAndOtherThings(this);
9939 
9940 	teachers_schedule_ready=false;
9941 	students_schedule_ready=false;
9942 	rooms_schedule_ready=false;
9943 
9944 	return count;
9945 }
9946 
deactivateTeacher(const QString & teacherName)9947 int Rules::deactivateTeacher(const QString& teacherName)
9948 {
9949 	int count=0;
9950 	for(int i=0; i<this->activitiesList.size(); i++){
9951 		Activity* act=this->activitiesList[i];
9952 		if(act->searchTeacher(teacherName)){
9953 			if(act->active)
9954 				count++;
9955 			act->active=false;
9956 		}
9957 	}
9958 
9959 	this->internalStructureComputed=false;
9960 	setRulesModifiedAndOtherThings(this);
9961 
9962 	teachers_schedule_ready=false;
9963 	students_schedule_ready=false;
9964 	rooms_schedule_ready=false;
9965 
9966 	return count;
9967 }
9968 
deactivateStudents(const QString & studentsName)9969 int Rules::deactivateStudents(const QString& studentsName)
9970 {
9971 	QSet<QString> allSets;
9972 
9973 	StudentsSet* studentsSet=this->searchStudentsSet(studentsName);
9974 	assert(studentsSet!=nullptr);
9975 	if(studentsSet->type==STUDENTS_SUBGROUP)
9976 		allSets.insert(studentsName);
9977 	else if(studentsSet->type==STUDENTS_GROUP){
9978 		allSets.insert(studentsName);
9979 		StudentsGroup* g=(StudentsGroup*)studentsSet;
9980 		for(StudentsSubgroup* s : qAsConst(g->subgroupsList))
9981 			allSets.insert(s->name);
9982 	}
9983 	else if(studentsSet->type==STUDENTS_YEAR){
9984 		allSets.insert(studentsName);
9985 		StudentsYear* y=(StudentsYear*)studentsSet;
9986 		for(StudentsGroup* g : qAsConst(y->groupsList)){
9987 			allSets.insert(g->name);
9988 			for(StudentsSubgroup* s : qAsConst(g->subgroupsList))
9989 				allSets.insert(s->name);
9990 		}
9991 	}
9992 
9993 	int count=0;
9994 	for(int i=0; i<this->activitiesList.size(); i++){
9995 		Activity* act=this->activitiesList[i];
9996 		if(act->active){
9997 			for(const QString& studentsSetName : qAsConst(act->studentsNames)){
9998 				if(allSets.contains(studentsSetName)){
9999 					count++;
10000 					act->active=false;
10001 					break;
10002 				}
10003 			}
10004 		}
10005 	}
10006 
10007 	this->internalStructureComputed=false;
10008 	setRulesModifiedAndOtherThings(this);
10009 
10010 	teachers_schedule_ready=false;
10011 	students_schedule_ready=false;
10012 	rooms_schedule_ready=false;
10013 
10014 	return count;
10015 }
10016 
deactivateSubject(const QString & subjectName)10017 int Rules::deactivateSubject(const QString& subjectName)
10018 {
10019 	int count=0;
10020 	for(int i=0; i<this->activitiesList.size(); i++){
10021 		Activity* act=this->activitiesList[i];
10022 		if(act->subjectName==subjectName){
10023 			if(act->active)
10024 				count++;
10025 			act->active=false;
10026 		}
10027 	}
10028 
10029 	this->internalStructureComputed=false;
10030 	setRulesModifiedAndOtherThings(this);
10031 
10032 	teachers_schedule_ready=false;
10033 	students_schedule_ready=false;
10034 	rooms_schedule_ready=false;
10035 
10036 	return count;
10037 }
10038 
deactivateActivityTag(const QString & activityTagName)10039 int Rules::deactivateActivityTag(const QString& activityTagName)
10040 {
10041 	int count=0;
10042 	for(int i=0; i<this->activitiesList.size(); i++){
10043 		Activity* act=this->activitiesList[i];
10044 		if(act->activityTagsNames.contains(activityTagName)){
10045 			if(act->active)
10046 				count++;
10047 			act->active=false;
10048 		}
10049 	}
10050 
10051 	this->internalStructureComputed=false;
10052 	setRulesModifiedAndOtherThings(this);
10053 
10054 	teachers_schedule_ready=false;
10055 	students_schedule_ready=false;
10056 	rooms_schedule_ready=false;
10057 
10058 	return count;
10059 }
10060 
makeActivityTagPrintable(const QString & activityTagName)10061 void Rules::makeActivityTagPrintable(const QString& activityTagName)
10062 {
10063 	int i=searchActivityTag(activityTagName);
10064 	assert(i>=0 && i<activityTagsList.count());
10065 
10066 	ActivityTag* at=activityTagsList[i];
10067 
10068 	if(at->printable==false){
10069 		at->printable=true;
10070 
10071 		this->internalStructureComputed=false;
10072 		setRulesModifiedAndOtherThings(this);
10073 
10074 		teachers_schedule_ready=false;
10075 		students_schedule_ready=false;
10076 		rooms_schedule_ready=false;
10077 	}
10078 }
10079 
makeActivityTagNotPrintable(const QString & activityTagName)10080 void Rules::makeActivityTagNotPrintable(const QString& activityTagName)
10081 {
10082 	int i=searchActivityTag(activityTagName);
10083 	assert(i>=0 && i<activityTagsList.count());
10084 
10085 	ActivityTag* at=activityTagsList[i];
10086 
10087 	if(at->printable==true){
10088 		at->printable=false;
10089 
10090 		this->internalStructureComputed=false;
10091 		setRulesModifiedAndOtherThings(this);
10092 
10093 		teachers_schedule_ready=false;
10094 		students_schedule_ready=false;
10095 		rooms_schedule_ready=false;
10096 	}
10097 }
10098 
readBasicCompulsoryTime(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)10099 TimeConstraint* Rules::readBasicCompulsoryTime(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
10100 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintBasicCompulsoryTime"));
10101 	ConstraintBasicCompulsoryTime* cn=new ConstraintBasicCompulsoryTime();
10102 	while(xmlReader.readNextStartElement()){
10103 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
10104 		if(xmlReader.name()==QString("Weight")){
10105 			//cn->weight=customFETStrToDouble(text);
10106 			xmlReader.skipCurrentElement();
10107 			xmlReadingLog+="    Ignoring old tag - weight - generating automatic 100% weight percentage\n";
10108 			cn->weightPercentage=100;
10109 		}
10110 		else if(xmlReader.name()==QString("Weight_Percentage")){
10111 			QString text=xmlReader.readElementText();
10112 			cn->weightPercentage=customFETStrToDouble(text);
10113 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
10114 		}
10115 		else if(xmlReader.name()==QString("Active")){
10116 			QString text=xmlReader.readElementText();
10117 			if(text=="false"){
10118 				cn->active=false;
10119 			}
10120 		}
10121 		else if(xmlReader.name()==QString("Comments")){
10122 			QString text=xmlReader.readElementText();
10123 			cn->comments=text;
10124 		}
10125 		else if(xmlReader.name()==QString("Compulsory")){
10126 			QString text=xmlReader.readElementText();
10127 			if(text=="yes"){
10128 				//cn->compulsory=true;
10129 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
10130 				cn->weightPercentage=100;
10131 			}
10132 			else{
10133 				//cn->compulsory=false;
10134 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
10135 				cn->weightPercentage=0;
10136 			}
10137 		}
10138 		else{
10139 			unrecognizedXmlTags.append(xmlReader.name().toString());
10140 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
10141 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
10142 
10143 			xmlReader.skipCurrentElement();
10144 			xmlReaderNumberOfUnrecognizedFields++;
10145 		}
10146 	}
10147 	return cn;
10148 }
10149 
readTeacherNotAvailable(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)10150 TimeConstraint* Rules::readTeacherNotAvailable(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
10151 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherNotAvailable"));
10152 
10153 	QList<int> days;
10154 	QList<int> hours;
10155 	QString teacher;
10156 	double weightPercentage=100;
10157 	int d=-1, h1=-1, h2=-1;
10158 	bool active=true;
10159 	QString comments=QString("");
10160 	while(xmlReader.readNextStartElement()){
10161 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
10162 		if(xmlReader.name()==QString("Weight_Percentage")){
10163 			QString text=xmlReader.readElementText();
10164 			weightPercentage=customFETStrToDouble(text);
10165 			if(weightPercentage<0){
10166 				xmlReader.raiseError(tr("Weight percentage incorrect"));
10167 				return nullptr;
10168 			}
10169 			assert(weightPercentage>=0);
10170 			xmlReadingLog+="    Read weight percentage="+CustomFETString::number(weightPercentage)+"\n";
10171 		}
10172 		else if(xmlReader.name()==QString("Active")){
10173 			QString text=xmlReader.readElementText();
10174 			if(text=="false"){
10175 				active=false;
10176 			}
10177 		}
10178 		else if(xmlReader.name()==QString("Comments")){
10179 			QString text=xmlReader.readElementText();
10180 			comments=text;
10181 		}
10182 		else if(xmlReader.name()==QString("Day")){
10183 			QString text=xmlReader.readElementText();
10184 			for(d=0; d<this->nDaysPerWeek; d++)
10185 				if(this->daysOfTheWeek[d]==text)
10186 					break;
10187 			if(d>=this->nDaysPerWeek){
10188 				xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
10189 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
10190 					tr("Constraint TeacherNotAvailable day corrupt for teacher %1, day %2 is inexistent ... ignoring constraint")
10191 					.arg(teacher)
10192 					.arg(text));*/
10193 				//cn=nullptr;
10194 
10195 				return nullptr;
10196 				//goto corruptConstraintTime;
10197 			}
10198 			assert(d<this->nDaysPerWeek);
10199 			xmlReadingLog+="    Crt. day="+this->daysOfTheWeek[d]+"\n";
10200 		}
10201 		else if(xmlReader.name()==QString("Start_Hour")){
10202 			QString text=xmlReader.readElementText();
10203 			for(h1=0; h1 < this->nHoursPerDay; h1++)
10204 				if(this->hoursOfTheDay[h1]==text)
10205 					break;
10206 			if(h1==this->nHoursPerDay){
10207 				xmlReader.raiseError(tr("Hour %1 is the last hour - impossible").arg(text));
10208 				return nullptr;
10209 			}
10210 			else if(h1>this->nHoursPerDay){
10211 				xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
10212 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
10213 					tr("Constraint TeacherNotAvailable start hour corrupt for teacher %1, hour %2 is inexistent ... ignoring constraint")
10214 					.arg(teacher)
10215 					.arg(text));*/
10216 				//cn=nullptr;
10217 
10218 				return nullptr;
10219 				//goto corruptConstraintTime;
10220 			}
10221 			assert(h1>=0 && h1 < this->nHoursPerDay);
10222 			xmlReadingLog+="    Start hour="+this->hoursOfTheDay[h1]+"\n";
10223 		}
10224 		else if(xmlReader.name()==QString("End_Hour")){
10225 			QString text=xmlReader.readElementText();
10226 			for(h2=0; h2 < this->nHoursPerDay; h2++)
10227 				if(this->hoursOfTheDay[h2]==text)
10228 					break;
10229 			if(h2==0){
10230 				xmlReader.raiseError(tr("Hour %1 is the first hour - impossible").arg(text));
10231 				return nullptr;
10232 			}
10233 			else if(h2>this->nHoursPerDay){
10234 				xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
10235 				return nullptr;
10236 			}
10237 			/*if(h2<=0 || h2>this->nHoursPerDay){
10238 				RulesReconcilableMessage::information(parent, tr("FET information"),
10239 					tr("Constraint TeacherNotAvailable end hour corrupt for teacher %1, hour %2 is inexistent ... ignoring constraint")
10240 					.arg(teacher)
10241 					.arg(text));
10242 
10243 				return nullptr;
10244 				//goto corruptConstraintTime;
10245 			}*/
10246 			assert(h2>0 && h2 <= this->nHoursPerDay);
10247 			xmlReadingLog+="    End hour="+this->hoursOfTheDay[h2]+"\n";
10248 		}
10249 		else if(xmlReader.name()==QString("Teacher_Name")){
10250 			QString text=xmlReader.readElementText();
10251 			teacher=text;
10252 			xmlReadingLog+="    Read teacher name="+teacher+"\n";
10253 		}
10254 		else{
10255 			unrecognizedXmlTags.append(xmlReader.name().toString());
10256 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
10257 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
10258 
10259 			xmlReader.skipCurrentElement();
10260 			xmlReaderNumberOfUnrecognizedFields++;
10261 		}
10262 	}
10263 
10264 	assert(weightPercentage>=0);
10265 	if(d<0){
10266 		xmlReader.raiseError(tr("Field missing: %1").arg("Day"));
10267 		return nullptr;
10268 	}
10269 	else if(h1<0){
10270 		xmlReader.raiseError(tr("Field missing: %1").arg("Start_Hour"));
10271 		return nullptr;
10272 	}
10273 	else if(h2<0){
10274 		xmlReader.raiseError(tr("Field missing: %1").arg("End_Hour"));
10275 		return nullptr;
10276 	}
10277 	assert(d>=0 && h1>=0 && h2>=0);
10278 
10279 	ConstraintTeacherNotAvailableTimes* cn = nullptr;
10280 
10281 	bool found=false;
10282 	for(TimeConstraint* c : qAsConst(this->timeConstraintsList))
10283 		if(c->type==CONSTRAINT_TEACHER_NOT_AVAILABLE_TIMES){
10284 			ConstraintTeacherNotAvailableTimes* tna=(ConstraintTeacherNotAvailableTimes*) c;
10285 			if(tna->teacher==teacher){
10286 				found=true;
10287 
10288 				for(int hh=h1; hh<h2; hh++){
10289 					int k;
10290 					for(k=0; k<tna->days.count(); k++)
10291 						if(tna->days.at(k)==d && tna->hours.at(k)==hh)
10292 							break;
10293 					if(k==tna->days.count()){
10294 						tna->days.append(d);
10295 						tna->hours.append(hh);
10296 					}
10297 				}
10298 
10299 				assert(tna->days.count()==tna->hours.count());
10300 			}
10301 		}
10302 	if(!found){
10303 		days.clear();
10304 		hours.clear();
10305 		for(int hh=h1; hh<h2; hh++){
10306 			days.append(d);
10307 			hours.append(hh);
10308 		}
10309 
10310 		cn=new ConstraintTeacherNotAvailableTimes(weightPercentage, teacher, days, hours);
10311 		cn->active=active;
10312 		cn->comments=comments;
10313 
10314 		return cn;
10315 	}
10316 	else
10317 		return nullptr;
10318 }
10319 
readTeacherNotAvailableTimes(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)10320 TimeConstraint* Rules::readTeacherNotAvailableTimes(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
10321 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherNotAvailableTimes"));
10322 
10323 	ConstraintTeacherNotAvailableTimes* cn=new ConstraintTeacherNotAvailableTimes();
10324 	int nNotAvailableSlots=-1;
10325 	int i=0;
10326 	while(xmlReader.readNextStartElement()){
10327 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
10328 		if(xmlReader.name()==QString("Weight_Percentage")){
10329 			QString text=xmlReader.readElementText();
10330 			cn->weightPercentage=customFETStrToDouble(text);
10331 			xmlReadingLog+="    Read weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
10332 		}
10333 		else if(xmlReader.name()==QString("Active")){
10334 			QString text=xmlReader.readElementText();
10335 			if(text=="false"){
10336 				cn->active=false;
10337 			}
10338 		}
10339 		else if(xmlReader.name()==QString("Comments")){
10340 			QString text=xmlReader.readElementText();
10341 			cn->comments=text;
10342 		}
10343 
10344 		else if(xmlReader.name()==QString("Number_of_Not_Available_Times")){
10345 			QString text=xmlReader.readElementText();
10346 			nNotAvailableSlots=text.toInt();
10347 			xmlReadingLog+="    Read number of not available times="+CustomFETString::number(nNotAvailableSlots)+"\n";
10348 		}
10349 
10350 		else if(xmlReader.name()==QString("Not_Available_Time")){
10351 			xmlReadingLog+="    Read: not available time\n";
10352 
10353 			int d=-1;
10354 			int h=-1;
10355 
10356 			assert(xmlReader.isStartElement());
10357 			while(xmlReader.readNextStartElement()){
10358 				xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
10359 				if(xmlReader.name()==QString("Day")){
10360 					QString text=xmlReader.readElementText();
10361 					for(d=0; d<this->nDaysPerWeek; d++)
10362 						if(this->daysOfTheWeek[d]==text)
10363 							break;
10364 
10365 					if(d>=this->nDaysPerWeek){
10366 						xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
10367 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
10368 							tr("Constraint TeacherNotAvailableTimes day corrupt for teacher %1, day %2 is inexistent ... ignoring constraint")
10369 							.arg(cn->teacher)
10370 							.arg(text));*/
10371 						delete cn;
10372 						cn=nullptr;
10373 						//goto corruptConstraintTime;
10374 						return nullptr;
10375 					}
10376 
10377 					assert(d<this->nDaysPerWeek);
10378 					xmlReadingLog+="    Day="+this->daysOfTheWeek[d]+"("+CustomFETString::number(i)+")"+"\n";
10379 				}
10380 				else if(xmlReader.name()==QString("Hour")){
10381 					QString text=xmlReader.readElementText();
10382 					for(h=0; h < this->nHoursPerDay; h++)
10383 						if(this->hoursOfTheDay[h]==text)
10384 							break;
10385 
10386 					if(h>=this->nHoursPerDay){
10387 						xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
10388 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
10389 							tr("Constraint TeacherNotAvailableTimes hour corrupt for teacher %1, hour %2 is inexistent ... ignoring constraint")
10390 							.arg(cn->teacher)
10391 							.arg(text));*/
10392 						delete cn;
10393 						cn=nullptr;
10394 						//goto corruptConstraintTime;
10395 						return nullptr;
10396 					}
10397 
10398 					assert(h>=0 && h < this->nHoursPerDay);
10399 					xmlReadingLog+="    Hour="+this->hoursOfTheDay[h]+"\n";
10400 				}
10401 				else{
10402 					unrecognizedXmlTags.append(xmlReader.name().toString());
10403 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
10404 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
10405 
10406 					xmlReader.skipCurrentElement();
10407 					xmlReaderNumberOfUnrecognizedFields++;
10408 				}
10409 			}
10410 			i++;
10411 
10412 			cn->days.append(d);
10413 			cn->hours.append(h);
10414 
10415 			if(d==-1 || h==-1){
10416 				xmlReader.raiseError(tr("%1 is incorrect").arg("Not_Available_Time"));
10417 				delete cn;
10418 				cn=nullptr;
10419 				return nullptr;
10420 			}
10421 		}
10422 		else if(xmlReader.name()==QString("Teacher")){
10423 			QString text=xmlReader.readElementText();
10424 			cn->teacher=text;
10425 			xmlReadingLog+="    Read teacher name="+cn->teacher+"\n";
10426 		}
10427 		else{
10428 			unrecognizedXmlTags.append(xmlReader.name().toString());
10429 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
10430 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
10431 
10432 			xmlReader.skipCurrentElement();
10433 			xmlReaderNumberOfUnrecognizedFields++;
10434 		}
10435 	}
10436 	assert(i==cn->days.count() && i==cn->hours.count());
10437 	if(!(i==nNotAvailableSlots)){
10438 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Not_Available_Times").arg("Not_Available_Time"));
10439 		delete cn;
10440 		cn=nullptr;
10441 		return nullptr;
10442 	}
10443 	assert(i==nNotAvailableSlots);
10444 
10445 	return cn;
10446 }
10447 
readTeacherMaxDaysPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)10448 TimeConstraint* Rules::readTeacherMaxDaysPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
10449 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxDaysPerWeek"));
10450 
10451 	ConstraintTeacherMaxDaysPerWeek* cn=new ConstraintTeacherMaxDaysPerWeek();
10452 	while(xmlReader.readNextStartElement()){
10453 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
10454 		if(xmlReader.name()==QString("Weight")){
10455 			//cn->weight=customFETStrToDouble(text);
10456 			xmlReader.skipCurrentElement();
10457 			xmlReadingLog+="    Ignoring old tag - weight - generating 100% weight percentage\n";
10458 			cn->weightPercentage=100;
10459 		}
10460 		else if(xmlReader.name()==QString("Weight_Percentage")){
10461 			QString text=xmlReader.readElementText();
10462 			cn->weightPercentage=customFETStrToDouble(text);
10463 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
10464 		}
10465 		else if(xmlReader.name()==QString("Active")){
10466 			QString text=xmlReader.readElementText();
10467 			if(text=="false"){
10468 				cn->active=false;
10469 			}
10470 		}
10471 		else if(xmlReader.name()==QString("Comments")){
10472 			QString text=xmlReader.readElementText();
10473 			cn->comments=text;
10474 		}
10475 		else if(xmlReader.name()==QString("Compulsory")){
10476 			QString text=xmlReader.readElementText();
10477 			if(text=="yes"){
10478 				//cn->compulsory=true;
10479 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
10480 				cn->weightPercentage=100;
10481 			}
10482 			else{
10483 				//cn->compulsory=false;
10484 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
10485 				cn->weightPercentage=0;
10486 			}
10487 		}
10488 		else if(xmlReader.name()==QString("Teacher_Name")){
10489 			QString text=xmlReader.readElementText();
10490 			cn->teacherName=text;
10491 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
10492 		}
10493 		else if(xmlReader.name()==QString("Max_Days_Per_Week")){
10494 			QString text=xmlReader.readElementText();
10495 			cn->maxDaysPerWeek=text.toInt();
10496 			if(cn->maxDaysPerWeek<=0 || cn->maxDaysPerWeek>this->nDaysPerWeek){
10497 				xmlReader.raiseError(tr("%1 is incorrect").arg("Max_Days_Per_Week"));
10498 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
10499 					tr("Constraint TeacherMaxDaysPerWeek max days corrupt for teacher %1, max days %2 <= 0 or >nDaysPerWeek, ignoring constraint")
10500 					.arg(cn->teacherName)
10501 					.arg(text));*/
10502 				delete cn;
10503 				cn=nullptr;
10504 				return nullptr;
10505 			}
10506 			assert(cn->maxDaysPerWeek>0 && cn->maxDaysPerWeek <= this->nDaysPerWeek);
10507 			xmlReadingLog+="    Max. days per week="+CustomFETString::number(cn->maxDaysPerWeek)+"\n";
10508 		}
10509 		else{
10510 			unrecognizedXmlTags.append(xmlReader.name().toString());
10511 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
10512 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
10513 
10514 			xmlReader.skipCurrentElement();
10515 			xmlReaderNumberOfUnrecognizedFields++;
10516 		}
10517 	}
10518 	return cn;
10519 }
10520 
readTeachersMaxDaysPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)10521 TimeConstraint* Rules::readTeachersMaxDaysPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
10522 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxDaysPerWeek"));
10523 
10524 	ConstraintTeachersMaxDaysPerWeek* cn=new ConstraintTeachersMaxDaysPerWeek();
10525 	while(xmlReader.readNextStartElement()){
10526 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
10527 		if(xmlReader.name()==QString("Weight_Percentage")){
10528 			QString text=xmlReader.readElementText();
10529 			cn->weightPercentage=customFETStrToDouble(text);
10530 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
10531 		}
10532 		else if(xmlReader.name()==QString("Active")){
10533 			QString text=xmlReader.readElementText();
10534 			if(text=="false"){
10535 				cn->active=false;
10536 			}
10537 		}
10538 		else if(xmlReader.name()==QString("Comments")){
10539 			QString text=xmlReader.readElementText();
10540 			cn->comments=text;
10541 		}
10542 		else if(xmlReader.name()==QString("Max_Days_Per_Week")){
10543 			QString text=xmlReader.readElementText();
10544 			cn->maxDaysPerWeek=text.toInt();
10545 			if(cn->maxDaysPerWeek<=0 || cn->maxDaysPerWeek>this->nDaysPerWeek){
10546 				xmlReader.raiseError(tr("%1 is incorrect").arg("Max_Days_Per_Week"));
10547 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
10548 					tr("Constraint TeachersMaxDaysPerWeek max days corrupt, max days %1 <= 0 or >nDaysPerWeek, ignoring constraint")
10549 					.arg(text));*/
10550 				delete cn;
10551 				cn=nullptr;
10552 				return nullptr;
10553 			}
10554 			assert(cn->maxDaysPerWeek>0 && cn->maxDaysPerWeek <= this->nDaysPerWeek);
10555 			xmlReadingLog+="    Max. days per week="+CustomFETString::number(cn->maxDaysPerWeek)+"\n";
10556 		}
10557 		else{
10558 			unrecognizedXmlTags.append(xmlReader.name().toString());
10559 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
10560 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
10561 
10562 			xmlReader.skipCurrentElement();
10563 			xmlReaderNumberOfUnrecognizedFields++;
10564 		}
10565 	}
10566 	return cn;
10567 }
10568 
readTeacherMinDaysPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)10569 TimeConstraint* Rules::readTeacherMinDaysPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
10570 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMinDaysPerWeek"));
10571 
10572 	ConstraintTeacherMinDaysPerWeek* cn=new ConstraintTeacherMinDaysPerWeek();
10573 	while(xmlReader.readNextStartElement()){
10574 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
10575 		if(xmlReader.name()==QString("Weight_Percentage")){
10576 			QString text=xmlReader.readElementText();
10577 			cn->weightPercentage=customFETStrToDouble(text);
10578 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
10579 		}
10580 		else if(xmlReader.name()==QString("Active")){
10581 			QString text=xmlReader.readElementText();
10582 			if(text=="false"){
10583 				cn->active=false;
10584 			}
10585 		}
10586 		else if(xmlReader.name()==QString("Comments")){
10587 			QString text=xmlReader.readElementText();
10588 			cn->comments=text;
10589 		}
10590 		else if(xmlReader.name()==QString("Teacher_Name")){
10591 			QString text=xmlReader.readElementText();
10592 			cn->teacherName=text;
10593 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
10594 		}
10595 		else if(xmlReader.name()==QString("Minimum_Days_Per_Week")){
10596 			QString text=xmlReader.readElementText();
10597 			cn->minDaysPerWeek=text.toInt();
10598 			if(cn->minDaysPerWeek<=0 || cn->minDaysPerWeek>this->nDaysPerWeek){
10599 				xmlReader.raiseError(tr("%1 is incorrect").arg("Minimum_Days_Per_Week"));
10600 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
10601 					tr("Constraint TeacherMinDaysPerWeek min days corrupt for teacher %1, min days %2 <= 0 or >nDaysPerWeek, ignoring constraint")
10602 					.arg(cn->teacherName)
10603 					.arg(text));*/
10604 				delete cn;
10605 				cn=nullptr;
10606 				return nullptr;
10607 			}
10608 			assert(cn->minDaysPerWeek>0 && cn->minDaysPerWeek <= this->nDaysPerWeek);
10609 			xmlReadingLog+="    Min. days per week="+CustomFETString::number(cn->minDaysPerWeek)+"\n";
10610 		}
10611 		else{
10612 			unrecognizedXmlTags.append(xmlReader.name().toString());
10613 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
10614 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
10615 
10616 			xmlReader.skipCurrentElement();
10617 			xmlReaderNumberOfUnrecognizedFields++;
10618 		}
10619 	}
10620 	return cn;
10621 }
10622 
readTeachersMinDaysPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)10623 TimeConstraint* Rules::readTeachersMinDaysPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
10624 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMinDaysPerWeek"));
10625 
10626 	ConstraintTeachersMinDaysPerWeek* cn=new ConstraintTeachersMinDaysPerWeek();
10627 	while(xmlReader.readNextStartElement()){
10628 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
10629 		if(xmlReader.name()==QString("Weight_Percentage")){
10630 			QString text=xmlReader.readElementText();
10631 			cn->weightPercentage=customFETStrToDouble(text);
10632 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
10633 		}
10634 		else if(xmlReader.name()==QString("Active")){
10635 			QString text=xmlReader.readElementText();
10636 			if(text=="false"){
10637 				cn->active=false;
10638 			}
10639 		}
10640 		else if(xmlReader.name()==QString("Comments")){
10641 			QString text=xmlReader.readElementText();
10642 			cn->comments=text;
10643 		}
10644 		else if(xmlReader.name()==QString("Minimum_Days_Per_Week")){
10645 			QString text=xmlReader.readElementText();
10646 			cn->minDaysPerWeek=text.toInt();
10647 			if(cn->minDaysPerWeek<=0 || cn->minDaysPerWeek>this->nDaysPerWeek){
10648 				xmlReader.raiseError(tr("%1 is incorrect").arg("Minimum_Days_Per_Week"));
10649 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
10650 					tr("Constraint TeachersMinDaysPerWeek min days corrupt, min days %1 <= 0 or >nDaysPerWeek, ignoring constraint")
10651 					.arg(text));*/
10652 				delete cn;
10653 				cn=nullptr;
10654 				return nullptr;
10655 			}
10656 			assert(cn->minDaysPerWeek>0 && cn->minDaysPerWeek <= this->nDaysPerWeek);
10657 			xmlReadingLog+="    Min. days per week="+CustomFETString::number(cn->minDaysPerWeek)+"\n";
10658 		}
10659 		else{
10660 			unrecognizedXmlTags.append(xmlReader.name().toString());
10661 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
10662 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
10663 
10664 			xmlReader.skipCurrentElement();
10665 			xmlReaderNumberOfUnrecognizedFields++;
10666 		}
10667 	}
10668 	return cn;
10669 }
10670 
readTeacherIntervalMaxDaysPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)10671 TimeConstraint* Rules::readTeacherIntervalMaxDaysPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
10672 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherIntervalMaxDaysPerWeek"));
10673 	ConstraintTeacherIntervalMaxDaysPerWeek* cn=new ConstraintTeacherIntervalMaxDaysPerWeek();
10674 	cn->maxDaysPerWeek=this->nDaysPerWeek;
10675 	cn->startHour=this->nHoursPerDay;
10676 	cn->endHour=this->nHoursPerDay;
10677 	int h1, h2;
10678 	while(xmlReader.readNextStartElement()){
10679 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
10680 		if(xmlReader.name()==QString("Weight")){
10681 			//cn->weight=customFETStrToDouble(text);
10682 			xmlReader.skipCurrentElement();
10683 			xmlReadingLog+="    Ignoring old tag - weight - generating 100% weight percentage\n";
10684 			cn->weightPercentage=100;
10685 		}
10686 		else if(xmlReader.name()==QString("Weight_Percentage")){
10687 			QString text=xmlReader.readElementText();
10688 			cn->weightPercentage=customFETStrToDouble(text);
10689 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
10690 		}
10691 		else if(xmlReader.name()==QString("Active")){
10692 			QString text=xmlReader.readElementText();
10693 			if(text=="false"){
10694 				cn->active=false;
10695 			}
10696 		}
10697 		else if(xmlReader.name()==QString("Comments")){
10698 			QString text=xmlReader.readElementText();
10699 			cn->comments=text;
10700 		}
10701 		else if(xmlReader.name()==QString("Compulsory")){
10702 			QString text=xmlReader.readElementText();
10703 			if(text=="yes"){
10704 				//cn->compulsory=true;
10705 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
10706 				cn->weightPercentage=100;
10707 			}
10708 			else{
10709 				//cn->compulsory=false;
10710 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
10711 				cn->weightPercentage=0;
10712 			}
10713 		}
10714 		else if(xmlReader.name()==QString("Teacher_Name")){
10715 			QString text=xmlReader.readElementText();
10716 			cn->teacherName=text;
10717 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
10718 		}
10719 		else if(xmlReader.name()==QString("Max_Days_Per_Week")){
10720 			QString text=xmlReader.readElementText();
10721 			cn->maxDaysPerWeek=text.toInt();
10722 			if(cn->maxDaysPerWeek>this->nDaysPerWeek){
10723 				RulesReconcilableMessage::information(parent, tr("FET information"),
10724 					tr("Constraint TeacherIntervalMaxDaysPerWeek max days corrupt for teacher %1, max days %2 >nDaysPerWeek, constraint added, please correct constraint")
10725 					.arg(cn->teacherName)
10726 					.arg(text));
10727 				/*delete cn;
10728 				cn=nullptr;
10729 				goto corruptConstraintTime;*/
10730 			}
10731 			//assert(cn->maxDaysPerWeek>0 && cn->maxDaysPerWeek <= this->nDaysPerWeek);
10732 			xmlReadingLog+="    Max. days per week="+CustomFETString::number(cn->maxDaysPerWeek)+"\n";
10733 		}
10734 		else if(xmlReader.name()==QString("Interval_Start_Hour")){
10735 			QString text=xmlReader.readElementText();
10736 			for(h1=0; h1 < this->nHoursPerDay; h1++)
10737 				if(this->hoursOfTheDay[h1]==text)
10738 					break;
10739 			if(h1>=this->nHoursPerDay){
10740 				xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
10741 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
10742 					tr("Constraint Teacher interval max days per week start hour corrupt for teacher %1, hour %2 is inexistent ... ignoring constraint")
10743 					.arg(cn->teacherName)
10744 					.arg(text));*/
10745 				delete cn;
10746 				//cn=nullptr;
10747 				//goto corruptConstraintTime;
10748 				return nullptr;
10749 			}
10750 			assert(h1>=0 && h1 < this->nHoursPerDay);
10751 			xmlReadingLog+="    Interval start hour="+this->hoursOfTheDay[h1]+"\n";
10752 			cn->startHour=h1;
10753 		}
10754 		else if(xmlReader.name()==QString("Interval_End_Hour")){
10755 			QString text=xmlReader.readElementText();
10756 			if(text==""){
10757 				xmlReadingLog+="    Interval end hour void, meaning end of day\n";
10758 				cn->endHour=this->nHoursPerDay;
10759 			}
10760 			else{
10761 				for(h2=0; h2 < this->nHoursPerDay; h2++)
10762 					if(this->hoursOfTheDay[h2]==text)
10763 						break;
10764 				if(h2>=this->nHoursPerDay){
10765 					xmlReader.raiseError(tr("Hour %1 is inexistent (it is also not void, to specify end of the day)").arg(text));
10766 					/*RulesReconcilableMessage::information(parent, tr("FET information"),
10767 						tr("Constraint Teacher interval max days per week end hour corrupt for teacher %1, hour %2 is inexistent (it is also not void, to specify end of the day) ... ignoring constraint")
10768 						.arg(cn->teacherName)
10769 						.arg(text));*/
10770 					delete cn;
10771 					//cn=nullptr;
10772 					//goto corruptConstraintTime;
10773 					return nullptr;
10774 				}
10775 				assert(h2>=0 && h2 < this->nHoursPerDay);
10776 				xmlReadingLog+="    Interval end hour="+this->hoursOfTheDay[h2]+"\n";
10777 				cn->endHour=h2;
10778 			}
10779 		}
10780 		else{
10781 			unrecognizedXmlTags.append(xmlReader.name().toString());
10782 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
10783 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
10784 
10785 			xmlReader.skipCurrentElement();
10786 			xmlReaderNumberOfUnrecognizedFields++;
10787 		}
10788 	}
10789 	return cn;
10790 }
10791 
readTeachersIntervalMaxDaysPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)10792 TimeConstraint* Rules::readTeachersIntervalMaxDaysPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
10793 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersIntervalMaxDaysPerWeek"));
10794 	ConstraintTeachersIntervalMaxDaysPerWeek* cn=new ConstraintTeachersIntervalMaxDaysPerWeek();
10795 	cn->maxDaysPerWeek=this->nDaysPerWeek;
10796 	cn->startHour=this->nHoursPerDay;
10797 	cn->endHour=this->nHoursPerDay;
10798 	int h1, h2;
10799 	while(xmlReader.readNextStartElement()){
10800 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
10801 		if(xmlReader.name()==QString("Weight")){
10802 			//cn->weight=customFETStrToDouble(text);
10803 			xmlReader.skipCurrentElement();
10804 			xmlReadingLog+="    Ignoring old tag - weight - generating 100% weight percentage\n";
10805 			cn->weightPercentage=100;
10806 		}
10807 		else if(xmlReader.name()==QString("Weight_Percentage")){
10808 			QString text=xmlReader.readElementText();
10809 			cn->weightPercentage=customFETStrToDouble(text);
10810 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
10811 		}
10812 		else if(xmlReader.name()==QString("Active")){
10813 			QString text=xmlReader.readElementText();
10814 			if(text=="false"){
10815 				cn->active=false;
10816 			}
10817 		}
10818 		else if(xmlReader.name()==QString("Comments")){
10819 			QString text=xmlReader.readElementText();
10820 			cn->comments=text;
10821 		}
10822 		else if(xmlReader.name()==QString("Compulsory")){
10823 			QString text=xmlReader.readElementText();
10824 			if(text=="yes"){
10825 				//cn->compulsory=true;
10826 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
10827 				cn->weightPercentage=100;
10828 			}
10829 			else{
10830 				//cn->compulsory=false;
10831 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
10832 				cn->weightPercentage=0;
10833 			}
10834 		}
10835 		/*else if(xmlReader.name()==QString("Teacher_Name")){
10836 			cn->teacherName=text;
10837 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
10838 		}*/
10839 		else if(xmlReader.name()==QString("Max_Days_Per_Week")){
10840 			QString text=xmlReader.readElementText();
10841 			cn->maxDaysPerWeek=text.toInt();
10842 			if(cn->maxDaysPerWeek>this->nDaysPerWeek){
10843 				RulesReconcilableMessage::information(parent, tr("FET information"),
10844 					tr("Constraint TeachersIntervalMaxDaysPerWeek max days corrupt, max days %1 >nDaysPerWeek, constraint added, please correct constraint")
10845 					//.arg(cn->teacherName)
10846 					.arg(text));
10847 				/*delete cn;
10848 				cn=nullptr;
10849 				goto corruptConstraintTime;*/
10850 			}
10851 			//assert(cn->maxDaysPerWeek>0 && cn->maxDaysPerWeek <= this->nDaysPerWeek);
10852 			xmlReadingLog+="    Max. days per week="+CustomFETString::number(cn->maxDaysPerWeek)+"\n";
10853 		}
10854 		else if(xmlReader.name()==QString("Interval_Start_Hour")){
10855 			QString text=xmlReader.readElementText();
10856 			for(h1=0; h1 < this->nHoursPerDay; h1++)
10857 				if(this->hoursOfTheDay[h1]==text)
10858 					break;
10859 			if(h1>=this->nHoursPerDay){
10860 				xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
10861 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
10862 					tr("Constraint Teachers interval max days per week start hour corrupt because hour %1 is inexistent ... ignoring constraint")
10863 					//.arg(cn->teacherName)
10864 					.arg(text));*/
10865 				delete cn;
10866 				//cn=nullptr;
10867 				//goto corruptConstraintTime;
10868 				return nullptr;
10869 			}
10870 			assert(h1>=0 && h1 < this->nHoursPerDay);
10871 			xmlReadingLog+="    Interval start hour="+this->hoursOfTheDay[h1]+"\n";
10872 			cn->startHour=h1;
10873 		}
10874 		else if(xmlReader.name()==QString("Interval_End_Hour")){
10875 			QString text=xmlReader.readElementText();
10876 			if(text==""){
10877 				xmlReadingLog+="    Interval end hour void, meaning end of day\n";
10878 				cn->endHour=this->nHoursPerDay;
10879 			}
10880 			else{
10881 				for(h2=0; h2 < this->nHoursPerDay; h2++)
10882 					if(this->hoursOfTheDay[h2]==text)
10883 						break;
10884 				if(h2>=this->nHoursPerDay){
10885 					xmlReader.raiseError(tr("Hour %1 is inexistent (it is also not void, to specify end of the day)").arg(text));
10886 					/*RulesReconcilableMessage::information(parent, tr("FET information"),
10887 						tr("Constraint Teachers interval max days per week end hour corrupt because hour %1 is inexistent (it is also not void, to specify end of the day) ... ignoring constraint")
10888 						//.arg(cn->teacherName)
10889 						.arg(text));*/
10890 					delete cn;
10891 					//cn=nullptr;
10892 					//goto corruptConstraintTime;
10893 					return nullptr;
10894 				}
10895 				assert(h2>=0 && h2 < this->nHoursPerDay);
10896 				xmlReadingLog+="    Interval end hour="+this->hoursOfTheDay[h2]+"\n";
10897 				cn->endHour=h2;
10898 			}
10899 		}
10900 		else{
10901 			unrecognizedXmlTags.append(xmlReader.name().toString());
10902 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
10903 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
10904 
10905 			xmlReader.skipCurrentElement();
10906 			xmlReaderNumberOfUnrecognizedFields++;
10907 		}
10908 	}
10909 	return cn;
10910 }
10911 
readStudentsSetMaxDaysPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)10912 TimeConstraint* Rules::readStudentsSetMaxDaysPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
10913 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMaxDaysPerWeek"));
10914 	ConstraintStudentsSetMaxDaysPerWeek* cn=new ConstraintStudentsSetMaxDaysPerWeek();
10915 	cn->maxDaysPerWeek=this->nDaysPerWeek;
10916 	while(xmlReader.readNextStartElement()){
10917 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
10918 		if(xmlReader.name()==QString("Weight_Percentage")){
10919 			QString text=xmlReader.readElementText();
10920 			cn->weightPercentage=customFETStrToDouble(text);
10921 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
10922 		}
10923 		else if(xmlReader.name()==QString("Active")){
10924 			QString text=xmlReader.readElementText();
10925 			if(text=="false"){
10926 				cn->active=false;
10927 			}
10928 		}
10929 		else if(xmlReader.name()==QString("Comments")){
10930 			QString text=xmlReader.readElementText();
10931 			cn->comments=text;
10932 		}
10933 		else if(xmlReader.name()==QString("Students")){
10934 			QString text=xmlReader.readElementText();
10935 			cn->students=text;
10936 			xmlReadingLog+="    Read students set name="+cn->students+"\n";
10937 		}
10938 		else if(xmlReader.name()==QString("Max_Days_Per_Week")){
10939 			QString text=xmlReader.readElementText();
10940 			cn->maxDaysPerWeek=text.toInt();
10941 			if(cn->maxDaysPerWeek>this->nDaysPerWeek){
10942 				RulesReconcilableMessage::information(parent, tr("FET information"),
10943 					tr("Constraint StudentsSetMaxDaysPerWeek max days corrupt for students set %1, max days %2 >nDaysPerWeek, constraint added, please correct constraint")
10944 					.arg(cn->students)
10945 					.arg(text));
10946 			}
10947 			xmlReadingLog+="    Max. days per week="+CustomFETString::number(cn->maxDaysPerWeek)+"\n";
10948 		}
10949 		else{
10950 			unrecognizedXmlTags.append(xmlReader.name().toString());
10951 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
10952 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
10953 
10954 			xmlReader.skipCurrentElement();
10955 			xmlReaderNumberOfUnrecognizedFields++;
10956 		}
10957 	}
10958 	return cn;
10959 }
10960 
readStudentsMaxDaysPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)10961 TimeConstraint* Rules::readStudentsMaxDaysPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
10962 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMaxDaysPerWeek"));
10963 	ConstraintStudentsMaxDaysPerWeek* cn=new ConstraintStudentsMaxDaysPerWeek();
10964 	cn->maxDaysPerWeek=this->nDaysPerWeek;
10965 	while(xmlReader.readNextStartElement()){
10966 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
10967 		if(xmlReader.name()==QString("Weight_Percentage")){
10968 			QString text=xmlReader.readElementText();
10969 			cn->weightPercentage=customFETStrToDouble(text);
10970 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
10971 		}
10972 		else if(xmlReader.name()==QString("Active")){
10973 			QString text=xmlReader.readElementText();
10974 			if(text=="false"){
10975 				cn->active=false;
10976 			}
10977 		}
10978 		else if(xmlReader.name()==QString("Comments")){
10979 			QString text=xmlReader.readElementText();
10980 			cn->comments=text;
10981 		}
10982 		else if(xmlReader.name()==QString("Max_Days_Per_Week")){
10983 			QString text=xmlReader.readElementText();
10984 			cn->maxDaysPerWeek=text.toInt();
10985 			if(cn->maxDaysPerWeek>this->nDaysPerWeek){
10986 				RulesReconcilableMessage::information(parent, tr("FET information"),
10987 					tr("Constraint StudentsMaxDaysPerWeek max days corrupt, max days %1 >nDaysPerWeek, constraint added, please correct constraint")
10988 					.arg(text));
10989 			}
10990 			xmlReadingLog+="    Max. days per week="+CustomFETString::number(cn->maxDaysPerWeek)+"\n";
10991 		}
10992 		else{
10993 			unrecognizedXmlTags.append(xmlReader.name().toString());
10994 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
10995 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
10996 
10997 			xmlReader.skipCurrentElement();
10998 			xmlReaderNumberOfUnrecognizedFields++;
10999 		}
11000 	}
11001 	return cn;
11002 }
11003 
readStudentsSetIntervalMaxDaysPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)11004 TimeConstraint* Rules::readStudentsSetIntervalMaxDaysPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
11005 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetIntervalMaxDaysPerWeek"));
11006 	ConstraintStudentsSetIntervalMaxDaysPerWeek* cn=new ConstraintStudentsSetIntervalMaxDaysPerWeek();
11007 	cn->maxDaysPerWeek=this->nDaysPerWeek;
11008 	cn->startHour=this->nHoursPerDay;
11009 	cn->endHour=this->nHoursPerDay;
11010 	int h1, h2;
11011 	while(xmlReader.readNextStartElement()){
11012 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
11013 		if(xmlReader.name()==QString("Weight")){
11014 			//cn->weight=customFETStrToDouble(text);
11015 			xmlReader.skipCurrentElement();
11016 			xmlReadingLog+="    Ignoring old tag - weight - generating 100% weight percentage\n";
11017 			cn->weightPercentage=100;
11018 		}
11019 		else if(xmlReader.name()==QString("Weight_Percentage")){
11020 			QString text=xmlReader.readElementText();
11021 			cn->weightPercentage=customFETStrToDouble(text);
11022 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
11023 		}
11024 		else if(xmlReader.name()==QString("Active")){
11025 			QString text=xmlReader.readElementText();
11026 			if(text=="false"){
11027 				cn->active=false;
11028 			}
11029 		}
11030 		else if(xmlReader.name()==QString("Comments")){
11031 			QString text=xmlReader.readElementText();
11032 			cn->comments=text;
11033 		}
11034 		else if(xmlReader.name()==QString("Compulsory")){
11035 			QString text=xmlReader.readElementText();
11036 			if(text=="yes"){
11037 				//cn->compulsory=true;
11038 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
11039 				cn->weightPercentage=100;
11040 			}
11041 			else{
11042 				//cn->compulsory=false;
11043 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
11044 				cn->weightPercentage=0;
11045 			}
11046 		}
11047 		else if(xmlReader.name()==QString("Students")){
11048 			QString text=xmlReader.readElementText();
11049 			cn->students=text;
11050 			xmlReadingLog+="    Read students set name="+cn->students+"\n";
11051 		}
11052 		else if(xmlReader.name()==QString("Max_Days_Per_Week")){
11053 			QString text=xmlReader.readElementText();
11054 			cn->maxDaysPerWeek=text.toInt();
11055 			if(cn->maxDaysPerWeek>this->nDaysPerWeek){
11056 				RulesReconcilableMessage::information(parent, tr("FET information"),
11057 					tr("Constraint StudentsSetIntervalMaxDaysPerWeek max days corrupt for students set %1, max days %2 >nDaysPerWeek, constraint added, please correct constraint")
11058 					.arg(cn->students)
11059 					.arg(text));
11060 				/*delete cn;
11061 				cn=nullptr;
11062 				goto corruptConstraintTime;*/
11063 			}
11064 			//assert(cn->maxDaysPerWeek>0 && cn->maxDaysPerWeek <= this->nDaysPerWeek);
11065 			xmlReadingLog+="    Max. days per week="+CustomFETString::number(cn->maxDaysPerWeek)+"\n";
11066 		}
11067 		else if(xmlReader.name()==QString("Interval_Start_Hour")){
11068 			QString text=xmlReader.readElementText();
11069 			for(h1=0; h1 < this->nHoursPerDay; h1++)
11070 				if(this->hoursOfTheDay[h1]==text)
11071 					break;
11072 			if(h1>=this->nHoursPerDay){
11073 				xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
11074 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
11075 					tr("Constraint Students set interval max days per week start hour corrupt for students %1, hour %2 is inexistent ... ignoring constraint")
11076 					.arg(cn->students)
11077 					.arg(text));*/
11078 				delete cn;
11079 				//cn=nullptr;
11080 				//goto corruptConstraintTime;
11081 				return nullptr;
11082 			}
11083 			assert(h1>=0 && h1 < this->nHoursPerDay);
11084 			xmlReadingLog+="    Interval start hour="+this->hoursOfTheDay[h1]+"\n";
11085 			cn->startHour=h1;
11086 		}
11087 		else if(xmlReader.name()==QString("Interval_End_Hour")){
11088 			QString text=xmlReader.readElementText();
11089 			if(text==""){
11090 				xmlReadingLog+="    Interval end hour void, meaning end of day\n";
11091 				cn->endHour=this->nHoursPerDay;
11092 			}
11093 			else{
11094 				for(h2=0; h2 < this->nHoursPerDay; h2++)
11095 					if(this->hoursOfTheDay[h2]==text)
11096 						break;
11097 				if(h2>=this->nHoursPerDay){
11098 					xmlReader.raiseError(tr("Hour %1 is inexistent (it is also not void, to specify end of the day)").arg(text));
11099 					/*RulesReconcilableMessage::information(parent, tr("FET information"),
11100 						tr("Constraint Students set interval max days per week end hour corrupt for students %1, hour %2 is inexistent (it is also not void, to specify end of the day) ... ignoring constraint")
11101 						.arg(cn->students)
11102 						.arg(text));*/
11103 					delete cn;
11104 					//cn=nullptr;
11105 					//goto corruptConstraintTime;
11106 					return nullptr;
11107 				}
11108 				assert(h2>=0 && h2 < this->nHoursPerDay);
11109 				xmlReadingLog+="    Interval end hour="+this->hoursOfTheDay[h2]+"\n";
11110 				cn->endHour=h2;
11111 			}
11112 		}
11113 		else{
11114 			unrecognizedXmlTags.append(xmlReader.name().toString());
11115 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
11116 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
11117 
11118 			xmlReader.skipCurrentElement();
11119 			xmlReaderNumberOfUnrecognizedFields++;
11120 		}
11121 	}
11122 	return cn;
11123 }
11124 
readStudentsIntervalMaxDaysPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)11125 TimeConstraint* Rules::readStudentsIntervalMaxDaysPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
11126 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsIntervalMaxDaysPerWeek"));
11127 	ConstraintStudentsIntervalMaxDaysPerWeek* cn=new ConstraintStudentsIntervalMaxDaysPerWeek();
11128 	cn->maxDaysPerWeek=this->nDaysPerWeek;
11129 	cn->startHour=this->nHoursPerDay;
11130 	cn->endHour=this->nHoursPerDay;
11131 	int h1, h2;
11132 	while(xmlReader.readNextStartElement()){
11133 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
11134 		if(xmlReader.name()==QString("Weight")){
11135 			//cn->weight=customFETStrToDouble(text);
11136 			xmlReader.skipCurrentElement();
11137 			xmlReadingLog+="    Ignoring old tag - weight - generating 100% weight percentage\n";
11138 			cn->weightPercentage=100;
11139 		}
11140 		else if(xmlReader.name()==QString("Weight_Percentage")){
11141 			QString text=xmlReader.readElementText();
11142 			cn->weightPercentage=customFETStrToDouble(text);
11143 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
11144 		}
11145 		else if(xmlReader.name()==QString("Active")){
11146 			QString text=xmlReader.readElementText();
11147 			if(text=="false"){
11148 				cn->active=false;
11149 			}
11150 		}
11151 		else if(xmlReader.name()==QString("Comments")){
11152 			QString text=xmlReader.readElementText();
11153 			cn->comments=text;
11154 		}
11155 		else if(xmlReader.name()==QString("Compulsory")){
11156 			QString text=xmlReader.readElementText();
11157 			if(text=="yes"){
11158 				//cn->compulsory=true;
11159 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
11160 				cn->weightPercentage=100;
11161 			}
11162 			else{
11163 				//cn->compulsory=false;
11164 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
11165 				cn->weightPercentage=0;
11166 			}
11167 		}
11168 		/*else if(xmlReader.name()==QString("Students")){
11169 			cn->students=text;
11170 			xmlReadingLog+="    Read students set name="+cn->students+"\n";
11171 		}*/
11172 		else if(xmlReader.name()==QString("Max_Days_Per_Week")){
11173 			QString text=xmlReader.readElementText();
11174 			cn->maxDaysPerWeek=text.toInt();
11175 			if(cn->maxDaysPerWeek>this->nDaysPerWeek){
11176 				RulesReconcilableMessage::information(parent, tr("FET information"),
11177 					tr("Constraint StudentsIntervalMaxDaysPerWeek max days corrupt: max days %1 >nDaysPerWeek, constraint added, please correct constraint")
11178 					.arg(text));
11179 				/*delete cn;
11180 				cn=nullptr;
11181 				goto corruptConstraintTime;*/
11182 			}
11183 			//assert(cn->maxDaysPerWeek>0 && cn->maxDaysPerWeek <= this->nDaysPerWeek);
11184 			xmlReadingLog+="    Max. days per week="+CustomFETString::number(cn->maxDaysPerWeek)+"\n";
11185 		}
11186 		else if(xmlReader.name()==QString("Interval_Start_Hour")){
11187 			QString text=xmlReader.readElementText();
11188 			for(h1=0; h1 < this->nHoursPerDay; h1++)
11189 				if(this->hoursOfTheDay[h1]==text)
11190 					break;
11191 			if(h1>=this->nHoursPerDay){
11192 				xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
11193 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
11194 					tr("Constraint Students interval max days per week start hour corrupt: hour %1 is inexistent ... ignoring constraint")
11195 					//.arg(cn->students)
11196 					.arg(text));*/
11197 				delete cn;
11198 				//cn=nullptr;
11199 				//goto corruptConstraintTime;
11200 				return nullptr;
11201 			}
11202 			assert(h1>=0 && h1 < this->nHoursPerDay);
11203 			xmlReadingLog+="    Interval start hour="+this->hoursOfTheDay[h1]+"\n";
11204 			cn->startHour=h1;
11205 		}
11206 		else if(xmlReader.name()==QString("Interval_End_Hour")){
11207 			QString text=xmlReader.readElementText();
11208 			if(text==""){
11209 				xmlReadingLog+="    Interval end hour void, meaning end of day\n";
11210 				cn->endHour=this->nHoursPerDay;
11211 			}
11212 			else{
11213 				for(h2=0; h2 < this->nHoursPerDay; h2++)
11214 					if(this->hoursOfTheDay[h2]==text)
11215 						break;
11216 				if(h2>=this->nHoursPerDay){
11217 					xmlReader.raiseError(tr("Hour %1 is inexistent (it is also not void, to specify end of the day)").arg(text));
11218 					/*RulesReconcilableMessage::information(parent, tr("FET information"),
11219 						tr("Constraint Students interval max days per week end hour corrupt: hour %1 is inexistent (it is also not void, to specify end of the day) ... ignoring constraint")
11220 						//.arg(cn->students)
11221 						.arg(text));*/
11222 					delete cn;
11223 					//cn=nullptr;
11224 					//goto corruptConstraintTime;
11225 					return nullptr;
11226 				}
11227 				assert(h2>=0 && h2 < this->nHoursPerDay);
11228 				xmlReadingLog+="    Interval end hour="+this->hoursOfTheDay[h2]+"\n";
11229 				cn->endHour=h2;
11230 			}
11231 		}
11232 		else{
11233 			unrecognizedXmlTags.append(xmlReader.name().toString());
11234 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
11235 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
11236 
11237 			xmlReader.skipCurrentElement();
11238 			xmlReaderNumberOfUnrecognizedFields++;
11239 		}
11240 	}
11241 	return cn;
11242 }
11243 
readStudentsSetNotAvailable(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)11244 TimeConstraint* Rules::readStudentsSetNotAvailable(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
11245 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetNotAvailable"));
11246 
11247 	//ConstraintStudentsSetNotAvailableTimes* cn=new ConstraintStudentsSetNotAvailableTimes();
11248 	QList<int> days;
11249 	QList<int> hours;
11250 	QString students;
11251 	double weightPercentage=100;
11252 	int d=-1, h1=-1, h2=-1;
11253 	bool active=true;
11254 	QString comments=QString("");
11255 	while(xmlReader.readNextStartElement()){
11256 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
11257 		if(xmlReader.name()==QString("Weight_Percentage")){
11258 			QString text=xmlReader.readElementText();
11259 			weightPercentage=customFETStrToDouble(text);
11260 			if(weightPercentage<0){
11261 				xmlReader.raiseError(tr("Weight percentage incorrect"));
11262 				return nullptr;
11263 			}
11264 			assert(weightPercentage>=0);
11265 			xmlReadingLog+="    Read weight percentage="+CustomFETString::number(weightPercentage)+"\n";
11266 		}
11267 		else if(xmlReader.name()==QString("Active")){
11268 			QString text=xmlReader.readElementText();
11269 			if(text=="false"){
11270 				active=false;
11271 			}
11272 		}
11273 		else if(xmlReader.name()==QString("Comments")){
11274 			QString text=xmlReader.readElementText();
11275 			comments=text;
11276 		}
11277 		else if(xmlReader.name()==QString("Day")){
11278 			QString text=xmlReader.readElementText();
11279 			for(d=0; d<this->nDaysPerWeek; d++)
11280 				if(this->daysOfTheWeek[d]==text)
11281 					break;
11282 			if(d>=this->nDaysPerWeek){
11283 				xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
11284 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
11285 					tr("Constraint StudentsSetNotAvailable day corrupt for students %1, day %2 is inexistent ... ignoring constraint")
11286 					.arg(students)
11287 					.arg(text));*/
11288 				//cn=nullptr;
11289 				//goto corruptConstraintTime;
11290 				return nullptr;
11291 			}
11292 			assert(d<this->nDaysPerWeek);
11293 			xmlReadingLog+="    Crt. day="+this->daysOfTheWeek[d]+"\n";
11294 		}
11295 		else if(xmlReader.name()==QString("Start_Hour")){
11296 			QString text=xmlReader.readElementText();
11297 			for(h1=0; h1 < this->nHoursPerDay; h1++)
11298 				if(this->hoursOfTheDay[h1]==text)
11299 					break;
11300 			if(h1==this->nHoursPerDay){
11301 				xmlReader.raiseError(tr("Hour %1 is the last hour - impossible").arg(text));
11302 				return nullptr;
11303 			}
11304 			else if(h1>this->nHoursPerDay){
11305 				xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
11306 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
11307 					tr("Constraint StudentsSetNotAvailable start hour corrupt for students set %1, hour %2 is inexistent ... ignoring constraint")
11308 					.arg(students)
11309 					.arg(text));*/
11310 				//cn=nullptr;
11311 				//goto corruptConstraintTime;
11312 				return nullptr;
11313 			}
11314 			assert(h1>=0 && h1 < this->nHoursPerDay);
11315 			xmlReadingLog+="    Start hour="+this->hoursOfTheDay[h1]+"\n";
11316 		}
11317 		else if(xmlReader.name()==QString("End_Hour")){
11318 			QString text=xmlReader.readElementText();
11319 			for(h2=0; h2 < this->nHoursPerDay; h2++)
11320 				if(this->hoursOfTheDay[h2]==text)
11321 					break;
11322 			if(h2==0){
11323 				xmlReader.raiseError(tr("Hour %1 is the first hour - impossible").arg(text));
11324 				return nullptr;
11325 			}
11326 			else if(h2>this->nHoursPerDay){
11327 				xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
11328 				return nullptr;
11329 			}
11330 			/*if(h2<=0 || h2>this->nHoursPerDay){
11331 				RulesReconcilableMessage::information(parent, tr("FET information"),
11332 					tr("Constraint StudentsSetNotAvailable end hour corrupt for students %1, hour %2 is inexistent ... ignoring constraint")
11333 					.arg(students)
11334 					.arg(text));
11335 				//goto corruptConstraintTime;
11336 				return nullptr;
11337 			}*/
11338 			assert(h2>0 && h2 <= this->nHoursPerDay);
11339 			xmlReadingLog+="    End hour="+this->hoursOfTheDay[h2]+"\n";
11340 		}
11341 		else if(xmlReader.name()==QString("Students")){
11342 			QString text=xmlReader.readElementText();
11343 			students=text;
11344 			xmlReadingLog+="    Read students name="+students+"\n";
11345 		}
11346 		else{
11347 			unrecognizedXmlTags.append(xmlReader.name().toString());
11348 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
11349 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
11350 
11351 			xmlReader.skipCurrentElement();
11352 			xmlReaderNumberOfUnrecognizedFields++;
11353 		}
11354 	}
11355 
11356 	assert(weightPercentage>=0);
11357 	if(d<0){
11358 		xmlReader.raiseError(tr("Field missing: %1").arg("Day"));
11359 		return nullptr;
11360 	}
11361 	else if(h1<0){
11362 		xmlReader.raiseError(tr("Field missing: %1").arg("Start_Hour"));
11363 		return nullptr;
11364 	}
11365 	else if(h2<0){
11366 		xmlReader.raiseError(tr("Field missing: %1").arg("End_Hour"));
11367 		return nullptr;
11368 	}
11369 	assert(d>=0 && h1>=0 && h2>=0);
11370 
11371 	ConstraintStudentsSetNotAvailableTimes* cn = nullptr;
11372 
11373 	bool found=false;
11374 	for(TimeConstraint* c : qAsConst(this->timeConstraintsList))
11375 		if(c->type==CONSTRAINT_STUDENTS_SET_NOT_AVAILABLE_TIMES){
11376 			ConstraintStudentsSetNotAvailableTimes* ssna=(ConstraintStudentsSetNotAvailableTimes*) c;
11377 			if(ssna->students==students){
11378 				found=true;
11379 
11380 				for(int hh=h1; hh<h2; hh++){
11381 					int k;
11382 					for(k=0; k<ssna->days.count(); k++)
11383 						if(ssna->days.at(k)==d && ssna->hours.at(k)==hh)
11384 							break;
11385 					if(k==ssna->days.count()){
11386 						ssna->days.append(d);
11387 						ssna->hours.append(hh);
11388 					}
11389 				}
11390 
11391 				assert(ssna->days.count()==ssna->hours.count());
11392 			}
11393 		}
11394 	if(!found){
11395 		days.clear();
11396 		hours.clear();
11397 		for(int hh=h1; hh<h2; hh++){
11398 			days.append(d);
11399 			hours.append(hh);
11400 		}
11401 
11402 		cn=new ConstraintStudentsSetNotAvailableTimes(weightPercentage, students, days, hours);
11403 		cn->active=active;
11404 		cn->comments=comments;
11405 
11406 		//crt_constraint=cn;
11407 		return cn;
11408 	}
11409 	else
11410 		return nullptr;
11411 }
11412 
readStudentsSetNotAvailableTimes(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)11413 TimeConstraint* Rules::readStudentsSetNotAvailableTimes(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
11414 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetNotAvailableTimes"));
11415 
11416 	ConstraintStudentsSetNotAvailableTimes* cn=new ConstraintStudentsSetNotAvailableTimes();
11417 	int nNotAvailableSlots=0;
11418 	int i=0;
11419 	while(xmlReader.readNextStartElement()){
11420 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
11421 		if(xmlReader.name()==QString("Weight_Percentage")){
11422 			QString text=xmlReader.readElementText();
11423 			cn->weightPercentage=customFETStrToDouble(text);
11424 			xmlReadingLog+="    Read weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
11425 		}
11426 		else if(xmlReader.name()==QString("Active")){
11427 			QString text=xmlReader.readElementText();
11428 			if(text=="false"){
11429 				cn->active=false;
11430 			}
11431 		}
11432 		else if(xmlReader.name()==QString("Comments")){
11433 			QString text=xmlReader.readElementText();
11434 			cn->comments=text;
11435 		}
11436 
11437 		else if(xmlReader.name()==QString("Number_of_Not_Available_Times")){
11438 			QString text=xmlReader.readElementText();
11439 			nNotAvailableSlots=text.toInt();
11440 			xmlReadingLog+="    Read number of not available times="+CustomFETString::number(nNotAvailableSlots)+"\n";
11441 		}
11442 
11443 		else if(xmlReader.name()==QString("Not_Available_Time")){
11444 			xmlReadingLog+="    Read: not available time\n";
11445 
11446 			int d=-1;
11447 			int h=-1;
11448 
11449 			assert(xmlReader.isStartElement());
11450 			while(xmlReader.readNextStartElement()){
11451 				xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
11452 				if(xmlReader.name()==QString("Day")){
11453 					QString text=xmlReader.readElementText();
11454 					for(d=0; d<this->nDaysPerWeek; d++)
11455 						if(this->daysOfTheWeek[d]==text)
11456 							break;
11457 
11458 					if(d>=this->nDaysPerWeek){
11459 						xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
11460 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
11461 							tr("Constraint StudentsSetNotAvailableTimes day corrupt for students %1, day %2 is inexistent ... ignoring constraint")
11462 							.arg(cn->students)
11463 							.arg(text));*/
11464 						delete cn;
11465 						cn=nullptr;
11466 						//goto corruptConstraintTime;
11467 						return nullptr;
11468 					}
11469 
11470 					assert(d<this->nDaysPerWeek);
11471 					xmlReadingLog+="    Day="+this->daysOfTheWeek[d]+"("+CustomFETString::number(i)+")"+"\n";
11472 				}
11473 				else if(xmlReader.name()==QString("Hour")){
11474 					QString text=xmlReader.readElementText();
11475 					for(h=0; h < this->nHoursPerDay; h++)
11476 						if(this->hoursOfTheDay[h]==text)
11477 							break;
11478 
11479 					if(h>=this->nHoursPerDay){
11480 						xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
11481 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
11482 							tr("Constraint StudentsSetNotAvailableTimes hour corrupt for students %1, hour %2 is inexistent ... ignoring constraint")
11483 							.arg(cn->students)
11484 							.arg(text));*/
11485 						delete cn;
11486 						cn=nullptr;
11487 						//goto corruptConstraintTime;
11488 						return nullptr;
11489 					}
11490 
11491 					assert(h>=0 && h < this->nHoursPerDay);
11492 					xmlReadingLog+="    Hour="+this->hoursOfTheDay[h]+"\n";
11493 				}
11494 				else{
11495 					unrecognizedXmlTags.append(xmlReader.name().toString());
11496 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
11497 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
11498 
11499 					xmlReader.skipCurrentElement();
11500 					xmlReaderNumberOfUnrecognizedFields++;
11501 				}
11502 			}
11503 			i++;
11504 
11505 			cn->days.append(d);
11506 			cn->hours.append(h);
11507 
11508 			if(d==-1 || h==-1){
11509 				xmlReader.raiseError(tr("%1 is incorrect").arg("Not_Available_Time"));
11510 				delete cn;
11511 				cn=nullptr;
11512 				return nullptr;
11513 			}
11514 		}
11515 		else if(xmlReader.name()==QString("Students")){
11516 			QString text=xmlReader.readElementText();
11517 			cn->students=text;
11518 			xmlReadingLog+="    Read students name="+cn->students+"\n";
11519 		}
11520 		else{
11521 			unrecognizedXmlTags.append(xmlReader.name().toString());
11522 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
11523 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
11524 
11525 			xmlReader.skipCurrentElement();
11526 			xmlReaderNumberOfUnrecognizedFields++;
11527 		}
11528 	}
11529 	assert(i==cn->days.count() && i==cn->hours.count());
11530 	if(!(i==nNotAvailableSlots)){
11531 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Not_Available_Times").arg("Not_Available_Time"));
11532 		delete cn;
11533 		cn=nullptr;
11534 		return nullptr;
11535 	}
11536 	assert(i==nNotAvailableSlots);
11537 
11538 	return cn;
11539 }
11540 
readMinNDaysBetweenActivities(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)11541 TimeConstraint* Rules::readMinNDaysBetweenActivities(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
11542 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintMinNDaysBetweenActivities"));
11543 
11544 	ConstraintMinDaysBetweenActivities* cn=new ConstraintMinDaysBetweenActivities();
11545 	cn->n_activities=0;
11546 	bool foundCISD=false;
11547 	int n_act=0;
11548 	cn->activitiesId.clear();
11549 	while(xmlReader.readNextStartElement()){
11550 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
11551 		if(xmlReader.name()==QString("Weight")){
11552 			//cn->weight=customFETStrToDouble(text);
11553 			xmlReader.skipCurrentElement();
11554 			xmlReadingLog+="    Ignoring old tag - weight - generating weightPercentage=95%\n";
11555 			cn->weightPercentage=95;
11556 		}
11557 		else if(xmlReader.name()==QString("Weight_Percentage")){
11558 			QString text=xmlReader.readElementText();
11559 			cn->weightPercentage=customFETStrToDouble(text);
11560 			xmlReadingLog+="    Adding weightPercentage="+CustomFETString::number(cn->weightPercentage)+"\n";
11561 		}
11562 		else if(xmlReader.name()==QString("Active")){
11563 			QString text=xmlReader.readElementText();
11564 			if(text=="false"){
11565 				cn->active=false;
11566 			}
11567 		}
11568 		else if(xmlReader.name()==QString("Comments")){
11569 			QString text=xmlReader.readElementText();
11570 			cn->comments=text;
11571 		}
11572 		else if(xmlReader.name()==QString("Consecutive_If_Same_Day") || xmlReader.name()==QString("Adjacent_If_Broken")){
11573 			QString text=xmlReader.readElementText();
11574 			if(text=="yes" || text=="true" || text=="1"){
11575 				cn->consecutiveIfSameDay=true;
11576 				foundCISD=true;
11577 				xmlReadingLog+="    Current constraint has consecutive if same day=true\n";
11578 			}
11579 			else{
11580 				if(!(text=="no" || text=="false" || text=="0")){
11581 					RulesReconcilableMessage::warning(parent, tr("FET warning"),
11582 						tr("Found constraint min days between activities with tag consecutive if same day"
11583 						" which is not 'true', 'false', 'yes', 'no', '1' or '0'."
11584 						" The tag will be considered false",
11585 						"Instructions for translators: please leave the 'true', 'false', 'yes' and 'no' fields untranslated, as they are in English"));
11586 				}
11587 				//assert(text=="no" || text=="false" || text=="0");
11588 				cn->consecutiveIfSameDay=false;
11589 				foundCISD=true;
11590 				xmlReadingLog+="    Current constraint has consecutive if same day=false\n";
11591 			}
11592 		}
11593 		else if(xmlReader.name()==QString("Compulsory")){
11594 			QString text=xmlReader.readElementText();
11595 			if(text=="yes"){
11596 				//cn->compulsory=true;
11597 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
11598 				cn->weightPercentage=95;
11599 				cn->consecutiveIfSameDay=true;
11600 				foundCISD=true;
11601 			}
11602 			else{
11603 				//cn->compulsory=false;
11604 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
11605 				cn->weightPercentage=0;
11606 				cn->consecutiveIfSameDay=false;
11607 				foundCISD=true;
11608 			}
11609 		}
11610 		else if(xmlReader.name()==QString("Number_of_Activities")){
11611 			QString text=xmlReader.readElementText();
11612 			cn->n_activities=text.toInt();
11613 			xmlReadingLog+="    Read n_activities="+CustomFETString::number(cn->n_activities)+"\n";
11614 		}
11615 		else if(xmlReader.name()==QString("Activity_Id")){
11616 			QString text=xmlReader.readElementText();
11617 			//cn->activitiesId[n_act]=text.toInt();
11618 			cn->activitiesId.append(text.toInt());
11619 			assert(n_act==cn->activitiesId.count()-1);
11620 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activitiesId[n_act])+"\n";
11621 			n_act++;
11622 		}
11623 		else if(xmlReader.name()==QString("MinDays")){
11624 			QString text=xmlReader.readElementText();
11625 			cn->minDays=text.toInt();
11626 			xmlReadingLog+="    Read MinDays="+CustomFETString::number(cn->minDays)+"\n";
11627 		}
11628 		else{
11629 			unrecognizedXmlTags.append(xmlReader.name().toString());
11630 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
11631 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
11632 
11633 			xmlReader.skipCurrentElement();
11634 			xmlReaderNumberOfUnrecognizedFields++;
11635 		}
11636 	}
11637 	if(!foundCISD){
11638 		xmlReadingLog+="    Could not find consecutive if same day information - making it true\n";
11639 		cn->consecutiveIfSameDay=true;
11640 	}
11641 	if(!(n_act==cn->n_activities)){
11642 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Activities").arg("Activity_Id"));
11643 		delete cn;
11644 		cn=nullptr;
11645 		return nullptr;
11646 	}
11647 	assert(n_act==cn->n_activities);
11648 	return cn;
11649 /*
11650 #if 0
11651 	if(0 && reportIncorrectMinDays && cn->n_activities > this->nDaysPerWeek){
11652 		QString s=tr("You have a constraint min days between activities with more activities than the number of days per week.");
11653 		s+=" ";
11654 		s+=tr("Constraint is:");
11655 		s+="\n";
11656 		s+=crt_constraint->getDescription(*this);
11657 		s+="\n";
11658 		s+=tr("This is a very bad practice from the way the algorithm of generation works (it slows down the generation and makes it harder to find a solution).");
11659 		s+="\n\n";
11660 		s+=tr("To improve your file, you are advised to remove the corresponding activities and constraint and add activities again, respecting the following rules:");
11661 		s+="\n\n";
11662 		s+=tr("1. If you add 'force consecutive if same day', then couple extra activities in pairs to obtain a number of activities equal to the number of days per week"
11663 			". Example: 7 activities with duration 1 in a 5 days week, then transform into 5 activities with durations: 2,2,1,1,1 and add a single container activity with these 5 components"
11664 			" (possibly raising the weight of added constraint min days between activities up to 100%)");
11665 		s+="\n\n";
11666 
11667 		s+=tr("2. If you don't add 'force consecutive if same day', then add a larger activity split into a number of"
11668 			" activities equal with the number of days per week and the remaining components into other larger split activity."
11669 			" For example, suppose you need to add 7 activities with duration 1 in a 5 days week. Add 2 larger container activities,"
11670 			" first one split into 5 activities with duration 1 and second one split into 2 activities with duration 1"
11671 			" (possibly raising the weight of added constraints min days between activities for each of the 2 containers up to 100%)");
11672 
11673 		int t=QMessageBox::warning(parent, tr("FET warning"), s,
11674 			tr("Skip rest"), tr("See next"), QString(),
11675 			1, 0 );
11676 
11677 		if(t==0)
11678 			reportIncorrectMinDays=false;
11679 	}
11680 #endif
11681 */
11682 }
11683 
readMinDaysBetweenActivities(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)11684 TimeConstraint* Rules::readMinDaysBetweenActivities(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
11685 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintMinDaysBetweenActivities"));
11686 
11687 	ConstraintMinDaysBetweenActivities* cn=new ConstraintMinDaysBetweenActivities();
11688 	cn->n_activities=0;
11689 	bool foundCISD=false;
11690 	int n_act=0;
11691 	cn->activitiesId.clear();
11692 	while(xmlReader.readNextStartElement()){
11693 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
11694 		if(xmlReader.name()==QString("Weight")){
11695 			//cn->weight=customFETStrToDouble(text);
11696 			xmlReader.skipCurrentElement();
11697 			xmlReadingLog+="    Ignoring old tag - weight - generating weightPercentage=95%\n";
11698 			cn->weightPercentage=95;
11699 		}
11700 		else if(xmlReader.name()==QString("Weight_Percentage")){
11701 			QString text=xmlReader.readElementText();
11702 			cn->weightPercentage=customFETStrToDouble(text);
11703 			xmlReadingLog+="    Adding weightPercentage="+CustomFETString::number(cn->weightPercentage)+"\n";
11704 		}
11705 		else if(xmlReader.name()==QString("Active")){
11706 			QString text=xmlReader.readElementText();
11707 			if(text=="false"){
11708 				cn->active=false;
11709 			}
11710 		}
11711 		else if(xmlReader.name()==QString("Comments")){
11712 			QString text=xmlReader.readElementText();
11713 			cn->comments=text;
11714 		}
11715 		else if(xmlReader.name()==QString("Consecutive_If_Same_Day") || xmlReader.name()==QString("Adjacent_If_Broken")){
11716 			QString text=xmlReader.readElementText();
11717 			if(text=="yes" || text=="true" || text=="1"){
11718 				cn->consecutiveIfSameDay=true;
11719 				foundCISD=true;
11720 				xmlReadingLog+="    Current constraint has consecutive if same day=true\n";
11721 			}
11722 			else{
11723 				if(!(text=="no" || text=="false" || text=="0")){
11724 					RulesReconcilableMessage::warning(parent, tr("FET warning"),
11725 						tr("Found constraint min days between activities with tag consecutive if same day"
11726 						" which is not 'true', 'false', 'yes', 'no', '1' or '0'."
11727 						" The tag will be considered false",
11728 						"Instructions for translators: please leave the 'true', 'false', 'yes' and 'no' fields untranslated, as they are in English"));
11729 				}
11730 				//assert(text=="no" || text=="false" || text=="0");
11731 				cn->consecutiveIfSameDay=false;
11732 				foundCISD=true;
11733 				xmlReadingLog+="    Current constraint has consecutive if same day=false\n";
11734 			}
11735 		}
11736 		else if(xmlReader.name()==QString("Compulsory")){
11737 			QString text=xmlReader.readElementText();
11738 			if(text=="yes"){
11739 				//cn->compulsory=true;
11740 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
11741 				cn->weightPercentage=95;
11742 				cn->consecutiveIfSameDay=true;
11743 				foundCISD=true;
11744 			}
11745 			else{
11746 				//cn->compulsory=false;
11747 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
11748 				cn->weightPercentage=0;
11749 				cn->consecutiveIfSameDay=false;
11750 				foundCISD=true;
11751 			}
11752 		}
11753 		else if(xmlReader.name()==QString("Number_of_Activities")){
11754 			QString text=xmlReader.readElementText();
11755 			cn->n_activities=text.toInt();
11756 			xmlReadingLog+="    Read n_activities="+CustomFETString::number(cn->n_activities)+"\n";
11757 		}
11758 		else if(xmlReader.name()==QString("Activity_Id")){
11759 			QString text=xmlReader.readElementText();
11760 			//cn->activitiesId[n_act]=text.toInt();
11761 			cn->activitiesId.append(text.toInt());
11762 			assert(n_act==cn->activitiesId.count()-1);
11763 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activitiesId[n_act])+"\n";
11764 			n_act++;
11765 		}
11766 		else if(xmlReader.name()==QString("MinDays")){
11767 			QString text=xmlReader.readElementText();
11768 			cn->minDays=text.toInt();
11769 			xmlReadingLog+="    Read MinDays="+CustomFETString::number(cn->minDays)+"\n";
11770 		}
11771 		else{
11772 			unrecognizedXmlTags.append(xmlReader.name().toString());
11773 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
11774 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
11775 
11776 			xmlReader.skipCurrentElement();
11777 			xmlReaderNumberOfUnrecognizedFields++;
11778 		}
11779 	}
11780 	if(!foundCISD){
11781 		xmlReadingLog+="    Could not find consecutive if same day information - making it true\n";
11782 		cn->consecutiveIfSameDay=true;
11783 	}
11784 	if(!(n_act==cn->n_activities)){
11785 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Activities").arg("Activity_Id"));
11786 		delete cn;
11787 		cn=nullptr;
11788 		return nullptr;
11789 	}
11790 	assert(n_act==cn->n_activities);
11791 	return cn;
11792 /*
11793 #if 0
11794 	if(0 && reportIncorrectMinDays && cn->n_activities > this->nDaysPerWeek){
11795 		QString s=tr("You have a constraint min days between activities with more activities than the number of days per week.");
11796 		s+=" ";
11797 		s+=tr("Constraint is:");
11798 		s+="\n";
11799 		s+=crt_constraint->getDescription(*this);
11800 		s+="\n";
11801 		s+=tr("This is a very bad practice from the way the algorithm of generation works (it slows down the generation and makes it harder to find a solution).");
11802 		s+="\n\n";
11803 		s+=tr("To improve your file, you are advised to remove the corresponding activities and constraint and add activities again, respecting the following rules:");
11804 		s+="\n\n";
11805 		s+=tr("1. If you add 'force consecutive if same day', then couple extra activities in pairs to obtain a number of activities equal to the number of days per week"
11806 			". Example: 7 activities with duration 1 in a 5 days week, then transform into 5 activities with durations: 2,2,1,1,1 and add a single container activity with these 5 components"
11807 			" (possibly raising the weight of added constraint min days between activities up to 100%)");
11808 		s+="\n\n";
11809 
11810 		s+=tr("2. If you don't add 'force consecutive if same day', then add a larger activity split into a number of"
11811 			" activities equal with the number of days per week and the remaining components into other larger split activity."
11812 			" For example, suppose you need to add 7 activities with duration 1 in a 5 days week. Add 2 larger container activities,"
11813 			" first one split into 5 activities with duration 1 and second one split into 2 activities with duration 1"
11814 			" (possibly raising the weight of added constraints min days between activities for each of the 2 containers up to 100%)");
11815 
11816 		int t=QMessageBox::warning(parent, tr("FET warning"), s,
11817 			tr("Skip rest"), tr("See next"), QString(),
11818 			1, 0 );
11819 
11820 		if(t==0)
11821 			reportIncorrectMinDays=false;
11822 	}
11823 #endif
11824 */
11825 }
11826 
readMaxDaysBetweenActivities(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)11827 TimeConstraint* Rules::readMaxDaysBetweenActivities(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
11828 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintMaxDaysBetweenActivities"));
11829 
11830 	ConstraintMaxDaysBetweenActivities* cn=new ConstraintMaxDaysBetweenActivities();
11831 	cn->n_activities=0;
11832 	int n_act=0;
11833 	cn->activitiesId.clear();
11834 	while(xmlReader.readNextStartElement()){
11835 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
11836 		if(xmlReader.name()==QString("Weight_Percentage")){
11837 			QString text=xmlReader.readElementText();
11838 			cn->weightPercentage=customFETStrToDouble(text);
11839 			xmlReadingLog+="    Adding weightPercentage="+CustomFETString::number(cn->weightPercentage)+"\n";
11840 		}
11841 		else if(xmlReader.name()==QString("Active")){
11842 			QString text=xmlReader.readElementText();
11843 			if(text=="false"){
11844 				cn->active=false;
11845 			}
11846 		}
11847 		else if(xmlReader.name()==QString("Comments")){
11848 			QString text=xmlReader.readElementText();
11849 			cn->comments=text;
11850 		}
11851 		else if(xmlReader.name()==QString("Number_of_Activities")){
11852 			QString text=xmlReader.readElementText();
11853 			cn->n_activities=text.toInt();
11854 			xmlReadingLog+="    Read n_activities="+CustomFETString::number(cn->n_activities)+"\n";
11855 		}
11856 		else if(xmlReader.name()==QString("Activity_Id")){
11857 			QString text=xmlReader.readElementText();
11858 			cn->activitiesId.append(text.toInt());
11859 			assert(n_act==cn->activitiesId.count()-1);
11860 			//cn->activitiesId[n_act]=text.toInt();
11861 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activitiesId[n_act])+"\n";
11862 			n_act++;
11863 		}
11864 		else if(xmlReader.name()==QString("MaxDays")){
11865 			QString text=xmlReader.readElementText();
11866 			cn->maxDays=text.toInt();
11867 			xmlReadingLog+="    Read MaxDays="+CustomFETString::number(cn->maxDays)+"\n";
11868 		}
11869 		else{
11870 			unrecognizedXmlTags.append(xmlReader.name().toString());
11871 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
11872 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
11873 
11874 			xmlReader.skipCurrentElement();
11875 			xmlReaderNumberOfUnrecognizedFields++;
11876 		}
11877 	}
11878 	if(!(n_act==cn->n_activities)){
11879 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Activities").arg("Activity_Id"));
11880 		delete cn;
11881 		cn=nullptr;
11882 		return nullptr;
11883 	}
11884 	assert(n_act==cn->n_activities);
11885 	return cn;
11886 }
11887 
readMinGapsBetweenActivities(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)11888 TimeConstraint* Rules::readMinGapsBetweenActivities(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
11889 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintMinGapsBetweenActivities"));
11890 	ConstraintMinGapsBetweenActivities* cn=new ConstraintMinGapsBetweenActivities();
11891 	cn->n_activities=0;
11892 	int n_act=0;
11893 	cn->activitiesId.clear();
11894 	while(xmlReader.readNextStartElement()){
11895 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
11896 		if(xmlReader.name()==QString("Weight_Percentage")){
11897 			QString text=xmlReader.readElementText();
11898 			cn->weightPercentage=customFETStrToDouble(text);
11899 			xmlReadingLog+="    Adding weightPercentage="+CustomFETString::number(cn->weightPercentage)+"\n";
11900 		}
11901 		else if(xmlReader.name()==QString("Active")){
11902 			QString text=xmlReader.readElementText();
11903 			if(text=="false"){
11904 				cn->active=false;
11905 			}
11906 		}
11907 		else if(xmlReader.name()==QString("Comments")){
11908 			QString text=xmlReader.readElementText();
11909 			cn->comments=text;
11910 		}
11911 		else if(xmlReader.name()==QString("Number_of_Activities")){
11912 			QString text=xmlReader.readElementText();
11913 			cn->n_activities=text.toInt();
11914 			xmlReadingLog+="    Read n_activities="+CustomFETString::number(cn->n_activities)+"\n";
11915 		}
11916 		else if(xmlReader.name()==QString("Activity_Id")){
11917 			QString text=xmlReader.readElementText();
11918 			cn->activitiesId.append(text.toInt());
11919 			assert(n_act==cn->activitiesId.count()-1);
11920 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activitiesId[n_act])+"\n";
11921 			n_act++;
11922 		}
11923 		else if(xmlReader.name()==QString("MinGaps")){
11924 			QString text=xmlReader.readElementText();
11925 			cn->minGaps=text.toInt();
11926 			xmlReadingLog+="    Read MinGaps="+CustomFETString::number(cn->minGaps)+"\n";
11927 		}
11928 		else{
11929 			unrecognizedXmlTags.append(xmlReader.name().toString());
11930 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
11931 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
11932 
11933 			xmlReader.skipCurrentElement();
11934 			xmlReaderNumberOfUnrecognizedFields++;
11935 		}
11936 	}
11937 	if(!(n_act==cn->n_activities)){
11938 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Activities").arg("Activity_Id"));
11939 		delete cn;
11940 		cn=nullptr;
11941 		return nullptr;
11942 	}
11943 	assert(n_act==cn->n_activities);
11944 	return cn;
11945 }
11946 
readMaxGapsBetweenActivities(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)11947 TimeConstraint* Rules::readMaxGapsBetweenActivities(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
11948 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintMaxGapsBetweenActivities"));
11949 	ConstraintMaxGapsBetweenActivities* cn=new ConstraintMaxGapsBetweenActivities();
11950 	cn->n_activities=0;
11951 	int n_act=0;
11952 	cn->activitiesId.clear();
11953 	while(xmlReader.readNextStartElement()){
11954 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
11955 		if(xmlReader.name()==QString("Weight_Percentage")){
11956 			QString text=xmlReader.readElementText();
11957 			cn->weightPercentage=customFETStrToDouble(text);
11958 			xmlReadingLog+="    Adding weightPercentage="+CustomFETString::number(cn->weightPercentage)+"\n";
11959 		}
11960 		else if(xmlReader.name()==QString("Active")){
11961 			QString text=xmlReader.readElementText();
11962 			if(text=="false"){
11963 				cn->active=false;
11964 			}
11965 		}
11966 		else if(xmlReader.name()==QString("Comments")){
11967 			QString text=xmlReader.readElementText();
11968 			cn->comments=text;
11969 		}
11970 		else if(xmlReader.name()==QString("Number_of_Activities")){
11971 			QString text=xmlReader.readElementText();
11972 			cn->n_activities=text.toInt();
11973 			xmlReadingLog+="    Read n_activities="+CustomFETString::number(cn->n_activities)+"\n";
11974 		}
11975 		else if(xmlReader.name()==QString("Activity_Id")){
11976 			QString text=xmlReader.readElementText();
11977 			cn->activitiesId.append(text.toInt());
11978 			assert(n_act==cn->activitiesId.count()-1);
11979 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activitiesId[n_act])+"\n";
11980 			n_act++;
11981 		}
11982 		else if(xmlReader.name()==QString("MaxGaps")){
11983 			QString text=xmlReader.readElementText();
11984 			cn->maxGaps=text.toInt();
11985 			xmlReadingLog+="    Read MaxGaps="+CustomFETString::number(cn->maxGaps)+"\n";
11986 		}
11987 		else{
11988 			unrecognizedXmlTags.append(xmlReader.name().toString());
11989 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
11990 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
11991 
11992 			xmlReader.skipCurrentElement();
11993 			xmlReaderNumberOfUnrecognizedFields++;
11994 		}
11995 	}
11996 	if(!(n_act==cn->n_activities)){
11997 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Activities").arg("Activity_Id"));
11998 		delete cn;
11999 		cn=nullptr;
12000 		return nullptr;
12001 	}
12002 	assert(n_act==cn->n_activities);
12003 	return cn;
12004 }
12005 
readActivitiesNotOverlapping(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)12006 TimeConstraint* Rules::readActivitiesNotOverlapping(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
12007 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivitiesNotOverlapping"));
12008 	ConstraintActivitiesNotOverlapping* cn=new ConstraintActivitiesNotOverlapping();
12009 	cn->n_activities=0;
12010 	int n_act=0;
12011 	cn->activitiesId.clear();
12012 	while(xmlReader.readNextStartElement()){
12013 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
12014 		if(xmlReader.name()==QString("Weight")){
12015 			//cn->weight=customFETStrToDouble(text);
12016 			xmlReader.skipCurrentElement();
12017 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
12018 			cn->weightPercentage=100;
12019 		}
12020 		else if(xmlReader.name()==QString("Weight_Percentage")){
12021 			QString text=xmlReader.readElementText();
12022 			cn->weightPercentage=customFETStrToDouble(text);
12023 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
12024 		}
12025 		else if(xmlReader.name()==QString("Active")){
12026 			QString text=xmlReader.readElementText();
12027 			if(text=="false"){
12028 				cn->active=false;
12029 			}
12030 		}
12031 		else if(xmlReader.name()==QString("Comments")){
12032 			QString text=xmlReader.readElementText();
12033 			cn->comments=text;
12034 		}
12035 		else if(xmlReader.name()==QString("Compulsory")){
12036 			QString text=xmlReader.readElementText();
12037 			if(text=="yes"){
12038 				//cn->compulsory=true;
12039 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
12040 				cn->weightPercentage=100;
12041 			}
12042 			else{
12043 				//cn->compulsory=false;
12044 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
12045 				cn->weightPercentage=0;
12046 			}
12047 		}
12048 		else if(xmlReader.name()==QString("Number_of_Activities")){
12049 			QString text=xmlReader.readElementText();
12050 			cn->n_activities=text.toInt();
12051 			xmlReadingLog+="    Read n_activities="+CustomFETString::number(cn->n_activities)+"\n";
12052 		}
12053 		else if(xmlReader.name()==QString("Activity_Id")){
12054 			QString text=xmlReader.readElementText();
12055 			//cn->activitiesId[n_act]=text.toInt();
12056 			cn->activitiesId.append(text.toInt());
12057 			assert(n_act==cn->activitiesId.count()-1);
12058 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activitiesId[n_act])+"\n";
12059 			n_act++;
12060 		}
12061 		else{
12062 			unrecognizedXmlTags.append(xmlReader.name().toString());
12063 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
12064 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
12065 
12066 			xmlReader.skipCurrentElement();
12067 			xmlReaderNumberOfUnrecognizedFields++;
12068 		}
12069 	}
12070 	if(!(n_act==cn->n_activities)){
12071 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Activities").arg("Activity_Id"));
12072 		delete cn;
12073 		cn=nullptr;
12074 		return nullptr;
12075 	}
12076 	assert(n_act==cn->n_activities);
12077 	return cn;
12078 }
12079 
readActivityTagsNotOverlapping(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)12080 TimeConstraint* Rules::readActivityTagsNotOverlapping(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
12081 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivityTagsNotOverlapping"));
12082 	ConstraintActivityTagsNotOverlapping* cn=new ConstraintActivityTagsNotOverlapping();
12083 	int nActivityTags=-1;
12084 	cn->activityTagsNames.clear();
12085 	QSet<QString> readTags;
12086 	while(xmlReader.readNextStartElement()){
12087 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
12088 		if(xmlReader.name()==QString("Weight")){
12089 			//cn->weight=customFETStrToDouble(text);
12090 			xmlReader.skipCurrentElement();
12091 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
12092 			cn->weightPercentage=100;
12093 		}
12094 		else if(xmlReader.name()==QString("Weight_Percentage")){
12095 			QString text=xmlReader.readElementText();
12096 			cn->weightPercentage=customFETStrToDouble(text);
12097 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
12098 		}
12099 		else if(xmlReader.name()==QString("Active")){
12100 			QString text=xmlReader.readElementText();
12101 			if(text=="false"){
12102 				cn->active=false;
12103 			}
12104 		}
12105 		else if(xmlReader.name()==QString("Comments")){
12106 			QString text=xmlReader.readElementText();
12107 			cn->comments=text;
12108 		}
12109 		else if(xmlReader.name()==QString("Compulsory")){
12110 			QString text=xmlReader.readElementText();
12111 			if(text=="yes"){
12112 				//cn->compulsory=true;
12113 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
12114 				cn->weightPercentage=100;
12115 			}
12116 			else{
12117 				//cn->compulsory=false;
12118 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
12119 				cn->weightPercentage=0;
12120 			}
12121 		}
12122 		else if(xmlReader.name()==QString("Number_of_Activity_Tags")){
12123 			QString text=xmlReader.readElementText();
12124 			nActivityTags=text.toInt();
12125 			if(nActivityTags<2){
12126 				xmlReader.raiseError(tr("The number of activity tags in the constraint activity tags not overlapping is lower than two"));
12127 				delete cn;
12128 				cn=nullptr;
12129 				return nullptr;
12130 			}
12131 			xmlReadingLog+="    Read n activity tags="+CustomFETString::number(nActivityTags)+"\n";
12132 		}
12133 		else if(xmlReader.name()==QString("Activity_Tag")){
12134 			QString text=xmlReader.readElementText();
12135 			if(readTags.contains(text)){
12136 				xmlReader.raiseError(tr("Duplicate activity tag %1 found in constraint activity tags not overlapping").arg(text));
12137 				delete cn;
12138 				cn=nullptr;
12139 				return nullptr;
12140 			}
12141 			else{
12142 				readTags.insert(text);
12143 			}
12144 			cn->activityTagsNames.append(text);
12145 			xmlReadingLog+="    Read activity tag="+cn->activityTagsNames.at(cn->activityTagsNames.count()-1)+"\n";
12146 		}
12147 		else{
12148 			unrecognizedXmlTags.append(xmlReader.name().toString());
12149 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
12150 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
12151 
12152 			xmlReader.skipCurrentElement();
12153 			xmlReaderNumberOfUnrecognizedFields++;
12154 		}
12155 	}
12156 	if(!(nActivityTags==cn->activityTagsNames.count())){
12157 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Activity_Tags").arg("Activity_Tag"));
12158 		delete cn;
12159 		cn=nullptr;
12160 		return nullptr;
12161 	}
12162 	assert(nActivityTags==cn->activityTagsNames.count());
12163 	return cn;
12164 }
12165 
readActivitiesSameStartingTime(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)12166 TimeConstraint* Rules::readActivitiesSameStartingTime(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
12167 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivitiesSameStartingTime"));
12168 	ConstraintActivitiesSameStartingTime* cn=new ConstraintActivitiesSameStartingTime();
12169 	cn->n_activities=0;
12170 	int n_act=0;
12171 	cn->activitiesId.clear();
12172 	while(xmlReader.readNextStartElement()){
12173 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
12174 		if(xmlReader.name()==QString("Weight")){
12175 			//cn->weight=customFETStrToDouble(text);
12176 			xmlReader.skipCurrentElement();
12177 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
12178 			cn->weightPercentage=100;
12179 		}
12180 		else if(xmlReader.name()==QString("Weight_Percentage")){
12181 			QString text=xmlReader.readElementText();
12182 			cn->weightPercentage=customFETStrToDouble(text);
12183 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
12184 		}
12185 		else if(xmlReader.name()==QString("Active")){
12186 			QString text=xmlReader.readElementText();
12187 			if(text=="false"){
12188 				cn->active=false;
12189 			}
12190 		}
12191 		else if(xmlReader.name()==QString("Comments")){
12192 			QString text=xmlReader.readElementText();
12193 			cn->comments=text;
12194 		}
12195 		else if(xmlReader.name()==QString("Compulsory")){
12196 			QString text=xmlReader.readElementText();
12197 			if(text=="yes"){
12198 				//cn->compulsory=true;
12199 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
12200 				cn->weightPercentage=100;
12201 			}
12202 			else{
12203 				//cn->compulsory=false;
12204 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
12205 				cn->weightPercentage=0;
12206 			}
12207 		}
12208 		else if(xmlReader.name()==QString("Number_of_Activities")){
12209 			QString text=xmlReader.readElementText();
12210 			cn->n_activities=text.toInt();
12211 			xmlReadingLog+="    Read n_activities="+CustomFETString::number(cn->n_activities)+"\n";
12212 		}
12213 		else if(xmlReader.name()==QString("Activity_Id")){
12214 			QString text=xmlReader.readElementText();
12215 			//cn->activitiesId[n_act]=text.toInt();
12216 			cn->activitiesId.append(text.toInt());
12217 			assert(n_act==cn->activitiesId.count()-1);
12218 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activitiesId[n_act])+"\n";
12219 			n_act++;
12220 		}
12221 		else{
12222 			unrecognizedXmlTags.append(xmlReader.name().toString());
12223 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
12224 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
12225 
12226 			xmlReader.skipCurrentElement();
12227 			xmlReaderNumberOfUnrecognizedFields++;
12228 		}
12229 	}
12230 	if(!(n_act==cn->n_activities)){
12231 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Activities").arg("Activity_Id"));
12232 		delete cn;
12233 		cn=nullptr;
12234 		return nullptr;
12235 	}
12236 	assert(n_act==cn->n_activities);
12237 	return cn;
12238 }
12239 
readActivitiesSameStartingHour(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)12240 TimeConstraint* Rules::readActivitiesSameStartingHour(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
12241 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivitiesSameStartingHour"));
12242 	ConstraintActivitiesSameStartingHour* cn=new ConstraintActivitiesSameStartingHour();
12243 	cn->n_activities=0;
12244 	int n_act=0;
12245 	cn->activitiesId.clear();
12246 	while(xmlReader.readNextStartElement()){
12247 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
12248 		if(xmlReader.name()==QString("Weight")){
12249 			//cn->weight=customFETStrToDouble(text);
12250 			xmlReader.skipCurrentElement();
12251 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
12252 			cn->weightPercentage=100;
12253 		}
12254 		else if(xmlReader.name()==QString("Weight_Percentage")){
12255 			QString text=xmlReader.readElementText();
12256 			cn->weightPercentage=customFETStrToDouble(text);
12257 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
12258 		}
12259 		else if(xmlReader.name()==QString("Active")){
12260 			QString text=xmlReader.readElementText();
12261 			if(text=="false"){
12262 				cn->active=false;
12263 			}
12264 		}
12265 		else if(xmlReader.name()==QString("Comments")){
12266 			QString text=xmlReader.readElementText();
12267 			cn->comments=text;
12268 		}
12269 		else if(xmlReader.name()==QString("Compulsory")){
12270 			QString text=xmlReader.readElementText();
12271 			if(text=="yes"){
12272 				//cn->compulsory=true;
12273 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
12274 				cn->weightPercentage=100;
12275 			}
12276 			else{
12277 				//cn->compulsory=false;
12278 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
12279 				cn->weightPercentage=0;
12280 			}
12281 		}
12282 		else if(xmlReader.name()==QString("Number_of_Activities")){
12283 			QString text=xmlReader.readElementText();
12284 			cn->n_activities=text.toInt();
12285 			xmlReadingLog+="    Read n_activities="+CustomFETString::number(cn->n_activities)+"\n";
12286 		}
12287 		else if(xmlReader.name()==QString("Activity_Id")){
12288 			QString text=xmlReader.readElementText();
12289 			//cn->activitiesId[n_act]=text.toInt();
12290 			cn->activitiesId.append(text.toInt());
12291 			assert(n_act==cn->activitiesId.count()-1);
12292 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activitiesId[n_act])+"\n";
12293 			n_act++;
12294 		}
12295 		else{
12296 			unrecognizedXmlTags.append(xmlReader.name().toString());
12297 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
12298 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
12299 
12300 			xmlReader.skipCurrentElement();
12301 			xmlReaderNumberOfUnrecognizedFields++;
12302 		}
12303 	}
12304 	if(!(n_act==cn->n_activities)){
12305 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Activities").arg("Activity_Id"));
12306 		delete cn;
12307 		cn=nullptr;
12308 		return nullptr;
12309 	}
12310 	assert(n_act==cn->n_activities);
12311 	return cn;
12312 }
12313 
readActivitiesSameStartingDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)12314 TimeConstraint* Rules::readActivitiesSameStartingDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
12315 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivitiesSameStartingDay"));
12316 	ConstraintActivitiesSameStartingDay* cn=new ConstraintActivitiesSameStartingDay();
12317 	cn->n_activities=0;
12318 	int n_act=0;
12319 	cn->activitiesId.clear();
12320 	while(xmlReader.readNextStartElement()){
12321 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
12322 		if(xmlReader.name()==QString("Weight_Percentage")){
12323 			QString text=xmlReader.readElementText();
12324 			cn->weightPercentage=customFETStrToDouble(text);
12325 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
12326 		}
12327 		else if(xmlReader.name()==QString("Active")){
12328 			QString text=xmlReader.readElementText();
12329 			if(text=="false"){
12330 				cn->active=false;
12331 			}
12332 		}
12333 		else if(xmlReader.name()==QString("Comments")){
12334 			QString text=xmlReader.readElementText();
12335 			cn->comments=text;
12336 		}
12337 		else if(xmlReader.name()==QString("Number_of_Activities")){
12338 			QString text=xmlReader.readElementText();
12339 			cn->n_activities=text.toInt();
12340 			xmlReadingLog+="    Read n_activities="+CustomFETString::number(cn->n_activities)+"\n";
12341 		}
12342 		else if(xmlReader.name()==QString("Activity_Id")){
12343 			QString text=xmlReader.readElementText();
12344 			//cn->activitiesId[n_act]=text.toInt();
12345 			cn->activitiesId.append(text.toInt());
12346 			assert(n_act==cn->activitiesId.count()-1);
12347 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activitiesId[n_act])+"\n";
12348 			n_act++;
12349 		}
12350 		else{
12351 			unrecognizedXmlTags.append(xmlReader.name().toString());
12352 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
12353 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
12354 
12355 			xmlReader.skipCurrentElement();
12356 			xmlReaderNumberOfUnrecognizedFields++;
12357 		}
12358 	}
12359 	if(!(n_act==cn->n_activities)){
12360 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Activities").arg("Activity_Id"));
12361 		delete cn;
12362 		cn=nullptr;
12363 		return nullptr;
12364 	}
12365 	assert(n_act==cn->n_activities);
12366 	return cn;
12367 }
12368 
readTeachersMaxHoursDaily(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)12369 TimeConstraint* Rules::readTeachersMaxHoursDaily(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
12370 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxHoursDaily"));
12371 	ConstraintTeachersMaxHoursDaily* cn=new ConstraintTeachersMaxHoursDaily();
12372 	while(xmlReader.readNextStartElement()){
12373 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
12374 		if(xmlReader.name()==QString("Weight")){
12375 			//cn->weight=customFETStrToDouble(text);
12376 			xmlReader.skipCurrentElement();
12377 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
12378 			cn->weightPercentage=100;
12379 		}
12380 		else if(xmlReader.name()==QString("Weight_Percentage")){
12381 			QString text=xmlReader.readElementText();
12382 			cn->weightPercentage=customFETStrToDouble(text);
12383 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
12384 		}
12385 		else if(xmlReader.name()==QString("Active")){
12386 			QString text=xmlReader.readElementText();
12387 			if(text=="false"){
12388 				cn->active=false;
12389 			}
12390 		}
12391 		else if(xmlReader.name()==QString("Comments")){
12392 			QString text=xmlReader.readElementText();
12393 			cn->comments=text;
12394 		}
12395 		else if(xmlReader.name()==QString("Compulsory")){
12396 			QString text=xmlReader.readElementText();
12397 			if(text=="yes"){
12398 				//cn->compulsory=true;
12399 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
12400 				cn->weightPercentage=100;
12401 			}
12402 			else{
12403 				//cn->compulsory=false;
12404 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
12405 				cn->weightPercentage=0;
12406 			}
12407 		}
12408 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
12409 			QString text=xmlReader.readElementText();
12410 			cn->maxHoursDaily=text.toInt();
12411 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
12412 		}
12413 		else{
12414 			unrecognizedXmlTags.append(xmlReader.name().toString());
12415 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
12416 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
12417 
12418 			xmlReader.skipCurrentElement();
12419 			xmlReaderNumberOfUnrecognizedFields++;
12420 		}
12421 	}
12422 	return cn;
12423 }
12424 
readTeacherMaxHoursDaily(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)12425 TimeConstraint* Rules::readTeacherMaxHoursDaily(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
12426 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxHoursDaily"));
12427 	ConstraintTeacherMaxHoursDaily* cn=new ConstraintTeacherMaxHoursDaily();
12428 	while(xmlReader.readNextStartElement()){
12429 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
12430 		if(xmlReader.name()==QString("Weight")){
12431 			//cn->weight=customFETStrToDouble(text);
12432 			xmlReader.skipCurrentElement();
12433 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
12434 			cn->weightPercentage=100;
12435 		}
12436 		else if(xmlReader.name()==QString("Weight_Percentage")){
12437 			QString text=xmlReader.readElementText();
12438 			cn->weightPercentage=customFETStrToDouble(text);
12439 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
12440 		}
12441 		else if(xmlReader.name()==QString("Active")){
12442 			QString text=xmlReader.readElementText();
12443 			if(text=="false"){
12444 				cn->active=false;
12445 			}
12446 		}
12447 		else if(xmlReader.name()==QString("Comments")){
12448 			QString text=xmlReader.readElementText();
12449 			cn->comments=text;
12450 		}
12451 		else if(xmlReader.name()==QString("Compulsory")){
12452 			QString text=xmlReader.readElementText();
12453 			if(text=="yes"){
12454 				//cn->compulsory=true;
12455 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
12456 				cn->weightPercentage=100;
12457 			}
12458 			else{
12459 				//cn->compulsory=false;
12460 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
12461 				cn->weightPercentage=0;
12462 			}
12463 		}
12464 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
12465 			QString text=xmlReader.readElementText();
12466 			cn->maxHoursDaily=text.toInt();
12467 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
12468 		}
12469 		else if(xmlReader.name()==QString("Teacher_Name")){
12470 			QString text=xmlReader.readElementText();
12471 			cn->teacherName=text;
12472 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
12473 		}
12474 		else{
12475 			unrecognizedXmlTags.append(xmlReader.name().toString());
12476 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
12477 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
12478 
12479 			xmlReader.skipCurrentElement();
12480 			xmlReaderNumberOfUnrecognizedFields++;
12481 		}
12482 	}
12483 	return cn;
12484 }
12485 
readTeachersMaxHoursContinuously(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)12486 TimeConstraint* Rules::readTeachersMaxHoursContinuously(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
12487 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxHoursContinuously"));
12488 	ConstraintTeachersMaxHoursContinuously* cn=new ConstraintTeachersMaxHoursContinuously();
12489 	while(xmlReader.readNextStartElement()){
12490 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
12491 		if(xmlReader.name()==QString("Weight")){
12492 			//cn->weight=customFETStrToDouble(text);
12493 			xmlReader.skipCurrentElement();
12494 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
12495 			cn->weightPercentage=100;
12496 		}
12497 		else if(xmlReader.name()==QString("Weight_Percentage")){
12498 			QString text=xmlReader.readElementText();
12499 			cn->weightPercentage=customFETStrToDouble(text);
12500 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
12501 		}
12502 		else if(xmlReader.name()==QString("Active")){
12503 			QString text=xmlReader.readElementText();
12504 			if(text=="false"){
12505 				cn->active=false;
12506 			}
12507 		}
12508 		else if(xmlReader.name()==QString("Comments")){
12509 			QString text=xmlReader.readElementText();
12510 			cn->comments=text;
12511 		}
12512 		else if(xmlReader.name()==QString("Compulsory")){
12513 			QString text=xmlReader.readElementText();
12514 			if(text=="yes"){
12515 				//cn->compulsory=true;
12516 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
12517 				cn->weightPercentage=100;
12518 			}
12519 			else{
12520 				//cn->compulsory=false;
12521 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
12522 				cn->weightPercentage=0;
12523 			}
12524 		}
12525 		else if(xmlReader.name()==QString("Maximum_Hours_Continuously")){
12526 			QString text=xmlReader.readElementText();
12527 			cn->maxHoursContinuously=text.toInt();
12528 			xmlReadingLog+="    Read maxHoursContinuously="+CustomFETString::number(cn->maxHoursContinuously)+"\n";
12529 		}
12530 		else{
12531 			unrecognizedXmlTags.append(xmlReader.name().toString());
12532 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
12533 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
12534 
12535 			xmlReader.skipCurrentElement();
12536 			xmlReaderNumberOfUnrecognizedFields++;
12537 		}
12538 	}
12539 	return cn;
12540 }
12541 
readTeacherMaxHoursContinuously(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)12542 TimeConstraint* Rules::readTeacherMaxHoursContinuously(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
12543 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxHoursContinuously"));
12544 	ConstraintTeacherMaxHoursContinuously* cn=new ConstraintTeacherMaxHoursContinuously();
12545 	while(xmlReader.readNextStartElement()){
12546 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
12547 		if(xmlReader.name()==QString("Weight")){
12548 			//cn->weight=customFETStrToDouble(text);
12549 			xmlReader.skipCurrentElement();
12550 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
12551 			cn->weightPercentage=100;
12552 		}
12553 		else if(xmlReader.name()==QString("Weight_Percentage")){
12554 			QString text=xmlReader.readElementText();
12555 			cn->weightPercentage=customFETStrToDouble(text);
12556 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
12557 		}
12558 		else if(xmlReader.name()==QString("Active")){
12559 			QString text=xmlReader.readElementText();
12560 			if(text=="false"){
12561 				cn->active=false;
12562 			}
12563 		}
12564 		else if(xmlReader.name()==QString("Comments")){
12565 			QString text=xmlReader.readElementText();
12566 			cn->comments=text;
12567 		}
12568 		else if(xmlReader.name()==QString("Compulsory")){
12569 			QString text=xmlReader.readElementText();
12570 			if(text=="yes"){
12571 				//cn->compulsory=true;
12572 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
12573 				cn->weightPercentage=100;
12574 			}
12575 			else{
12576 				//cn->compulsory=false;
12577 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
12578 				cn->weightPercentage=0;
12579 			}
12580 		}
12581 		else if(xmlReader.name()==QString("Maximum_Hours_Continuously")){
12582 			QString text=xmlReader.readElementText();
12583 			cn->maxHoursContinuously=text.toInt();
12584 			xmlReadingLog+="    Read maxHoursContinuously="+CustomFETString::number(cn->maxHoursContinuously)+"\n";
12585 		}
12586 		else if(xmlReader.name()==QString("Teacher_Name")){
12587 			QString text=xmlReader.readElementText();
12588 			cn->teacherName=text;
12589 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
12590 		}
12591 		else{
12592 			unrecognizedXmlTags.append(xmlReader.name().toString());
12593 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
12594 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
12595 
12596 			xmlReader.skipCurrentElement();
12597 			xmlReaderNumberOfUnrecognizedFields++;
12598 		}
12599 	}
12600 	return cn;
12601 }
12602 
readTeacherActivityTagMaxHoursContinuously(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)12603 TimeConstraint* Rules::readTeacherActivityTagMaxHoursContinuously(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
12604 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherActivityTagMaxHoursContinuously"));
12605 	ConstraintTeacherActivityTagMaxHoursContinuously* cn=new ConstraintTeacherActivityTagMaxHoursContinuously();
12606 	while(xmlReader.readNextStartElement()){
12607 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
12608 		if(xmlReader.name()==QString("Weight_Percentage")){
12609 			QString text=xmlReader.readElementText();
12610 			cn->weightPercentage=customFETStrToDouble(text);
12611 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
12612 		}
12613 		else if(xmlReader.name()==QString("Active")){
12614 			QString text=xmlReader.readElementText();
12615 			if(text=="false"){
12616 				cn->active=false;
12617 			}
12618 		}
12619 		else if(xmlReader.name()==QString("Comments")){
12620 			QString text=xmlReader.readElementText();
12621 			cn->comments=text;
12622 		}
12623 		else if(xmlReader.name()==QString("Maximum_Hours_Continuously")){
12624 			QString text=xmlReader.readElementText();
12625 			cn->maxHoursContinuously=text.toInt();
12626 			xmlReadingLog+="    Read maxHoursContinuously="+CustomFETString::number(cn->maxHoursContinuously)+"\n";
12627 		}
12628 		else if(xmlReader.name()==QString("Teacher_Name")){
12629 			QString text=xmlReader.readElementText();
12630 			cn->teacherName=text;
12631 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
12632 		}
12633 		else if(xmlReader.name()==QString("Activity_Tag_Name")){
12634 			QString text=xmlReader.readElementText();
12635 			cn->activityTagName=text;
12636 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
12637 		}
12638 		else{
12639 			unrecognizedXmlTags.append(xmlReader.name().toString());
12640 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
12641 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
12642 
12643 			xmlReader.skipCurrentElement();
12644 			xmlReaderNumberOfUnrecognizedFields++;
12645 		}
12646 	}
12647 	return cn;
12648 }
12649 
readTeachersActivityTagMaxHoursContinuously(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)12650 TimeConstraint* Rules::readTeachersActivityTagMaxHoursContinuously(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
12651 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersActivityTagMaxHoursContinuously"));
12652 	ConstraintTeachersActivityTagMaxHoursContinuously* cn=new ConstraintTeachersActivityTagMaxHoursContinuously();
12653 	while(xmlReader.readNextStartElement()){
12654 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
12655 		if(xmlReader.name()==QString("Weight_Percentage")){
12656 			QString text=xmlReader.readElementText();
12657 			cn->weightPercentage=customFETStrToDouble(text);
12658 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
12659 		}
12660 		else if(xmlReader.name()==QString("Active")){
12661 			QString text=xmlReader.readElementText();
12662 			if(text=="false"){
12663 				cn->active=false;
12664 			}
12665 		}
12666 		else if(xmlReader.name()==QString("Comments")){
12667 			QString text=xmlReader.readElementText();
12668 			cn->comments=text;
12669 		}
12670 		else if(xmlReader.name()==QString("Maximum_Hours_Continuously")){
12671 			QString text=xmlReader.readElementText();
12672 			cn->maxHoursContinuously=text.toInt();
12673 			xmlReadingLog+="    Read maxHoursContinuously="+CustomFETString::number(cn->maxHoursContinuously)+"\n";
12674 		}
12675 		else if(xmlReader.name()==QString("Activity_Tag_Name")){
12676 			QString text=xmlReader.readElementText();
12677 			cn->activityTagName=text;
12678 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
12679 		}
12680 		else{
12681 			unrecognizedXmlTags.append(xmlReader.name().toString());
12682 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
12683 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
12684 
12685 			xmlReader.skipCurrentElement();
12686 			xmlReaderNumberOfUnrecognizedFields++;
12687 		}
12688 	}
12689 	return cn;
12690 }
12691 
readTeacherActivityTagMaxHoursDaily(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)12692 TimeConstraint* Rules::readTeacherActivityTagMaxHoursDaily(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
12693 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherActivityTagMaxHoursDaily"));
12694 	ConstraintTeacherActivityTagMaxHoursDaily* cn=new ConstraintTeacherActivityTagMaxHoursDaily();
12695 	while(xmlReader.readNextStartElement()){
12696 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
12697 		if(xmlReader.name()==QString("Weight_Percentage")){
12698 			QString text=xmlReader.readElementText();
12699 			cn->weightPercentage=customFETStrToDouble(text);
12700 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
12701 		}
12702 		else if(xmlReader.name()==QString("Active")){
12703 			QString text=xmlReader.readElementText();
12704 			if(text=="false"){
12705 				cn->active=false;
12706 			}
12707 		}
12708 		else if(xmlReader.name()==QString("Comments")){
12709 			QString text=xmlReader.readElementText();
12710 			cn->comments=text;
12711 		}
12712 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
12713 			QString text=xmlReader.readElementText();
12714 			cn->maxHoursDaily=text.toInt();
12715 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
12716 		}
12717 		else if(xmlReader.name()==QString("Teacher_Name")){
12718 			QString text=xmlReader.readElementText();
12719 			cn->teacherName=text;
12720 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
12721 		}
12722 		else if(xmlReader.name()==QString("Activity_Tag_Name")){
12723 			QString text=xmlReader.readElementText();
12724 			cn->activityTagName=text;
12725 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
12726 		}
12727 		else{
12728 			unrecognizedXmlTags.append(xmlReader.name().toString());
12729 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
12730 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
12731 
12732 			xmlReader.skipCurrentElement();
12733 			xmlReaderNumberOfUnrecognizedFields++;
12734 		}
12735 	}
12736 	return cn;
12737 }
12738 
readTeachersActivityTagMaxHoursDaily(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)12739 TimeConstraint* Rules::readTeachersActivityTagMaxHoursDaily(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
12740 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersActivityTagMaxHoursDaily"));
12741 	ConstraintTeachersActivityTagMaxHoursDaily* cn=new ConstraintTeachersActivityTagMaxHoursDaily();
12742 	while(xmlReader.readNextStartElement()){
12743 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
12744 		if(xmlReader.name()==QString("Weight_Percentage")){
12745 			QString text=xmlReader.readElementText();
12746 			cn->weightPercentage=customFETStrToDouble(text);
12747 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
12748 		}
12749 		else if(xmlReader.name()==QString("Active")){
12750 			QString text=xmlReader.readElementText();
12751 			if(text=="false"){
12752 				cn->active=false;
12753 			}
12754 		}
12755 		else if(xmlReader.name()==QString("Comments")){
12756 			QString text=xmlReader.readElementText();
12757 			cn->comments=text;
12758 		}
12759 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
12760 			QString text=xmlReader.readElementText();
12761 			cn->maxHoursDaily=text.toInt();
12762 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
12763 		}
12764 		else if(xmlReader.name()==QString("Activity_Tag_Name")){
12765 			QString text=xmlReader.readElementText();
12766 			cn->activityTagName=text;
12767 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
12768 		}
12769 		else{
12770 			unrecognizedXmlTags.append(xmlReader.name().toString());
12771 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
12772 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
12773 
12774 			xmlReader.skipCurrentElement();
12775 			xmlReaderNumberOfUnrecognizedFields++;
12776 		}
12777 	}
12778 	return cn;
12779 }
12780 
readTeacherActivityTagMinHoursDaily(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)12781 TimeConstraint* Rules::readTeacherActivityTagMinHoursDaily(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
12782 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherActivityTagMinHoursDaily"));
12783 	ConstraintTeacherActivityTagMinHoursDaily* cn=new ConstraintTeacherActivityTagMinHoursDaily();
12784 	while(xmlReader.readNextStartElement()){
12785 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
12786 		if(xmlReader.name()==QString("Weight_Percentage")){
12787 			QString text=xmlReader.readElementText();
12788 			cn->weightPercentage=customFETStrToDouble(text);
12789 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
12790 		}
12791 		else if(xmlReader.name()==QString("Active")){
12792 			QString text=xmlReader.readElementText();
12793 			if(text=="false"){
12794 				cn->active=false;
12795 			}
12796 		}
12797 		else if(xmlReader.name()==QString("Comments")){
12798 			QString text=xmlReader.readElementText();
12799 			cn->comments=text;
12800 		}
12801 		else if(xmlReader.name()==QString("Minimum_Hours_Daily")){
12802 			QString text=xmlReader.readElementText();
12803 			cn->minHoursDaily=text.toInt();
12804 			xmlReadingLog+="    Read minHoursDaily="+CustomFETString::number(cn->minHoursDaily)+"\n";
12805 		}
12806 		else if(xmlReader.name()==QString("Teacher_Name")){
12807 			QString text=xmlReader.readElementText();
12808 			cn->teacherName=text;
12809 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
12810 		}
12811 		else if(xmlReader.name()==QString("Activity_Tag_Name")){
12812 			QString text=xmlReader.readElementText();
12813 			cn->activityTagName=text;
12814 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
12815 		}
12816 		else if(xmlReader.name()==QString("Allow_Empty_Days")){
12817 			QString text=xmlReader.readElementText();
12818 			if(text=="true")
12819 				cn->allowEmptyDays=true;
12820 			else
12821 				cn->allowEmptyDays=false;
12822 		}
12823 		else{
12824 			unrecognizedXmlTags.append(xmlReader.name().toString());
12825 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
12826 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
12827 
12828 			xmlReader.skipCurrentElement();
12829 			xmlReaderNumberOfUnrecognizedFields++;
12830 		}
12831 	}
12832 	return cn;
12833 }
12834 
readTeachersActivityTagMinHoursDaily(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)12835 TimeConstraint* Rules::readTeachersActivityTagMinHoursDaily(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
12836 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersActivityTagMinHoursDaily"));
12837 	ConstraintTeachersActivityTagMinHoursDaily* cn=new ConstraintTeachersActivityTagMinHoursDaily();
12838 	while(xmlReader.readNextStartElement()){
12839 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
12840 		if(xmlReader.name()==QString("Weight_Percentage")){
12841 			QString text=xmlReader.readElementText();
12842 			cn->weightPercentage=customFETStrToDouble(text);
12843 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
12844 		}
12845 		else if(xmlReader.name()==QString("Active")){
12846 			QString text=xmlReader.readElementText();
12847 			if(text=="false"){
12848 				cn->active=false;
12849 			}
12850 		}
12851 		else if(xmlReader.name()==QString("Comments")){
12852 			QString text=xmlReader.readElementText();
12853 			cn->comments=text;
12854 		}
12855 		else if(xmlReader.name()==QString("Minimum_Hours_Daily")){
12856 			QString text=xmlReader.readElementText();
12857 			cn->minHoursDaily=text.toInt();
12858 			xmlReadingLog+="    Read minHoursDaily="+CustomFETString::number(cn->minHoursDaily)+"\n";
12859 		}
12860 		else if(xmlReader.name()==QString("Activity_Tag_Name")){
12861 			QString text=xmlReader.readElementText();
12862 			cn->activityTagName=text;
12863 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
12864 		}
12865 		else if(xmlReader.name()==QString("Allow_Empty_Days")){
12866 			QString text=xmlReader.readElementText();
12867 			if(text=="true")
12868 				cn->allowEmptyDays=true;
12869 			else
12870 				cn->allowEmptyDays=false;
12871 		}
12872 		else{
12873 			unrecognizedXmlTags.append(xmlReader.name().toString());
12874 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
12875 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
12876 
12877 			xmlReader.skipCurrentElement();
12878 			xmlReaderNumberOfUnrecognizedFields++;
12879 		}
12880 	}
12881 	return cn;
12882 }
12883 
readTeachersMinHoursDaily(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)12884 TimeConstraint* Rules::readTeachersMinHoursDaily(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
12885 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMinHoursDaily"));
12886 	ConstraintTeachersMinHoursDaily* cn=new ConstraintTeachersMinHoursDaily();
12887 	cn->allowEmptyDays=true;
12888 	while(xmlReader.readNextStartElement()){
12889 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
12890 		if(xmlReader.name()==QString("Weight")){
12891 			//cn->weight=customFETStrToDouble(text);
12892 			xmlReader.skipCurrentElement();
12893 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
12894 			cn->weightPercentage=100;
12895 		}
12896 		else if(xmlReader.name()==QString("Weight_Percentage")){
12897 			QString text=xmlReader.readElementText();
12898 			cn->weightPercentage=customFETStrToDouble(text);
12899 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
12900 		}
12901 		else if(xmlReader.name()==QString("Active")){
12902 			QString text=xmlReader.readElementText();
12903 			if(text=="false"){
12904 				cn->active=false;
12905 			}
12906 		}
12907 		else if(xmlReader.name()==QString("Comments")){
12908 			QString text=xmlReader.readElementText();
12909 			cn->comments=text;
12910 		}
12911 		else if(xmlReader.name()==QString("Compulsory")){
12912 			QString text=xmlReader.readElementText();
12913 			if(text=="yes"){
12914 				//cn->compulsory=true;
12915 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
12916 				cn->weightPercentage=100;
12917 			}
12918 			else{
12919 				//cn->compulsory=false;
12920 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
12921 				cn->weightPercentage=0;
12922 			}
12923 		}
12924 		else if(xmlReader.name()==QString("Minimum_Hours_Daily")){
12925 			QString text=xmlReader.readElementText();
12926 			cn->minHoursDaily=text.toInt();
12927 			xmlReadingLog+="    Read minHoursDaily="+CustomFETString::number(cn->minHoursDaily)+"\n";
12928 		}
12929 		else if(xmlReader.name()==QString("Allow_Empty_Days")){
12930 			QString text=xmlReader.readElementText();
12931 			if(text=="true" || text=="1" || text=="yes"){
12932 				xmlReadingLog+="    Read allow empty days=true\n";
12933 				cn->allowEmptyDays=true;
12934 			}
12935 			else{
12936 				if(!(text=="no" || text=="false" || text=="0")){
12937 					RulesReconcilableMessage::warning(parent, tr("FET warning"),
12938 						tr("Found constraint teachers min hours daily with tag allow empty days"
12939 						" which is not 'true', 'false', 'yes', 'no', '1' or '0'."
12940 						" The tag will be considered false",
12941 						"Instructions for translators: please leave the 'true', 'false', 'yes' and 'no' fields untranslated, as they are in English"));
12942 				}
12943 				//assert(text=="false" || text=="0" || text=="no");
12944 				xmlReadingLog+="    Read allow empty days=false\n";
12945 				cn->allowEmptyDays=false;
12946 			}
12947 		}
12948 		else{
12949 			unrecognizedXmlTags.append(xmlReader.name().toString());
12950 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
12951 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
12952 
12953 			xmlReader.skipCurrentElement();
12954 			xmlReaderNumberOfUnrecognizedFields++;
12955 		}
12956 	}
12957 	return cn;
12958 }
12959 
readTeacherMinHoursDaily(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)12960 TimeConstraint* Rules::readTeacherMinHoursDaily(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
12961 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMinHoursDaily"));
12962 	ConstraintTeacherMinHoursDaily* cn=new ConstraintTeacherMinHoursDaily();
12963 	cn->allowEmptyDays=true;
12964 	while(xmlReader.readNextStartElement()){
12965 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
12966 		if(xmlReader.name()==QString("Weight")){
12967 			//cn->weight=customFETStrToDouble(text);
12968 			xmlReader.skipCurrentElement();
12969 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
12970 			cn->weightPercentage=100;
12971 		}
12972 		else if(xmlReader.name()==QString("Weight_Percentage")){
12973 			QString text=xmlReader.readElementText();
12974 			cn->weightPercentage=customFETStrToDouble(text);
12975 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
12976 		}
12977 		else if(xmlReader.name()==QString("Active")){
12978 			QString text=xmlReader.readElementText();
12979 			if(text=="false"){
12980 				cn->active=false;
12981 			}
12982 		}
12983 		else if(xmlReader.name()==QString("Comments")){
12984 			QString text=xmlReader.readElementText();
12985 			cn->comments=text;
12986 		}
12987 		else if(xmlReader.name()==QString("Compulsory")){
12988 			QString text=xmlReader.readElementText();
12989 			if(text=="yes"){
12990 				//cn->compulsory=true;
12991 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
12992 				cn->weightPercentage=100;
12993 			}
12994 			else{
12995 				//cn->compulsory=false;
12996 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
12997 				cn->weightPercentage=0;
12998 			}
12999 		}
13000 		else if(xmlReader.name()==QString("Minimum_Hours_Daily")){
13001 			QString text=xmlReader.readElementText();
13002 			cn->minHoursDaily=text.toInt();
13003 			xmlReadingLog+="    Read minHoursDaily="+CustomFETString::number(cn->minHoursDaily)+"\n";
13004 		}
13005 		else if(xmlReader.name()==QString("Teacher_Name")){
13006 			QString text=xmlReader.readElementText();
13007 			cn->teacherName=text;
13008 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
13009 		}
13010 		else if(xmlReader.name()==QString("Allow_Empty_Days")){
13011 			QString text=xmlReader.readElementText();
13012 			if(text=="true" || text=="1" || text=="yes"){
13013 				xmlReadingLog+="    Read allow empty days=true\n";
13014 				cn->allowEmptyDays=true;
13015 			}
13016 			else{
13017 				if(!(text=="no" || text=="false" || text=="0")){
13018 					RulesReconcilableMessage::warning(parent, tr("FET warning"),
13019 						tr("Found constraint teacher min hours daily with tag allow empty days"
13020 						" which is not 'true', 'false', 'yes', 'no', '1' or '0'."
13021 						" The tag will be considered false",
13022 						"Instructions for translators: please leave the 'true', 'false', 'yes' and 'no' fields untranslated, as they are in English"));
13023 				}
13024 				//assert(text=="false" || text=="0" || text=="no");
13025 				xmlReadingLog+="    Read allow empty days=false\n";
13026 				cn->allowEmptyDays=false;
13027 			}
13028 		}
13029 		else{
13030 			unrecognizedXmlTags.append(xmlReader.name().toString());
13031 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
13032 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
13033 
13034 			xmlReader.skipCurrentElement();
13035 			xmlReaderNumberOfUnrecognizedFields++;
13036 		}
13037 	}
13038 	return cn;
13039 }
13040 
readStudentsMaxHoursDaily(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)13041 TimeConstraint* Rules::readStudentsMaxHoursDaily(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
13042 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMaxHoursDaily"));
13043 	ConstraintStudentsMaxHoursDaily* cn=new ConstraintStudentsMaxHoursDaily();
13044 	cn->maxHoursDaily=-1;
13045 	while(xmlReader.readNextStartElement()){
13046 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
13047 		if(xmlReader.name()==QString("Weight")){
13048 			//cn->weight=customFETStrToDouble(text);
13049 			xmlReader.skipCurrentElement();
13050 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
13051 			cn->weightPercentage=100;
13052 		}
13053 		else if(xmlReader.name()==QString("Weight_Percentage")){
13054 			QString text=xmlReader.readElementText();
13055 			cn->weightPercentage=customFETStrToDouble(text);
13056 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
13057 		}
13058 		else if(xmlReader.name()==QString("Active")){
13059 			QString text=xmlReader.readElementText();
13060 			if(text=="false"){
13061 				cn->active=false;
13062 			}
13063 		}
13064 		else if(xmlReader.name()==QString("Comments")){
13065 			QString text=xmlReader.readElementText();
13066 			cn->comments=text;
13067 		}
13068 		else if(xmlReader.name()==QString("Compulsory")){
13069 			QString text=xmlReader.readElementText();
13070 			if(text=="yes"){
13071 				//cn->compulsory=true;
13072 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
13073 				cn->weightPercentage=100;
13074 			}
13075 			else{
13076 				//cn->compulsory=false;
13077 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
13078 				cn->weightPercentage=0;
13079 			}
13080 		}
13081 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
13082 			QString text=xmlReader.readElementText();
13083 			cn->maxHoursDaily=text.toInt();
13084 			if(cn->maxHoursDaily<0){
13085 				xmlReader.raiseError(tr("%1 is incorrect").arg("Maximum_Hours_Daily"));
13086 				delete cn;
13087 				cn=nullptr;
13088 				return nullptr;
13089 			}
13090 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
13091 		}
13092 		else{
13093 			unrecognizedXmlTags.append(xmlReader.name().toString());
13094 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
13095 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
13096 
13097 			xmlReader.skipCurrentElement();
13098 			xmlReaderNumberOfUnrecognizedFields++;
13099 		}
13100 	}
13101 	if(cn->maxHoursDaily<0){
13102 		xmlReader.raiseError(tr("%1 not found").arg("Maximum_Hours_Daily"));
13103 		delete cn;
13104 		cn=nullptr;
13105 		return nullptr;
13106 	}
13107 	assert(cn->maxHoursDaily>=0);
13108 	return cn;
13109 }
13110 
readStudentsSetMaxHoursDaily(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)13111 TimeConstraint* Rules::readStudentsSetMaxHoursDaily(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
13112 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMaxHoursDaily"));
13113 	ConstraintStudentsSetMaxHoursDaily* cn=new ConstraintStudentsSetMaxHoursDaily();
13114 	cn->maxHoursDaily=-1;
13115 	while(xmlReader.readNextStartElement()){
13116 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
13117 		if(xmlReader.name()==QString("Weight")){
13118 			//cn->weight=customFETStrToDouble(text);
13119 			xmlReader.skipCurrentElement();
13120 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
13121 			cn->weightPercentage=100;
13122 		}
13123 		else if(xmlReader.name()==QString("Weight_Percentage")){
13124 			QString text=xmlReader.readElementText();
13125 			cn->weightPercentage=customFETStrToDouble(text);
13126 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
13127 		}
13128 		else if(xmlReader.name()==QString("Active")){
13129 			QString text=xmlReader.readElementText();
13130 			if(text=="false"){
13131 				cn->active=false;
13132 			}
13133 		}
13134 		else if(xmlReader.name()==QString("Comments")){
13135 			QString text=xmlReader.readElementText();
13136 			cn->comments=text;
13137 		}
13138 		else if(xmlReader.name()==QString("Compulsory")){
13139 			QString text=xmlReader.readElementText();
13140 			if(text=="yes"){
13141 				//cn->compulsory=true;
13142 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
13143 				cn->weightPercentage=100;
13144 			}
13145 			else{
13146 				//cn->compulsory=false;
13147 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
13148 				cn->weightPercentage=0;
13149 			}
13150 		}
13151 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
13152 			QString text=xmlReader.readElementText();
13153 			cn->maxHoursDaily=text.toInt();
13154 			if(cn->maxHoursDaily<0){
13155 				xmlReader.raiseError(tr("%1 is incorrect").arg("Maximum_Hours_Daily"));
13156 				delete cn;
13157 				cn=nullptr;
13158 				return nullptr;
13159 			}
13160 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
13161 		}
13162 		else if(xmlReader.name()==QString("Students")){
13163 			QString text=xmlReader.readElementText();
13164 			cn->students=text;
13165 			xmlReadingLog+="    Read students name="+cn->students+"\n";
13166 		}
13167 		else{
13168 			unrecognizedXmlTags.append(xmlReader.name().toString());
13169 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
13170 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
13171 
13172 			xmlReader.skipCurrentElement();
13173 			xmlReaderNumberOfUnrecognizedFields++;
13174 		}
13175 	}
13176 	if(cn->maxHoursDaily<0){
13177 		xmlReader.raiseError(tr("%1 not found").arg("Maximum_Hours_Daily"));
13178 		delete cn;
13179 		cn=nullptr;
13180 		return nullptr;
13181 	}
13182 	assert(cn->maxHoursDaily>=0);
13183 	return cn;
13184 }
13185 
readStudentsMaxHoursContinuously(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)13186 TimeConstraint* Rules::readStudentsMaxHoursContinuously(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
13187 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMaxHoursContinuously"));
13188 	ConstraintStudentsMaxHoursContinuously* cn=new ConstraintStudentsMaxHoursContinuously();
13189 	cn->maxHoursContinuously=-1;
13190 	while(xmlReader.readNextStartElement()){
13191 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
13192 		if(xmlReader.name()==QString("Weight")){
13193 			//cn->weight=customFETStrToDouble(text);
13194 			xmlReader.skipCurrentElement();
13195 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
13196 			cn->weightPercentage=100;
13197 		}
13198 		else if(xmlReader.name()==QString("Weight_Percentage")){
13199 			QString text=xmlReader.readElementText();
13200 			cn->weightPercentage=customFETStrToDouble(text);
13201 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
13202 		}
13203 		else if(xmlReader.name()==QString("Active")){
13204 			QString text=xmlReader.readElementText();
13205 			if(text=="false"){
13206 				cn->active=false;
13207 			}
13208 		}
13209 		else if(xmlReader.name()==QString("Comments")){
13210 			QString text=xmlReader.readElementText();
13211 			cn->comments=text;
13212 		}
13213 		else if(xmlReader.name()==QString("Compulsory")){
13214 			QString text=xmlReader.readElementText();
13215 			if(text=="yes"){
13216 				//cn->compulsory=true;
13217 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
13218 				cn->weightPercentage=100;
13219 			}
13220 			else{
13221 				//cn->compulsory=false;
13222 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
13223 				cn->weightPercentage=0;
13224 			}
13225 		}
13226 		else if(xmlReader.name()==QString("Maximum_Hours_Continuously")){
13227 			QString text=xmlReader.readElementText();
13228 			cn->maxHoursContinuously=text.toInt();
13229 			if(cn->maxHoursContinuously<0){
13230 				xmlReader.raiseError(tr("%1 is incorrect").arg("Maximum_Hours_Continuously"));
13231 				delete cn;
13232 				cn=nullptr;
13233 				return nullptr;
13234 			}
13235 			xmlReadingLog+="    Read maxHoursContinuously="+CustomFETString::number(cn->maxHoursContinuously)+"\n";
13236 		}
13237 		else{
13238 			unrecognizedXmlTags.append(xmlReader.name().toString());
13239 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
13240 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
13241 
13242 			xmlReader.skipCurrentElement();
13243 			xmlReaderNumberOfUnrecognizedFields++;
13244 		}
13245 	}
13246 	if(cn->maxHoursContinuously<0){
13247 		xmlReader.raiseError(tr("%1 not found").arg("Maximum_Hours_Continuously"));
13248 		delete cn;
13249 		cn=nullptr;
13250 		return nullptr;
13251 	}
13252 	assert(cn->maxHoursContinuously>=0);
13253 	return cn;
13254 }
13255 
readStudentsSetMaxHoursContinuously(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)13256 TimeConstraint* Rules::readStudentsSetMaxHoursContinuously(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
13257 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMaxHoursContinuously"));
13258 	ConstraintStudentsSetMaxHoursContinuously* cn=new ConstraintStudentsSetMaxHoursContinuously();
13259 	cn->maxHoursContinuously=-1;
13260 	while(xmlReader.readNextStartElement()){
13261 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
13262 		if(xmlReader.name()==QString("Weight")){
13263 			//cn->weight=customFETStrToDouble(text);
13264 			xmlReader.skipCurrentElement();
13265 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
13266 			cn->weightPercentage=100;
13267 		}
13268 		else if(xmlReader.name()==QString("Weight_Percentage")){
13269 			QString text=xmlReader.readElementText();
13270 			cn->weightPercentage=customFETStrToDouble(text);
13271 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
13272 		}
13273 		else if(xmlReader.name()==QString("Active")){
13274 			QString text=xmlReader.readElementText();
13275 			if(text=="false"){
13276 				cn->active=false;
13277 			}
13278 		}
13279 		else if(xmlReader.name()==QString("Comments")){
13280 			QString text=xmlReader.readElementText();
13281 			cn->comments=text;
13282 		}
13283 		else if(xmlReader.name()==QString("Compulsory")){
13284 			QString text=xmlReader.readElementText();
13285 			if(text=="yes"){
13286 				//cn->compulsory=true;
13287 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
13288 				cn->weightPercentage=100;
13289 			}
13290 			else{
13291 				//cn->compulsory=false;
13292 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
13293 				cn->weightPercentage=0;
13294 			}
13295 		}
13296 		else if(xmlReader.name()==QString("Maximum_Hours_Continuously")){
13297 			QString text=xmlReader.readElementText();
13298 			cn->maxHoursContinuously=text.toInt();
13299 			if(cn->maxHoursContinuously<0){
13300 				xmlReader.raiseError(tr("%1 is incorrect").arg("Maximum_Hours_Continuously"));
13301 				delete cn;
13302 				cn=nullptr;
13303 				return nullptr;
13304 			}
13305 			xmlReadingLog+="    Read maxHoursContinuously="+CustomFETString::number(cn->maxHoursContinuously)+"\n";
13306 		}
13307 		else if(xmlReader.name()==QString("Students")){
13308 			QString text=xmlReader.readElementText();
13309 			cn->students=text;
13310 			xmlReadingLog+="    Read students name="+cn->students+"\n";
13311 		}
13312 		else{
13313 			unrecognizedXmlTags.append(xmlReader.name().toString());
13314 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
13315 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
13316 
13317 			xmlReader.skipCurrentElement();
13318 			xmlReaderNumberOfUnrecognizedFields++;
13319 		}
13320 	}
13321 	if(cn->maxHoursContinuously<0){
13322 		xmlReader.raiseError(tr("%1 not found").arg("Maximum_Hours_Continuously"));
13323 		delete cn;
13324 		cn=nullptr;
13325 		return nullptr;
13326 	}
13327 	assert(cn->maxHoursContinuously>=0);
13328 	return cn;
13329 }
13330 
readStudentsSetActivityTagMaxHoursContinuously(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)13331 TimeConstraint* Rules::readStudentsSetActivityTagMaxHoursContinuously(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
13332 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetActivityTagMaxHoursContinuously"));
13333 	ConstraintStudentsSetActivityTagMaxHoursContinuously* cn=new ConstraintStudentsSetActivityTagMaxHoursContinuously();
13334 	cn->maxHoursContinuously=-1;
13335 	while(xmlReader.readNextStartElement()){
13336 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
13337 		if(xmlReader.name()==QString("Weight_Percentage")){
13338 			QString text=xmlReader.readElementText();
13339 			cn->weightPercentage=customFETStrToDouble(text);
13340 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
13341 		}
13342 		else if(xmlReader.name()==QString("Active")){
13343 			QString text=xmlReader.readElementText();
13344 			if(text=="false"){
13345 				cn->active=false;
13346 			}
13347 		}
13348 		else if(xmlReader.name()==QString("Comments")){
13349 			QString text=xmlReader.readElementText();
13350 			cn->comments=text;
13351 		}
13352 		else if(xmlReader.name()==QString("Maximum_Hours_Continuously")){
13353 			QString text=xmlReader.readElementText();
13354 			cn->maxHoursContinuously=text.toInt();
13355 			if(cn->maxHoursContinuously<0){
13356 				xmlReader.raiseError(tr("%1 is incorrect").arg("Maximum_Hours_Continuously"));
13357 				delete cn;
13358 				cn=nullptr;
13359 				return nullptr;
13360 			}
13361 			xmlReadingLog+="    Read maxHoursContinuously="+CustomFETString::number(cn->maxHoursContinuously)+"\n";
13362 		}
13363 		else if(xmlReader.name()==QString("Students")){
13364 			QString text=xmlReader.readElementText();
13365 			cn->students=text;
13366 			xmlReadingLog+="    Read students name="+cn->students+"\n";
13367 		}
13368 		else if(xmlReader.name()==QString("Activity_Tag")){
13369 			QString text=xmlReader.readElementText();
13370 			cn->activityTagName=text;
13371 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
13372 		}
13373 		else{
13374 			unrecognizedXmlTags.append(xmlReader.name().toString());
13375 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
13376 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
13377 
13378 			xmlReader.skipCurrentElement();
13379 			xmlReaderNumberOfUnrecognizedFields++;
13380 		}
13381 	}
13382 	if(cn->maxHoursContinuously<0){
13383 		xmlReader.raiseError(tr("%1 not found").arg("Maximum_Hours_Continuously"));
13384 		delete cn;
13385 		cn=nullptr;
13386 		return nullptr;
13387 	}
13388 	assert(cn->maxHoursContinuously>=0);
13389 	return cn;
13390 }
13391 
readStudentsActivityTagMaxHoursContinuously(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)13392 TimeConstraint* Rules::readStudentsActivityTagMaxHoursContinuously(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
13393 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsActivityTagMaxHoursContinuously"));
13394 	ConstraintStudentsActivityTagMaxHoursContinuously* cn=new ConstraintStudentsActivityTagMaxHoursContinuously();
13395 	cn->maxHoursContinuously=-1;
13396 	while(xmlReader.readNextStartElement()){
13397 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
13398 		if(xmlReader.name()==QString("Weight_Percentage")){
13399 			QString text=xmlReader.readElementText();
13400 			cn->weightPercentage=customFETStrToDouble(text);
13401 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
13402 		}
13403 		else if(xmlReader.name()==QString("Active")){
13404 			QString text=xmlReader.readElementText();
13405 			if(text=="false"){
13406 				cn->active=false;
13407 			}
13408 		}
13409 		else if(xmlReader.name()==QString("Comments")){
13410 			QString text=xmlReader.readElementText();
13411 			cn->comments=text;
13412 		}
13413 		else if(xmlReader.name()==QString("Maximum_Hours_Continuously")){
13414 			QString text=xmlReader.readElementText();
13415 			cn->maxHoursContinuously=text.toInt();
13416 			if(cn->maxHoursContinuously<0){
13417 				xmlReader.raiseError(tr("%1 is incorrect").arg("Maximum_Hours_Continuously"));
13418 				delete cn;
13419 				cn=nullptr;
13420 				return nullptr;
13421 			}
13422 			xmlReadingLog+="    Read maxHoursContinuously="+CustomFETString::number(cn->maxHoursContinuously)+"\n";
13423 		}
13424 		else if(xmlReader.name()==QString("Activity_Tag")){
13425 			QString text=xmlReader.readElementText();
13426 			cn->activityTagName=text;
13427 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
13428 		}
13429 		else{
13430 			unrecognizedXmlTags.append(xmlReader.name().toString());
13431 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
13432 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
13433 
13434 			xmlReader.skipCurrentElement();
13435 			xmlReaderNumberOfUnrecognizedFields++;
13436 		}
13437 	}
13438 	if(cn->maxHoursContinuously<0){
13439 		xmlReader.raiseError(tr("%1 not found").arg("Maximum_Hours_Continuously"));
13440 		delete cn;
13441 		cn=nullptr;
13442 		return nullptr;
13443 	}
13444 	assert(cn->maxHoursContinuously>=0);
13445 	return cn;
13446 }
13447 
readStudentsSetActivityTagMaxHoursDaily(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)13448 TimeConstraint* Rules::readStudentsSetActivityTagMaxHoursDaily(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
13449 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetActivityTagMaxHoursDaily"));
13450 	ConstraintStudentsSetActivityTagMaxHoursDaily* cn=new ConstraintStudentsSetActivityTagMaxHoursDaily();
13451 	cn->maxHoursDaily=-1;
13452 	while(xmlReader.readNextStartElement()){
13453 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
13454 		if(xmlReader.name()==QString("Weight_Percentage")){
13455 			QString text=xmlReader.readElementText();
13456 			cn->weightPercentage=customFETStrToDouble(text);
13457 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
13458 		}
13459 		else if(xmlReader.name()==QString("Active")){
13460 			QString text=xmlReader.readElementText();
13461 			if(text=="false"){
13462 				cn->active=false;
13463 			}
13464 		}
13465 		else if(xmlReader.name()==QString("Comments")){
13466 			QString text=xmlReader.readElementText();
13467 			cn->comments=text;
13468 		}
13469 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
13470 			QString text=xmlReader.readElementText();
13471 			cn->maxHoursDaily=text.toInt();
13472 			if(cn->maxHoursDaily<0){
13473 				xmlReader.raiseError(tr("%1 is incorrect").arg("Maximum_Hours_Daily"));
13474 				delete cn;
13475 				cn=nullptr;
13476 				return nullptr;
13477 			}
13478 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
13479 		}
13480 		else if(xmlReader.name()==QString("Students")){
13481 			QString text=xmlReader.readElementText();
13482 			cn->students=text;
13483 			xmlReadingLog+="    Read students name="+cn->students+"\n";
13484 		}
13485 		else if(xmlReader.name()==QString("Activity_Tag")){
13486 			QString text=xmlReader.readElementText();
13487 			cn->activityTagName=text;
13488 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
13489 		}
13490 		else{
13491 			unrecognizedXmlTags.append(xmlReader.name().toString());
13492 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
13493 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
13494 
13495 			xmlReader.skipCurrentElement();
13496 			xmlReaderNumberOfUnrecognizedFields++;
13497 		}
13498 	}
13499 	if(cn->maxHoursDaily<0){
13500 		xmlReader.raiseError(tr("%1 not found").arg("Maximum_Hours_Daily"));
13501 		delete cn;
13502 		cn=nullptr;
13503 		return nullptr;
13504 	}
13505 	assert(cn->maxHoursDaily>=0);
13506 	return cn;
13507 }
13508 
readStudentsActivityTagMaxHoursDaily(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)13509 TimeConstraint* Rules::readStudentsActivityTagMaxHoursDaily(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
13510 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsActivityTagMaxHoursDaily"));
13511 	ConstraintStudentsActivityTagMaxHoursDaily* cn=new ConstraintStudentsActivityTagMaxHoursDaily();
13512 	cn->maxHoursDaily=-1;
13513 	while(xmlReader.readNextStartElement()){
13514 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
13515 		if(xmlReader.name()==QString("Weight_Percentage")){
13516 			QString text=xmlReader.readElementText();
13517 			cn->weightPercentage=customFETStrToDouble(text);
13518 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
13519 		}
13520 		else if(xmlReader.name()==QString("Active")){
13521 			QString text=xmlReader.readElementText();
13522 			if(text=="false"){
13523 				cn->active=false;
13524 			}
13525 		}
13526 		else if(xmlReader.name()==QString("Comments")){
13527 			QString text=xmlReader.readElementText();
13528 			cn->comments=text;
13529 		}
13530 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
13531 			QString text=xmlReader.readElementText();
13532 			cn->maxHoursDaily=text.toInt();
13533 			if(cn->maxHoursDaily<0){
13534 				xmlReader.raiseError(tr("%1 is incorrect").arg("Maximum_Hours_Daily"));
13535 				delete cn;
13536 				cn=nullptr;
13537 				return nullptr;
13538 			}
13539 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
13540 		}
13541 		else if(xmlReader.name()==QString("Activity_Tag")){
13542 			QString text=xmlReader.readElementText();
13543 			cn->activityTagName=text;
13544 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
13545 		}
13546 		else{
13547 			unrecognizedXmlTags.append(xmlReader.name().toString());
13548 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
13549 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
13550 
13551 			xmlReader.skipCurrentElement();
13552 			xmlReaderNumberOfUnrecognizedFields++;
13553 		}
13554 	}
13555 	if(cn->maxHoursDaily<0){
13556 		xmlReader.raiseError(tr("%1 not found").arg("Maximum_Hours_Daily"));
13557 		delete cn;
13558 		cn=nullptr;
13559 		return nullptr;
13560 	}
13561 	assert(cn->maxHoursDaily>=0);
13562 	return cn;
13563 }
13564 
readStudentsSetActivityTagMinHoursDaily(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)13565 TimeConstraint* Rules::readStudentsSetActivityTagMinHoursDaily(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
13566 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetActivityTagMinHoursDaily"));
13567 	ConstraintStudentsSetActivityTagMinHoursDaily* cn=new ConstraintStudentsSetActivityTagMinHoursDaily();
13568 	cn->minHoursDaily=-1;
13569 	while(xmlReader.readNextStartElement()){
13570 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
13571 		if(xmlReader.name()==QString("Weight_Percentage")){
13572 			QString text=xmlReader.readElementText();
13573 			cn->weightPercentage=customFETStrToDouble(text);
13574 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
13575 		}
13576 		else if(xmlReader.name()==QString("Active")){
13577 			QString text=xmlReader.readElementText();
13578 			if(text=="false"){
13579 				cn->active=false;
13580 			}
13581 		}
13582 		else if(xmlReader.name()==QString("Comments")){
13583 			QString text=xmlReader.readElementText();
13584 			cn->comments=text;
13585 		}
13586 		else if(xmlReader.name()==QString("Minimum_Hours_Daily")){
13587 			QString text=xmlReader.readElementText();
13588 			cn->minHoursDaily=text.toInt();
13589 			if(cn->minHoursDaily<0){
13590 				xmlReader.raiseError(tr("%1 is incorrect").arg("Minimum_Hours_Daily"));
13591 				delete cn;
13592 				cn=nullptr;
13593 				return nullptr;
13594 			}
13595 			xmlReadingLog+="    Read minHoursDaily="+CustomFETString::number(cn->minHoursDaily)+"\n";
13596 		}
13597 		else if(xmlReader.name()==QString("Students")){
13598 			QString text=xmlReader.readElementText();
13599 			cn->students=text;
13600 			xmlReadingLog+="    Read students name="+cn->students+"\n";
13601 		}
13602 		else if(xmlReader.name()==QString("Activity_Tag")){
13603 			QString text=xmlReader.readElementText();
13604 			cn->activityTagName=text;
13605 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
13606 		}
13607 		else if(xmlReader.name()==QString("Allow_Empty_Days")){
13608 			QString text=xmlReader.readElementText();
13609 			if(text=="true")
13610 				cn->allowEmptyDays=true;
13611 			else
13612 				cn->allowEmptyDays=false;
13613 		}
13614 		else{
13615 			unrecognizedXmlTags.append(xmlReader.name().toString());
13616 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
13617 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
13618 
13619 			xmlReader.skipCurrentElement();
13620 			xmlReaderNumberOfUnrecognizedFields++;
13621 		}
13622 	}
13623 	if(cn->minHoursDaily<0){
13624 		xmlReader.raiseError(tr("%1 not found").arg("Minimum_Hours_Daily"));
13625 		delete cn;
13626 		cn=nullptr;
13627 		return nullptr;
13628 	}
13629 	assert(cn->minHoursDaily>=0);
13630 	return cn;
13631 }
13632 
readStudentsActivityTagMinHoursDaily(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)13633 TimeConstraint* Rules::readStudentsActivityTagMinHoursDaily(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
13634 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsActivityTagMinHoursDaily"));
13635 	ConstraintStudentsActivityTagMinHoursDaily* cn=new ConstraintStudentsActivityTagMinHoursDaily();
13636 	cn->minHoursDaily=-1;
13637 	while(xmlReader.readNextStartElement()){
13638 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
13639 		if(xmlReader.name()==QString("Weight_Percentage")){
13640 			QString text=xmlReader.readElementText();
13641 			cn->weightPercentage=customFETStrToDouble(text);
13642 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
13643 		}
13644 		else if(xmlReader.name()==QString("Active")){
13645 			QString text=xmlReader.readElementText();
13646 			if(text=="false"){
13647 				cn->active=false;
13648 			}
13649 		}
13650 		else if(xmlReader.name()==QString("Comments")){
13651 			QString text=xmlReader.readElementText();
13652 			cn->comments=text;
13653 		}
13654 		else if(xmlReader.name()==QString("Minimum_Hours_Daily")){
13655 			QString text=xmlReader.readElementText();
13656 			cn->minHoursDaily=text.toInt();
13657 			if(cn->minHoursDaily<0){
13658 				xmlReader.raiseError(tr("%1 is incorrect").arg("Minimum_Hours_Daily"));
13659 				delete cn;
13660 				cn=nullptr;
13661 				return nullptr;
13662 			}
13663 			xmlReadingLog+="    Read minHoursDaily="+CustomFETString::number(cn->minHoursDaily)+"\n";
13664 		}
13665 		else if(xmlReader.name()==QString("Activity_Tag")){
13666 			QString text=xmlReader.readElementText();
13667 			cn->activityTagName=text;
13668 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
13669 		}
13670 		else if(xmlReader.name()==QString("Allow_Empty_Days")){
13671 			QString text=xmlReader.readElementText();
13672 			if(text=="true")
13673 				cn->allowEmptyDays=true;
13674 			else
13675 				cn->allowEmptyDays=false;
13676 		}
13677 		else{
13678 			unrecognizedXmlTags.append(xmlReader.name().toString());
13679 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
13680 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
13681 
13682 			xmlReader.skipCurrentElement();
13683 			xmlReaderNumberOfUnrecognizedFields++;
13684 		}
13685 	}
13686 	if(cn->minHoursDaily<0){
13687 		xmlReader.raiseError(tr("%1 not found").arg("Minimum_Hours_Daily"));
13688 		delete cn;
13689 		cn=nullptr;
13690 		return nullptr;
13691 	}
13692 	assert(cn->minHoursDaily>=0);
13693 	return cn;
13694 }
13695 
readStudentsMinHoursDaily(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)13696 TimeConstraint* Rules::readStudentsMinHoursDaily(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
13697 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMinHoursDaily"));
13698 	ConstraintStudentsMinHoursDaily* cn=new ConstraintStudentsMinHoursDaily();
13699 	cn->minHoursDaily=-1;
13700 	cn->allowEmptyDays=false;
13701 	while(xmlReader.readNextStartElement()){
13702 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
13703 		if(xmlReader.name()==QString("Weight")){
13704 			//cn->weight=customFETStrToDouble(text);
13705 			xmlReader.skipCurrentElement();
13706 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
13707 			cn->weightPercentage=100;
13708 		}
13709 		else if(xmlReader.name()==QString("Weight_Percentage")){
13710 			QString text=xmlReader.readElementText();
13711 			cn->weightPercentage=customFETStrToDouble(text);
13712 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
13713 		}
13714 		else if(xmlReader.name()==QString("Active")){
13715 			QString text=xmlReader.readElementText();
13716 			if(text=="false"){
13717 				cn->active=false;
13718 			}
13719 		}
13720 		else if(xmlReader.name()==QString("Comments")){
13721 			QString text=xmlReader.readElementText();
13722 			cn->comments=text;
13723 		}
13724 		else if(xmlReader.name()==QString("Compulsory")){
13725 			QString text=xmlReader.readElementText();
13726 			if(text=="yes"){
13727 				//cn->compulsory=true;
13728 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
13729 				cn->weightPercentage=100;
13730 			}
13731 			else{
13732 				//cn->compulsory=false;
13733 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
13734 				cn->weightPercentage=0;
13735 			}
13736 		}
13737 		else if(xmlReader.name()==QString("Minimum_Hours_Daily")){
13738 			QString text=xmlReader.readElementText();
13739 			cn->minHoursDaily=text.toInt();
13740 			if(cn->minHoursDaily<0){
13741 				xmlReader.raiseError(tr("%1 is incorrect").arg("Minimum_Hours_Daily"));
13742 				delete cn;
13743 				cn=nullptr;
13744 				return nullptr;
13745 			}
13746 			xmlReadingLog+="    Read minHoursDaily="+CustomFETString::number(cn->minHoursDaily)+"\n";
13747 		}
13748 		else if(xmlReader.name()==QString("Allow_Empty_Days")){
13749 			QString text=xmlReader.readElementText();
13750 			if(text=="true" || text=="1" || text=="yes"){
13751 				xmlReadingLog+="    Read allow empty days=true\n";
13752 				cn->allowEmptyDays=true;
13753 			}
13754 			else{
13755 				if(!(text=="no" || text=="false" || text=="0")){
13756 					RulesReconcilableMessage::warning(parent, tr("FET warning"),
13757 						tr("Found constraint students min hours daily with tag allow empty days"
13758 						" which is not 'true', 'false', 'yes', 'no', '1' or '0'."
13759 						" The tag will be considered false",
13760 						"Instructions for translators: please leave the 'true', 'false', 'yes' and 'no' fields untranslated, as they are in English"));
13761 				}
13762 				//assert(text=="false" || text=="0" || text=="no");
13763 				xmlReadingLog+="    Read allow empty days=false\n";
13764 				cn->allowEmptyDays=false;
13765 			}
13766 		}
13767 		else{
13768 			unrecognizedXmlTags.append(xmlReader.name().toString());
13769 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
13770 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
13771 
13772 			xmlReader.skipCurrentElement();
13773 			xmlReaderNumberOfUnrecognizedFields++;
13774 		}
13775 	}
13776 	if(cn->minHoursDaily<0){
13777 		xmlReader.raiseError(tr("%1 not found").arg("Minimum_Hours_Daily"));
13778 		delete cn;
13779 		cn=nullptr;
13780 		return nullptr;
13781 	}
13782 	assert(cn->minHoursDaily>=0);
13783 	return cn;
13784 }
13785 
readStudentsSetMinHoursDaily(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)13786 TimeConstraint* Rules::readStudentsSetMinHoursDaily(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
13787 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMinHoursDaily"));
13788 	ConstraintStudentsSetMinHoursDaily* cn=new ConstraintStudentsSetMinHoursDaily();
13789 	cn->minHoursDaily=-1;
13790 	cn->allowEmptyDays=false;
13791 	while(xmlReader.readNextStartElement()){
13792 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
13793 		if(xmlReader.name()==QString("Weight")){
13794 			//cn->weight=customFETStrToDouble(text);
13795 			xmlReader.skipCurrentElement();
13796 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
13797 			cn->weightPercentage=100;
13798 		}
13799 		else if(xmlReader.name()==QString("Weight_Percentage")){
13800 			QString text=xmlReader.readElementText();
13801 			cn->weightPercentage=customFETStrToDouble(text);
13802 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
13803 		}
13804 		else if(xmlReader.name()==QString("Active")){
13805 			QString text=xmlReader.readElementText();
13806 			if(text=="false"){
13807 				cn->active=false;
13808 			}
13809 		}
13810 		else if(xmlReader.name()==QString("Comments")){
13811 			QString text=xmlReader.readElementText();
13812 			cn->comments=text;
13813 		}
13814 		else if(xmlReader.name()==QString("Compulsory")){
13815 			QString text=xmlReader.readElementText();
13816 			if(text=="yes"){
13817 				//cn->compulsory=true;
13818 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
13819 				cn->weightPercentage=100;
13820 			}
13821 			else{
13822 				//cn->compulsory=false;
13823 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
13824 				cn->weightPercentage=0;
13825 			}
13826 		}
13827 		else if(xmlReader.name()==QString("Minimum_Hours_Daily")){
13828 			QString text=xmlReader.readElementText();
13829 			cn->minHoursDaily=text.toInt();
13830 			if(cn->minHoursDaily<0){
13831 				xmlReader.raiseError(tr("%1 is incorrect").arg("Minimum_Hours_Daily"));
13832 				delete cn;
13833 				cn=nullptr;
13834 				return nullptr;
13835 			}
13836 			xmlReadingLog+="    Read minHoursDaily="+CustomFETString::number(cn->minHoursDaily)+"\n";
13837 		}
13838 		else if(xmlReader.name()==QString("Students")){
13839 			QString text=xmlReader.readElementText();
13840 			cn->students=text;
13841 			xmlReadingLog+="    Read students name="+cn->students+"\n";
13842 		}
13843 		else if(xmlReader.name()==QString("Allow_Empty_Days")){
13844 			QString text=xmlReader.readElementText();
13845 			if(text=="true" || text=="1" || text=="yes"){
13846 				xmlReadingLog+="    Read allow empty days=true\n";
13847 				cn->allowEmptyDays=true;
13848 			}
13849 			else{
13850 				if(!(text=="no" || text=="false" || text=="0")){
13851 					RulesReconcilableMessage::warning(parent, tr("FET warning"),
13852 						tr("Found constraint students set min hours daily with tag allow empty days"
13853 						" which is not 'true', 'false', 'yes', 'no', '1' or '0'."
13854 						" The tag will be considered false",
13855 						"Instructions for translators: please leave the 'true', 'false', 'yes' and 'no' fields untranslated, as they are in English"));
13856 				}
13857 				//assert(text=="false" || text=="0" || text=="no");
13858 				xmlReadingLog+="    Read allow empty days=false\n";
13859 				cn->allowEmptyDays=false;
13860 			}
13861 		}
13862 		else{
13863 			unrecognizedXmlTags.append(xmlReader.name().toString());
13864 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
13865 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
13866 
13867 			xmlReader.skipCurrentElement();
13868 			xmlReaderNumberOfUnrecognizedFields++;
13869 		}
13870 	}
13871 	if(cn->minHoursDaily<0){
13872 		xmlReader.raiseError(tr("%1 not found").arg("Minimum_Hours_Daily"));
13873 		delete cn;
13874 		cn=nullptr;
13875 		return nullptr;
13876 	}
13877 	assert(cn->minHoursDaily>=0);
13878 	return cn;
13879 }
13880 
readStudentsSetMinGapsBetweenOrderedPairOfActivityTags(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)13881 TimeConstraint* Rules::readStudentsSetMinGapsBetweenOrderedPairOfActivityTags(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
13882 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMinGapsBetweenOrderedPairOfActivityTags"));
13883 	ConstraintStudentsSetMinGapsBetweenOrderedPairOfActivityTags* cn=new ConstraintStudentsSetMinGapsBetweenOrderedPairOfActivityTags();
13884 	cn->minGaps=-1;
13885 	while(xmlReader.readNextStartElement()){
13886 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
13887 		if(xmlReader.name()==QString("Weight_Percentage")){
13888 			QString text=xmlReader.readElementText();
13889 			cn->weightPercentage=customFETStrToDouble(text);
13890 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
13891 		}
13892 		else if(xmlReader.name()==QString("Active")){
13893 			QString text=xmlReader.readElementText();
13894 			if(text=="false"){
13895 				cn->active=false;
13896 			}
13897 		}
13898 		else if(xmlReader.name()==QString("Comments")){
13899 			QString text=xmlReader.readElementText();
13900 			cn->comments=text;
13901 		}
13902 		else if(xmlReader.name()==QString("MinGaps")){
13903 			QString text=xmlReader.readElementText();
13904 			cn->minGaps=text.toInt();
13905 			if(cn->minGaps<0){
13906 				xmlReader.raiseError(tr("%1 is incorrect").arg("MinGaps"));
13907 				delete cn;
13908 				cn=nullptr;
13909 				return nullptr;
13910 			}
13911 			xmlReadingLog+="    Read minGaps="+CustomFETString::number(cn->minGaps)+"\n";
13912 		}
13913 		else if(xmlReader.name()==QString("Students")){
13914 			QString text=xmlReader.readElementText();
13915 			cn->students=text;
13916 			xmlReadingLog+="    Read students name="+cn->students+"\n";
13917 		}
13918 		else if(xmlReader.name()==QString("First_Activity_Tag")){
13919 			QString text=xmlReader.readElementText();
13920 			cn->firstActivityTag=text;
13921 			xmlReadingLog+="    Read first activity name="+cn->firstActivityTag+"\n";
13922 		}
13923 		else if(xmlReader.name()==QString("Second_Activity_Tag")){
13924 			QString text=xmlReader.readElementText();
13925 			cn->secondActivityTag=text;
13926 			xmlReadingLog+="    Read second activity name="+cn->secondActivityTag+"\n";
13927 		}
13928 		else{
13929 			unrecognizedXmlTags.append(xmlReader.name().toString());
13930 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
13931 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
13932 
13933 			xmlReader.skipCurrentElement();
13934 			xmlReaderNumberOfUnrecognizedFields++;
13935 		}
13936 	}
13937 	if(cn->minGaps<0){
13938 		xmlReader.raiseError(tr("%1 not found").arg("MinGaps"));
13939 		delete cn;
13940 		cn=nullptr;
13941 		return nullptr;
13942 	}
13943 	assert(cn->minGaps>=0);
13944 	return cn;
13945 }
13946 
readStudentsMinGapsBetweenOrderedPairOfActivityTags(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)13947 TimeConstraint* Rules::readStudentsMinGapsBetweenOrderedPairOfActivityTags(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
13948 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMinGapsBetweenOrderedPairOfActivityTags"));
13949 	ConstraintStudentsMinGapsBetweenOrderedPairOfActivityTags* cn=new ConstraintStudentsMinGapsBetweenOrderedPairOfActivityTags();
13950 	cn->minGaps=-1;
13951 	while(xmlReader.readNextStartElement()){
13952 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
13953 		if(xmlReader.name()==QString("Weight_Percentage")){
13954 			QString text=xmlReader.readElementText();
13955 			cn->weightPercentage=customFETStrToDouble(text);
13956 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
13957 		}
13958 		else if(xmlReader.name()==QString("Active")){
13959 			QString text=xmlReader.readElementText();
13960 			if(text=="false"){
13961 				cn->active=false;
13962 			}
13963 		}
13964 		else if(xmlReader.name()==QString("Comments")){
13965 			QString text=xmlReader.readElementText();
13966 			cn->comments=text;
13967 		}
13968 		else if(xmlReader.name()==QString("MinGaps")){
13969 			QString text=xmlReader.readElementText();
13970 			cn->minGaps=text.toInt();
13971 			if(cn->minGaps<0){
13972 				xmlReader.raiseError(tr("%1 is incorrect").arg("MinGaps"));
13973 				delete cn;
13974 				cn=nullptr;
13975 				return nullptr;
13976 			}
13977 			xmlReadingLog+="    Read minGaps="+CustomFETString::number(cn->minGaps)+"\n";
13978 		}
13979 		else if(xmlReader.name()==QString("First_Activity_Tag")){
13980 			QString text=xmlReader.readElementText();
13981 			cn->firstActivityTag=text;
13982 			xmlReadingLog+="    Read first activity name="+cn->firstActivityTag+"\n";
13983 		}
13984 		else if(xmlReader.name()==QString("Second_Activity_Tag")){
13985 			QString text=xmlReader.readElementText();
13986 			cn->secondActivityTag=text;
13987 			xmlReadingLog+="    Read second activity name="+cn->secondActivityTag+"\n";
13988 		}
13989 		else{
13990 			unrecognizedXmlTags.append(xmlReader.name().toString());
13991 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
13992 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
13993 
13994 			xmlReader.skipCurrentElement();
13995 			xmlReaderNumberOfUnrecognizedFields++;
13996 		}
13997 	}
13998 	if(cn->minGaps<0){
13999 		xmlReader.raiseError(tr("%1 not found").arg("MinGaps"));
14000 		delete cn;
14001 		cn=nullptr;
14002 		return nullptr;
14003 	}
14004 	assert(cn->minGaps>=0);
14005 	return cn;
14006 }
14007 
readTeacherMinGapsBetweenOrderedPairOfActivityTags(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)14008 TimeConstraint* Rules::readTeacherMinGapsBetweenOrderedPairOfActivityTags(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
14009 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMinGapsBetweenOrderedPairOfActivityTags"));
14010 	ConstraintTeacherMinGapsBetweenOrderedPairOfActivityTags* cn=new ConstraintTeacherMinGapsBetweenOrderedPairOfActivityTags();
14011 	cn->minGaps=-1;
14012 	while(xmlReader.readNextStartElement()){
14013 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
14014 		if(xmlReader.name()==QString("Weight_Percentage")){
14015 			QString text=xmlReader.readElementText();
14016 			cn->weightPercentage=customFETStrToDouble(text);
14017 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
14018 		}
14019 		else if(xmlReader.name()==QString("Active")){
14020 			QString text=xmlReader.readElementText();
14021 			if(text=="false"){
14022 				cn->active=false;
14023 			}
14024 		}
14025 		else if(xmlReader.name()==QString("Comments")){
14026 			QString text=xmlReader.readElementText();
14027 			cn->comments=text;
14028 		}
14029 		else if(xmlReader.name()==QString("MinGaps")){
14030 			QString text=xmlReader.readElementText();
14031 			cn->minGaps=text.toInt();
14032 			if(cn->minGaps<0){
14033 				xmlReader.raiseError(tr("%1 is incorrect").arg("MinGaps"));
14034 				delete cn;
14035 				cn=nullptr;
14036 				return nullptr;
14037 			}
14038 			xmlReadingLog+="    Read minGaps="+CustomFETString::number(cn->minGaps)+"\n";
14039 		}
14040 		else if(xmlReader.name()==QString("Teacher")){
14041 			QString text=xmlReader.readElementText();
14042 			cn->teacher=text;
14043 			xmlReadingLog+="    Read teacher name="+cn->teacher+"\n";
14044 		}
14045 		else if(xmlReader.name()==QString("First_Activity_Tag")){
14046 			QString text=xmlReader.readElementText();
14047 			cn->firstActivityTag=text;
14048 			xmlReadingLog+="    Read first activity name="+cn->firstActivityTag+"\n";
14049 		}
14050 		else if(xmlReader.name()==QString("Second_Activity_Tag")){
14051 			QString text=xmlReader.readElementText();
14052 			cn->secondActivityTag=text;
14053 			xmlReadingLog+="    Read second activity name="+cn->secondActivityTag+"\n";
14054 		}
14055 		else{
14056 			unrecognizedXmlTags.append(xmlReader.name().toString());
14057 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
14058 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
14059 
14060 			xmlReader.skipCurrentElement();
14061 			xmlReaderNumberOfUnrecognizedFields++;
14062 		}
14063 	}
14064 	if(cn->minGaps<0){
14065 		xmlReader.raiseError(tr("%1 not found").arg("MinGaps"));
14066 		delete cn;
14067 		cn=nullptr;
14068 		return nullptr;
14069 	}
14070 	assert(cn->minGaps>=0);
14071 	return cn;
14072 }
14073 
readTeachersMinGapsBetweenOrderedPairOfActivityTags(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)14074 TimeConstraint* Rules::readTeachersMinGapsBetweenOrderedPairOfActivityTags(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
14075 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMinGapsBetweenOrderedPairOfActivityTags"));
14076 	ConstraintTeachersMinGapsBetweenOrderedPairOfActivityTags* cn=new ConstraintTeachersMinGapsBetweenOrderedPairOfActivityTags();
14077 	cn->minGaps=-1;
14078 	while(xmlReader.readNextStartElement()){
14079 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
14080 		if(xmlReader.name()==QString("Weight_Percentage")){
14081 			QString text=xmlReader.readElementText();
14082 			cn->weightPercentage=customFETStrToDouble(text);
14083 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
14084 		}
14085 		else if(xmlReader.name()==QString("Active")){
14086 			QString text=xmlReader.readElementText();
14087 			if(text=="false"){
14088 				cn->active=false;
14089 			}
14090 		}
14091 		else if(xmlReader.name()==QString("Comments")){
14092 			QString text=xmlReader.readElementText();
14093 			cn->comments=text;
14094 		}
14095 		else if(xmlReader.name()==QString("MinGaps")){
14096 			QString text=xmlReader.readElementText();
14097 			cn->minGaps=text.toInt();
14098 			if(cn->minGaps<0){
14099 				xmlReader.raiseError(tr("%1 is incorrect").arg("MinGaps"));
14100 				delete cn;
14101 				cn=nullptr;
14102 				return nullptr;
14103 			}
14104 			xmlReadingLog+="    Read minGaps="+CustomFETString::number(cn->minGaps)+"\n";
14105 		}
14106 		else if(xmlReader.name()==QString("First_Activity_Tag")){
14107 			QString text=xmlReader.readElementText();
14108 			cn->firstActivityTag=text;
14109 			xmlReadingLog+="    Read first activity name="+cn->firstActivityTag+"\n";
14110 		}
14111 		else if(xmlReader.name()==QString("Second_Activity_Tag")){
14112 			QString text=xmlReader.readElementText();
14113 			cn->secondActivityTag=text;
14114 			xmlReadingLog+="    Read second activity name="+cn->secondActivityTag+"\n";
14115 		}
14116 		else{
14117 			unrecognizedXmlTags.append(xmlReader.name().toString());
14118 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
14119 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
14120 
14121 			xmlReader.skipCurrentElement();
14122 			xmlReaderNumberOfUnrecognizedFields++;
14123 		}
14124 	}
14125 	if(cn->minGaps<0){
14126 		xmlReader.raiseError(tr("%1 not found").arg("MinGaps"));
14127 		delete cn;
14128 		cn=nullptr;
14129 		return nullptr;
14130 	}
14131 	assert(cn->minGaps>=0);
14132 	return cn;
14133 }
14134 
readActivityPreferredTime(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog,bool & reportUnspecifiedPermanentlyLockedTime,bool & reportUnspecifiedDayOrHourPreferredStartingTime)14135 TimeConstraint* Rules::readActivityPreferredTime(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog,
14136 bool& reportUnspecifiedPermanentlyLockedTime, bool& reportUnspecifiedDayOrHourPreferredStartingTime){
14137 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivityPreferredTime"));
14138 
14139 	ConstraintActivityPreferredStartingTime* cn=new ConstraintActivityPreferredStartingTime();
14140 	cn->day = cn->hour = -1;
14141 	cn->permanentlyLocked=false; //default not locked
14142 	bool foundLocked=false;
14143 	while(xmlReader.readNextStartElement()){
14144 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
14145 		if(xmlReader.name()==QString("Weight")){
14146 			//cn->weight=customFETStrToDouble(text);
14147 			xmlReader.skipCurrentElement();
14148 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
14149 			cn->weightPercentage=100;
14150 		}
14151 		else if(xmlReader.name()==QString("Weight_Percentage")){
14152 			QString text=xmlReader.readElementText();
14153 			cn->weightPercentage=customFETStrToDouble(text);
14154 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
14155 		}
14156 		else if(xmlReader.name()==QString("Active")){
14157 			QString text=xmlReader.readElementText();
14158 			if(text=="false"){
14159 				cn->active=false;
14160 			}
14161 		}
14162 		else if(xmlReader.name()==QString("Comments")){
14163 			QString text=xmlReader.readElementText();
14164 			cn->comments=text;
14165 		}
14166 		else if(xmlReader.name()==QString("Compulsory")){
14167 			QString text=xmlReader.readElementText();
14168 			if(text=="yes"){
14169 				//cn->compulsory=true;
14170 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
14171 				cn->weightPercentage=100;
14172 			}
14173 			else{
14174 				//cn->compulsory=false;
14175 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
14176 				cn->weightPercentage=0;
14177 			}
14178 		}
14179 		else if(xmlReader.name()==QString("Permanently_Locked")){
14180 			QString text=xmlReader.readElementText();
14181 			if(text=="true" || text=="1" || text=="yes"){
14182 				xmlReadingLog+="    Permanently locked\n";
14183 				cn->permanentlyLocked=true;
14184 			}
14185 			else{
14186 				if(!(text=="no" || text=="false" || text=="0")){
14187 					RulesReconcilableMessage::warning(parent, tr("FET warning"),
14188 						tr("Found constraint activity preferred starting time with tag permanently locked"
14189 						" which is not 'true', 'false', 'yes', 'no', '1' or '0'."
14190 						" The tag will be considered false",
14191 						"Instructions for translators: please leave the 'true', 'false', 'yes' and 'no' fields untranslated, as they are in English"));
14192 				}
14193 				//assert(text=="false" || text=="0" || text=="no");
14194 				xmlReadingLog+="    Not permanently locked\n";
14195 				cn->permanentlyLocked=false;
14196 			}
14197 			foundLocked=true;
14198 		}
14199 		else if(xmlReader.name()==QString("Activity_Id")){
14200 			QString text=xmlReader.readElementText();
14201 			cn->activityId=text.toInt();
14202 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activityId)+"\n";
14203 		}
14204 		else if(xmlReader.name()==QString("Preferred_Day")){
14205 			QString text=xmlReader.readElementText();
14206 			for(cn->day=0; cn->day<this->nDaysPerWeek; cn->day++)
14207 				if(this->daysOfTheWeek[cn->day]==text)
14208 					break;
14209 			if(cn->day>=this->nDaysPerWeek){
14210 				xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
14211 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
14212 					tr("Constraint ActivityPreferredTime day corrupt for activity with id %1, day %2 is inexistent ... ignoring constraint")
14213 					.arg(cn->activityId)
14214 					.arg(text));*/
14215 				delete cn;
14216 				cn=nullptr;
14217 				//goto corruptConstraintTime;
14218 				return nullptr;
14219 			}
14220 			assert(cn->day<this->nDaysPerWeek);
14221 			xmlReadingLog+="    Preferred day="+this->daysOfTheWeek[cn->day]+"\n";
14222 		}
14223 		else if(xmlReader.name()==QString("Preferred_Hour")){
14224 			QString text=xmlReader.readElementText();
14225 			for(cn->hour=0; cn->hour < this->nHoursPerDay; cn->hour++)
14226 				if(this->hoursOfTheDay[cn->hour]==text)
14227 					break;
14228 			if(cn->hour>=this->nHoursPerDay){
14229 				xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
14230 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
14231 					tr("Constraint ActivityPreferredTime hour corrupt for activity with id %1, hour %2 is inexistent ... ignoring constraint")
14232 					.arg(cn->activityId)
14233 					.arg(text));*/
14234 				delete cn;
14235 				cn=nullptr;
14236 				//goto corruptConstraintTime;
14237 				return nullptr;
14238 			}
14239 			assert(cn->hour>=0 && cn->hour < this->nHoursPerDay);
14240 			xmlReadingLog+="    Preferred hour="+this->hoursOfTheDay[cn->hour]+"\n";
14241 		}
14242 		else{
14243 			unrecognizedXmlTags.append(xmlReader.name().toString());
14244 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
14245 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
14246 
14247 			xmlReader.skipCurrentElement();
14248 			xmlReaderNumberOfUnrecognizedFields++;
14249 		}
14250 	}
14251 	//crt_constraint=cn;
14252 
14253 	if(cn->hour>=0 && cn->day>=0 && !foundLocked && reportUnspecifiedPermanentlyLockedTime){
14254 		int t=RulesReconcilableMessage::information(parent, tr("FET information"),
14255 			tr("Found constraint activity preferred starting time, with unspecified tag"
14256 			" 'permanently locked' - this tag will be set to 'false' by default. You can always modify it"
14257 			" by editing the constraint in the 'Data' menu")+"\n\n"
14258 			+tr("Explanation: starting with version 5.8.0 (January 2009), the constraint"
14259 			" activity preferred starting time has"
14260 			" a new tag, 'permanently locked' (true or false)."
14261 			" It is recommended to make the tag 'permanently locked' true for the constraints you"
14262 			" need to be not modifiable from the 'Timetable' menu"
14263 			" and leave this tag false for the constraints you need to be modifiable from the 'Timetable' menu"
14264 			" (the 'permanently locked' tag can be modified by editing the constraint from the 'Data' menu)."
14265 			" This way, when viewing the timetable"
14266 			" and locking/unlocking some activities, you will not unlock the constraints which"
14267 			" need to be locked all the time."
14268 			),
14269 			tr("Skip rest"), tr("See next"), QString(), 1, 0 );
14270 		if(t==0)
14271 			reportUnspecifiedPermanentlyLockedTime=false;
14272 	}
14273 
14274 	if(cn->hour==-1 || cn->day==-1){
14275 		if(reportUnspecifiedDayOrHourPreferredStartingTime){
14276 			int t=RulesReconcilableMessage::information(parent, tr("FET information"),
14277 				tr("Found constraint activity preferred starting time, with unspecified day or hour."
14278 				" This constraint will be transformed into constraint activity preferred starting times (a set of times, not only one)."
14279 				" This change is done in FET versions 5.8.1 and higher."
14280 				),
14281 				tr("Skip rest"), tr("See next"), QString(), 1, 0 );
14282 			if(t==0)
14283 				reportUnspecifiedDayOrHourPreferredStartingTime=false;
14284 		}
14285 
14286 		ConstraintActivityPreferredStartingTimes* cgood=new ConstraintActivityPreferredStartingTimes();
14287 		if(cn->day==-1){
14288 			cgood->activityId=cn->activityId;
14289 			cgood->weightPercentage=cn->weightPercentage;
14290 			cgood->nPreferredStartingTimes_L=this->nDaysPerWeek;
14291 			for(int i=0; i<cgood->nPreferredStartingTimes_L; i++){
14292 				/*cgood->days[i]=i;
14293 				cgood->hours[i]=cn->hour;*/
14294 				cgood->days_L.append(i);
14295 				cgood->hours_L.append(cn->hour);
14296 			}
14297 		}
14298 		else{
14299 			assert(cn->hour==-1);
14300 			cgood->activityId=cn->activityId;
14301 			cgood->weightPercentage=cn->weightPercentage;
14302 			cgood->nPreferredStartingTimes_L=this->nHoursPerDay;
14303 			for(int i=0; i<cgood->nPreferredStartingTimes_L; i++){
14304 				/*cgood->days[i]=cn->day;
14305 				cgood->hours[i]=i;*/
14306 				cgood->days_L.append(cn->day);
14307 				cgood->hours_L.append(i);
14308 			}
14309 		}
14310 
14311 		delete cn;
14312 		return cgood;
14313 	}
14314 
14315 	return cn;
14316 }
14317 
readActivityPreferredStartingTime(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog,bool & reportUnspecifiedPermanentlyLockedTime,bool & reportUnspecifiedDayOrHourPreferredStartingTime)14318 TimeConstraint* Rules::readActivityPreferredStartingTime(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog,
14319 bool& reportUnspecifiedPermanentlyLockedTime, bool& reportUnspecifiedDayOrHourPreferredStartingTime){
14320 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivityPreferredStartingTime"));
14321 	ConstraintActivityPreferredStartingTime* cn=new ConstraintActivityPreferredStartingTime();
14322 	cn->day = cn->hour = -1;
14323 	cn->permanentlyLocked=false; //default false
14324 	bool foundLocked=false;
14325 	while(xmlReader.readNextStartElement()){
14326 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
14327 		if(xmlReader.name()==QString("Weight")){
14328 			//cn->weight=customFETStrToDouble(text);
14329 			xmlReader.skipCurrentElement();
14330 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
14331 			cn->weightPercentage=100;
14332 		}
14333 		else if(xmlReader.name()==QString("Weight_Percentage")){
14334 			QString text=xmlReader.readElementText();
14335 			cn->weightPercentage=customFETStrToDouble(text);
14336 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
14337 		}
14338 		else if(xmlReader.name()==QString("Active")){
14339 			QString text=xmlReader.readElementText();
14340 			if(text=="false"){
14341 				cn->active=false;
14342 			}
14343 		}
14344 		else if(xmlReader.name()==QString("Comments")){
14345 			QString text=xmlReader.readElementText();
14346 			cn->comments=text;
14347 		}
14348 		else if(xmlReader.name()==QString("Compulsory")){
14349 			QString text=xmlReader.readElementText();
14350 			if(text=="yes"){
14351 				//cn->compulsory=true;
14352 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
14353 				cn->weightPercentage=100;
14354 			}
14355 			else{
14356 				//cn->compulsory=false;
14357 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
14358 				cn->weightPercentage=0;
14359 			}
14360 		}
14361 		else if(xmlReader.name()==QString("Permanently_Locked")){
14362 			QString text=xmlReader.readElementText();
14363 			if(text=="true" || text=="1" || text=="yes"){
14364 				xmlReadingLog+="    Permanently locked\n";
14365 				cn->permanentlyLocked=true;
14366 			}
14367 			else{
14368 				if(!(text=="no" || text=="false" || text=="0")){
14369 					RulesReconcilableMessage::warning(parent, tr("FET warning"),
14370 						tr("Found constraint activity preferred starting time with tag permanently locked"
14371 						" which is not 'true', 'false', 'yes', 'no', '1' or '0'."
14372 						" The tag will be considered false",
14373 						"Instructions for translators: please leave the 'true', 'false', 'yes' and 'no' fields untranslated, as they are in English"));
14374 				}
14375 				//assert(text=="false" || text=="0" || text=="no");
14376 				xmlReadingLog+="    Not permanently locked\n";
14377 				cn->permanentlyLocked=false;
14378 			}
14379 			foundLocked=true;
14380 		}
14381 		else if(xmlReader.name()==QString("Activity_Id")){
14382 			QString text=xmlReader.readElementText();
14383 			cn->activityId=text.toInt();
14384 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activityId)+"\n";
14385 		}
14386 		else if(xmlReader.name()==QString("Preferred_Day")){
14387 			QString text=xmlReader.readElementText();
14388 			for(cn->day=0; cn->day<this->nDaysPerWeek; cn->day++)
14389 				if(this->daysOfTheWeek[cn->day]==text)
14390 					break;
14391 			if(cn->day>=this->nDaysPerWeek){
14392 				xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
14393 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
14394 					tr("Constraint ActivityPreferredStartingTime day corrupt for activity with id %1, day %2 is inexistent ... ignoring constraint")
14395 					.arg(cn->activityId)
14396 					.arg(text));*/
14397 				delete cn;
14398 				cn=nullptr;
14399 				//goto corruptConstraintTime;
14400 				return nullptr;
14401 			}
14402 			assert(cn->day<this->nDaysPerWeek);
14403 			xmlReadingLog+="    Preferred day="+this->daysOfTheWeek[cn->day]+"\n";
14404 		}
14405 		else if(xmlReader.name()==QString("Preferred_Hour")){
14406 			QString text=xmlReader.readElementText();
14407 			for(cn->hour=0; cn->hour < this->nHoursPerDay; cn->hour++)
14408 				if(this->hoursOfTheDay[cn->hour]==text)
14409 					break;
14410 			if(cn->hour>=this->nHoursPerDay){
14411 				xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
14412 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
14413 					tr("Constraint ActivityPreferredStartingTime hour corrupt for activity with id %1, hour %2 is inexistent ... ignoring constraint")
14414 					.arg(cn->activityId)
14415 					.arg(text));*/
14416 				delete cn;
14417 				cn=nullptr;
14418 				//goto corruptConstraintTime;
14419 				return nullptr;
14420 			}
14421 			assert(cn->hour>=0 && cn->hour < this->nHoursPerDay);
14422 			xmlReadingLog+="    Preferred hour="+this->hoursOfTheDay[cn->hour]+"\n";
14423 		}
14424 		else{
14425 			unrecognizedXmlTags.append(xmlReader.name().toString());
14426 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
14427 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
14428 
14429 			xmlReader.skipCurrentElement();
14430 			xmlReaderNumberOfUnrecognizedFields++;
14431 		}
14432 	}
14433 	//crt_constraint=cn;
14434 
14435 	if(cn->hour>=0 && cn->day>=0 && !foundLocked && reportUnspecifiedPermanentlyLockedTime){
14436 		int t=RulesReconcilableMessage::information(parent, tr("FET information"),
14437 			tr("Found constraint activity preferred starting time, with unspecified tag"
14438 			" 'permanently locked' - this tag will be set to 'false' by default. You can always modify it"
14439 			" by editing the constraint in the 'Data' menu")+"\n\n"
14440 			+tr("Explanation: starting with version 5.8.0 (January 2009), the constraint"
14441 			" activity preferred starting time has"
14442 			" a new tag, 'permanently locked' (true or false)."
14443 			" It is recommended to make the tag 'permanently locked' true for the constraints you"
14444 			" need to be not modifiable from the 'Timetable' menu"
14445 			" and leave this tag false for the constraints you need to be modifiable from the 'Timetable' menu"
14446 			" (the 'permanently locked' tag can be modified by editing the constraint from the 'Data' menu)."
14447 			" This way, when viewing the timetable"
14448 			" and locking/unlocking some activities, you will not unlock the constraints which"
14449 			" need to be locked all the time."
14450 			),
14451 			tr("Skip rest"), tr("See next"), QString(), 1, 0 );
14452 		if(t==0)
14453 			reportUnspecifiedPermanentlyLockedTime=false;
14454 	}
14455 
14456 	if(cn->hour==-1 || cn->day==-1){
14457 		if(reportUnspecifiedDayOrHourPreferredStartingTime){
14458 			int t=RulesReconcilableMessage::information(parent, tr("FET information"),
14459 				tr("Found constraint activity preferred starting time, with unspecified day or hour."
14460 				" This constraint will be transformed into constraint activity preferred starting times (a set of times, not only one)."
14461 				" This change is done in FET versions 5.8.1 and higher."
14462 				),
14463 				tr("Skip rest"), tr("See next"), QString(), 1, 0 );
14464 			if(t==0)
14465 				reportUnspecifiedDayOrHourPreferredStartingTime=false;
14466 		}
14467 
14468 		ConstraintActivityPreferredStartingTimes* cgood=new ConstraintActivityPreferredStartingTimes();
14469 		if(cn->day==-1){
14470 			cgood->activityId=cn->activityId;
14471 			cgood->weightPercentage=cn->weightPercentage;
14472 			cgood->nPreferredStartingTimes_L=this->nDaysPerWeek;
14473 			for(int i=0; i<cgood->nPreferredStartingTimes_L; i++){
14474 				/*cgood->days[i]=i;
14475 				cgood->hours[i]=cn->hour;*/
14476 				cgood->days_L.append(i);
14477 				cgood->hours_L.append(cn->hour);
14478 			}
14479 		}
14480 		else{
14481 			assert(cn->hour==-1);
14482 			cgood->activityId=cn->activityId;
14483 			cgood->weightPercentage=cn->weightPercentage;
14484 			cgood->nPreferredStartingTimes_L=this->nHoursPerDay;
14485 			for(int i=0; i<cgood->nPreferredStartingTimes_L; i++){
14486 				/*cgood->days[i]=cn->day;
14487 				cgood->hours[i]=i;*/
14488 				cgood->days_L.append(cn->day);
14489 				cgood->hours_L.append(i);
14490 			}
14491 		}
14492 
14493 		delete cn;
14494 		return cgood;
14495 	}
14496 
14497 	return cn;
14498 }
14499 
readActivityEndsStudentsDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)14500 TimeConstraint* Rules::readActivityEndsStudentsDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
14501 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivityEndsStudentsDay"));
14502 	ConstraintActivityEndsStudentsDay* cn=new ConstraintActivityEndsStudentsDay();
14503 	while(xmlReader.readNextStartElement()){
14504 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
14505 		if(xmlReader.name()==QString("Weight_Percentage")){
14506 			QString text=xmlReader.readElementText();
14507 			cn->weightPercentage=customFETStrToDouble(text);
14508 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
14509 		}
14510 		else if(xmlReader.name()==QString("Active")){
14511 			QString text=xmlReader.readElementText();
14512 			if(text=="false"){
14513 				cn->active=false;
14514 			}
14515 		}
14516 		else if(xmlReader.name()==QString("Comments")){
14517 			QString text=xmlReader.readElementText();
14518 			cn->comments=text;
14519 		}
14520 		else if(xmlReader.name()==QString("Activity_Id")){
14521 			QString text=xmlReader.readElementText();
14522 			cn->activityId=text.toInt();
14523 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activityId)+"\n";
14524 		}
14525 		else{
14526 			unrecognizedXmlTags.append(xmlReader.name().toString());
14527 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
14528 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
14529 
14530 			xmlReader.skipCurrentElement();
14531 			xmlReaderNumberOfUnrecognizedFields++;
14532 		}
14533 	}
14534 	return cn;
14535 }
14536 
readActivitiesEndStudentsDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)14537 TimeConstraint* Rules::readActivitiesEndStudentsDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
14538 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivitiesEndStudentsDay"));
14539 	ConstraintActivitiesEndStudentsDay* cn=new ConstraintActivitiesEndStudentsDay();
14540 	cn->teacherName="";
14541 	cn->studentsName="";
14542 	cn->subjectName="";
14543 	cn->activityTagName="";
14544 
14545 	//i=0;
14546 	while(xmlReader.readNextStartElement()){
14547 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
14548 		if(xmlReader.name()==QString("Weight_Percentage")){
14549 			QString text=xmlReader.readElementText();
14550 			cn->weightPercentage=customFETStrToDouble(text);
14551 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
14552 		}
14553 		else if(xmlReader.name()==QString("Active")){
14554 			QString text=xmlReader.readElementText();
14555 			if(text=="false"){
14556 				cn->active=false;
14557 			}
14558 		}
14559 		else if(xmlReader.name()==QString("Comments")){
14560 			QString text=xmlReader.readElementText();
14561 			cn->comments=text;
14562 		}
14563 		else if(xmlReader.name()==QString("Teacher_Name")){
14564 			QString text=xmlReader.readElementText();
14565 			cn->teacherName=text;
14566 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
14567 		}
14568 		else if(xmlReader.name()==QString("Students_Name")){
14569 			QString text=xmlReader.readElementText();
14570 			cn->studentsName=text;
14571 			xmlReadingLog+="    Read students name="+cn->studentsName+"\n";
14572 		}
14573 		else if(xmlReader.name()==QString("Subject_Name")){
14574 			QString text=xmlReader.readElementText();
14575 			cn->subjectName=text;
14576 			xmlReadingLog+="    Read subject name="+cn->subjectName+"\n";
14577 		}
14578 		else if(xmlReader.name()==QString("Subject_Tag_Name")){
14579 			QString text=xmlReader.readElementText();
14580 			cn->activityTagName=text;
14581 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
14582 		}
14583 		else if(xmlReader.name()==QString("Activity_Tag_Name")){
14584 			QString text=xmlReader.readElementText();
14585 			cn->activityTagName=text;
14586 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
14587 		}
14588 		else{
14589 			unrecognizedXmlTags.append(xmlReader.name().toString());
14590 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
14591 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
14592 
14593 			xmlReader.skipCurrentElement();
14594 			xmlReaderNumberOfUnrecognizedFields++;
14595 		}
14596 	}
14597 	return cn;
14598 }
14599 
readActivityEndsTeachersDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)14600 TimeConstraint* Rules::readActivityEndsTeachersDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
14601 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivityEndsTeachersDay"));
14602 	ConstraintActivityEndsTeachersDay* cn=new ConstraintActivityEndsTeachersDay();
14603 	while(xmlReader.readNextStartElement()){
14604 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
14605 		if(xmlReader.name()==QString("Weight_Percentage")){
14606 			QString text=xmlReader.readElementText();
14607 			cn->weightPercentage=customFETStrToDouble(text);
14608 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
14609 		}
14610 		else if(xmlReader.name()==QString("Active")){
14611 			QString text=xmlReader.readElementText();
14612 			if(text=="false"){
14613 				cn->active=false;
14614 			}
14615 		}
14616 		else if(xmlReader.name()==QString("Comments")){
14617 			QString text=xmlReader.readElementText();
14618 			cn->comments=text;
14619 		}
14620 		else if(xmlReader.name()==QString("Activity_Id")){
14621 			QString text=xmlReader.readElementText();
14622 			cn->activityId=text.toInt();
14623 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activityId)+"\n";
14624 		}
14625 		else{
14626 			unrecognizedXmlTags.append(xmlReader.name().toString());
14627 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
14628 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
14629 
14630 			xmlReader.skipCurrentElement();
14631 			xmlReaderNumberOfUnrecognizedFields++;
14632 		}
14633 	}
14634 	return cn;
14635 }
14636 
readActivitiesEndTeachersDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)14637 TimeConstraint* Rules::readActivitiesEndTeachersDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
14638 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivitiesEndTeachersDay"));
14639 	ConstraintActivitiesEndTeachersDay* cn=new ConstraintActivitiesEndTeachersDay();
14640 	cn->teacherName="";
14641 	cn->studentsName="";
14642 	cn->subjectName="";
14643 	cn->activityTagName="";
14644 
14645 	//i=0;
14646 	while(xmlReader.readNextStartElement()){
14647 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
14648 		if(xmlReader.name()==QString("Weight_Percentage")){
14649 			QString text=xmlReader.readElementText();
14650 			cn->weightPercentage=customFETStrToDouble(text);
14651 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
14652 		}
14653 		else if(xmlReader.name()==QString("Active")){
14654 			QString text=xmlReader.readElementText();
14655 			if(text=="false"){
14656 				cn->active=false;
14657 			}
14658 		}
14659 		else if(xmlReader.name()==QString("Comments")){
14660 			QString text=xmlReader.readElementText();
14661 			cn->comments=text;
14662 		}
14663 		else if(xmlReader.name()==QString("Teacher_Name")){
14664 			QString text=xmlReader.readElementText();
14665 			cn->teacherName=text;
14666 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
14667 		}
14668 		else if(xmlReader.name()==QString("Students_Name")){
14669 			QString text=xmlReader.readElementText();
14670 			cn->studentsName=text;
14671 			xmlReadingLog+="    Read students name="+cn->studentsName+"\n";
14672 		}
14673 		else if(xmlReader.name()==QString("Subject_Name")){
14674 			QString text=xmlReader.readElementText();
14675 			cn->subjectName=text;
14676 			xmlReadingLog+="    Read subject name="+cn->subjectName+"\n";
14677 		}
14678 		else if(xmlReader.name()==QString("Subject_Tag_Name")){
14679 			QString text=xmlReader.readElementText();
14680 			cn->activityTagName=text;
14681 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
14682 		}
14683 		else if(xmlReader.name()==QString("Activity_Tag_Name")){
14684 			QString text=xmlReader.readElementText();
14685 			cn->activityTagName=text;
14686 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
14687 		}
14688 		else{
14689 			unrecognizedXmlTags.append(xmlReader.name().toString());
14690 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
14691 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
14692 
14693 			xmlReader.skipCurrentElement();
14694 			xmlReaderNumberOfUnrecognizedFields++;
14695 		}
14696 	}
14697 	return cn;
14698 }
14699 
read2ActivitiesConsecutive(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)14700 TimeConstraint* Rules::read2ActivitiesConsecutive(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
14701 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("Constraint2ActivitiesConsecutive"));
14702 	ConstraintTwoActivitiesConsecutive* cn=new ConstraintTwoActivitiesConsecutive();
14703 	while(xmlReader.readNextStartElement()){
14704 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
14705 		if(xmlReader.name()==QString("Weight")){
14706 			//cn->weight=customFETStrToDouble(text);
14707 			xmlReader.skipCurrentElement();
14708 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
14709 			cn->weightPercentage=100;
14710 		}
14711 		else if(xmlReader.name()==QString("Weight_Percentage")){
14712 			QString text=xmlReader.readElementText();
14713 			cn->weightPercentage=customFETStrToDouble(text);
14714 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
14715 		}
14716 		else if(xmlReader.name()==QString("Active")){
14717 			QString text=xmlReader.readElementText();
14718 			if(text=="false"){
14719 				cn->active=false;
14720 			}
14721 		}
14722 		else if(xmlReader.name()==QString("Comments")){
14723 			QString text=xmlReader.readElementText();
14724 			cn->comments=text;
14725 		}
14726 		else if(xmlReader.name()==QString("Compulsory")){
14727 			QString text=xmlReader.readElementText();
14728 			if(text=="yes"){
14729 				//cn->compulsory=true;
14730 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
14731 				cn->weightPercentage=100;
14732 			}
14733 			else{
14734 				//cn->compulsory=false;
14735 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
14736 				cn->weightPercentage=0;
14737 			}
14738 		}
14739 		else if(xmlReader.name()==QString("First_Activity_Id")){
14740 			QString text=xmlReader.readElementText();
14741 			cn->firstActivityId=text.toInt();
14742 			xmlReadingLog+="    Read first activity id="+CustomFETString::number(cn->firstActivityId)+"\n";
14743 		}
14744 		else if(xmlReader.name()==QString("Second_Activity_Id")){
14745 			QString text=xmlReader.readElementText();
14746 			cn->secondActivityId=text.toInt();
14747 			xmlReadingLog+="    Read second activity id="+CustomFETString::number(cn->secondActivityId)+"\n";
14748 		}
14749 		else{
14750 			unrecognizedXmlTags.append(xmlReader.name().toString());
14751 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
14752 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
14753 
14754 			xmlReader.skipCurrentElement();
14755 			xmlReaderNumberOfUnrecognizedFields++;
14756 		}
14757 	}
14758 	return cn;
14759 }
14760 
read2ActivitiesGrouped(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)14761 TimeConstraint* Rules::read2ActivitiesGrouped(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
14762 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("Constraint2ActivitiesGrouped"));
14763 	ConstraintTwoActivitiesGrouped* cn=new ConstraintTwoActivitiesGrouped();
14764 	while(xmlReader.readNextStartElement()){
14765 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
14766 		if(xmlReader.name()==QString("Weight")){
14767 			//cn->weight=customFETStrToDouble(text);
14768 			xmlReader.skipCurrentElement();
14769 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
14770 			cn->weightPercentage=100;
14771 		}
14772 		else if(xmlReader.name()==QString("Weight_Percentage")){
14773 			QString text=xmlReader.readElementText();
14774 			cn->weightPercentage=customFETStrToDouble(text);
14775 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
14776 		}
14777 		else if(xmlReader.name()==QString("Active")){
14778 			QString text=xmlReader.readElementText();
14779 			if(text=="false"){
14780 				cn->active=false;
14781 			}
14782 		}
14783 		else if(xmlReader.name()==QString("Comments")){
14784 			QString text=xmlReader.readElementText();
14785 			cn->comments=text;
14786 		}
14787 		else if(xmlReader.name()==QString("Compulsory")){
14788 			QString text=xmlReader.readElementText();
14789 			if(text=="yes"){
14790 				//cn->compulsory=true;
14791 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
14792 				cn->weightPercentage=100;
14793 			}
14794 			else{
14795 				//cn->compulsory=false;
14796 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
14797 				cn->weightPercentage=0;
14798 			}
14799 		}
14800 		else if(xmlReader.name()==QString("First_Activity_Id")){
14801 			QString text=xmlReader.readElementText();
14802 			cn->firstActivityId=text.toInt();
14803 			xmlReadingLog+="    Read first activity id="+CustomFETString::number(cn->firstActivityId)+"\n";
14804 		}
14805 		else if(xmlReader.name()==QString("Second_Activity_Id")){
14806 			QString text=xmlReader.readElementText();
14807 			cn->secondActivityId=text.toInt();
14808 			xmlReadingLog+="    Read second activity id="+CustomFETString::number(cn->secondActivityId)+"\n";
14809 		}
14810 		else{
14811 			unrecognizedXmlTags.append(xmlReader.name().toString());
14812 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
14813 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
14814 
14815 			xmlReader.skipCurrentElement();
14816 			xmlReaderNumberOfUnrecognizedFields++;
14817 		}
14818 	}
14819 	return cn;
14820 }
14821 
read3ActivitiesGrouped(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)14822 TimeConstraint* Rules::read3ActivitiesGrouped(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
14823 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("Constraint3ActivitiesGrouped"));
14824 	ConstraintThreeActivitiesGrouped* cn=new ConstraintThreeActivitiesGrouped();
14825 	while(xmlReader.readNextStartElement()){
14826 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
14827 		if(xmlReader.name()==QString("Weight_Percentage")){
14828 			QString text=xmlReader.readElementText();
14829 			cn->weightPercentage=customFETStrToDouble(text);
14830 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
14831 		}
14832 		else if(xmlReader.name()==QString("Active")){
14833 			QString text=xmlReader.readElementText();
14834 			if(text=="false"){
14835 				cn->active=false;
14836 			}
14837 		}
14838 		else if(xmlReader.name()==QString("Comments")){
14839 			QString text=xmlReader.readElementText();
14840 			cn->comments=text;
14841 		}
14842 		else if(xmlReader.name()==QString("First_Activity_Id")){
14843 			QString text=xmlReader.readElementText();
14844 			cn->firstActivityId=text.toInt();
14845 			xmlReadingLog+="    Read first activity id="+CustomFETString::number(cn->firstActivityId)+"\n";
14846 		}
14847 		else if(xmlReader.name()==QString("Second_Activity_Id")){
14848 			QString text=xmlReader.readElementText();
14849 			cn->secondActivityId=text.toInt();
14850 			xmlReadingLog+="    Read second activity id="+CustomFETString::number(cn->secondActivityId)+"\n";
14851 		}
14852 		else if(xmlReader.name()==QString("Third_Activity_Id")){
14853 			QString text=xmlReader.readElementText();
14854 			cn->thirdActivityId=text.toInt();
14855 			xmlReadingLog+="    Read third activity id="+CustomFETString::number(cn->thirdActivityId)+"\n";
14856 		}
14857 		else{
14858 			unrecognizedXmlTags.append(xmlReader.name().toString());
14859 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
14860 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
14861 
14862 			xmlReader.skipCurrentElement();
14863 			xmlReaderNumberOfUnrecognizedFields++;
14864 		}
14865 	}
14866 	return cn;
14867 }
14868 
read2ActivitiesOrdered(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)14869 TimeConstraint* Rules::read2ActivitiesOrdered(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
14870 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("Constraint2ActivitiesOrdered"));
14871 	ConstraintTwoActivitiesOrdered* cn=new ConstraintTwoActivitiesOrdered();
14872 	while(xmlReader.readNextStartElement()){
14873 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
14874 		if(xmlReader.name()==QString("Weight")){
14875 			//cn->weight=customFETStrToDouble(text);
14876 			xmlReader.skipCurrentElement();
14877 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
14878 			cn->weightPercentage=100;
14879 		}
14880 		else if(xmlReader.name()==QString("Weight_Percentage")){
14881 			QString text=xmlReader.readElementText();
14882 			cn->weightPercentage=customFETStrToDouble(text);
14883 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
14884 		}
14885 		else if(xmlReader.name()==QString("Active")){
14886 			QString text=xmlReader.readElementText();
14887 			if(text=="false"){
14888 				cn->active=false;
14889 			}
14890 		}
14891 		else if(xmlReader.name()==QString("Comments")){
14892 			QString text=xmlReader.readElementText();
14893 			cn->comments=text;
14894 		}
14895 		else if(xmlReader.name()==QString("Compulsory")){
14896 			QString text=xmlReader.readElementText();
14897 			if(text=="yes"){
14898 				//cn->compulsory=true;
14899 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
14900 				cn->weightPercentage=100;
14901 			}
14902 			else{
14903 				//cn->compulsory=false;
14904 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
14905 				cn->weightPercentage=0;
14906 			}
14907 		}
14908 		else if(xmlReader.name()==QString("First_Activity_Id")){
14909 			QString text=xmlReader.readElementText();
14910 			cn->firstActivityId=text.toInt();
14911 			xmlReadingLog+="    Read first activity id="+CustomFETString::number(cn->firstActivityId)+"\n";
14912 		}
14913 		else if(xmlReader.name()==QString("Second_Activity_Id")){
14914 			QString text=xmlReader.readElementText();
14915 			cn->secondActivityId=text.toInt();
14916 			xmlReadingLog+="    Read second activity id="+CustomFETString::number(cn->secondActivityId)+"\n";
14917 		}
14918 		else{
14919 			unrecognizedXmlTags.append(xmlReader.name().toString());
14920 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
14921 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
14922 
14923 			xmlReader.skipCurrentElement();
14924 			xmlReaderNumberOfUnrecognizedFields++;
14925 		}
14926 	}
14927 	return cn;
14928 }
14929 
readTwoActivitiesConsecutive(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)14930 TimeConstraint* Rules::readTwoActivitiesConsecutive(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
14931 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTwoActivitiesConsecutive"));
14932 	ConstraintTwoActivitiesConsecutive* cn=new ConstraintTwoActivitiesConsecutive();
14933 	while(xmlReader.readNextStartElement()){
14934 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
14935 		if(xmlReader.name()==QString("Weight")){
14936 			//cn->weight=customFETStrToDouble(text);
14937 			xmlReader.skipCurrentElement();
14938 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
14939 			cn->weightPercentage=100;
14940 		}
14941 		else if(xmlReader.name()==QString("Weight_Percentage")){
14942 			QString text=xmlReader.readElementText();
14943 			cn->weightPercentage=customFETStrToDouble(text);
14944 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
14945 		}
14946 		else if(xmlReader.name()==QString("Active")){
14947 			QString text=xmlReader.readElementText();
14948 			if(text=="false"){
14949 				cn->active=false;
14950 			}
14951 		}
14952 		else if(xmlReader.name()==QString("Comments")){
14953 			QString text=xmlReader.readElementText();
14954 			cn->comments=text;
14955 		}
14956 		else if(xmlReader.name()==QString("Compulsory")){
14957 			QString text=xmlReader.readElementText();
14958 			if(text=="yes"){
14959 				//cn->compulsory=true;
14960 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
14961 				cn->weightPercentage=100;
14962 			}
14963 			else{
14964 				//cn->compulsory=false;
14965 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
14966 				cn->weightPercentage=0;
14967 			}
14968 		}
14969 		else if(xmlReader.name()==QString("First_Activity_Id")){
14970 			QString text=xmlReader.readElementText();
14971 			cn->firstActivityId=text.toInt();
14972 			xmlReadingLog+="    Read first activity id="+CustomFETString::number(cn->firstActivityId)+"\n";
14973 		}
14974 		else if(xmlReader.name()==QString("Second_Activity_Id")){
14975 			QString text=xmlReader.readElementText();
14976 			cn->secondActivityId=text.toInt();
14977 			xmlReadingLog+="    Read second activity id="+CustomFETString::number(cn->secondActivityId)+"\n";
14978 		}
14979 		else{
14980 			unrecognizedXmlTags.append(xmlReader.name().toString());
14981 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
14982 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
14983 
14984 			xmlReader.skipCurrentElement();
14985 			xmlReaderNumberOfUnrecognizedFields++;
14986 		}
14987 	}
14988 	return cn;
14989 }
14990 
readTwoActivitiesGrouped(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)14991 TimeConstraint* Rules::readTwoActivitiesGrouped(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
14992 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTwoActivitiesGrouped"));
14993 	ConstraintTwoActivitiesGrouped* cn=new ConstraintTwoActivitiesGrouped();
14994 	while(xmlReader.readNextStartElement()){
14995 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
14996 		if(xmlReader.name()==QString("Weight")){
14997 			//cn->weight=customFETStrToDouble(text);
14998 			xmlReader.skipCurrentElement();
14999 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
15000 			cn->weightPercentage=100;
15001 		}
15002 		else if(xmlReader.name()==QString("Weight_Percentage")){
15003 			QString text=xmlReader.readElementText();
15004 			cn->weightPercentage=customFETStrToDouble(text);
15005 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
15006 		}
15007 		else if(xmlReader.name()==QString("Active")){
15008 			QString text=xmlReader.readElementText();
15009 			if(text=="false"){
15010 				cn->active=false;
15011 			}
15012 		}
15013 		else if(xmlReader.name()==QString("Comments")){
15014 			QString text=xmlReader.readElementText();
15015 			cn->comments=text;
15016 		}
15017 		else if(xmlReader.name()==QString("Compulsory")){
15018 			QString text=xmlReader.readElementText();
15019 			if(text=="yes"){
15020 				//cn->compulsory=true;
15021 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
15022 				cn->weightPercentage=100;
15023 			}
15024 			else{
15025 				//cn->compulsory=false;
15026 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
15027 				cn->weightPercentage=0;
15028 			}
15029 		}
15030 		else if(xmlReader.name()==QString("First_Activity_Id")){
15031 			QString text=xmlReader.readElementText();
15032 			cn->firstActivityId=text.toInt();
15033 			xmlReadingLog+="    Read first activity id="+CustomFETString::number(cn->firstActivityId)+"\n";
15034 		}
15035 		else if(xmlReader.name()==QString("Second_Activity_Id")){
15036 			QString text=xmlReader.readElementText();
15037 			cn->secondActivityId=text.toInt();
15038 			xmlReadingLog+="    Read second activity id="+CustomFETString::number(cn->secondActivityId)+"\n";
15039 		}
15040 		else{
15041 			unrecognizedXmlTags.append(xmlReader.name().toString());
15042 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
15043 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
15044 
15045 			xmlReader.skipCurrentElement();
15046 			xmlReaderNumberOfUnrecognizedFields++;
15047 		}
15048 	}
15049 	return cn;
15050 }
15051 
readThreeActivitiesGrouped(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)15052 TimeConstraint* Rules::readThreeActivitiesGrouped(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
15053 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintThreeActivitiesGrouped"));
15054 	ConstraintThreeActivitiesGrouped* cn=new ConstraintThreeActivitiesGrouped();
15055 	while(xmlReader.readNextStartElement()){
15056 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
15057 		if(xmlReader.name()==QString("Weight_Percentage")){
15058 			QString text=xmlReader.readElementText();
15059 			cn->weightPercentage=customFETStrToDouble(text);
15060 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
15061 		}
15062 		else if(xmlReader.name()==QString("Active")){
15063 			QString text=xmlReader.readElementText();
15064 			if(text=="false"){
15065 				cn->active=false;
15066 			}
15067 		}
15068 		else if(xmlReader.name()==QString("Comments")){
15069 			QString text=xmlReader.readElementText();
15070 			cn->comments=text;
15071 		}
15072 		else if(xmlReader.name()==QString("First_Activity_Id")){
15073 			QString text=xmlReader.readElementText();
15074 			cn->firstActivityId=text.toInt();
15075 			xmlReadingLog+="    Read first activity id="+CustomFETString::number(cn->firstActivityId)+"\n";
15076 		}
15077 		else if(xmlReader.name()==QString("Second_Activity_Id")){
15078 			QString text=xmlReader.readElementText();
15079 			cn->secondActivityId=text.toInt();
15080 			xmlReadingLog+="    Read second activity id="+CustomFETString::number(cn->secondActivityId)+"\n";
15081 		}
15082 		else if(xmlReader.name()==QString("Third_Activity_Id")){
15083 			QString text=xmlReader.readElementText();
15084 			cn->thirdActivityId=text.toInt();
15085 			xmlReadingLog+="    Read third activity id="+CustomFETString::number(cn->thirdActivityId)+"\n";
15086 		}
15087 		else{
15088 			unrecognizedXmlTags.append(xmlReader.name().toString());
15089 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
15090 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
15091 
15092 			xmlReader.skipCurrentElement();
15093 			xmlReaderNumberOfUnrecognizedFields++;
15094 		}
15095 	}
15096 	return cn;
15097 }
15098 
readTwoActivitiesOrdered(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)15099 TimeConstraint* Rules::readTwoActivitiesOrdered(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
15100 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTwoActivitiesOrdered"));
15101 	ConstraintTwoActivitiesOrdered* cn=new ConstraintTwoActivitiesOrdered();
15102 	while(xmlReader.readNextStartElement()){
15103 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
15104 		if(xmlReader.name()==QString("Weight")){
15105 			//cn->weight=customFETStrToDouble(text);
15106 			xmlReader.skipCurrentElement();
15107 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
15108 			cn->weightPercentage=100;
15109 		}
15110 		else if(xmlReader.name()==QString("Weight_Percentage")){
15111 			QString text=xmlReader.readElementText();
15112 			cn->weightPercentage=customFETStrToDouble(text);
15113 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
15114 		}
15115 		else if(xmlReader.name()==QString("Active")){
15116 			QString text=xmlReader.readElementText();
15117 			if(text=="false"){
15118 				cn->active=false;
15119 			}
15120 		}
15121 		else if(xmlReader.name()==QString("Comments")){
15122 			QString text=xmlReader.readElementText();
15123 			cn->comments=text;
15124 		}
15125 		else if(xmlReader.name()==QString("Compulsory")){
15126 			QString text=xmlReader.readElementText();
15127 			if(text=="yes"){
15128 				//cn->compulsory=true;
15129 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
15130 				cn->weightPercentage=100;
15131 			}
15132 			else{
15133 				//cn->compulsory=false;
15134 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
15135 				cn->weightPercentage=0;
15136 			}
15137 		}
15138 		else if(xmlReader.name()==QString("First_Activity_Id")){
15139 			QString text=xmlReader.readElementText();
15140 			cn->firstActivityId=text.toInt();
15141 			xmlReadingLog+="    Read first activity id="+CustomFETString::number(cn->firstActivityId)+"\n";
15142 		}
15143 		else if(xmlReader.name()==QString("Second_Activity_Id")){
15144 			QString text=xmlReader.readElementText();
15145 			cn->secondActivityId=text.toInt();
15146 			xmlReadingLog+="    Read second activity id="+CustomFETString::number(cn->secondActivityId)+"\n";
15147 		}
15148 		else{
15149 			unrecognizedXmlTags.append(xmlReader.name().toString());
15150 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
15151 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
15152 
15153 			xmlReader.skipCurrentElement();
15154 			xmlReaderNumberOfUnrecognizedFields++;
15155 		}
15156 	}
15157 	return cn;
15158 }
15159 
readTwoSetsOfActivitiesOrdered(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)15160 TimeConstraint* Rules::readTwoSetsOfActivitiesOrdered(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
15161 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTwoSetsOfActivitiesOrdered"));
15162 	ConstraintTwoSetsOfActivitiesOrdered* cn=new ConstraintTwoSetsOfActivitiesOrdered();
15163 	int rnfa=-1, rnsa=-1; //read number of first/second activities
15164 	while(xmlReader.readNextStartElement()){
15165 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
15166 		if(xmlReader.name()==QString("Weight_Percentage")){
15167 			QString text=xmlReader.readElementText();
15168 			cn->weightPercentage=customFETStrToDouble(text);
15169 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
15170 		}
15171 		else if(xmlReader.name()==QString("Active")){
15172 			QString text=xmlReader.readElementText();
15173 			if(text=="false"){
15174 				cn->active=false;
15175 			}
15176 		}
15177 		else if(xmlReader.name()==QString("Comments")){
15178 			QString text=xmlReader.readElementText();
15179 			cn->comments=text;
15180 		}
15181 		else if(xmlReader.name()==QString("First_Activities_Ids_Set")){
15182 			xmlReadingLog+="    Reading first activities ids set\n";
15183 			assert(xmlReader.isStartElement());
15184 			while(xmlReader.readNextStartElement()){
15185 				xmlReadingLog+="     Found "+xmlReader.name().toString()+" tag\n";
15186 				if(xmlReader.name()==QString("Number_of_Activities")){
15187 					QString text=xmlReader.readElementText();
15188 					rnfa=text.toInt();
15189 					xmlReadingLog+="     Read number of activities="+CustomFETString::number(rnfa)+"\n";
15190 				}
15191 				else if(xmlReader.name()==QString("Activity_Id")){
15192 					QString text=xmlReader.readElementText();
15193 					cn->firstActivitiesIdsList.append(text.toInt());
15194 					xmlReadingLog+="     Read activity id="+CustomFETString::number(cn->firstActivitiesIdsList.last())+"\n";
15195 				}
15196 				else{
15197 					unrecognizedXmlTags.append(xmlReader.name().toString());
15198 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
15199 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
15200 
15201 					xmlReader.skipCurrentElement();
15202 					xmlReaderNumberOfUnrecognizedFields++;
15203 				}
15204 			}
15205 			if(rnfa==-1){
15206 				xmlReader.raiseError(tr("Field %1 not met").arg("Number_of_Activities"));
15207 				delete cn;
15208 				cn=nullptr;
15209 				return nullptr;
15210 			}
15211 			else if(rnfa!=cn->firstActivitiesIdsList.count()){
15212 				xmlReader.raiseError(tr("The value in field %1 is not equal with the number of read %2 fields").arg("Number_of_Activities").arg("Activity_Id"));
15213 				delete cn;
15214 				cn=nullptr;
15215 				return nullptr;
15216 			}
15217 		}
15218 		else if(xmlReader.name()==QString("Second_Activities_Ids_Set")){
15219 			xmlReadingLog+="    Reading second activities ids set\n";
15220 			assert(xmlReader.isStartElement());
15221 			while(xmlReader.readNextStartElement()){
15222 				xmlReadingLog+="     Found "+xmlReader.name().toString()+" tag\n";
15223 				if(xmlReader.name()==QString("Number_of_Activities")){
15224 					QString text=xmlReader.readElementText();
15225 					rnsa=text.toInt();
15226 					xmlReadingLog+="     Read number of activities="+CustomFETString::number(rnsa)+"\n";
15227 				}
15228 				else if(xmlReader.name()==QString("Activity_Id")){
15229 					QString text=xmlReader.readElementText();
15230 					cn->secondActivitiesIdsList.append(text.toInt());
15231 					xmlReadingLog+="     Read activity id="+CustomFETString::number(cn->secondActivitiesIdsList.last())+"\n";
15232 				}
15233 				else{
15234 					unrecognizedXmlTags.append(xmlReader.name().toString());
15235 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
15236 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
15237 
15238 					xmlReader.skipCurrentElement();
15239 					xmlReaderNumberOfUnrecognizedFields++;
15240 				}
15241 			}
15242 			if(rnsa==-1){
15243 				xmlReader.raiseError(tr("Field %1 not met").arg("Number_of_Activities"));
15244 				delete cn;
15245 				cn=nullptr;
15246 				return nullptr;
15247 			}
15248 			else if(rnsa!=cn->secondActivitiesIdsList.count()){
15249 				xmlReader.raiseError(tr("The value in field %1 is not equal with the number of read %2 fields").arg("Number_of_Activities").arg("Activity_Id"));
15250 				delete cn;
15251 				cn=nullptr;
15252 				return nullptr;
15253 			}
15254 		}
15255 		else{
15256 			unrecognizedXmlTags.append(xmlReader.name().toString());
15257 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
15258 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
15259 
15260 			xmlReader.skipCurrentElement();
15261 			xmlReaderNumberOfUnrecognizedFields++;
15262 		}
15263 	}
15264 	return cn;
15265 }
15266 
readTwoActivitiesOrderedIfSameDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)15267 TimeConstraint* Rules::readTwoActivitiesOrderedIfSameDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
15268 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTwoActivitiesOrderedIfSameDay"));
15269 	ConstraintTwoActivitiesOrderedIfSameDay* cn=new ConstraintTwoActivitiesOrderedIfSameDay();
15270 	while(xmlReader.readNextStartElement()){
15271 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
15272 		if(xmlReader.name()==QString("Weight")){
15273 			//cn->weight=customFETStrToDouble(text);
15274 			xmlReader.skipCurrentElement();
15275 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
15276 			cn->weightPercentage=100;
15277 		}
15278 		else if(xmlReader.name()==QString("Weight_Percentage")){
15279 			QString text=xmlReader.readElementText();
15280 			cn->weightPercentage=customFETStrToDouble(text);
15281 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
15282 		}
15283 		else if(xmlReader.name()==QString("Active")){
15284 			QString text=xmlReader.readElementText();
15285 			if(text=="false"){
15286 				cn->active=false;
15287 			}
15288 		}
15289 		else if(xmlReader.name()==QString("Comments")){
15290 			QString text=xmlReader.readElementText();
15291 			cn->comments=text;
15292 		}
15293 		else if(xmlReader.name()==QString("Compulsory")){
15294 			QString text=xmlReader.readElementText();
15295 			if(text=="yes"){
15296 				//cn->compulsory=true;
15297 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
15298 				cn->weightPercentage=100;
15299 			}
15300 			else{
15301 				//cn->compulsory=false;
15302 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
15303 				cn->weightPercentage=0;
15304 			}
15305 		}
15306 		else if(xmlReader.name()==QString("First_Activity_Id")){
15307 			QString text=xmlReader.readElementText();
15308 			cn->firstActivityId=text.toInt();
15309 			xmlReadingLog+="    Read first activity id="+CustomFETString::number(cn->firstActivityId)+"\n";
15310 		}
15311 		else if(xmlReader.name()==QString("Second_Activity_Id")){
15312 			QString text=xmlReader.readElementText();
15313 			cn->secondActivityId=text.toInt();
15314 			xmlReadingLog+="    Read second activity id="+CustomFETString::number(cn->secondActivityId)+"\n";
15315 		}
15316 		else{
15317 			unrecognizedXmlTags.append(xmlReader.name().toString());
15318 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
15319 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
15320 
15321 			xmlReader.skipCurrentElement();
15322 			xmlReaderNumberOfUnrecognizedFields++;
15323 		}
15324 	}
15325 	return cn;
15326 }
15327 
readActivityPreferredTimes(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)15328 TimeConstraint* Rules::readActivityPreferredTimes(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
15329 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivityPreferredTimes"));
15330 
15331 	ConstraintActivityPreferredStartingTimes* cn=new ConstraintActivityPreferredStartingTimes();
15332 	cn->nPreferredStartingTimes_L=0;
15333 	int i;
15334 	/*for(i=0; i<MAX_N_CONSTRAINT_ACTIVITY_PREFERRED_STARTING_TIMES; i++){
15335 		cn->days[i] = cn->hours[i] = -1;
15336 	}*/
15337 	i=0;
15338 	while(xmlReader.readNextStartElement()){
15339 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
15340 		if(xmlReader.name()==QString("Weight")){
15341 			//cn->weight=customFETStrToDouble(text);
15342 			xmlReader.skipCurrentElement();
15343 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
15344 			cn->weightPercentage=100;
15345 		}
15346 		else if(xmlReader.name()==QString("Weight_Percentage")){
15347 			QString text=xmlReader.readElementText();
15348 			cn->weightPercentage=customFETStrToDouble(text);
15349 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
15350 		}
15351 		else if(xmlReader.name()==QString("Active")){
15352 			QString text=xmlReader.readElementText();
15353 			if(text=="false"){
15354 				cn->active=false;
15355 			}
15356 		}
15357 		else if(xmlReader.name()==QString("Comments")){
15358 			QString text=xmlReader.readElementText();
15359 			cn->comments=text;
15360 		}
15361 		else if(xmlReader.name()==QString("Compulsory")){
15362 			QString text=xmlReader.readElementText();
15363 			if(text=="yes"){
15364 				//cn->compulsory=true;
15365 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
15366 				cn->weightPercentage=100;
15367 			}
15368 			else{
15369 				//cn->compulsory=false;
15370 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
15371 				cn->weightPercentage=0;
15372 			}
15373 		}
15374 		else if(xmlReader.name()==QString("Activity_Id")){
15375 			QString text=xmlReader.readElementText();
15376 			cn->activityId=text.toInt();
15377 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activityId)+"\n";
15378 		}
15379 		else if(xmlReader.name()==QString("Number_of_Preferred_Times")){
15380 			QString text=xmlReader.readElementText();
15381 			cn->nPreferredStartingTimes_L=text.toInt();
15382 			xmlReadingLog+="    Read number of preferred times="+CustomFETString::number(cn->nPreferredStartingTimes_L)+"\n";
15383 		}
15384 		else if(xmlReader.name()==QString("Preferred_Time")){
15385 			xmlReadingLog+="    Read: preferred time\n";
15386 
15387 			assert(xmlReader.isStartElement());
15388 			while(xmlReader.readNextStartElement()){
15389 				xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
15390 				if(xmlReader.name()==QString("Preferred_Day")){
15391 					QString text=xmlReader.readElementText();
15392 					cn->days_L.append(0);
15393 					assert(cn->days_L.count()-1==i);
15394 					for(cn->days_L[i]=0; cn->days_L[i]<this->nDaysPerWeek; cn->days_L[i]++)
15395 						if(this->daysOfTheWeek[cn->days_L[i]]==text)
15396 							break;
15397 
15398 					if(cn->days_L[i]>=this->nDaysPerWeek){
15399 						xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
15400 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
15401 							tr("Constraint ActivityPreferredTimes day corrupt for activity with id %1, day %2 is inexistent ... ignoring constraint")
15402 							.arg(cn->activityId)
15403 							.arg(text));*/
15404 						delete cn;
15405 						cn=nullptr;
15406 						//goto corruptConstraintTime;
15407 						return nullptr;
15408 					}
15409 
15410 					assert(cn->days_L[i]<this->nDaysPerWeek);
15411 					xmlReadingLog+="    Preferred day="+this->daysOfTheWeek[cn->days_L[i]]+"("+CustomFETString::number(i)+")"+"\n";
15412 				}
15413 				else if(xmlReader.name()==QString("Preferred_Hour")){
15414 					QString text=xmlReader.readElementText();
15415 					cn->hours_L.append(0);
15416 					assert(cn->hours_L.count()-1==i);
15417 					for(cn->hours_L[i]=0; cn->hours_L[i] < this->nHoursPerDay; cn->hours_L[i]++)
15418 						if(this->hoursOfTheDay[cn->hours_L[i]]==text)
15419 							break;
15420 
15421 					if(cn->hours_L[i]>=this->nHoursPerDay){
15422 						xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
15423 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
15424 							tr("Constraint ActivityPreferredTimes hour corrupt for activity with id %1, hour %2 is inexistent ... ignoring constraint")
15425 							.arg(cn->activityId)
15426 							.arg(text));*/
15427 						delete cn;
15428 						cn=nullptr;
15429 						//goto corruptConstraintTime;
15430 						return nullptr;
15431 					}
15432 
15433 					assert(cn->hours_L[i]>=0 && cn->hours_L[i] < this->nHoursPerDay);
15434 					xmlReadingLog+="    Preferred hour="+this->hoursOfTheDay[cn->hours_L[i]]+"\n";
15435 				}
15436 				else{
15437 					unrecognizedXmlTags.append(xmlReader.name().toString());
15438 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
15439 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
15440 
15441 					xmlReader.skipCurrentElement();
15442 					xmlReaderNumberOfUnrecognizedFields++;
15443 				}
15444 			}
15445 			i++;
15446 
15447 			if(!(i==cn->days_L.count()) || !(i==cn->hours_L.count())){
15448 				xmlReader.raiseError(tr("%1 is incorrect").arg("Preferred_Time"));
15449 				delete cn;
15450 				cn=nullptr;
15451 				return nullptr;
15452 			}
15453 			assert(i==cn->days_L.count());
15454 			assert(i==cn->hours_L.count());
15455 		}
15456 		else{
15457 			unrecognizedXmlTags.append(xmlReader.name().toString());
15458 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
15459 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
15460 
15461 			xmlReader.skipCurrentElement();
15462 			xmlReaderNumberOfUnrecognizedFields++;
15463 		}
15464 	}
15465 	if(!(i==cn->nPreferredStartingTimes_L)){
15466 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Preferred_Times").arg("Preferred_Time"));
15467 		delete cn;
15468 		cn=nullptr;
15469 		return nullptr;
15470 	}
15471 	assert(i==cn->nPreferredStartingTimes_L);
15472 	return cn;
15473 }
15474 
readActivityPreferredTimeSlots(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)15475 TimeConstraint* Rules::readActivityPreferredTimeSlots(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
15476 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivityPreferredTimeSlots"));
15477 	ConstraintActivityPreferredTimeSlots* cn=new ConstraintActivityPreferredTimeSlots();
15478 	cn->p_nPreferredTimeSlots_L=0;
15479 	int i;
15480 	/*for(i=0; i<MAX_N_CONSTRAINT_ACTIVITY_PREFERRED_TIME_SLOTS; i++){
15481 		cn->p_days[i] = cn->p_hours[i] = -1;
15482 	}*/
15483 	i=0;
15484 	while(xmlReader.readNextStartElement()){
15485 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
15486 		if(xmlReader.name()==QString("Weight")){
15487 			//cn->weight=customFETStrToDouble(text);
15488 			xmlReader.skipCurrentElement();
15489 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
15490 			cn->weightPercentage=100;
15491 		}
15492 		else if(xmlReader.name()==QString("Weight_Percentage")){
15493 			QString text=xmlReader.readElementText();
15494 			cn->weightPercentage=customFETStrToDouble(text);
15495 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
15496 		}
15497 		else if(xmlReader.name()==QString("Active")){
15498 			QString text=xmlReader.readElementText();
15499 			if(text=="false"){
15500 				cn->active=false;
15501 			}
15502 		}
15503 		else if(xmlReader.name()==QString("Comments")){
15504 			QString text=xmlReader.readElementText();
15505 			cn->comments=text;
15506 		}
15507 		else if(xmlReader.name()==QString("Compulsory")){
15508 			QString text=xmlReader.readElementText();
15509 			if(text=="yes"){
15510 				//cn->compulsory=true;
15511 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
15512 				cn->weightPercentage=100;
15513 			}
15514 			else{
15515 				//cn->compulsory=false;
15516 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
15517 				cn->weightPercentage=0;
15518 			}
15519 		}
15520 		else if(xmlReader.name()==QString("Activity_Id")){
15521 			QString text=xmlReader.readElementText();
15522 			cn->p_activityId=text.toInt();
15523 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->p_activityId)+"\n";
15524 		}
15525 		else if(xmlReader.name()==QString("Number_of_Preferred_Time_Slots")){
15526 			QString text=xmlReader.readElementText();
15527 			cn->p_nPreferredTimeSlots_L=text.toInt();
15528 			xmlReadingLog+="    Read number of preferred times="+CustomFETString::number(cn->p_nPreferredTimeSlots_L)+"\n";
15529 		}
15530 		else if(xmlReader.name()==QString("Preferred_Time_Slot")){
15531 			xmlReadingLog+="    Read: preferred time slot\n";
15532 
15533 			assert(xmlReader.isStartElement());
15534 			while(xmlReader.readNextStartElement()){
15535 				xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
15536 				if(xmlReader.name()==QString("Preferred_Day")){
15537 					QString text=xmlReader.readElementText();
15538 					cn->p_days_L.append(0);
15539 					assert(cn->p_days_L.count()-1==i);
15540 					for(cn->p_days_L[i]=0; cn->p_days_L[i]<this->nDaysPerWeek; cn->p_days_L[i]++)
15541 						if(this->daysOfTheWeek[cn->p_days_L[i]]==text)
15542 							break;
15543 
15544 					if(cn->p_days_L[i]>=this->nDaysPerWeek){
15545 						xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
15546 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
15547 							tr("Constraint ActivityPreferredTimeSlots day corrupt for activity with id %1, day %2 is inexistent ... ignoring constraint")
15548 							.arg(cn->p_activityId)
15549 							.arg(text));*/
15550 						delete cn;
15551 						cn=nullptr;
15552 						//goto corruptConstraintTime;
15553 						return nullptr;
15554 					}
15555 
15556 					assert(cn->p_days_L[i]<this->nDaysPerWeek);
15557 					xmlReadingLog+="    Preferred day="+this->daysOfTheWeek[cn->p_days_L[i]]+"("+CustomFETString::number(i)+")"+"\n";
15558 				}
15559 				else if(xmlReader.name()==QString("Preferred_Hour")){
15560 					QString text=xmlReader.readElementText();
15561 					cn->p_hours_L.append(0);
15562 					assert(cn->p_hours_L.count()-1==i);
15563 					for(cn->p_hours_L[i]=0; cn->p_hours_L[i] < this->nHoursPerDay; cn->p_hours_L[i]++)
15564 						if(this->hoursOfTheDay[cn->p_hours_L[i]]==text)
15565 							break;
15566 
15567 					if(cn->p_hours_L[i]>=this->nHoursPerDay){
15568 						xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
15569 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
15570 							tr("Constraint ActivityPreferredTimeSlots hour corrupt for activity with id %1, hour %2 is inexistent ... ignoring constraint")
15571 							.arg(cn->p_activityId)
15572 							.arg(text));*/
15573 						delete cn;
15574 						cn=nullptr;
15575 						//goto corruptConstraintTime;
15576 						return nullptr;
15577 					}
15578 
15579 					assert(cn->p_hours_L[i]>=0 && cn->p_hours_L[i] < this->nHoursPerDay);
15580 					xmlReadingLog+="    Preferred hour="+this->hoursOfTheDay[cn->p_hours_L[i]]+"\n";
15581 				}
15582 				else{
15583 					unrecognizedXmlTags.append(xmlReader.name().toString());
15584 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
15585 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
15586 
15587 					xmlReader.skipCurrentElement();
15588 					xmlReaderNumberOfUnrecognizedFields++;
15589 				}
15590 			}
15591 
15592 			i++;
15593 
15594 			if(!(i==cn->p_days_L.count()) || !(i==cn->p_hours_L.count())){
15595 				xmlReader.raiseError(tr("%1 is incorrect").arg("Preferred_Time_Slot"));
15596 				delete cn;
15597 				cn=nullptr;
15598 				return nullptr;
15599 			}
15600 			assert(i==cn->p_days_L.count());
15601 			assert(i==cn->p_hours_L.count());
15602 		}
15603 		else{
15604 			unrecognizedXmlTags.append(xmlReader.name().toString());
15605 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
15606 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
15607 
15608 			xmlReader.skipCurrentElement();
15609 			xmlReaderNumberOfUnrecognizedFields++;
15610 		}
15611 	}
15612 	if(!(i==cn->p_nPreferredTimeSlots_L)){
15613 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Preferred_Time_Slots").arg("Preferred_Time_Slot"));
15614 		delete cn;
15615 		cn=nullptr;
15616 		return nullptr;
15617 	}
15618 	assert(i==cn->p_nPreferredTimeSlots_L);
15619 	return cn;
15620 }
15621 
readActivityPreferredStartingTimes(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)15622 TimeConstraint* Rules::readActivityPreferredStartingTimes(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
15623 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivityPreferredStartingTimes"));
15624 	ConstraintActivityPreferredStartingTimes* cn=new ConstraintActivityPreferredStartingTimes();
15625 	cn->nPreferredStartingTimes_L=0;
15626 	int i;
15627 	/*for(i=0; i<MAX_N_CONSTRAINT_ACTIVITY_PREFERRED_STARTING_TIMES; i++){
15628 		cn->days[i] = cn->hours[i] = -1;
15629 	}*/
15630 	i=0;
15631 	while(xmlReader.readNextStartElement()){
15632 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
15633 		if(xmlReader.name()==QString("Weight")){
15634 			//cn->weight=customFETStrToDouble(text);
15635 			xmlReader.skipCurrentElement();
15636 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
15637 			cn->weightPercentage=100;
15638 		}
15639 		else if(xmlReader.name()==QString("Weight_Percentage")){
15640 			QString text=xmlReader.readElementText();
15641 			cn->weightPercentage=customFETStrToDouble(text);
15642 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
15643 		}
15644 		else if(xmlReader.name()==QString("Active")){
15645 			QString text=xmlReader.readElementText();
15646 			if(text=="false"){
15647 				cn->active=false;
15648 			}
15649 		}
15650 		else if(xmlReader.name()==QString("Comments")){
15651 			QString text=xmlReader.readElementText();
15652 			cn->comments=text;
15653 		}
15654 		else if(xmlReader.name()==QString("Compulsory")){
15655 			QString text=xmlReader.readElementText();
15656 			if(text=="yes"){
15657 				//cn->compulsory=true;
15658 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
15659 				cn->weightPercentage=100;
15660 			}
15661 			else{
15662 				//cn->compulsory=false;
15663 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
15664 				cn->weightPercentage=0;
15665 			}
15666 		}
15667 		else if(xmlReader.name()==QString("Activity_Id")){
15668 			QString text=xmlReader.readElementText();
15669 			cn->activityId=text.toInt();
15670 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activityId)+"\n";
15671 		}
15672 		else if(xmlReader.name()==QString("Number_of_Preferred_Starting_Times")){
15673 			QString text=xmlReader.readElementText();
15674 			cn->nPreferredStartingTimes_L=text.toInt();
15675 			xmlReadingLog+="    Read number of preferred starting times="+CustomFETString::number(cn->nPreferredStartingTimes_L)+"\n";
15676 		}
15677 		else if(xmlReader.name()==QString("Preferred_Starting_Time")){
15678 			xmlReadingLog+="    Read: preferred starting time\n";
15679 
15680 			assert(xmlReader.isStartElement());
15681 			while(xmlReader.readNextStartElement()){
15682 				xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
15683 				if(xmlReader.name()==QString("Preferred_Starting_Day")){
15684 					QString text=xmlReader.readElementText();
15685 					cn->days_L.append(0);
15686 					assert(cn->days_L.count()-1==i);
15687 					for(cn->days_L[i]=0; cn->days_L[i]<this->nDaysPerWeek; cn->days_L[i]++)
15688 						if(this->daysOfTheWeek[cn->days_L[i]]==text)
15689 							break;
15690 
15691 					if(cn->days_L[i]>=this->nDaysPerWeek){
15692 						xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
15693 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
15694 							tr("Constraint ActivityPreferredStartingTimes day corrupt for activity with id %1, day %2 is inexistent ... ignoring constraint")
15695 							.arg(cn->activityId)
15696 							.arg(text));*/
15697 						delete cn;
15698 						cn=nullptr;
15699 						//goto corruptConstraintTime;
15700 						return nullptr;
15701 					}
15702 
15703 					assert(cn->days_L[i]<this->nDaysPerWeek);
15704 					xmlReadingLog+="    Preferred starting day="+this->daysOfTheWeek[cn->days_L[i]]+"("+CustomFETString::number(i)+")"+"\n";
15705 				}
15706 				else if(xmlReader.name()==QString("Preferred_Starting_Hour")){
15707 					QString text=xmlReader.readElementText();
15708 					cn->hours_L.append(0);
15709 					assert(cn->hours_L.count()-1==i);
15710 					for(cn->hours_L[i]=0; cn->hours_L[i] < this->nHoursPerDay; cn->hours_L[i]++)
15711 						if(this->hoursOfTheDay[cn->hours_L[i]]==text)
15712 							break;
15713 
15714 					if(cn->hours_L[i]>=this->nHoursPerDay){
15715 						xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
15716 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
15717 							tr("Constraint ActivityPreferredStartingTimes hour corrupt for activity with id %1, hour %2 is inexistent ... ignoring constraint")
15718 							.arg(cn->activityId)
15719 							.arg(text));*/
15720 						delete cn;
15721 						cn=nullptr;
15722 						//goto corruptConstraintTime;
15723 						return nullptr;
15724 					}
15725 
15726 					assert(cn->hours_L[i]>=0 && cn->hours_L[i] < this->nHoursPerDay);
15727 					xmlReadingLog+="    Preferred starting hour="+this->hoursOfTheDay[cn->hours_L[i]]+"\n";
15728 				}
15729 				else{
15730 					unrecognizedXmlTags.append(xmlReader.name().toString());
15731 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
15732 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
15733 
15734 					xmlReader.skipCurrentElement();
15735 					xmlReaderNumberOfUnrecognizedFields++;
15736 				}
15737 			}
15738 
15739 			i++;
15740 
15741 			if(!(i==cn->days_L.count()) || !(i==cn->hours_L.count())){
15742 				xmlReader.raiseError(tr("%1 is incorrect").arg("Preferred_Starting_Time"));
15743 				delete cn;
15744 				cn=nullptr;
15745 				return nullptr;
15746 			}
15747 			assert(i==cn->days_L.count());
15748 			assert(i==cn->hours_L.count());
15749 		}
15750 		else{
15751 			unrecognizedXmlTags.append(xmlReader.name().toString());
15752 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
15753 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
15754 
15755 			xmlReader.skipCurrentElement();
15756 			xmlReaderNumberOfUnrecognizedFields++;
15757 		}
15758 	}
15759 	if(!(i==cn->nPreferredStartingTimes_L)){
15760 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Preferred_Starting_Times").arg("Preferred_Starting_Time"));
15761 		delete cn;
15762 		cn=nullptr;
15763 		return nullptr;
15764 	}
15765 	assert(i==cn->nPreferredStartingTimes_L);
15766 	return cn;
15767 }
15768 
readBreak(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)15769 TimeConstraint* Rules::readBreak(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
15770 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintBreak"));
15771 
15772 	QList<int> days;
15773 	QList<int> hours;
15774 	double weightPercentage=100;
15775 	int d=-1, h1=-1, h2=-1;
15776 	bool active=true;
15777 	QString comments=QString("");
15778 	while(xmlReader.readNextStartElement()){
15779 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
15780 		if(xmlReader.name()==QString("Weight_Percentage")){
15781 			QString text=xmlReader.readElementText();
15782 			weightPercentage=customFETStrToDouble(text);
15783 			if(weightPercentage<0){
15784 				xmlReader.raiseError(tr("Weight percentage incorrect"));
15785 				return nullptr;
15786 			}
15787 			assert(weightPercentage>=0);
15788 			xmlReadingLog+="    Read weight percentage="+CustomFETString::number(weightPercentage)+"\n";
15789 		}
15790 		else if(xmlReader.name()==QString("Active")){
15791 			QString text=xmlReader.readElementText();
15792 			if(text=="false"){
15793 				active=false;
15794 			}
15795 		}
15796 		else if(xmlReader.name()==QString("Comments")){
15797 			QString text=xmlReader.readElementText();
15798 			comments=text;
15799 		}
15800 		else if(xmlReader.name()==QString("Day")){
15801 			QString text=xmlReader.readElementText();
15802 			for(d=0; d<this->nDaysPerWeek; d++)
15803 				if(this->daysOfTheWeek[d]==text)
15804 					break;
15805 			if(d>=this->nDaysPerWeek){
15806 				xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
15807 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
15808 					tr("Constraint Break day corrupt for day %1 is inexistent ... ignoring constraint")
15809 					.arg(text));*/
15810 				//cn=nullptr;
15811 				//goto corruptConstraintTime;
15812 				return nullptr;
15813 			}
15814 			assert(d<this->nDaysPerWeek);
15815 			xmlReadingLog+="    Crt. day="+this->daysOfTheWeek[d]+"\n";
15816 		}
15817 		else if(xmlReader.name()==QString("Start_Hour")){
15818 			QString text=xmlReader.readElementText();
15819 			for(h1=0; h1 < this->nHoursPerDay; h1++)
15820 				if(this->hoursOfTheDay[h1]==text)
15821 					break;
15822 			if(h1==this->nHoursPerDay){
15823 				xmlReader.raiseError(tr("Hour %1 is the last hour - impossible").arg(text));
15824 				return nullptr;
15825 			}
15826 			else if(h1>this->nHoursPerDay){
15827 				xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
15828 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
15829 					tr("Constraint Break start hour corrupt for hour %1 is inexistent ... ignoring constraint")
15830 					.arg(text));*/
15831 				//cn=nullptr;
15832 				//goto corruptConstraintTime;
15833 				return nullptr;
15834 			}
15835 			assert(h1>=0 && h1 < this->nHoursPerDay);
15836 			xmlReadingLog+="    Start hour="+this->hoursOfTheDay[h1]+"\n";
15837 		}
15838 		else if(xmlReader.name()==QString("End_Hour")){
15839 			QString text=xmlReader.readElementText();
15840 			for(h2=0; h2 < this->nHoursPerDay; h2++)
15841 				if(this->hoursOfTheDay[h2]==text)
15842 					break;
15843 			if(h2==0){
15844 				xmlReader.raiseError(tr("Hour %1 is the first hour - impossible").arg(text));
15845 				return nullptr;
15846 			}
15847 			else if(h2>this->nHoursPerDay){
15848 				xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
15849 				return nullptr;
15850 			}
15851 			/*if(h2<=0 || h2>this->nHoursPerDay){
15852 				RulesReconcilableMessage::information(parent, tr("FET information"),
15853 					tr("Constraint Break end hour corrupt for hour %1 is inexistent ... ignoring constraint")
15854 					.arg(text));
15855 				//goto corruptConstraintTime;
15856 				return nullptr;
15857 			}*/
15858 			assert(h2>0 && h2 <= this->nHoursPerDay);
15859 			xmlReadingLog+="    End hour="+this->hoursOfTheDay[h2]+"\n";
15860 		}
15861 		else{
15862 			unrecognizedXmlTags.append(xmlReader.name().toString());
15863 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
15864 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
15865 
15866 			xmlReader.skipCurrentElement();
15867 			xmlReaderNumberOfUnrecognizedFields++;
15868 		}
15869 	}
15870 
15871 	assert(weightPercentage>=0);
15872 	if(d<0){
15873 		xmlReader.raiseError(tr("Field missing: %1").arg("Day"));
15874 		return nullptr;
15875 	}
15876 	else if(h1<0){
15877 		xmlReader.raiseError(tr("Field missing: %1").arg("Start_Hour"));
15878 		return nullptr;
15879 	}
15880 	else if(h2<0){
15881 		xmlReader.raiseError(tr("Field missing: %1").arg("End_Hour"));
15882 		return nullptr;
15883 	}
15884 	assert(d>=0 && h1>=0 && h2>=0);
15885 
15886 	ConstraintBreakTimes* cn = nullptr;
15887 
15888 	bool found=false;
15889 	for(TimeConstraint* c : qAsConst(this->timeConstraintsList))
15890 		if(c->type==CONSTRAINT_BREAK_TIMES){
15891 			ConstraintBreakTimes* tna=(ConstraintBreakTimes*) c;
15892 			if(true){
15893 				found=true;
15894 
15895 				for(int hh=h1; hh<h2; hh++){
15896 					int k;
15897 					for(k=0; k<tna->days.count(); k++)
15898 						if(tna->days.at(k)==d && tna->hours.at(k)==hh)
15899 							break;
15900 					if(k==tna->days.count()){
15901 						tna->days.append(d);
15902 						tna->hours.append(hh);
15903 					}
15904 				}
15905 
15906 				assert(tna->days.count()==tna->hours.count());
15907 			}
15908 		}
15909 	if(!found){
15910 		days.clear();
15911 		hours.clear();
15912 		for(int hh=h1; hh<h2; hh++){
15913 			days.append(d);
15914 			hours.append(hh);
15915 		}
15916 
15917 		cn=new ConstraintBreakTimes(weightPercentage, days, hours);
15918 		cn->active=active;
15919 		cn->comments=comments;
15920 
15921 		return cn;
15922 	}
15923 	else
15924 		return nullptr;
15925 }
15926 
readBreakTimes(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)15927 TimeConstraint* Rules::readBreakTimes(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
15928 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintBreakTimes"));
15929 	ConstraintBreakTimes* cn=new ConstraintBreakTimes();
15930 	int nNotAvailableSlots=-1;
15931 	int i=0;
15932 	while(xmlReader.readNextStartElement()){
15933 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
15934 		if(xmlReader.name()==QString("Weight_Percentage")){
15935 			QString text=xmlReader.readElementText();
15936 			cn->weightPercentage=customFETStrToDouble(text);
15937 			xmlReadingLog+="    Read weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
15938 		}
15939 		else if(xmlReader.name()==QString("Active")){
15940 			QString text=xmlReader.readElementText();
15941 			if(text=="false"){
15942 				cn->active=false;
15943 			}
15944 		}
15945 		else if(xmlReader.name()==QString("Comments")){
15946 			QString text=xmlReader.readElementText();
15947 			cn->comments=text;
15948 		}
15949 
15950 		else if(xmlReader.name()==QString("Number_of_Break_Times")){
15951 			QString text=xmlReader.readElementText();
15952 			nNotAvailableSlots=text.toInt();
15953 			xmlReadingLog+="    Read number of break times="+CustomFETString::number(nNotAvailableSlots)+"\n";
15954 		}
15955 
15956 		else if(xmlReader.name()==QString("Break_Time")){
15957 			xmlReadingLog+="    Read: not available time\n";
15958 
15959 			int d=-1;
15960 			int h=-1;
15961 
15962 			assert(xmlReader.isStartElement());
15963 			while(xmlReader.readNextStartElement()){
15964 				xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
15965 				if(xmlReader.name()==QString("Day")){
15966 					QString text=xmlReader.readElementText();
15967 					for(d=0; d<this->nDaysPerWeek; d++)
15968 						if(this->daysOfTheWeek[d]==text)
15969 							break;
15970 
15971 					if(d>=this->nDaysPerWeek){
15972 						xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
15973 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
15974 							tr("Constraint BreakTimes day corrupt for day %1 is inexistent ... ignoring constraint")
15975 							.arg(text));*/
15976 						delete cn;
15977 						cn=nullptr;
15978 						//goto corruptConstraintTime;
15979 						return nullptr;
15980 					}
15981 
15982 					assert(d<this->nDaysPerWeek);
15983 					xmlReadingLog+="    Day="+this->daysOfTheWeek[d]+"("+CustomFETString::number(i)+")"+"\n";
15984 				}
15985 				else if(xmlReader.name()==QString("Hour")){
15986 					QString text=xmlReader.readElementText();
15987 					for(h=0; h < this->nHoursPerDay; h++)
15988 						if(this->hoursOfTheDay[h]==text)
15989 							break;
15990 
15991 					if(h>=this->nHoursPerDay){
15992 						xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
15993 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
15994 							tr("Constraint BreakTimes hour corrupt for hour %1 is inexistent ... ignoring constraint")
15995 							.arg(text));*/
15996 						delete cn;
15997 						cn=nullptr;
15998 						//goto corruptConstraintTime;
15999 						return nullptr;
16000 					}
16001 
16002 					assert(h>=0 && h < this->nHoursPerDay);
16003 					xmlReadingLog+="    Hour="+this->hoursOfTheDay[h]+"\n";
16004 				}
16005 				else{
16006 					unrecognizedXmlTags.append(xmlReader.name().toString());
16007 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
16008 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
16009 
16010 					xmlReader.skipCurrentElement();
16011 					xmlReaderNumberOfUnrecognizedFields++;
16012 				}
16013 			}
16014 			i++;
16015 
16016 			cn->days.append(d);
16017 			cn->hours.append(h);
16018 
16019 			if(d==-1 || h==-1){
16020 				xmlReader.raiseError(tr("%1 is incorrect").arg("Break_Time"));
16021 				delete cn;
16022 				cn=nullptr;
16023 				return nullptr;
16024 			}
16025 		}
16026 		else{
16027 			unrecognizedXmlTags.append(xmlReader.name().toString());
16028 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
16029 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
16030 
16031 			xmlReader.skipCurrentElement();
16032 			xmlReaderNumberOfUnrecognizedFields++;
16033 		}
16034 	}
16035 	if(!(i==nNotAvailableSlots)){
16036 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Break_Times").arg("Break_Time"));
16037 		delete cn;
16038 		cn=nullptr;
16039 		return nullptr;
16040 	}
16041 	assert(i==nNotAvailableSlots);
16042 	return cn;
16043 }
16044 
readTeachersNoGaps(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)16045 TimeConstraint* Rules::readTeachersNoGaps(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
16046 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersNoGaps"));
16047 	ConstraintTeachersMaxGapsPerWeek* cn=new ConstraintTeachersMaxGapsPerWeek();
16048 	cn->maxGaps=0;
16049 	//ConstraintTeachersNoGaps* cn=new ConstraintTeachersNoGaps();
16050 	while(xmlReader.readNextStartElement()){
16051 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
16052 		if(xmlReader.name()==QString("Weight")){
16053 			//cn->weight=customFETStrToDouble(text);
16054 			xmlReader.skipCurrentElement();
16055 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
16056 			cn->weightPercentage=100;
16057 		}
16058 		else if(xmlReader.name()==QString("Weight_Percentage")){
16059 			QString text=xmlReader.readElementText();
16060 			cn->weightPercentage=customFETStrToDouble(text);
16061 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
16062 		}
16063 		else if(xmlReader.name()==QString("Active")){
16064 			QString text=xmlReader.readElementText();
16065 			if(text=="false"){
16066 				cn->active=false;
16067 			}
16068 		}
16069 		else if(xmlReader.name()==QString("Comments")){
16070 			QString text=xmlReader.readElementText();
16071 			cn->comments=text;
16072 		}
16073 		else if(xmlReader.name()==QString("Compulsory")){
16074 			QString text=xmlReader.readElementText();
16075 			if(text=="yes"){
16076 				//cn->compulsory=true;
16077 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
16078 				cn->weightPercentage=100;
16079 			}
16080 			else{
16081 				//cn->compulsory=false;
16082 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
16083 				cn->weightPercentage=0;
16084 			}
16085 		}
16086 		else{
16087 			unrecognizedXmlTags.append(xmlReader.name().toString());
16088 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
16089 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
16090 
16091 			xmlReader.skipCurrentElement();
16092 			xmlReaderNumberOfUnrecognizedFields++;
16093 		}
16094 	}
16095 	return cn;
16096 }
16097 
readTeachersMaxGapsPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)16098 TimeConstraint* Rules::readTeachersMaxGapsPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
16099 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxGapsPerWeek"));
16100 	ConstraintTeachersMaxGapsPerWeek* cn=new ConstraintTeachersMaxGapsPerWeek();
16101 	while(xmlReader.readNextStartElement()){
16102 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
16103 		if(xmlReader.name()==QString("Weight")){
16104 			//cn->weight=customFETStrToDouble(text);
16105 			xmlReader.skipCurrentElement();
16106 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
16107 			cn->weightPercentage=100;
16108 		}
16109 		else if(xmlReader.name()==QString("Weight_Percentage")){
16110 			QString text=xmlReader.readElementText();
16111 			cn->weightPercentage=customFETStrToDouble(text);
16112 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
16113 		}
16114 		else if(xmlReader.name()==QString("Active")){
16115 			QString text=xmlReader.readElementText();
16116 			if(text=="false"){
16117 				cn->active=false;
16118 			}
16119 		}
16120 		else if(xmlReader.name()==QString("Comments")){
16121 			QString text=xmlReader.readElementText();
16122 			cn->comments=text;
16123 		}
16124 		else if(xmlReader.name()==QString("Max_Gaps")){
16125 			QString text=xmlReader.readElementText();
16126 			cn->maxGaps=text.toInt();
16127 			xmlReadingLog+="    Adding max gaps="+CustomFETString::number(cn->maxGaps)+"\n";
16128 		}
16129 		else if(xmlReader.name()==QString("Compulsory")){
16130 			QString text=xmlReader.readElementText();
16131 			if(text=="yes"){
16132 				//cn->compulsory=true;
16133 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
16134 				cn->weightPercentage=100;
16135 			}
16136 			else{
16137 				//cn->compulsory=false;
16138 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
16139 				cn->weightPercentage=0;
16140 			}
16141 		}
16142 		else{
16143 			unrecognizedXmlTags.append(xmlReader.name().toString());
16144 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
16145 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
16146 
16147 			xmlReader.skipCurrentElement();
16148 			xmlReaderNumberOfUnrecognizedFields++;
16149 		}
16150 	}
16151 	return cn;
16152 }
16153 
readTeacherMaxGapsPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)16154 TimeConstraint* Rules::readTeacherMaxGapsPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
16155 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxGapsPerWeek"));
16156 	ConstraintTeacherMaxGapsPerWeek* cn=new ConstraintTeacherMaxGapsPerWeek();
16157 	while(xmlReader.readNextStartElement()){
16158 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
16159 		if(xmlReader.name()==QString("Weight")){
16160 			//cn->weight=customFETStrToDouble(text);
16161 			xmlReader.skipCurrentElement();
16162 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
16163 			cn->weightPercentage=100;
16164 		}
16165 		else if(xmlReader.name()==QString("Teacher_Name")){
16166 			QString text=xmlReader.readElementText();
16167 			cn->teacherName=text;
16168 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
16169 		}
16170 		else if(xmlReader.name()==QString("Weight_Percentage")){
16171 			QString text=xmlReader.readElementText();
16172 			cn->weightPercentage=customFETStrToDouble(text);
16173 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
16174 		}
16175 		else if(xmlReader.name()==QString("Active")){
16176 			QString text=xmlReader.readElementText();
16177 			if(text=="false"){
16178 				cn->active=false;
16179 			}
16180 		}
16181 		else if(xmlReader.name()==QString("Comments")){
16182 			QString text=xmlReader.readElementText();
16183 			cn->comments=text;
16184 		}
16185 		else if(xmlReader.name()==QString("Max_Gaps")){
16186 			QString text=xmlReader.readElementText();
16187 			cn->maxGaps=text.toInt();
16188 			xmlReadingLog+="    Adding max gaps="+CustomFETString::number(cn->maxGaps)+"\n";
16189 		}
16190 		else if(xmlReader.name()==QString("Compulsory")){
16191 			QString text=xmlReader.readElementText();
16192 			if(text=="yes"){
16193 				//cn->compulsory=true;
16194 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
16195 				cn->weightPercentage=100;
16196 			}
16197 			else{
16198 				//cn->compulsory=false;
16199 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
16200 				cn->weightPercentage=0;
16201 			}
16202 		}
16203 		else{
16204 			unrecognizedXmlTags.append(xmlReader.name().toString());
16205 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
16206 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
16207 
16208 			xmlReader.skipCurrentElement();
16209 			xmlReaderNumberOfUnrecognizedFields++;
16210 		}
16211 	}
16212 	return cn;
16213 }
16214 
readTeachersMaxGapsPerDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)16215 TimeConstraint* Rules::readTeachersMaxGapsPerDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
16216 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxGapsPerDay"));
16217 	ConstraintTeachersMaxGapsPerDay* cn=new ConstraintTeachersMaxGapsPerDay();
16218 	while(xmlReader.readNextStartElement()){
16219 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
16220 		if(xmlReader.name()==QString("Weight")){
16221 			//cn->weight=customFETStrToDouble(text);
16222 			xmlReader.skipCurrentElement();
16223 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
16224 			cn->weightPercentage=100;
16225 		}
16226 		else if(xmlReader.name()==QString("Weight_Percentage")){
16227 			QString text=xmlReader.readElementText();
16228 			cn->weightPercentage=customFETStrToDouble(text);
16229 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
16230 		}
16231 		else if(xmlReader.name()==QString("Active")){
16232 			QString text=xmlReader.readElementText();
16233 			if(text=="false"){
16234 				cn->active=false;
16235 			}
16236 		}
16237 		else if(xmlReader.name()==QString("Comments")){
16238 			QString text=xmlReader.readElementText();
16239 			cn->comments=text;
16240 		}
16241 		else if(xmlReader.name()==QString("Max_Gaps")){
16242 			QString text=xmlReader.readElementText();
16243 			cn->maxGaps=text.toInt();
16244 			xmlReadingLog+="    Adding max gaps="+CustomFETString::number(cn->maxGaps)+"\n";
16245 		}
16246 		else if(xmlReader.name()==QString("Compulsory")){
16247 			QString text=xmlReader.readElementText();
16248 			if(text=="yes"){
16249 				//cn->compulsory=true;
16250 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
16251 				cn->weightPercentage=100;
16252 			}
16253 			else{
16254 				//cn->compulsory=false;
16255 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
16256 				cn->weightPercentage=0;
16257 			}
16258 		}
16259 		else{
16260 			unrecognizedXmlTags.append(xmlReader.name().toString());
16261 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
16262 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
16263 
16264 			xmlReader.skipCurrentElement();
16265 			xmlReaderNumberOfUnrecognizedFields++;
16266 		}
16267 	}
16268 	return cn;
16269 }
16270 
readTeacherMaxGapsPerDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)16271 TimeConstraint* Rules::readTeacherMaxGapsPerDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
16272 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxGapsPerDay"));
16273 	ConstraintTeacherMaxGapsPerDay* cn=new ConstraintTeacherMaxGapsPerDay();
16274 	while(xmlReader.readNextStartElement()){
16275 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
16276 		if(xmlReader.name()==QString("Weight")){
16277 			//cn->weight=customFETStrToDouble(text);
16278 			xmlReader.skipCurrentElement();
16279 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
16280 			cn->weightPercentage=100;
16281 		}
16282 		else if(xmlReader.name()==QString("Teacher_Name")){
16283 			QString text=xmlReader.readElementText();
16284 			cn->teacherName=text;
16285 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
16286 		}
16287 		else if(xmlReader.name()==QString("Weight_Percentage")){
16288 			QString text=xmlReader.readElementText();
16289 			cn->weightPercentage=customFETStrToDouble(text);
16290 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
16291 		}
16292 		else if(xmlReader.name()==QString("Active")){
16293 			QString text=xmlReader.readElementText();
16294 			if(text=="false"){
16295 				cn->active=false;
16296 			}
16297 		}
16298 		else if(xmlReader.name()==QString("Comments")){
16299 			QString text=xmlReader.readElementText();
16300 			cn->comments=text;
16301 		}
16302 		else if(xmlReader.name()==QString("Max_Gaps")){
16303 			QString text=xmlReader.readElementText();
16304 			cn->maxGaps=text.toInt();
16305 			xmlReadingLog+="    Adding max gaps="+CustomFETString::number(cn->maxGaps)+"\n";
16306 		}
16307 		else if(xmlReader.name()==QString("Compulsory")){
16308 			QString text=xmlReader.readElementText();
16309 			if(text=="yes"){
16310 				//cn->compulsory=true;
16311 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
16312 				cn->weightPercentage=100;
16313 			}
16314 			else{
16315 				//cn->compulsory=false;
16316 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
16317 				cn->weightPercentage=0;
16318 			}
16319 		}
16320 		else{
16321 			unrecognizedXmlTags.append(xmlReader.name().toString());
16322 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
16323 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
16324 
16325 			xmlReader.skipCurrentElement();
16326 			xmlReaderNumberOfUnrecognizedFields++;
16327 		}
16328 	}
16329 	return cn;
16330 }
16331 
readTeachersMaxGapsPerMorningAndAfternoon(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)16332 TimeConstraint* Rules::readTeachersMaxGapsPerMorningAndAfternoon(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
16333 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxGapsPerMorningAndAfternoon"));
16334 	ConstraintTeachersMaxGapsPerMorningAndAfternoon* cn=new ConstraintTeachersMaxGapsPerMorningAndAfternoon();
16335 	while(xmlReader.readNextStartElement()){
16336 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
16337 		if(xmlReader.name()==QString("Weight")){
16338 			//cn->weight=customFETStrToDouble(text);
16339 			xmlReader.skipCurrentElement();
16340 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
16341 			cn->weightPercentage=100;
16342 		}
16343 		else if(xmlReader.name()==QString("Weight_Percentage")){
16344 			QString text=xmlReader.readElementText();
16345 			cn->weightPercentage=customFETStrToDouble(text);
16346 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
16347 		}
16348 		else if(xmlReader.name()==QString("Active")){
16349 			QString text=xmlReader.readElementText();
16350 			if(text=="false"){
16351 				cn->active=false;
16352 			}
16353 		}
16354 		else if(xmlReader.name()==QString("Comments")){
16355 			QString text=xmlReader.readElementText();
16356 			cn->comments=text;
16357 		}
16358 		else if(xmlReader.name()==QString("Max_Gaps")){
16359 			QString text=xmlReader.readElementText();
16360 			cn->maxGaps=text.toInt();
16361 			xmlReadingLog+="    Adding max gaps="+CustomFETString::number(cn->maxGaps)+"\n";
16362 		}
16363 		else if(xmlReader.name()==QString("Compulsory")){
16364 			QString text=xmlReader.readElementText();
16365 			if(text=="yes"){
16366 				//cn->compulsory=true;
16367 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
16368 				cn->weightPercentage=100;
16369 			}
16370 			else{
16371 				//cn->compulsory=false;
16372 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
16373 				cn->weightPercentage=0;
16374 			}
16375 		}
16376 		else{
16377 			unrecognizedXmlTags.append(xmlReader.name().toString());
16378 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
16379 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
16380 
16381 			xmlReader.skipCurrentElement();
16382 			xmlReaderNumberOfUnrecognizedFields++;
16383 		}
16384 	}
16385 	return cn;
16386 }
16387 
readTeacherMaxGapsPerMorningAndAfternoon(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)16388 TimeConstraint* Rules::readTeacherMaxGapsPerMorningAndAfternoon(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
16389 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxGapsPerMorningAndAfternoon"));
16390 	ConstraintTeacherMaxGapsPerMorningAndAfternoon* cn=new ConstraintTeacherMaxGapsPerMorningAndAfternoon();
16391 	while(xmlReader.readNextStartElement()){
16392 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
16393 		if(xmlReader.name()==QString("Weight")){
16394 			//cn->weight=customFETStrToDouble(text);
16395 			xmlReader.skipCurrentElement();
16396 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
16397 			cn->weightPercentage=100;
16398 		}
16399 		else if(xmlReader.name()==QString("Teacher_Name")){
16400 			QString text=xmlReader.readElementText();
16401 			cn->teacherName=text;
16402 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
16403 		}
16404 		else if(xmlReader.name()==QString("Weight_Percentage")){
16405 			QString text=xmlReader.readElementText();
16406 			cn->weightPercentage=customFETStrToDouble(text);
16407 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
16408 		}
16409 		else if(xmlReader.name()==QString("Active")){
16410 			QString text=xmlReader.readElementText();
16411 			if(text=="false"){
16412 				cn->active=false;
16413 			}
16414 		}
16415 		else if(xmlReader.name()==QString("Comments")){
16416 			QString text=xmlReader.readElementText();
16417 			cn->comments=text;
16418 		}
16419 		else if(xmlReader.name()==QString("Max_Gaps")){
16420 			QString text=xmlReader.readElementText();
16421 			cn->maxGaps=text.toInt();
16422 			xmlReadingLog+="    Adding max gaps="+CustomFETString::number(cn->maxGaps)+"\n";
16423 		}
16424 		else if(xmlReader.name()==QString("Compulsory")){
16425 			QString text=xmlReader.readElementText();
16426 			if(text=="yes"){
16427 				//cn->compulsory=true;
16428 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
16429 				cn->weightPercentage=100;
16430 			}
16431 			else{
16432 				//cn->compulsory=false;
16433 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
16434 				cn->weightPercentage=0;
16435 			}
16436 		}
16437 		else{
16438 			unrecognizedXmlTags.append(xmlReader.name().toString());
16439 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
16440 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
16441 
16442 			xmlReader.skipCurrentElement();
16443 			xmlReaderNumberOfUnrecognizedFields++;
16444 		}
16445 	}
16446 	return cn;
16447 }
16448 
readStudentsNoGaps(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)16449 TimeConstraint* Rules::readStudentsNoGaps(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
16450 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsNoGaps"));
16451 
16452 	ConstraintStudentsMaxGapsPerWeek* cn=new ConstraintStudentsMaxGapsPerWeek();
16453 
16454 	cn->maxGaps=0;
16455 
16456 	//bool compulsory_read=false;
16457 	while(xmlReader.readNextStartElement()){
16458 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
16459 		if(xmlReader.name()==QString("Weight")){
16460 			//cn->weight=customFETStrToDouble(text);
16461 			xmlReader.skipCurrentElement();
16462 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
16463 			cn->weightPercentage=100;
16464 		}
16465 		else if(xmlReader.name()==QString("Weight_Percentage")){
16466 			QString text=xmlReader.readElementText();
16467 			cn->weightPercentage=customFETStrToDouble(text);
16468 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
16469 		}
16470 		else if(xmlReader.name()==QString("Active")){
16471 			QString text=xmlReader.readElementText();
16472 			if(text=="false"){
16473 				cn->active=false;
16474 			}
16475 		}
16476 		else if(xmlReader.name()==QString("Comments")){
16477 			QString text=xmlReader.readElementText();
16478 			cn->comments=text;
16479 		}
16480 		else if(xmlReader.name()==QString("Compulsory")){
16481 			QString text=xmlReader.readElementText();
16482 			if(text=="yes"){
16483 				//cn->compulsory=true;
16484 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
16485 				cn->weightPercentage=100;
16486 			}
16487 			else{
16488 				//cn->compulsory=false;
16489 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
16490 				cn->weightPercentage=0;
16491 			}
16492 			//compulsory_read=true;
16493 		}
16494 		else{
16495 			unrecognizedXmlTags.append(xmlReader.name().toString());
16496 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
16497 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
16498 
16499 			xmlReader.skipCurrentElement();
16500 			xmlReaderNumberOfUnrecognizedFields++;
16501 		}
16502 	}
16503 	return cn;
16504 }
16505 
readStudentsSetNoGaps(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)16506 TimeConstraint* Rules::readStudentsSetNoGaps(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
16507 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetNoGaps"));
16508 
16509 	ConstraintStudentsSetMaxGapsPerWeek* cn=new ConstraintStudentsSetMaxGapsPerWeek();
16510 
16511 	cn->maxGaps=0;
16512 
16513 	//bool compulsory_read=false;
16514 	while(xmlReader.readNextStartElement()){
16515 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
16516 		if(xmlReader.name()==QString("Weight")){
16517 			//cn->weight=customFETStrToDouble(text);
16518 			xmlReader.skipCurrentElement();
16519 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
16520 			cn->weightPercentage=100;
16521 		}
16522 		else if(xmlReader.name()==QString("Weight_Percentage")){
16523 			QString text=xmlReader.readElementText();
16524 			cn->weightPercentage=customFETStrToDouble(text);
16525 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
16526 		}
16527 		else if(xmlReader.name()==QString("Active")){
16528 			QString text=xmlReader.readElementText();
16529 			if(text=="false"){
16530 				cn->active=false;
16531 			}
16532 		}
16533 		else if(xmlReader.name()==QString("Comments")){
16534 			QString text=xmlReader.readElementText();
16535 			cn->comments=text;
16536 		}
16537 		else if(xmlReader.name()==QString("Compulsory")){
16538 			QString text=xmlReader.readElementText();
16539 			if(text=="yes"){
16540 				//cn->compulsory=true;
16541 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
16542 				cn->weightPercentage=100;
16543 			}
16544 			else{
16545 				//cn->compulsory=false;
16546 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
16547 				cn->weightPercentage=0;
16548 			}
16549 			//compulsory_read=true;
16550 		}
16551 		else if(xmlReader.name()==QString("Students")){
16552 			QString text=xmlReader.readElementText();
16553 			cn->students=text;
16554 			xmlReadingLog+="    Read students name="+cn->students+"\n";
16555 		}
16556 		else{
16557 			unrecognizedXmlTags.append(xmlReader.name().toString());
16558 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
16559 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
16560 
16561 			xmlReader.skipCurrentElement();
16562 			xmlReaderNumberOfUnrecognizedFields++;
16563 		}
16564 	}
16565 	return cn;
16566 }
16567 
readStudentsMaxGapsPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)16568 TimeConstraint* Rules::readStudentsMaxGapsPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
16569 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMaxGapsPerWeek"));
16570 	ConstraintStudentsMaxGapsPerWeek* cn=new ConstraintStudentsMaxGapsPerWeek();
16571 
16572 	//bool compulsory_read=false;
16573 	while(xmlReader.readNextStartElement()){
16574 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
16575 		if(xmlReader.name()==QString("Weight")){
16576 			//cn->weight=customFETStrToDouble(text);
16577 			xmlReader.skipCurrentElement();
16578 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
16579 			cn->weightPercentage=100;
16580 		}
16581 		else if(xmlReader.name()==QString("Weight_Percentage")){
16582 			QString text=xmlReader.readElementText();
16583 			cn->weightPercentage=customFETStrToDouble(text);
16584 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
16585 		}
16586 		else if(xmlReader.name()==QString("Active")){
16587 			QString text=xmlReader.readElementText();
16588 			if(text=="false"){
16589 				cn->active=false;
16590 			}
16591 		}
16592 		else if(xmlReader.name()==QString("Comments")){
16593 			QString text=xmlReader.readElementText();
16594 			cn->comments=text;
16595 		}
16596 		else if(xmlReader.name()==QString("Max_Gaps")){
16597 			QString text=xmlReader.readElementText();
16598 			cn->maxGaps=text.toInt();
16599 			xmlReadingLog+="    Adding max gaps="+CustomFETString::number(cn->maxGaps)+"\n";
16600 		}
16601 		else if(xmlReader.name()==QString("Compulsory")){
16602 			QString text=xmlReader.readElementText();
16603 			if(text=="yes"){
16604 				//cn->compulsory=true;
16605 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
16606 				cn->weightPercentage=100;
16607 			}
16608 			else{
16609 				//cn->compulsory=false;
16610 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
16611 				cn->weightPercentage=0;
16612 			}
16613 			//compulsory_read=true;
16614 		}
16615 		else{
16616 			unrecognizedXmlTags.append(xmlReader.name().toString());
16617 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
16618 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
16619 
16620 			xmlReader.skipCurrentElement();
16621 			xmlReaderNumberOfUnrecognizedFields++;
16622 		}
16623 	}
16624 	return cn;
16625 }
16626 
readStudentsSetMaxGapsPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)16627 TimeConstraint* Rules::readStudentsSetMaxGapsPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
16628 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMaxGapsPerWeek"));
16629 	ConstraintStudentsSetMaxGapsPerWeek* cn=new ConstraintStudentsSetMaxGapsPerWeek();
16630 
16631 	//bool compulsory_read=false;
16632 	while(xmlReader.readNextStartElement()){
16633 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
16634 		if(xmlReader.name()==QString("Weight")){
16635 			//cn->weight=customFETStrToDouble(text);
16636 			xmlReader.skipCurrentElement();
16637 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
16638 			cn->weightPercentage=100;
16639 		}
16640 		else if(xmlReader.name()==QString("Weight_Percentage")){
16641 			QString text=xmlReader.readElementText();
16642 			cn->weightPercentage=customFETStrToDouble(text);
16643 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
16644 		}
16645 		else if(xmlReader.name()==QString("Active")){
16646 			QString text=xmlReader.readElementText();
16647 			if(text=="false"){
16648 				cn->active=false;
16649 			}
16650 		}
16651 		else if(xmlReader.name()==QString("Comments")){
16652 			QString text=xmlReader.readElementText();
16653 			cn->comments=text;
16654 		}
16655 		else if(xmlReader.name()==QString("Max_Gaps")){
16656 			QString text=xmlReader.readElementText();
16657 			cn->maxGaps=text.toInt();
16658 			xmlReadingLog+="    Adding max gaps="+CustomFETString::number(cn->maxGaps)+"\n";
16659 		}
16660 		else if(xmlReader.name()==QString("Compulsory")){
16661 			QString text=xmlReader.readElementText();
16662 			if(text=="yes"){
16663 				//cn->compulsory=true;
16664 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
16665 				cn->weightPercentage=100;
16666 			}
16667 			else{
16668 				//cn->compulsory=false;
16669 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
16670 				cn->weightPercentage=0;
16671 			}
16672 			//compulsory_read=true;
16673 		}
16674 		else if(xmlReader.name()==QString("Students")){
16675 			QString text=xmlReader.readElementText();
16676 			cn->students=text;
16677 			xmlReadingLog+="    Read students name="+cn->students+"\n";
16678 		}
16679 		else{
16680 			unrecognizedXmlTags.append(xmlReader.name().toString());
16681 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
16682 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
16683 
16684 			xmlReader.skipCurrentElement();
16685 			xmlReaderNumberOfUnrecognizedFields++;
16686 		}
16687 	}
16688 	return cn;
16689 }
16690 
readStudentsMaxGapsPerDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)16691 TimeConstraint* Rules::readStudentsMaxGapsPerDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
16692 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMaxGapsPerDay"));
16693 	ConstraintStudentsMaxGapsPerDay* cn=new ConstraintStudentsMaxGapsPerDay();
16694 
16695 	//bool compulsory_read=false;
16696 	while(xmlReader.readNextStartElement()){
16697 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
16698 		if(xmlReader.name()==QString("Weight")){
16699 			//cn->weight=customFETStrToDouble(text);
16700 			xmlReader.skipCurrentElement();
16701 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
16702 			cn->weightPercentage=100;
16703 		}
16704 		else if(xmlReader.name()==QString("Weight_Percentage")){
16705 			QString text=xmlReader.readElementText();
16706 			cn->weightPercentage=customFETStrToDouble(text);
16707 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
16708 		}
16709 		else if(xmlReader.name()==QString("Active")){
16710 			QString text=xmlReader.readElementText();
16711 			if(text=="false"){
16712 				cn->active=false;
16713 			}
16714 		}
16715 		else if(xmlReader.name()==QString("Comments")){
16716 			QString text=xmlReader.readElementText();
16717 			cn->comments=text;
16718 		}
16719 		else if(xmlReader.name()==QString("Max_Gaps")){
16720 			QString text=xmlReader.readElementText();
16721 			cn->maxGaps=text.toInt();
16722 			xmlReadingLog+="    Adding max gaps="+CustomFETString::number(cn->maxGaps)+"\n";
16723 		}
16724 		else if(xmlReader.name()==QString("Compulsory")){
16725 			QString text=xmlReader.readElementText();
16726 			if(text=="yes"){
16727 				//cn->compulsory=true;
16728 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
16729 				cn->weightPercentage=100;
16730 			}
16731 			else{
16732 				//cn->compulsory=false;
16733 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
16734 				cn->weightPercentage=0;
16735 			}
16736 			//compulsory_read=true;
16737 		}
16738 		else{
16739 			unrecognizedXmlTags.append(xmlReader.name().toString());
16740 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
16741 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
16742 
16743 			xmlReader.skipCurrentElement();
16744 			xmlReaderNumberOfUnrecognizedFields++;
16745 		}
16746 	}
16747 	return cn;
16748 }
16749 
readStudentsSetMaxGapsPerDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)16750 TimeConstraint* Rules::readStudentsSetMaxGapsPerDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
16751 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMaxGapsPerDay"));
16752 	ConstraintStudentsSetMaxGapsPerDay* cn=new ConstraintStudentsSetMaxGapsPerDay();
16753 
16754 	//bool compulsory_read=false;
16755 	while(xmlReader.readNextStartElement()){
16756 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
16757 		if(xmlReader.name()==QString("Weight")){
16758 			//cn->weight=customFETStrToDouble(text);
16759 			xmlReader.skipCurrentElement();
16760 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
16761 			cn->weightPercentage=100;
16762 		}
16763 		else if(xmlReader.name()==QString("Weight_Percentage")){
16764 			QString text=xmlReader.readElementText();
16765 			cn->weightPercentage=customFETStrToDouble(text);
16766 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
16767 		}
16768 		else if(xmlReader.name()==QString("Active")){
16769 			QString text=xmlReader.readElementText();
16770 			if(text=="false"){
16771 				cn->active=false;
16772 			}
16773 		}
16774 		else if(xmlReader.name()==QString("Comments")){
16775 			QString text=xmlReader.readElementText();
16776 			cn->comments=text;
16777 		}
16778 		else if(xmlReader.name()==QString("Max_Gaps")){
16779 			QString text=xmlReader.readElementText();
16780 			cn->maxGaps=text.toInt();
16781 			xmlReadingLog+="    Adding max gaps="+CustomFETString::number(cn->maxGaps)+"\n";
16782 		}
16783 		else if(xmlReader.name()==QString("Compulsory")){
16784 			QString text=xmlReader.readElementText();
16785 			if(text=="yes"){
16786 				//cn->compulsory=true;
16787 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
16788 				cn->weightPercentage=100;
16789 			}
16790 			else{
16791 				//cn->compulsory=false;
16792 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
16793 				cn->weightPercentage=0;
16794 			}
16795 			//compulsory_read=true;
16796 		}
16797 		else if(xmlReader.name()==QString("Students")){
16798 			QString text=xmlReader.readElementText();
16799 			cn->students=text;
16800 			xmlReadingLog+="    Read students name="+cn->students+"\n";
16801 		}
16802 		else{
16803 			unrecognizedXmlTags.append(xmlReader.name().toString());
16804 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
16805 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
16806 
16807 			xmlReader.skipCurrentElement();
16808 			xmlReaderNumberOfUnrecognizedFields++;
16809 		}
16810 	}
16811 	return cn;
16812 }
16813 
readStudentsEarly(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)16814 TimeConstraint* Rules::readStudentsEarly(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
16815 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsEarly"));
16816 	ConstraintStudentsEarlyMaxBeginningsAtSecondHour* cn=new ConstraintStudentsEarlyMaxBeginningsAtSecondHour();
16817 
16818 	cn->maxBeginningsAtSecondHour=0;
16819 
16820 	while(xmlReader.readNextStartElement()){
16821 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
16822 		if(xmlReader.name()==QString("Weight")){
16823 			//cn->weight=customFETStrToDouble(text);
16824 			xmlReader.skipCurrentElement();
16825 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
16826 			cn->weightPercentage=100;
16827 		}
16828 		else if(xmlReader.name()==QString("Weight_Percentage")){
16829 			QString text=xmlReader.readElementText();
16830 			cn->weightPercentage=customFETStrToDouble(text);
16831 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
16832 		}
16833 		else if(xmlReader.name()==QString("Active")){
16834 			QString text=xmlReader.readElementText();
16835 			if(text=="false"){
16836 				cn->active=false;
16837 			}
16838 		}
16839 		else if(xmlReader.name()==QString("Comments")){
16840 			QString text=xmlReader.readElementText();
16841 			cn->comments=text;
16842 		}
16843 		else if(xmlReader.name()==QString("Compulsory")){
16844 			QString text=xmlReader.readElementText();
16845 			if(text=="yes"){
16846 				//cn->compulsory=true;
16847 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
16848 				cn->weightPercentage=100;
16849 			}
16850 			else{
16851 				//cn->compulsory=false;
16852 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
16853 				cn->weightPercentage=0;
16854 			}
16855 		}
16856 		else{
16857 			unrecognizedXmlTags.append(xmlReader.name().toString());
16858 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
16859 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
16860 
16861 			xmlReader.skipCurrentElement();
16862 			xmlReaderNumberOfUnrecognizedFields++;
16863 		}
16864 	}
16865 	return cn;
16866 }
16867 
readStudentsEarlyMaxBeginningsAtSecondHour(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)16868 TimeConstraint* Rules::readStudentsEarlyMaxBeginningsAtSecondHour(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
16869 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsEarlyMaxBeginningsAtSecondHour"));
16870 	ConstraintStudentsEarlyMaxBeginningsAtSecondHour* cn=new ConstraintStudentsEarlyMaxBeginningsAtSecondHour();
16871 	cn->maxBeginningsAtSecondHour=-1;
16872 	while(xmlReader.readNextStartElement()){
16873 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
16874 		if(xmlReader.name()==QString("Weight")){
16875 			//cn->weight=customFETStrToDouble(text);
16876 			xmlReader.skipCurrentElement();
16877 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
16878 			cn->weightPercentage=100;
16879 		}
16880 		else if(xmlReader.name()==QString("Weight_Percentage")){
16881 			QString text=xmlReader.readElementText();
16882 			cn->weightPercentage=customFETStrToDouble(text);
16883 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
16884 		}
16885 		else if(xmlReader.name()==QString("Active")){
16886 			QString text=xmlReader.readElementText();
16887 			if(text=="false"){
16888 				cn->active=false;
16889 			}
16890 		}
16891 		else if(xmlReader.name()==QString("Comments")){
16892 			QString text=xmlReader.readElementText();
16893 			cn->comments=text;
16894 		}
16895 		else if(xmlReader.name()==QString("Max_Beginnings_At_Second_Hour")){
16896 			QString text=xmlReader.readElementText();
16897 			cn->maxBeginningsAtSecondHour=text.toInt();
16898 			if(!(cn->maxBeginningsAtSecondHour>=0)){
16899 				xmlReader.raiseError(tr("%1 is incorrect").arg("Max_Beginnings_At_Second_Hour"));
16900 				delete cn;
16901 				cn=nullptr;
16902 				return nullptr;
16903 			}
16904 			xmlReadingLog+="    Adding max beginnings at second hour="+CustomFETString::number(cn->maxBeginningsAtSecondHour)+"\n";
16905 		}
16906 		else if(xmlReader.name()==QString("Compulsory")){
16907 			QString text=xmlReader.readElementText();
16908 			if(text=="yes"){
16909 				//cn->compulsory=true;
16910 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
16911 				cn->weightPercentage=100;
16912 			}
16913 			else{
16914 				//cn->compulsory=false;
16915 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
16916 				cn->weightPercentage=0;
16917 			}
16918 		}
16919 		else{
16920 			unrecognizedXmlTags.append(xmlReader.name().toString());
16921 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
16922 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
16923 
16924 			xmlReader.skipCurrentElement();
16925 			xmlReaderNumberOfUnrecognizedFields++;
16926 		}
16927 	}
16928 	if(!(cn->maxBeginningsAtSecondHour>=0)){
16929 		xmlReader.raiseError(tr("%1 not found").arg("Max_Beginnings_At_Second_Hour"));
16930 		delete cn;
16931 		cn=nullptr;
16932 		return nullptr;
16933 	}
16934 	assert(cn->maxBeginningsAtSecondHour>=0);
16935 	return cn;
16936 }
16937 
readStudentsSetEarly(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)16938 TimeConstraint* Rules::readStudentsSetEarly(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
16939 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetEarly"));
16940 	ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour* cn=new ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour();
16941 
16942 	cn->maxBeginningsAtSecondHour=0;
16943 
16944 	while(xmlReader.readNextStartElement()){
16945 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
16946 		if(xmlReader.name()==QString("Weight")){
16947 			//cn->weight=customFETStrToDouble(text);
16948 			xmlReader.skipCurrentElement();
16949 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
16950 			cn->weightPercentage=100;
16951 		}
16952 		else if(xmlReader.name()==QString("Weight_Percentage")){
16953 			QString text=xmlReader.readElementText();
16954 			cn->weightPercentage=customFETStrToDouble(text);
16955 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
16956 		}
16957 		else if(xmlReader.name()==QString("Active")){
16958 			QString text=xmlReader.readElementText();
16959 			if(text=="false"){
16960 				cn->active=false;
16961 			}
16962 		}
16963 		else if(xmlReader.name()==QString("Comments")){
16964 			QString text=xmlReader.readElementText();
16965 			cn->comments=text;
16966 		}
16967 		else if(xmlReader.name()==QString("Compulsory")){
16968 			QString text=xmlReader.readElementText();
16969 			if(text=="yes"){
16970 				//cn->compulsory=true;
16971 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
16972 				cn->weightPercentage=100;
16973 			}
16974 			else{
16975 				//cn->compulsory=false;
16976 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
16977 				cn->weightPercentage=0;
16978 			}
16979 		}
16980 		else if(xmlReader.name()==QString("Students")){
16981 			QString text=xmlReader.readElementText();
16982 			cn->students=text;
16983 			xmlReadingLog+="    Read students name="+cn->students+"\n";
16984 		}
16985 		else{
16986 			unrecognizedXmlTags.append(xmlReader.name().toString());
16987 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
16988 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
16989 
16990 			xmlReader.skipCurrentElement();
16991 			xmlReaderNumberOfUnrecognizedFields++;
16992 		}
16993 	}
16994 	return cn;
16995 }
16996 
readStudentsSetEarlyMaxBeginningsAtSecondHour(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)16997 TimeConstraint* Rules::readStudentsSetEarlyMaxBeginningsAtSecondHour(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
16998 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour"));
16999 	ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour* cn=new ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour();
17000 	cn->maxBeginningsAtSecondHour=-1;
17001 	while(xmlReader.readNextStartElement()){
17002 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
17003 		if(xmlReader.name()==QString("Weight")){
17004 			//cn->weight=customFETStrToDouble(text);
17005 			xmlReader.skipCurrentElement();
17006 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
17007 			cn->weightPercentage=100;
17008 		}
17009 		else if(xmlReader.name()==QString("Weight_Percentage")){
17010 			QString text=xmlReader.readElementText();
17011 			cn->weightPercentage=customFETStrToDouble(text);
17012 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
17013 		}
17014 		else if(xmlReader.name()==QString("Active")){
17015 			QString text=xmlReader.readElementText();
17016 			if(text=="false"){
17017 				cn->active=false;
17018 			}
17019 		}
17020 		else if(xmlReader.name()==QString("Comments")){
17021 			QString text=xmlReader.readElementText();
17022 			cn->comments=text;
17023 		}
17024 		else if(xmlReader.name()==QString("Max_Beginnings_At_Second_Hour")){
17025 			QString text=xmlReader.readElementText();
17026 			cn->maxBeginningsAtSecondHour=text.toInt();
17027 			if(!(cn->maxBeginningsAtSecondHour>=0)){
17028 				xmlReader.raiseError(tr("%1 is incorrect").arg("Max_Beginnings_At_Second_Hour"));
17029 				delete cn;
17030 				cn=nullptr;
17031 				return nullptr;
17032 			}
17033 			xmlReadingLog+="    Adding max beginnings at second hour="+CustomFETString::number(cn->maxBeginningsAtSecondHour)+"\n";
17034 		}
17035 		else if(xmlReader.name()==QString("Compulsory")){
17036 			QString text=xmlReader.readElementText();
17037 			if(text=="yes"){
17038 				//cn->compulsory=true;
17039 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
17040 				cn->weightPercentage=100;
17041 			}
17042 			else{
17043 				//cn->compulsory=false;
17044 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
17045 				cn->weightPercentage=0;
17046 			}
17047 		}
17048 		else if(xmlReader.name()==QString("Students")){
17049 			QString text=xmlReader.readElementText();
17050 			cn->students=text;
17051 			xmlReadingLog+="    Read students name="+cn->students+"\n";
17052 		}
17053 		else{
17054 			unrecognizedXmlTags.append(xmlReader.name().toString());
17055 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
17056 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
17057 
17058 			xmlReader.skipCurrentElement();
17059 			xmlReaderNumberOfUnrecognizedFields++;
17060 		}
17061 	}
17062 	if(!(cn->maxBeginningsAtSecondHour>=0)){
17063 		xmlReader.raiseError(tr("%1 not found").arg("Max_Beginnings_At_Second_Hour"));
17064 		delete cn;
17065 		cn=nullptr;
17066 		return nullptr;
17067 	}
17068 	assert(cn->maxBeginningsAtSecondHour>=0);
17069 	return cn;
17070 }
17071 
readActivitiesPreferredTimes(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)17072 TimeConstraint* Rules::readActivitiesPreferredTimes(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
17073 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivitiesPreferredTimes"));
17074 
17075 	ConstraintActivitiesPreferredStartingTimes* cn=new ConstraintActivitiesPreferredStartingTimes();
17076 	cn->duration=-1;
17077 	cn->nPreferredStartingTimes_L=0;
17078 	int i;
17079 	/*for(i=0; i<MAX_N_CONSTRAINT_ACTIVITIES_PREFERRED_STARTING_TIMES; i++){
17080 		cn->days[i] = cn->hours[i] = -1;
17081 	}*/
17082 	cn->teacherName="";
17083 	cn->studentsName="";
17084 	cn->subjectName="";
17085 	cn->activityTagName="";
17086 
17087 	i=0;
17088 	while(xmlReader.readNextStartElement()){
17089 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
17090 		if(xmlReader.name()==QString("Weight")){
17091 			//cn->weight=customFETStrToDouble(text);
17092 			xmlReader.skipCurrentElement();
17093 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
17094 			cn->weightPercentage=100;
17095 		}
17096 		else if(xmlReader.name()==QString("Weight_Percentage")){
17097 			QString text=xmlReader.readElementText();
17098 			cn->weightPercentage=customFETStrToDouble(text);
17099 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
17100 		}
17101 		else if(xmlReader.name()==QString("Active")){
17102 			QString text=xmlReader.readElementText();
17103 			if(text=="false"){
17104 				cn->active=false;
17105 			}
17106 		}
17107 		else if(xmlReader.name()==QString("Comments")){
17108 			QString text=xmlReader.readElementText();
17109 			cn->comments=text;
17110 		}
17111 		else if(xmlReader.name()==QString("Compulsory")){
17112 			QString text=xmlReader.readElementText();
17113 			if(text=="yes"){
17114 				//cn->compulsory=true;
17115 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
17116 				cn->weightPercentage=100;
17117 			}
17118 			else{
17119 				//cn->compulsory=false;
17120 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
17121 				cn->weightPercentage=0;
17122 			}
17123 		}
17124 		else if(xmlReader.name()==QString("Teacher_Name")){
17125 			QString text=xmlReader.readElementText();
17126 			cn->teacherName=text;
17127 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
17128 		}
17129 		else if(xmlReader.name()==QString("Students_Name")){
17130 			QString text=xmlReader.readElementText();
17131 			cn->studentsName=text;
17132 			xmlReadingLog+="    Read students name="+cn->studentsName+"\n";
17133 		}
17134 		else if(xmlReader.name()==QString("Subject_Name")){
17135 			QString text=xmlReader.readElementText();
17136 			cn->subjectName=text;
17137 			xmlReadingLog+="    Read subject name="+cn->subjectName+"\n";
17138 		}
17139 		else if(xmlReader.name()==QString("Subject_Tag_Name")){
17140 			QString text=xmlReader.readElementText();
17141 			cn->activityTagName=text;
17142 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
17143 		}
17144 		else if(xmlReader.name()==QString("Activity_Tag_Name")){
17145 			QString text=xmlReader.readElementText();
17146 			cn->activityTagName=text;
17147 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
17148 		}
17149 		else if(xmlReader.name()==QString("Number_of_Preferred_Times")){
17150 			QString text=xmlReader.readElementText();
17151 			cn->nPreferredStartingTimes_L=text.toInt();
17152 			xmlReadingLog+="    Read number of preferred times="+CustomFETString::number(cn->nPreferredStartingTimes_L)+"\n";
17153 		}
17154 		else if(xmlReader.name()==QString("Preferred_Time")){
17155 			xmlReadingLog+="    Read: preferred time\n";
17156 
17157 			assert(xmlReader.isStartElement());
17158 			while(xmlReader.readNextStartElement()){
17159 				xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
17160 				if(xmlReader.name()==QString("Preferred_Day")){
17161 					QString text=xmlReader.readElementText();
17162 					cn->days_L.append(0);
17163 					assert(cn->days_L.count()-1==i);
17164 					for(cn->days_L[i]=0; cn->days_L[i]<this->nDaysPerWeek; cn->days_L[i]++)
17165 						if(this->daysOfTheWeek[cn->days_L[i]]==text)
17166 							break;
17167 
17168 					if(cn->days_L[i]>=this->nDaysPerWeek){
17169 						xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
17170 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
17171 							tr("Constraint ActivitiesPreferredTimes day corrupt for teacher name=%1, students names=%2, subject name=%3, activity tag name=%4, day %5 is inexistent ... ignoring constraint")
17172 							.arg(cn->teacherName)
17173 							.arg(cn->studentsName)
17174 							.arg(cn->subjectName)
17175 							.arg(cn->activityTagName)
17176 							.arg(text));*/
17177 						delete cn;
17178 						cn=nullptr;
17179 						//goto corruptConstraintTime;
17180 						return nullptr;
17181 					}
17182 
17183 					assert(cn->days_L[i]<this->nDaysPerWeek);
17184 					xmlReadingLog+="    Preferred day="+this->daysOfTheWeek[cn->days_L[i]]+"("+CustomFETString::number(i)+")"+"\n";
17185 				}
17186 				else if(xmlReader.name()==QString("Preferred_Hour")){
17187 					QString text=xmlReader.readElementText();
17188 					cn->hours_L.append(0);
17189 					assert(cn->hours_L.count()-1==i);
17190 					for(cn->hours_L[i]=0; cn->hours_L[i] < this->nHoursPerDay; cn->hours_L[i]++)
17191 						if(this->hoursOfTheDay[cn->hours_L[i]]==text)
17192 							break;
17193 
17194 					if(cn->hours_L[i]>=this->nHoursPerDay){
17195 						xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
17196 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
17197 							tr("Constraint ActivitiesPreferredTimes hour corrupt for teacher name=%1, students names=%2, subject name=%3, activity tag name=%4, hour %5 is inexistent ... ignoring constraint")
17198 							.arg(cn->teacherName)
17199 							.arg(cn->studentsName)
17200 							.arg(cn->subjectName)
17201 							.arg(cn->activityTagName)
17202 							.arg(text));*/
17203 						delete cn;
17204 						cn=nullptr;
17205 						//goto corruptConstraintTime;
17206 						return nullptr;
17207 					}
17208 
17209 					assert(cn->hours_L[i]>=0 && cn->hours_L[i] < this->nHoursPerDay);
17210 					xmlReadingLog+="    Preferred hour="+this->hoursOfTheDay[cn->hours_L[i]]+"\n";
17211 				}
17212 				else{
17213 					unrecognizedXmlTags.append(xmlReader.name().toString());
17214 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
17215 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
17216 
17217 					xmlReader.skipCurrentElement();
17218 					xmlReaderNumberOfUnrecognizedFields++;
17219 				}
17220 			}
17221 
17222 			i++;
17223 
17224 			if(!(i==cn->days_L.count()) || !(i==cn->hours_L.count())){
17225 				xmlReader.raiseError(tr("%1 is incorrect").arg("Preferred_Time"));
17226 				delete cn;
17227 				cn=nullptr;
17228 				return nullptr;
17229 			}
17230 			assert(i==cn->days_L.count());
17231 			assert(i==cn->hours_L.count());
17232 		}
17233 		else{
17234 			unrecognizedXmlTags.append(xmlReader.name().toString());
17235 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
17236 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
17237 
17238 			xmlReader.skipCurrentElement();
17239 			xmlReaderNumberOfUnrecognizedFields++;
17240 		}
17241 	}
17242 	if(!(i==cn->nPreferredStartingTimes_L)){
17243 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Preferred_Times").arg("Preferred_Time"));
17244 		delete cn;
17245 		cn=nullptr;
17246 		return nullptr;
17247 	}
17248 	assert(i==cn->nPreferredStartingTimes_L);
17249 	return cn;
17250 }
17251 
readActivitiesPreferredTimeSlots(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)17252 TimeConstraint* Rules::readActivitiesPreferredTimeSlots(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
17253 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivitiesPreferredTimeSlots"));
17254 	ConstraintActivitiesPreferredTimeSlots* cn=new ConstraintActivitiesPreferredTimeSlots();
17255 	cn->duration=-1;
17256 	cn->p_nPreferredTimeSlots_L=0;
17257 	int i;
17258 	/*for(i=0; i<MAX_N_CONSTRAINT_ACTIVITIES_PREFERRED_TIME_SLOTS; i++){
17259 		cn->p_days[i] = cn->p_hours[i] = -1;
17260 	}*/
17261 	cn->p_teacherName="";
17262 	cn->p_studentsName="";
17263 	cn->p_subjectName="";
17264 	cn->p_activityTagName="";
17265 
17266 	i=0;
17267 	while(xmlReader.readNextStartElement()){
17268 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
17269 		if(xmlReader.name()==QString("Weight")){
17270 			//cn->weight=customFETStrToDouble(text);
17271 			xmlReader.skipCurrentElement();
17272 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
17273 			cn->weightPercentage=100;
17274 		}
17275 		else if(xmlReader.name()==QString("Weight_Percentage")){
17276 			QString text=xmlReader.readElementText();
17277 			cn->weightPercentage=customFETStrToDouble(text);
17278 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
17279 		}
17280 		else if(xmlReader.name()==QString("Active")){
17281 			QString text=xmlReader.readElementText();
17282 			if(text=="false"){
17283 				cn->active=false;
17284 			}
17285 		}
17286 		else if(xmlReader.name()==QString("Comments")){
17287 			QString text=xmlReader.readElementText();
17288 			cn->comments=text;
17289 		}
17290 		else if(xmlReader.name()==QString("Compulsory")){
17291 			QString text=xmlReader.readElementText();
17292 			if(text=="yes"){
17293 				//cn->compulsory=true;
17294 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
17295 				cn->weightPercentage=100;
17296 			}
17297 			else{
17298 				//cn->compulsory=false;
17299 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
17300 				cn->weightPercentage=0;
17301 			}
17302 		}
17303 		else if(xmlReader.name()==QString("Teacher_Name")){
17304 			QString text=xmlReader.readElementText();
17305 			cn->p_teacherName=text;
17306 			xmlReadingLog+="    Read teacher name="+cn->p_teacherName+"\n";
17307 		}
17308 		else if(xmlReader.name()==QString("Students_Name")){
17309 			QString text=xmlReader.readElementText();
17310 			cn->p_studentsName=text;
17311 			xmlReadingLog+="    Read students name="+cn->p_studentsName+"\n";
17312 		}
17313 		else if(xmlReader.name()==QString("Subject_Name")){
17314 			QString text=xmlReader.readElementText();
17315 			cn->p_subjectName=text;
17316 			xmlReadingLog+="    Read subject name="+cn->p_subjectName+"\n";
17317 		}
17318 		else if(xmlReader.name()==QString("Subject_Tag_Name")){
17319 			QString text=xmlReader.readElementText();
17320 			cn->p_activityTagName=text;
17321 			xmlReadingLog+="    Read activity tag name="+cn->p_activityTagName+"\n";
17322 		}
17323 		else if(xmlReader.name()==QString("Activity_Tag_Name")){
17324 			QString text=xmlReader.readElementText();
17325 			cn->p_activityTagName=text;
17326 			xmlReadingLog+="    Read activity tag name="+cn->p_activityTagName+"\n";
17327 		}
17328 		else if(xmlReader.name()==QString("Duration")){
17329 			QString text=xmlReader.readElementText();
17330 			if(!text.isEmpty()){
17331 				cn->duration=text.toInt();
17332 				xmlReadingLog+="    Read duration="+CustomFETString::number(cn->duration)+"\n";
17333 			}
17334 			else{
17335 				cn->duration=-1;
17336 			}
17337 		}
17338 		else if(xmlReader.name()==QString("Number_of_Preferred_Time_Slots")){
17339 			QString text=xmlReader.readElementText();
17340 			cn->p_nPreferredTimeSlots_L=text.toInt();
17341 			xmlReadingLog+="    Read number of preferred times="+CustomFETString::number(cn->p_nPreferredTimeSlots_L)+"\n";
17342 		}
17343 		else if(xmlReader.name()==QString("Preferred_Time_Slot")){
17344 			xmlReadingLog+="    Read: preferred time slot\n";
17345 
17346 			assert(xmlReader.isStartElement());
17347 			while(xmlReader.readNextStartElement()){
17348 				xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
17349 				if(xmlReader.name()==QString("Preferred_Day")){
17350 					QString text=xmlReader.readElementText();
17351 					cn->p_days_L.append(0);
17352 					assert(cn->p_days_L.count()-1==i);
17353 					for(cn->p_days_L[i]=0; cn->p_days_L[i]<this->nDaysPerWeek; cn->p_days_L[i]++)
17354 						if(this->daysOfTheWeek[cn->p_days_L[i]]==text)
17355 							break;
17356 
17357 					if(cn->p_days_L[i]>=this->nDaysPerWeek){
17358 						xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
17359 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
17360 							tr("Constraint ActivitiesPreferredTimeSlots day corrupt for teacher name=%1, students names=%2, subject name=%3, activity tag name=%4, day %5 is inexistent ... ignoring constraint")
17361 							.arg(cn->p_teacherName)
17362 							.arg(cn->p_studentsName)
17363 							.arg(cn->p_subjectName)
17364 							.arg(cn->p_activityTagName)
17365 							.arg(text));*/
17366 						delete cn;
17367 						cn=nullptr;
17368 						//goto corruptConstraintTime;
17369 						return nullptr;
17370 					}
17371 
17372 					assert(cn->p_days_L[i]<this->nDaysPerWeek);
17373 					xmlReadingLog+="    Preferred day="+this->daysOfTheWeek[cn->p_days_L[i]]+"("+CustomFETString::number(i)+")"+"\n";
17374 				}
17375 				else if(xmlReader.name()==QString("Preferred_Hour")){
17376 					QString text=xmlReader.readElementText();
17377 					cn->p_hours_L.append(0);
17378 					assert(cn->p_hours_L.count()-1==i);
17379 					for(cn->p_hours_L[i]=0; cn->p_hours_L[i] < this->nHoursPerDay; cn->p_hours_L[i]++)
17380 						if(this->hoursOfTheDay[cn->p_hours_L[i]]==text)
17381 							break;
17382 
17383 					if(cn->p_hours_L[i]>=this->nHoursPerDay){
17384 						xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
17385 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
17386 							tr("Constraint ActivitiesPreferredTimeSlots hour corrupt for teacher name=%1, students names=%2, subject name=%3, activity tag name=%4, hour %5 is inexistent ... ignoring constraint")
17387 							.arg(cn->p_teacherName)
17388 							.arg(cn->p_studentsName)
17389 							.arg(cn->p_subjectName)
17390 							.arg(cn->p_activityTagName)
17391 							.arg(text));*/
17392 						delete cn;
17393 						cn=nullptr;
17394 						//goto corruptConstraintTime;
17395 						return nullptr;
17396 					}
17397 
17398 					assert(cn->p_hours_L[i]>=0 && cn->p_hours_L[i] < this->nHoursPerDay);
17399 					xmlReadingLog+="    Preferred hour="+this->hoursOfTheDay[cn->p_hours_L[i]]+"\n";
17400 				}
17401 				else{
17402 					unrecognizedXmlTags.append(xmlReader.name().toString());
17403 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
17404 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
17405 
17406 					xmlReader.skipCurrentElement();
17407 					xmlReaderNumberOfUnrecognizedFields++;
17408 				}
17409 			}
17410 
17411 			i++;
17412 
17413 			if(!(i==cn->p_days_L.count()) || !(i==cn->p_hours_L.count())){
17414 				xmlReader.raiseError(tr("%1 is incorrect").arg("Preferred_Time_Slot"));
17415 				delete cn;
17416 				cn=nullptr;
17417 				return nullptr;
17418 			}
17419 			assert(i==cn->p_days_L.count());
17420 			assert(i==cn->p_hours_L.count());
17421 		}
17422 		else{
17423 			unrecognizedXmlTags.append(xmlReader.name().toString());
17424 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
17425 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
17426 
17427 			xmlReader.skipCurrentElement();
17428 			xmlReaderNumberOfUnrecognizedFields++;
17429 		}
17430 	}
17431 	if(!(i==cn->p_nPreferredTimeSlots_L)){
17432 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Preferred_Time_Slots").arg("Preferred_Time_Slot"));
17433 		delete cn;
17434 		cn=nullptr;
17435 		return nullptr;
17436 	}
17437 	assert(i==cn->p_nPreferredTimeSlots_L);
17438 	return cn;
17439 }
17440 
readActivitiesPreferredStartingTimes(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)17441 TimeConstraint* Rules::readActivitiesPreferredStartingTimes(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
17442 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivitiesPreferredStartingTimes"));
17443 	ConstraintActivitiesPreferredStartingTimes* cn=new ConstraintActivitiesPreferredStartingTimes();
17444 	cn->duration=-1;
17445 	cn->nPreferredStartingTimes_L=0;
17446 	int i;
17447 	/*for(i=0; i<MAX_N_CONSTRAINT_ACTIVITIES_PREFERRED_STARTING_TIMES; i++){
17448 		cn->days[i] = cn->hours[i] = -1;
17449 	}*/
17450 	cn->teacherName="";
17451 	cn->studentsName="";
17452 	cn->subjectName="";
17453 	cn->activityTagName="";
17454 
17455 	i=0;
17456 	while(xmlReader.readNextStartElement()){
17457 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
17458 		if(xmlReader.name()==QString("Weight")){
17459 			//cn->weight=customFETStrToDouble(text);
17460 			xmlReader.skipCurrentElement();
17461 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
17462 			cn->weightPercentage=100;
17463 		}
17464 		else if(xmlReader.name()==QString("Weight_Percentage")){
17465 			QString text=xmlReader.readElementText();
17466 			cn->weightPercentage=customFETStrToDouble(text);
17467 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
17468 		}
17469 		else if(xmlReader.name()==QString("Active")){
17470 			QString text=xmlReader.readElementText();
17471 			if(text=="false"){
17472 				cn->active=false;
17473 			}
17474 		}
17475 		else if(xmlReader.name()==QString("Comments")){
17476 			QString text=xmlReader.readElementText();
17477 			cn->comments=text;
17478 		}
17479 		else if(xmlReader.name()==QString("Compulsory")){
17480 			QString text=xmlReader.readElementText();
17481 			if(text=="yes"){
17482 				//cn->compulsory=true;
17483 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
17484 				cn->weightPercentage=100;
17485 			}
17486 			else{
17487 				//cn->compulsory=false;
17488 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
17489 				cn->weightPercentage=0;
17490 			}
17491 		}
17492 		else if(xmlReader.name()==QString("Teacher_Name")){
17493 			QString text=xmlReader.readElementText();
17494 			cn->teacherName=text;
17495 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
17496 		}
17497 		else if(xmlReader.name()==QString("Students_Name")){
17498 			QString text=xmlReader.readElementText();
17499 			cn->studentsName=text;
17500 			xmlReadingLog+="    Read students name="+cn->studentsName+"\n";
17501 		}
17502 		else if(xmlReader.name()==QString("Subject_Name")){
17503 			QString text=xmlReader.readElementText();
17504 			cn->subjectName=text;
17505 			xmlReadingLog+="    Read subject name="+cn->subjectName+"\n";
17506 		}
17507 		else if(xmlReader.name()==QString("Subject_Tag_Name")){
17508 			QString text=xmlReader.readElementText();
17509 			cn->activityTagName=text;
17510 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
17511 		}
17512 		else if(xmlReader.name()==QString("Activity_Tag_Name")){
17513 			QString text=xmlReader.readElementText();
17514 			cn->activityTagName=text;
17515 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
17516 		}
17517 		else if(xmlReader.name()==QString("Duration")){
17518 			QString text=xmlReader.readElementText();
17519 			if(!text.isEmpty()){
17520 				cn->duration=text.toInt();
17521 				xmlReadingLog+="    Read duration="+CustomFETString::number(cn->duration)+"\n";
17522 			}
17523 			else{
17524 				cn->duration=-1;
17525 			}
17526 		}
17527 		else if(xmlReader.name()==QString("Number_of_Preferred_Starting_Times")){
17528 			QString text=xmlReader.readElementText();
17529 			cn->nPreferredStartingTimes_L=text.toInt();
17530 			xmlReadingLog+="    Read number of preferred starting times="+CustomFETString::number(cn->nPreferredStartingTimes_L)+"\n";
17531 		}
17532 		else if(xmlReader.name()==QString("Preferred_Starting_Time")){
17533 			xmlReadingLog+="    Read: preferred starting time\n";
17534 
17535 			assert(xmlReader.isStartElement());
17536 			while(xmlReader.readNextStartElement()){
17537 				xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
17538 				if(xmlReader.name()==QString("Preferred_Starting_Day")){
17539 					QString text=xmlReader.readElementText();
17540 					cn->days_L.append(0);
17541 					assert(cn->days_L.count()-1==i);
17542 					for(cn->days_L[i]=0; cn->days_L[i]<this->nDaysPerWeek; cn->days_L[i]++)
17543 						if(this->daysOfTheWeek[cn->days_L[i]]==text)
17544 							break;
17545 
17546 					if(cn->days_L[i]>=this->nDaysPerWeek){
17547 						xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
17548 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
17549 							tr("Constraint ActivitiesPreferredStartingTimes day corrupt for teacher name=%1, students names=%2, subject name=%3, activity tag name=%4, day %5 is inexistent ... ignoring constraint")
17550 							.arg(cn->teacherName)
17551 							.arg(cn->studentsName)
17552 							.arg(cn->subjectName)
17553 							.arg(cn->activityTagName)
17554 							.arg(text));*/
17555 						delete cn;
17556 						cn=nullptr;
17557 						//goto corruptConstraintTime;
17558 						return nullptr;
17559 					}
17560 
17561 					assert(cn->days_L[i]<this->nDaysPerWeek);
17562 					xmlReadingLog+="    Preferred starting day="+this->daysOfTheWeek[cn->days_L[i]]+"("+CustomFETString::number(i)+")"+"\n";
17563 				}
17564 				else if(xmlReader.name()==QString("Preferred_Starting_Hour")){
17565 					QString text=xmlReader.readElementText();
17566 					cn->hours_L.append(0);
17567 					assert(cn->hours_L.count()-1==i);
17568 					for(cn->hours_L[i]=0; cn->hours_L[i] < this->nHoursPerDay; cn->hours_L[i]++)
17569 						if(this->hoursOfTheDay[cn->hours_L[i]]==text)
17570 							break;
17571 
17572 					if(cn->hours_L[i]>=this->nHoursPerDay){
17573 						xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
17574 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
17575 							tr("Constraint ActivitiesPreferredStartingTimes hour corrupt for teacher name=%1, students names=%2, subject name=%3, activity tag name=%4, hour %5 is inexistent ... ignoring constraint")
17576 							.arg(cn->teacherName)
17577 							.arg(cn->studentsName)
17578 							.arg(cn->subjectName)
17579 							.arg(cn->activityTagName)
17580 							.arg(text));*/
17581 						delete cn;
17582 						cn=nullptr;
17583 						//goto corruptConstraintTime;
17584 						return nullptr;
17585 					}
17586 
17587 					assert(cn->hours_L[i]>=0 && cn->hours_L[i] < this->nHoursPerDay);
17588 					xmlReadingLog+="    Preferred starting hour="+this->hoursOfTheDay[cn->hours_L[i]]+"\n";
17589 				}
17590 				else{
17591 					unrecognizedXmlTags.append(xmlReader.name().toString());
17592 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
17593 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
17594 
17595 					xmlReader.skipCurrentElement();
17596 					xmlReaderNumberOfUnrecognizedFields++;
17597 				}
17598 			}
17599 
17600 			i++;
17601 
17602 			if(!(i==cn->days_L.count()) || !(i==cn->hours_L.count())){
17603 				xmlReader.raiseError(tr("%1 is incorrect").arg("Preferred_Starting_Time"));
17604 				delete cn;
17605 				cn=nullptr;
17606 				return nullptr;
17607 			}
17608 			assert(i==cn->days_L.count());
17609 			assert(i==cn->hours_L.count());
17610 		}
17611 		else{
17612 			unrecognizedXmlTags.append(xmlReader.name().toString());
17613 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
17614 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
17615 
17616 			xmlReader.skipCurrentElement();
17617 			xmlReaderNumberOfUnrecognizedFields++;
17618 		}
17619 	}
17620 	if(!(i==cn->nPreferredStartingTimes_L)){
17621 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Preferred_Starting_Times").arg("Preferred_Starting_Time"));
17622 		delete cn;
17623 		cn=nullptr;
17624 		return nullptr;
17625 	}
17626 	assert(i==cn->nPreferredStartingTimes_L);
17627 	return cn;
17628 }
17629 
17630 ////////////////
readSubactivitiesPreferredTimeSlots(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)17631 TimeConstraint* Rules::readSubactivitiesPreferredTimeSlots(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
17632 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintSubactivitiesPreferredTimeSlots"));
17633 	ConstraintSubactivitiesPreferredTimeSlots* cn=new ConstraintSubactivitiesPreferredTimeSlots();
17634 	cn->duration=-1;
17635 	cn->p_nPreferredTimeSlots_L=0;
17636 	cn->componentNumber=0;
17637 	int i;
17638 	/*for(i=0; i<MAX_N_CONSTRAINT_SUBACTIVITIES_PREFERRED_TIME_SLOTS; i++){
17639 		cn->p_days[i] = cn->p_hours[i] = -1;
17640 	}*/
17641 	cn->p_teacherName="";
17642 	cn->p_studentsName="";
17643 	cn->p_subjectName="";
17644 	cn->p_activityTagName="";
17645 
17646 	i=0;
17647 	while(xmlReader.readNextStartElement()){
17648 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
17649 		if(xmlReader.name()==QString("Weight")){
17650 			//cn->weight=customFETStrToDouble(text);
17651 			xmlReader.skipCurrentElement();
17652 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
17653 			cn->weightPercentage=100;
17654 		}
17655 		else if(xmlReader.name()==QString("Weight_Percentage")){
17656 			QString text=xmlReader.readElementText();
17657 			cn->weightPercentage=customFETStrToDouble(text);
17658 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
17659 		}
17660 		else if(xmlReader.name()==QString("Active")){
17661 			QString text=xmlReader.readElementText();
17662 			if(text=="false"){
17663 				cn->active=false;
17664 			}
17665 		}
17666 		else if(xmlReader.name()==QString("Comments")){
17667 			QString text=xmlReader.readElementText();
17668 			cn->comments=text;
17669 		}
17670 		else if(xmlReader.name()==QString("Component_Number")){
17671 			QString text=xmlReader.readElementText();
17672 			cn->componentNumber=text.toInt();
17673 			xmlReadingLog+="    Adding component number="+CustomFETString::number(cn->componentNumber)+"\n";
17674 		}
17675 		else if(xmlReader.name()==QString("Compulsory")){
17676 			QString text=xmlReader.readElementText();
17677 			if(text=="yes"){
17678 				//cn->compulsory=true;
17679 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
17680 				cn->weightPercentage=100;
17681 			}
17682 			else{
17683 				//cn->compulsory=false;
17684 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
17685 				cn->weightPercentage=0;
17686 			}
17687 		}
17688 		else if(xmlReader.name()==QString("Teacher_Name")){
17689 			QString text=xmlReader.readElementText();
17690 			cn->p_teacherName=text;
17691 			xmlReadingLog+="    Read teacher name="+cn->p_teacherName+"\n";
17692 		}
17693 		else if(xmlReader.name()==QString("Students_Name")){
17694 			QString text=xmlReader.readElementText();
17695 			cn->p_studentsName=text;
17696 			xmlReadingLog+="    Read students name="+cn->p_studentsName+"\n";
17697 		}
17698 		else if(xmlReader.name()==QString("Subject_Name")){
17699 			QString text=xmlReader.readElementText();
17700 			cn->p_subjectName=text;
17701 			xmlReadingLog+="    Read subject name="+cn->p_subjectName+"\n";
17702 		}
17703 		else if(xmlReader.name()==QString("Subject_Tag_Name")){
17704 			QString text=xmlReader.readElementText();
17705 			cn->p_activityTagName=text;
17706 			xmlReadingLog+="    Read activity tag name="+cn->p_activityTagName+"\n";
17707 		}
17708 		else if(xmlReader.name()==QString("Activity_Tag_Name")){
17709 			QString text=xmlReader.readElementText();
17710 			cn->p_activityTagName=text;
17711 			xmlReadingLog+="    Read activity tag name="+cn->p_activityTagName+"\n";
17712 		}
17713 		else if(xmlReader.name()==QString("Duration")){
17714 			QString text=xmlReader.readElementText();
17715 			if(!text.isEmpty()){
17716 				cn->duration=text.toInt();
17717 				xmlReadingLog+="    Read duration="+CustomFETString::number(cn->duration)+"\n";
17718 			}
17719 			else{
17720 				cn->duration=-1;
17721 			}
17722 		}
17723 		else if(xmlReader.name()==QString("Number_of_Preferred_Time_Slots")){
17724 			QString text=xmlReader.readElementText();
17725 			cn->p_nPreferredTimeSlots_L=text.toInt();
17726 			xmlReadingLog+="    Read number of preferred times="+CustomFETString::number(cn->p_nPreferredTimeSlots_L)+"\n";
17727 		}
17728 		else if(xmlReader.name()==QString("Preferred_Time_Slot")){
17729 			xmlReadingLog+="    Read: preferred time slot\n";
17730 
17731 			assert(xmlReader.isStartElement());
17732 			while(xmlReader.readNextStartElement()){
17733 				xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
17734 				if(xmlReader.name()==QString("Preferred_Day")){
17735 					QString text=xmlReader.readElementText();
17736 					cn->p_days_L.append(0);
17737 					assert(cn->p_days_L.count()-1==i);
17738 					for(cn->p_days_L[i]=0; cn->p_days_L[i]<this->nDaysPerWeek; cn->p_days_L[i]++)
17739 						if(this->daysOfTheWeek[cn->p_days_L[i]]==text)
17740 							break;
17741 
17742 					if(cn->p_days_L[i]>=this->nDaysPerWeek){
17743 						xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
17744 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
17745 							tr("Constraint ActivitiesPreferredTimeSlots day corrupt for teacher name=%1, students names=%2, subject name=%3, activity tag name=%4, day %5 is inexistent ... ignoring constraint")
17746 							.arg(cn->p_teacherName)
17747 							.arg(cn->p_studentsName)
17748 							.arg(cn->p_subjectName)
17749 							.arg(cn->p_activityTagName)
17750 							.arg(text));*/
17751 						delete cn;
17752 						cn=nullptr;
17753 						//goto corruptConstraintTime;
17754 						return nullptr;
17755 					}
17756 
17757 					assert(cn->p_days_L[i]<this->nDaysPerWeek);
17758 					xmlReadingLog+="    Preferred day="+this->daysOfTheWeek[cn->p_days_L[i]]+"("+CustomFETString::number(i)+")"+"\n";
17759 				}
17760 				else if(xmlReader.name()==QString("Preferred_Hour")){
17761 					QString text=xmlReader.readElementText();
17762 					cn->p_hours_L.append(0);
17763 					assert(cn->p_hours_L.count()-1==i);
17764 					for(cn->p_hours_L[i]=0; cn->p_hours_L[i] < this->nHoursPerDay; cn->p_hours_L[i]++)
17765 						if(this->hoursOfTheDay[cn->p_hours_L[i]]==text)
17766 							break;
17767 
17768 					if(cn->p_hours_L[i]>=this->nHoursPerDay){
17769 						xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
17770 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
17771 							tr("Constraint ActivitiesPreferredTimeSlots hour corrupt for teacher name=%1, students names=%2, subject name=%3, activity tag name=%4, hour %5 is inexistent ... ignoring constraint")
17772 							.arg(cn->p_teacherName)
17773 							.arg(cn->p_studentsName)
17774 							.arg(cn->p_subjectName)
17775 							.arg(cn->p_activityTagName)
17776 							.arg(text));*/
17777 						delete cn;
17778 						cn=nullptr;
17779 						//goto corruptConstraintTime;
17780 						return nullptr;
17781 					}
17782 
17783 					assert(cn->p_hours_L[i]>=0 && cn->p_hours_L[i] < this->nHoursPerDay);
17784 					xmlReadingLog+="    Preferred hour="+this->hoursOfTheDay[cn->p_hours_L[i]]+"\n";
17785 				}
17786 				else{
17787 					unrecognizedXmlTags.append(xmlReader.name().toString());
17788 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
17789 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
17790 
17791 					xmlReader.skipCurrentElement();
17792 					xmlReaderNumberOfUnrecognizedFields++;
17793 				}
17794 			}
17795 
17796 			i++;
17797 
17798 			if(!(i==cn->p_days_L.count()) || !(i==cn->p_hours_L.count())){
17799 				xmlReader.raiseError(tr("%1 is incorrect").arg("Preferred_Time_Slot"));
17800 				delete cn;
17801 				cn=nullptr;
17802 				return nullptr;
17803 			}
17804 			assert(i==cn->p_days_L.count());
17805 			assert(i==cn->p_hours_L.count());
17806 		}
17807 		else{
17808 			unrecognizedXmlTags.append(xmlReader.name().toString());
17809 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
17810 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
17811 
17812 			xmlReader.skipCurrentElement();
17813 			xmlReaderNumberOfUnrecognizedFields++;
17814 		}
17815 	}
17816 	if(!(i==cn->p_nPreferredTimeSlots_L)){
17817 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Preferred_Time_Slots").arg("Preferred_Time_Slot"));
17818 		delete cn;
17819 		cn=nullptr;
17820 		return nullptr;
17821 	}
17822 	assert(i==cn->p_nPreferredTimeSlots_L);
17823 	return cn;
17824 }
17825 
readSubactivitiesPreferredStartingTimes(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)17826 TimeConstraint* Rules::readSubactivitiesPreferredStartingTimes(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
17827 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintSubactivitiesPreferredStartingTimes"));
17828 	ConstraintSubactivitiesPreferredStartingTimes* cn=new ConstraintSubactivitiesPreferredStartingTimes();
17829 	cn->duration=-1;
17830 	cn->nPreferredStartingTimes_L=0;
17831 	cn->componentNumber=0;
17832 	int i;
17833 	/*for(i=0; i<MAX_N_CONSTRAINT_SUBACTIVITIES_PREFERRED_STARTING_TIMES; i++){
17834 		cn->days[i] = cn->hours[i] = -1;
17835 	}*/
17836 	cn->teacherName="";
17837 	cn->studentsName="";
17838 	cn->subjectName="";
17839 	cn->activityTagName="";
17840 
17841 	i=0;
17842 	while(xmlReader.readNextStartElement()){
17843 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
17844 		if(xmlReader.name()==QString("Weight")){
17845 			//cn->weight=customFETStrToDouble(text);
17846 			xmlReader.skipCurrentElement();
17847 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
17848 			cn->weightPercentage=100;
17849 		}
17850 		else if(xmlReader.name()==QString("Weight_Percentage")){
17851 			QString text=xmlReader.readElementText();
17852 			cn->weightPercentage=customFETStrToDouble(text);
17853 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
17854 		}
17855 		else if(xmlReader.name()==QString("Active")){
17856 			QString text=xmlReader.readElementText();
17857 			if(text=="false"){
17858 				cn->active=false;
17859 			}
17860 		}
17861 		else if(xmlReader.name()==QString("Comments")){
17862 			QString text=xmlReader.readElementText();
17863 			cn->comments=text;
17864 		}
17865 		else if(xmlReader.name()==QString("Component_Number")){
17866 			QString text=xmlReader.readElementText();
17867 			cn->componentNumber=text.toInt();
17868 			xmlReadingLog+="    Adding component number="+CustomFETString::number(cn->componentNumber)+"\n";
17869 		}
17870 		else if(xmlReader.name()==QString("Compulsory")){
17871 			QString text=xmlReader.readElementText();
17872 			if(text=="yes"){
17873 				//cn->compulsory=true;
17874 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
17875 				cn->weightPercentage=100;
17876 			}
17877 			else{
17878 				//cn->compulsory=false;
17879 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
17880 				cn->weightPercentage=0;
17881 			}
17882 		}
17883 		else if(xmlReader.name()==QString("Teacher_Name")){
17884 			QString text=xmlReader.readElementText();
17885 			cn->teacherName=text;
17886 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
17887 		}
17888 		else if(xmlReader.name()==QString("Students_Name")){
17889 			QString text=xmlReader.readElementText();
17890 			cn->studentsName=text;
17891 			xmlReadingLog+="    Read students name="+cn->studentsName+"\n";
17892 		}
17893 		else if(xmlReader.name()==QString("Subject_Name")){
17894 			QString text=xmlReader.readElementText();
17895 			cn->subjectName=text;
17896 			xmlReadingLog+="    Read subject name="+cn->subjectName+"\n";
17897 		}
17898 		else if(xmlReader.name()==QString("Subject_Tag_Name")){
17899 			QString text=xmlReader.readElementText();
17900 			cn->activityTagName=text;
17901 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
17902 		}
17903 		else if(xmlReader.name()==QString("Activity_Tag_Name")){
17904 			QString text=xmlReader.readElementText();
17905 			cn->activityTagName=text;
17906 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
17907 		}
17908 		else if(xmlReader.name()==QString("Duration")){
17909 			QString text=xmlReader.readElementText();
17910 			if(!text.isEmpty()){
17911 				cn->duration=text.toInt();
17912 				xmlReadingLog+="    Read duration="+CustomFETString::number(cn->duration)+"\n";
17913 			}
17914 			else{
17915 				cn->duration=-1;
17916 			}
17917 		}
17918 		else if(xmlReader.name()==QString("Number_of_Preferred_Starting_Times")){
17919 			QString text=xmlReader.readElementText();
17920 			cn->nPreferredStartingTimes_L=text.toInt();
17921 			xmlReadingLog+="    Read number of preferred starting times="+CustomFETString::number(cn->nPreferredStartingTimes_L)+"\n";
17922 		}
17923 		else if(xmlReader.name()==QString("Preferred_Starting_Time")){
17924 			xmlReadingLog+="    Read: preferred starting time\n";
17925 
17926 			assert(xmlReader.isStartElement());
17927 			while(xmlReader.readNextStartElement()){
17928 				xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
17929 				if(xmlReader.name()==QString("Preferred_Starting_Day")){
17930 					QString text=xmlReader.readElementText();
17931 					cn->days_L.append(0);
17932 					assert(cn->days_L.count()-1==i);
17933 					for(cn->days_L[i]=0; cn->days_L[i]<this->nDaysPerWeek; cn->days_L[i]++)
17934 						if(this->daysOfTheWeek[cn->days_L[i]]==text)
17935 							break;
17936 
17937 					if(cn->days_L[i]>=this->nDaysPerWeek){
17938 						xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
17939 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
17940 							tr("Constraint ActivitiesPreferredStartingTimes day corrupt for teacher name=%1, students names=%2, subject name=%3, activity tag name=%4, day %5 is inexistent ... ignoring constraint")
17941 							.arg(cn->teacherName)
17942 							.arg(cn->studentsName)
17943 							.arg(cn->subjectName)
17944 							.arg(cn->activityTagName)
17945 							.arg(text));*/
17946 						delete cn;
17947 						cn=nullptr;
17948 						//goto corruptConstraintTime;
17949 						return nullptr;
17950 					}
17951 
17952 					assert(cn->days_L[i]<this->nDaysPerWeek);
17953 					xmlReadingLog+="    Preferred starting day="+this->daysOfTheWeek[cn->days_L[i]]+"("+CustomFETString::number(i)+")"+"\n";
17954 				}
17955 				else if(xmlReader.name()==QString("Preferred_Starting_Hour")){
17956 					QString text=xmlReader.readElementText();
17957 					cn->hours_L.append(0);
17958 					assert(cn->hours_L.count()-1==i);
17959 					for(cn->hours_L[i]=0; cn->hours_L[i] < this->nHoursPerDay; cn->hours_L[i]++)
17960 						if(this->hoursOfTheDay[cn->hours_L[i]]==text)
17961 							break;
17962 
17963 					if(cn->hours_L[i]>=this->nHoursPerDay){
17964 						xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
17965 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
17966 							tr("Constraint ActivitiesPreferredStartingTimes hour corrupt for teacher name=%1, students names=%2, subject name=%3, activity tag name=%4, hour %5 is inexistent ... ignoring constraint")
17967 							.arg(cn->teacherName)
17968 							.arg(cn->studentsName)
17969 							.arg(cn->subjectName)
17970 							.arg(cn->activityTagName)
17971 							.arg(text));*/
17972 						delete cn;
17973 						cn=nullptr;
17974 						//goto corruptConstraintTime;
17975 						return nullptr;
17976 					}
17977 
17978 					assert(cn->hours_L[i]>=0 && cn->hours_L[i] < this->nHoursPerDay);
17979 					xmlReadingLog+="    Preferred starting hour="+this->hoursOfTheDay[cn->hours_L[i]]+"\n";
17980 				}
17981 				else{
17982 					unrecognizedXmlTags.append(xmlReader.name().toString());
17983 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
17984 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
17985 
17986 					xmlReader.skipCurrentElement();
17987 					xmlReaderNumberOfUnrecognizedFields++;
17988 				}
17989 			}
17990 
17991 			i++;
17992 
17993 			if(!(i==cn->days_L.count()) || !(i==cn->hours_L.count())){
17994 				xmlReader.raiseError(tr("%1 is incorrect").arg("Preferred_Starting_Time"));
17995 				delete cn;
17996 				cn=nullptr;
17997 				return nullptr;
17998 			}
17999 			assert(i==cn->days_L.count());
18000 			assert(i==cn->hours_L.count());
18001 		}
18002 		else{
18003 			unrecognizedXmlTags.append(xmlReader.name().toString());
18004 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
18005 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
18006 
18007 			xmlReader.skipCurrentElement();
18008 			xmlReaderNumberOfUnrecognizedFields++;
18009 		}
18010 	}
18011 	if(!(i==cn->nPreferredStartingTimes_L)){
18012 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Preferred_Starting_Times").arg("Preferred_Starting_Time"));
18013 		delete cn;
18014 		cn=nullptr;
18015 		return nullptr;
18016 	}
18017 	assert(i==cn->nPreferredStartingTimes_L);
18018 	return cn;
18019 }
18020 
18021 //2011-09-25
readActivitiesOccupyMaxTimeSlotsFromSelection(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)18022 TimeConstraint* Rules::readActivitiesOccupyMaxTimeSlotsFromSelection(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
18023 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivitiesOccupyMaxTimeSlotsFromSelection"));
18024 	ConstraintActivitiesOccupyMaxTimeSlotsFromSelection* cn=new ConstraintActivitiesOccupyMaxTimeSlotsFromSelection();
18025 
18026 	int ac=0;
18027 	int tsc=0;
18028 	int i=0;
18029 
18030 	while(xmlReader.readNextStartElement()){
18031 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
18032 
18033 		if(xmlReader.name()==QString("Weight_Percentage")){
18034 			QString text=xmlReader.readElementText();
18035 			cn->weightPercentage=customFETStrToDouble(text);
18036 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
18037 		}
18038 		else if(xmlReader.name()==QString("Active")){
18039 			QString text=xmlReader.readElementText();
18040 			if(text=="false"){
18041 				cn->active=false;
18042 			}
18043 		}
18044 		else if(xmlReader.name()==QString("Comments")){
18045 			QString text=xmlReader.readElementText();
18046 			cn->comments=text;
18047 		}
18048 		else if(xmlReader.name()==QString("Number_of_Activities")){
18049 			QString text=xmlReader.readElementText();
18050 			ac=text.toInt();
18051 			xmlReadingLog+="    Read number of activities="+CustomFETString::number(ac)+"\n";
18052 		}
18053 		else if(xmlReader.name()==QString("Activity_Id")){
18054 			QString text=xmlReader.readElementText();
18055 			cn->activitiesIds.append(text.toInt());
18056 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activitiesIds[cn->activitiesIds.count()-1])+"\n";
18057 		}
18058 		else if(xmlReader.name()==QString("Number_of_Selected_Time_Slots")){
18059 			QString text=xmlReader.readElementText();
18060 			tsc=text.toInt();
18061 			xmlReadingLog+="    Read number of selected time slots="+CustomFETString::number(tsc)+"\n";
18062 		}
18063 		else if(xmlReader.name()==QString("Selected_Time_Slot")){
18064 			xmlReadingLog+="    Read: selected time slot\n";
18065 
18066 			assert(xmlReader.isStartElement());
18067 			while(xmlReader.readNextStartElement()){
18068 				xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
18069 				if(xmlReader.name()==QString("Selected_Day")){
18070 					QString text=xmlReader.readElementText();
18071 					cn->selectedDays.append(0);
18072 					assert(cn->selectedDays.count()-1==i);
18073 					for(cn->selectedDays[i]=0; cn->selectedDays[i]<this->nDaysPerWeek; cn->selectedDays[i]++)
18074 						if(this->daysOfTheWeek[cn->selectedDays[i]]==text)
18075 							break;
18076 
18077 					if(cn->selectedDays[i]>=this->nDaysPerWeek){
18078 						xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
18079 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
18080 							tr("Constraint ActivitiesOccupyMaxTimeSlotsFromSelection day corrupt, day %1 is inexistent ... ignoring constraint")
18081 							.arg(text));*/
18082 						delete cn;
18083 						cn=nullptr;
18084 						//goto corruptConstraintTime;
18085 						return nullptr;
18086 					}
18087 
18088 					assert(cn->selectedDays[i]<this->nDaysPerWeek);
18089 					xmlReadingLog+="    Selected day="+this->daysOfTheWeek[cn->selectedDays[i]]+"("+CustomFETString::number(i)+")"+"\n";
18090 				}
18091 				else if(xmlReader.name()==QString("Selected_Hour")){
18092 					QString text=xmlReader.readElementText();
18093 					cn->selectedHours.append(0);
18094 					assert(cn->selectedHours.count()-1==i);
18095 					for(cn->selectedHours[i]=0; cn->selectedHours[i] < this->nHoursPerDay; cn->selectedHours[i]++)
18096 						if(this->hoursOfTheDay[cn->selectedHours[i]]==text)
18097 							break;
18098 
18099 					if(cn->selectedHours[i]>=this->nHoursPerDay){
18100 						xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
18101 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
18102 							tr(" Constraint ActivitiesOccupyMaxTimeSlotsFromSelection hour corrupt, hour %1 is inexistent ... ignoring constraint")
18103 							.arg(text));*/
18104 						delete cn;
18105 						cn=nullptr;
18106 						//goto corruptConstraintTime;
18107 						return nullptr;
18108 					}
18109 
18110 					assert(cn->selectedHours[i]>=0 && cn->selectedHours[i] < this->nHoursPerDay);
18111 					xmlReadingLog+="    Selected hour="+this->hoursOfTheDay[cn->selectedHours[i]]+"\n";
18112 				}
18113 				else{
18114 					unrecognizedXmlTags.append(xmlReader.name().toString());
18115 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
18116 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
18117 
18118 					xmlReader.skipCurrentElement();
18119 					xmlReaderNumberOfUnrecognizedFields++;
18120 				}
18121 			}
18122 
18123 			i++;
18124 
18125 			if(!(i==cn->selectedDays.count()) || !(i==cn->selectedHours.count())){
18126 				xmlReader.raiseError(tr("%1 is incorrect").arg("Selected_Time_Slot"));
18127 				delete cn;
18128 				cn=nullptr;
18129 				return nullptr;
18130 			}
18131 			assert(i==cn->selectedDays.count());
18132 			assert(i==cn->selectedHours.count());
18133 		}
18134 		else if(xmlReader.name()==QString("Max_Number_of_Occupied_Time_Slots")){
18135 			QString text=xmlReader.readElementText();
18136 			cn->maxOccupiedTimeSlots=text.toInt();
18137 			xmlReadingLog+="    Read max number of occupied time slots="+CustomFETString::number(cn->maxOccupiedTimeSlots)+"\n";
18138 		}
18139 		else{
18140 			unrecognizedXmlTags.append(xmlReader.name().toString());
18141 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
18142 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
18143 
18144 			xmlReader.skipCurrentElement();
18145 			xmlReaderNumberOfUnrecognizedFields++;
18146 		}
18147 	}
18148 
18149 	if(!(ac==cn->activitiesIds.count())){
18150 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Activities").arg("Activity_Id"));
18151 		delete cn;
18152 		cn=nullptr;
18153 		return nullptr;
18154 	}
18155 
18156 	if(!(i==tsc)){
18157 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Selected_Time_Slots").arg("Selected_Time_Slot"));
18158 		delete cn;
18159 		cn=nullptr;
18160 		return nullptr;
18161 	}
18162 
18163 	assert(ac==cn->activitiesIds.count());
18164 	assert(i==tsc);
18165 	return cn;
18166 }
18167 ////////////////
18168 
18169 //2019-11-16
readActivitiesOccupyMinTimeSlotsFromSelection(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)18170 TimeConstraint* Rules::readActivitiesOccupyMinTimeSlotsFromSelection(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
18171 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivitiesOccupyMinTimeSlotsFromSelection"));
18172 	ConstraintActivitiesOccupyMinTimeSlotsFromSelection* cn=new ConstraintActivitiesOccupyMinTimeSlotsFromSelection();
18173 
18174 	int ac=0;
18175 	int tsc=0;
18176 	int i=0;
18177 
18178 	while(xmlReader.readNextStartElement()){
18179 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
18180 
18181 		if(xmlReader.name()==QString("Weight_Percentage")){
18182 			QString text=xmlReader.readElementText();
18183 			cn->weightPercentage=customFETStrToDouble(text);
18184 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
18185 		}
18186 		else if(xmlReader.name()==QString("Active")){
18187 			QString text=xmlReader.readElementText();
18188 			if(text=="false"){
18189 				cn->active=false;
18190 			}
18191 		}
18192 		else if(xmlReader.name()==QString("Comments")){
18193 			QString text=xmlReader.readElementText();
18194 			cn->comments=text;
18195 		}
18196 		else if(xmlReader.name()==QString("Number_of_Activities")){
18197 			QString text=xmlReader.readElementText();
18198 			ac=text.toInt();
18199 			xmlReadingLog+="    Read number of activities="+CustomFETString::number(ac)+"\n";
18200 		}
18201 		else if(xmlReader.name()==QString("Activity_Id")){
18202 			QString text=xmlReader.readElementText();
18203 			cn->activitiesIds.append(text.toInt());
18204 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activitiesIds[cn->activitiesIds.count()-1])+"\n";
18205 		}
18206 		else if(xmlReader.name()==QString("Number_of_Selected_Time_Slots")){
18207 			QString text=xmlReader.readElementText();
18208 			tsc=text.toInt();
18209 			xmlReadingLog+="    Read number of selected time slots="+CustomFETString::number(tsc)+"\n";
18210 		}
18211 		else if(xmlReader.name()==QString("Selected_Time_Slot")){
18212 			xmlReadingLog+="    Read: selected time slot\n";
18213 
18214 			assert(xmlReader.isStartElement());
18215 			while(xmlReader.readNextStartElement()){
18216 				xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
18217 				if(xmlReader.name()==QString("Selected_Day")){
18218 					QString text=xmlReader.readElementText();
18219 					cn->selectedDays.append(0);
18220 					assert(cn->selectedDays.count()-1==i);
18221 					for(cn->selectedDays[i]=0; cn->selectedDays[i]<this->nDaysPerWeek; cn->selectedDays[i]++)
18222 						if(this->daysOfTheWeek[cn->selectedDays[i]]==text)
18223 							break;
18224 
18225 					if(cn->selectedDays[i]>=this->nDaysPerWeek){
18226 						xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
18227 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
18228 							tr("Constraint ActivitiesOccupyMinTimeSlotsFromSelection day corrupt, day %1 is inexistent ... ignoring constraint")
18229 							.arg(text));*/
18230 						delete cn;
18231 						cn=nullptr;
18232 						//goto corruptConstraintTime;
18233 						return nullptr;
18234 					}
18235 
18236 					assert(cn->selectedDays[i]<this->nDaysPerWeek);
18237 					xmlReadingLog+="    Selected day="+this->daysOfTheWeek[cn->selectedDays[i]]+"("+CustomFETString::number(i)+")"+"\n";
18238 				}
18239 				else if(xmlReader.name()==QString("Selected_Hour")){
18240 					QString text=xmlReader.readElementText();
18241 					cn->selectedHours.append(0);
18242 					assert(cn->selectedHours.count()-1==i);
18243 					for(cn->selectedHours[i]=0; cn->selectedHours[i] < this->nHoursPerDay; cn->selectedHours[i]++)
18244 						if(this->hoursOfTheDay[cn->selectedHours[i]]==text)
18245 							break;
18246 
18247 					if(cn->selectedHours[i]>=this->nHoursPerDay){
18248 						xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
18249 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
18250 							tr(" Constraint ActivitiesOccupyMinTimeSlotsFromSelection hour corrupt, hour %1 is inexistent ... ignoring constraint")
18251 							.arg(text));*/
18252 						delete cn;
18253 						cn=nullptr;
18254 						//goto corruptConstraintTime;
18255 						return nullptr;
18256 					}
18257 
18258 					assert(cn->selectedHours[i]>=0 && cn->selectedHours[i] < this->nHoursPerDay);
18259 					xmlReadingLog+="    Selected hour="+this->hoursOfTheDay[cn->selectedHours[i]]+"\n";
18260 				}
18261 				else{
18262 					unrecognizedXmlTags.append(xmlReader.name().toString());
18263 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
18264 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
18265 
18266 					xmlReader.skipCurrentElement();
18267 					xmlReaderNumberOfUnrecognizedFields++;
18268 				}
18269 			}
18270 
18271 			i++;
18272 
18273 			if(!(i==cn->selectedDays.count()) || !(i==cn->selectedHours.count())){
18274 				xmlReader.raiseError(tr("%1 is incorrect").arg("Selected_Time_Slot"));
18275 				delete cn;
18276 				cn=nullptr;
18277 				return nullptr;
18278 			}
18279 			assert(i==cn->selectedDays.count());
18280 			assert(i==cn->selectedHours.count());
18281 		}
18282 		else if(xmlReader.name()==QString("Min_Number_of_Occupied_Time_Slots")){
18283 			QString text=xmlReader.readElementText();
18284 			cn->minOccupiedTimeSlots=text.toInt();
18285 			xmlReadingLog+="    Read min number of occupied time slots="+CustomFETString::number(cn->minOccupiedTimeSlots)+"\n";
18286 		}
18287 		else{
18288 			unrecognizedXmlTags.append(xmlReader.name().toString());
18289 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
18290 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
18291 
18292 			xmlReader.skipCurrentElement();
18293 			xmlReaderNumberOfUnrecognizedFields++;
18294 		}
18295 	}
18296 
18297 	if(!(ac==cn->activitiesIds.count())){
18298 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Activities").arg("Activity_Id"));
18299 		delete cn;
18300 		cn=nullptr;
18301 		return nullptr;
18302 	}
18303 
18304 	if(!(i==tsc)){
18305 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Selected_Time_Slots").arg("Selected_Time_Slot"));
18306 		delete cn;
18307 		cn=nullptr;
18308 		return nullptr;
18309 	}
18310 
18311 	assert(ac==cn->activitiesIds.count());
18312 	assert(i==tsc);
18313 	return cn;
18314 }
18315 ////////////////
18316 
18317 //2011-09-30
readActivitiesMaxSimultaneousInSelectedTimeSlots(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)18318 TimeConstraint* Rules::readActivitiesMaxSimultaneousInSelectedTimeSlots(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
18319 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivitiesMaxSimultaneousInSelectedTimeSlots"));
18320 	ConstraintActivitiesMaxSimultaneousInSelectedTimeSlots* cn=new ConstraintActivitiesMaxSimultaneousInSelectedTimeSlots();
18321 
18322 	int ac=0;
18323 	int tsc=0;
18324 	int i=0;
18325 
18326 	while(xmlReader.readNextStartElement()){
18327 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
18328 
18329 		if(xmlReader.name()==QString("Weight_Percentage")){
18330 			QString text=xmlReader.readElementText();
18331 			cn->weightPercentage=customFETStrToDouble(text);
18332 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
18333 		}
18334 		else if(xmlReader.name()==QString("Active")){
18335 			QString text=xmlReader.readElementText();
18336 			if(text=="false"){
18337 				cn->active=false;
18338 			}
18339 		}
18340 		else if(xmlReader.name()==QString("Comments")){
18341 			QString text=xmlReader.readElementText();
18342 			cn->comments=text;
18343 		}
18344 		else if(xmlReader.name()==QString("Number_of_Activities")){
18345 			QString text=xmlReader.readElementText();
18346 			ac=text.toInt();
18347 			xmlReadingLog+="    Read number of activities="+CustomFETString::number(ac)+"\n";
18348 		}
18349 		else if(xmlReader.name()==QString("Activity_Id")){
18350 			QString text=xmlReader.readElementText();
18351 			cn->activitiesIds.append(text.toInt());
18352 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activitiesIds[cn->activitiesIds.count()-1])+"\n";
18353 		}
18354 		else if(xmlReader.name()==QString("Number_of_Selected_Time_Slots")){
18355 			QString text=xmlReader.readElementText();
18356 			tsc=text.toInt();
18357 			xmlReadingLog+="    Read number of selected time slots="+CustomFETString::number(tsc)+"\n";
18358 		}
18359 		else if(xmlReader.name()==QString("Selected_Time_Slot")){
18360 			xmlReadingLog+="    Read: selected time slot\n";
18361 
18362 			assert(xmlReader.isStartElement());
18363 			while(xmlReader.readNextStartElement()){
18364 				xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
18365 				if(xmlReader.name()==QString("Selected_Day")){
18366 					QString text=xmlReader.readElementText();
18367 					cn->selectedDays.append(0);
18368 					assert(cn->selectedDays.count()-1==i);
18369 					for(cn->selectedDays[i]=0; cn->selectedDays[i]<this->nDaysPerWeek; cn->selectedDays[i]++)
18370 						if(this->daysOfTheWeek[cn->selectedDays[i]]==text)
18371 							break;
18372 
18373 					if(cn->selectedDays[i]>=this->nDaysPerWeek){
18374 						xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
18375 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
18376 							tr("Constraint ActivitiesMaxSimultaneousInSelectedTimeSlots day corrupt, day %1 is inexistent ... ignoring constraint")
18377 							.arg(text));*/
18378 						delete cn;
18379 						cn=nullptr;
18380 						//goto corruptConstraintTime;
18381 						return nullptr;
18382 					}
18383 
18384 					assert(cn->selectedDays[i]<this->nDaysPerWeek);
18385 					xmlReadingLog+="    Selected day="+this->daysOfTheWeek[cn->selectedDays[i]]+"("+CustomFETString::number(i)+")"+"\n";
18386 				}
18387 				else if(xmlReader.name()==QString("Selected_Hour")){
18388 					QString text=xmlReader.readElementText();
18389 					cn->selectedHours.append(0);
18390 					assert(cn->selectedHours.count()-1==i);
18391 					for(cn->selectedHours[i]=0; cn->selectedHours[i] < this->nHoursPerDay; cn->selectedHours[i]++)
18392 						if(this->hoursOfTheDay[cn->selectedHours[i]]==text)
18393 							break;
18394 
18395 					if(cn->selectedHours[i]>=this->nHoursPerDay){
18396 						xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
18397 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
18398 							tr(" Constraint ActivitiesMaxSimultaneousInSelectedTimeSlots hour corrupt, hour %1 is inexistent ... ignoring constraint")
18399 							.arg(text));*/
18400 						delete cn;
18401 						cn=nullptr;
18402 						//goto corruptConstraintTime;
18403 						return nullptr;
18404 					}
18405 
18406 					assert(cn->selectedHours[i]>=0 && cn->selectedHours[i] < this->nHoursPerDay);
18407 					xmlReadingLog+="    Selected hour="+this->hoursOfTheDay[cn->selectedHours[i]]+"\n";
18408 				}
18409 				else{
18410 					unrecognizedXmlTags.append(xmlReader.name().toString());
18411 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
18412 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
18413 
18414 					xmlReader.skipCurrentElement();
18415 					xmlReaderNumberOfUnrecognizedFields++;
18416 				}
18417 			}
18418 
18419 			i++;
18420 
18421 			if(!(i==cn->selectedDays.count()) || !(i==cn->selectedHours.count())){
18422 				xmlReader.raiseError(tr("%1 is incorrect").arg("Selected_Time_Slot"));
18423 				delete cn;
18424 				cn=nullptr;
18425 				return nullptr;
18426 			}
18427 			assert(i==cn->selectedDays.count());
18428 			assert(i==cn->selectedHours.count());
18429 		}
18430 		else if(xmlReader.name()==QString("Max_Number_of_Simultaneous_Activities")){
18431 			QString text=xmlReader.readElementText();
18432 			cn->maxSimultaneous=text.toInt();
18433 			xmlReadingLog+="    Read max number of simultaneous activities="+CustomFETString::number(cn->maxSimultaneous)+"\n";
18434 		}
18435 		else{
18436 			unrecognizedXmlTags.append(xmlReader.name().toString());
18437 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
18438 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
18439 
18440 			xmlReader.skipCurrentElement();
18441 			xmlReaderNumberOfUnrecognizedFields++;
18442 		}
18443 	}
18444 
18445 	if(!(ac==cn->activitiesIds.count())){
18446 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Activities").arg("Activity_Id"));
18447 		delete cn;
18448 		cn=nullptr;
18449 		return nullptr;
18450 	}
18451 
18452 	if(!(i==tsc)){
18453 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Selected_Time_Slots").arg("Selected_Time_Slot"));
18454 		delete cn;
18455 		cn=nullptr;
18456 		return nullptr;
18457 	}
18458 
18459 	assert(ac==cn->activitiesIds.count());
18460 	assert(i==tsc);
18461 	return cn;
18462 }
18463 ////////////////
18464 
18465 //2019-11-16
readActivitiesMinSimultaneousInSelectedTimeSlots(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)18466 TimeConstraint* Rules::readActivitiesMinSimultaneousInSelectedTimeSlots(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
18467 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivitiesMinSimultaneousInSelectedTimeSlots"));
18468 	ConstraintActivitiesMinSimultaneousInSelectedTimeSlots* cn=new ConstraintActivitiesMinSimultaneousInSelectedTimeSlots();
18469 
18470 	cn->allowEmptySlots=false;
18471 
18472 	int ac=0;
18473 	int tsc=0;
18474 	int i=0;
18475 
18476 	while(xmlReader.readNextStartElement()){
18477 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
18478 
18479 		if(xmlReader.name()==QString("Weight_Percentage")){
18480 			QString text=xmlReader.readElementText();
18481 			cn->weightPercentage=customFETStrToDouble(text);
18482 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
18483 		}
18484 		else if(xmlReader.name()==QString("Active")){
18485 			QString text=xmlReader.readElementText();
18486 			if(text=="false"){
18487 				cn->active=false;
18488 			}
18489 		}
18490 		else if(xmlReader.name()==QString("Comments")){
18491 			QString text=xmlReader.readElementText();
18492 			cn->comments=text;
18493 		}
18494 		else if(xmlReader.name()==QString("Number_of_Activities")){
18495 			QString text=xmlReader.readElementText();
18496 			ac=text.toInt();
18497 			xmlReadingLog+="    Read number of activities="+CustomFETString::number(ac)+"\n";
18498 		}
18499 		else if(xmlReader.name()==QString("Activity_Id")){
18500 			QString text=xmlReader.readElementText();
18501 			cn->activitiesIds.append(text.toInt());
18502 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activitiesIds[cn->activitiesIds.count()-1])+"\n";
18503 		}
18504 		else if(xmlReader.name()==QString("Number_of_Selected_Time_Slots")){
18505 			QString text=xmlReader.readElementText();
18506 			tsc=text.toInt();
18507 			xmlReadingLog+="    Read number of selected time slots="+CustomFETString::number(tsc)+"\n";
18508 		}
18509 		else if(xmlReader.name()==QString("Selected_Time_Slot")){
18510 			xmlReadingLog+="    Read: selected time slot\n";
18511 
18512 			assert(xmlReader.isStartElement());
18513 			while(xmlReader.readNextStartElement()){
18514 				xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
18515 				if(xmlReader.name()==QString("Selected_Day")){
18516 					QString text=xmlReader.readElementText();
18517 					cn->selectedDays.append(0);
18518 					assert(cn->selectedDays.count()-1==i);
18519 					for(cn->selectedDays[i]=0; cn->selectedDays[i]<this->nDaysPerWeek; cn->selectedDays[i]++)
18520 						if(this->daysOfTheWeek[cn->selectedDays[i]]==text)
18521 							break;
18522 
18523 					if(cn->selectedDays[i]>=this->nDaysPerWeek){
18524 						xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
18525 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
18526 							tr("Constraint ActivitiesMinSimultaneousInSelectedTimeSlots day corrupt, day %1 is inexistent ... ignoring constraint")
18527 							.arg(text));*/
18528 						delete cn;
18529 						cn=nullptr;
18530 						//goto corruptConstraintTime;
18531 						return nullptr;
18532 					}
18533 
18534 					assert(cn->selectedDays[i]<this->nDaysPerWeek);
18535 					xmlReadingLog+="    Selected day="+this->daysOfTheWeek[cn->selectedDays[i]]+"("+CustomFETString::number(i)+")"+"\n";
18536 				}
18537 				else if(xmlReader.name()==QString("Selected_Hour")){
18538 					QString text=xmlReader.readElementText();
18539 					cn->selectedHours.append(0);
18540 					assert(cn->selectedHours.count()-1==i);
18541 					for(cn->selectedHours[i]=0; cn->selectedHours[i] < this->nHoursPerDay; cn->selectedHours[i]++)
18542 						if(this->hoursOfTheDay[cn->selectedHours[i]]==text)
18543 							break;
18544 
18545 					if(cn->selectedHours[i]>=this->nHoursPerDay){
18546 						xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
18547 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
18548 							tr(" Constraint ActivitiesMinSimultaneousInSelectedTimeSlots hour corrupt, hour %1 is inexistent ... ignoring constraint")
18549 							.arg(text));*/
18550 						delete cn;
18551 						cn=nullptr;
18552 						//goto corruptConstraintTime;
18553 						return nullptr;
18554 					}
18555 
18556 					assert(cn->selectedHours[i]>=0 && cn->selectedHours[i] < this->nHoursPerDay);
18557 					xmlReadingLog+="    Selected hour="+this->hoursOfTheDay[cn->selectedHours[i]]+"\n";
18558 				}
18559 				else{
18560 					unrecognizedXmlTags.append(xmlReader.name().toString());
18561 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
18562 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
18563 
18564 					xmlReader.skipCurrentElement();
18565 					xmlReaderNumberOfUnrecognizedFields++;
18566 				}
18567 			}
18568 
18569 			i++;
18570 
18571 			if(!(i==cn->selectedDays.count()) || !(i==cn->selectedHours.count())){
18572 				xmlReader.raiseError(tr("%1 is incorrect").arg("Selected_Time_Slot"));
18573 				delete cn;
18574 				cn=nullptr;
18575 				return nullptr;
18576 			}
18577 			assert(i==cn->selectedDays.count());
18578 			assert(i==cn->selectedHours.count());
18579 		}
18580 		else if(xmlReader.name()==QString("Min_Number_of_Simultaneous_Activities")){
18581 			QString text=xmlReader.readElementText();
18582 			cn->minSimultaneous=text.toInt();
18583 			xmlReadingLog+="    Read min number of simultaneous activities="+CustomFETString::number(cn->minSimultaneous)+"\n";
18584 		}
18585 		else if(xmlReader.name()==QString("Allow_Empty_Slots")){
18586 			QString text=xmlReader.readElementText();
18587 			if(text=="true")
18588 				cn->allowEmptySlots=true;
18589 			else
18590 				cn->allowEmptySlots=false;
18591 		}
18592 		else{
18593 			unrecognizedXmlTags.append(xmlReader.name().toString());
18594 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
18595 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
18596 
18597 			xmlReader.skipCurrentElement();
18598 			xmlReaderNumberOfUnrecognizedFields++;
18599 		}
18600 	}
18601 
18602 	if(!(ac==cn->activitiesIds.count())){
18603 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Activities").arg("Activity_Id"));
18604 		delete cn;
18605 		cn=nullptr;
18606 		return nullptr;
18607 	}
18608 
18609 	if(!(i==tsc)){
18610 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Selected_Time_Slots").arg("Selected_Time_Slot"));
18611 		delete cn;
18612 		cn=nullptr;
18613 		return nullptr;
18614 	}
18615 
18616 	assert(ac==cn->activitiesIds.count());
18617 	assert(i==tsc);
18618 	return cn;
18619 }
18620 ////////////////
18621 
18622 //2020-05-02
readMaxTotalActivitiesFromSetInSelectedTimeSlots(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)18623 TimeConstraint* Rules::readMaxTotalActivitiesFromSetInSelectedTimeSlots(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
18624 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintMaxTotalActivitiesFromSetInSelectedTimeSlots"));
18625 	ConstraintMaxTotalActivitiesFromSetInSelectedTimeSlots* cn=new ConstraintMaxTotalActivitiesFromSetInSelectedTimeSlots();
18626 
18627 	int ac=0;
18628 	int tsc=0;
18629 	int i=0;
18630 
18631 	while(xmlReader.readNextStartElement()){
18632 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
18633 
18634 		if(xmlReader.name()==QString("Weight_Percentage")){
18635 			QString text=xmlReader.readElementText();
18636 			cn->weightPercentage=customFETStrToDouble(text);
18637 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
18638 		}
18639 		else if(xmlReader.name()==QString("Active")){
18640 			QString text=xmlReader.readElementText();
18641 			if(text=="false"){
18642 				cn->active=false;
18643 			}
18644 		}
18645 		else if(xmlReader.name()==QString("Comments")){
18646 			QString text=xmlReader.readElementText();
18647 			cn->comments=text;
18648 		}
18649 		else if(xmlReader.name()==QString("Number_of_Activities")){
18650 			QString text=xmlReader.readElementText();
18651 			ac=text.toInt();
18652 			xmlReadingLog+="    Read number of activities="+CustomFETString::number(ac)+"\n";
18653 		}
18654 		else if(xmlReader.name()==QString("Activity_Id")){
18655 			QString text=xmlReader.readElementText();
18656 			cn->activitiesIds.append(text.toInt());
18657 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activitiesIds[cn->activitiesIds.count()-1])+"\n";
18658 		}
18659 		else if(xmlReader.name()==QString("Number_of_Selected_Time_Slots")){
18660 			QString text=xmlReader.readElementText();
18661 			tsc=text.toInt();
18662 			xmlReadingLog+="    Read number of selected time slots="+CustomFETString::number(tsc)+"\n";
18663 		}
18664 		else if(xmlReader.name()==QString("Selected_Time_Slot")){
18665 			xmlReadingLog+="    Read: selected time slot\n";
18666 
18667 			assert(xmlReader.isStartElement());
18668 			while(xmlReader.readNextStartElement()){
18669 				xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
18670 				if(xmlReader.name()==QString("Selected_Day")){
18671 					QString text=xmlReader.readElementText();
18672 					cn->selectedDays.append(0);
18673 					assert(cn->selectedDays.count()-1==i);
18674 					for(cn->selectedDays[i]=0; cn->selectedDays[i]<this->nDaysPerWeek; cn->selectedDays[i]++)
18675 						if(this->daysOfTheWeek[cn->selectedDays[i]]==text)
18676 							break;
18677 
18678 					if(cn->selectedDays[i]>=this->nDaysPerWeek){
18679 						xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
18680 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
18681 							tr("Constraint ActivitiesMaxSimultaneousInSelectedTimeSlots day corrupt, day %1 is inexistent ... ignoring constraint")
18682 							.arg(text));*/
18683 						delete cn;
18684 						cn=nullptr;
18685 						//goto corruptConstraintTime;
18686 						return nullptr;
18687 					}
18688 
18689 					assert(cn->selectedDays[i]<this->nDaysPerWeek);
18690 					xmlReadingLog+="    Selected day="+this->daysOfTheWeek[cn->selectedDays[i]]+"("+CustomFETString::number(i)+")"+"\n";
18691 				}
18692 				else if(xmlReader.name()==QString("Selected_Hour")){
18693 					QString text=xmlReader.readElementText();
18694 					cn->selectedHours.append(0);
18695 					assert(cn->selectedHours.count()-1==i);
18696 					for(cn->selectedHours[i]=0; cn->selectedHours[i] < this->nHoursPerDay; cn->selectedHours[i]++)
18697 						if(this->hoursOfTheDay[cn->selectedHours[i]]==text)
18698 							break;
18699 
18700 					if(cn->selectedHours[i]>=this->nHoursPerDay){
18701 						xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
18702 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
18703 							tr(" Constraint ActivitiesMaxSimultaneousInSelectedTimeSlots hour corrupt, hour %1 is inexistent ... ignoring constraint")
18704 							.arg(text));*/
18705 						delete cn;
18706 						cn=nullptr;
18707 						//goto corruptConstraintTime;
18708 						return nullptr;
18709 					}
18710 
18711 					assert(cn->selectedHours[i]>=0 && cn->selectedHours[i] < this->nHoursPerDay);
18712 					xmlReadingLog+="    Selected hour="+this->hoursOfTheDay[cn->selectedHours[i]]+"\n";
18713 				}
18714 				else{
18715 					unrecognizedXmlTags.append(xmlReader.name().toString());
18716 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
18717 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
18718 
18719 					xmlReader.skipCurrentElement();
18720 					xmlReaderNumberOfUnrecognizedFields++;
18721 				}
18722 			}
18723 
18724 			i++;
18725 
18726 			if(!(i==cn->selectedDays.count()) || !(i==cn->selectedHours.count())){
18727 				xmlReader.raiseError(tr("%1 is incorrect").arg("Selected_Time_Slot"));
18728 				delete cn;
18729 				cn=nullptr;
18730 				return nullptr;
18731 			}
18732 			assert(i==cn->selectedDays.count());
18733 			assert(i==cn->selectedHours.count());
18734 		}
18735 		else if(xmlReader.name()==QString("Max_Total_Number_of_Activities")){
18736 			QString text=xmlReader.readElementText();
18737 			cn->maxActivities=text.toInt();
18738 			xmlReadingLog+="    Read max total number of activities="+CustomFETString::number(cn->maxActivities)+"\n";
18739 		}
18740 		else{
18741 			unrecognizedXmlTags.append(xmlReader.name().toString());
18742 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
18743 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
18744 
18745 			xmlReader.skipCurrentElement();
18746 			xmlReaderNumberOfUnrecognizedFields++;
18747 		}
18748 	}
18749 
18750 	if(!(ac==cn->activitiesIds.count())){
18751 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Activities").arg("Activity_Id"));
18752 		delete cn;
18753 		cn=nullptr;
18754 		return nullptr;
18755 	}
18756 
18757 	if(!(i==tsc)){
18758 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Selected_Time_Slots").arg("Selected_Time_Slot"));
18759 		delete cn;
18760 		cn=nullptr;
18761 		return nullptr;
18762 	}
18763 
18764 	assert(ac==cn->activitiesIds.count());
18765 	assert(i==tsc);
18766 	return cn;
18767 }
18768 ////////////////
18769 
18770 //2020-01-14
readActivitiesMaxInATerm(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)18771 TimeConstraint* Rules::readActivitiesMaxInATerm(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
18772 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivitiesMaxInATerm"));
18773 	ConstraintActivitiesMaxInATerm* cn=new ConstraintActivitiesMaxInATerm();
18774 
18775 	int ac=0;
18776 
18777 	while(xmlReader.readNextStartElement()){
18778 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
18779 
18780 		if(xmlReader.name()==QString("Weight_Percentage")){
18781 			QString text=xmlReader.readElementText();
18782 			cn->weightPercentage=customFETStrToDouble(text);
18783 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
18784 		}
18785 		else if(xmlReader.name()==QString("Active")){
18786 			QString text=xmlReader.readElementText();
18787 			if(text=="false"){
18788 				cn->active=false;
18789 			}
18790 		}
18791 		else if(xmlReader.name()==QString("Comments")){
18792 			QString text=xmlReader.readElementText();
18793 			cn->comments=text;
18794 		}
18795 		else if(xmlReader.name()==QString("Number_of_Activities")){
18796 			QString text=xmlReader.readElementText();
18797 			ac=text.toInt();
18798 			xmlReadingLog+="    Read number of activities="+CustomFETString::number(ac)+"\n";
18799 		}
18800 		else if(xmlReader.name()==QString("Activity_Id")){
18801 			QString text=xmlReader.readElementText();
18802 			cn->activitiesIds.append(text.toInt());
18803 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activitiesIds[cn->activitiesIds.count()-1])+"\n";
18804 		}
18805 		else if(xmlReader.name()==QString("Max_Number_of_Activities_in_A_Term")){
18806 			QString text=xmlReader.readElementText();
18807 			cn->maxActivitiesInATerm=text.toInt();
18808 			xmlReadingLog+="    Read max number of activities in a term="+CustomFETString::number(cn->maxActivitiesInATerm)+"\n";
18809 		}
18810 		else{
18811 			unrecognizedXmlTags.append(xmlReader.name().toString());
18812 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
18813 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
18814 
18815 			xmlReader.skipCurrentElement();
18816 			xmlReaderNumberOfUnrecognizedFields++;
18817 		}
18818 	}
18819 
18820 	if(!(ac==cn->activitiesIds.count())){
18821 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Activities").arg("Activity_Id"));
18822 		delete cn;
18823 		cn=nullptr;
18824 		return nullptr;
18825 	}
18826 
18827 	assert(ac==cn->activitiesIds.count());
18828 	return cn;
18829 }
18830 
18831 //2020-01-14
readActivitiesOccupyMaxTerms(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)18832 TimeConstraint* Rules::readActivitiesOccupyMaxTerms(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
18833 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivitiesOccupyMaxTerms"));
18834 	ConstraintActivitiesOccupyMaxTerms* cn=new ConstraintActivitiesOccupyMaxTerms();
18835 
18836 	int ac=0;
18837 
18838 	while(xmlReader.readNextStartElement()){
18839 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
18840 
18841 		if(xmlReader.name()==QString("Weight_Percentage")){
18842 			QString text=xmlReader.readElementText();
18843 			cn->weightPercentage=customFETStrToDouble(text);
18844 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
18845 		}
18846 		else if(xmlReader.name()==QString("Active")){
18847 			QString text=xmlReader.readElementText();
18848 			if(text=="false"){
18849 				cn->active=false;
18850 			}
18851 		}
18852 		else if(xmlReader.name()==QString("Comments")){
18853 			QString text=xmlReader.readElementText();
18854 			cn->comments=text;
18855 		}
18856 		else if(xmlReader.name()==QString("Number_of_Activities")){
18857 			QString text=xmlReader.readElementText();
18858 			ac=text.toInt();
18859 			xmlReadingLog+="    Read number of activities="+CustomFETString::number(ac)+"\n";
18860 		}
18861 		else if(xmlReader.name()==QString("Activity_Id")){
18862 			QString text=xmlReader.readElementText();
18863 			cn->activitiesIds.append(text.toInt());
18864 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activitiesIds[cn->activitiesIds.count()-1])+"\n";
18865 		}
18866 		else if(xmlReader.name()==QString("Max_Number_of_Occupied_Terms")){
18867 			QString text=xmlReader.readElementText();
18868 			cn->maxOccupiedTerms=text.toInt();
18869 			xmlReadingLog+="    Read max number of occupied terms="+CustomFETString::number(cn->maxOccupiedTerms)+"\n";
18870 		}
18871 		else{
18872 			unrecognizedXmlTags.append(xmlReader.name().toString());
18873 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
18874 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
18875 
18876 			xmlReader.skipCurrentElement();
18877 			xmlReaderNumberOfUnrecognizedFields++;
18878 		}
18879 	}
18880 
18881 	if(!(ac==cn->activitiesIds.count())){
18882 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Activities").arg("Activity_Id"));
18883 		delete cn;
18884 		cn=nullptr;
18885 		return nullptr;
18886 	}
18887 
18888 	assert(ac==cn->activitiesIds.count());
18889 	return cn;
18890 }
18891 
18892 /////2017-02-07
readTeacherMaxSpanPerDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)18893 TimeConstraint* Rules::readTeacherMaxSpanPerDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
18894 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxSpanPerDay"));
18895 	ConstraintTeacherMaxSpanPerDay* cn=new ConstraintTeacherMaxSpanPerDay();
18896 	cn->allowOneDayExceptionPlusOne=false;
18897 	while(xmlReader.readNextStartElement()){
18898 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
18899 		if(xmlReader.name()==QString("Weight_Percentage")){
18900 			QString text=xmlReader.readElementText();
18901 			cn->weightPercentage=customFETStrToDouble(text);
18902 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
18903 		}
18904 		else if(xmlReader.name()==QString("Allow_One_Day_Exception_of_Plus_One")){
18905 			QString text=xmlReader.readElementText();
18906 			if(text=="true"){
18907 				cn->allowOneDayExceptionPlusOne=true;
18908 			}
18909 		}
18910 		else if(xmlReader.name()==QString("Active")){
18911 			QString text=xmlReader.readElementText();
18912 			if(text=="false"){
18913 				cn->active=false;
18914 			}
18915 		}
18916 		else if(xmlReader.name()==QString("Comments")){
18917 			QString text=xmlReader.readElementText();
18918 			cn->comments=text;
18919 		}
18920 		else if(xmlReader.name()==QString("Teacher_Name")){
18921 			QString text=xmlReader.readElementText();
18922 			cn->teacherName=text;
18923 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
18924 		}
18925 		else if(xmlReader.name()==QString("Max_Span")){
18926 			QString text=xmlReader.readElementText();
18927 			cn->maxSpanPerDay=text.toInt();
18928 			xmlReadingLog+="    Adding max span per day="+CustomFETString::number(cn->maxSpanPerDay)+"\n";
18929 		}
18930 		else{
18931 			unrecognizedXmlTags.append(xmlReader.name().toString());
18932 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
18933 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
18934 
18935 			xmlReader.skipCurrentElement();
18936 			xmlReaderNumberOfUnrecognizedFields++;
18937 		}
18938 	}
18939 	return cn;
18940 }
18941 
readTeachersMaxSpanPerDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)18942 TimeConstraint* Rules::readTeachersMaxSpanPerDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
18943 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxSpanPerDay"));
18944 	ConstraintTeachersMaxSpanPerDay* cn=new ConstraintTeachersMaxSpanPerDay();
18945 	cn->allowOneDayExceptionPlusOne=false;
18946 	while(xmlReader.readNextStartElement()){
18947 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
18948 		if(xmlReader.name()==QString("Weight_Percentage")){
18949 			QString text=xmlReader.readElementText();
18950 			cn->weightPercentage=customFETStrToDouble(text);
18951 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
18952 		}
18953 		else if(xmlReader.name()==QString("Allow_One_Day_Exception_of_Plus_One")){
18954 			QString text=xmlReader.readElementText();
18955 			if(text=="true"){
18956 				cn->allowOneDayExceptionPlusOne=true;
18957 			}
18958 		}
18959 		else if(xmlReader.name()==QString("Active")){
18960 			QString text=xmlReader.readElementText();
18961 			if(text=="false"){
18962 				cn->active=false;
18963 			}
18964 		}
18965 		else if(xmlReader.name()==QString("Comments")){
18966 			QString text=xmlReader.readElementText();
18967 			cn->comments=text;
18968 		}
18969 		else if(xmlReader.name()==QString("Max_Span")){
18970 			QString text=xmlReader.readElementText();
18971 			cn->maxSpanPerDay=text.toInt();
18972 			xmlReadingLog+="    Adding max span per day="+CustomFETString::number(cn->maxSpanPerDay)+"\n";
18973 		}
18974 		else{
18975 			unrecognizedXmlTags.append(xmlReader.name().toString());
18976 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
18977 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
18978 
18979 			xmlReader.skipCurrentElement();
18980 			xmlReaderNumberOfUnrecognizedFields++;
18981 		}
18982 	}
18983 	return cn;
18984 }
18985 
readStudentsSetMaxSpanPerDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)18986 TimeConstraint* Rules::readStudentsSetMaxSpanPerDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
18987 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMaxSpanPerDay"));
18988 	ConstraintStudentsSetMaxSpanPerDay* cn=new ConstraintStudentsSetMaxSpanPerDay();
18989 	while(xmlReader.readNextStartElement()){
18990 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
18991 		if(xmlReader.name()==QString("Weight_Percentage")){
18992 			QString text=xmlReader.readElementText();
18993 			cn->weightPercentage=customFETStrToDouble(text);
18994 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
18995 		}
18996 		else if(xmlReader.name()==QString("Active")){
18997 			QString text=xmlReader.readElementText();
18998 			if(text=="false"){
18999 				cn->active=false;
19000 			}
19001 		}
19002 		else if(xmlReader.name()==QString("Comments")){
19003 			QString text=xmlReader.readElementText();
19004 			cn->comments=text;
19005 		}
19006 		else if(xmlReader.name()==QString("Students")){
19007 			QString text=xmlReader.readElementText();
19008 			cn->students=text;
19009 			xmlReadingLog+="    Read students name="+cn->students+"\n";
19010 		}
19011 		else if(xmlReader.name()==QString("Max_Span")){
19012 			QString text=xmlReader.readElementText();
19013 			cn->maxSpanPerDay=text.toInt();
19014 			xmlReadingLog+="    Adding max span per day="+CustomFETString::number(cn->maxSpanPerDay)+"\n";
19015 		}
19016 		else{
19017 			unrecognizedXmlTags.append(xmlReader.name().toString());
19018 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
19019 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
19020 
19021 			xmlReader.skipCurrentElement();
19022 			xmlReaderNumberOfUnrecognizedFields++;
19023 		}
19024 	}
19025 	return cn;
19026 }
19027 
readStudentsMaxSpanPerDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)19028 TimeConstraint* Rules::readStudentsMaxSpanPerDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
19029 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMaxSpanPerDay"));
19030 	ConstraintStudentsMaxSpanPerDay* cn=new ConstraintStudentsMaxSpanPerDay();
19031 	while(xmlReader.readNextStartElement()){
19032 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
19033 		if(xmlReader.name()==QString("Weight_Percentage")){
19034 			QString text=xmlReader.readElementText();
19035 			cn->weightPercentage=customFETStrToDouble(text);
19036 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
19037 		}
19038 		else if(xmlReader.name()==QString("Active")){
19039 			QString text=xmlReader.readElementText();
19040 			if(text=="false"){
19041 				cn->active=false;
19042 			}
19043 		}
19044 		else if(xmlReader.name()==QString("Comments")){
19045 			QString text=xmlReader.readElementText();
19046 			cn->comments=text;
19047 		}
19048 		else if(xmlReader.name()==QString("Max_Span")){
19049 			QString text=xmlReader.readElementText();
19050 			cn->maxSpanPerDay=text.toInt();
19051 			xmlReadingLog+="    Adding max span per day="+CustomFETString::number(cn->maxSpanPerDay)+"\n";
19052 		}
19053 		else{
19054 			unrecognizedXmlTags.append(xmlReader.name().toString());
19055 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
19056 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
19057 
19058 			xmlReader.skipCurrentElement();
19059 			xmlReaderNumberOfUnrecognizedFields++;
19060 		}
19061 	}
19062 	return cn;
19063 }
19064 
readTeacherMinRestingHours(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)19065 TimeConstraint* Rules::readTeacherMinRestingHours(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
19066 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMinRestingHours"));
19067 	ConstraintTeacherMinRestingHours* cn=new ConstraintTeacherMinRestingHours();
19068 	cn->circular=true;
19069 	while(xmlReader.readNextStartElement()){
19070 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
19071 		if(xmlReader.name()==QString("Weight_Percentage")){
19072 			QString text=xmlReader.readElementText();
19073 			cn->weightPercentage=customFETStrToDouble(text);
19074 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
19075 		}
19076 		else if(xmlReader.name()==QString("Active")){
19077 			QString text=xmlReader.readElementText();
19078 			if(text=="false"){
19079 				cn->active=false;
19080 			}
19081 		}
19082 		else if(xmlReader.name()==QString("Circular")){
19083 			QString text=xmlReader.readElementText();
19084 			if(text=="false"){
19085 				cn->circular=false;
19086 			}
19087 		}
19088 		else if(xmlReader.name()==QString("Comments")){
19089 			QString text=xmlReader.readElementText();
19090 			cn->comments=text;
19091 		}
19092 		else if(xmlReader.name()==QString("Teacher_Name")){
19093 			QString text=xmlReader.readElementText();
19094 			cn->teacherName=text;
19095 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
19096 		}
19097 		else if(xmlReader.name()==QString("Minimum_Resting_Hours")){
19098 			QString text=xmlReader.readElementText();
19099 			cn->minRestingHours=text.toInt();
19100 			xmlReadingLog+="    Adding min resting hours="+CustomFETString::number(cn->minRestingHours)+"\n";
19101 		}
19102 		else{
19103 			unrecognizedXmlTags.append(xmlReader.name().toString());
19104 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
19105 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
19106 
19107 			xmlReader.skipCurrentElement();
19108 			xmlReaderNumberOfUnrecognizedFields++;
19109 		}
19110 	}
19111 	return cn;
19112 }
19113 
readTeachersMinRestingHours(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)19114 TimeConstraint* Rules::readTeachersMinRestingHours(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
19115 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMinRestingHours"));
19116 	ConstraintTeachersMinRestingHours* cn=new ConstraintTeachersMinRestingHours();
19117 	cn->circular=true;
19118 	while(xmlReader.readNextStartElement()){
19119 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
19120 		if(xmlReader.name()==QString("Weight_Percentage")){
19121 			QString text=xmlReader.readElementText();
19122 			cn->weightPercentage=customFETStrToDouble(text);
19123 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
19124 		}
19125 		else if(xmlReader.name()==QString("Active")){
19126 			QString text=xmlReader.readElementText();
19127 			if(text=="false"){
19128 				cn->active=false;
19129 			}
19130 		}
19131 		else if(xmlReader.name()==QString("Circular")){
19132 			QString text=xmlReader.readElementText();
19133 			if(text=="false"){
19134 				cn->circular=false;
19135 			}
19136 		}
19137 		else if(xmlReader.name()==QString("Comments")){
19138 			QString text=xmlReader.readElementText();
19139 			cn->comments=text;
19140 		}
19141 		else if(xmlReader.name()==QString("Minimum_Resting_Hours")){
19142 			QString text=xmlReader.readElementText();
19143 			cn->minRestingHours=text.toInt();
19144 			xmlReadingLog+="    Adding min resting hours="+CustomFETString::number(cn->minRestingHours)+"\n";
19145 		}
19146 		else{
19147 			unrecognizedXmlTags.append(xmlReader.name().toString());
19148 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
19149 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
19150 
19151 			xmlReader.skipCurrentElement();
19152 			xmlReaderNumberOfUnrecognizedFields++;
19153 		}
19154 	}
19155 	return cn;
19156 }
19157 
readStudentsSetMinRestingHours(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)19158 TimeConstraint* Rules::readStudentsSetMinRestingHours(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
19159 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMinRestingHours"));
19160 	ConstraintStudentsSetMinRestingHours* cn=new ConstraintStudentsSetMinRestingHours();
19161 	cn->circular=true;
19162 	while(xmlReader.readNextStartElement()){
19163 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
19164 		if(xmlReader.name()==QString("Weight_Percentage")){
19165 			QString text=xmlReader.readElementText();
19166 			cn->weightPercentage=customFETStrToDouble(text);
19167 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
19168 		}
19169 		else if(xmlReader.name()==QString("Active")){
19170 			QString text=xmlReader.readElementText();
19171 			if(text=="false"){
19172 				cn->active=false;
19173 			}
19174 		}
19175 		else if(xmlReader.name()==QString("Circular")){
19176 			QString text=xmlReader.readElementText();
19177 			if(text=="false"){
19178 				cn->circular=false;
19179 			}
19180 		}
19181 		else if(xmlReader.name()==QString("Comments")){
19182 			QString text=xmlReader.readElementText();
19183 			cn->comments=text;
19184 		}
19185 		else if(xmlReader.name()==QString("Students")){
19186 			QString text=xmlReader.readElementText();
19187 			cn->students=text;
19188 			xmlReadingLog+="    Read students name="+cn->students+"\n";
19189 		}
19190 		else if(xmlReader.name()==QString("Minimum_Resting_Hours")){
19191 			QString text=xmlReader.readElementText();
19192 			cn->minRestingHours=text.toInt();
19193 			xmlReadingLog+="    Adding min resting hours="+CustomFETString::number(cn->minRestingHours)+"\n";
19194 		}
19195 		else{
19196 			unrecognizedXmlTags.append(xmlReader.name().toString());
19197 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
19198 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
19199 
19200 			xmlReader.skipCurrentElement();
19201 			xmlReaderNumberOfUnrecognizedFields++;
19202 		}
19203 	}
19204 	return cn;
19205 }
19206 
readStudentsMinRestingHours(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)19207 TimeConstraint* Rules::readStudentsMinRestingHours(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
19208 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMinRestingHours"));
19209 	ConstraintStudentsMinRestingHours* cn=new ConstraintStudentsMinRestingHours();
19210 	cn->circular=true;
19211 	while(xmlReader.readNextStartElement()){
19212 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
19213 		if(xmlReader.name()==QString("Weight_Percentage")){
19214 			QString text=xmlReader.readElementText();
19215 			cn->weightPercentage=customFETStrToDouble(text);
19216 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
19217 		}
19218 		else if(xmlReader.name()==QString("Active")){
19219 			QString text=xmlReader.readElementText();
19220 			if(text=="false"){
19221 				cn->active=false;
19222 			}
19223 		}
19224 		else if(xmlReader.name()==QString("Circular")){
19225 			QString text=xmlReader.readElementText();
19226 			if(text=="false"){
19227 				cn->circular=false;
19228 			}
19229 		}
19230 		else if(xmlReader.name()==QString("Comments")){
19231 			QString text=xmlReader.readElementText();
19232 			cn->comments=text;
19233 		}
19234 		else if(xmlReader.name()==QString("Minimum_Resting_Hours")){
19235 			QString text=xmlReader.readElementText();
19236 			cn->minRestingHours=text.toInt();
19237 			xmlReadingLog+="    Adding min resting hours="+CustomFETString::number(cn->minRestingHours)+"\n";
19238 		}
19239 		else{
19240 			unrecognizedXmlTags.append(xmlReader.name().toString());
19241 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
19242 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
19243 
19244 			xmlReader.skipCurrentElement();
19245 			xmlReaderNumberOfUnrecognizedFields++;
19246 		}
19247 	}
19248 	return cn;
19249 }
19250 
19251 //mornings-afternoons
readOldMATeacherMaxDaysPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)19252 TimeConstraint* Rules::readOldMATeacherMaxDaysPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
19253 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxDaysPerWeek"));
19254 
19255 	ConstraintTeacherMaxRealDaysPerWeek* cn=new ConstraintTeacherMaxRealDaysPerWeek();
19256 	while(xmlReader.readNextStartElement()){
19257 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
19258 		if(xmlReader.name()==QString("Weight")){
19259 			//cn->weight=customFETStrToDouble(text);
19260 			xmlReader.skipCurrentElement();
19261 			xmlReadingLog+="    Ignoring old tag - weight - generating 100% weight percentage\n";
19262 			cn->weightPercentage=100;
19263 		}
19264 		else if(xmlReader.name()==QString("Weight_Percentage")){
19265 			QString text=xmlReader.readElementText();
19266 			cn->weightPercentage=customFETStrToDouble(text);
19267 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
19268 		}
19269 		else if(xmlReader.name()==QString("Active")){
19270 			QString text=xmlReader.readElementText();
19271 			if(text=="false"){
19272 				cn->active=false;
19273 			}
19274 		}
19275 		else if(xmlReader.name()==QString("Comments")){
19276 			QString text=xmlReader.readElementText();
19277 			cn->comments=text;
19278 		}
19279 		else if(xmlReader.name()==QString("Compulsory")){
19280 			QString text=xmlReader.readElementText();
19281 			if(text=="yes"){
19282 				//cn->compulsory=true;
19283 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
19284 				cn->weightPercentage=100;
19285 			}
19286 			else{
19287 				//cn->compulsory=false;
19288 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
19289 				cn->weightPercentage=0;
19290 			}
19291 		}
19292 		else if(xmlReader.name()==QString("Teacher_Name")){
19293 			QString text=xmlReader.readElementText();
19294 			cn->teacherName=text;
19295 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
19296 		}
19297 		else if(xmlReader.name()==QString("Max_Days_Per_Week")){
19298 			QString text=xmlReader.readElementText();
19299 			cn->maxDaysPerWeek=text.toInt();
19300 			if(cn->maxDaysPerWeek<=0 || cn->maxDaysPerWeek>this->nDaysPerWeek){
19301 				xmlReader.raiseError(tr("%1 is incorrect").arg("Max_Days_Per_Week"));
19302 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
19303 					tr("Constraint TeacherMaxDaysPerWeek max days corrupt for teacher %1, max days %2 <= 0 or >nDaysPerWeek, ignoring constraint")
19304 					.arg(cn->teacherName)
19305 					.arg(text));*/
19306 				delete cn;
19307 				cn=nullptr;
19308 				return nullptr;
19309 			}
19310 			assert(cn->maxDaysPerWeek>0 && cn->maxDaysPerWeek <= this->nDaysPerWeek);
19311 			xmlReadingLog+="    Max. days per week="+CustomFETString::number(cn->maxDaysPerWeek)+"\n";
19312 		}
19313 		else{
19314 			unrecognizedXmlTags.append(xmlReader.name().toString());
19315 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
19316 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
19317 
19318 			xmlReader.skipCurrentElement();
19319 			xmlReaderNumberOfUnrecognizedFields++;
19320 		}
19321 	}
19322 	return cn;
19323 }
19324 
readTeacherMaxRealDaysPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)19325 TimeConstraint* Rules::readTeacherMaxRealDaysPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
19326 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxRealDaysPerWeek"));
19327 
19328 	ConstraintTeacherMaxRealDaysPerWeek* cn=new ConstraintTeacherMaxRealDaysPerWeek();
19329 	while(xmlReader.readNextStartElement()){
19330 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
19331 		if(xmlReader.name()==QString("Weight")){
19332 			//cn->weight=customFETStrToDouble(text);
19333 			xmlReader.skipCurrentElement();
19334 			xmlReadingLog+="    Ignoring old tag - weight - generating 100% weight percentage\n";
19335 			cn->weightPercentage=100;
19336 		}
19337 		else if(xmlReader.name()==QString("Weight_Percentage")){
19338 			QString text=xmlReader.readElementText();
19339 			cn->weightPercentage=customFETStrToDouble(text);
19340 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
19341 		}
19342 		else if(xmlReader.name()==QString("Active")){
19343 			QString text=xmlReader.readElementText();
19344 			if(text=="false"){
19345 				cn->active=false;
19346 			}
19347 		}
19348 		else if(xmlReader.name()==QString("Comments")){
19349 			QString text=xmlReader.readElementText();
19350 			cn->comments=text;
19351 		}
19352 		else if(xmlReader.name()==QString("Compulsory")){
19353 			QString text=xmlReader.readElementText();
19354 			if(text=="yes"){
19355 				//cn->compulsory=true;
19356 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
19357 				cn->weightPercentage=100;
19358 			}
19359 			else{
19360 				//cn->compulsory=false;
19361 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
19362 				cn->weightPercentage=0;
19363 			}
19364 		}
19365 		else if(xmlReader.name()==QString("Teacher_Name")){
19366 			QString text=xmlReader.readElementText();
19367 			cn->teacherName=text;
19368 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
19369 		}
19370 		else if(xmlReader.name()==QString("Max_Days_Per_Week")){
19371 			QString text=xmlReader.readElementText();
19372 			cn->maxDaysPerWeek=text.toInt();
19373 			if(cn->maxDaysPerWeek<=0 || cn->maxDaysPerWeek>this->nDaysPerWeek){
19374 				xmlReader.raiseError(tr("%1 is incorrect").arg("Max_Days_Per_Week"));
19375 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
19376 					tr("Constraint TeacherMaxDaysPerWeek max days corrupt for teacher %1, max days %2 <= 0 or >nDaysPerWeek, ignoring constraint")
19377 					.arg(cn->teacherName)
19378 					.arg(text));*/
19379 				delete cn;
19380 				cn=nullptr;
19381 				return nullptr;
19382 			}
19383 			assert(cn->maxDaysPerWeek>0 && cn->maxDaysPerWeek <= this->nDaysPerWeek);
19384 			xmlReadingLog+="    Max. days per week="+CustomFETString::number(cn->maxDaysPerWeek)+"\n";
19385 		}
19386 		else{
19387 			unrecognizedXmlTags.append(xmlReader.name().toString());
19388 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
19389 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
19390 
19391 			xmlReader.skipCurrentElement();
19392 			xmlReaderNumberOfUnrecognizedFields++;
19393 		}
19394 	}
19395 	return cn;
19396 }
19397 
readOldMATeachersMaxDaysPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)19398 TimeConstraint* Rules::readOldMATeachersMaxDaysPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
19399 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxDaysPerWeek"));
19400 
19401 	ConstraintTeachersMaxRealDaysPerWeek* cn=new ConstraintTeachersMaxRealDaysPerWeek();
19402 	while(xmlReader.readNextStartElement()){
19403 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
19404 		if(xmlReader.name()==QString("Weight_Percentage")){
19405 			QString text=xmlReader.readElementText();
19406 			cn->weightPercentage=customFETStrToDouble(text);
19407 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
19408 		}
19409 		else if(xmlReader.name()==QString("Active")){
19410 			QString text=xmlReader.readElementText();
19411 			if(text=="false"){
19412 				cn->active=false;
19413 			}
19414 		}
19415 		else if(xmlReader.name()==QString("Comments")){
19416 			QString text=xmlReader.readElementText();
19417 			cn->comments=text;
19418 		}
19419 		else if(xmlReader.name()==QString("Max_Days_Per_Week")){
19420 			QString text=xmlReader.readElementText();
19421 			cn->maxDaysPerWeek=text.toInt();
19422 			if(cn->maxDaysPerWeek<=0 || cn->maxDaysPerWeek>this->nDaysPerWeek){
19423 				xmlReader.raiseError(tr("%1 is incorrect").arg("Max_Days_Per_Week"));
19424 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
19425 					tr("Constraint TeachersMaxDaysPerWeek max days corrupt, max days %1 <= 0 or >nDaysPerWeek, ignoring constraint")
19426 					.arg(text));*/
19427 				delete cn;
19428 				cn=nullptr;
19429 				return nullptr;
19430 			}
19431 			assert(cn->maxDaysPerWeek>0 && cn->maxDaysPerWeek <= this->nDaysPerWeek);
19432 			xmlReadingLog+="    Max. days per week="+CustomFETString::number(cn->maxDaysPerWeek)+"\n";
19433 		}
19434 		else{
19435 			unrecognizedXmlTags.append(xmlReader.name().toString());
19436 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
19437 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
19438 
19439 			xmlReader.skipCurrentElement();
19440 			xmlReaderNumberOfUnrecognizedFields++;
19441 		}
19442 	}
19443 	return cn;
19444 }
19445 
readTeachersMaxRealDaysPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)19446 TimeConstraint* Rules::readTeachersMaxRealDaysPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
19447 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxRealDaysPerWeek"));
19448 
19449 	ConstraintTeachersMaxRealDaysPerWeek* cn=new ConstraintTeachersMaxRealDaysPerWeek();
19450 	while(xmlReader.readNextStartElement()){
19451 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
19452 		if(xmlReader.name()==QString("Weight_Percentage")){
19453 			QString text=xmlReader.readElementText();
19454 			cn->weightPercentage=customFETStrToDouble(text);
19455 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
19456 		}
19457 		else if(xmlReader.name()==QString("Active")){
19458 			QString text=xmlReader.readElementText();
19459 			if(text=="false"){
19460 				cn->active=false;
19461 			}
19462 		}
19463 		else if(xmlReader.name()==QString("Comments")){
19464 			QString text=xmlReader.readElementText();
19465 			cn->comments=text;
19466 		}
19467 		else if(xmlReader.name()==QString("Max_Days_Per_Week")){
19468 			QString text=xmlReader.readElementText();
19469 			cn->maxDaysPerWeek=text.toInt();
19470 			if(cn->maxDaysPerWeek<=0 || cn->maxDaysPerWeek>this->nDaysPerWeek){
19471 				xmlReader.raiseError(tr("%1 is incorrect").arg("Max_Days_Per_Week"));
19472 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
19473 					tr("Constraint TeachersMaxDaysPerWeek max days corrupt, max days %1 <= 0 or >nDaysPerWeek, ignoring constraint")
19474 					.arg(text));*/
19475 				delete cn;
19476 				cn=nullptr;
19477 				return nullptr;
19478 			}
19479 			assert(cn->maxDaysPerWeek>0 && cn->maxDaysPerWeek <= this->nDaysPerWeek);
19480 			xmlReadingLog+="    Max. days per week="+CustomFETString::number(cn->maxDaysPerWeek)+"\n";
19481 		}
19482 		else{
19483 			unrecognizedXmlTags.append(xmlReader.name().toString());
19484 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
19485 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
19486 
19487 			xmlReader.skipCurrentElement();
19488 			xmlReaderNumberOfUnrecognizedFields++;
19489 		}
19490 	}
19491 	return cn;
19492 }
19493 
readTeacherMaxAfternoonsPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)19494 TimeConstraint* Rules::readTeacherMaxAfternoonsPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
19495 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxAfternoonsPerWeek"));
19496 
19497 	ConstraintTeacherMaxAfternoonsPerWeek* cn=new ConstraintTeacherMaxAfternoonsPerWeek();
19498 	while(xmlReader.readNextStartElement()){
19499 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
19500 		if(xmlReader.name()==QString("Weight")){
19501 			//cn->weight=customFETStrToDouble(text);
19502 			xmlReader.skipCurrentElement();
19503 			xmlReadingLog+="    Ignoring old tag - weight - generating 100% weight percentage\n";
19504 			cn->weightPercentage=100;
19505 		}
19506 		else if(xmlReader.name()==QString("Weight_Percentage")){
19507 			QString text=xmlReader.readElementText();
19508 			cn->weightPercentage=customFETStrToDouble(text);
19509 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
19510 		}
19511 		else if(xmlReader.name()==QString("Active")){
19512 			QString text=xmlReader.readElementText();
19513 			if(text=="false"){
19514 				cn->active=false;
19515 			}
19516 		}
19517 		else if(xmlReader.name()==QString("Comments")){
19518 			QString text=xmlReader.readElementText();
19519 			cn->comments=text;
19520 		}
19521 		else if(xmlReader.name()==QString("Compulsory")){
19522 			QString text=xmlReader.readElementText();
19523 			if(text=="yes"){
19524 				//cn->compulsory=true;
19525 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
19526 				cn->weightPercentage=100;
19527 			}
19528 			else{
19529 				//cn->compulsory=false;
19530 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
19531 				cn->weightPercentage=0;
19532 			}
19533 		}
19534 		else if(xmlReader.name()==QString("Teacher_Name")){
19535 			QString text=xmlReader.readElementText();
19536 			cn->teacherName=text;
19537 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
19538 		}
19539 		else if(xmlReader.name()==QString("Max_Afternoons_Per_Week")){
19540 			QString text=xmlReader.readElementText();
19541 			cn->maxAfternoonsPerWeek=text.toInt();
19542 			if(cn->maxAfternoonsPerWeek<=0 || cn->maxAfternoonsPerWeek>this->nDaysPerWeek){
19543 				xmlReader.raiseError(tr("%1 is incorrect").arg("Max_Afternoons_Per_Week"));
19544 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
19545 					tr("Constraint TeacherMaxDaysPerWeek max days corrupt for teacher %1, max days %2 <= 0 or >nDaysPerWeek, ignoring constraint")
19546 					.arg(cn->teacherName)
19547 					.arg(text));*/
19548 				delete cn;
19549 				cn=nullptr;
19550 				return nullptr;
19551 			}
19552 			assert(cn->maxAfternoonsPerWeek>0 && cn->maxAfternoonsPerWeek <= this->nDaysPerWeek);
19553 			xmlReadingLog+="    Max. afternoons per week="+CustomFETString::number(cn->maxAfternoonsPerWeek)+"\n";
19554 		}
19555 		else{
19556 			unrecognizedXmlTags.append(xmlReader.name().toString());
19557 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
19558 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
19559 
19560 			xmlReader.skipCurrentElement();
19561 			xmlReaderNumberOfUnrecognizedFields++;
19562 		}
19563 	}
19564 	return cn;
19565 }
19566 
readTeachersMaxAfternoonsPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)19567 TimeConstraint* Rules::readTeachersMaxAfternoonsPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
19568 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxAfternoonsPerWeek"));
19569 
19570 	ConstraintTeachersMaxAfternoonsPerWeek* cn=new ConstraintTeachersMaxAfternoonsPerWeek();
19571 	while(xmlReader.readNextStartElement()){
19572 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
19573 		if(xmlReader.name()==QString("Weight_Percentage")){
19574 			QString text=xmlReader.readElementText();
19575 			cn->weightPercentage=customFETStrToDouble(text);
19576 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
19577 		}
19578 		else if(xmlReader.name()==QString("Active")){
19579 			QString text=xmlReader.readElementText();
19580 			if(text=="false"){
19581 				cn->active=false;
19582 			}
19583 		}
19584 		else if(xmlReader.name()==QString("Comments")){
19585 			QString text=xmlReader.readElementText();
19586 			cn->comments=text;
19587 		}
19588 		else if(xmlReader.name()==QString("Max_Afternoons_Per_Week")){
19589 			QString text=xmlReader.readElementText();
19590 			cn->maxAfternoonsPerWeek=text.toInt();
19591 			if(cn->maxAfternoonsPerWeek<=0 || cn->maxAfternoonsPerWeek>this->nDaysPerWeek){
19592 				xmlReader.raiseError(tr("%1 is incorrect").arg("Max_Afternoons_Per_Week"));
19593 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
19594 					tr("Constraint TeachersMaxDaysPerWeek max days corrupt, max days %1 <= 0 or >nDaysPerWeek, ignoring constraint")
19595 					.arg(text));*/
19596 				delete cn;
19597 				cn=nullptr;
19598 				return nullptr;
19599 			}
19600 			assert(cn->maxAfternoonsPerWeek>0 && cn->maxAfternoonsPerWeek <= this->nDaysPerWeek);
19601 			xmlReadingLog+="    Max. afternoons per week="+CustomFETString::number(cn->maxAfternoonsPerWeek)+"\n";
19602 		}
19603 		else{
19604 			unrecognizedXmlTags.append(xmlReader.name().toString());
19605 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
19606 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
19607 
19608 			xmlReader.skipCurrentElement();
19609 			xmlReaderNumberOfUnrecognizedFields++;
19610 		}
19611 	}
19612 	return cn;
19613 }
19614 
readTeacherMaxTwoActivityTagsPerDayFromN1N2N3(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)19615 TimeConstraint* Rules::readTeacherMaxTwoActivityTagsPerDayFromN1N2N3(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
19616 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxTwoActivityTagsPerDayFromN1N2N3"));
19617 
19618 	ConstraintTeacherMaxTwoActivityTagsPerDayFromN1N2N3* cn=new ConstraintTeacherMaxTwoActivityTagsPerDayFromN1N2N3();
19619 	while(xmlReader.readNextStartElement()){
19620 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
19621 		if(xmlReader.name()==QString("Weight")){
19622 			//cn->weight=customFETStrToDouble(text);
19623 			xmlReader.skipCurrentElement();
19624 			xmlReadingLog+="    Ignoring old tag - weight - generating 100% weight percentage\n";
19625 			cn->weightPercentage=100;
19626 		}
19627 		else if(xmlReader.name()==QString("Weight_Percentage")){
19628 			QString text=xmlReader.readElementText();
19629 			cn->weightPercentage=customFETStrToDouble(text);
19630 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
19631 		}
19632 		else if(xmlReader.name()==QString("Active")){
19633 			QString text=xmlReader.readElementText();
19634 			if(text=="false"){
19635 				cn->active=false;
19636 			}
19637 		}
19638 		else if(xmlReader.name()==QString("Comments")){
19639 			QString text=xmlReader.readElementText();
19640 			cn->comments=text;
19641 		}
19642 		else if(xmlReader.name()==QString("Compulsory")){
19643 			QString text=xmlReader.readElementText();
19644 			if(text=="yes"){
19645 				//cn->compulsory=true;
19646 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
19647 				cn->weightPercentage=100;
19648 			}
19649 			else{
19650 				//cn->compulsory=false;
19651 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
19652 				cn->weightPercentage=0;
19653 			}
19654 		}
19655 		else if(xmlReader.name()==QString("Teacher_Name")){
19656 			QString text=xmlReader.readElementText();
19657 			cn->teacherName=text;
19658 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
19659 		}
19660 		else{
19661 			unrecognizedXmlTags.append(xmlReader.name().toString());
19662 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
19663 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
19664 
19665 			xmlReader.skipCurrentElement();
19666 			xmlReaderNumberOfUnrecognizedFields++;
19667 		}
19668 	}
19669 	return cn;
19670 }
19671 
readTeachersMaxTwoActivityTagsPerDayFromN1N2N3(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)19672 TimeConstraint* Rules::readTeachersMaxTwoActivityTagsPerDayFromN1N2N3(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
19673 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxTwoActivityTagsPerDayFromN1N2N3"));
19674 
19675 	ConstraintTeachersMaxTwoActivityTagsPerDayFromN1N2N3* cn=new ConstraintTeachersMaxTwoActivityTagsPerDayFromN1N2N3();
19676 	while(xmlReader.readNextStartElement()){
19677 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
19678 		if(xmlReader.name()==QString("Weight")){
19679 			//cn->weight=customFETStrToDouble(text);
19680 			xmlReader.skipCurrentElement();
19681 			xmlReadingLog+="    Ignoring old tag - weight - generating 100% weight percentage\n";
19682 			cn->weightPercentage=100;
19683 		}
19684 		else if(xmlReader.name()==QString("Weight_Percentage")){
19685 			QString text=xmlReader.readElementText();
19686 			cn->weightPercentage=customFETStrToDouble(text);
19687 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
19688 		}
19689 		else if(xmlReader.name()==QString("Active")){
19690 			QString text=xmlReader.readElementText();
19691 			if(text=="false"){
19692 				cn->active=false;
19693 			}
19694 		}
19695 		else if(xmlReader.name()==QString("Comments")){
19696 			QString text=xmlReader.readElementText();
19697 			cn->comments=text;
19698 		}
19699 		else if(xmlReader.name()==QString("Compulsory")){
19700 			QString text=xmlReader.readElementText();
19701 			if(text=="yes"){
19702 				//cn->compulsory=true;
19703 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
19704 				cn->weightPercentage=100;
19705 			}
19706 			else{
19707 				//cn->compulsory=false;
19708 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
19709 				cn->weightPercentage=0;
19710 			}
19711 		}
19712 		else{
19713 			unrecognizedXmlTags.append(xmlReader.name().toString());
19714 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
19715 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
19716 
19717 			xmlReader.skipCurrentElement();
19718 			xmlReaderNumberOfUnrecognizedFields++;
19719 		}
19720 	}
19721 	return cn;
19722 }
19723 
readTeacherMaxMorningsPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)19724 TimeConstraint* Rules::readTeacherMaxMorningsPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
19725 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxMorningsPerWeek"));
19726 
19727 	ConstraintTeacherMaxMorningsPerWeek* cn=new ConstraintTeacherMaxMorningsPerWeek();
19728 	while(xmlReader.readNextStartElement()){
19729 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
19730 		if(xmlReader.name()==QString("Weight")){
19731 			//cn->weight=customFETStrToDouble(text);
19732 			xmlReader.skipCurrentElement();
19733 			xmlReadingLog+="    Ignoring old tag - weight - generating 100% weight percentage\n";
19734 			cn->weightPercentage=100;
19735 		}
19736 		else if(xmlReader.name()==QString("Weight_Percentage")){
19737 			QString text=xmlReader.readElementText();
19738 			cn->weightPercentage=customFETStrToDouble(text);
19739 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
19740 		}
19741 		else if(xmlReader.name()==QString("Active")){
19742 			QString text=xmlReader.readElementText();
19743 			if(text=="false"){
19744 				cn->active=false;
19745 			}
19746 		}
19747 		else if(xmlReader.name()==QString("Comments")){
19748 			QString text=xmlReader.readElementText();
19749 			cn->comments=text;
19750 		}
19751 		else if(xmlReader.name()==QString("Compulsory")){
19752 			QString text=xmlReader.readElementText();
19753 			if(text=="yes"){
19754 				//cn->compulsory=true;
19755 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
19756 				cn->weightPercentage=100;
19757 			}
19758 			else{
19759 				//cn->compulsory=false;
19760 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
19761 				cn->weightPercentage=0;
19762 			}
19763 		}
19764 		else if(xmlReader.name()==QString("Teacher_Name")){
19765 			QString text=xmlReader.readElementText();
19766 			cn->teacherName=text;
19767 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
19768 		}
19769 		else if(xmlReader.name()==QString("Max_Mornings_Per_Week")){
19770 			QString text=xmlReader.readElementText();
19771 			cn->maxMorningsPerWeek=text.toInt();
19772 			if(cn->maxMorningsPerWeek<=0 || cn->maxMorningsPerWeek>this->nDaysPerWeek){
19773 				xmlReader.raiseError(tr("%1 is incorrect").arg("Max_Mornings_Per_Week"));
19774 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
19775 					tr("Constraint TeacherMaxDaysPerWeek max days corrupt for teacher %1, max days %2 <= 0 or >nDaysPerWeek, ignoring constraint")
19776 					.arg(cn->teacherName)
19777 					.arg(text));*/
19778 				delete cn;
19779 				cn=nullptr;
19780 				return nullptr;
19781 			}
19782 			assert(cn->maxMorningsPerWeek>0 && cn->maxMorningsPerWeek <= this->nDaysPerWeek);
19783 			xmlReadingLog+="    Max. mornings per week="+CustomFETString::number(cn->maxMorningsPerWeek)+"\n";
19784 		}
19785 		else{
19786 			unrecognizedXmlTags.append(xmlReader.name().toString());
19787 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
19788 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
19789 
19790 			xmlReader.skipCurrentElement();
19791 			xmlReaderNumberOfUnrecognizedFields++;
19792 		}
19793 	}
19794 	return cn;
19795 }
19796 
readTeachersMaxMorningsPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)19797 TimeConstraint* Rules::readTeachersMaxMorningsPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
19798 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxMorningsPerWeek"));
19799 
19800 	ConstraintTeachersMaxMorningsPerWeek* cn=new ConstraintTeachersMaxMorningsPerWeek();
19801 	while(xmlReader.readNextStartElement()){
19802 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
19803 		if(xmlReader.name()==QString("Weight_Percentage")){
19804 			QString text=xmlReader.readElementText();
19805 			cn->weightPercentage=customFETStrToDouble(text);
19806 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
19807 		}
19808 		else if(xmlReader.name()==QString("Active")){
19809 			QString text=xmlReader.readElementText();
19810 			if(text=="false"){
19811 				cn->active=false;
19812 			}
19813 		}
19814 		else if(xmlReader.name()==QString("Comments")){
19815 			QString text=xmlReader.readElementText();
19816 			cn->comments=text;
19817 		}
19818 		else if(xmlReader.name()==QString("Max_Mornings_Per_Week")){
19819 			QString text=xmlReader.readElementText();
19820 			cn->maxMorningsPerWeek=text.toInt();
19821 			if(cn->maxMorningsPerWeek<=0 || cn->maxMorningsPerWeek>this->nDaysPerWeek){
19822 				xmlReader.raiseError(tr("%1 is incorrect").arg("Max_Mornings_Per_Week"));
19823 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
19824 					tr("Constraint TeachersMaxDaysPerWeek max days corrupt, max days %1 <= 0 or >nDaysPerWeek, ignoring constraint")
19825 					.arg(text));*/
19826 				delete cn;
19827 				cn=nullptr;
19828 				return nullptr;
19829 			}
19830 			assert(cn->maxMorningsPerWeek>0 && cn->maxMorningsPerWeek <= this->nDaysPerWeek);
19831 			xmlReadingLog+="    Max. mornings per week="+CustomFETString::number(cn->maxMorningsPerWeek)+"\n";
19832 		}
19833 		else{
19834 			unrecognizedXmlTags.append(xmlReader.name().toString());
19835 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
19836 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
19837 
19838 			xmlReader.skipCurrentElement();
19839 			xmlReaderNumberOfUnrecognizedFields++;
19840 		}
19841 	}
19842 	return cn;
19843 }
19844 
readTeachersMaxTwoConsecutiveMornings(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)19845 TimeConstraint* Rules::readTeachersMaxTwoConsecutiveMornings(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
19846 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxTwoConsecutiveMornings"));
19847 
19848 	ConstraintTeachersMaxTwoConsecutiveMornings* cn=new ConstraintTeachersMaxTwoConsecutiveMornings();
19849 	while(xmlReader.readNextStartElement()){
19850 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
19851 		if(xmlReader.name()==QString("Weight_Percentage")){
19852 			QString text=xmlReader.readElementText();
19853 			cn->weightPercentage=customFETStrToDouble(text);
19854 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
19855 		}
19856 		else if(xmlReader.name()==QString("Active")){
19857 			QString text=xmlReader.readElementText();
19858 			if(text=="false"){
19859 				cn->active=false;
19860 			}
19861 		}
19862 		else if(xmlReader.name()==QString("Comments")){
19863 			QString text=xmlReader.readElementText();
19864 			cn->comments=text;
19865 		}
19866 		else{
19867 			unrecognizedXmlTags.append(xmlReader.name().toString());
19868 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
19869 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
19870 
19871 			xmlReader.skipCurrentElement();
19872 			xmlReaderNumberOfUnrecognizedFields++;
19873 		}
19874 	}
19875 	return cn;
19876 }
19877 
readTeacherMaxTwoConsecutiveMornings(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)19878 TimeConstraint* Rules::readTeacherMaxTwoConsecutiveMornings(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
19879 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxTwoConsecutiveMornings"));
19880 
19881 	ConstraintTeacherMaxTwoConsecutiveMornings* cn=new ConstraintTeacherMaxTwoConsecutiveMornings();
19882 	while(xmlReader.readNextStartElement()){
19883 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
19884 		if(xmlReader.name()==QString("Weight_Percentage")){
19885 			QString text=xmlReader.readElementText();
19886 			cn->weightPercentage=customFETStrToDouble(text);
19887 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
19888 		}
19889 		else if(xmlReader.name()==QString("Teacher_Name")){
19890 			QString text=xmlReader.readElementText();
19891 			cn->teacherName=text;
19892 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
19893 		}
19894 		else if(xmlReader.name()==QString("Active")){
19895 			QString text=xmlReader.readElementText();
19896 			if(text=="false"){
19897 				cn->active=false;
19898 			}
19899 		}
19900 		else if(xmlReader.name()==QString("Comments")){
19901 			QString text=xmlReader.readElementText();
19902 			cn->comments=text;
19903 		}
19904 		else{
19905 			unrecognizedXmlTags.append(xmlReader.name().toString());
19906 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
19907 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
19908 
19909 			xmlReader.skipCurrentElement();
19910 			xmlReaderNumberOfUnrecognizedFields++;
19911 		}
19912 	}
19913 	return cn;
19914 }
19915 
readTeachersMaxTwoConsecutiveAfternoons(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)19916 TimeConstraint* Rules::readTeachersMaxTwoConsecutiveAfternoons(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
19917 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxTwoConsecutiveAfternoons"));
19918 
19919 	ConstraintTeachersMaxTwoConsecutiveAfternoons* cn=new ConstraintTeachersMaxTwoConsecutiveAfternoons();
19920 	while(xmlReader.readNextStartElement()){
19921 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
19922 		if(xmlReader.name()==QString("Weight_Percentage")){
19923 			QString text=xmlReader.readElementText();
19924 			cn->weightPercentage=customFETStrToDouble(text);
19925 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
19926 		}
19927 		else if(xmlReader.name()==QString("Active")){
19928 			QString text=xmlReader.readElementText();
19929 			if(text=="false"){
19930 				cn->active=false;
19931 			}
19932 		}
19933 		else if(xmlReader.name()==QString("Comments")){
19934 			QString text=xmlReader.readElementText();
19935 			cn->comments=text;
19936 		}
19937 		else{
19938 			unrecognizedXmlTags.append(xmlReader.name().toString());
19939 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
19940 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
19941 
19942 			xmlReader.skipCurrentElement();
19943 			xmlReaderNumberOfUnrecognizedFields++;
19944 		}
19945 	}
19946 	return cn;
19947 }
19948 
readTeacherMaxTwoConsecutiveAfternoons(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)19949 TimeConstraint* Rules::readTeacherMaxTwoConsecutiveAfternoons(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
19950 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxTwoConsecutiveAfternoons"));
19951 
19952 	ConstraintTeacherMaxTwoConsecutiveAfternoons* cn=new ConstraintTeacherMaxTwoConsecutiveAfternoons();
19953 	while(xmlReader.readNextStartElement()){
19954 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
19955 		if(xmlReader.name()==QString("Weight_Percentage")){
19956 			QString text=xmlReader.readElementText();
19957 			cn->weightPercentage=customFETStrToDouble(text);
19958 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
19959 		}
19960 		else if(xmlReader.name()==QString("Teacher_Name")){
19961 			QString text=xmlReader.readElementText();
19962 			cn->teacherName=text;
19963 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
19964 		}
19965 		else if(xmlReader.name()==QString("Active")){
19966 			QString text=xmlReader.readElementText();
19967 			if(text=="false"){
19968 				cn->active=false;
19969 			}
19970 		}
19971 		else if(xmlReader.name()==QString("Comments")){
19972 			QString text=xmlReader.readElementText();
19973 			cn->comments=text;
19974 		}
19975 		else{
19976 			unrecognizedXmlTags.append(xmlReader.name().toString());
19977 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
19978 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
19979 
19980 			xmlReader.skipCurrentElement();
19981 			xmlReaderNumberOfUnrecognizedFields++;
19982 		}
19983 	}
19984 	return cn;
19985 }
19986 
readOldMATeacherMinDaysPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)19987 TimeConstraint* Rules::readOldMATeacherMinDaysPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
19988 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMinDaysPerWeek"));
19989 
19990 	ConstraintTeacherMinRealDaysPerWeek* cn=new ConstraintTeacherMinRealDaysPerWeek();
19991 	while(xmlReader.readNextStartElement()){
19992 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
19993 		if(xmlReader.name()==QString("Weight_Percentage")){
19994 			QString text=xmlReader.readElementText();
19995 			cn->weightPercentage=customFETStrToDouble(text);
19996 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
19997 		}
19998 		else if(xmlReader.name()==QString("Active")){
19999 			QString text=xmlReader.readElementText();
20000 			if(text=="false"){
20001 				cn->active=false;
20002 			}
20003 		}
20004 		else if(xmlReader.name()==QString("Comments")){
20005 			QString text=xmlReader.readElementText();
20006 			cn->comments=text;
20007 		}
20008 		else if(xmlReader.name()==QString("Teacher_Name")){
20009 			QString text=xmlReader.readElementText();
20010 			cn->teacherName=text;
20011 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
20012 		}
20013 		else if(xmlReader.name()==QString("Minimum_Days_Per_Week")){
20014 			QString text=xmlReader.readElementText();
20015 			cn->minDaysPerWeek=text.toInt();
20016 			if(cn->minDaysPerWeek<=0 || cn->minDaysPerWeek>this->nDaysPerWeek){
20017 				xmlReader.raiseError(tr("%1 is incorrect").arg("Minimum_Days_Per_Week"));
20018 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
20019 					tr("Constraint TeacherMinDaysPerWeek min days corrupt for teacher %1, min days %2 <= 0 or >nDaysPerWeek, ignoring constraint")
20020 					.arg(cn->teacherName)
20021 					.arg(text));*/
20022 				delete cn;
20023 				cn=nullptr;
20024 				return nullptr;
20025 			}
20026 			assert(cn->minDaysPerWeek>0 && cn->minDaysPerWeek <= this->nDaysPerWeek);
20027 			xmlReadingLog+="    Min. days per week="+CustomFETString::number(cn->minDaysPerWeek)+"\n";
20028 		}
20029 		else{
20030 			unrecognizedXmlTags.append(xmlReader.name().toString());
20031 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
20032 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
20033 
20034 			xmlReader.skipCurrentElement();
20035 			xmlReaderNumberOfUnrecognizedFields++;
20036 		}
20037 	}
20038 	return cn;
20039 }
20040 
readTeacherMinRealDaysPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)20041 TimeConstraint* Rules::readTeacherMinRealDaysPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
20042 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMinRealDaysPerWeek"));
20043 
20044 	ConstraintTeacherMinRealDaysPerWeek* cn=new ConstraintTeacherMinRealDaysPerWeek();
20045 	while(xmlReader.readNextStartElement()){
20046 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
20047 		if(xmlReader.name()==QString("Weight_Percentage")){
20048 			QString text=xmlReader.readElementText();
20049 			cn->weightPercentage=customFETStrToDouble(text);
20050 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
20051 		}
20052 		else if(xmlReader.name()==QString("Active")){
20053 			QString text=xmlReader.readElementText();
20054 			if(text=="false"){
20055 				cn->active=false;
20056 			}
20057 		}
20058 		else if(xmlReader.name()==QString("Comments")){
20059 			QString text=xmlReader.readElementText();
20060 			cn->comments=text;
20061 		}
20062 		else if(xmlReader.name()==QString("Teacher_Name")){
20063 			QString text=xmlReader.readElementText();
20064 			cn->teacherName=text;
20065 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
20066 		}
20067 		else if(xmlReader.name()==QString("Minimum_Days_Per_Week")){
20068 			QString text=xmlReader.readElementText();
20069 			cn->minDaysPerWeek=text.toInt();
20070 			if(cn->minDaysPerWeek<=0 || cn->minDaysPerWeek>this->nDaysPerWeek){
20071 				xmlReader.raiseError(tr("%1 is incorrect").arg("Minimum_Days_Per_Week"));
20072 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
20073 					tr("Constraint TeacherMinDaysPerWeek min days corrupt for teacher %1, min days %2 <= 0 or >nDaysPerWeek, ignoring constraint")
20074 					.arg(cn->teacherName)
20075 					.arg(text));*/
20076 				delete cn;
20077 				cn=nullptr;
20078 				return nullptr;
20079 			}
20080 			assert(cn->minDaysPerWeek>0 && cn->minDaysPerWeek <= this->nDaysPerWeek);
20081 			xmlReadingLog+="    Min. days per week="+CustomFETString::number(cn->minDaysPerWeek)+"\n";
20082 		}
20083 		else{
20084 			unrecognizedXmlTags.append(xmlReader.name().toString());
20085 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
20086 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
20087 
20088 			xmlReader.skipCurrentElement();
20089 			xmlReaderNumberOfUnrecognizedFields++;
20090 		}
20091 	}
20092 	return cn;
20093 }
20094 
readOldMATeachersMinDaysPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)20095 TimeConstraint* Rules::readOldMATeachersMinDaysPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
20096 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMinDaysPerWeek"));
20097 
20098 	ConstraintTeachersMinRealDaysPerWeek* cn=new ConstraintTeachersMinRealDaysPerWeek();
20099 	while(xmlReader.readNextStartElement()){
20100 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
20101 		if(xmlReader.name()==QString("Weight_Percentage")){
20102 			QString text=xmlReader.readElementText();
20103 			cn->weightPercentage=customFETStrToDouble(text);
20104 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
20105 		}
20106 		else if(xmlReader.name()==QString("Active")){
20107 			QString text=xmlReader.readElementText();
20108 			if(text=="false"){
20109 				cn->active=false;
20110 			}
20111 		}
20112 		else if(xmlReader.name()==QString("Comments")){
20113 			QString text=xmlReader.readElementText();
20114 			cn->comments=text;
20115 		}
20116 		else if(xmlReader.name()==QString("Minimum_Days_Per_Week")){
20117 			QString text=xmlReader.readElementText();
20118 			cn->minDaysPerWeek=text.toInt();
20119 			if(cn->minDaysPerWeek<=0 || cn->minDaysPerWeek>this->nDaysPerWeek){
20120 				xmlReader.raiseError(tr("%1 is incorrect").arg("Minimum_Days_Per_Week"));
20121 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
20122 					tr("Constraint TeachersMinDaysPerWeek min days corrupt, min days %1 <= 0 or >nDaysPerWeek, ignoring constraint")
20123 					.arg(text));*/
20124 				delete cn;
20125 				cn=nullptr;
20126 				return nullptr;
20127 			}
20128 			assert(cn->minDaysPerWeek>0 && cn->minDaysPerWeek <= this->nDaysPerWeek);
20129 			xmlReadingLog+="    Min. days per week="+CustomFETString::number(cn->minDaysPerWeek)+"\n";
20130 		}
20131 		else{
20132 			unrecognizedXmlTags.append(xmlReader.name().toString());
20133 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
20134 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
20135 
20136 			xmlReader.skipCurrentElement();
20137 			xmlReaderNumberOfUnrecognizedFields++;
20138 		}
20139 	}
20140 	return cn;
20141 }
20142 
readTeachersMinRealDaysPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)20143 TimeConstraint* Rules::readTeachersMinRealDaysPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
20144 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMinRealDaysPerWeek"));
20145 
20146 	ConstraintTeachersMinRealDaysPerWeek* cn=new ConstraintTeachersMinRealDaysPerWeek();
20147 	while(xmlReader.readNextStartElement()){
20148 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
20149 		if(xmlReader.name()==QString("Weight_Percentage")){
20150 			QString text=xmlReader.readElementText();
20151 			cn->weightPercentage=customFETStrToDouble(text);
20152 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
20153 		}
20154 		else if(xmlReader.name()==QString("Active")){
20155 			QString text=xmlReader.readElementText();
20156 			if(text=="false"){
20157 				cn->active=false;
20158 			}
20159 		}
20160 		else if(xmlReader.name()==QString("Comments")){
20161 			QString text=xmlReader.readElementText();
20162 			cn->comments=text;
20163 		}
20164 		else if(xmlReader.name()==QString("Minimum_Days_Per_Week")){
20165 			QString text=xmlReader.readElementText();
20166 			cn->minDaysPerWeek=text.toInt();
20167 			if(cn->minDaysPerWeek<=0 || cn->minDaysPerWeek>this->nDaysPerWeek){
20168 				xmlReader.raiseError(tr("%1 is incorrect").arg("Minimum_Days_Per_Week"));
20169 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
20170 					tr("Constraint TeachersMinDaysPerWeek min days corrupt, min days %1 <= 0 or >nDaysPerWeek, ignoring constraint")
20171 					.arg(text));*/
20172 				delete cn;
20173 				cn=nullptr;
20174 				return nullptr;
20175 			}
20176 			assert(cn->minDaysPerWeek>0 && cn->minDaysPerWeek <= this->nDaysPerWeek);
20177 			xmlReadingLog+="    Min. days per week="+CustomFETString::number(cn->minDaysPerWeek)+"\n";
20178 		}
20179 		else{
20180 			unrecognizedXmlTags.append(xmlReader.name().toString());
20181 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
20182 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
20183 
20184 			xmlReader.skipCurrentElement();
20185 			xmlReaderNumberOfUnrecognizedFields++;
20186 		}
20187 	}
20188 	return cn;
20189 }
20190 
readTeacherMinMorningsPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)20191 TimeConstraint* Rules::readTeacherMinMorningsPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
20192 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMinMorningsPerWeek"));
20193 
20194 	ConstraintTeacherMinMorningsPerWeek* cn=new ConstraintTeacherMinMorningsPerWeek();
20195 	while(xmlReader.readNextStartElement()){
20196 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
20197 		if(xmlReader.name()==QString("Weight_Percentage")){
20198 			QString text=xmlReader.readElementText();
20199 			cn->weightPercentage=customFETStrToDouble(text);
20200 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
20201 		}
20202 		else if(xmlReader.name()==QString("Active")){
20203 			QString text=xmlReader.readElementText();
20204 			if(text=="false"){
20205 				cn->active=false;
20206 			}
20207 		}
20208 		else if(xmlReader.name()==QString("Comments")){
20209 			QString text=xmlReader.readElementText();
20210 			cn->comments=text;
20211 		}
20212 		else if(xmlReader.name()==QString("Teacher_Name")){
20213 			QString text=xmlReader.readElementText();
20214 			cn->teacherName=text;
20215 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
20216 		}
20217 		else if(xmlReader.name()==QString("Minimum_Mornings_Per_Week")){
20218 			QString text=xmlReader.readElementText();
20219 			cn->minMorningsPerWeek=text.toInt();
20220 			if(cn->minMorningsPerWeek<=0 || cn->minMorningsPerWeek>this->nDaysPerWeek/2){
20221 				xmlReader.raiseError(tr("%1 is incorrect").arg("Minimum_Mornings_Per_Week"));
20222 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
20223 					tr("Constraint TeacherMinMorningsPerWeek min days corrupt for teacher %1, min days %2 <= 0 or >nMorningsPerWeek, ignoring constraint")
20224 					.arg(cn->teacherName)
20225 					.arg(text));*/
20226 				delete cn;
20227 				cn=nullptr;
20228 				return nullptr;
20229 			}
20230 			assert(cn->minMorningsPerWeek>0 && cn->minMorningsPerWeek <= this->nDaysPerWeek/2);
20231 			xmlReadingLog+="    Min. days per week="+CustomFETString::number(cn->minMorningsPerWeek)+"\n";
20232 		}
20233 		else{
20234 			unrecognizedXmlTags.append(xmlReader.name().toString());
20235 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
20236 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
20237 
20238 			xmlReader.skipCurrentElement();
20239 			xmlReaderNumberOfUnrecognizedFields++;
20240 		}
20241 	}
20242 	return cn;
20243 }
20244 
readTeachersMinMorningsPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)20245 TimeConstraint* Rules::readTeachersMinMorningsPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
20246 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMinMorningsPerWeek"));
20247 
20248 	ConstraintTeachersMinMorningsPerWeek* cn=new ConstraintTeachersMinMorningsPerWeek();
20249 	while(xmlReader.readNextStartElement()){
20250 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
20251 		if(xmlReader.name()==QString("Weight_Percentage")){
20252 			QString text=xmlReader.readElementText();
20253 			cn->weightPercentage=customFETStrToDouble(text);
20254 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
20255 		}
20256 		else if(xmlReader.name()==QString("Active")){
20257 			QString text=xmlReader.readElementText();
20258 			if(text=="false"){
20259 				cn->active=false;
20260 			}
20261 		}
20262 		else if(xmlReader.name()==QString("Comments")){
20263 			QString text=xmlReader.readElementText();
20264 			cn->comments=text;
20265 		}
20266 		else if(xmlReader.name()==QString("Minimum_Mornings_Per_Week")){
20267 			QString text=xmlReader.readElementText();
20268 			cn->minMorningsPerWeek=text.toInt();
20269 			if(cn->minMorningsPerWeek<=0 || cn->minMorningsPerWeek>this->nDaysPerWeek/2){
20270 				xmlReader.raiseError(tr("%1 is incorrect").arg("Minimum_Mornings_Per_Week"));
20271 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
20272 					tr("Constraint TeachersMinMorningsPerWeek min days corrupt, min days %1 <= 0 or >nMorningsPerWeek, ignoring constraint")
20273 					.arg(text));*/
20274 				delete cn;
20275 				cn=nullptr;
20276 				return nullptr;
20277 			}
20278 			assert(cn->minMorningsPerWeek>0 && cn->minMorningsPerWeek <= this->nDaysPerWeek/2);
20279 			xmlReadingLog+="    Min. days per week="+CustomFETString::number(cn->minMorningsPerWeek)+"\n";
20280 		}
20281 		else{
20282 			unrecognizedXmlTags.append(xmlReader.name().toString());
20283 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
20284 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
20285 
20286 			xmlReader.skipCurrentElement();
20287 			xmlReaderNumberOfUnrecognizedFields++;
20288 		}
20289 	}
20290 	return cn;
20291 }
20292 
readTeacherMinAfternoonsPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)20293 TimeConstraint* Rules::readTeacherMinAfternoonsPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
20294 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMinAfternoonsPerWeek"));
20295 
20296 	ConstraintTeacherMinAfternoonsPerWeek* cn=new ConstraintTeacherMinAfternoonsPerWeek();
20297 	while(xmlReader.readNextStartElement()){
20298 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
20299 		if(xmlReader.name()==QString("Weight_Percentage")){
20300 			QString text=xmlReader.readElementText();
20301 			cn->weightPercentage=customFETStrToDouble(text);
20302 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
20303 		}
20304 		else if(xmlReader.name()==QString("Active")){
20305 			QString text=xmlReader.readElementText();
20306 			if(text=="false"){
20307 				cn->active=false;
20308 			}
20309 		}
20310 		else if(xmlReader.name()==QString("Comments")){
20311 			QString text=xmlReader.readElementText();
20312 			cn->comments=text;
20313 		}
20314 		else if(xmlReader.name()==QString("Teacher_Name")){
20315 			QString text=xmlReader.readElementText();
20316 			cn->teacherName=text;
20317 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
20318 		}
20319 		else if(xmlReader.name()==QString("Minimum_Afternoons_Per_Week")){
20320 			QString text=xmlReader.readElementText();
20321 			cn->minAfternoonsPerWeek=text.toInt();
20322 			if(cn->minAfternoonsPerWeek<=0 || cn->minAfternoonsPerWeek>this->nDaysPerWeek/2){
20323 				xmlReader.raiseError(tr("%1 is incorrect").arg("Minimum_Afternoons_Per_Week"));
20324 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
20325 					tr("Constraint TeacherMinAfternoonsPerWeek min days corrupt for teacher %1, min days %2 <= 0 or >nAfternoonsPerWeek, ignoring constraint")
20326 					.arg(cn->teacherName)
20327 					.arg(text));*/
20328 				delete cn;
20329 				cn=nullptr;
20330 				return nullptr;
20331 			}
20332 			assert(cn->minAfternoonsPerWeek>0 && cn->minAfternoonsPerWeek <= this->nDaysPerWeek/2);
20333 			xmlReadingLog+="    Min. days per week="+CustomFETString::number(cn->minAfternoonsPerWeek)+"\n";
20334 		}
20335 		else{
20336 			unrecognizedXmlTags.append(xmlReader.name().toString());
20337 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
20338 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
20339 
20340 			xmlReader.skipCurrentElement();
20341 			xmlReaderNumberOfUnrecognizedFields++;
20342 		}
20343 	}
20344 	return cn;
20345 }
20346 
readTeachersMinAfternoonsPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)20347 TimeConstraint* Rules::readTeachersMinAfternoonsPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
20348 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMinAfternoonsPerWeek"));
20349 
20350 	ConstraintTeachersMinAfternoonsPerWeek* cn=new ConstraintTeachersMinAfternoonsPerWeek();
20351 	while(xmlReader.readNextStartElement()){
20352 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
20353 		if(xmlReader.name()==QString("Weight_Percentage")){
20354 			QString text=xmlReader.readElementText();
20355 			cn->weightPercentage=customFETStrToDouble(text);
20356 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
20357 		}
20358 		else if(xmlReader.name()==QString("Active")){
20359 			QString text=xmlReader.readElementText();
20360 			if(text=="false"){
20361 				cn->active=false;
20362 			}
20363 		}
20364 		else if(xmlReader.name()==QString("Comments")){
20365 			QString text=xmlReader.readElementText();
20366 			cn->comments=text;
20367 		}
20368 		else if(xmlReader.name()==QString("Minimum_Afternoons_Per_Week")){
20369 			QString text=xmlReader.readElementText();
20370 			cn->minAfternoonsPerWeek=text.toInt();
20371 			if(cn->minAfternoonsPerWeek<=0 || cn->minAfternoonsPerWeek>this->nDaysPerWeek/2){
20372 				xmlReader.raiseError(tr("%1 is incorrect").arg("Minimum_Afternoons_Per_Week"));
20373 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
20374 					tr("Constraint TeachersMinAfternoonsPerWeek min days corrupt, min days %1 <= 0 or >nAfternoonsPerWeek, ignoring constraint")
20375 					.arg(text));*/
20376 				delete cn;
20377 				cn=nullptr;
20378 				return nullptr;
20379 			}
20380 			assert(cn->minAfternoonsPerWeek>0 && cn->minAfternoonsPerWeek <= this->nDaysPerWeek/2);
20381 			xmlReadingLog+="    Min. days per week="+CustomFETString::number(cn->minAfternoonsPerWeek)+"\n";
20382 		}
20383 		else{
20384 			unrecognizedXmlTags.append(xmlReader.name().toString());
20385 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
20386 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
20387 
20388 			xmlReader.skipCurrentElement();
20389 			xmlReaderNumberOfUnrecognizedFields++;
20390 		}
20391 	}
20392 	return cn;
20393 }
20394 
20395 //morning
readTeacherMorningIntervalMaxDaysPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)20396 TimeConstraint* Rules::readTeacherMorningIntervalMaxDaysPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
20397 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMorningIntervalMaxDaysPerWeek"));
20398 	ConstraintTeacherMorningIntervalMaxDaysPerWeek* cn=new ConstraintTeacherMorningIntervalMaxDaysPerWeek();
20399 	cn->maxDaysPerWeek=this->nDaysPerWeek;
20400 	cn->startHour=this->nHoursPerDay;
20401 	cn->endHour=this->nHoursPerDay;
20402 	int h1, h2;
20403 	while(xmlReader.readNextStartElement()){
20404 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
20405 		if(xmlReader.name()==QString("Weight")){
20406 			//cn->weight=customFETStrToDouble(text);
20407 			xmlReader.skipCurrentElement();
20408 			xmlReadingLog+="    Ignoring old tag - weight - generating 100% weight percentage\n";
20409 			cn->weightPercentage=100;
20410 		}
20411 		else if(xmlReader.name()==QString("Weight_Percentage")){
20412 			QString text=xmlReader.readElementText();
20413 			cn->weightPercentage=customFETStrToDouble(text);
20414 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
20415 		}
20416 		else if(xmlReader.name()==QString("Active")){
20417 			QString text=xmlReader.readElementText();
20418 			if(text=="false"){
20419 				cn->active=false;
20420 			}
20421 		}
20422 		else if(xmlReader.name()==QString("Comments")){
20423 			QString text=xmlReader.readElementText();
20424 			cn->comments=text;
20425 		}
20426 		else if(xmlReader.name()==QString("Compulsory")){
20427 			QString text=xmlReader.readElementText();
20428 			if(text=="yes"){
20429 				//cn->compulsory=true;
20430 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
20431 				cn->weightPercentage=100;
20432 			}
20433 			else{
20434 				//cn->compulsory=false;
20435 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
20436 				cn->weightPercentage=0;
20437 			}
20438 		}
20439 		else if(xmlReader.name()==QString("Teacher_Name")){
20440 			QString text=xmlReader.readElementText();
20441 			cn->teacherName=text;
20442 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
20443 		}
20444 		else if(xmlReader.name()==QString("Max_Days_Per_Week")){
20445 			QString text=xmlReader.readElementText();
20446 			cn->maxDaysPerWeek=text.toInt();
20447 			if(cn->maxDaysPerWeek>this->nDaysPerWeek/2){
20448 				RulesReconcilableMessage::information(parent, tr("FET information"),
20449 					tr("Constraint TeacherMorningIntervalMaxDaysPerWeek max days corrupt for teacher %1, max days %2 >nDaysPerWeek/2, constraint added, please correct constraint")
20450 					.arg(cn->teacherName)
20451 					.arg(text));
20452 				/*delete cn;
20453 				cn=nullptr;
20454 				goto corruptConstraintTime;*/
20455 			}
20456 			//assert(cn->maxDaysPerWeek>0 && cn->maxDaysPerWeek <= this->nDaysPerWeek);
20457 			xmlReadingLog+="    Max. days per week="+CustomFETString::number(cn->maxDaysPerWeek)+"\n";
20458 		}
20459 		else if(xmlReader.name()==QString("Interval_Start_Hour")){
20460 			QString text=xmlReader.readElementText();
20461 			for(h1=0; h1 < this->nHoursPerDay; h1++)
20462 				if(this->hoursOfTheDay[h1]==text)
20463 					break;
20464 			if(h1>=this->nHoursPerDay){
20465 				xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
20466 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
20467 					tr("Constraint Teacher interval max days per week start hour corrupt for teacher %1, hour %2 is inexistent ... ignoring constraint")
20468 					.arg(cn->teacherName)
20469 					.arg(text));*/
20470 				delete cn;
20471 				//cn=nullptr;
20472 				//goto corruptConstraintTime;
20473 				return nullptr;
20474 			}
20475 			assert(h1>=0 && h1 < this->nHoursPerDay);
20476 			xmlReadingLog+="    Interval start hour="+this->hoursOfTheDay[h1]+"\n";
20477 			cn->startHour=h1;
20478 		}
20479 		else if(xmlReader.name()==QString("Interval_End_Hour")){
20480 			QString text=xmlReader.readElementText();
20481 			if(text==""){
20482 				xmlReadingLog+="    Interval end hour void, meaning end of day\n";
20483 				cn->endHour=this->nHoursPerDay;
20484 			}
20485 			else{
20486 				for(h2=0; h2 < this->nHoursPerDay; h2++)
20487 					if(this->hoursOfTheDay[h2]==text)
20488 						break;
20489 				if(h2>=this->nHoursPerDay){
20490 					xmlReader.raiseError(tr("Hour %1 is inexistent (it is also not void, to specify end of the day)").arg(text));
20491 					/*RulesReconcilableMessage::information(parent, tr("FET information"),
20492 						tr("Constraint Teacher interval max days per week end hour corrupt for teacher %1, hour %2 is inexistent (it is also not void, to specify end of the day) ... ignoring constraint")
20493 						.arg(cn->teacherName)
20494 						.arg(text));*/
20495 					delete cn;
20496 					//cn=nullptr;
20497 					//goto corruptConstraintTime;
20498 					return nullptr;
20499 				}
20500 				assert(h2>=0 && h2 < this->nHoursPerDay);
20501 				xmlReadingLog+="    Interval end hour="+this->hoursOfTheDay[h2]+"\n";
20502 				cn->endHour=h2;
20503 			}
20504 		}
20505 		else{
20506 			unrecognizedXmlTags.append(xmlReader.name().toString());
20507 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
20508 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
20509 
20510 			xmlReader.skipCurrentElement();
20511 			xmlReaderNumberOfUnrecognizedFields++;
20512 		}
20513 	}
20514 	return cn;
20515 }
20516 
readTeachersMorningIntervalMaxDaysPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)20517 TimeConstraint* Rules::readTeachersMorningIntervalMaxDaysPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
20518 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMorningIntervalMaxDaysPerWeek"));
20519 	ConstraintTeachersMorningIntervalMaxDaysPerWeek* cn=new ConstraintTeachersMorningIntervalMaxDaysPerWeek();
20520 	cn->maxDaysPerWeek=this->nDaysPerWeek;
20521 	cn->startHour=this->nHoursPerDay;
20522 	cn->endHour=this->nHoursPerDay;
20523 	int h1, h2;
20524 	while(xmlReader.readNextStartElement()){
20525 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
20526 		if(xmlReader.name()==QString("Weight")){
20527 			//cn->weight=customFETStrToDouble(text);
20528 			xmlReader.skipCurrentElement();
20529 			xmlReadingLog+="    Ignoring old tag - weight - generating 100% weight percentage\n";
20530 			cn->weightPercentage=100;
20531 		}
20532 		else if(xmlReader.name()==QString("Weight_Percentage")){
20533 			QString text=xmlReader.readElementText();
20534 			cn->weightPercentage=customFETStrToDouble(text);
20535 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
20536 		}
20537 		else if(xmlReader.name()==QString("Active")){
20538 			QString text=xmlReader.readElementText();
20539 			if(text=="false"){
20540 				cn->active=false;
20541 			}
20542 		}
20543 		else if(xmlReader.name()==QString("Comments")){
20544 			QString text=xmlReader.readElementText();
20545 			cn->comments=text;
20546 		}
20547 		else if(xmlReader.name()==QString("Compulsory")){
20548 			QString text=xmlReader.readElementText();
20549 			if(text=="yes"){
20550 				//cn->compulsory=true;
20551 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
20552 				cn->weightPercentage=100;
20553 			}
20554 			else{
20555 				//cn->compulsory=false;
20556 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
20557 				cn->weightPercentage=0;
20558 			}
20559 		}
20560 		/*else if(xmlReader.name()==QString("Teacher_Name")){
20561 			cn->teacherName=text;
20562 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
20563 		}*/
20564 		else if(xmlReader.name()==QString("Max_Days_Per_Week")){
20565 			QString text=xmlReader.readElementText();
20566 			cn->maxDaysPerWeek=text.toInt();
20567 			if(cn->maxDaysPerWeek>this->nDaysPerWeek/2){
20568 				RulesReconcilableMessage::information(parent, tr("FET information"),
20569 					tr("Constraint TeachersMorningIntervalMaxDaysPerWeek max days corrupt, max days %1 >nDaysPerWeek/2, constraint added, please correct constraint")
20570 					//.arg(cn->teacherName)
20571 					.arg(text));
20572 				/*delete cn;
20573 				cn=nullptr;
20574 				goto corruptConstraintTime;*/
20575 			}
20576 			//assert(cn->maxDaysPerWeek>0 && cn->maxDaysPerWeek <= this->nDaysPerWeek);
20577 			xmlReadingLog+="    Max. days per week="+CustomFETString::number(cn->maxDaysPerWeek)+"\n";
20578 		}
20579 		else if(xmlReader.name()==QString("Interval_Start_Hour")){
20580 			QString text=xmlReader.readElementText();
20581 			for(h1=0; h1 < this->nHoursPerDay; h1++)
20582 				if(this->hoursOfTheDay[h1]==text)
20583 					break;
20584 			if(h1>=this->nHoursPerDay){
20585 				xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
20586 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
20587 					tr("Constraint Teachers interval max days per week start hour corrupt because hour %1 is inexistent ... ignoring constraint")
20588 					//.arg(cn->teacherName)
20589 					.arg(text));*/
20590 				delete cn;
20591 				//cn=nullptr;
20592 				//goto corruptConstraintTime;
20593 				return nullptr;
20594 			}
20595 			assert(h1>=0 && h1 < this->nHoursPerDay);
20596 			xmlReadingLog+="    Interval start hour="+this->hoursOfTheDay[h1]+"\n";
20597 			cn->startHour=h1;
20598 		}
20599 		else if(xmlReader.name()==QString("Interval_End_Hour")){
20600 			QString text=xmlReader.readElementText();
20601 			if(text==""){
20602 				xmlReadingLog+="    Interval end hour void, meaning end of day\n";
20603 				cn->endHour=this->nHoursPerDay;
20604 			}
20605 			else{
20606 				for(h2=0; h2 < this->nHoursPerDay; h2++)
20607 					if(this->hoursOfTheDay[h2]==text)
20608 						break;
20609 				if(h2>=this->nHoursPerDay){
20610 					xmlReader.raiseError(tr("Hour %1 is inexistent (it is also not void, to specify end of the day)").arg(text));
20611 					/*RulesReconcilableMessage::information(parent, tr("FET information"),
20612 						tr("Constraint Teachers interval max days per week end hour corrupt because hour %1 is inexistent (it is also not void, to specify end of the day) ... ignoring constraint")
20613 						//.arg(cn->teacherName)
20614 						.arg(text));*/
20615 					delete cn;
20616 					//cn=nullptr;
20617 					//goto corruptConstraintTime;
20618 					return nullptr;
20619 				}
20620 				assert(h2>=0 && h2 < this->nHoursPerDay);
20621 				xmlReadingLog+="    Interval end hour="+this->hoursOfTheDay[h2]+"\n";
20622 				cn->endHour=h2;
20623 			}
20624 		}
20625 		else{
20626 			unrecognizedXmlTags.append(xmlReader.name().toString());
20627 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
20628 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
20629 
20630 			xmlReader.skipCurrentElement();
20631 			xmlReaderNumberOfUnrecognizedFields++;
20632 		}
20633 	}
20634 	return cn;
20635 }
20636 
20637 //afternoon
readTeacherAfternoonIntervalMaxDaysPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)20638 TimeConstraint* Rules::readTeacherAfternoonIntervalMaxDaysPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
20639 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherAfternoonIntervalMaxDaysPerWeek"));
20640 	ConstraintTeacherAfternoonIntervalMaxDaysPerWeek* cn=new ConstraintTeacherAfternoonIntervalMaxDaysPerWeek();
20641 	cn->maxDaysPerWeek=this->nDaysPerWeek;
20642 	cn->startHour=this->nHoursPerDay;
20643 	cn->endHour=this->nHoursPerDay;
20644 	int h1, h2;
20645 	while(xmlReader.readNextStartElement()){
20646 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
20647 		if(xmlReader.name()==QString("Weight")){
20648 			//cn->weight=customFETStrToDouble(text);
20649 			xmlReader.skipCurrentElement();
20650 			xmlReadingLog+="    Ignoring old tag - weight - generating 100% weight percentage\n";
20651 			cn->weightPercentage=100;
20652 		}
20653 		else if(xmlReader.name()==QString("Weight_Percentage")){
20654 			QString text=xmlReader.readElementText();
20655 			cn->weightPercentage=customFETStrToDouble(text);
20656 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
20657 		}
20658 		else if(xmlReader.name()==QString("Active")){
20659 			QString text=xmlReader.readElementText();
20660 			if(text=="false"){
20661 				cn->active=false;
20662 			}
20663 		}
20664 		else if(xmlReader.name()==QString("Comments")){
20665 			QString text=xmlReader.readElementText();
20666 			cn->comments=text;
20667 		}
20668 		else if(xmlReader.name()==QString("Compulsory")){
20669 			QString text=xmlReader.readElementText();
20670 			if(text=="yes"){
20671 				//cn->compulsory=true;
20672 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
20673 				cn->weightPercentage=100;
20674 			}
20675 			else{
20676 				//cn->compulsory=false;
20677 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
20678 				cn->weightPercentage=0;
20679 			}
20680 		}
20681 		else if(xmlReader.name()==QString("Teacher_Name")){
20682 			QString text=xmlReader.readElementText();
20683 			cn->teacherName=text;
20684 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
20685 		}
20686 		else if(xmlReader.name()==QString("Max_Days_Per_Week")){
20687 			QString text=xmlReader.readElementText();
20688 			cn->maxDaysPerWeek=text.toInt();
20689 			if(cn->maxDaysPerWeek>this->nDaysPerWeek/2){
20690 				RulesReconcilableMessage::information(parent, tr("FET information"),
20691 					tr("Constraint TeacherAfternoonIntervalMaxDaysPerWeek max days corrupt for teacher %1, max days %2 >nDaysPerWeek/2, constraint added, please correct constraint")
20692 					.arg(cn->teacherName)
20693 					.arg(text));
20694 				/*delete cn;
20695 				cn=nullptr;
20696 				goto corruptConstraintTime;*/
20697 			}
20698 			//assert(cn->maxDaysPerWeek>0 && cn->maxDaysPerWeek <= this->nDaysPerWeek);
20699 			xmlReadingLog+="    Max. days per week="+CustomFETString::number(cn->maxDaysPerWeek)+"\n";
20700 		}
20701 		else if(xmlReader.name()==QString("Interval_Start_Hour")){
20702 			QString text=xmlReader.readElementText();
20703 			for(h1=0; h1 < this->nHoursPerDay; h1++)
20704 				if(this->hoursOfTheDay[h1]==text)
20705 					break;
20706 			if(h1>=this->nHoursPerDay){
20707 				xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
20708 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
20709 					tr("Constraint Teacher interval max days per week start hour corrupt for teacher %1, hour %2 is inexistent ... ignoring constraint")
20710 					.arg(cn->teacherName)
20711 					.arg(text));*/
20712 				delete cn;
20713 				//cn=nullptr;
20714 				//goto corruptConstraintTime;
20715 				return nullptr;
20716 			}
20717 			assert(h1>=0 && h1 < this->nHoursPerDay);
20718 			xmlReadingLog+="    Interval start hour="+this->hoursOfTheDay[h1]+"\n";
20719 			cn->startHour=h1;
20720 		}
20721 		else if(xmlReader.name()==QString("Interval_End_Hour")){
20722 			QString text=xmlReader.readElementText();
20723 			if(text==""){
20724 				xmlReadingLog+="    Interval end hour void, meaning end of day\n";
20725 				cn->endHour=this->nHoursPerDay;
20726 			}
20727 			else{
20728 				for(h2=0; h2 < this->nHoursPerDay; h2++)
20729 					if(this->hoursOfTheDay[h2]==text)
20730 						break;
20731 				if(h2>=this->nHoursPerDay){
20732 					xmlReader.raiseError(tr("Hour %1 is inexistent (it is also not void, to specify end of the day)").arg(text));
20733 					/*RulesReconcilableMessage::information(parent, tr("FET information"),
20734 						tr("Constraint Teacher interval max days per week end hour corrupt for teacher %1, hour %2 is inexistent (it is also not void, to specify end of the day) ... ignoring constraint")
20735 						.arg(cn->teacherName)
20736 						.arg(text));*/
20737 					delete cn;
20738 					//cn=nullptr;
20739 					//goto corruptConstraintTime;
20740 					return nullptr;
20741 				}
20742 				assert(h2>=0 && h2 < this->nHoursPerDay);
20743 				xmlReadingLog+="    Interval end hour="+this->hoursOfTheDay[h2]+"\n";
20744 				cn->endHour=h2;
20745 			}
20746 		}
20747 		else{
20748 			unrecognizedXmlTags.append(xmlReader.name().toString());
20749 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
20750 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
20751 
20752 			xmlReader.skipCurrentElement();
20753 			xmlReaderNumberOfUnrecognizedFields++;
20754 		}
20755 	}
20756 	return cn;
20757 }
20758 
readTeachersAfternoonIntervalMaxDaysPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)20759 TimeConstraint* Rules::readTeachersAfternoonIntervalMaxDaysPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
20760 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersAfternoonIntervalMaxDaysPerWeek"));
20761 	ConstraintTeachersAfternoonIntervalMaxDaysPerWeek* cn=new ConstraintTeachersAfternoonIntervalMaxDaysPerWeek();
20762 	cn->maxDaysPerWeek=this->nDaysPerWeek;
20763 	cn->startHour=this->nHoursPerDay;
20764 	cn->endHour=this->nHoursPerDay;
20765 	int h1, h2;
20766 	while(xmlReader.readNextStartElement()){
20767 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
20768 		if(xmlReader.name()==QString("Weight")){
20769 			//cn->weight=customFETStrToDouble(text);
20770 			xmlReader.skipCurrentElement();
20771 			xmlReadingLog+="    Ignoring old tag - weight - generating 100% weight percentage\n";
20772 			cn->weightPercentage=100;
20773 		}
20774 		else if(xmlReader.name()==QString("Weight_Percentage")){
20775 			QString text=xmlReader.readElementText();
20776 			cn->weightPercentage=customFETStrToDouble(text);
20777 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
20778 		}
20779 		else if(xmlReader.name()==QString("Active")){
20780 			QString text=xmlReader.readElementText();
20781 			if(text=="false"){
20782 				cn->active=false;
20783 			}
20784 		}
20785 		else if(xmlReader.name()==QString("Comments")){
20786 			QString text=xmlReader.readElementText();
20787 			cn->comments=text;
20788 		}
20789 		else if(xmlReader.name()==QString("Compulsory")){
20790 			QString text=xmlReader.readElementText();
20791 			if(text=="yes"){
20792 				//cn->compulsory=true;
20793 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
20794 				cn->weightPercentage=100;
20795 			}
20796 			else{
20797 				//cn->compulsory=false;
20798 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
20799 				cn->weightPercentage=0;
20800 			}
20801 		}
20802 		/*else if(xmlReader.name()==QString("Teacher_Name")){
20803 			cn->teacherName=text;
20804 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
20805 		}*/
20806 		else if(xmlReader.name()==QString("Max_Days_Per_Week")){
20807 			QString text=xmlReader.readElementText();
20808 			cn->maxDaysPerWeek=text.toInt();
20809 			if(cn->maxDaysPerWeek>this->nDaysPerWeek/2){
20810 				RulesReconcilableMessage::information(parent, tr("FET information"),
20811 					tr("Constraint TeachersAfternoonIntervalMaxDaysPerWeek max days corrupt, max days %1 >nDaysPerWeek/2, constraint added, please correct constraint")
20812 					//.arg(cn->teacherName)
20813 					.arg(text));
20814 				/*delete cn;
20815 				cn=nullptr;
20816 				goto corruptConstraintTime;*/
20817 			}
20818 			//assert(cn->maxDaysPerWeek>0 && cn->maxDaysPerWeek <= this->nDaysPerWeek);
20819 			xmlReadingLog+="    Max. days per week="+CustomFETString::number(cn->maxDaysPerWeek)+"\n";
20820 		}
20821 		else if(xmlReader.name()==QString("Interval_Start_Hour")){
20822 			QString text=xmlReader.readElementText();
20823 			for(h1=0; h1 < this->nHoursPerDay; h1++)
20824 				if(this->hoursOfTheDay[h1]==text)
20825 					break;
20826 			if(h1>=this->nHoursPerDay){
20827 				xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
20828 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
20829 					tr("Constraint Teachers interval max days per week start hour corrupt because hour %1 is inexistent ... ignoring constraint")
20830 					//.arg(cn->teacherName)
20831 					.arg(text));*/
20832 				delete cn;
20833 				//cn=nullptr;
20834 				//goto corruptConstraintTime;
20835 				return nullptr;
20836 			}
20837 			assert(h1>=0 && h1 < this->nHoursPerDay);
20838 			xmlReadingLog+="    Interval start hour="+this->hoursOfTheDay[h1]+"\n";
20839 			cn->startHour=h1;
20840 		}
20841 		else if(xmlReader.name()==QString("Interval_End_Hour")){
20842 			QString text=xmlReader.readElementText();
20843 			if(text==""){
20844 				xmlReadingLog+="    Interval end hour void, meaning end of day\n";
20845 				cn->endHour=this->nHoursPerDay;
20846 			}
20847 			else{
20848 				for(h2=0; h2 < this->nHoursPerDay; h2++)
20849 					if(this->hoursOfTheDay[h2]==text)
20850 						break;
20851 				if(h2>=this->nHoursPerDay){
20852 					xmlReader.raiseError(tr("Hour %1 is inexistent (it is also not void, to specify end of the day)").arg(text));
20853 					/*RulesReconcilableMessage::information(parent, tr("FET information"),
20854 						tr("Constraint Teachers interval max days per week end hour corrupt because hour %1 is inexistent (it is also not void, to specify end of the day) ... ignoring constraint")
20855 						//.arg(cn->teacherName)
20856 						.arg(text));*/
20857 					delete cn;
20858 					//cn=nullptr;
20859 					//goto corruptConstraintTime;
20860 					return nullptr;
20861 				}
20862 				assert(h2>=0 && h2 < this->nHoursPerDay);
20863 				xmlReadingLog+="    Interval end hour="+this->hoursOfTheDay[h2]+"\n";
20864 				cn->endHour=h2;
20865 			}
20866 		}
20867 		else{
20868 			unrecognizedXmlTags.append(xmlReader.name().toString());
20869 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
20870 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
20871 
20872 			xmlReader.skipCurrentElement();
20873 			xmlReaderNumberOfUnrecognizedFields++;
20874 		}
20875 	}
20876 	return cn;
20877 }
20878 
readOldMAStudentsSetMaxDaysPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)20879 TimeConstraint* Rules::readOldMAStudentsSetMaxDaysPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
20880 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMaxDaysPerWeek"));
20881 	ConstraintStudentsSetMaxRealDaysPerWeek* cn=new ConstraintStudentsSetMaxRealDaysPerWeek();
20882 	cn->maxDaysPerWeek=this->nDaysPerWeek;
20883 	while(xmlReader.readNextStartElement()){
20884 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
20885 		if(xmlReader.name()==QString("Weight_Percentage")){
20886 			QString text=xmlReader.readElementText();
20887 			cn->weightPercentage=customFETStrToDouble(text);
20888 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
20889 		}
20890 		else if(xmlReader.name()==QString("Active")){
20891 			QString text=xmlReader.readElementText();
20892 			if(text=="false"){
20893 				cn->active=false;
20894 			}
20895 		}
20896 		else if(xmlReader.name()==QString("Comments")){
20897 			QString text=xmlReader.readElementText();
20898 			cn->comments=text;
20899 		}
20900 		else if(xmlReader.name()==QString("Students")){
20901 			QString text=xmlReader.readElementText();
20902 			cn->students=text;
20903 			xmlReadingLog+="    Read students set name="+cn->students+"\n";
20904 		}
20905 		else if(xmlReader.name()==QString("Max_Days_Per_Week")){
20906 			QString text=xmlReader.readElementText();
20907 			cn->maxDaysPerWeek=text.toInt();
20908 			if(cn->maxDaysPerWeek>this->nDaysPerWeek){
20909 				RulesReconcilableMessage::information(parent, tr("FET information"),
20910 					tr("Constraint StudentsSetMaxDaysPerWeek max days corrupt for students set %1, max days %2 >nDaysPerWeek, constraint added, please correct constraint")
20911 					.arg(cn->students)
20912 					.arg(text));
20913 			}
20914 			xmlReadingLog+="    Max. days per week="+CustomFETString::number(cn->maxDaysPerWeek)+"\n";
20915 		}
20916 		else{
20917 			unrecognizedXmlTags.append(xmlReader.name().toString());
20918 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
20919 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
20920 
20921 			xmlReader.skipCurrentElement();
20922 			xmlReaderNumberOfUnrecognizedFields++;
20923 		}
20924 	}
20925 	return cn;
20926 }
20927 
readStudentsSetMaxRealDaysPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)20928 TimeConstraint* Rules::readStudentsSetMaxRealDaysPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
20929 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMaxRealDaysPerWeek"));
20930 	ConstraintStudentsSetMaxRealDaysPerWeek* cn=new ConstraintStudentsSetMaxRealDaysPerWeek();
20931 	cn->maxDaysPerWeek=this->nDaysPerWeek;
20932 	while(xmlReader.readNextStartElement()){
20933 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
20934 		if(xmlReader.name()==QString("Weight_Percentage")){
20935 			QString text=xmlReader.readElementText();
20936 			cn->weightPercentage=customFETStrToDouble(text);
20937 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
20938 		}
20939 		else if(xmlReader.name()==QString("Active")){
20940 			QString text=xmlReader.readElementText();
20941 			if(text=="false"){
20942 				cn->active=false;
20943 			}
20944 		}
20945 		else if(xmlReader.name()==QString("Comments")){
20946 			QString text=xmlReader.readElementText();
20947 			cn->comments=text;
20948 		}
20949 		else if(xmlReader.name()==QString("Students")){
20950 			QString text=xmlReader.readElementText();
20951 			cn->students=text;
20952 			xmlReadingLog+="    Read students set name="+cn->students+"\n";
20953 		}
20954 		else if(xmlReader.name()==QString("Max_Days_Per_Week")){
20955 			QString text=xmlReader.readElementText();
20956 			cn->maxDaysPerWeek=text.toInt();
20957 			if(cn->maxDaysPerWeek>this->nDaysPerWeek){
20958 				RulesReconcilableMessage::information(parent, tr("FET information"),
20959 					tr("Constraint StudentsSetMaxDaysPerWeek max days corrupt for students set %1, max days %2 >nDaysPerWeek, constraint added, please correct constraint")
20960 					.arg(cn->students)
20961 					.arg(text));
20962 			}
20963 			xmlReadingLog+="    Max. days per week="+CustomFETString::number(cn->maxDaysPerWeek)+"\n";
20964 		}
20965 		else{
20966 			unrecognizedXmlTags.append(xmlReader.name().toString());
20967 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
20968 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
20969 
20970 			xmlReader.skipCurrentElement();
20971 			xmlReaderNumberOfUnrecognizedFields++;
20972 		}
20973 	}
20974 	return cn;
20975 }
20976 
readOldMAStudentsMaxDaysPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)20977 TimeConstraint* Rules::readOldMAStudentsMaxDaysPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
20978 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMaxDaysPerWeek"));
20979 	ConstraintStudentsMaxRealDaysPerWeek* cn=new ConstraintStudentsMaxRealDaysPerWeek();
20980 	cn->maxDaysPerWeek=this->nDaysPerWeek;
20981 	while(xmlReader.readNextStartElement()){
20982 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
20983 		if(xmlReader.name()==QString("Weight_Percentage")){
20984 			QString text=xmlReader.readElementText();
20985 			cn->weightPercentage=customFETStrToDouble(text);
20986 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
20987 		}
20988 		else if(xmlReader.name()==QString("Active")){
20989 			QString text=xmlReader.readElementText();
20990 			if(text=="false"){
20991 				cn->active=false;
20992 			}
20993 		}
20994 		else if(xmlReader.name()==QString("Comments")){
20995 			QString text=xmlReader.readElementText();
20996 			cn->comments=text;
20997 		}
20998 		else if(xmlReader.name()==QString("Max_Days_Per_Week")){
20999 			QString text=xmlReader.readElementText();
21000 			cn->maxDaysPerWeek=text.toInt();
21001 			if(cn->maxDaysPerWeek>this->nDaysPerWeek){
21002 				RulesReconcilableMessage::information(parent, tr("FET information"),
21003 					tr("Constraint StudentsMaxDaysPerWeek max days corrupt, max days %1 >nDaysPerWeek, constraint added, please correct constraint")
21004 					.arg(text));
21005 			}
21006 			xmlReadingLog+="    Max. days per week="+CustomFETString::number(cn->maxDaysPerWeek)+"\n";
21007 		}
21008 		else{
21009 			unrecognizedXmlTags.append(xmlReader.name().toString());
21010 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
21011 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
21012 
21013 			xmlReader.skipCurrentElement();
21014 			xmlReaderNumberOfUnrecognizedFields++;
21015 		}
21016 	}
21017 	return cn;
21018 }
21019 
readStudentsMaxRealDaysPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)21020 TimeConstraint* Rules::readStudentsMaxRealDaysPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
21021 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMaxRealDaysPerWeek"));
21022 	ConstraintStudentsMaxRealDaysPerWeek* cn=new ConstraintStudentsMaxRealDaysPerWeek();
21023 	cn->maxDaysPerWeek=this->nDaysPerWeek;
21024 	while(xmlReader.readNextStartElement()){
21025 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
21026 		if(xmlReader.name()==QString("Weight_Percentage")){
21027 			QString text=xmlReader.readElementText();
21028 			cn->weightPercentage=customFETStrToDouble(text);
21029 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
21030 		}
21031 		else if(xmlReader.name()==QString("Active")){
21032 			QString text=xmlReader.readElementText();
21033 			if(text=="false"){
21034 				cn->active=false;
21035 			}
21036 		}
21037 		else if(xmlReader.name()==QString("Comments")){
21038 			QString text=xmlReader.readElementText();
21039 			cn->comments=text;
21040 		}
21041 		else if(xmlReader.name()==QString("Max_Days_Per_Week")){
21042 			QString text=xmlReader.readElementText();
21043 			cn->maxDaysPerWeek=text.toInt();
21044 			if(cn->maxDaysPerWeek>this->nDaysPerWeek){
21045 				RulesReconcilableMessage::information(parent, tr("FET information"),
21046 					tr("Constraint StudentsMaxDaysPerWeek max days corrupt, max days %1 >nDaysPerWeek, constraint added, please correct constraint")
21047 					.arg(text));
21048 			}
21049 			xmlReadingLog+="    Max. days per week="+CustomFETString::number(cn->maxDaysPerWeek)+"\n";
21050 		}
21051 		else{
21052 			unrecognizedXmlTags.append(xmlReader.name().toString());
21053 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
21054 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
21055 
21056 			xmlReader.skipCurrentElement();
21057 			xmlReaderNumberOfUnrecognizedFields++;
21058 		}
21059 	}
21060 	return cn;
21061 }
21062 
21063 //2020-06-25
readStudentsSetMaxAfternoonsPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)21064 TimeConstraint* Rules::readStudentsSetMaxAfternoonsPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
21065 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMaxAfternoonsPerWeek"));
21066 	ConstraintStudentsSetMaxAfternoonsPerWeek* cn=new ConstraintStudentsSetMaxAfternoonsPerWeek();
21067 	cn->maxAfternoonsPerWeek=this->nDaysPerWeek;
21068 	while(xmlReader.readNextStartElement()){
21069 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
21070 		if(xmlReader.name()==QString("Weight_Percentage")){
21071 			QString text=xmlReader.readElementText();
21072 			cn->weightPercentage=customFETStrToDouble(text);
21073 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
21074 		}
21075 		else if(xmlReader.name()==QString("Active")){
21076 			QString text=xmlReader.readElementText();
21077 			if(text=="false"){
21078 				cn->active=false;
21079 			}
21080 		}
21081 		else if(xmlReader.name()==QString("Comments")){
21082 			QString text=xmlReader.readElementText();
21083 			cn->comments=text;
21084 		}
21085 		else if(xmlReader.name()==QString("Students")){
21086 			QString text=xmlReader.readElementText();
21087 			cn->students=text;
21088 			xmlReadingLog+="    Read students set name="+cn->students+"\n";
21089 		}
21090 		else if(xmlReader.name()==QString("Max_Afternoons_Per_Week")){
21091 			QString text=xmlReader.readElementText();
21092 			cn->maxAfternoonsPerWeek=text.toInt();
21093 			if(cn->maxAfternoonsPerWeek>this->nDaysPerWeek/2){
21094 				RulesReconcilableMessage::information(parent, tr("FET information"),
21095 					tr("Constraint StudentsSetMaxAfternoonsPerWeek max afternoons corrupt for students set %1, max afternoons %2 >nDaysPerWeek/2, constraint added, please correct constraint")
21096 					.arg(cn->students)
21097 					.arg(text));
21098 			}
21099 			xmlReadingLog+="    Max. afternoons per week="+CustomFETString::number(cn->maxAfternoonsPerWeek)+"\n";
21100 		}
21101 		else{
21102 			unrecognizedXmlTags.append(xmlReader.name().toString());
21103 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
21104 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
21105 
21106 			xmlReader.skipCurrentElement();
21107 			xmlReaderNumberOfUnrecognizedFields++;
21108 		}
21109 	}
21110 	return cn;
21111 }
21112 
readStudentsMaxAfternoonsPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)21113 TimeConstraint* Rules::readStudentsMaxAfternoonsPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
21114 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMaxAfternoonsPerWeek"));
21115 	ConstraintStudentsMaxAfternoonsPerWeek* cn=new ConstraintStudentsMaxAfternoonsPerWeek();
21116 	cn->maxAfternoonsPerWeek=this->nDaysPerWeek;
21117 	while(xmlReader.readNextStartElement()){
21118 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
21119 		if(xmlReader.name()==QString("Weight_Percentage")){
21120 			QString text=xmlReader.readElementText();
21121 			cn->weightPercentage=customFETStrToDouble(text);
21122 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
21123 		}
21124 		else if(xmlReader.name()==QString("Active")){
21125 			QString text=xmlReader.readElementText();
21126 			if(text=="false"){
21127 				cn->active=false;
21128 			}
21129 		}
21130 		else if(xmlReader.name()==QString("Comments")){
21131 			QString text=xmlReader.readElementText();
21132 			cn->comments=text;
21133 		}
21134 		else if(xmlReader.name()==QString("Max_Afternoons_Per_Week")){
21135 			QString text=xmlReader.readElementText();
21136 			cn->maxAfternoonsPerWeek=text.toInt();
21137 			if(cn->maxAfternoonsPerWeek>this->nDaysPerWeek/2){
21138 				RulesReconcilableMessage::information(parent, tr("FET information"),
21139 					tr("Constraint StudentsMaxAfternoonsPerWeek max afternoons corrupt, max afternoons %1 >nDaysPerWeek/2, constraint added, please correct constraint")
21140 					.arg(text));
21141 			}
21142 			xmlReadingLog+="    Max. afternoons per week="+CustomFETString::number(cn->maxAfternoonsPerWeek)+"\n";
21143 		}
21144 		else{
21145 			unrecognizedXmlTags.append(xmlReader.name().toString());
21146 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
21147 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
21148 
21149 			xmlReader.skipCurrentElement();
21150 			xmlReaderNumberOfUnrecognizedFields++;
21151 		}
21152 	}
21153 	return cn;
21154 }
21155 
readStudentsSetMaxMorningsPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)21156 TimeConstraint* Rules::readStudentsSetMaxMorningsPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
21157 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMaxMorningsPerWeek"));
21158 	ConstraintStudentsSetMaxMorningsPerWeek* cn=new ConstraintStudentsSetMaxMorningsPerWeek();
21159 	cn->maxMorningsPerWeek=this->nDaysPerWeek;
21160 	while(xmlReader.readNextStartElement()){
21161 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
21162 		if(xmlReader.name()==QString("Weight_Percentage")){
21163 			QString text=xmlReader.readElementText();
21164 			cn->weightPercentage=customFETStrToDouble(text);
21165 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
21166 		}
21167 		else if(xmlReader.name()==QString("Active")){
21168 			QString text=xmlReader.readElementText();
21169 			if(text=="false"){
21170 				cn->active=false;
21171 			}
21172 		}
21173 		else if(xmlReader.name()==QString("Comments")){
21174 			QString text=xmlReader.readElementText();
21175 			cn->comments=text;
21176 		}
21177 		else if(xmlReader.name()==QString("Students")){
21178 			QString text=xmlReader.readElementText();
21179 			cn->students=text;
21180 			xmlReadingLog+="    Read students set name="+cn->students+"\n";
21181 		}
21182 		else if(xmlReader.name()==QString("Max_Mornings_Per_Week")){
21183 			QString text=xmlReader.readElementText();
21184 			cn->maxMorningsPerWeek=text.toInt();
21185 			if(cn->maxMorningsPerWeek>this->nDaysPerWeek/2){
21186 				RulesReconcilableMessage::information(parent, tr("FET information"),
21187 					tr("Constraint StudentsSetMaxMorningsPerWeek max mornings corrupt for students set %1, max mornings %2 >nDaysPerWeek/2, constraint added, please correct constraint")
21188 					.arg(cn->students)
21189 					.arg(text));
21190 			}
21191 			xmlReadingLog+="    Max. mornings per week="+CustomFETString::number(cn->maxMorningsPerWeek)+"\n";
21192 		}
21193 		else{
21194 			unrecognizedXmlTags.append(xmlReader.name().toString());
21195 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
21196 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
21197 
21198 			xmlReader.skipCurrentElement();
21199 			xmlReaderNumberOfUnrecognizedFields++;
21200 		}
21201 	}
21202 	return cn;
21203 }
21204 
readStudentsMaxMorningsPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)21205 TimeConstraint* Rules::readStudentsMaxMorningsPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
21206 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMaxMorningsPerWeek"));
21207 	ConstraintStudentsMaxMorningsPerWeek* cn=new ConstraintStudentsMaxMorningsPerWeek();
21208 	cn->maxMorningsPerWeek=this->nDaysPerWeek;
21209 	while(xmlReader.readNextStartElement()){
21210 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
21211 		if(xmlReader.name()==QString("Weight_Percentage")){
21212 			QString text=xmlReader.readElementText();
21213 			cn->weightPercentage=customFETStrToDouble(text);
21214 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
21215 		}
21216 		else if(xmlReader.name()==QString("Active")){
21217 			QString text=xmlReader.readElementText();
21218 			if(text=="false"){
21219 				cn->active=false;
21220 			}
21221 		}
21222 		else if(xmlReader.name()==QString("Comments")){
21223 			QString text=xmlReader.readElementText();
21224 			cn->comments=text;
21225 		}
21226 		else if(xmlReader.name()==QString("Max_Mornings_Per_Week")){
21227 			QString text=xmlReader.readElementText();
21228 			cn->maxMorningsPerWeek=text.toInt();
21229 			if(cn->maxMorningsPerWeek>this->nDaysPerWeek/2){
21230 				RulesReconcilableMessage::information(parent, tr("FET information"),
21231 					tr("Constraint StudentsMaxMorningsPerWeek max mornings corrupt, max mornings %1 >nDaysPerWeek/2, constraint added, please correct constraint")
21232 					.arg(text));
21233 			}
21234 			xmlReadingLog+="    Max. mornings per week="+CustomFETString::number(cn->maxMorningsPerWeek)+"\n";
21235 		}
21236 		else{
21237 			unrecognizedXmlTags.append(xmlReader.name().toString());
21238 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
21239 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
21240 
21241 			xmlReader.skipCurrentElement();
21242 			xmlReaderNumberOfUnrecognizedFields++;
21243 		}
21244 	}
21245 	return cn;
21246 }
21247 
21248 //2020-06-26
readStudentsSetMinAfternoonsPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)21249 TimeConstraint* Rules::readStudentsSetMinAfternoonsPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
21250 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMinAfternoonsPerWeek"));
21251 	ConstraintStudentsSetMinAfternoonsPerWeek* cn=new ConstraintStudentsSetMinAfternoonsPerWeek();
21252 	cn->minAfternoonsPerWeek=this->nDaysPerWeek;
21253 	while(xmlReader.readNextStartElement()){
21254 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
21255 		if(xmlReader.name()==QString("Weight_Percentage")){
21256 			QString text=xmlReader.readElementText();
21257 			cn->weightPercentage=customFETStrToDouble(text);
21258 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
21259 		}
21260 		else if(xmlReader.name()==QString("Active")){
21261 			QString text=xmlReader.readElementText();
21262 			if(text=="false"){
21263 				cn->active=false;
21264 			}
21265 		}
21266 		else if(xmlReader.name()==QString("Comments")){
21267 			QString text=xmlReader.readElementText();
21268 			cn->comments=text;
21269 		}
21270 		else if(xmlReader.name()==QString("Students")){
21271 			QString text=xmlReader.readElementText();
21272 			cn->students=text;
21273 			xmlReadingLog+="    Read students set name="+cn->students+"\n";
21274 		}
21275 		else if(xmlReader.name()==QString("Min_Afternoons_Per_Week")){
21276 			QString text=xmlReader.readElementText();
21277 			cn->minAfternoonsPerWeek=text.toInt();
21278 			if(cn->minAfternoonsPerWeek>this->nDaysPerWeek/2){
21279 				RulesReconcilableMessage::information(parent, tr("FET information"),
21280 					tr("Constraint StudentsSetMinAfternoonsPerWeek min afternoons corrupt for students set %1, min afternoons %2 >nDaysPerWeek/2, constraint added, please correct constraint")
21281 					.arg(cn->students)
21282 					.arg(text));
21283 			}
21284 			xmlReadingLog+="    Min. afternoons per week="+CustomFETString::number(cn->minAfternoonsPerWeek)+"\n";
21285 		}
21286 		else{
21287 			unrecognizedXmlTags.append(xmlReader.name().toString());
21288 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
21289 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
21290 
21291 			xmlReader.skipCurrentElement();
21292 			xmlReaderNumberOfUnrecognizedFields++;
21293 		}
21294 	}
21295 	return cn;
21296 }
21297 
readStudentsMinAfternoonsPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)21298 TimeConstraint* Rules::readStudentsMinAfternoonsPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
21299 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMinAfternoonsPerWeek"));
21300 	ConstraintStudentsMinAfternoonsPerWeek* cn=new ConstraintStudentsMinAfternoonsPerWeek();
21301 	cn->minAfternoonsPerWeek=this->nDaysPerWeek;
21302 	while(xmlReader.readNextStartElement()){
21303 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
21304 		if(xmlReader.name()==QString("Weight_Percentage")){
21305 			QString text=xmlReader.readElementText();
21306 			cn->weightPercentage=customFETStrToDouble(text);
21307 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
21308 		}
21309 		else if(xmlReader.name()==QString("Active")){
21310 			QString text=xmlReader.readElementText();
21311 			if(text=="false"){
21312 				cn->active=false;
21313 			}
21314 		}
21315 		else if(xmlReader.name()==QString("Comments")){
21316 			QString text=xmlReader.readElementText();
21317 			cn->comments=text;
21318 		}
21319 		else if(xmlReader.name()==QString("Min_Afternoons_Per_Week")){
21320 			QString text=xmlReader.readElementText();
21321 			cn->minAfternoonsPerWeek=text.toInt();
21322 			if(cn->minAfternoonsPerWeek>this->nDaysPerWeek/2){
21323 				RulesReconcilableMessage::information(parent, tr("FET information"),
21324 					tr("Constraint StudentsMinAfternoonsPerWeek min afternoons corrupt, min afternoons %1 >nDaysPerWeek/2, constraint added, please correct constraint")
21325 					.arg(text));
21326 			}
21327 			xmlReadingLog+="    Min. afternoons per week="+CustomFETString::number(cn->minAfternoonsPerWeek)+"\n";
21328 		}
21329 		else{
21330 			unrecognizedXmlTags.append(xmlReader.name().toString());
21331 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
21332 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
21333 
21334 			xmlReader.skipCurrentElement();
21335 			xmlReaderNumberOfUnrecognizedFields++;
21336 		}
21337 	}
21338 	return cn;
21339 }
21340 
readStudentsSetMinMorningsPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)21341 TimeConstraint* Rules::readStudentsSetMinMorningsPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
21342 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMinMorningsPerWeek"));
21343 	ConstraintStudentsSetMinMorningsPerWeek* cn=new ConstraintStudentsSetMinMorningsPerWeek();
21344 	cn->minMorningsPerWeek=this->nDaysPerWeek;
21345 	while(xmlReader.readNextStartElement()){
21346 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
21347 		if(xmlReader.name()==QString("Weight_Percentage")){
21348 			QString text=xmlReader.readElementText();
21349 			cn->weightPercentage=customFETStrToDouble(text);
21350 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
21351 		}
21352 		else if(xmlReader.name()==QString("Active")){
21353 			QString text=xmlReader.readElementText();
21354 			if(text=="false"){
21355 				cn->active=false;
21356 			}
21357 		}
21358 		else if(xmlReader.name()==QString("Comments")){
21359 			QString text=xmlReader.readElementText();
21360 			cn->comments=text;
21361 		}
21362 		else if(xmlReader.name()==QString("Students")){
21363 			QString text=xmlReader.readElementText();
21364 			cn->students=text;
21365 			xmlReadingLog+="    Read students set name="+cn->students+"\n";
21366 		}
21367 		else if(xmlReader.name()==QString("Min_Mornings_Per_Week")){
21368 			QString text=xmlReader.readElementText();
21369 			cn->minMorningsPerWeek=text.toInt();
21370 			if(cn->minMorningsPerWeek>this->nDaysPerWeek/2){
21371 				RulesReconcilableMessage::information(parent, tr("FET information"),
21372 					tr("Constraint StudentsSetMinMorningsPerWeek min mornings corrupt for students set %1, min mornings %2 >nDaysPerWeek/2, constraint added, please correct constraint")
21373 					.arg(cn->students)
21374 					.arg(text));
21375 			}
21376 			xmlReadingLog+="    Min. mornings per week="+CustomFETString::number(cn->minMorningsPerWeek)+"\n";
21377 		}
21378 		else{
21379 			unrecognizedXmlTags.append(xmlReader.name().toString());
21380 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
21381 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
21382 
21383 			xmlReader.skipCurrentElement();
21384 			xmlReaderNumberOfUnrecognizedFields++;
21385 		}
21386 	}
21387 	return cn;
21388 }
21389 
readStudentsMinMorningsPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)21390 TimeConstraint* Rules::readStudentsMinMorningsPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
21391 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMinMorningsPerWeek"));
21392 	ConstraintStudentsMinMorningsPerWeek* cn=new ConstraintStudentsMinMorningsPerWeek();
21393 	cn->minMorningsPerWeek=this->nDaysPerWeek;
21394 	while(xmlReader.readNextStartElement()){
21395 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
21396 		if(xmlReader.name()==QString("Weight_Percentage")){
21397 			QString text=xmlReader.readElementText();
21398 			cn->weightPercentage=customFETStrToDouble(text);
21399 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
21400 		}
21401 		else if(xmlReader.name()==QString("Active")){
21402 			QString text=xmlReader.readElementText();
21403 			if(text=="false"){
21404 				cn->active=false;
21405 			}
21406 		}
21407 		else if(xmlReader.name()==QString("Comments")){
21408 			QString text=xmlReader.readElementText();
21409 			cn->comments=text;
21410 		}
21411 		else if(xmlReader.name()==QString("Min_Mornings_Per_Week")){
21412 			QString text=xmlReader.readElementText();
21413 			cn->minMorningsPerWeek=text.toInt();
21414 			if(cn->minMorningsPerWeek>this->nDaysPerWeek/2){
21415 				RulesReconcilableMessage::information(parent, tr("FET information"),
21416 					tr("Constraint StudentsMinMorningsPerWeek min mornings corrupt, min mornings %1 >nDaysPerWeek/2, constraint added, please correct constraint")
21417 					.arg(text));
21418 			}
21419 			xmlReadingLog+="    Min. mornings per week="+CustomFETString::number(cn->minMorningsPerWeek)+"\n";
21420 		}
21421 		else{
21422 			unrecognizedXmlTags.append(xmlReader.name().toString());
21423 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
21424 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
21425 
21426 			xmlReader.skipCurrentElement();
21427 			xmlReaderNumberOfUnrecognizedFields++;
21428 		}
21429 	}
21430 	return cn;
21431 }
21432 //
21433 
21434 //2020-06-26
readStudentsSetMorningIntervalMaxDaysPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)21435 TimeConstraint* Rules::readStudentsSetMorningIntervalMaxDaysPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
21436 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMorningIntervalMaxDaysPerWeek"));
21437 	ConstraintStudentsSetMorningIntervalMaxDaysPerWeek* cn=new ConstraintStudentsSetMorningIntervalMaxDaysPerWeek();
21438 	cn->maxDaysPerWeek=this->nDaysPerWeek;
21439 	cn->startHour=this->nHoursPerDay;
21440 	cn->endHour=this->nHoursPerDay;
21441 	int h1, h2;
21442 	while(xmlReader.readNextStartElement()){
21443 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
21444 		if(xmlReader.name()==QString("Weight")){
21445 			//cn->weight=customFETStrToDouble(text);
21446 			xmlReader.skipCurrentElement();
21447 			xmlReadingLog+="    Ignoring old tag - weight - generating 100% weight percentage\n";
21448 			cn->weightPercentage=100;
21449 		}
21450 		else if(xmlReader.name()==QString("Weight_Percentage")){
21451 			QString text=xmlReader.readElementText();
21452 			cn->weightPercentage=customFETStrToDouble(text);
21453 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
21454 		}
21455 		else if(xmlReader.name()==QString("Active")){
21456 			QString text=xmlReader.readElementText();
21457 			if(text=="false"){
21458 				cn->active=false;
21459 			}
21460 		}
21461 		else if(xmlReader.name()==QString("Comments")){
21462 			QString text=xmlReader.readElementText();
21463 			cn->comments=text;
21464 		}
21465 		else if(xmlReader.name()==QString("Compulsory")){
21466 			QString text=xmlReader.readElementText();
21467 			if(text=="yes"){
21468 				//cn->compulsory=true;
21469 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
21470 				cn->weightPercentage=100;
21471 			}
21472 			else{
21473 				//cn->compulsory=false;
21474 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
21475 				cn->weightPercentage=0;
21476 			}
21477 		}
21478 		else if(xmlReader.name()==QString("Students")){
21479 			QString text=xmlReader.readElementText();
21480 			cn->students=text;
21481 			xmlReadingLog+="    Read students set name="+cn->students+"\n";
21482 		}
21483 		else if(xmlReader.name()==QString("Max_Days_Per_Week")){
21484 			QString text=xmlReader.readElementText();
21485 			cn->maxDaysPerWeek=text.toInt();
21486 			if(cn->maxDaysPerWeek>this->nDaysPerWeek/2){
21487 				RulesReconcilableMessage::information(parent, tr("FET information"),
21488 					tr("Constraint StudentsSetMorningIntervalMaxDaysPerWeek max days corrupt for students set %1, max days %2 >nDaysPerWeek/2, constraint added, please correct constraint")
21489 					.arg(cn->students)
21490 					.arg(text));
21491 				/*delete cn;
21492 				cn=nullptr;
21493 				goto corruptConstraintTime;*/
21494 			}
21495 			//assert(cn->maxDaysPerWeek>0 && cn->maxDaysPerWeek <= this->nDaysPerWeek);
21496 			xmlReadingLog+="    Max. days per week="+CustomFETString::number(cn->maxDaysPerWeek)+"\n";
21497 		}
21498 		else if(xmlReader.name()==QString("Interval_Start_Hour")){
21499 			QString text=xmlReader.readElementText();
21500 			for(h1=0; h1 < this->nHoursPerDay; h1++)
21501 				if(this->hoursOfTheDay[h1]==text)
21502 					break;
21503 			if(h1>=this->nHoursPerDay){
21504 				xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
21505 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
21506 					tr("Constraint Students set interval max days per week start hour corrupt for students %1, hour %2 is inexistent ... ignoring constraint")
21507 					.arg(cn->students)
21508 					.arg(text));*/
21509 				delete cn;
21510 				//cn=nullptr;
21511 				//goto corruptConstraintTime;
21512 				return nullptr;
21513 			}
21514 			assert(h1>=0 && h1 < this->nHoursPerDay);
21515 			xmlReadingLog+="    Interval start hour="+this->hoursOfTheDay[h1]+"\n";
21516 			cn->startHour=h1;
21517 		}
21518 		else if(xmlReader.name()==QString("Interval_End_Hour")){
21519 			QString text=xmlReader.readElementText();
21520 			if(text==""){
21521 				xmlReadingLog+="    Interval end hour void, meaning end of day\n";
21522 				cn->endHour=this->nHoursPerDay;
21523 			}
21524 			else{
21525 				for(h2=0; h2 < this->nHoursPerDay; h2++)
21526 					if(this->hoursOfTheDay[h2]==text)
21527 						break;
21528 				if(h2>=this->nHoursPerDay){
21529 					xmlReader.raiseError(tr("Hour %1 is inexistent (it is also not void, to specify end of the day)").arg(text));
21530 					/*RulesReconcilableMessage::information(parent, tr("FET information"),
21531 						tr("Constraint Students set interval max days per week end hour corrupt for students %1, hour %2 is inexistent (it is also not void, to specify end of the day) ... ignoring constraint")
21532 						.arg(cn->students)
21533 						.arg(text));*/
21534 					delete cn;
21535 					//cn=nullptr;
21536 					//goto corruptConstraintTime;
21537 					return nullptr;
21538 				}
21539 				assert(h2>=0 && h2 < this->nHoursPerDay);
21540 				xmlReadingLog+="    Interval end hour="+this->hoursOfTheDay[h2]+"\n";
21541 				cn->endHour=h2;
21542 			}
21543 		}
21544 		else{
21545 			unrecognizedXmlTags.append(xmlReader.name().toString());
21546 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
21547 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
21548 
21549 			xmlReader.skipCurrentElement();
21550 			xmlReaderNumberOfUnrecognizedFields++;
21551 		}
21552 	}
21553 	return cn;
21554 }
21555 
readStudentsMorningIntervalMaxDaysPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)21556 TimeConstraint* Rules::readStudentsMorningIntervalMaxDaysPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
21557 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMorningIntervalMaxDaysPerWeek"));
21558 	ConstraintStudentsMorningIntervalMaxDaysPerWeek* cn=new ConstraintStudentsMorningIntervalMaxDaysPerWeek();
21559 	cn->maxDaysPerWeek=this->nDaysPerWeek;
21560 	cn->startHour=this->nHoursPerDay;
21561 	cn->endHour=this->nHoursPerDay;
21562 	int h1, h2;
21563 	while(xmlReader.readNextStartElement()){
21564 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
21565 		if(xmlReader.name()==QString("Weight")){
21566 			//cn->weight=customFETStrToDouble(text);
21567 			xmlReader.skipCurrentElement();
21568 			xmlReadingLog+="    Ignoring old tag - weight - generating 100% weight percentage\n";
21569 			cn->weightPercentage=100;
21570 		}
21571 		else if(xmlReader.name()==QString("Weight_Percentage")){
21572 			QString text=xmlReader.readElementText();
21573 			cn->weightPercentage=customFETStrToDouble(text);
21574 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
21575 		}
21576 		else if(xmlReader.name()==QString("Active")){
21577 			QString text=xmlReader.readElementText();
21578 			if(text=="false"){
21579 				cn->active=false;
21580 			}
21581 		}
21582 		else if(xmlReader.name()==QString("Comments")){
21583 			QString text=xmlReader.readElementText();
21584 			cn->comments=text;
21585 		}
21586 		else if(xmlReader.name()==QString("Compulsory")){
21587 			QString text=xmlReader.readElementText();
21588 			if(text=="yes"){
21589 				//cn->compulsory=true;
21590 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
21591 				cn->weightPercentage=100;
21592 			}
21593 			else{
21594 				//cn->compulsory=false;
21595 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
21596 				cn->weightPercentage=0;
21597 			}
21598 		}
21599 		/*else if(xmlReader.name()==QString("Students")){
21600 			cn->students=text;
21601 			xmlReadingLog+="    Read students set name="+cn->students+"\n";
21602 		}*/
21603 		else if(xmlReader.name()==QString("Max_Days_Per_Week")){
21604 			QString text=xmlReader.readElementText();
21605 			cn->maxDaysPerWeek=text.toInt();
21606 			if(cn->maxDaysPerWeek>this->nDaysPerWeek/2){
21607 				RulesReconcilableMessage::information(parent, tr("FET information"),
21608 					tr("Constraint StudentsMorningIntervalMaxDaysPerWeek max days corrupt: max days %1 >nDaysPerWeek/2, constraint added, please correct constraint")
21609 					.arg(text));
21610 				/*delete cn;
21611 				cn=nullptr;
21612 				goto corruptConstraintTime;*/
21613 			}
21614 			//assert(cn->maxDaysPerWeek>0 && cn->maxDaysPerWeek <= this->nDaysPerWeek);
21615 			xmlReadingLog+="    Max. days per week="+CustomFETString::number(cn->maxDaysPerWeek)+"\n";
21616 		}
21617 		else if(xmlReader.name()==QString("Interval_Start_Hour")){
21618 			QString text=xmlReader.readElementText();
21619 			for(h1=0; h1 < this->nHoursPerDay; h1++)
21620 				if(this->hoursOfTheDay[h1]==text)
21621 					break;
21622 			if(h1>=this->nHoursPerDay){
21623 				xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
21624 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
21625 					tr("Constraint Students interval max days per week start hour corrupt: hour %1 is inexistent ... ignoring constraint")
21626 					//.arg(cn->students)
21627 					.arg(text));*/
21628 				delete cn;
21629 				//cn=nullptr;
21630 				//goto corruptConstraintTime;
21631 				return nullptr;
21632 			}
21633 			assert(h1>=0 && h1 < this->nHoursPerDay);
21634 			xmlReadingLog+="    Interval start hour="+this->hoursOfTheDay[h1]+"\n";
21635 			cn->startHour=h1;
21636 		}
21637 		else if(xmlReader.name()==QString("Interval_End_Hour")){
21638 			QString text=xmlReader.readElementText();
21639 			if(text==""){
21640 				xmlReadingLog+="    Interval end hour void, meaning end of day\n";
21641 				cn->endHour=this->nHoursPerDay;
21642 			}
21643 			else{
21644 				for(h2=0; h2 < this->nHoursPerDay; h2++)
21645 					if(this->hoursOfTheDay[h2]==text)
21646 						break;
21647 				if(h2>=this->nHoursPerDay){
21648 					xmlReader.raiseError(tr("Hour %1 is inexistent (it is also not void, to specify end of the day)").arg(text));
21649 					/*RulesReconcilableMessage::information(parent, tr("FET information"),
21650 						tr("Constraint Students interval max days per week end hour corrupt: hour %1 is inexistent (it is also not void, to specify end of the day) ... ignoring constraint")
21651 						//.arg(cn->students)
21652 						.arg(text));*/
21653 					delete cn;
21654 					//cn=nullptr;
21655 					//goto corruptConstraintTime;
21656 					return nullptr;
21657 				}
21658 				assert(h2>=0 && h2 < this->nHoursPerDay);
21659 				xmlReadingLog+="    Interval end hour="+this->hoursOfTheDay[h2]+"\n";
21660 				cn->endHour=h2;
21661 			}
21662 		}
21663 		else{
21664 			unrecognizedXmlTags.append(xmlReader.name().toString());
21665 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
21666 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
21667 
21668 			xmlReader.skipCurrentElement();
21669 			xmlReaderNumberOfUnrecognizedFields++;
21670 		}
21671 	}
21672 	return cn;
21673 }
21674 
readStudentsSetAfternoonIntervalMaxDaysPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)21675 TimeConstraint* Rules::readStudentsSetAfternoonIntervalMaxDaysPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
21676 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetAfternoonIntervalMaxDaysPerWeek"));
21677 	ConstraintStudentsSetAfternoonIntervalMaxDaysPerWeek* cn=new ConstraintStudentsSetAfternoonIntervalMaxDaysPerWeek();
21678 	cn->maxDaysPerWeek=this->nDaysPerWeek;
21679 	cn->startHour=this->nHoursPerDay;
21680 	cn->endHour=this->nHoursPerDay;
21681 	int h1, h2;
21682 	while(xmlReader.readNextStartElement()){
21683 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
21684 		if(xmlReader.name()==QString("Weight")){
21685 			//cn->weight=customFETStrToDouble(text);
21686 			xmlReader.skipCurrentElement();
21687 			xmlReadingLog+="    Ignoring old tag - weight - generating 100% weight percentage\n";
21688 			cn->weightPercentage=100;
21689 		}
21690 		else if(xmlReader.name()==QString("Weight_Percentage")){
21691 			QString text=xmlReader.readElementText();
21692 			cn->weightPercentage=customFETStrToDouble(text);
21693 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
21694 		}
21695 		else if(xmlReader.name()==QString("Active")){
21696 			QString text=xmlReader.readElementText();
21697 			if(text=="false"){
21698 				cn->active=false;
21699 			}
21700 		}
21701 		else if(xmlReader.name()==QString("Comments")){
21702 			QString text=xmlReader.readElementText();
21703 			cn->comments=text;
21704 		}
21705 		else if(xmlReader.name()==QString("Compulsory")){
21706 			QString text=xmlReader.readElementText();
21707 			if(text=="yes"){
21708 				//cn->compulsory=true;
21709 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
21710 				cn->weightPercentage=100;
21711 			}
21712 			else{
21713 				//cn->compulsory=false;
21714 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
21715 				cn->weightPercentage=0;
21716 			}
21717 		}
21718 		else if(xmlReader.name()==QString("Students")){
21719 			QString text=xmlReader.readElementText();
21720 			cn->students=text;
21721 			xmlReadingLog+="    Read students set name="+cn->students+"\n";
21722 		}
21723 		else if(xmlReader.name()==QString("Max_Days_Per_Week")){
21724 			QString text=xmlReader.readElementText();
21725 			cn->maxDaysPerWeek=text.toInt();
21726 			if(cn->maxDaysPerWeek>this->nDaysPerWeek/2){
21727 				RulesReconcilableMessage::information(parent, tr("FET information"),
21728 					tr("Constraint StudentsSetAfternoonIntervalMaxDaysPerWeek max days corrupt for students set %1, max days %2 >nDaysPerWeek/2, constraint added, please correct constraint")
21729 					.arg(cn->students)
21730 					.arg(text));
21731 				/*delete cn;
21732 				cn=nullptr;
21733 				goto corruptConstraintTime;*/
21734 			}
21735 			//assert(cn->maxDaysPerWeek>0 && cn->maxDaysPerWeek <= this->nDaysPerWeek);
21736 			xmlReadingLog+="    Max. days per week="+CustomFETString::number(cn->maxDaysPerWeek)+"\n";
21737 		}
21738 		else if(xmlReader.name()==QString("Interval_Start_Hour")){
21739 			QString text=xmlReader.readElementText();
21740 			for(h1=0; h1 < this->nHoursPerDay; h1++)
21741 				if(this->hoursOfTheDay[h1]==text)
21742 					break;
21743 			if(h1>=this->nHoursPerDay){
21744 				xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
21745 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
21746 					tr("Constraint Students set interval max days per week start hour corrupt for students %1, hour %2 is inexistent ... ignoring constraint")
21747 					.arg(cn->students)
21748 					.arg(text));*/
21749 				delete cn;
21750 				//cn=nullptr;
21751 				//goto corruptConstraintTime;
21752 				return nullptr;
21753 			}
21754 			assert(h1>=0 && h1 < this->nHoursPerDay);
21755 			xmlReadingLog+="    Interval start hour="+this->hoursOfTheDay[h1]+"\n";
21756 			cn->startHour=h1;
21757 		}
21758 		else if(xmlReader.name()==QString("Interval_End_Hour")){
21759 			QString text=xmlReader.readElementText();
21760 			if(text==""){
21761 				xmlReadingLog+="    Interval end hour void, meaning end of day\n";
21762 				cn->endHour=this->nHoursPerDay;
21763 			}
21764 			else{
21765 				for(h2=0; h2 < this->nHoursPerDay; h2++)
21766 					if(this->hoursOfTheDay[h2]==text)
21767 						break;
21768 				if(h2>=this->nHoursPerDay){
21769 					xmlReader.raiseError(tr("Hour %1 is inexistent (it is also not void, to specify end of the day)").arg(text));
21770 					/*RulesReconcilableMessage::information(parent, tr("FET information"),
21771 						tr("Constraint Students set interval max days per week end hour corrupt for students %1, hour %2 is inexistent (it is also not void, to specify end of the day) ... ignoring constraint")
21772 						.arg(cn->students)
21773 						.arg(text));*/
21774 					delete cn;
21775 					//cn=nullptr;
21776 					//goto corruptConstraintTime;
21777 					return nullptr;
21778 				}
21779 				assert(h2>=0 && h2 < this->nHoursPerDay);
21780 				xmlReadingLog+="    Interval end hour="+this->hoursOfTheDay[h2]+"\n";
21781 				cn->endHour=h2;
21782 			}
21783 		}
21784 		else{
21785 			unrecognizedXmlTags.append(xmlReader.name().toString());
21786 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
21787 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
21788 
21789 			xmlReader.skipCurrentElement();
21790 			xmlReaderNumberOfUnrecognizedFields++;
21791 		}
21792 	}
21793 	return cn;
21794 }
21795 
readStudentsAfternoonIntervalMaxDaysPerWeek(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)21796 TimeConstraint* Rules::readStudentsAfternoonIntervalMaxDaysPerWeek(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
21797 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsAfternoonIntervalMaxDaysPerWeek"));
21798 	ConstraintStudentsAfternoonIntervalMaxDaysPerWeek* cn=new ConstraintStudentsAfternoonIntervalMaxDaysPerWeek();
21799 	cn->maxDaysPerWeek=this->nDaysPerWeek;
21800 	cn->startHour=this->nHoursPerDay;
21801 	cn->endHour=this->nHoursPerDay;
21802 	int h1, h2;
21803 	while(xmlReader.readNextStartElement()){
21804 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
21805 		if(xmlReader.name()==QString("Weight")){
21806 			//cn->weight=customFETStrToDouble(text);
21807 			xmlReader.skipCurrentElement();
21808 			xmlReadingLog+="    Ignoring old tag - weight - generating 100% weight percentage\n";
21809 			cn->weightPercentage=100;
21810 		}
21811 		else if(xmlReader.name()==QString("Weight_Percentage")){
21812 			QString text=xmlReader.readElementText();
21813 			cn->weightPercentage=customFETStrToDouble(text);
21814 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
21815 		}
21816 		else if(xmlReader.name()==QString("Active")){
21817 			QString text=xmlReader.readElementText();
21818 			if(text=="false"){
21819 				cn->active=false;
21820 			}
21821 		}
21822 		else if(xmlReader.name()==QString("Comments")){
21823 			QString text=xmlReader.readElementText();
21824 			cn->comments=text;
21825 		}
21826 		else if(xmlReader.name()==QString("Compulsory")){
21827 			QString text=xmlReader.readElementText();
21828 			if(text=="yes"){
21829 				//cn->compulsory=true;
21830 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
21831 				cn->weightPercentage=100;
21832 			}
21833 			else{
21834 				//cn->compulsory=false;
21835 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
21836 				cn->weightPercentage=0;
21837 			}
21838 		}
21839 		/*else if(xmlReader.name()==QString("Students")){
21840 			cn->students=text;
21841 			xmlReadingLog+="    Read students set name="+cn->students+"\n";
21842 		}*/
21843 		else if(xmlReader.name()==QString("Max_Days_Per_Week")){
21844 			QString text=xmlReader.readElementText();
21845 			cn->maxDaysPerWeek=text.toInt();
21846 			if(cn->maxDaysPerWeek>this->nDaysPerWeek/2){
21847 				RulesReconcilableMessage::information(parent, tr("FET information"),
21848 					tr("Constraint StudentsAfternoonIntervalMaxDaysPerWeek max days corrupt: max days %1 >nDaysPerWeek/2, constraint added, please correct constraint")
21849 					.arg(text));
21850 				/*delete cn;
21851 				cn=nullptr;
21852 				goto corruptConstraintTime;*/
21853 			}
21854 			//assert(cn->maxDaysPerWeek>0 && cn->maxDaysPerWeek <= this->nDaysPerWeek);
21855 			xmlReadingLog+="    Max. days per week="+CustomFETString::number(cn->maxDaysPerWeek)+"\n";
21856 		}
21857 		else if(xmlReader.name()==QString("Interval_Start_Hour")){
21858 			QString text=xmlReader.readElementText();
21859 			for(h1=0; h1 < this->nHoursPerDay; h1++)
21860 				if(this->hoursOfTheDay[h1]==text)
21861 					break;
21862 			if(h1>=this->nHoursPerDay){
21863 				xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
21864 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
21865 					tr("Constraint Students interval max days per week start hour corrupt: hour %1 is inexistent ... ignoring constraint")
21866 					//.arg(cn->students)
21867 					.arg(text));*/
21868 				delete cn;
21869 				//cn=nullptr;
21870 				//goto corruptConstraintTime;
21871 				return nullptr;
21872 			}
21873 			assert(h1>=0 && h1 < this->nHoursPerDay);
21874 			xmlReadingLog+="    Interval start hour="+this->hoursOfTheDay[h1]+"\n";
21875 			cn->startHour=h1;
21876 		}
21877 		else if(xmlReader.name()==QString("Interval_End_Hour")){
21878 			QString text=xmlReader.readElementText();
21879 			if(text==""){
21880 				xmlReadingLog+="    Interval end hour void, meaning end of day\n";
21881 				cn->endHour=this->nHoursPerDay;
21882 			}
21883 			else{
21884 				for(h2=0; h2 < this->nHoursPerDay; h2++)
21885 					if(this->hoursOfTheDay[h2]==text)
21886 						break;
21887 				if(h2>=this->nHoursPerDay){
21888 					xmlReader.raiseError(tr("Hour %1 is inexistent (it is also not void, to specify end of the day)").arg(text));
21889 					/*RulesReconcilableMessage::information(parent, tr("FET information"),
21890 						tr("Constraint Students interval max days per week end hour corrupt: hour %1 is inexistent (it is also not void, to specify end of the day) ... ignoring constraint")
21891 						//.arg(cn->students)
21892 						.arg(text));*/
21893 					delete cn;
21894 					//cn=nullptr;
21895 					//goto corruptConstraintTime;
21896 					return nullptr;
21897 				}
21898 				assert(h2>=0 && h2 < this->nHoursPerDay);
21899 				xmlReadingLog+="    Interval end hour="+this->hoursOfTheDay[h2]+"\n";
21900 				cn->endHour=h2;
21901 			}
21902 		}
21903 		else{
21904 			unrecognizedXmlTags.append(xmlReader.name().toString());
21905 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
21906 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
21907 
21908 			xmlReader.skipCurrentElement();
21909 			xmlReaderNumberOfUnrecognizedFields++;
21910 		}
21911 	}
21912 	return cn;
21913 }
21914 
readOldMATeachersMaxHoursDaily(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)21915 TimeConstraint* Rules::readOldMATeachersMaxHoursDaily(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
21916 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxHoursDaily"));
21917 	ConstraintTeachersMaxHoursDailyRealDays* cn=new ConstraintTeachersMaxHoursDailyRealDays();
21918 	while(xmlReader.readNextStartElement()){
21919 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
21920 		if(xmlReader.name()==QString("Weight")){
21921 			//cn->weight=customFETStrToDouble(text);
21922 			xmlReader.skipCurrentElement();
21923 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
21924 			cn->weightPercentage=100;
21925 		}
21926 		else if(xmlReader.name()==QString("Weight_Percentage")){
21927 			QString text=xmlReader.readElementText();
21928 			cn->weightPercentage=customFETStrToDouble(text);
21929 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
21930 		}
21931 		else if(xmlReader.name()==QString("Active")){
21932 			QString text=xmlReader.readElementText();
21933 			if(text=="false"){
21934 				cn->active=false;
21935 			}
21936 		}
21937 		else if(xmlReader.name()==QString("Comments")){
21938 			QString text=xmlReader.readElementText();
21939 			cn->comments=text;
21940 		}
21941 		else if(xmlReader.name()==QString("Compulsory")){
21942 			QString text=xmlReader.readElementText();
21943 			if(text=="yes"){
21944 				//cn->compulsory=true;
21945 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
21946 				cn->weightPercentage=100;
21947 			}
21948 			else{
21949 				//cn->compulsory=false;
21950 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
21951 				cn->weightPercentage=0;
21952 			}
21953 		}
21954 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
21955 			QString text=xmlReader.readElementText();
21956 			cn->maxHoursDaily=text.toInt();
21957 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
21958 		}
21959 		else{
21960 			unrecognizedXmlTags.append(xmlReader.name().toString());
21961 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
21962 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
21963 
21964 			xmlReader.skipCurrentElement();
21965 			xmlReaderNumberOfUnrecognizedFields++;
21966 		}
21967 	}
21968 	return cn;
21969 }
21970 
readTeachersMaxHoursDailyRealDays(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)21971 TimeConstraint* Rules::readTeachersMaxHoursDailyRealDays(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
21972 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxHoursDailyRealDays"));
21973 	ConstraintTeachersMaxHoursDailyRealDays* cn=new ConstraintTeachersMaxHoursDailyRealDays();
21974 	while(xmlReader.readNextStartElement()){
21975 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
21976 		if(xmlReader.name()==QString("Weight")){
21977 			//cn->weight=customFETStrToDouble(text);
21978 			xmlReader.skipCurrentElement();
21979 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
21980 			cn->weightPercentage=100;
21981 		}
21982 		else if(xmlReader.name()==QString("Weight_Percentage")){
21983 			QString text=xmlReader.readElementText();
21984 			cn->weightPercentage=customFETStrToDouble(text);
21985 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
21986 		}
21987 		else if(xmlReader.name()==QString("Active")){
21988 			QString text=xmlReader.readElementText();
21989 			if(text=="false"){
21990 				cn->active=false;
21991 			}
21992 		}
21993 		else if(xmlReader.name()==QString("Comments")){
21994 			QString text=xmlReader.readElementText();
21995 			cn->comments=text;
21996 		}
21997 		else if(xmlReader.name()==QString("Compulsory")){
21998 			QString text=xmlReader.readElementText();
21999 			if(text=="yes"){
22000 				//cn->compulsory=true;
22001 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
22002 				cn->weightPercentage=100;
22003 			}
22004 			else{
22005 				//cn->compulsory=false;
22006 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
22007 				cn->weightPercentage=0;
22008 			}
22009 		}
22010 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
22011 			QString text=xmlReader.readElementText();
22012 			cn->maxHoursDaily=text.toInt();
22013 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
22014 		}
22015 		else{
22016 			unrecognizedXmlTags.append(xmlReader.name().toString());
22017 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
22018 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
22019 
22020 			xmlReader.skipCurrentElement();
22021 			xmlReaderNumberOfUnrecognizedFields++;
22022 		}
22023 	}
22024 	return cn;
22025 }
22026 
readOldMATeacherMaxHoursDaily(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)22027 TimeConstraint* Rules::readOldMATeacherMaxHoursDaily(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
22028 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxHoursDaily"));
22029 	ConstraintTeacherMaxHoursDailyRealDays* cn=new ConstraintTeacherMaxHoursDailyRealDays();
22030 	while(xmlReader.readNextStartElement()){
22031 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
22032 		if(xmlReader.name()==QString("Weight")){
22033 			//cn->weight=customFETStrToDouble(text);
22034 			xmlReader.skipCurrentElement();
22035 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
22036 			cn->weightPercentage=100;
22037 		}
22038 		else if(xmlReader.name()==QString("Weight_Percentage")){
22039 			QString text=xmlReader.readElementText();
22040 			cn->weightPercentage=customFETStrToDouble(text);
22041 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
22042 		}
22043 		else if(xmlReader.name()==QString("Active")){
22044 			QString text=xmlReader.readElementText();
22045 			if(text=="false"){
22046 				cn->active=false;
22047 			}
22048 		}
22049 		else if(xmlReader.name()==QString("Comments")){
22050 			QString text=xmlReader.readElementText();
22051 			cn->comments=text;
22052 		}
22053 		else if(xmlReader.name()==QString("Compulsory")){
22054 			QString text=xmlReader.readElementText();
22055 			if(text=="yes"){
22056 				//cn->compulsory=true;
22057 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
22058 				cn->weightPercentage=100;
22059 			}
22060 			else{
22061 				//cn->compulsory=false;
22062 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
22063 				cn->weightPercentage=0;
22064 			}
22065 		}
22066 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
22067 			QString text=xmlReader.readElementText();
22068 			cn->maxHoursDaily=text.toInt();
22069 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
22070 		}
22071 		else if(xmlReader.name()==QString("Teacher_Name")){
22072 			QString text=xmlReader.readElementText();
22073 			cn->teacherName=text;
22074 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
22075 		}
22076 		else{
22077 			unrecognizedXmlTags.append(xmlReader.name().toString());
22078 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
22079 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
22080 
22081 			xmlReader.skipCurrentElement();
22082 			xmlReaderNumberOfUnrecognizedFields++;
22083 		}
22084 	}
22085 	return cn;
22086 }
22087 
readTeacherMaxHoursDailyRealDays(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)22088 TimeConstraint* Rules::readTeacherMaxHoursDailyRealDays(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
22089 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxHoursDailyRealDays"));
22090 	ConstraintTeacherMaxHoursDailyRealDays* cn=new ConstraintTeacherMaxHoursDailyRealDays();
22091 	while(xmlReader.readNextStartElement()){
22092 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
22093 		if(xmlReader.name()==QString("Weight")){
22094 			//cn->weight=customFETStrToDouble(text);
22095 			xmlReader.skipCurrentElement();
22096 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
22097 			cn->weightPercentage=100;
22098 		}
22099 		else if(xmlReader.name()==QString("Weight_Percentage")){
22100 			QString text=xmlReader.readElementText();
22101 			cn->weightPercentage=customFETStrToDouble(text);
22102 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
22103 		}
22104 		else if(xmlReader.name()==QString("Active")){
22105 			QString text=xmlReader.readElementText();
22106 			if(text=="false"){
22107 				cn->active=false;
22108 			}
22109 		}
22110 		else if(xmlReader.name()==QString("Comments")){
22111 			QString text=xmlReader.readElementText();
22112 			cn->comments=text;
22113 		}
22114 		else if(xmlReader.name()==QString("Compulsory")){
22115 			QString text=xmlReader.readElementText();
22116 			if(text=="yes"){
22117 				//cn->compulsory=true;
22118 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
22119 				cn->weightPercentage=100;
22120 			}
22121 			else{
22122 				//cn->compulsory=false;
22123 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
22124 				cn->weightPercentage=0;
22125 			}
22126 		}
22127 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
22128 			QString text=xmlReader.readElementText();
22129 			cn->maxHoursDaily=text.toInt();
22130 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
22131 		}
22132 		else if(xmlReader.name()==QString("Teacher_Name")){
22133 			QString text=xmlReader.readElementText();
22134 			cn->teacherName=text;
22135 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
22136 		}
22137 		else{
22138 			unrecognizedXmlTags.append(xmlReader.name().toString());
22139 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
22140 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
22141 
22142 			xmlReader.skipCurrentElement();
22143 			xmlReaderNumberOfUnrecognizedFields++;
22144 		}
22145 	}
22146 	return cn;
22147 }
22148 
readOldMATeachersMaxHoursDailyHalfDays(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)22149 TimeConstraint* Rules::readOldMATeachersMaxHoursDailyHalfDays(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
22150 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxHoursDailyHalfDays"));
22151 	ConstraintTeachersMaxHoursDaily* cn=new ConstraintTeachersMaxHoursDaily();
22152 	while(xmlReader.readNextStartElement()){
22153 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
22154 		if(xmlReader.name()==QString("Weight")){
22155 			//cn->weight=customFETStrToDouble(text);
22156 			xmlReader.skipCurrentElement();
22157 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
22158 			cn->weightPercentage=100;
22159 		}
22160 		else if(xmlReader.name()==QString("Weight_Percentage")){
22161 			QString text=xmlReader.readElementText();
22162 			cn->weightPercentage=customFETStrToDouble(text);
22163 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
22164 		}
22165 		else if(xmlReader.name()==QString("Active")){
22166 			QString text=xmlReader.readElementText();
22167 			if(text=="false"){
22168 				cn->active=false;
22169 			}
22170 		}
22171 		else if(xmlReader.name()==QString("Comments")){
22172 			QString text=xmlReader.readElementText();
22173 			cn->comments=text;
22174 		}
22175 		else if(xmlReader.name()==QString("Compulsory")){
22176 			QString text=xmlReader.readElementText();
22177 			if(text=="yes"){
22178 				//cn->compulsory=true;
22179 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
22180 				cn->weightPercentage=100;
22181 			}
22182 			else{
22183 				//cn->compulsory=false;
22184 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
22185 				cn->weightPercentage=0;
22186 			}
22187 		}
22188 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
22189 			QString text=xmlReader.readElementText();
22190 			cn->maxHoursDaily=text.toInt();
22191 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
22192 		}
22193 		else{
22194 			unrecognizedXmlTags.append(xmlReader.name().toString());
22195 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
22196 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
22197 
22198 			xmlReader.skipCurrentElement();
22199 			xmlReaderNumberOfUnrecognizedFields++;
22200 		}
22201 	}
22202 	return cn;
22203 }
22204 
readOldMATeacherMaxHoursDailyHalfDays(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)22205 TimeConstraint* Rules::readOldMATeacherMaxHoursDailyHalfDays(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
22206 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxHoursDailyHalfDays"));
22207 	ConstraintTeacherMaxHoursDaily* cn=new ConstraintTeacherMaxHoursDaily();
22208 	while(xmlReader.readNextStartElement()){
22209 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
22210 		if(xmlReader.name()==QString("Weight")){
22211 			//cn->weight=customFETStrToDouble(text);
22212 			xmlReader.skipCurrentElement();
22213 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
22214 			cn->weightPercentage=100;
22215 		}
22216 		else if(xmlReader.name()==QString("Weight_Percentage")){
22217 			QString text=xmlReader.readElementText();
22218 			cn->weightPercentage=customFETStrToDouble(text);
22219 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
22220 		}
22221 		else if(xmlReader.name()==QString("Active")){
22222 			QString text=xmlReader.readElementText();
22223 			if(text=="false"){
22224 				cn->active=false;
22225 			}
22226 		}
22227 		else if(xmlReader.name()==QString("Comments")){
22228 			QString text=xmlReader.readElementText();
22229 			cn->comments=text;
22230 		}
22231 		else if(xmlReader.name()==QString("Compulsory")){
22232 			QString text=xmlReader.readElementText();
22233 			if(text=="yes"){
22234 				//cn->compulsory=true;
22235 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
22236 				cn->weightPercentage=100;
22237 			}
22238 			else{
22239 				//cn->compulsory=false;
22240 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
22241 				cn->weightPercentage=0;
22242 			}
22243 		}
22244 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
22245 			QString text=xmlReader.readElementText();
22246 			cn->maxHoursDaily=text.toInt();
22247 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
22248 		}
22249 		else if(xmlReader.name()==QString("Teacher_Name")){
22250 			QString text=xmlReader.readElementText();
22251 			cn->teacherName=text;
22252 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
22253 		}
22254 		else{
22255 			unrecognizedXmlTags.append(xmlReader.name().toString());
22256 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
22257 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
22258 
22259 			xmlReader.skipCurrentElement();
22260 			xmlReaderNumberOfUnrecognizedFields++;
22261 		}
22262 	}
22263 	return cn;
22264 }
22265 
readOldMATeacherActivityTagMaxHoursDaily(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)22266 TimeConstraint* Rules::readOldMATeacherActivityTagMaxHoursDaily(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
22267 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherActivityTagMaxHoursDaily"));
22268 	ConstraintTeacherActivityTagMaxHoursDailyRealDays* cn=new ConstraintTeacherActivityTagMaxHoursDailyRealDays();
22269 	while(xmlReader.readNextStartElement()){
22270 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
22271 		if(xmlReader.name()==QString("Weight_Percentage")){
22272 			QString text=xmlReader.readElementText();
22273 			cn->weightPercentage=customFETStrToDouble(text);
22274 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
22275 		}
22276 		else if(xmlReader.name()==QString("Active")){
22277 			QString text=xmlReader.readElementText();
22278 			if(text=="false"){
22279 				cn->active=false;
22280 			}
22281 		}
22282 		else if(xmlReader.name()==QString("Comments")){
22283 			QString text=xmlReader.readElementText();
22284 			cn->comments=text;
22285 		}
22286 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
22287 			QString text=xmlReader.readElementText();
22288 			cn->maxHoursDaily=text.toInt();
22289 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
22290 		}
22291 		else if(xmlReader.name()==QString("Teacher_Name")){
22292 			QString text=xmlReader.readElementText();
22293 			cn->teacherName=text;
22294 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
22295 		}
22296 		else if(xmlReader.name()==QString("Activity_Tag_Name")){
22297 			QString text=xmlReader.readElementText();
22298 			cn->activityTagName=text;
22299 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
22300 		}
22301 		else{
22302 			unrecognizedXmlTags.append(xmlReader.name().toString());
22303 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
22304 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
22305 
22306 			xmlReader.skipCurrentElement();
22307 			xmlReaderNumberOfUnrecognizedFields++;
22308 		}
22309 	}
22310 	return cn;
22311 }
22312 
readTeacherActivityTagMaxHoursDailyRealDays(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)22313 TimeConstraint* Rules::readTeacherActivityTagMaxHoursDailyRealDays(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
22314 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherActivityTagMaxHoursDailyRealDays"));
22315 	ConstraintTeacherActivityTagMaxHoursDailyRealDays* cn=new ConstraintTeacherActivityTagMaxHoursDailyRealDays();
22316 	while(xmlReader.readNextStartElement()){
22317 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
22318 		if(xmlReader.name()==QString("Weight_Percentage")){
22319 			QString text=xmlReader.readElementText();
22320 			cn->weightPercentage=customFETStrToDouble(text);
22321 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
22322 		}
22323 		else if(xmlReader.name()==QString("Active")){
22324 			QString text=xmlReader.readElementText();
22325 			if(text=="false"){
22326 				cn->active=false;
22327 			}
22328 		}
22329 		else if(xmlReader.name()==QString("Comments")){
22330 			QString text=xmlReader.readElementText();
22331 			cn->comments=text;
22332 		}
22333 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
22334 			QString text=xmlReader.readElementText();
22335 			cn->maxHoursDaily=text.toInt();
22336 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
22337 		}
22338 		else if(xmlReader.name()==QString("Teacher_Name")){
22339 			QString text=xmlReader.readElementText();
22340 			cn->teacherName=text;
22341 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
22342 		}
22343 		else if(xmlReader.name()==QString("Activity_Tag_Name")){
22344 			QString text=xmlReader.readElementText();
22345 			cn->activityTagName=text;
22346 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
22347 		}
22348 		else{
22349 			unrecognizedXmlTags.append(xmlReader.name().toString());
22350 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
22351 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
22352 
22353 			xmlReader.skipCurrentElement();
22354 			xmlReaderNumberOfUnrecognizedFields++;
22355 		}
22356 	}
22357 	return cn;
22358 }
22359 
readOldMATeachersActivityTagMaxHoursDaily(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)22360 TimeConstraint* Rules::readOldMATeachersActivityTagMaxHoursDaily(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
22361 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersActivityTagMaxHoursDaily"));
22362 	ConstraintTeachersActivityTagMaxHoursDailyRealDays* cn=new ConstraintTeachersActivityTagMaxHoursDailyRealDays();
22363 	while(xmlReader.readNextStartElement()){
22364 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
22365 		if(xmlReader.name()==QString("Weight_Percentage")){
22366 			QString text=xmlReader.readElementText();
22367 			cn->weightPercentage=customFETStrToDouble(text);
22368 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
22369 		}
22370 		else if(xmlReader.name()==QString("Active")){
22371 			QString text=xmlReader.readElementText();
22372 			if(text=="false"){
22373 				cn->active=false;
22374 			}
22375 		}
22376 		else if(xmlReader.name()==QString("Comments")){
22377 			QString text=xmlReader.readElementText();
22378 			cn->comments=text;
22379 		}
22380 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
22381 			QString text=xmlReader.readElementText();
22382 			cn->maxHoursDaily=text.toInt();
22383 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
22384 		}
22385 		else if(xmlReader.name()==QString("Activity_Tag_Name")){
22386 			QString text=xmlReader.readElementText();
22387 			cn->activityTagName=text;
22388 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
22389 		}
22390 		else{
22391 			unrecognizedXmlTags.append(xmlReader.name().toString());
22392 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
22393 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
22394 
22395 			xmlReader.skipCurrentElement();
22396 			xmlReaderNumberOfUnrecognizedFields++;
22397 		}
22398 	}
22399 	return cn;
22400 }
22401 
readTeachersActivityTagMaxHoursDailyRealDays(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)22402 TimeConstraint* Rules::readTeachersActivityTagMaxHoursDailyRealDays(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
22403 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersActivityTagMaxHoursDailyRealDays"));
22404 	ConstraintTeachersActivityTagMaxHoursDailyRealDays* cn=new ConstraintTeachersActivityTagMaxHoursDailyRealDays();
22405 	while(xmlReader.readNextStartElement()){
22406 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
22407 		if(xmlReader.name()==QString("Weight_Percentage")){
22408 			QString text=xmlReader.readElementText();
22409 			cn->weightPercentage=customFETStrToDouble(text);
22410 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
22411 		}
22412 		else if(xmlReader.name()==QString("Active")){
22413 			QString text=xmlReader.readElementText();
22414 			if(text=="false"){
22415 				cn->active=false;
22416 			}
22417 		}
22418 		else if(xmlReader.name()==QString("Comments")){
22419 			QString text=xmlReader.readElementText();
22420 			cn->comments=text;
22421 		}
22422 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
22423 			QString text=xmlReader.readElementText();
22424 			cn->maxHoursDaily=text.toInt();
22425 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
22426 		}
22427 		else if(xmlReader.name()==QString("Activity_Tag_Name")){
22428 			QString text=xmlReader.readElementText();
22429 			cn->activityTagName=text;
22430 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
22431 		}
22432 		else{
22433 			unrecognizedXmlTags.append(xmlReader.name().toString());
22434 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
22435 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
22436 
22437 			xmlReader.skipCurrentElement();
22438 			xmlReaderNumberOfUnrecognizedFields++;
22439 		}
22440 	}
22441 	return cn;
22442 }
22443 
22444 //2020-06-28
readTeacherMaxHoursPerAllAfternoons(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)22445 TimeConstraint* Rules::readTeacherMaxHoursPerAllAfternoons(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
22446 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxHoursPerAllAfternoons"));
22447 	ConstraintTeacherMaxHoursPerAllAfternoons* cn=new ConstraintTeacherMaxHoursPerAllAfternoons();
22448 	while(xmlReader.readNextStartElement()){
22449 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
22450 		if(xmlReader.name()==QString("Weight_Percentage")){
22451 			QString text=xmlReader.readElementText();
22452 			cn->weightPercentage=customFETStrToDouble(text);
22453 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
22454 		}
22455 		else if(xmlReader.name()==QString("Active")){
22456 			QString text=xmlReader.readElementText();
22457 			if(text=="false"){
22458 				cn->active=false;
22459 			}
22460 		}
22461 		else if(xmlReader.name()==QString("Comments")){
22462 			QString text=xmlReader.readElementText();
22463 			cn->comments=text;
22464 		}
22465 		else if(xmlReader.name()==QString("Maximum_Hours_Per_All_Afternoons")){
22466 			QString text=xmlReader.readElementText();
22467 			cn->maxHoursPerAllAfternoons=text.toInt();
22468 			xmlReadingLog+="    Read maxHoursPerAllAfternoons="+CustomFETString::number(cn->maxHoursPerAllAfternoons)+"\n";
22469 		}
22470 		else if(xmlReader.name()==QString("Teacher_Name")){
22471 			QString text=xmlReader.readElementText();
22472 			cn->teacherName=text;
22473 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
22474 		}
22475 		else{
22476 			unrecognizedXmlTags.append(xmlReader.name().toString());
22477 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
22478 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
22479 
22480 			xmlReader.skipCurrentElement();
22481 			xmlReaderNumberOfUnrecognizedFields++;
22482 		}
22483 	}
22484 	return cn;
22485 }
22486 
readTeachersMaxHoursPerAllAfternoons(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)22487 TimeConstraint* Rules::readTeachersMaxHoursPerAllAfternoons(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
22488 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxHoursPerAllAfternoons"));
22489 	ConstraintTeachersMaxHoursPerAllAfternoons* cn=new ConstraintTeachersMaxHoursPerAllAfternoons();
22490 	while(xmlReader.readNextStartElement()){
22491 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
22492 		if(xmlReader.name()==QString("Weight_Percentage")){
22493 			QString text=xmlReader.readElementText();
22494 			cn->weightPercentage=customFETStrToDouble(text);
22495 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
22496 		}
22497 		else if(xmlReader.name()==QString("Active")){
22498 			QString text=xmlReader.readElementText();
22499 			if(text=="false"){
22500 				cn->active=false;
22501 			}
22502 		}
22503 		else if(xmlReader.name()==QString("Comments")){
22504 			QString text=xmlReader.readElementText();
22505 			cn->comments=text;
22506 		}
22507 		else if(xmlReader.name()==QString("Maximum_Hours_Per_All_Afternoons")){
22508 			QString text=xmlReader.readElementText();
22509 			cn->maxHoursPerAllAfternoons=text.toInt();
22510 			xmlReadingLog+="    Read maxHoursPerAllAfternoons="+CustomFETString::number(cn->maxHoursPerAllAfternoons)+"\n";
22511 		}
22512 		else{
22513 			unrecognizedXmlTags.append(xmlReader.name().toString());
22514 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
22515 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
22516 
22517 			xmlReader.skipCurrentElement();
22518 			xmlReaderNumberOfUnrecognizedFields++;
22519 		}
22520 	}
22521 	return cn;
22522 }
22523 
22524 //2020-06-28
readStudentsSetMaxHoursPerAllAfternoons(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)22525 TimeConstraint* Rules::readStudentsSetMaxHoursPerAllAfternoons(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
22526 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMaxHoursPerAllAfternoons"));
22527 	ConstraintStudentsSetMaxHoursPerAllAfternoons* cn=new ConstraintStudentsSetMaxHoursPerAllAfternoons();
22528 	while(xmlReader.readNextStartElement()){
22529 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
22530 		if(xmlReader.name()==QString("Weight_Percentage")){
22531 			QString text=xmlReader.readElementText();
22532 			cn->weightPercentage=customFETStrToDouble(text);
22533 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
22534 		}
22535 		else if(xmlReader.name()==QString("Active")){
22536 			QString text=xmlReader.readElementText();
22537 			if(text=="false"){
22538 				cn->active=false;
22539 			}
22540 		}
22541 		else if(xmlReader.name()==QString("Comments")){
22542 			QString text=xmlReader.readElementText();
22543 			cn->comments=text;
22544 		}
22545 		else if(xmlReader.name()==QString("Maximum_Hours_Per_All_Afternoons")){
22546 			QString text=xmlReader.readElementText();
22547 			cn->maxHoursPerAllAfternoons=text.toInt();
22548 			xmlReadingLog+="    Read maxHoursPerAllAfternoons="+CustomFETString::number(cn->maxHoursPerAllAfternoons)+"\n";
22549 		}
22550 		else if(xmlReader.name()==QString("Students")){
22551 			QString text=xmlReader.readElementText();
22552 			cn->students=text;
22553 			xmlReadingLog+="    Read students name="+cn->students+"\n";
22554 		}
22555 		else{
22556 			unrecognizedXmlTags.append(xmlReader.name().toString());
22557 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
22558 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
22559 
22560 			xmlReader.skipCurrentElement();
22561 			xmlReaderNumberOfUnrecognizedFields++;
22562 		}
22563 	}
22564 	return cn;
22565 }
22566 
readStudentsMaxHoursPerAllAfternoons(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)22567 TimeConstraint* Rules::readStudentsMaxHoursPerAllAfternoons(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
22568 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMaxHoursPerAllAfternoons"));
22569 	ConstraintStudentsMaxHoursPerAllAfternoons* cn=new ConstraintStudentsMaxHoursPerAllAfternoons();
22570 	while(xmlReader.readNextStartElement()){
22571 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
22572 		if(xmlReader.name()==QString("Weight_Percentage")){
22573 			QString text=xmlReader.readElementText();
22574 			cn->weightPercentage=customFETStrToDouble(text);
22575 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
22576 		}
22577 		else if(xmlReader.name()==QString("Active")){
22578 			QString text=xmlReader.readElementText();
22579 			if(text=="false"){
22580 				cn->active=false;
22581 			}
22582 		}
22583 		else if(xmlReader.name()==QString("Comments")){
22584 			QString text=xmlReader.readElementText();
22585 			cn->comments=text;
22586 		}
22587 		else if(xmlReader.name()==QString("Maximum_Hours_Per_All_Afternoons")){
22588 			QString text=xmlReader.readElementText();
22589 			cn->maxHoursPerAllAfternoons=text.toInt();
22590 			xmlReadingLog+="    Read maxHoursPerAllAfternoons="+CustomFETString::number(cn->maxHoursPerAllAfternoons)+"\n";
22591 		}
22592 		else{
22593 			unrecognizedXmlTags.append(xmlReader.name().toString());
22594 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
22595 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
22596 
22597 			xmlReader.skipCurrentElement();
22598 			xmlReaderNumberOfUnrecognizedFields++;
22599 		}
22600 	}
22601 	return cn;
22602 }
22603 //
22604 
readTeachersMinHoursPerMorning(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)22605 TimeConstraint* Rules::readTeachersMinHoursPerMorning(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
22606 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMinHoursPerMorning"));
22607 	ConstraintTeachersMinHoursPerMorning* cn=new ConstraintTeachersMinHoursPerMorning();
22608 	cn->allowEmptyMornings=true;
22609 	while(xmlReader.readNextStartElement()){
22610 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
22611 		if(xmlReader.name()==QString("Weight")){
22612 			//cn->weight=customFETStrToDouble(text);
22613 			xmlReader.skipCurrentElement();
22614 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
22615 			cn->weightPercentage=100;
22616 		}
22617 		else if(xmlReader.name()==QString("Weight_Percentage")){
22618 			QString text=xmlReader.readElementText();
22619 			cn->weightPercentage=customFETStrToDouble(text);
22620 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
22621 		}
22622 		else if(xmlReader.name()==QString("Active")){
22623 			QString text=xmlReader.readElementText();
22624 			if(text=="false"){
22625 				cn->active=false;
22626 			}
22627 		}
22628 		else if(xmlReader.name()==QString("Comments")){
22629 			QString text=xmlReader.readElementText();
22630 			cn->comments=text;
22631 		}
22632 		else if(xmlReader.name()==QString("Compulsory")){
22633 			QString text=xmlReader.readElementText();
22634 			if(text=="yes"){
22635 				//cn->compulsory=true;
22636 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
22637 				cn->weightPercentage=100;
22638 			}
22639 			else{
22640 				//cn->compulsory=false;
22641 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
22642 				cn->weightPercentage=0;
22643 			}
22644 		}
22645 		else if(xmlReader.name()==QString("Minimum_Hours_Per_Morning")){
22646 			QString text=xmlReader.readElementText();
22647 			cn->minHoursPerMorning=text.toInt();
22648 			xmlReadingLog+="    Read minHoursPerMorning="+CustomFETString::number(cn->minHoursPerMorning)+"\n";
22649 		}
22650 		//obsolete
22651 		else if(xmlReader.name()==QString("Allow_Empty_Days")){
22652 			QString text=xmlReader.readElementText();
22653 			if(text=="true" || text=="1" || text=="yes"){
22654 				xmlReadingLog+="    Read allow empty days=true\n";
22655 				cn->allowEmptyMornings=true;
22656 			}
22657 			else{
22658 				if(!(text=="no" || text=="false" || text=="0")){
22659 					RulesReconcilableMessage::warning(parent, tr("FET warning"),
22660 						tr("Found constraint teachers min hours per morning with tag allow empty days"
22661 						" which is not 'true', 'false', 'yes', 'no', '1' or '0'."
22662 						" The tag will be considered false",
22663 						"Instructions for translators: please leave the 'true', 'false', 'yes' and 'no' fields untranslated, as they are in English"));
22664 				}
22665 				//assert(text=="false" || text=="0" || text=="no");
22666 				xmlReadingLog+="    Read allow empty days=false\n";
22667 				cn->allowEmptyMornings=false;
22668 			}
22669 		}
22670 		else if(xmlReader.name()==QString("Allow_Empty_Mornings")){
22671 			QString text=xmlReader.readElementText();
22672 			if(text=="true" || text=="1" || text=="yes"){
22673 				xmlReadingLog+="    Read allow empty mornings=true\n";
22674 				cn->allowEmptyMornings=true;
22675 			}
22676 			else{
22677 				if(!(text=="no" || text=="false" || text=="0")){
22678 					RulesReconcilableMessage::warning(parent, tr("FET warning"),
22679 						tr("Found constraint teachers min hours per morning with tag allow empty mornings"
22680 						" which is not 'true', 'false', 'yes', 'no', '1' or '0'."
22681 						" The tag will be considered false",
22682 						"Instructions for translators: please leave the 'true', 'false', 'yes' and 'no' fields untranslated, as they are in English"));
22683 				}
22684 				//assert(text=="false" || text=="0" || text=="no");
22685 				xmlReadingLog+="    Read allow empty mornings=false\n";
22686 				cn->allowEmptyMornings=false;
22687 			}
22688 		}
22689 		else{
22690 			unrecognizedXmlTags.append(xmlReader.name().toString());
22691 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
22692 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
22693 
22694 			xmlReader.skipCurrentElement();
22695 			xmlReaderNumberOfUnrecognizedFields++;
22696 		}
22697 	}
22698 	return cn;
22699 }
22700 
readTeacherMinHoursPerMorning(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)22701 TimeConstraint* Rules::readTeacherMinHoursPerMorning(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
22702 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMinHoursPerMorning"));
22703 	ConstraintTeacherMinHoursPerMorning* cn=new ConstraintTeacherMinHoursPerMorning();
22704 	cn->allowEmptyMornings=true;
22705 	while(xmlReader.readNextStartElement()){
22706 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
22707 		if(xmlReader.name()==QString("Weight")){
22708 			//cn->weight=customFETStrToDouble(text);
22709 			xmlReader.skipCurrentElement();
22710 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
22711 			cn->weightPercentage=100;
22712 		}
22713 		else if(xmlReader.name()==QString("Weight_Percentage")){
22714 			QString text=xmlReader.readElementText();
22715 			cn->weightPercentage=customFETStrToDouble(text);
22716 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
22717 		}
22718 		else if(xmlReader.name()==QString("Active")){
22719 			QString text=xmlReader.readElementText();
22720 			if(text=="false"){
22721 				cn->active=false;
22722 			}
22723 		}
22724 		else if(xmlReader.name()==QString("Comments")){
22725 			QString text=xmlReader.readElementText();
22726 			cn->comments=text;
22727 		}
22728 		else if(xmlReader.name()==QString("Compulsory")){
22729 			QString text=xmlReader.readElementText();
22730 			if(text=="yes"){
22731 				//cn->compulsory=true;
22732 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
22733 				cn->weightPercentage=100;
22734 			}
22735 			else{
22736 				//cn->compulsory=false;
22737 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
22738 				cn->weightPercentage=0;
22739 			}
22740 		}
22741 		else if(xmlReader.name()==QString("Minimum_Hours_Per_Morning")){
22742 			QString text=xmlReader.readElementText();
22743 			cn->minHoursPerMorning=text.toInt();
22744 			xmlReadingLog+="    Read minHoursPerMorning="+CustomFETString::number(cn->minHoursPerMorning)+"\n";
22745 		}
22746 		else if(xmlReader.name()==QString("Teacher_Name")){
22747 			QString text=xmlReader.readElementText();
22748 			cn->teacherName=text;
22749 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
22750 		}
22751 		//obsolete
22752 		else if(xmlReader.name()==QString("Allow_Empty_Days")){
22753 			QString text=xmlReader.readElementText();
22754 			if(text=="true" || text=="1" || text=="yes"){
22755 				xmlReadingLog+="    Read allow empty days=true\n";
22756 				cn->allowEmptyMornings=true;
22757 			}
22758 			else{
22759 				if(!(text=="no" || text=="false" || text=="0")){
22760 					RulesReconcilableMessage::warning(parent, tr("FET warning"),
22761 						tr("Found constraint teacher min hours per morning with tag allow empty days"
22762 						" which is not 'true', 'false', 'yes', 'no', '1' or '0'."
22763 						" The tag will be considered false",
22764 						"Instructions for translators: please leave the 'true', 'false', 'yes' and 'no' fields untranslated, as they are in English"));
22765 				}
22766 				//assert(text=="false" || text=="0" || text=="no");
22767 				xmlReadingLog+="    Read allow empty days=false\n";
22768 				cn->allowEmptyMornings=false;
22769 			}
22770 		}
22771 		else if(xmlReader.name()==QString("Allow_Empty_Mornings")){
22772 			QString text=xmlReader.readElementText();
22773 			if(text=="true" || text=="1" || text=="yes"){
22774 				xmlReadingLog+="    Read allow empty mornings=true\n";
22775 				cn->allowEmptyMornings=true;
22776 			}
22777 			else{
22778 				if(!(text=="no" || text=="false" || text=="0")){
22779 					RulesReconcilableMessage::warning(parent, tr("FET warning"),
22780 						tr("Found constraint teacher min hours per morning with tag allow empty mornings"
22781 						" which is not 'true', 'false', 'yes', 'no', '1' or '0'."
22782 						" The tag will be considered false",
22783 						"Instructions for translators: please leave the 'true', 'false', 'yes' and 'no' fields untranslated, as they are in English"));
22784 				}
22785 				//assert(text=="false" || text=="0" || text=="no");
22786 				xmlReadingLog+="    Read allow empty mornings=false\n";
22787 				cn->allowEmptyMornings=false;
22788 			}
22789 		}
22790 		else{
22791 			unrecognizedXmlTags.append(xmlReader.name().toString());
22792 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
22793 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
22794 
22795 			xmlReader.skipCurrentElement();
22796 			xmlReaderNumberOfUnrecognizedFields++;
22797 		}
22798 	}
22799 	return cn;
22800 }
22801 
readTeachersMinHoursDailyRealDays(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)22802 TimeConstraint* Rules::readTeachersMinHoursDailyRealDays(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
22803 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMinHoursDailyRealDays"));
22804 	ConstraintTeachersMinHoursDailyRealDays* cn=new ConstraintTeachersMinHoursDailyRealDays();
22805 	cn->allowEmptyDays=true;
22806 	while(xmlReader.readNextStartElement()){
22807 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
22808 		if(xmlReader.name()==QString("Weight")){
22809 			//cn->weight=customFETStrToDouble(text);
22810 			xmlReader.skipCurrentElement();
22811 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
22812 			cn->weightPercentage=100;
22813 		}
22814 		else if(xmlReader.name()==QString("Weight_Percentage")){
22815 			QString text=xmlReader.readElementText();
22816 			cn->weightPercentage=customFETStrToDouble(text);
22817 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
22818 		}
22819 		else if(xmlReader.name()==QString("Active")){
22820 			QString text=xmlReader.readElementText();
22821 			if(text=="false"){
22822 				cn->active=false;
22823 			}
22824 		}
22825 		else if(xmlReader.name()==QString("Comments")){
22826 			QString text=xmlReader.readElementText();
22827 			cn->comments=text;
22828 		}
22829 		else if(xmlReader.name()==QString("Compulsory")){
22830 			QString text=xmlReader.readElementText();
22831 			if(text=="yes"){
22832 				//cn->compulsory=true;
22833 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
22834 				cn->weightPercentage=100;
22835 			}
22836 			else{
22837 				//cn->compulsory=false;
22838 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
22839 				cn->weightPercentage=0;
22840 			}
22841 		}
22842 		else if(xmlReader.name()==QString("Minimum_Hours_Daily")){
22843 			QString text=xmlReader.readElementText();
22844 			cn->minHoursDaily=text.toInt();
22845 			xmlReadingLog+="    Read minHoursDaily="+CustomFETString::number(cn->minHoursDaily)+"\n";
22846 		}
22847 		else if(xmlReader.name()==QString("Allow_Empty_Days")){
22848 			QString text=xmlReader.readElementText();
22849 			if(text=="true" || text=="1" || text=="yes"){
22850 				xmlReadingLog+="    Read allow empty days=true\n";
22851 				cn->allowEmptyDays=true;
22852 			}
22853 			else{
22854 				if(!(text=="no" || text=="false" || text=="0")){
22855 					RulesReconcilableMessage::warning(parent, tr("FET warning"),
22856 						tr("Found constraint teachers min hours daily with tag allow empty days"
22857 						" which is not 'true', 'false', 'yes', 'no', '1' or '0'."
22858 						" The tag will be considered false",
22859 						"Instructions for translators: please leave the 'true', 'false', 'yes' and 'no' fields untranslated, as they are in English"));
22860 				}
22861 				//assert(text=="false" || text=="0" || text=="no");
22862 				xmlReadingLog+="    Read allow empty days=false\n";
22863 				cn->allowEmptyDays=false;
22864 			}
22865 		}
22866 		else{
22867 			unrecognizedXmlTags.append(xmlReader.name().toString());
22868 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
22869 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
22870 
22871 			xmlReader.skipCurrentElement();
22872 			xmlReaderNumberOfUnrecognizedFields++;
22873 		}
22874 	}
22875 	return cn;
22876 }
22877 
readTeacherMinHoursDailyRealDays(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)22878 TimeConstraint* Rules::readTeacherMinHoursDailyRealDays(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
22879 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMinHoursDailyRealDays"));
22880 	ConstraintTeacherMinHoursDailyRealDays* cn=new ConstraintTeacherMinHoursDailyRealDays();
22881 	cn->allowEmptyDays=true;
22882 	while(xmlReader.readNextStartElement()){
22883 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
22884 		if(xmlReader.name()==QString("Weight")){
22885 			//cn->weight=customFETStrToDouble(text);
22886 			xmlReader.skipCurrentElement();
22887 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
22888 			cn->weightPercentage=100;
22889 		}
22890 		else if(xmlReader.name()==QString("Weight_Percentage")){
22891 			QString text=xmlReader.readElementText();
22892 			cn->weightPercentage=customFETStrToDouble(text);
22893 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
22894 		}
22895 		else if(xmlReader.name()==QString("Active")){
22896 			QString text=xmlReader.readElementText();
22897 			if(text=="false"){
22898 				cn->active=false;
22899 			}
22900 		}
22901 		else if(xmlReader.name()==QString("Comments")){
22902 			QString text=xmlReader.readElementText();
22903 			cn->comments=text;
22904 		}
22905 		else if(xmlReader.name()==QString("Compulsory")){
22906 			QString text=xmlReader.readElementText();
22907 			if(text=="yes"){
22908 				//cn->compulsory=true;
22909 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
22910 				cn->weightPercentage=100;
22911 			}
22912 			else{
22913 				//cn->compulsory=false;
22914 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
22915 				cn->weightPercentage=0;
22916 			}
22917 		}
22918 		else if(xmlReader.name()==QString("Minimum_Hours_Daily")){
22919 			QString text=xmlReader.readElementText();
22920 			cn->minHoursDaily=text.toInt();
22921 			xmlReadingLog+="    Read minHoursDaily="+CustomFETString::number(cn->minHoursDaily)+"\n";
22922 		}
22923 		else if(xmlReader.name()==QString("Teacher_Name")){
22924 			QString text=xmlReader.readElementText();
22925 			cn->teacherName=text;
22926 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
22927 		}
22928 		else if(xmlReader.name()==QString("Allow_Empty_Days")){
22929 			QString text=xmlReader.readElementText();
22930 			if(text=="true" || text=="1" || text=="yes"){
22931 				xmlReadingLog+="    Read allow empty days=true\n";
22932 				cn->allowEmptyDays=true;
22933 			}
22934 			else{
22935 				if(!(text=="no" || text=="false" || text=="0")){
22936 					RulesReconcilableMessage::warning(parent, tr("FET warning"),
22937 						tr("Found constraint teacher min hours daily with tag allow empty days"
22938 						" which is not 'true', 'false', 'yes', 'no', '1' or '0'."
22939 						" The tag will be considered false",
22940 						"Instructions for translators: please leave the 'true', 'false', 'yes' and 'no' fields untranslated, as they are in English"));
22941 				}
22942 				//assert(text=="false" || text=="0" || text=="no");
22943 				xmlReadingLog+="    Read allow empty days=false\n";
22944 				cn->allowEmptyDays=false;
22945 			}
22946 		}
22947 		else{
22948 			unrecognizedXmlTags.append(xmlReader.name().toString());
22949 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
22950 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
22951 
22952 			xmlReader.skipCurrentElement();
22953 			xmlReaderNumberOfUnrecognizedFields++;
22954 		}
22955 	}
22956 	return cn;
22957 }
22958 
readOldMAStudentsMaxHoursDaily(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)22959 TimeConstraint* Rules::readOldMAStudentsMaxHoursDaily(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
22960 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMaxHoursDaily"));
22961 	ConstraintStudentsMaxHoursDailyRealDays* cn=new ConstraintStudentsMaxHoursDailyRealDays();
22962 	cn->maxHoursDaily=-1;
22963 	while(xmlReader.readNextStartElement()){
22964 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
22965 		if(xmlReader.name()==QString("Weight")){
22966 			//cn->weight=customFETStrToDouble(text);
22967 			xmlReader.skipCurrentElement();
22968 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
22969 			cn->weightPercentage=100;
22970 		}
22971 		else if(xmlReader.name()==QString("Weight_Percentage")){
22972 			QString text=xmlReader.readElementText();
22973 			cn->weightPercentage=customFETStrToDouble(text);
22974 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
22975 		}
22976 		else if(xmlReader.name()==QString("Active")){
22977 			QString text=xmlReader.readElementText();
22978 			if(text=="false"){
22979 				cn->active=false;
22980 			}
22981 		}
22982 		else if(xmlReader.name()==QString("Comments")){
22983 			QString text=xmlReader.readElementText();
22984 			cn->comments=text;
22985 		}
22986 		else if(xmlReader.name()==QString("Compulsory")){
22987 			QString text=xmlReader.readElementText();
22988 			if(text=="yes"){
22989 				//cn->compulsory=true;
22990 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
22991 				cn->weightPercentage=100;
22992 			}
22993 			else{
22994 				//cn->compulsory=false;
22995 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
22996 				cn->weightPercentage=0;
22997 			}
22998 		}
22999 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
23000 			QString text=xmlReader.readElementText();
23001 			cn->maxHoursDaily=text.toInt();
23002 			if(cn->maxHoursDaily<0){
23003 				xmlReader.raiseError(tr("%1 is incorrect").arg("Maximum_Hours_Daily"));
23004 				delete cn;
23005 				cn=nullptr;
23006 				return nullptr;
23007 			}
23008 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
23009 		}
23010 		else{
23011 			unrecognizedXmlTags.append(xmlReader.name().toString());
23012 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
23013 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
23014 
23015 			xmlReader.skipCurrentElement();
23016 			xmlReaderNumberOfUnrecognizedFields++;
23017 		}
23018 	}
23019 	if(cn->maxHoursDaily<0){
23020 		xmlReader.raiseError(tr("%1 not found").arg("Maximum_Hours_Daily"));
23021 		delete cn;
23022 		cn=nullptr;
23023 		return nullptr;
23024 	}
23025 	assert(cn->maxHoursDaily>=0);
23026 	return cn;
23027 }
23028 
readStudentsMaxHoursDailyRealDays(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)23029 TimeConstraint* Rules::readStudentsMaxHoursDailyRealDays(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
23030 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMaxHoursDailyRealDays"));
23031 	ConstraintStudentsMaxHoursDailyRealDays* cn=new ConstraintStudentsMaxHoursDailyRealDays();
23032 	cn->maxHoursDaily=-1;
23033 	while(xmlReader.readNextStartElement()){
23034 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
23035 		if(xmlReader.name()==QString("Weight")){
23036 			//cn->weight=customFETStrToDouble(text);
23037 			xmlReader.skipCurrentElement();
23038 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
23039 			cn->weightPercentage=100;
23040 		}
23041 		else if(xmlReader.name()==QString("Weight_Percentage")){
23042 			QString text=xmlReader.readElementText();
23043 			cn->weightPercentage=customFETStrToDouble(text);
23044 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
23045 		}
23046 		else if(xmlReader.name()==QString("Active")){
23047 			QString text=xmlReader.readElementText();
23048 			if(text=="false"){
23049 				cn->active=false;
23050 			}
23051 		}
23052 		else if(xmlReader.name()==QString("Comments")){
23053 			QString text=xmlReader.readElementText();
23054 			cn->comments=text;
23055 		}
23056 		else if(xmlReader.name()==QString("Compulsory")){
23057 			QString text=xmlReader.readElementText();
23058 			if(text=="yes"){
23059 				//cn->compulsory=true;
23060 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
23061 				cn->weightPercentage=100;
23062 			}
23063 			else{
23064 				//cn->compulsory=false;
23065 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
23066 				cn->weightPercentage=0;
23067 			}
23068 		}
23069 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
23070 			QString text=xmlReader.readElementText();
23071 			cn->maxHoursDaily=text.toInt();
23072 			if(cn->maxHoursDaily<0){
23073 				xmlReader.raiseError(tr("%1 is incorrect").arg("Maximum_Hours_Daily"));
23074 				delete cn;
23075 				cn=nullptr;
23076 				return nullptr;
23077 			}
23078 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
23079 		}
23080 		else{
23081 			unrecognizedXmlTags.append(xmlReader.name().toString());
23082 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
23083 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
23084 
23085 			xmlReader.skipCurrentElement();
23086 			xmlReaderNumberOfUnrecognizedFields++;
23087 		}
23088 	}
23089 	if(cn->maxHoursDaily<0){
23090 		xmlReader.raiseError(tr("%1 not found").arg("Maximum_Hours_Daily"));
23091 		delete cn;
23092 		cn=nullptr;
23093 		return nullptr;
23094 	}
23095 	assert(cn->maxHoursDaily>=0);
23096 	return cn;
23097 }
23098 
readOldMAStudentsSetMaxHoursDaily(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)23099 TimeConstraint* Rules::readOldMAStudentsSetMaxHoursDaily(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
23100 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMaxHoursDaily"));
23101 	ConstraintStudentsSetMaxHoursDailyRealDays* cn=new ConstraintStudentsSetMaxHoursDailyRealDays();
23102 	cn->maxHoursDaily=-1;
23103 	while(xmlReader.readNextStartElement()){
23104 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
23105 		if(xmlReader.name()==QString("Weight")){
23106 			//cn->weight=customFETStrToDouble(text);
23107 			xmlReader.skipCurrentElement();
23108 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
23109 			cn->weightPercentage=100;
23110 		}
23111 		else if(xmlReader.name()==QString("Weight_Percentage")){
23112 			QString text=xmlReader.readElementText();
23113 			cn->weightPercentage=customFETStrToDouble(text);
23114 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
23115 		}
23116 		else if(xmlReader.name()==QString("Active")){
23117 			QString text=xmlReader.readElementText();
23118 			if(text=="false"){
23119 				cn->active=false;
23120 			}
23121 		}
23122 		else if(xmlReader.name()==QString("Comments")){
23123 			QString text=xmlReader.readElementText();
23124 			cn->comments=text;
23125 		}
23126 		else if(xmlReader.name()==QString("Compulsory")){
23127 			QString text=xmlReader.readElementText();
23128 			if(text=="yes"){
23129 				//cn->compulsory=true;
23130 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
23131 				cn->weightPercentage=100;
23132 			}
23133 			else{
23134 				//cn->compulsory=false;
23135 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
23136 				cn->weightPercentage=0;
23137 			}
23138 		}
23139 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
23140 			QString text=xmlReader.readElementText();
23141 			cn->maxHoursDaily=text.toInt();
23142 			if(cn->maxHoursDaily<0){
23143 				xmlReader.raiseError(tr("%1 is incorrect").arg("Maximum_Hours_Daily"));
23144 				delete cn;
23145 				cn=nullptr;
23146 				return nullptr;
23147 			}
23148 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
23149 		}
23150 		else if(xmlReader.name()==QString("Students")){
23151 			QString text=xmlReader.readElementText();
23152 			cn->students=text;
23153 			xmlReadingLog+="    Read students name="+cn->students+"\n";
23154 		}
23155 		else{
23156 			unrecognizedXmlTags.append(xmlReader.name().toString());
23157 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
23158 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
23159 
23160 			xmlReader.skipCurrentElement();
23161 			xmlReaderNumberOfUnrecognizedFields++;
23162 		}
23163 	}
23164 	if(cn->maxHoursDaily<0){
23165 		xmlReader.raiseError(tr("%1 not found").arg("Maximum_Hours_Daily"));
23166 		delete cn;
23167 		cn=nullptr;
23168 		return nullptr;
23169 	}
23170 	assert(cn->maxHoursDaily>=0);
23171 	return cn;
23172 }
23173 
readStudentsSetMaxHoursDailyRealDays(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)23174 TimeConstraint* Rules::readStudentsSetMaxHoursDailyRealDays(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
23175 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMaxHoursDailyRealDays"));
23176 	ConstraintStudentsSetMaxHoursDailyRealDays* cn=new ConstraintStudentsSetMaxHoursDailyRealDays();
23177 	cn->maxHoursDaily=-1;
23178 	while(xmlReader.readNextStartElement()){
23179 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
23180 		if(xmlReader.name()==QString("Weight")){
23181 			//cn->weight=customFETStrToDouble(text);
23182 			xmlReader.skipCurrentElement();
23183 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
23184 			cn->weightPercentage=100;
23185 		}
23186 		else if(xmlReader.name()==QString("Weight_Percentage")){
23187 			QString text=xmlReader.readElementText();
23188 			cn->weightPercentage=customFETStrToDouble(text);
23189 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
23190 		}
23191 		else if(xmlReader.name()==QString("Active")){
23192 			QString text=xmlReader.readElementText();
23193 			if(text=="false"){
23194 				cn->active=false;
23195 			}
23196 		}
23197 		else if(xmlReader.name()==QString("Comments")){
23198 			QString text=xmlReader.readElementText();
23199 			cn->comments=text;
23200 		}
23201 		else if(xmlReader.name()==QString("Compulsory")){
23202 			QString text=xmlReader.readElementText();
23203 			if(text=="yes"){
23204 				//cn->compulsory=true;
23205 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
23206 				cn->weightPercentage=100;
23207 			}
23208 			else{
23209 				//cn->compulsory=false;
23210 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
23211 				cn->weightPercentage=0;
23212 			}
23213 		}
23214 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
23215 			QString text=xmlReader.readElementText();
23216 			cn->maxHoursDaily=text.toInt();
23217 			if(cn->maxHoursDaily<0){
23218 				xmlReader.raiseError(tr("%1 is incorrect").arg("Maximum_Hours_Daily"));
23219 				delete cn;
23220 				cn=nullptr;
23221 				return nullptr;
23222 			}
23223 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
23224 		}
23225 		else if(xmlReader.name()==QString("Students")){
23226 			QString text=xmlReader.readElementText();
23227 			cn->students=text;
23228 			xmlReadingLog+="    Read students name="+cn->students+"\n";
23229 		}
23230 		else{
23231 			unrecognizedXmlTags.append(xmlReader.name().toString());
23232 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
23233 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
23234 
23235 			xmlReader.skipCurrentElement();
23236 			xmlReaderNumberOfUnrecognizedFields++;
23237 		}
23238 	}
23239 	if(cn->maxHoursDaily<0){
23240 		xmlReader.raiseError(tr("%1 not found").arg("Maximum_Hours_Daily"));
23241 		delete cn;
23242 		cn=nullptr;
23243 		return nullptr;
23244 	}
23245 	assert(cn->maxHoursDaily>=0);
23246 	return cn;
23247 }
23248 
readOldMAStudentsSetActivityTagMaxHoursDaily(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)23249 TimeConstraint* Rules::readOldMAStudentsSetActivityTagMaxHoursDaily(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
23250 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetActivityTagMaxHoursDaily"));
23251 	ConstraintStudentsSetActivityTagMaxHoursDailyRealDays* cn=new ConstraintStudentsSetActivityTagMaxHoursDailyRealDays();
23252 	cn->maxHoursDaily=-1;
23253 	while(xmlReader.readNextStartElement()){
23254 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
23255 		if(xmlReader.name()==QString("Weight_Percentage")){
23256 			QString text=xmlReader.readElementText();
23257 			cn->weightPercentage=customFETStrToDouble(text);
23258 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
23259 		}
23260 		else if(xmlReader.name()==QString("Active")){
23261 			QString text=xmlReader.readElementText();
23262 			if(text=="false"){
23263 				cn->active=false;
23264 			}
23265 		}
23266 		else if(xmlReader.name()==QString("Comments")){
23267 			QString text=xmlReader.readElementText();
23268 			cn->comments=text;
23269 		}
23270 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
23271 			QString text=xmlReader.readElementText();
23272 			cn->maxHoursDaily=text.toInt();
23273 			if(cn->maxHoursDaily<0){
23274 				xmlReader.raiseError(tr("%1 is incorrect").arg("Maximum_Hours_Daily"));
23275 				delete cn;
23276 				cn=nullptr;
23277 				return nullptr;
23278 			}
23279 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
23280 		}
23281 		else if(xmlReader.name()==QString("Students")){
23282 			QString text=xmlReader.readElementText();
23283 			cn->students=text;
23284 			xmlReadingLog+="    Read students name="+cn->students+"\n";
23285 		}
23286 		else if(xmlReader.name()==QString("Activity_Tag")){
23287 			QString text=xmlReader.readElementText();
23288 			cn->activityTagName=text;
23289 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
23290 		}
23291 		else{
23292 			unrecognizedXmlTags.append(xmlReader.name().toString());
23293 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
23294 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
23295 
23296 			xmlReader.skipCurrentElement();
23297 			xmlReaderNumberOfUnrecognizedFields++;
23298 		}
23299 	}
23300 	if(cn->maxHoursDaily<0){
23301 		xmlReader.raiseError(tr("%1 not found").arg("Maximum_Hours_Daily"));
23302 		delete cn;
23303 		cn=nullptr;
23304 		return nullptr;
23305 	}
23306 	assert(cn->maxHoursDaily>=0);
23307 	return cn;
23308 }
23309 
readStudentsSetActivityTagMaxHoursDailyRealDays(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)23310 TimeConstraint* Rules::readStudentsSetActivityTagMaxHoursDailyRealDays(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
23311 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetActivityTagMaxHoursDailyRealDays"));
23312 	ConstraintStudentsSetActivityTagMaxHoursDailyRealDays* cn=new ConstraintStudentsSetActivityTagMaxHoursDailyRealDays();
23313 	cn->maxHoursDaily=-1;
23314 	while(xmlReader.readNextStartElement()){
23315 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
23316 		if(xmlReader.name()==QString("Weight_Percentage")){
23317 			QString text=xmlReader.readElementText();
23318 			cn->weightPercentage=customFETStrToDouble(text);
23319 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
23320 		}
23321 		else if(xmlReader.name()==QString("Active")){
23322 			QString text=xmlReader.readElementText();
23323 			if(text=="false"){
23324 				cn->active=false;
23325 			}
23326 		}
23327 		else if(xmlReader.name()==QString("Comments")){
23328 			QString text=xmlReader.readElementText();
23329 			cn->comments=text;
23330 		}
23331 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
23332 			QString text=xmlReader.readElementText();
23333 			cn->maxHoursDaily=text.toInt();
23334 			if(cn->maxHoursDaily<0){
23335 				xmlReader.raiseError(tr("%1 is incorrect").arg("Maximum_Hours_Daily"));
23336 				delete cn;
23337 				cn=nullptr;
23338 				return nullptr;
23339 			}
23340 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
23341 		}
23342 		else if(xmlReader.name()==QString("Students")){
23343 			QString text=xmlReader.readElementText();
23344 			cn->students=text;
23345 			xmlReadingLog+="    Read students name="+cn->students+"\n";
23346 		}
23347 		else if(xmlReader.name()==QString("Activity_Tag")){
23348 			QString text=xmlReader.readElementText();
23349 			cn->activityTagName=text;
23350 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
23351 		}
23352 		else{
23353 			unrecognizedXmlTags.append(xmlReader.name().toString());
23354 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
23355 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
23356 
23357 			xmlReader.skipCurrentElement();
23358 			xmlReaderNumberOfUnrecognizedFields++;
23359 		}
23360 	}
23361 	if(cn->maxHoursDaily<0){
23362 		xmlReader.raiseError(tr("%1 not found").arg("Maximum_Hours_Daily"));
23363 		delete cn;
23364 		cn=nullptr;
23365 		return nullptr;
23366 	}
23367 	assert(cn->maxHoursDaily>=0);
23368 	return cn;
23369 }
23370 
readOldMAStudentsActivityTagMaxHoursDaily(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)23371 TimeConstraint* Rules::readOldMAStudentsActivityTagMaxHoursDaily(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
23372 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsActivityTagMaxHoursDaily"));
23373 	ConstraintStudentsActivityTagMaxHoursDailyRealDays* cn=new ConstraintStudentsActivityTagMaxHoursDailyRealDays();
23374 	cn->maxHoursDaily=-1;
23375 	while(xmlReader.readNextStartElement()){
23376 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
23377 		if(xmlReader.name()==QString("Weight_Percentage")){
23378 			QString text=xmlReader.readElementText();
23379 			cn->weightPercentage=customFETStrToDouble(text);
23380 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
23381 		}
23382 		else if(xmlReader.name()==QString("Active")){
23383 			QString text=xmlReader.readElementText();
23384 			if(text=="false"){
23385 				cn->active=false;
23386 			}
23387 		}
23388 		else if(xmlReader.name()==QString("Comments")){
23389 			QString text=xmlReader.readElementText();
23390 			cn->comments=text;
23391 		}
23392 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
23393 			QString text=xmlReader.readElementText();
23394 			cn->maxHoursDaily=text.toInt();
23395 			if(cn->maxHoursDaily<0){
23396 				xmlReader.raiseError(tr("%1 is incorrect").arg("Maximum_Hours_Daily"));
23397 				delete cn;
23398 				cn=nullptr;
23399 				return nullptr;
23400 			}
23401 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
23402 		}
23403 		else if(xmlReader.name()==QString("Activity_Tag")){
23404 			QString text=xmlReader.readElementText();
23405 			cn->activityTagName=text;
23406 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
23407 		}
23408 		else{
23409 			unrecognizedXmlTags.append(xmlReader.name().toString());
23410 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
23411 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
23412 
23413 			xmlReader.skipCurrentElement();
23414 			xmlReaderNumberOfUnrecognizedFields++;
23415 		}
23416 	}
23417 	if(cn->maxHoursDaily<0){
23418 		xmlReader.raiseError(tr("%1 not found").arg("Maximum_Hours_Daily"));
23419 		delete cn;
23420 		cn=nullptr;
23421 		return nullptr;
23422 	}
23423 	assert(cn->maxHoursDaily>=0);
23424 	return cn;
23425 }
23426 
readStudentsActivityTagMaxHoursDailyRealDays(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)23427 TimeConstraint* Rules::readStudentsActivityTagMaxHoursDailyRealDays(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
23428 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsActivityTagMaxHoursDailyRealDays"));
23429 	ConstraintStudentsActivityTagMaxHoursDailyRealDays* cn=new ConstraintStudentsActivityTagMaxHoursDailyRealDays();
23430 	cn->maxHoursDaily=-1;
23431 	while(xmlReader.readNextStartElement()){
23432 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
23433 		if(xmlReader.name()==QString("Weight_Percentage")){
23434 			QString text=xmlReader.readElementText();
23435 			cn->weightPercentage=customFETStrToDouble(text);
23436 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
23437 		}
23438 		else if(xmlReader.name()==QString("Active")){
23439 			QString text=xmlReader.readElementText();
23440 			if(text=="false"){
23441 				cn->active=false;
23442 			}
23443 		}
23444 		else if(xmlReader.name()==QString("Comments")){
23445 			QString text=xmlReader.readElementText();
23446 			cn->comments=text;
23447 		}
23448 		else if(xmlReader.name()==QString("Maximum_Hours_Daily")){
23449 			QString text=xmlReader.readElementText();
23450 			cn->maxHoursDaily=text.toInt();
23451 			if(cn->maxHoursDaily<0){
23452 				xmlReader.raiseError(tr("%1 is incorrect").arg("Maximum_Hours_Daily"));
23453 				delete cn;
23454 				cn=nullptr;
23455 				return nullptr;
23456 			}
23457 			xmlReadingLog+="    Read maxHoursDaily="+CustomFETString::number(cn->maxHoursDaily)+"\n";
23458 		}
23459 		else if(xmlReader.name()==QString("Activity_Tag")){
23460 			QString text=xmlReader.readElementText();
23461 			cn->activityTagName=text;
23462 			xmlReadingLog+="    Read activity tag name="+cn->activityTagName+"\n";
23463 		}
23464 		else{
23465 			unrecognizedXmlTags.append(xmlReader.name().toString());
23466 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
23467 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
23468 
23469 			xmlReader.skipCurrentElement();
23470 			xmlReaderNumberOfUnrecognizedFields++;
23471 		}
23472 	}
23473 	if(cn->maxHoursDaily<0){
23474 		xmlReader.raiseError(tr("%1 not found").arg("Maximum_Hours_Daily"));
23475 		delete cn;
23476 		cn=nullptr;
23477 		return nullptr;
23478 	}
23479 	assert(cn->maxHoursDaily>=0);
23480 	return cn;
23481 }
23482 
readStudentsMinHoursPerMorning(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)23483 TimeConstraint* Rules::readStudentsMinHoursPerMorning(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
23484 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMinHoursPerMorning"));
23485 	ConstraintStudentsMinHoursPerMorning* cn=new ConstraintStudentsMinHoursPerMorning();
23486 	cn->minHoursPerMorning=-1;
23487 	cn->allowEmptyMornings=true;
23488 	while(xmlReader.readNextStartElement()){
23489 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
23490 		if(xmlReader.name()==QString("Weight")){
23491 			//cn->weight=customFETStrToDouble(text);
23492 			xmlReader.skipCurrentElement();
23493 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
23494 			cn->weightPercentage=100;
23495 		}
23496 		else if(xmlReader.name()==QString("Weight_Percentage")){
23497 			QString text=xmlReader.readElementText();
23498 			cn->weightPercentage=customFETStrToDouble(text);
23499 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
23500 		}
23501 		else if(xmlReader.name()==QString("Active")){
23502 			QString text=xmlReader.readElementText();
23503 			if(text=="false"){
23504 				cn->active=false;
23505 			}
23506 		}
23507 		else if(xmlReader.name()==QString("Comments")){
23508 			QString text=xmlReader.readElementText();
23509 			cn->comments=text;
23510 		}
23511 		else if(xmlReader.name()==QString("Compulsory")){
23512 			QString text=xmlReader.readElementText();
23513 			if(text=="yes"){
23514 				//cn->compulsory=true;
23515 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
23516 				cn->weightPercentage=100;
23517 			}
23518 			else{
23519 				//cn->compulsory=false;
23520 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
23521 				cn->weightPercentage=0;
23522 			}
23523 		}
23524 		else if(xmlReader.name()==QString("Minimum_Hours_Per_Morning")){
23525 			QString text=xmlReader.readElementText();
23526 			cn->minHoursPerMorning=text.toInt();
23527 			if(cn->minHoursPerMorning<0){
23528 				xmlReader.raiseError(tr("%1 is incorrect").arg("Minimum_Hours_Per_Morning"));
23529 				delete cn;
23530 				cn=nullptr;
23531 				return nullptr;
23532 			}
23533 			xmlReadingLog+="    Read minHoursPerMorning="+CustomFETString::number(cn->minHoursPerMorning)+"\n";
23534 		}
23535 		else if(xmlReader.name()==QString("Allow_Empty_Mornings")){
23536 			QString text=xmlReader.readElementText();
23537 			if(text=="true" || text=="1" || text=="yes"){
23538 				xmlReadingLog+="    Read allow empty mornings=true\n";
23539 				cn->allowEmptyMornings=true;
23540 			}
23541 			else{
23542 				if(!(text=="no" || text=="false" || text=="0")){
23543 					RulesReconcilableMessage::warning(parent, tr("FET warning"),
23544 						tr("Found constraint students min hours per morning with tag allow empty mornings"
23545 						" which is not 'true', 'false', 'yes', 'no', '1' or '0'."
23546 						" The tag will be considered false",
23547 						"Instructions for translators: please leave the 'true', 'false', 'yes' and 'no' fields untranslated, as they are in English"));
23548 				}
23549 				//assert(text=="false" || text=="0" || text=="no");
23550 				xmlReadingLog+="    Read allow empty mornings=false\n";
23551 				cn->allowEmptyMornings=false;
23552 			}
23553 		}
23554 		else{
23555 			unrecognizedXmlTags.append(xmlReader.name().toString());
23556 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
23557 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
23558 
23559 			xmlReader.skipCurrentElement();
23560 			xmlReaderNumberOfUnrecognizedFields++;
23561 		}
23562 	}
23563 	if(cn->minHoursPerMorning<0){
23564 		xmlReader.raiseError(tr("%1 not found").arg("Minimum_Hours_Per_Morning"));
23565 		delete cn;
23566 		cn=nullptr;
23567 		return nullptr;
23568 	}
23569 	assert(cn->minHoursPerMorning>=0);
23570 	return cn;
23571 }
23572 
readStudentsSetMinHoursPerMorning(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)23573 TimeConstraint* Rules::readStudentsSetMinHoursPerMorning(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
23574 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMinHoursPerMorning"));
23575 	ConstraintStudentsSetMinHoursPerMorning* cn=new ConstraintStudentsSetMinHoursPerMorning();
23576 	cn->minHoursPerMorning=-1;
23577 	cn->allowEmptyMornings=true;
23578 	while(xmlReader.readNextStartElement()){
23579 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
23580 		if(xmlReader.name()==QString("Weight")){
23581 			//cn->weight=customFETStrToDouble(text);
23582 			xmlReader.skipCurrentElement();
23583 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
23584 			cn->weightPercentage=100;
23585 		}
23586 		else if(xmlReader.name()==QString("Weight_Percentage")){
23587 			QString text=xmlReader.readElementText();
23588 			cn->weightPercentage=customFETStrToDouble(text);
23589 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
23590 		}
23591 		else if(xmlReader.name()==QString("Active")){
23592 			QString text=xmlReader.readElementText();
23593 			if(text=="false"){
23594 				cn->active=false;
23595 			}
23596 		}
23597 		else if(xmlReader.name()==QString("Comments")){
23598 			QString text=xmlReader.readElementText();
23599 			cn->comments=text;
23600 		}
23601 		else if(xmlReader.name()==QString("Compulsory")){
23602 			QString text=xmlReader.readElementText();
23603 			if(text=="yes"){
23604 				//cn->compulsory=true;
23605 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
23606 				cn->weightPercentage=100;
23607 			}
23608 			else{
23609 				//cn->compulsory=false;
23610 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
23611 				cn->weightPercentage=0;
23612 			}
23613 		}
23614 		else if(xmlReader.name()==QString("Minimum_Hours_Per_Morning")){
23615 			QString text=xmlReader.readElementText();
23616 			cn->minHoursPerMorning=text.toInt();
23617 			if(cn->minHoursPerMorning<0){
23618 				xmlReader.raiseError(tr("%1 is incorrect").arg("Minimum_Hours_Per_Morning"));
23619 				delete cn;
23620 				cn=nullptr;
23621 				return nullptr;
23622 			}
23623 			xmlReadingLog+="    Read minHoursPerMorning="+CustomFETString::number(cn->minHoursPerMorning)+"\n";
23624 		}
23625 		else if(xmlReader.name()==QString("Students")){
23626 			QString text=xmlReader.readElementText();
23627 			cn->students=text;
23628 			xmlReadingLog+="    Read students name="+cn->students+"\n";
23629 		}
23630 		else if(xmlReader.name()==QString("Allow_Empty_Mornings")){
23631 			QString text=xmlReader.readElementText();
23632 			if(text=="true" || text=="1" || text=="yes"){
23633 				xmlReadingLog+="    Read allow empty mornings=true\n";
23634 				cn->allowEmptyMornings=true;
23635 			}
23636 			else{
23637 				if(!(text=="no" || text=="false" || text=="0")){
23638 					RulesReconcilableMessage::warning(parent, tr("FET warning"),
23639 						tr("Found constraint students set min hours per morning with tag allow empty mornings"
23640 						" which is not 'true', 'false', 'yes', 'no', '1' or '0'."
23641 						" The tag will be considered false",
23642 						"Instructions for translators: please leave the 'true', 'false', 'yes' and 'no' fields untranslated, as they are in English"));
23643 				}
23644 				//assert(text=="false" || text=="0" || text=="no");
23645 				xmlReadingLog+="    Read allow empty mornings=false\n";
23646 				cn->allowEmptyMornings=false;
23647 			}
23648 		}
23649 		else{
23650 			unrecognizedXmlTags.append(xmlReader.name().toString());
23651 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
23652 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
23653 
23654 			xmlReader.skipCurrentElement();
23655 			xmlReaderNumberOfUnrecognizedFields++;
23656 		}
23657 	}
23658 	if(cn->minHoursPerMorning<0){
23659 		xmlReader.raiseError(tr("%1 not found").arg("Minimum_Hours_Per_Morning"));
23660 		delete cn;
23661 		cn=nullptr;
23662 		return nullptr;
23663 	}
23664 	assert(cn->minHoursPerMorning>=0);
23665 	return cn;
23666 }
23667 
readTeachersMaxGapsPerRealDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)23668 TimeConstraint* Rules::readTeachersMaxGapsPerRealDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
23669 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxGapsPerRealDay"));
23670 	ConstraintTeachersMaxGapsPerRealDay* cn=new ConstraintTeachersMaxGapsPerRealDay();
23671 	cn->allowOneDayExceptionPlusOne=false;
23672 	while(xmlReader.readNextStartElement()){
23673 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
23674 		if(xmlReader.name()==QString("Weight")){
23675 			//cn->weight=customFETStrToDouble(text);
23676 			xmlReader.skipCurrentElement();
23677 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
23678 			cn->weightPercentage=100;
23679 		}
23680 		else if(xmlReader.name()==QString("Weight_Percentage")){
23681 			QString text=xmlReader.readElementText();
23682 			cn->weightPercentage=customFETStrToDouble(text);
23683 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
23684 		}
23685 		else if(xmlReader.name()==QString("Active")){
23686 			QString text=xmlReader.readElementText();
23687 			if(text=="false"){
23688 				cn->active=false;
23689 			}
23690 		}
23691 		else if(xmlReader.name()==QString("Comments")){
23692 			QString text=xmlReader.readElementText();
23693 			cn->comments=text;
23694 		}
23695 		else if(xmlReader.name()==QString("Max_Gaps")){
23696 			QString text=xmlReader.readElementText();
23697 			cn->maxGaps=text.toInt();
23698 			xmlReadingLog+="    Adding max gaps="+CustomFETString::number(cn->maxGaps)+"\n";
23699 		}
23700 		else if(xmlReader.name()==QString("Allow_One_Day_Exception_of_Plus_One")){
23701 			QString text=xmlReader.readElementText();
23702 			if(text=="true"){
23703 				cn->allowOneDayExceptionPlusOne=true;
23704 			}
23705 		}
23706 		else if(xmlReader.name()==QString("Compulsory")){
23707 			QString text=xmlReader.readElementText();
23708 			if(text=="yes"){
23709 				//cn->compulsory=true;
23710 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
23711 				cn->weightPercentage=100;
23712 			}
23713 			else{
23714 				//cn->compulsory=false;
23715 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
23716 				cn->weightPercentage=0;
23717 			}
23718 		}
23719 		else{
23720 			unrecognizedXmlTags.append(xmlReader.name().toString());
23721 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
23722 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
23723 
23724 			xmlReader.skipCurrentElement();
23725 			xmlReaderNumberOfUnrecognizedFields++;
23726 		}
23727 	}
23728 	return cn;
23729 }
23730 
readTeacherMaxGapsPerRealDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)23731 TimeConstraint* Rules::readTeacherMaxGapsPerRealDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
23732 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxGapsPerRealDay"));
23733 	ConstraintTeacherMaxGapsPerRealDay* cn=new ConstraintTeacherMaxGapsPerRealDay();
23734 	cn->allowOneDayExceptionPlusOne=false;
23735 	while(xmlReader.readNextStartElement()){
23736 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
23737 		if(xmlReader.name()==QString("Weight")){
23738 			//cn->weight=customFETStrToDouble(text);
23739 			xmlReader.skipCurrentElement();
23740 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
23741 			cn->weightPercentage=100;
23742 		}
23743 		else if(xmlReader.name()==QString("Teacher_Name")){
23744 			QString text=xmlReader.readElementText();
23745 			cn->teacherName=text;
23746 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
23747 		}
23748 		else if(xmlReader.name()==QString("Weight_Percentage")){
23749 			QString text=xmlReader.readElementText();
23750 			cn->weightPercentage=customFETStrToDouble(text);
23751 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
23752 		}
23753 		else if(xmlReader.name()==QString("Active")){
23754 			QString text=xmlReader.readElementText();
23755 			if(text=="false"){
23756 				cn->active=false;
23757 			}
23758 		}
23759 		else if(xmlReader.name()==QString("Comments")){
23760 			QString text=xmlReader.readElementText();
23761 			cn->comments=text;
23762 		}
23763 		else if(xmlReader.name()==QString("Max_Gaps")){
23764 			QString text=xmlReader.readElementText();
23765 			cn->maxGaps=text.toInt();
23766 			xmlReadingLog+="    Adding max gaps="+CustomFETString::number(cn->maxGaps)+"\n";
23767 		}
23768 		else if(xmlReader.name()==QString("Allow_One_Day_Exception_of_Plus_One")){
23769 			QString text=xmlReader.readElementText();
23770 			if(text=="true"){
23771 				cn->allowOneDayExceptionPlusOne=true;
23772 			}
23773 		}
23774 		else if(xmlReader.name()==QString("Compulsory")){
23775 			QString text=xmlReader.readElementText();
23776 			if(text=="yes"){
23777 				//cn->compulsory=true;
23778 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
23779 				cn->weightPercentage=100;
23780 			}
23781 			else{
23782 				//cn->compulsory=false;
23783 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
23784 				cn->weightPercentage=0;
23785 			}
23786 		}
23787 		else{
23788 			unrecognizedXmlTags.append(xmlReader.name().toString());
23789 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
23790 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
23791 
23792 			xmlReader.skipCurrentElement();
23793 			xmlReaderNumberOfUnrecognizedFields++;
23794 		}
23795 	}
23796 	return cn;
23797 }
23798 
readTeacherMaxZeroGapsPerAfternoon(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)23799 TimeConstraint* Rules::readTeacherMaxZeroGapsPerAfternoon(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
23800 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxZeroGapsPerAfternoon"));
23801 	ConstraintTeacherMaxZeroGapsPerAfternoon* cn=new ConstraintTeacherMaxZeroGapsPerAfternoon();
23802 	while(xmlReader.readNextStartElement()){
23803 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
23804 		if(xmlReader.name()==QString("Weight")){
23805 			//cn->weight=customFETStrToDouble(text);
23806 			xmlReader.skipCurrentElement();
23807 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
23808 			cn->weightPercentage=100;
23809 		}
23810 		else if(xmlReader.name()==QString("Teacher_Name")){
23811 			QString text=xmlReader.readElementText();
23812 			cn->teacherName=text;
23813 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
23814 		}
23815 		else if(xmlReader.name()==QString("Weight_Percentage")){
23816 			QString text=xmlReader.readElementText();
23817 			cn->weightPercentage=customFETStrToDouble(text);
23818 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
23819 		}
23820 		else if(xmlReader.name()==QString("Active")){
23821 			QString text=xmlReader.readElementText();
23822 			if(text=="false"){
23823 				cn->active=false;
23824 			}
23825 		}
23826 		else if(xmlReader.name()==QString("Comments")){
23827 			QString text=xmlReader.readElementText();
23828 			cn->comments=text;
23829 		}
23830 		else if(xmlReader.name()==QString("Compulsory")){
23831 			QString text=xmlReader.readElementText();
23832 			if(text=="yes"){
23833 				//cn->compulsory=true;
23834 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
23835 				cn->weightPercentage=100;
23836 			}
23837 			else{
23838 				//cn->compulsory=false;
23839 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
23840 				cn->weightPercentage=0;
23841 			}
23842 		}
23843 		else{
23844 			unrecognizedXmlTags.append(xmlReader.name().toString());
23845 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
23846 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
23847 
23848 			xmlReader.skipCurrentElement();
23849 			xmlReaderNumberOfUnrecognizedFields++;
23850 		}
23851 	}
23852 	return cn;
23853 }
23854 
readTeachersMaxZeroGapsPerAfternoon(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)23855 TimeConstraint* Rules::readTeachersMaxZeroGapsPerAfternoon(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
23856 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxZeroGapsPerAfternoon"));
23857 	ConstraintTeachersMaxZeroGapsPerAfternoon* cn=new ConstraintTeachersMaxZeroGapsPerAfternoon();
23858 	while(xmlReader.readNextStartElement()){
23859 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
23860 		if(xmlReader.name()==QString("Weight")){
23861 			//cn->weight=customFETStrToDouble(text);
23862 			xmlReader.skipCurrentElement();
23863 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
23864 			cn->weightPercentage=100;
23865 		}
23866 		else if(xmlReader.name()==QString("Weight_Percentage")){
23867 			QString text=xmlReader.readElementText();
23868 			cn->weightPercentage=customFETStrToDouble(text);
23869 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
23870 		}
23871 		else if(xmlReader.name()==QString("Active")){
23872 			QString text=xmlReader.readElementText();
23873 			if(text=="false"){
23874 				cn->active=false;
23875 			}
23876 		}
23877 		else if(xmlReader.name()==QString("Comments")){
23878 			QString text=xmlReader.readElementText();
23879 			cn->comments=text;
23880 		}
23881 		else if(xmlReader.name()==QString("Compulsory")){
23882 			QString text=xmlReader.readElementText();
23883 			if(text=="yes"){
23884 				//cn->compulsory=true;
23885 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
23886 				cn->weightPercentage=100;
23887 			}
23888 			else{
23889 				//cn->compulsory=false;
23890 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
23891 				cn->weightPercentage=0;
23892 			}
23893 		}
23894 		else{
23895 			unrecognizedXmlTags.append(xmlReader.name().toString());
23896 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
23897 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
23898 
23899 			xmlReader.skipCurrentElement();
23900 			xmlReaderNumberOfUnrecognizedFields++;
23901 		}
23902 	}
23903 	return cn;
23904 }
23905 
readStudentsMaxGapsPerRealDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)23906 TimeConstraint* Rules::readStudentsMaxGapsPerRealDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
23907 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMaxGapsPerRealDay"));
23908 	ConstraintStudentsMaxGapsPerRealDay* cn=new ConstraintStudentsMaxGapsPerRealDay();
23909 
23910 	//bool compulsory_read=false;
23911 	while(xmlReader.readNextStartElement()){
23912 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
23913 		if(xmlReader.name()==QString("Weight")){
23914 			//cn->weight=customFETStrToDouble(text);
23915 			xmlReader.skipCurrentElement();
23916 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
23917 			cn->weightPercentage=100;
23918 		}
23919 		else if(xmlReader.name()==QString("Weight_Percentage")){
23920 			QString text=xmlReader.readElementText();
23921 			cn->weightPercentage=customFETStrToDouble(text);
23922 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
23923 		}
23924 		else if(xmlReader.name()==QString("Active")){
23925 			QString text=xmlReader.readElementText();
23926 			if(text=="false"){
23927 				cn->active=false;
23928 			}
23929 		}
23930 		else if(xmlReader.name()==QString("Comments")){
23931 			QString text=xmlReader.readElementText();
23932 			cn->comments=text;
23933 		}
23934 		else if(xmlReader.name()==QString("Max_Gaps")){
23935 			QString text=xmlReader.readElementText();
23936 			cn->maxGaps=text.toInt();
23937 			xmlReadingLog+="    Adding max gaps="+CustomFETString::number(cn->maxGaps)+"\n";
23938 		}
23939 		else if(xmlReader.name()==QString("Compulsory")){
23940 			QString text=xmlReader.readElementText();
23941 			if(text=="yes"){
23942 				//cn->compulsory=true;
23943 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
23944 				cn->weightPercentage=100;
23945 			}
23946 			else{
23947 				//cn->compulsory=false;
23948 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
23949 				cn->weightPercentage=0;
23950 			}
23951 			//compulsory_read=true;
23952 		}
23953 		else{
23954 			unrecognizedXmlTags.append(xmlReader.name().toString());
23955 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
23956 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
23957 
23958 			xmlReader.skipCurrentElement();
23959 			xmlReaderNumberOfUnrecognizedFields++;
23960 		}
23961 	}
23962 	return cn;
23963 }
23964 
readStudentsSetMaxGapsPerRealDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)23965 TimeConstraint* Rules::readStudentsSetMaxGapsPerRealDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
23966 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMaxGapsPerRealDay"));
23967 	ConstraintStudentsSetMaxGapsPerRealDay* cn=new ConstraintStudentsSetMaxGapsPerRealDay();
23968 
23969 	//bool compulsory_read=false;
23970 	while(xmlReader.readNextStartElement()){
23971 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
23972 		if(xmlReader.name()==QString("Weight")){
23973 			//cn->weight=customFETStrToDouble(text);
23974 			xmlReader.skipCurrentElement();
23975 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
23976 			cn->weightPercentage=100;
23977 		}
23978 		else if(xmlReader.name()==QString("Weight_Percentage")){
23979 			QString text=xmlReader.readElementText();
23980 			cn->weightPercentage=customFETStrToDouble(text);
23981 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
23982 		}
23983 		else if(xmlReader.name()==QString("Active")){
23984 			QString text=xmlReader.readElementText();
23985 			if(text=="false"){
23986 				cn->active=false;
23987 			}
23988 		}
23989 		else if(xmlReader.name()==QString("Comments")){
23990 			QString text=xmlReader.readElementText();
23991 			cn->comments=text;
23992 		}
23993 		else if(xmlReader.name()==QString("Max_Gaps")){
23994 			QString text=xmlReader.readElementText();
23995 			cn->maxGaps=text.toInt();
23996 			xmlReadingLog+="    Adding max gaps="+CustomFETString::number(cn->maxGaps)+"\n";
23997 		}
23998 		else if(xmlReader.name()==QString("Compulsory")){
23999 			QString text=xmlReader.readElementText();
24000 			if(text=="yes"){
24001 				//cn->compulsory=true;
24002 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
24003 				cn->weightPercentage=100;
24004 			}
24005 			else{
24006 				//cn->compulsory=false;
24007 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
24008 				cn->weightPercentage=0;
24009 			}
24010 			//compulsory_read=true;
24011 		}
24012 		else if(xmlReader.name()==QString("Students")){
24013 			QString text=xmlReader.readElementText();
24014 			cn->students=text;
24015 			xmlReadingLog+="    Read students name="+cn->students+"\n";
24016 		}
24017 		else{
24018 			unrecognizedXmlTags.append(xmlReader.name().toString());
24019 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
24020 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
24021 
24022 			xmlReader.skipCurrentElement();
24023 			xmlReaderNumberOfUnrecognizedFields++;
24024 		}
24025 	}
24026 	return cn;
24027 }
24028 
24029 //2020-07-24
readStudentsAfternoonsEarlyMaxBeginningsAtSecondHour(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)24030 TimeConstraint* Rules::readStudentsAfternoonsEarlyMaxBeginningsAtSecondHour(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
24031 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsAfternoonsEarlyMaxBeginningsAtSecondHour"));
24032 	ConstraintStudentsAfternoonsEarlyMaxBeginningsAtSecondHour* cn=new ConstraintStudentsAfternoonsEarlyMaxBeginningsAtSecondHour();
24033 	cn->maxBeginningsAtSecondHour=-1;
24034 	while(xmlReader.readNextStartElement()){
24035 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
24036 		if(xmlReader.name()==QString("Weight")){
24037 			//cn->weight=customFETStrToDouble(text);
24038 			xmlReader.skipCurrentElement();
24039 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
24040 			cn->weightPercentage=100;
24041 		}
24042 		else if(xmlReader.name()==QString("Weight_Percentage")){
24043 			QString text=xmlReader.readElementText();
24044 			cn->weightPercentage=customFETStrToDouble(text);
24045 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
24046 		}
24047 		else if(xmlReader.name()==QString("Active")){
24048 			QString text=xmlReader.readElementText();
24049 			if(text=="false"){
24050 				cn->active=false;
24051 			}
24052 		}
24053 		else if(xmlReader.name()==QString("Comments")){
24054 			QString text=xmlReader.readElementText();
24055 			cn->comments=text;
24056 		}
24057 		else if(xmlReader.name()==QString("Max_Beginnings_At_Second_Hour")){
24058 			QString text=xmlReader.readElementText();
24059 			cn->maxBeginningsAtSecondHour=text.toInt();
24060 			if(!(cn->maxBeginningsAtSecondHour>=0)){
24061 				xmlReader.raiseError(tr("%1 is incorrect").arg("Max_Beginnings_At_Second_Hour"));
24062 				delete cn;
24063 				cn=nullptr;
24064 				return nullptr;
24065 			}
24066 			xmlReadingLog+="    Adding max beginnings at second hour="+CustomFETString::number(cn->maxBeginningsAtSecondHour)+"\n";
24067 		}
24068 		else if(xmlReader.name()==QString("Compulsory")){
24069 			QString text=xmlReader.readElementText();
24070 			if(text=="yes"){
24071 				//cn->compulsory=true;
24072 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
24073 				cn->weightPercentage=100;
24074 			}
24075 			else{
24076 				//cn->compulsory=false;
24077 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
24078 				cn->weightPercentage=0;
24079 			}
24080 		}
24081 		else{
24082 			unrecognizedXmlTags.append(xmlReader.name().toString());
24083 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
24084 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
24085 
24086 			xmlReader.skipCurrentElement();
24087 			xmlReaderNumberOfUnrecognizedFields++;
24088 		}
24089 	}
24090 	if(!(cn->maxBeginningsAtSecondHour>=0)){
24091 		xmlReader.raiseError(tr("%1 not found").arg("Max_Beginnings_At_Second_Hour"));
24092 		delete cn;
24093 		cn=nullptr;
24094 		return nullptr;
24095 	}
24096 	assert(cn->maxBeginningsAtSecondHour>=0);
24097 	return cn;
24098 }
24099 
readStudentsSetAfternoonsEarlyMaxBeginningsAtSecondHour(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)24100 TimeConstraint* Rules::readStudentsSetAfternoonsEarlyMaxBeginningsAtSecondHour(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
24101 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetAfternoonsEarlyMaxBeginningsAtSecondHour"));
24102 	ConstraintStudentsSetAfternoonsEarlyMaxBeginningsAtSecondHour* cn=new ConstraintStudentsSetAfternoonsEarlyMaxBeginningsAtSecondHour();
24103 	cn->maxBeginningsAtSecondHour=-1;
24104 	while(xmlReader.readNextStartElement()){
24105 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
24106 		if(xmlReader.name()==QString("Weight")){
24107 			//cn->weight=customFETStrToDouble(text);
24108 			xmlReader.skipCurrentElement();
24109 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
24110 			cn->weightPercentage=100;
24111 		}
24112 		else if(xmlReader.name()==QString("Weight_Percentage")){
24113 			QString text=xmlReader.readElementText();
24114 			cn->weightPercentage=customFETStrToDouble(text);
24115 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
24116 		}
24117 		else if(xmlReader.name()==QString("Active")){
24118 			QString text=xmlReader.readElementText();
24119 			if(text=="false"){
24120 				cn->active=false;
24121 			}
24122 		}
24123 		else if(xmlReader.name()==QString("Comments")){
24124 			QString text=xmlReader.readElementText();
24125 			cn->comments=text;
24126 		}
24127 		else if(xmlReader.name()==QString("Max_Beginnings_At_Second_Hour")){
24128 			QString text=xmlReader.readElementText();
24129 			cn->maxBeginningsAtSecondHour=text.toInt();
24130 			if(!(cn->maxBeginningsAtSecondHour>=0)){
24131 				xmlReader.raiseError(tr("%1 is incorrect").arg("Max_Beginnings_At_Second_Hour"));
24132 				delete cn;
24133 				cn=nullptr;
24134 				return nullptr;
24135 			}
24136 			xmlReadingLog+="    Adding max beginnings at second hour="+CustomFETString::number(cn->maxBeginningsAtSecondHour)+"\n";
24137 		}
24138 		else if(xmlReader.name()==QString("Compulsory")){
24139 			QString text=xmlReader.readElementText();
24140 			if(text=="yes"){
24141 				//cn->compulsory=true;
24142 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
24143 				cn->weightPercentage=100;
24144 			}
24145 			else{
24146 				//cn->compulsory=false;
24147 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
24148 				cn->weightPercentage=0;
24149 			}
24150 		}
24151 		else if(xmlReader.name()==QString("Students")){
24152 			QString text=xmlReader.readElementText();
24153 			cn->students=text;
24154 			xmlReadingLog+="    Read students name="+cn->students+"\n";
24155 		}
24156 		else{
24157 			unrecognizedXmlTags.append(xmlReader.name().toString());
24158 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
24159 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
24160 
24161 			xmlReader.skipCurrentElement();
24162 			xmlReaderNumberOfUnrecognizedFields++;
24163 		}
24164 	}
24165 	if(!(cn->maxBeginningsAtSecondHour>=0)){
24166 		xmlReader.raiseError(tr("%1 not found").arg("Max_Beginnings_At_Second_Hour"));
24167 		delete cn;
24168 		cn=nullptr;
24169 		return nullptr;
24170 	}
24171 	assert(cn->maxBeginningsAtSecondHour>=0);
24172 	return cn;
24173 }
24174 /////////////
24175 
readTeachersAfternoonsEarlyMaxBeginningsAtSecondHour(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)24176 TimeConstraint* Rules::readTeachersAfternoonsEarlyMaxBeginningsAtSecondHour(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
24177 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersAfternoonsEarlyMaxBeginningsAtSecondHour"));
24178 	ConstraintTeachersAfternoonsEarlyMaxBeginningsAtSecondHour* cn=new ConstraintTeachersAfternoonsEarlyMaxBeginningsAtSecondHour();
24179 	cn->maxBeginningsAtSecondHour=-1;
24180 	while(xmlReader.readNextStartElement()){
24181 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
24182 		if(xmlReader.name()==QString("Weight")){
24183 			//cn->weight=customFETStrToDouble(text);
24184 			xmlReader.skipCurrentElement();
24185 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
24186 			cn->weightPercentage=100;
24187 		}
24188 		else if(xmlReader.name()==QString("Weight_Percentage")){
24189 			QString text=xmlReader.readElementText();
24190 			cn->weightPercentage=customFETStrToDouble(text);
24191 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
24192 		}
24193 		else if(xmlReader.name()==QString("Active")){
24194 			QString text=xmlReader.readElementText();
24195 			if(text=="false"){
24196 				cn->active=false;
24197 			}
24198 		}
24199 		else if(xmlReader.name()==QString("Comments")){
24200 			QString text=xmlReader.readElementText();
24201 			cn->comments=text;
24202 		}
24203 		else if(xmlReader.name()==QString("Max_Beginnings_At_Second_Hour")){
24204 			QString text=xmlReader.readElementText();
24205 			cn->maxBeginningsAtSecondHour=text.toInt();
24206 			if(!(cn->maxBeginningsAtSecondHour>=0)){
24207 				xmlReader.raiseError(tr("%1 is incorrect").arg("Max_Beginnings_At_Second_Hour"));
24208 				delete cn;
24209 				cn=nullptr;
24210 				return nullptr;
24211 			}
24212 			xmlReadingLog+="    Adding max beginnings at second hour="+CustomFETString::number(cn->maxBeginningsAtSecondHour)+"\n";
24213 		}
24214 		else if(xmlReader.name()==QString("Compulsory")){
24215 			QString text=xmlReader.readElementText();
24216 			if(text=="yes"){
24217 				//cn->compulsory=true;
24218 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
24219 				cn->weightPercentage=100;
24220 			}
24221 			else{
24222 				//cn->compulsory=false;
24223 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
24224 				cn->weightPercentage=0;
24225 			}
24226 		}
24227 		else{
24228 			unrecognizedXmlTags.append(xmlReader.name().toString());
24229 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
24230 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
24231 
24232 			xmlReader.skipCurrentElement();
24233 			xmlReaderNumberOfUnrecognizedFields++;
24234 		}
24235 	}
24236 	if(!(cn->maxBeginningsAtSecondHour>=0)){
24237 		xmlReader.raiseError(tr("%1 not found").arg("Max_Beginnings_At_Second_Hour"));
24238 		delete cn;
24239 		cn=nullptr;
24240 		return nullptr;
24241 	}
24242 	assert(cn->maxBeginningsAtSecondHour>=0);
24243 	return cn;
24244 }
24245 
readTeacherAfternoonsEarlyMaxBeginningsAtSecondHour(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)24246 TimeConstraint* Rules::readTeacherAfternoonsEarlyMaxBeginningsAtSecondHour(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
24247 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherAfternoonsEarlyMaxBeginningsAtSecondHour"));
24248 	ConstraintTeacherAfternoonsEarlyMaxBeginningsAtSecondHour* cn=new ConstraintTeacherAfternoonsEarlyMaxBeginningsAtSecondHour();
24249 	cn->maxBeginningsAtSecondHour=-1;
24250 	while(xmlReader.readNextStartElement()){
24251 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
24252 		if(xmlReader.name()==QString("Weight")){
24253 			//cn->weight=customFETStrToDouble(text);
24254 			xmlReader.skipCurrentElement();
24255 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
24256 			cn->weightPercentage=100;
24257 		}
24258 		else if(xmlReader.name()==QString("Weight_Percentage")){
24259 			QString text=xmlReader.readElementText();
24260 			cn->weightPercentage=customFETStrToDouble(text);
24261 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
24262 		}
24263 		else if(xmlReader.name()==QString("Active")){
24264 			QString text=xmlReader.readElementText();
24265 			if(text=="false"){
24266 				cn->active=false;
24267 			}
24268 		}
24269 		else if(xmlReader.name()==QString("Comments")){
24270 			QString text=xmlReader.readElementText();
24271 			cn->comments=text;
24272 		}
24273 		else if(xmlReader.name()==QString("Max_Beginnings_At_Second_Hour")){
24274 			QString text=xmlReader.readElementText();
24275 			cn->maxBeginningsAtSecondHour=text.toInt();
24276 			if(!(cn->maxBeginningsAtSecondHour>=0)){
24277 				xmlReader.raiseError(tr("%1 is incorrect").arg("Max_Beginnings_At_Second_Hour"));
24278 				delete cn;
24279 				cn=nullptr;
24280 				return nullptr;
24281 			}
24282 			xmlReadingLog+="    Adding max beginnings at second hour="+CustomFETString::number(cn->maxBeginningsAtSecondHour)+"\n";
24283 		}
24284 		else if(xmlReader.name()==QString("Compulsory")){
24285 			QString text=xmlReader.readElementText();
24286 			if(text=="yes"){
24287 				//cn->compulsory=true;
24288 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
24289 				cn->weightPercentage=100;
24290 			}
24291 			else{
24292 				//cn->compulsory=false;
24293 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
24294 				cn->weightPercentage=0;
24295 			}
24296 		}
24297 		else if(xmlReader.name()==QString("Teacher")){
24298 			QString text=xmlReader.readElementText();
24299 			cn->teacherName=text;
24300 			xmlReadingLog+="    Read students name="+cn->teacherName+"\n";
24301 		}
24302 		else{
24303 			unrecognizedXmlTags.append(xmlReader.name().toString());
24304 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
24305 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
24306 
24307 			xmlReader.skipCurrentElement();
24308 			xmlReaderNumberOfUnrecognizedFields++;
24309 		}
24310 	}
24311 	if(!(cn->maxBeginningsAtSecondHour>=0)){
24312 		xmlReader.raiseError(tr("%1 not found").arg("Max_Beginnings_At_Second_Hour"));
24313 		delete cn;
24314 		cn=nullptr;
24315 		return nullptr;
24316 	}
24317 	assert(cn->maxBeginningsAtSecondHour>=0);
24318 	return cn;
24319 }
24320 
24321 //2021-08-12
readStudentsMorningsEarlyMaxBeginningsAtSecondHour(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)24322 TimeConstraint* Rules::readStudentsMorningsEarlyMaxBeginningsAtSecondHour(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
24323 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMorningsEarlyMaxBeginningsAtSecondHour"));
24324 	ConstraintStudentsMorningsEarlyMaxBeginningsAtSecondHour* cn=new ConstraintStudentsMorningsEarlyMaxBeginningsAtSecondHour();
24325 	cn->maxBeginningsAtSecondHour=-1;
24326 	while(xmlReader.readNextStartElement()){
24327 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
24328 		if(xmlReader.name()==QString("Weight")){
24329 			//cn->weight=customFETStrToDouble(text);
24330 			xmlReader.skipCurrentElement();
24331 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
24332 			cn->weightPercentage=100;
24333 		}
24334 		else if(xmlReader.name()==QString("Weight_Percentage")){
24335 			QString text=xmlReader.readElementText();
24336 			cn->weightPercentage=customFETStrToDouble(text);
24337 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
24338 		}
24339 		else if(xmlReader.name()==QString("Active")){
24340 			QString text=xmlReader.readElementText();
24341 			if(text=="false"){
24342 				cn->active=false;
24343 			}
24344 		}
24345 		else if(xmlReader.name()==QString("Comments")){
24346 			QString text=xmlReader.readElementText();
24347 			cn->comments=text;
24348 		}
24349 		else if(xmlReader.name()==QString("Max_Beginnings_At_Second_Hour")){
24350 			QString text=xmlReader.readElementText();
24351 			cn->maxBeginningsAtSecondHour=text.toInt();
24352 			if(!(cn->maxBeginningsAtSecondHour>=0)){
24353 				xmlReader.raiseError(tr("%1 is incorrect").arg("Max_Beginnings_At_Second_Hour"));
24354 				delete cn;
24355 				cn=nullptr;
24356 				return nullptr;
24357 			}
24358 			xmlReadingLog+="    Adding max beginnings at second hour="+CustomFETString::number(cn->maxBeginningsAtSecondHour)+"\n";
24359 		}
24360 		else if(xmlReader.name()==QString("Compulsory")){
24361 			QString text=xmlReader.readElementText();
24362 			if(text=="yes"){
24363 				//cn->compulsory=true;
24364 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
24365 				cn->weightPercentage=100;
24366 			}
24367 			else{
24368 				//cn->compulsory=false;
24369 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
24370 				cn->weightPercentage=0;
24371 			}
24372 		}
24373 		else{
24374 			unrecognizedXmlTags.append(xmlReader.name().toString());
24375 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
24376 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
24377 
24378 			xmlReader.skipCurrentElement();
24379 			xmlReaderNumberOfUnrecognizedFields++;
24380 		}
24381 	}
24382 	if(!(cn->maxBeginningsAtSecondHour>=0)){
24383 		xmlReader.raiseError(tr("%1 not found").arg("Max_Beginnings_At_Second_Hour"));
24384 		delete cn;
24385 		cn=nullptr;
24386 		return nullptr;
24387 	}
24388 	assert(cn->maxBeginningsAtSecondHour>=0);
24389 	return cn;
24390 }
24391 
readStudentsSetMorningsEarlyMaxBeginningsAtSecondHour(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)24392 TimeConstraint* Rules::readStudentsSetMorningsEarlyMaxBeginningsAtSecondHour(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
24393 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMorningsEarlyMaxBeginningsAtSecondHour"));
24394 	ConstraintStudentsSetMorningsEarlyMaxBeginningsAtSecondHour* cn=new ConstraintStudentsSetMorningsEarlyMaxBeginningsAtSecondHour();
24395 	cn->maxBeginningsAtSecondHour=-1;
24396 	while(xmlReader.readNextStartElement()){
24397 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
24398 		if(xmlReader.name()==QString("Weight")){
24399 			//cn->weight=customFETStrToDouble(text);
24400 			xmlReader.skipCurrentElement();
24401 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
24402 			cn->weightPercentage=100;
24403 		}
24404 		else if(xmlReader.name()==QString("Weight_Percentage")){
24405 			QString text=xmlReader.readElementText();
24406 			cn->weightPercentage=customFETStrToDouble(text);
24407 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
24408 		}
24409 		else if(xmlReader.name()==QString("Active")){
24410 			QString text=xmlReader.readElementText();
24411 			if(text=="false"){
24412 				cn->active=false;
24413 			}
24414 		}
24415 		else if(xmlReader.name()==QString("Comments")){
24416 			QString text=xmlReader.readElementText();
24417 			cn->comments=text;
24418 		}
24419 		else if(xmlReader.name()==QString("Max_Beginnings_At_Second_Hour")){
24420 			QString text=xmlReader.readElementText();
24421 			cn->maxBeginningsAtSecondHour=text.toInt();
24422 			if(!(cn->maxBeginningsAtSecondHour>=0)){
24423 				xmlReader.raiseError(tr("%1 is incorrect").arg("Max_Beginnings_At_Second_Hour"));
24424 				delete cn;
24425 				cn=nullptr;
24426 				return nullptr;
24427 			}
24428 			xmlReadingLog+="    Adding max beginnings at second hour="+CustomFETString::number(cn->maxBeginningsAtSecondHour)+"\n";
24429 		}
24430 		else if(xmlReader.name()==QString("Compulsory")){
24431 			QString text=xmlReader.readElementText();
24432 			if(text=="yes"){
24433 				//cn->compulsory=true;
24434 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
24435 				cn->weightPercentage=100;
24436 			}
24437 			else{
24438 				//cn->compulsory=false;
24439 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
24440 				cn->weightPercentage=0;
24441 			}
24442 		}
24443 		else if(xmlReader.name()==QString("Students")){
24444 			QString text=xmlReader.readElementText();
24445 			cn->students=text;
24446 			xmlReadingLog+="    Read students name="+cn->students+"\n";
24447 		}
24448 		else{
24449 			unrecognizedXmlTags.append(xmlReader.name().toString());
24450 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
24451 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
24452 
24453 			xmlReader.skipCurrentElement();
24454 			xmlReaderNumberOfUnrecognizedFields++;
24455 		}
24456 	}
24457 	if(!(cn->maxBeginningsAtSecondHour>=0)){
24458 		xmlReader.raiseError(tr("%1 not found").arg("Max_Beginnings_At_Second_Hour"));
24459 		delete cn;
24460 		cn=nullptr;
24461 		return nullptr;
24462 	}
24463 	assert(cn->maxBeginningsAtSecondHour>=0);
24464 	return cn;
24465 }
24466 /////////////
24467 
readTeachersMorningsEarlyMaxBeginningsAtSecondHour(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)24468 TimeConstraint* Rules::readTeachersMorningsEarlyMaxBeginningsAtSecondHour(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
24469 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMorningsEarlyMaxBeginningsAtSecondHour"));
24470 	ConstraintTeachersMorningsEarlyMaxBeginningsAtSecondHour* cn=new ConstraintTeachersMorningsEarlyMaxBeginningsAtSecondHour();
24471 	cn->maxBeginningsAtSecondHour=-1;
24472 	while(xmlReader.readNextStartElement()){
24473 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
24474 		if(xmlReader.name()==QString("Weight")){
24475 			//cn->weight=customFETStrToDouble(text);
24476 			xmlReader.skipCurrentElement();
24477 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
24478 			cn->weightPercentage=100;
24479 		}
24480 		else if(xmlReader.name()==QString("Weight_Percentage")){
24481 			QString text=xmlReader.readElementText();
24482 			cn->weightPercentage=customFETStrToDouble(text);
24483 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
24484 		}
24485 		else if(xmlReader.name()==QString("Active")){
24486 			QString text=xmlReader.readElementText();
24487 			if(text=="false"){
24488 				cn->active=false;
24489 			}
24490 		}
24491 		else if(xmlReader.name()==QString("Comments")){
24492 			QString text=xmlReader.readElementText();
24493 			cn->comments=text;
24494 		}
24495 		else if(xmlReader.name()==QString("Max_Beginnings_At_Second_Hour")){
24496 			QString text=xmlReader.readElementText();
24497 			cn->maxBeginningsAtSecondHour=text.toInt();
24498 			if(!(cn->maxBeginningsAtSecondHour>=0)){
24499 				xmlReader.raiseError(tr("%1 is incorrect").arg("Max_Beginnings_At_Second_Hour"));
24500 				delete cn;
24501 				cn=nullptr;
24502 				return nullptr;
24503 			}
24504 			xmlReadingLog+="    Adding max beginnings at second hour="+CustomFETString::number(cn->maxBeginningsAtSecondHour)+"\n";
24505 		}
24506 		else if(xmlReader.name()==QString("Compulsory")){
24507 			QString text=xmlReader.readElementText();
24508 			if(text=="yes"){
24509 				//cn->compulsory=true;
24510 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
24511 				cn->weightPercentage=100;
24512 			}
24513 			else{
24514 				//cn->compulsory=false;
24515 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
24516 				cn->weightPercentage=0;
24517 			}
24518 		}
24519 		else{
24520 			unrecognizedXmlTags.append(xmlReader.name().toString());
24521 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
24522 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
24523 
24524 			xmlReader.skipCurrentElement();
24525 			xmlReaderNumberOfUnrecognizedFields++;
24526 		}
24527 	}
24528 	if(!(cn->maxBeginningsAtSecondHour>=0)){
24529 		xmlReader.raiseError(tr("%1 not found").arg("Max_Beginnings_At_Second_Hour"));
24530 		delete cn;
24531 		cn=nullptr;
24532 		return nullptr;
24533 	}
24534 	assert(cn->maxBeginningsAtSecondHour>=0);
24535 	return cn;
24536 }
24537 
readTeacherMorningsEarlyMaxBeginningsAtSecondHour(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)24538 TimeConstraint* Rules::readTeacherMorningsEarlyMaxBeginningsAtSecondHour(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
24539 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMorningsEarlyMaxBeginningsAtSecondHour"));
24540 	ConstraintTeacherMorningsEarlyMaxBeginningsAtSecondHour* cn=new ConstraintTeacherMorningsEarlyMaxBeginningsAtSecondHour();
24541 	cn->maxBeginningsAtSecondHour=-1;
24542 	while(xmlReader.readNextStartElement()){
24543 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
24544 		if(xmlReader.name()==QString("Weight")){
24545 			//cn->weight=customFETStrToDouble(text);
24546 			xmlReader.skipCurrentElement();
24547 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
24548 			cn->weightPercentage=100;
24549 		}
24550 		else if(xmlReader.name()==QString("Weight_Percentage")){
24551 			QString text=xmlReader.readElementText();
24552 			cn->weightPercentage=customFETStrToDouble(text);
24553 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
24554 		}
24555 		else if(xmlReader.name()==QString("Active")){
24556 			QString text=xmlReader.readElementText();
24557 			if(text=="false"){
24558 				cn->active=false;
24559 			}
24560 		}
24561 		else if(xmlReader.name()==QString("Comments")){
24562 			QString text=xmlReader.readElementText();
24563 			cn->comments=text;
24564 		}
24565 		else if(xmlReader.name()==QString("Max_Beginnings_At_Second_Hour")){
24566 			QString text=xmlReader.readElementText();
24567 			cn->maxBeginningsAtSecondHour=text.toInt();
24568 			if(!(cn->maxBeginningsAtSecondHour>=0)){
24569 				xmlReader.raiseError(tr("%1 is incorrect").arg("Max_Beginnings_At_Second_Hour"));
24570 				delete cn;
24571 				cn=nullptr;
24572 				return nullptr;
24573 			}
24574 			xmlReadingLog+="    Adding max beginnings at second hour="+CustomFETString::number(cn->maxBeginningsAtSecondHour)+"\n";
24575 		}
24576 		else if(xmlReader.name()==QString("Compulsory")){
24577 			QString text=xmlReader.readElementText();
24578 			if(text=="yes"){
24579 				//cn->compulsory=true;
24580 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
24581 				cn->weightPercentage=100;
24582 			}
24583 			else{
24584 				//cn->compulsory=false;
24585 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
24586 				cn->weightPercentage=0;
24587 			}
24588 		}
24589 		else if(xmlReader.name()==QString("Teacher")){
24590 			QString text=xmlReader.readElementText();
24591 			cn->teacherName=text;
24592 			xmlReadingLog+="    Read students name="+cn->teacherName+"\n";
24593 		}
24594 		else{
24595 			unrecognizedXmlTags.append(xmlReader.name().toString());
24596 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
24597 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
24598 
24599 			xmlReader.skipCurrentElement();
24600 			xmlReaderNumberOfUnrecognizedFields++;
24601 		}
24602 	}
24603 	if(!(cn->maxBeginningsAtSecondHour>=0)){
24604 		xmlReader.raiseError(tr("%1 not found").arg("Max_Beginnings_At_Second_Hour"));
24605 		delete cn;
24606 		cn=nullptr;
24607 		return nullptr;
24608 	}
24609 	assert(cn->maxBeginningsAtSecondHour>=0);
24610 	return cn;
24611 }
24612 
readOldMATeacherMaxSpanPerDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)24613 TimeConstraint* Rules::readOldMATeacherMaxSpanPerDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
24614 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxSpanPerDay"));
24615 	ConstraintTeacherMaxSpanPerRealDay* cn=new ConstraintTeacherMaxSpanPerRealDay();
24616 	cn->allowOneDayExceptionPlusOne=false;
24617 	while(xmlReader.readNextStartElement()){
24618 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
24619 		if(xmlReader.name()==QString("Weight_Percentage")){
24620 			QString text=xmlReader.readElementText();
24621 			cn->weightPercentage=customFETStrToDouble(text);
24622 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
24623 		}
24624 		else if(xmlReader.name()==QString("Allow_One_Day_Exception_of_Plus_One")){
24625 			QString text=xmlReader.readElementText();
24626 			if(text=="true"){
24627 				cn->allowOneDayExceptionPlusOne=true;
24628 			}
24629 		}
24630 		else if(xmlReader.name()==QString("Active")){
24631 			QString text=xmlReader.readElementText();
24632 			if(text=="false"){
24633 				cn->active=false;
24634 			}
24635 		}
24636 		else if(xmlReader.name()==QString("Comments")){
24637 			QString text=xmlReader.readElementText();
24638 			cn->comments=text;
24639 		}
24640 		else if(xmlReader.name()==QString("Teacher_Name")){
24641 			QString text=xmlReader.readElementText();
24642 			cn->teacherName=text;
24643 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
24644 		}
24645 		else if(xmlReader.name()==QString("Max_Span")){
24646 			QString text=xmlReader.readElementText();
24647 			cn->maxSpanPerDay=text.toInt();
24648 			xmlReadingLog+="    Adding max span per day="+CustomFETString::number(cn->maxSpanPerDay)+"\n";
24649 		}
24650 		else{
24651 			unrecognizedXmlTags.append(xmlReader.name().toString());
24652 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
24653 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
24654 
24655 			xmlReader.skipCurrentElement();
24656 			xmlReaderNumberOfUnrecognizedFields++;
24657 		}
24658 	}
24659 	return cn;
24660 }
24661 
readTeacherMaxSpanPerRealDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)24662 TimeConstraint* Rules::readTeacherMaxSpanPerRealDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
24663 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxSpanPerRealDay"));
24664 	ConstraintTeacherMaxSpanPerRealDay* cn=new ConstraintTeacherMaxSpanPerRealDay();
24665 	cn->allowOneDayExceptionPlusOne=false;
24666 	while(xmlReader.readNextStartElement()){
24667 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
24668 		if(xmlReader.name()==QString("Weight_Percentage")){
24669 			QString text=xmlReader.readElementText();
24670 			cn->weightPercentage=customFETStrToDouble(text);
24671 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
24672 		}
24673 		else if(xmlReader.name()==QString("Allow_One_Day_Exception_of_Plus_One")){
24674 			QString text=xmlReader.readElementText();
24675 			if(text=="true"){
24676 				cn->allowOneDayExceptionPlusOne=true;
24677 			}
24678 		}
24679 		else if(xmlReader.name()==QString("Active")){
24680 			QString text=xmlReader.readElementText();
24681 			if(text=="false"){
24682 				cn->active=false;
24683 			}
24684 		}
24685 		else if(xmlReader.name()==QString("Comments")){
24686 			QString text=xmlReader.readElementText();
24687 			cn->comments=text;
24688 		}
24689 		else if(xmlReader.name()==QString("Teacher_Name")){
24690 			QString text=xmlReader.readElementText();
24691 			cn->teacherName=text;
24692 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
24693 		}
24694 		else if(xmlReader.name()==QString("Max_Span")){
24695 			QString text=xmlReader.readElementText();
24696 			cn->maxSpanPerDay=text.toInt();
24697 			xmlReadingLog+="    Adding max span per day="+CustomFETString::number(cn->maxSpanPerDay)+"\n";
24698 		}
24699 		else{
24700 			unrecognizedXmlTags.append(xmlReader.name().toString());
24701 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
24702 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
24703 
24704 			xmlReader.skipCurrentElement();
24705 			xmlReaderNumberOfUnrecognizedFields++;
24706 		}
24707 	}
24708 	return cn;
24709 }
24710 
readOldMATeachersMaxSpanPerDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)24711 TimeConstraint* Rules::readOldMATeachersMaxSpanPerDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
24712 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxSpanPerDay"));
24713 	ConstraintTeachersMaxSpanPerRealDay* cn=new ConstraintTeachersMaxSpanPerRealDay();
24714 	cn->allowOneDayExceptionPlusOne=false;
24715 	while(xmlReader.readNextStartElement()){
24716 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
24717 		if(xmlReader.name()==QString("Weight_Percentage")){
24718 			QString text=xmlReader.readElementText();
24719 			cn->weightPercentage=customFETStrToDouble(text);
24720 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
24721 		}
24722 		else if(xmlReader.name()==QString("Allow_One_Day_Exception_of_Plus_One")){
24723 			QString text=xmlReader.readElementText();
24724 			if(text=="true"){
24725 				cn->allowOneDayExceptionPlusOne=true;
24726 			}
24727 		}
24728 		else if(xmlReader.name()==QString("Active")){
24729 			QString text=xmlReader.readElementText();
24730 			if(text=="false"){
24731 				cn->active=false;
24732 			}
24733 		}
24734 		else if(xmlReader.name()==QString("Comments")){
24735 			QString text=xmlReader.readElementText();
24736 			cn->comments=text;
24737 		}
24738 		else if(xmlReader.name()==QString("Max_Span")){
24739 			QString text=xmlReader.readElementText();
24740 			cn->maxSpanPerDay=text.toInt();
24741 			xmlReadingLog+="    Adding max span per day="+CustomFETString::number(cn->maxSpanPerDay)+"\n";
24742 		}
24743 		else{
24744 			unrecognizedXmlTags.append(xmlReader.name().toString());
24745 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
24746 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
24747 
24748 			xmlReader.skipCurrentElement();
24749 			xmlReaderNumberOfUnrecognizedFields++;
24750 		}
24751 	}
24752 	return cn;
24753 }
24754 
readTeachersMaxSpanPerRealDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)24755 TimeConstraint* Rules::readTeachersMaxSpanPerRealDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
24756 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxSpanPerRealDay"));
24757 	ConstraintTeachersMaxSpanPerRealDay* cn=new ConstraintTeachersMaxSpanPerRealDay();
24758 	cn->allowOneDayExceptionPlusOne=false;
24759 	while(xmlReader.readNextStartElement()){
24760 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
24761 		if(xmlReader.name()==QString("Weight_Percentage")){
24762 			QString text=xmlReader.readElementText();
24763 			cn->weightPercentage=customFETStrToDouble(text);
24764 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
24765 		}
24766 		else if(xmlReader.name()==QString("Allow_One_Day_Exception_of_Plus_One")){
24767 			QString text=xmlReader.readElementText();
24768 			if(text=="true"){
24769 				cn->allowOneDayExceptionPlusOne=true;
24770 			}
24771 		}
24772 		else if(xmlReader.name()==QString("Active")){
24773 			QString text=xmlReader.readElementText();
24774 			if(text=="false"){
24775 				cn->active=false;
24776 			}
24777 		}
24778 		else if(xmlReader.name()==QString("Comments")){
24779 			QString text=xmlReader.readElementText();
24780 			cn->comments=text;
24781 		}
24782 		else if(xmlReader.name()==QString("Max_Span")){
24783 			QString text=xmlReader.readElementText();
24784 			cn->maxSpanPerDay=text.toInt();
24785 			xmlReadingLog+="    Adding max span per day="+CustomFETString::number(cn->maxSpanPerDay)+"\n";
24786 		}
24787 		else{
24788 			unrecognizedXmlTags.append(xmlReader.name().toString());
24789 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
24790 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
24791 
24792 			xmlReader.skipCurrentElement();
24793 			xmlReaderNumberOfUnrecognizedFields++;
24794 		}
24795 	}
24796 	return cn;
24797 }
24798 
readOldMAStudentsSetMaxSpanPerDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)24799 TimeConstraint* Rules::readOldMAStudentsSetMaxSpanPerDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
24800 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMaxSpanPerDay"));
24801 	ConstraintStudentsSetMaxSpanPerRealDay* cn=new ConstraintStudentsSetMaxSpanPerRealDay();
24802 	while(xmlReader.readNextStartElement()){
24803 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
24804 		if(xmlReader.name()==QString("Weight_Percentage")){
24805 			QString text=xmlReader.readElementText();
24806 			cn->weightPercentage=customFETStrToDouble(text);
24807 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
24808 		}
24809 		else if(xmlReader.name()==QString("Active")){
24810 			QString text=xmlReader.readElementText();
24811 			if(text=="false"){
24812 				cn->active=false;
24813 			}
24814 		}
24815 		else if(xmlReader.name()==QString("Comments")){
24816 			QString text=xmlReader.readElementText();
24817 			cn->comments=text;
24818 		}
24819 		else if(xmlReader.name()==QString("Students")){
24820 			QString text=xmlReader.readElementText();
24821 			cn->students=text;
24822 			xmlReadingLog+="    Read students name="+cn->students+"\n";
24823 		}
24824 		else if(xmlReader.name()==QString("Max_Span")){
24825 			QString text=xmlReader.readElementText();
24826 			cn->maxSpanPerDay=text.toInt();
24827 			xmlReadingLog+="    Adding max span per day="+CustomFETString::number(cn->maxSpanPerDay)+"\n";
24828 		}
24829 		else{
24830 			unrecognizedXmlTags.append(xmlReader.name().toString());
24831 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
24832 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
24833 
24834 			xmlReader.skipCurrentElement();
24835 			xmlReaderNumberOfUnrecognizedFields++;
24836 		}
24837 	}
24838 	return cn;
24839 }
24840 
readStudentsSetMaxSpanPerRealDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)24841 TimeConstraint* Rules::readStudentsSetMaxSpanPerRealDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
24842 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMaxSpanPerRealDay"));
24843 	ConstraintStudentsSetMaxSpanPerRealDay* cn=new ConstraintStudentsSetMaxSpanPerRealDay();
24844 	while(xmlReader.readNextStartElement()){
24845 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
24846 		if(xmlReader.name()==QString("Weight_Percentage")){
24847 			QString text=xmlReader.readElementText();
24848 			cn->weightPercentage=customFETStrToDouble(text);
24849 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
24850 		}
24851 		else if(xmlReader.name()==QString("Active")){
24852 			QString text=xmlReader.readElementText();
24853 			if(text=="false"){
24854 				cn->active=false;
24855 			}
24856 		}
24857 		else if(xmlReader.name()==QString("Comments")){
24858 			QString text=xmlReader.readElementText();
24859 			cn->comments=text;
24860 		}
24861 		else if(xmlReader.name()==QString("Students")){
24862 			QString text=xmlReader.readElementText();
24863 			cn->students=text;
24864 			xmlReadingLog+="    Read students name="+cn->students+"\n";
24865 		}
24866 		else if(xmlReader.name()==QString("Max_Span")){
24867 			QString text=xmlReader.readElementText();
24868 			cn->maxSpanPerDay=text.toInt();
24869 			xmlReadingLog+="    Adding max span per day="+CustomFETString::number(cn->maxSpanPerDay)+"\n";
24870 		}
24871 		else{
24872 			unrecognizedXmlTags.append(xmlReader.name().toString());
24873 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
24874 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
24875 
24876 			xmlReader.skipCurrentElement();
24877 			xmlReaderNumberOfUnrecognizedFields++;
24878 		}
24879 	}
24880 	return cn;
24881 }
24882 
readOldMAStudentsMaxSpanPerDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)24883 TimeConstraint* Rules::readOldMAStudentsMaxSpanPerDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
24884 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMaxSpanPerDay"));
24885 	ConstraintStudentsMaxSpanPerRealDay* cn=new ConstraintStudentsMaxSpanPerRealDay();
24886 	while(xmlReader.readNextStartElement()){
24887 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
24888 		if(xmlReader.name()==QString("Weight_Percentage")){
24889 			QString text=xmlReader.readElementText();
24890 			cn->weightPercentage=customFETStrToDouble(text);
24891 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
24892 		}
24893 		else if(xmlReader.name()==QString("Active")){
24894 			QString text=xmlReader.readElementText();
24895 			if(text=="false"){
24896 				cn->active=false;
24897 			}
24898 		}
24899 		else if(xmlReader.name()==QString("Comments")){
24900 			QString text=xmlReader.readElementText();
24901 			cn->comments=text;
24902 		}
24903 		else if(xmlReader.name()==QString("Max_Span")){
24904 			QString text=xmlReader.readElementText();
24905 			cn->maxSpanPerDay=text.toInt();
24906 			xmlReadingLog+="    Adding max span per day="+CustomFETString::number(cn->maxSpanPerDay)+"\n";
24907 		}
24908 		else{
24909 			unrecognizedXmlTags.append(xmlReader.name().toString());
24910 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
24911 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
24912 
24913 			xmlReader.skipCurrentElement();
24914 			xmlReaderNumberOfUnrecognizedFields++;
24915 		}
24916 	}
24917 	return cn;
24918 }
24919 
readStudentsMaxSpanPerRealDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)24920 TimeConstraint* Rules::readStudentsMaxSpanPerRealDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
24921 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMaxSpanPerRealDay"));
24922 	ConstraintStudentsMaxSpanPerRealDay* cn=new ConstraintStudentsMaxSpanPerRealDay();
24923 	while(xmlReader.readNextStartElement()){
24924 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
24925 		if(xmlReader.name()==QString("Weight_Percentage")){
24926 			QString text=xmlReader.readElementText();
24927 			cn->weightPercentage=customFETStrToDouble(text);
24928 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
24929 		}
24930 		else if(xmlReader.name()==QString("Active")){
24931 			QString text=xmlReader.readElementText();
24932 			if(text=="false"){
24933 				cn->active=false;
24934 			}
24935 		}
24936 		else if(xmlReader.name()==QString("Comments")){
24937 			QString text=xmlReader.readElementText();
24938 			cn->comments=text;
24939 		}
24940 		else if(xmlReader.name()==QString("Max_Span")){
24941 			QString text=xmlReader.readElementText();
24942 			cn->maxSpanPerDay=text.toInt();
24943 			xmlReadingLog+="    Adding max span per day="+CustomFETString::number(cn->maxSpanPerDay)+"\n";
24944 		}
24945 		else{
24946 			unrecognizedXmlTags.append(xmlReader.name().toString());
24947 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
24948 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
24949 
24950 			xmlReader.skipCurrentElement();
24951 			xmlReaderNumberOfUnrecognizedFields++;
24952 		}
24953 	}
24954 	return cn;
24955 }
24956 /////////////
24957 
24958 /////////////
readTeacherMinRestingHoursBetweenMorningAndAfternoon(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)24959 TimeConstraint* Rules::readTeacherMinRestingHoursBetweenMorningAndAfternoon(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
24960 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMinRestingHoursBetweenMorningAndAfternoon"));
24961 	ConstraintTeacherMinRestingHoursBetweenMorningAndAfternoon* cn=new ConstraintTeacherMinRestingHoursBetweenMorningAndAfternoon();
24962 	while(xmlReader.readNextStartElement()){
24963 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
24964 		if(xmlReader.name()==QString("Weight_Percentage")){
24965 			QString text=xmlReader.readElementText();
24966 			cn->weightPercentage=customFETStrToDouble(text);
24967 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
24968 		}
24969 		else if(xmlReader.name()==QString("Active")){
24970 			QString text=xmlReader.readElementText();
24971 			if(text=="false"){
24972 				cn->active=false;
24973 			}
24974 		}
24975 		else if(xmlReader.name()==QString("Comments")){
24976 			QString text=xmlReader.readElementText();
24977 			cn->comments=text;
24978 		}
24979 		else if(xmlReader.name()==QString("Teacher_Name")){
24980 			QString text=xmlReader.readElementText();
24981 			cn->teacherName=text;
24982 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
24983 		}
24984 		else if(xmlReader.name()==QString("Minimum_Resting_Hours")){
24985 			QString text=xmlReader.readElementText();
24986 			cn->minRestingHours=text.toInt();
24987 			xmlReadingLog+="    Adding min resting hours="+CustomFETString::number(cn->minRestingHours)+"\n";
24988 		}
24989 		else{
24990 			unrecognizedXmlTags.append(xmlReader.name().toString());
24991 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
24992 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
24993 
24994 			xmlReader.skipCurrentElement();
24995 			xmlReaderNumberOfUnrecognizedFields++;
24996 		}
24997 	}
24998 	return cn;
24999 }
25000 
readTeachersMinRestingHoursBetweenMorningAndAfternoon(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)25001 TimeConstraint* Rules::readTeachersMinRestingHoursBetweenMorningAndAfternoon(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
25002 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMinRestingHoursBetweenMorningAndAfternoon"));
25003 	ConstraintTeachersMinRestingHoursBetweenMorningAndAfternoon* cn=new ConstraintTeachersMinRestingHoursBetweenMorningAndAfternoon();
25004 	while(xmlReader.readNextStartElement()){
25005 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
25006 		if(xmlReader.name()==QString("Weight_Percentage")){
25007 			QString text=xmlReader.readElementText();
25008 			cn->weightPercentage=customFETStrToDouble(text);
25009 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
25010 		}
25011 		else if(xmlReader.name()==QString("Active")){
25012 			QString text=xmlReader.readElementText();
25013 			if(text=="false"){
25014 				cn->active=false;
25015 			}
25016 		}
25017 		else if(xmlReader.name()==QString("Comments")){
25018 			QString text=xmlReader.readElementText();
25019 			cn->comments=text;
25020 		}
25021 		else if(xmlReader.name()==QString("Minimum_Resting_Hours")){
25022 			QString text=xmlReader.readElementText();
25023 			cn->minRestingHours=text.toInt();
25024 			xmlReadingLog+="    Adding min resting hours="+CustomFETString::number(cn->minRestingHours)+"\n";
25025 		}
25026 		else{
25027 			unrecognizedXmlTags.append(xmlReader.name().toString());
25028 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
25029 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
25030 
25031 			xmlReader.skipCurrentElement();
25032 			xmlReaderNumberOfUnrecognizedFields++;
25033 		}
25034 	}
25035 	return cn;
25036 }
25037 
readStudentsSetMinRestingHoursBetweenMorningAndAfternoon(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)25038 TimeConstraint* Rules::readStudentsSetMinRestingHoursBetweenMorningAndAfternoon(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
25039 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMinRestingHoursBetweenMorningAndAfternoon"));
25040 	ConstraintStudentsSetMinRestingHoursBetweenMorningAndAfternoon* cn=new ConstraintStudentsSetMinRestingHoursBetweenMorningAndAfternoon();
25041 	while(xmlReader.readNextStartElement()){
25042 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
25043 		if(xmlReader.name()==QString("Weight_Percentage")){
25044 			QString text=xmlReader.readElementText();
25045 			cn->weightPercentage=customFETStrToDouble(text);
25046 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
25047 		}
25048 		else if(xmlReader.name()==QString("Active")){
25049 			QString text=xmlReader.readElementText();
25050 			if(text=="false"){
25051 				cn->active=false;
25052 			}
25053 		}
25054 		else if(xmlReader.name()==QString("Comments")){
25055 			QString text=xmlReader.readElementText();
25056 			cn->comments=text;
25057 		}
25058 		else if(xmlReader.name()==QString("Students")){
25059 			QString text=xmlReader.readElementText();
25060 			cn->students=text;
25061 			xmlReadingLog+="    Read students name="+cn->students+"\n";
25062 		}
25063 		else if(xmlReader.name()==QString("Minimum_Resting_Hours")){
25064 			QString text=xmlReader.readElementText();
25065 			cn->minRestingHours=text.toInt();
25066 			xmlReadingLog+="    Adding min resting hours="+CustomFETString::number(cn->minRestingHours)+"\n";
25067 		}
25068 		else{
25069 			unrecognizedXmlTags.append(xmlReader.name().toString());
25070 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
25071 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
25072 
25073 			xmlReader.skipCurrentElement();
25074 			xmlReaderNumberOfUnrecognizedFields++;
25075 		}
25076 	}
25077 	return cn;
25078 }
25079 
readStudentsMinRestingHoursBetweenMorningAndAfternoon(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)25080 TimeConstraint* Rules::readStudentsMinRestingHoursBetweenMorningAndAfternoon(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
25081 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMinRestingHoursBetweenMorningAndAfternoon"));
25082 	ConstraintStudentsMinRestingHoursBetweenMorningAndAfternoon* cn=new ConstraintStudentsMinRestingHoursBetweenMorningAndAfternoon();
25083 	while(xmlReader.readNextStartElement()){
25084 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
25085 		if(xmlReader.name()==QString("Weight_Percentage")){
25086 			QString text=xmlReader.readElementText();
25087 			cn->weightPercentage=customFETStrToDouble(text);
25088 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
25089 		}
25090 		else if(xmlReader.name()==QString("Active")){
25091 			QString text=xmlReader.readElementText();
25092 			if(text=="false"){
25093 				cn->active=false;
25094 			}
25095 		}
25096 		else if(xmlReader.name()==QString("Comments")){
25097 			QString text=xmlReader.readElementText();
25098 			cn->comments=text;
25099 		}
25100 		else if(xmlReader.name()==QString("Minimum_Resting_Hours")){
25101 			QString text=xmlReader.readElementText();
25102 			cn->minRestingHours=text.toInt();
25103 			xmlReadingLog+="    Adding min resting hours="+CustomFETString::number(cn->minRestingHours)+"\n";
25104 		}
25105 		else{
25106 			unrecognizedXmlTags.append(xmlReader.name().toString());
25107 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
25108 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
25109 
25110 			xmlReader.skipCurrentElement();
25111 			xmlReaderNumberOfUnrecognizedFields++;
25112 		}
25113 	}
25114 	return cn;
25115 }
25116 ///////////////
25117 
25118 //2020-07-29
readTeachersMaxGapsPerWeekForRealDays(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)25119 TimeConstraint* Rules::readTeachersMaxGapsPerWeekForRealDays(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
25120 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxGapsPerWeekForRealDays"));
25121 	ConstraintTeachersMaxGapsPerWeekForRealDays* cn=new ConstraintTeachersMaxGapsPerWeekForRealDays();
25122 	while(xmlReader.readNextStartElement()){
25123 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
25124 		if(xmlReader.name()==QString("Weight_Percentage")){
25125 			QString text=xmlReader.readElementText();
25126 			cn->weightPercentage=customFETStrToDouble(text);
25127 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
25128 		}
25129 		else if(xmlReader.name()==QString("Active")){
25130 			QString text=xmlReader.readElementText();
25131 			if(text=="false"){
25132 				cn->active=false;
25133 			}
25134 		}
25135 		else if(xmlReader.name()==QString("Comments")){
25136 			QString text=xmlReader.readElementText();
25137 			cn->comments=text;
25138 		}
25139 		else if(xmlReader.name()==QString("Max_Gaps")){
25140 			QString text=xmlReader.readElementText();
25141 			cn->maxGaps=text.toInt();
25142 			xmlReadingLog+="    Adding max gaps="+CustomFETString::number(cn->maxGaps)+"\n";
25143 		}
25144 		else{
25145 			unrecognizedXmlTags.append(xmlReader.name().toString());
25146 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
25147 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
25148 
25149 			xmlReader.skipCurrentElement();
25150 			xmlReaderNumberOfUnrecognizedFields++;
25151 		}
25152 	}
25153 	return cn;
25154 }
25155 
readTeacherMaxGapsPerWeekForRealDays(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)25156 TimeConstraint* Rules::readTeacherMaxGapsPerWeekForRealDays(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
25157 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxGapsPerWeekForRealDays"));
25158 	ConstraintTeacherMaxGapsPerWeekForRealDays* cn=new ConstraintTeacherMaxGapsPerWeekForRealDays();
25159 	while(xmlReader.readNextStartElement()){
25160 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
25161 		if(xmlReader.name()==QString("Teacher_Name")){
25162 			QString text=xmlReader.readElementText();
25163 			cn->teacherName=text;
25164 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
25165 		}
25166 		else if(xmlReader.name()==QString("Weight_Percentage")){
25167 			QString text=xmlReader.readElementText();
25168 			cn->weightPercentage=customFETStrToDouble(text);
25169 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
25170 		}
25171 		else if(xmlReader.name()==QString("Active")){
25172 			QString text=xmlReader.readElementText();
25173 			if(text=="false"){
25174 				cn->active=false;
25175 			}
25176 		}
25177 		else if(xmlReader.name()==QString("Comments")){
25178 			QString text=xmlReader.readElementText();
25179 			cn->comments=text;
25180 		}
25181 		else if(xmlReader.name()==QString("Max_Gaps")){
25182 			QString text=xmlReader.readElementText();
25183 			cn->maxGaps=text.toInt();
25184 			xmlReadingLog+="    Adding max gaps="+CustomFETString::number(cn->maxGaps)+"\n";
25185 		}
25186 		else{
25187 			unrecognizedXmlTags.append(xmlReader.name().toString());
25188 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
25189 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
25190 
25191 			xmlReader.skipCurrentElement();
25192 			xmlReaderNumberOfUnrecognizedFields++;
25193 		}
25194 	}
25195 	return cn;
25196 }
25197 
readStudentsMaxGapsPerWeekForRealDays(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)25198 TimeConstraint* Rules::readStudentsMaxGapsPerWeekForRealDays(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
25199 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMaxGapsPerWeekForRealDays"));
25200 	ConstraintStudentsMaxGapsPerWeekForRealDays* cn=new ConstraintStudentsMaxGapsPerWeekForRealDays();
25201 
25202 	//bool compulsory_read=false;
25203 	while(xmlReader.readNextStartElement()){
25204 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
25205 		if(xmlReader.name()==QString("Weight_Percentage")){
25206 			QString text=xmlReader.readElementText();
25207 			cn->weightPercentage=customFETStrToDouble(text);
25208 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
25209 		}
25210 		else if(xmlReader.name()==QString("Active")){
25211 			QString text=xmlReader.readElementText();
25212 			if(text=="false"){
25213 				cn->active=false;
25214 			}
25215 		}
25216 		else if(xmlReader.name()==QString("Comments")){
25217 			QString text=xmlReader.readElementText();
25218 			cn->comments=text;
25219 		}
25220 		else if(xmlReader.name()==QString("Max_Gaps")){
25221 			QString text=xmlReader.readElementText();
25222 			cn->maxGaps=text.toInt();
25223 			xmlReadingLog+="    Adding max gaps="+CustomFETString::number(cn->maxGaps)+"\n";
25224 		}
25225 		else{
25226 			unrecognizedXmlTags.append(xmlReader.name().toString());
25227 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
25228 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
25229 
25230 			xmlReader.skipCurrentElement();
25231 			xmlReaderNumberOfUnrecognizedFields++;
25232 		}
25233 	}
25234 	return cn;
25235 }
25236 
readStudentsSetMaxGapsPerWeekForRealDays(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)25237 TimeConstraint* Rules::readStudentsSetMaxGapsPerWeekForRealDays(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
25238 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMaxGapsPerWeekForRealDays"));
25239 	ConstraintStudentsSetMaxGapsPerWeekForRealDays* cn=new ConstraintStudentsSetMaxGapsPerWeekForRealDays();
25240 
25241 	//bool compulsory_read=false;
25242 	while(xmlReader.readNextStartElement()){
25243 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
25244 		if(xmlReader.name()==QString("Weight_Percentage")){
25245 			QString text=xmlReader.readElementText();
25246 			cn->weightPercentage=customFETStrToDouble(text);
25247 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
25248 		}
25249 		else if(xmlReader.name()==QString("Active")){
25250 			QString text=xmlReader.readElementText();
25251 			if(text=="false"){
25252 				cn->active=false;
25253 			}
25254 		}
25255 		else if(xmlReader.name()==QString("Comments")){
25256 			QString text=xmlReader.readElementText();
25257 			cn->comments=text;
25258 		}
25259 		else if(xmlReader.name()==QString("Max_Gaps")){
25260 			QString text=xmlReader.readElementText();
25261 			cn->maxGaps=text.toInt();
25262 			xmlReadingLog+="    Adding max gaps="+CustomFETString::number(cn->maxGaps)+"\n";
25263 		}
25264 		else if(xmlReader.name()==QString("Students")){
25265 			QString text=xmlReader.readElementText();
25266 			cn->students=text;
25267 			xmlReadingLog+="    Read students name="+cn->students+"\n";
25268 		}
25269 		else{
25270 			unrecognizedXmlTags.append(xmlReader.name().toString());
25271 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
25272 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
25273 
25274 			xmlReader.skipCurrentElement();
25275 			xmlReaderNumberOfUnrecognizedFields++;
25276 		}
25277 	}
25278 	return cn;
25279 }
25280 
readTeacherMaxThreeConsecutiveDays(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)25281 TimeConstraint* Rules::readTeacherMaxThreeConsecutiveDays(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
25282 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxThreeConsecutiveDays"));
25283 
25284 	ConstraintTeacherMaxThreeConsecutiveDays* cn=new ConstraintTeacherMaxThreeConsecutiveDays();
25285 	cn->allowAMAMException=false;
25286 	bool foundAllowAMAMException=false;
25287 	while(xmlReader.readNextStartElement()){
25288 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
25289 		if(xmlReader.name()==QString("Weight_Percentage")){
25290 			QString text=xmlReader.readElementText();
25291 			cn->weightPercentage=customFETStrToDouble(text);
25292 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
25293 		}
25294 		else if(xmlReader.name()==QString("Active")){
25295 			QString text=xmlReader.readElementText();
25296 			if(text=="false"){
25297 				cn->active=false;
25298 			}
25299 		}
25300 		else if(xmlReader.name()==QString("Comments")){
25301 			QString text=xmlReader.readElementText();
25302 			cn->comments=text;
25303 		}
25304 		else if(xmlReader.name()==QString("Teacher_Name")){
25305 			QString text=xmlReader.readElementText();
25306 			cn->teacherName=text;
25307 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
25308 		}
25309 		else if(xmlReader.name()==QString("Allow_Afternoon_Morning_Afternoon_Morning_Exception")){
25310 			foundAllowAMAMException=true;
25311 			QString text=xmlReader.readElementText();
25312 			if(text=="yes" || text=="true" || text=="1"){
25313 				cn->allowAMAMException=true;
25314 				xmlReadingLog+="    Current constraint has allowAMAMException=true\n";
25315 			}
25316 			else{
25317 				if(!(text=="no" || text=="false" || text=="0")){
25318 					RulesReconcilableMessage::warning(parent, tr("FET warning"),
25319 						tr("Found constraint teacher max three consecutive days with tag %1"
25320 						" which is not 'true', 'false', 'yes', 'no', '1' or '0'."
25321 						" The tag will be considered false",
25322 						"Instructions for translators: please leave the 'true', 'false', 'yes' and 'no' fields untranslated, as they are in English")
25323 						.arg("Allow_Afternoon_Morning_Afternoon_Morning_Exception"));
25324 				}
25325 				cn->allowAMAMException=false;
25326 				xmlReadingLog+="    Current constraint has allowAMAMException=false\n";
25327 			}
25328 		}
25329 		else{
25330 			unrecognizedXmlTags.append(xmlReader.name().toString());
25331 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
25332 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
25333 
25334 			xmlReader.skipCurrentElement();
25335 			xmlReaderNumberOfUnrecognizedFields++;
25336 		}
25337 	}
25338 	if(!foundAllowAMAMException){
25339 		xmlReader.raiseError(tr("%1 not found").arg("Allow_Afternoon_Morning_Afternoon_Morning_Exception"));
25340 		delete cn;
25341 		cn=nullptr;
25342 		return nullptr;
25343 	}
25344 	return cn;
25345 }
25346 
readTeachersMaxThreeConsecutiveDays(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)25347 TimeConstraint* Rules::readTeachersMaxThreeConsecutiveDays(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
25348 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxThreeConsecutiveDays"));
25349 
25350 	ConstraintTeachersMaxThreeConsecutiveDays* cn=new ConstraintTeachersMaxThreeConsecutiveDays();
25351 	cn->allowAMAMException=false;
25352 	bool foundAllowAMAMException=false;
25353 	while(xmlReader.readNextStartElement()){
25354 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
25355 		if(xmlReader.name()==QString("Weight_Percentage")){
25356 			QString text=xmlReader.readElementText();
25357 			cn->weightPercentage=customFETStrToDouble(text);
25358 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
25359 		}
25360 		else if(xmlReader.name()==QString("Active")){
25361 			QString text=xmlReader.readElementText();
25362 			if(text=="false"){
25363 				cn->active=false;
25364 			}
25365 		}
25366 		else if(xmlReader.name()==QString("Comments")){
25367 			QString text=xmlReader.readElementText();
25368 			cn->comments=text;
25369 		}
25370 		else if(xmlReader.name()==QString("Allow_Afternoon_Morning_Afternoon_Morning_Exception")){
25371 			foundAllowAMAMException=true;
25372 			QString text=xmlReader.readElementText();
25373 			if(text=="yes" || text=="true" || text=="1"){
25374 				cn->allowAMAMException=true;
25375 				xmlReadingLog+="    Current constraint has allowAMAMException=true\n";
25376 			}
25377 			else{
25378 				if(!(text=="no" || text=="false" || text=="0")){
25379 					RulesReconcilableMessage::warning(parent, tr("FET warning"),
25380 						tr("Found constraint teacher max three consecutive days with tag %1"
25381 						" which is not 'true', 'false', 'yes', 'no', '1' or '0'."
25382 						" The tag will be considered false",
25383 						"Instructions for translators: please leave the 'true', 'false', 'yes' and 'no' fields untranslated, as they are in English")
25384 						.arg("Allow_Afternoon_Morning_Afternoon_Morning_Exception"));
25385 				}
25386 				cn->allowAMAMException=false;
25387 				xmlReadingLog+="    Current constraint has allowAMAMException=false\n";
25388 			}
25389 		}
25390 		else{
25391 			unrecognizedXmlTags.append(xmlReader.name().toString());
25392 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
25393 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
25394 
25395 			xmlReader.skipCurrentElement();
25396 			xmlReaderNumberOfUnrecognizedFields++;
25397 		}
25398 	}
25399 	if(!foundAllowAMAMException){
25400 		xmlReader.raiseError(tr("%1 not found").arg("Allow_Afternoon_Morning_Afternoon_Morning_Exception"));
25401 		delete cn;
25402 		cn=nullptr;
25403 		return nullptr;
25404 	}
25405 	return cn;
25406 }
25407 
25408 ///////////////
25409 
25410 ///space constraints reading routines
readBasicCompulsorySpace(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)25411 SpaceConstraint* Rules::readBasicCompulsorySpace(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
25412 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintBasicCompulsorySpace"));
25413 	ConstraintBasicCompulsorySpace* cn=new ConstraintBasicCompulsorySpace();
25414 	while(xmlReader.readNextStartElement()){
25415 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
25416 
25417 		if(xmlReader.name()==QString("Weight")){
25418 			//cn->weight=customFETStrToDouble(text);
25419 			xmlReader.skipCurrentElement();
25420 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
25421 			cn->weightPercentage=100;
25422 		}
25423 		else if(xmlReader.name()==QString("Weight_Percentage")){
25424 			QString text=xmlReader.readElementText();
25425 			cn->weightPercentage=customFETStrToDouble(text);
25426 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
25427 		}
25428 		else if(xmlReader.name()==QString("Active")){
25429 			QString text=xmlReader.readElementText();
25430 			if(text=="false"){
25431 				cn->active=false;
25432 			}
25433 		}
25434 		else if(xmlReader.name()==QString("Comments")){
25435 			QString text=xmlReader.readElementText();
25436 			cn->comments=text;
25437 		}
25438 		else if(xmlReader.name()==QString("Compulsory")){
25439 			QString text=xmlReader.readElementText();
25440 			if(text=="yes"){
25441 				//cn->compulsory=true;
25442 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
25443 				cn->weightPercentage=100;
25444 			}
25445 			else{
25446 				//cn->compulsory=false;
25447 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
25448 				cn->weightPercentage=0;
25449 			}
25450 		}
25451 		/*if(xmlReader.name()==QString("Weight")){
25452 			cn->weight=customFETStrToDouble(text);
25453 			xmlReadingLog+="    Adding weight="+CustomFETString::number(cn->weight)+"\n";
25454 		}
25455 		else if(xmlReader.name()==QString("Compulsory")){
25456 			if(text=="yes"){
25457 				cn->compulsory=true;
25458 				xmlReadingLog+="    Current constraint is compulsory\n";
25459 			}
25460 			else{
25461 				cn->compulsory=false;
25462 				xmlReadingLog+="    Current constraint is not compulsory\n";
25463 			}
25464 		}*/
25465 		else{
25466 			unrecognizedXmlTags.append(xmlReader.name().toString());
25467 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
25468 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
25469 
25470 			xmlReader.skipCurrentElement();
25471 			xmlReaderNumberOfUnrecognizedFields++;
25472 		}
25473 	}
25474 	return cn;
25475 }
25476 
readRoomNotAvailable(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)25477 SpaceConstraint* Rules::readRoomNotAvailable(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
25478 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintRoomNotAvailable"));
25479 
25480 	QList<int> days;
25481 	QList<int> hours;
25482 	QString room;
25483 	double weightPercentage=100;
25484 	int d=-1, h1=-1, h2=-1;
25485 	bool active=true;
25486 	QString comments=QString("");
25487 	while(xmlReader.readNextStartElement()){
25488 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
25489 		if(xmlReader.name()==QString("Weight_Percentage")){
25490 			QString text=xmlReader.readElementText();
25491 			weightPercentage=customFETStrToDouble(text);
25492 			xmlReadingLog+="    Read weight percentage="+CustomFETString::number(weightPercentage)+"\n";
25493 		}
25494 		else if(xmlReader.name()==QString("Active")){
25495 			QString text=xmlReader.readElementText();
25496 			if(text=="false"){
25497 				active=false;
25498 			}
25499 		}
25500 		else if(xmlReader.name()==QString("Comments")){
25501 			QString text=xmlReader.readElementText();
25502 			comments=text;
25503 		}
25504 		else if(xmlReader.name()==QString("Day")){
25505 			QString text=xmlReader.readElementText();
25506 			for(d=0; d<this->nDaysPerWeek; d++)
25507 				if(this->daysOfTheWeek[d]==text)
25508 					break;
25509 			if(d>=this->nDaysPerWeek){
25510 				xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
25511 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
25512 					tr("Constraint RoomNotAvailable day corrupt for room %1, day %2 is inexistent ... ignoring constraint")
25513 					.arg(room)
25514 					.arg(text));*/
25515 				//cn=nullptr;
25516 				//goto corruptConstraintSpace;
25517 				return nullptr;
25518 			}
25519 			assert(d<this->nDaysPerWeek);
25520 			xmlReadingLog+="    Crt. day="+this->daysOfTheWeek[d]+"\n";
25521 		}
25522 		else if(xmlReader.name()==QString("Start_Hour")){
25523 			QString text=xmlReader.readElementText();
25524 			for(h1=0; h1 < this->nHoursPerDay; h1++)
25525 				if(this->hoursOfTheDay[h1]==text)
25526 					break;
25527 			if(h1==this->nHoursPerDay){
25528 				xmlReader.raiseError(tr("Hour %1 is the last hour - impossible").arg(text));
25529 				return nullptr;
25530 			}
25531 			else if(h1>this->nHoursPerDay){
25532 				xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
25533 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
25534 					tr("Constraint RoomNotAvailable start hour corrupt for room %1, hour %2 is inexistent ... ignoring constraint")
25535 					.arg(room)
25536 					.arg(text));*/
25537 				//cn=nullptr;
25538 				//goto corruptConstraintSpace;
25539 				return nullptr;
25540 			}
25541 			assert(h1>=0 && h1 < this->nHoursPerDay);
25542 			xmlReadingLog+="    Start hour="+this->hoursOfTheDay[h1]+"\n";
25543 		}
25544 		else if(xmlReader.name()==QString("End_Hour")){
25545 			QString text=xmlReader.readElementText();
25546 			for(h2=0; h2 < this->nHoursPerDay; h2++)
25547 				if(this->hoursOfTheDay[h2]==text)
25548 					break;
25549 			if(h2==0){
25550 				xmlReader.raiseError(tr("Hour %1 is the first hour - impossible").arg(text));
25551 				return nullptr;
25552 			}
25553 			else if(h2<0 || h2>this->nHoursPerDay){
25554 				xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
25555 				/*RulesReconcilableMessage::information(parent, tr("FET information"),
25556 					tr("Constraint RoomNotAvailable end hour corrupt for room %1, hour %2 is inexistent ... ignoring constraint")
25557 					.arg(room)
25558 					.arg(text));*/
25559 				//goto corruptConstraintSpace;
25560 				return nullptr;
25561 			}
25562 			assert(h2>0 && h2 <= this->nHoursPerDay);
25563 			xmlReadingLog+="    End hour="+this->hoursOfTheDay[h2]+"\n";
25564 		}
25565 		else if(xmlReader.name()==QString("Room_Name")){
25566 			QString text=xmlReader.readElementText();
25567 			room=text;
25568 			xmlReadingLog+="    Read room name="+room+"\n";
25569 		}
25570 		else{
25571 			unrecognizedXmlTags.append(xmlReader.name().toString());
25572 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
25573 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
25574 
25575 			xmlReader.skipCurrentElement();
25576 			xmlReaderNumberOfUnrecognizedFields++;
25577 		}
25578 	}
25579 
25580 	if(d<0){
25581 		xmlReader.raiseError(tr("Field missing: %1").arg("Day"));
25582 		return nullptr;
25583 	}
25584 	else if(h1<0){
25585 		xmlReader.raiseError(tr("Field missing: %1").arg("Start_Hour"));
25586 		return nullptr;
25587 	}
25588 	else if(h2<0){
25589 		xmlReader.raiseError(tr("Field missing: %1").arg("End_Hour"));
25590 		return nullptr;
25591 	}
25592 	assert(weightPercentage>=0);
25593 	assert(d>=0 && h1>=0 && h2>=0);
25594 
25595 	ConstraintRoomNotAvailableTimes* cn = nullptr;
25596 
25597 	bool found=false;
25598 	for(SpaceConstraint* c : qAsConst(this->spaceConstraintsList))
25599 		if(c->type==CONSTRAINT_ROOM_NOT_AVAILABLE_TIMES){
25600 			ConstraintRoomNotAvailableTimes* tna=(ConstraintRoomNotAvailableTimes*) c;
25601 			if(tna->room==room){
25602 				found=true;
25603 
25604 				for(int hh=h1; hh<h2; hh++){
25605 					int k;
25606 					for(k=0; k<tna->days.count(); k++)
25607 						if(tna->days.at(k)==d && tna->hours.at(k)==hh)
25608 							break;
25609 					if(k==tna->days.count()){
25610 						tna->days.append(d);
25611 						tna->hours.append(hh);
25612 					}
25613 				}
25614 
25615 				assert(tna->days.count()==tna->hours.count());
25616 			}
25617 		}
25618 	if(!found){
25619 		days.clear();
25620 		hours.clear();
25621 		for(int hh=h1; hh<h2; hh++){
25622 			days.append(d);
25623 			hours.append(hh);
25624 		}
25625 
25626 		cn=new ConstraintRoomNotAvailableTimes(weightPercentage, room, days, hours);
25627 		cn->active=active;
25628 		cn->comments=comments;
25629 
25630 		return cn;
25631 	}
25632 	else
25633 		return nullptr;
25634 }
25635 
readRoomNotAvailableTimes(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)25636 SpaceConstraint* Rules::readRoomNotAvailableTimes(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
25637 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintRoomNotAvailableTimes"));
25638 	ConstraintRoomNotAvailableTimes* cn=new ConstraintRoomNotAvailableTimes();
25639 	int nNotAvailableSlots=-1;
25640 	int i=0;
25641 	while(xmlReader.readNextStartElement()){
25642 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
25643 		if(xmlReader.name()==QString("Weight_Percentage")){
25644 			QString text=xmlReader.readElementText();
25645 			cn->weightPercentage=customFETStrToDouble(text);
25646 			xmlReadingLog+="    Read weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
25647 		}
25648 		else if(xmlReader.name()==QString("Active")){
25649 			QString text=xmlReader.readElementText();
25650 			if(text=="false"){
25651 				cn->active=false;
25652 			}
25653 		}
25654 		else if(xmlReader.name()==QString("Comments")){
25655 			QString text=xmlReader.readElementText();
25656 			cn->comments=text;
25657 		}
25658 
25659 		else if(xmlReader.name()==QString("Number_of_Not_Available_Times")){
25660 			QString text=xmlReader.readElementText();
25661 			nNotAvailableSlots=text.toInt();
25662 			xmlReadingLog+="    Read number of not available times="+CustomFETString::number(nNotAvailableSlots)+"\n";
25663 		}
25664 
25665 		else if(xmlReader.name()==QString("Not_Available_Time")){
25666 			xmlReadingLog+="    Read: not available time\n";
25667 
25668 			int d=-1;
25669 			int h=-1;
25670 
25671 			assert(xmlReader.isStartElement());
25672 			while(xmlReader.readNextStartElement()){
25673 				xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
25674 				if(xmlReader.name()==QString("Day")){
25675 					QString text=xmlReader.readElementText();
25676 					for(d=0; d<this->nDaysPerWeek; d++)
25677 						if(this->daysOfTheWeek[d]==text)
25678 							break;
25679 
25680 					if(d>=this->nDaysPerWeek){
25681 						xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
25682 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
25683 							tr("Constraint RoomNotAvailableTimes day corrupt for room %1, day %2 is inexistent ... ignoring constraint")
25684 							.arg(cn->room)
25685 							.arg(text));*/
25686 						delete cn;
25687 						cn=nullptr;
25688 						return nullptr;
25689 						//goto corruptConstraintSpace;
25690 					}
25691 
25692 					assert(d<this->nDaysPerWeek);
25693 					xmlReadingLog+="    Day="+this->daysOfTheWeek[d]+"("+CustomFETString::number(i)+")"+"\n";
25694 				}
25695 				else if(xmlReader.name()==QString("Hour")){
25696 					QString text=xmlReader.readElementText();
25697 					for(h=0; h < this->nHoursPerDay; h++)
25698 						if(this->hoursOfTheDay[h]==text)
25699 							break;
25700 
25701 					if(h>=this->nHoursPerDay){
25702 						xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
25703 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
25704 							tr("Constraint RoomNotAvailableTimes hour corrupt for room %1, hour %2 is inexistent ... ignoring constraint")
25705 							.arg(cn->room)
25706 							.arg(text));*/
25707 						delete cn;
25708 						cn=nullptr;
25709 						//goto corruptConstraintSpace;
25710 						return nullptr;
25711 					}
25712 
25713 					assert(h>=0 && h < this->nHoursPerDay);
25714 					xmlReadingLog+="    Hour="+this->hoursOfTheDay[h]+"\n";
25715 				}
25716 				else{
25717 					unrecognizedXmlTags.append(xmlReader.name().toString());
25718 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
25719 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
25720 
25721 					xmlReader.skipCurrentElement();
25722 					xmlReaderNumberOfUnrecognizedFields++;
25723 				}
25724 			}
25725 			i++;
25726 
25727 			cn->days.append(d);
25728 			cn->hours.append(h);
25729 
25730 			if(d==-1 || h==-1){
25731 				xmlReader.raiseError(tr("%1 is incorrect").arg("Not_Available_Time"));
25732 				delete cn;
25733 				cn=nullptr;
25734 				return nullptr;
25735 			}
25736 		}
25737 		else if(xmlReader.name()==QString("Room")){
25738 			QString text=xmlReader.readElementText();
25739 			cn->room=text;
25740 			xmlReadingLog+="    Read room name="+cn->room+"\n";
25741 		}
25742 		else{
25743 			unrecognizedXmlTags.append(xmlReader.name().toString());
25744 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
25745 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
25746 
25747 			xmlReader.skipCurrentElement();
25748 			xmlReaderNumberOfUnrecognizedFields++;
25749 		}
25750 	}
25751 	assert(i==cn->days.count() && i==cn->hours.count());
25752 	if(!(i==nNotAvailableSlots)){
25753 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Not_Available_Times").arg("Not_Available_Time"));
25754 		delete cn;
25755 		cn=nullptr;
25756 		return nullptr;
25757 	}
25758 	assert(i==nNotAvailableSlots);
25759 	return cn;
25760 }
25761 
readTeacherRoomNotAvailableTimes(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)25762 SpaceConstraint* Rules::readTeacherRoomNotAvailableTimes(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
25763 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherRoomNotAvailableTimes"));
25764 	ConstraintTeacherRoomNotAvailableTimes* cn=new ConstraintTeacherRoomNotAvailableTimes();
25765 	int nNotAvailableSlots=-1;
25766 	int i=0;
25767 	while(xmlReader.readNextStartElement()){
25768 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
25769 		if(xmlReader.name()==QString("Weight_Percentage")){
25770 			QString text=xmlReader.readElementText();
25771 			cn->weightPercentage=customFETStrToDouble(text);
25772 			xmlReadingLog+="    Read weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
25773 		}
25774 		else if(xmlReader.name()==QString("Active")){
25775 			QString text=xmlReader.readElementText();
25776 			if(text=="false"){
25777 				cn->active=false;
25778 			}
25779 		}
25780 		else if(xmlReader.name()==QString("Comments")){
25781 			QString text=xmlReader.readElementText();
25782 			cn->comments=text;
25783 		}
25784 
25785 		else if(xmlReader.name()==QString("Number_of_Not_Available_Times")){
25786 			QString text=xmlReader.readElementText();
25787 			nNotAvailableSlots=text.toInt();
25788 			xmlReadingLog+="    Read number of not available times="+CustomFETString::number(nNotAvailableSlots)+"\n";
25789 		}
25790 
25791 		else if(xmlReader.name()==QString("Not_Available_Time")){
25792 			xmlReadingLog+="    Read: not available time\n";
25793 
25794 			int d=-1;
25795 			int h=-1;
25796 
25797 			assert(xmlReader.isStartElement());
25798 			while(xmlReader.readNextStartElement()){
25799 				xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
25800 				if(xmlReader.name()==QString("Day")){
25801 					QString text=xmlReader.readElementText();
25802 					for(d=0; d<this->nDaysPerWeek; d++)
25803 						if(this->daysOfTheWeek[d]==text)
25804 							break;
25805 
25806 					if(d>=this->nDaysPerWeek){
25807 						xmlReader.raiseError(tr("Day %1 is inexistent").arg(text));
25808 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
25809 							tr("Constraint RoomNotAvailableTimes day corrupt for room %1, day %2 is inexistent ... ignoring constraint")
25810 							.arg(cn->room)
25811 							.arg(text));*/
25812 						delete cn;
25813 						cn=nullptr;
25814 						return nullptr;
25815 						//goto corruptConstraintSpace;
25816 					}
25817 
25818 					assert(d<this->nDaysPerWeek);
25819 					xmlReadingLog+="    Day="+this->daysOfTheWeek[d]+"("+CustomFETString::number(i)+")"+"\n";
25820 				}
25821 				else if(xmlReader.name()==QString("Hour")){
25822 					QString text=xmlReader.readElementText();
25823 					for(h=0; h < this->nHoursPerDay; h++)
25824 						if(this->hoursOfTheDay[h]==text)
25825 							break;
25826 
25827 					if(h>=this->nHoursPerDay){
25828 						xmlReader.raiseError(tr("Hour %1 is inexistent").arg(text));
25829 						/*RulesReconcilableMessage::information(parent, tr("FET information"),
25830 							tr("Constraint RoomNotAvailableTimes hour corrupt for room %1, hour %2 is inexistent ... ignoring constraint")
25831 							.arg(cn->room)
25832 							.arg(text));*/
25833 						delete cn;
25834 						cn=nullptr;
25835 						//goto corruptConstraintSpace;
25836 						return nullptr;
25837 					}
25838 
25839 					assert(h>=0 && h < this->nHoursPerDay);
25840 					xmlReadingLog+="    Hour="+this->hoursOfTheDay[h]+"\n";
25841 				}
25842 				else{
25843 					unrecognizedXmlTags.append(xmlReader.name().toString());
25844 					unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
25845 					unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
25846 
25847 					xmlReader.skipCurrentElement();
25848 					xmlReaderNumberOfUnrecognizedFields++;
25849 				}
25850 			}
25851 			i++;
25852 
25853 			cn->days.append(d);
25854 			cn->hours.append(h);
25855 
25856 			if(d==-1 || h==-1){
25857 				xmlReader.raiseError(tr("%1 is incorrect").arg("Not_Available_Time"));
25858 				delete cn;
25859 				cn=nullptr;
25860 				return nullptr;
25861 			}
25862 		}
25863 		else if(xmlReader.name()==QString("Room")){
25864 			QString text=xmlReader.readElementText();
25865 			cn->room=text;
25866 			xmlReadingLog+="    Read room name="+cn->room+"\n";
25867 		}
25868 		else if(xmlReader.name()==QString("Teacher")){
25869 			QString text=xmlReader.readElementText();
25870 			cn->teacherName=text;
25871 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
25872 		}
25873 		else{
25874 			unrecognizedXmlTags.append(xmlReader.name().toString());
25875 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
25876 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
25877 
25878 			xmlReader.skipCurrentElement();
25879 			xmlReaderNumberOfUnrecognizedFields++;
25880 		}
25881 	}
25882 	assert(i==cn->days.count() && i==cn->hours.count());
25883 	if(!(i==nNotAvailableSlots)){
25884 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Not_Available_Times").arg("Not_Available_Time"));
25885 		delete cn;
25886 		cn=nullptr;
25887 		return nullptr;
25888 	}
25889 	assert(i==nNotAvailableSlots);
25890 	return cn;
25891 }
25892 
readActivityPreferredRoom(QWidget * parent,QXmlStreamReader & xmlReader,FakeString & xmlReadingLog,bool & reportUnspecifiedPermanentlyLockedSpace)25893 SpaceConstraint* Rules::readActivityPreferredRoom(QWidget* parent, QXmlStreamReader& xmlReader, FakeString& xmlReadingLog,
25894 bool& reportUnspecifiedPermanentlyLockedSpace){
25895 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivityPreferredRoom"));
25896 	ConstraintActivityPreferredRoom* cn=new ConstraintActivityPreferredRoom();
25897 	cn->permanentlyLocked=false; //default
25898 	bool foundLocked=false;
25899 	int specifiedNumberOfRealRooms=0;
25900 	while(xmlReader.readNextStartElement()){
25901 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
25902 		if(xmlReader.name()==QString("Weight")){
25903 			//cn->weight=customFETStrToDouble(text);
25904 			xmlReader.skipCurrentElement();
25905 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
25906 			cn->weightPercentage=100;
25907 		}
25908 		else if(xmlReader.name()==QString("Weight_Percentage")){
25909 			QString text=xmlReader.readElementText();
25910 			cn->weightPercentage=customFETStrToDouble(text);
25911 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
25912 		}
25913 		else if(xmlReader.name()==QString("Active")){
25914 			QString text=xmlReader.readElementText();
25915 			if(text=="false"){
25916 				cn->active=false;
25917 			}
25918 		}
25919 		else if(xmlReader.name()==QString("Comments")){
25920 			QString text=xmlReader.readElementText();
25921 			cn->comments=text;
25922 		}
25923 		else if(xmlReader.name()==QString("Compulsory")){
25924 			QString text=xmlReader.readElementText();
25925 			if(text=="yes"){
25926 				//cn->compulsory=true;
25927 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
25928 				cn->weightPercentage=100;
25929 			}
25930 			else{
25931 				//cn->compulsory=false;
25932 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
25933 				cn->weightPercentage=0;
25934 			}
25935 		}
25936 		else if(xmlReader.name()==QString("Permanently_Locked")){
25937 			QString text=xmlReader.readElementText();
25938 			if(text=="true" || text=="1" || text=="yes"){
25939 				xmlReadingLog+="    Permanently locked\n";
25940 				cn->permanentlyLocked=true;
25941 			}
25942 			else{
25943 				if(!(text=="no" || text=="false" || text=="0")){
25944 					RulesReconcilableMessage::warning(parent, tr("FET warning"),
25945 						tr("Found constraint activity preferred room with tag permanently locked"
25946 						" which is not 'true', 'false', 'yes', 'no', '1' or '0'."
25947 						" The tag will be considered false",
25948 						"Instructions for translators: please leave the 'true', 'false', 'yes' and 'no' fields untranslated, as they are in English"));
25949 				}
25950 				//assert(text=="false" || text=="0" || text=="no");
25951 				xmlReadingLog+="    Not permanently locked\n";
25952 				cn->permanentlyLocked=false;
25953 			}
25954 			foundLocked=true;
25955 		}
25956 
25957 		/*if(xmlReader.name()==QString("Weight")){
25958 			cn->weight=customFETStrToDouble(text);
25959 			xmlReadingLog+="    Adding weight="+CustomFETString::number(cn->weight)+"\n";
25960 		}
25961 		else if(xmlReader.name()==QString("Compulsory")){
25962 			if(text=="yes"){
25963 				cn->compulsory=true;
25964 				xmlReadingLog+="    Current constraint is compulsory\n";
25965 			}
25966 			else{
25967 				cn->compulsory=false;
25968 				xmlReadingLog+="    Current constraint is not compulsory\n";
25969 			}
25970 		}*/
25971 		else if(xmlReader.name()==QString("Activity_Id")){
25972 			QString text=xmlReader.readElementText();
25973 			cn->activityId=text.toInt();
25974 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activityId)+"\n";
25975 		}
25976 		else if(xmlReader.name()==QString("Room")){
25977 			QString text=xmlReader.readElementText();
25978 			cn->roomName=text;
25979 			xmlReadingLog+="    Read room="+text+"\n";
25980 		}
25981 		else if(xmlReader.name()==QString("Number_of_Real_Rooms")){
25982 			QString text=xmlReader.readElementText();
25983 			specifiedNumberOfRealRooms=text.toInt();
25984 			xmlReadingLog+="    Read number of real rooms="+CustomFETString::number(specifiedNumberOfRealRooms)+"\n";
25985 		}
25986 		else if(xmlReader.name()==QString("Real_Room")){
25987 			QString text=xmlReader.readElementText();
25988 			cn->preferredRealRoomsNames.append(text);
25989 			xmlReadingLog+="    Read real room="+text+"\n";
25990 		}
25991 		else{
25992 			unrecognizedXmlTags.append(xmlReader.name().toString());
25993 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
25994 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
25995 
25996 			xmlReader.skipCurrentElement();
25997 			xmlReaderNumberOfUnrecognizedFields++;
25998 		}
25999 	}
26000 
26001 	//Might be slow, so I deactivated this check.
26002 	//To add it again, initialize specifiedNumberOfRealRooms with -1 in the beginning.
26003 	/*int r=gt.rules.searchRoom(cn->roomName);
26004 	if(r>=0){
26005 		if(gt.rules.roomsList[r]->isVirtual){
26006 			if(specifiedNumberOfRealRooms==-1){
26007 				xmlReader.raiseError(tr("Argument %1 missing in constraint.").arg("Number_of_Real_Rooms"));
26008 				delete cn;
26009 				cn=nullptr;
26010 				return nullptr;
26011 			}
26012 		}
26013 	}*/
26014 
26015 	if(cn->preferredRealRoomsNames.count()!=specifiedNumberOfRealRooms){
26016 		xmlReader.raiseError(tr("The specified number of real rooms is not equal to the read number of real rooms in constraint."));
26017 		delete cn;
26018 		cn=nullptr;
26019 		return nullptr;
26020 	}
26021 
26022 	if(!foundLocked && reportUnspecifiedPermanentlyLockedSpace){
26023 		int t=RulesReconcilableMessage::information(parent, tr("FET information"),
26024 			tr("Found constraint activity preferred room, with unspecified tag"
26025 			" 'permanently locked' - this tag will be set to 'false' by default. You can always modify it"
26026 			" by editing the constraint in the 'Data' menu")+"\n\n"
26027 			+tr("Explanation: starting with version 5.8.0 (January 2009), the constraint"
26028 			" activity preferred room has"
26029 			" a new tag, 'permanently locked' (true or false)."
26030 			" It is recommended to make the tag 'permanently locked' true for the constraints you"
26031 			" need to be not modifiable from the 'Timetable' menu"
26032 			" and leave this tag false for the constraints you need to be modifiable from the 'Timetable' menu"
26033 			" (the 'permanently locked' tag can be modified by editing the constraint from the 'Data' menu)."
26034 			" This way, when viewing the timetable"
26035 			" and locking/unlocking some activities, you will not unlock the constraints which"
26036 			" need to be locked all the time."
26037 			),
26038 			tr("Skip rest"), tr("See next"), QString(), 1, 0 );
26039 		if(t==0)
26040 			reportUnspecifiedPermanentlyLockedSpace=false;
26041 	}
26042 
26043 	return cn;
26044 }
26045 
readActivityPreferredRooms(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)26046 SpaceConstraint* Rules::readActivityPreferredRooms(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
26047 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivityPreferredRooms"));
26048 	int _n_preferred_rooms=0;
26049 	ConstraintActivityPreferredRooms* cn=new ConstraintActivityPreferredRooms();
26050 	while(xmlReader.readNextStartElement()){
26051 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
26052 		if(xmlReader.name()==QString("Weight")){
26053 			//cn->weight=customFETStrToDouble(text);
26054 			xmlReader.skipCurrentElement();
26055 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
26056 			cn->weightPercentage=100;
26057 		}
26058 		else if(xmlReader.name()==QString("Weight_Percentage")){
26059 			QString text=xmlReader.readElementText();
26060 			cn->weightPercentage=customFETStrToDouble(text);
26061 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
26062 		}
26063 		else if(xmlReader.name()==QString("Active")){
26064 			QString text=xmlReader.readElementText();
26065 			if(text=="false"){
26066 				cn->active=false;
26067 			}
26068 		}
26069 		else if(xmlReader.name()==QString("Comments")){
26070 			QString text=xmlReader.readElementText();
26071 			cn->comments=text;
26072 		}
26073 		else if(xmlReader.name()==QString("Compulsory")){
26074 			QString text=xmlReader.readElementText();
26075 			if(text=="yes"){
26076 				//cn->compulsory=true;
26077 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
26078 				cn->weightPercentage=100;
26079 			}
26080 			else{
26081 				//cn->compulsory=false;
26082 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
26083 				cn->weightPercentage=0;
26084 			}
26085 		}
26086 		/*if(xmlReader.name()==QString("Weight")){
26087 			cn->weight=customFETStrToDouble(text);
26088 			xmlReadingLog+="    Adding weight="+CustomFETString::number(cn->weight)+"\n";
26089 		}
26090 		else if(xmlReader.name()==QString("Compulsory")){
26091 			if(text=="yes"){
26092 				cn->compulsory=true;
26093 				xmlReadingLog+="    Current constraint is compulsory\n";
26094 			}
26095 			else{
26096 				cn->compulsory=false;
26097 				xmlReadingLog+="    Current constraint is not compulsory\n";
26098 			}
26099 		}*/
26100 		else if(xmlReader.name()==QString("Activity_Id")){
26101 			QString text=xmlReader.readElementText();
26102 			cn->activityId=text.toInt();
26103 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activityId)+"\n";
26104 		}
26105 		else if(xmlReader.name()==QString("Number_of_Preferred_Rooms")){
26106 			QString text=xmlReader.readElementText();
26107 			_n_preferred_rooms=text.toInt();
26108 			xmlReadingLog+="    Read number of preferred rooms: "+CustomFETString::number(_n_preferred_rooms)+"\n";
26109 			//assert(_n_preferred_rooms>=2);
26110 		}
26111 		else if(xmlReader.name()==QString("Preferred_Room")){
26112 			QString text=xmlReader.readElementText();
26113 			cn->roomsNames.append(text);
26114 			xmlReadingLog+="    Read room="+text+"\n";
26115 		}
26116 		else{
26117 			unrecognizedXmlTags.append(xmlReader.name().toString());
26118 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
26119 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
26120 
26121 			xmlReader.skipCurrentElement();
26122 			xmlReaderNumberOfUnrecognizedFields++;
26123 		}
26124 	}
26125 	if(!(_n_preferred_rooms==cn->roomsNames.count())){
26126 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Preferred_Rooms").arg("Preferred_Room"));
26127 		delete cn;
26128 		cn=nullptr;
26129 		return nullptr;
26130 	}
26131 	assert(_n_preferred_rooms==cn->roomsNames.count());
26132 	return cn;
26133 }
26134 
readSubjectPreferredRoom(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)26135 SpaceConstraint* Rules::readSubjectPreferredRoom(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
26136 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintSubjectPreferredRoom"));
26137 	ConstraintSubjectPreferredRoom* cn=new ConstraintSubjectPreferredRoom();
26138 	while(xmlReader.readNextStartElement()){
26139 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
26140 		if(xmlReader.name()==QString("Weight")){
26141 			//cn->weight=customFETStrToDouble(text);
26142 			xmlReader.skipCurrentElement();
26143 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
26144 			cn->weightPercentage=100;
26145 		}
26146 		else if(xmlReader.name()==QString("Weight_Percentage")){
26147 			QString text=xmlReader.readElementText();
26148 			cn->weightPercentage=customFETStrToDouble(text);
26149 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
26150 		}
26151 		else if(xmlReader.name()==QString("Active")){
26152 			QString text=xmlReader.readElementText();
26153 			if(text=="false"){
26154 				cn->active=false;
26155 			}
26156 		}
26157 		else if(xmlReader.name()==QString("Comments")){
26158 			QString text=xmlReader.readElementText();
26159 			cn->comments=text;
26160 		}
26161 		else if(xmlReader.name()==QString("Compulsory")){
26162 			QString text=xmlReader.readElementText();
26163 			if(text=="yes"){
26164 				//cn->compulsory=true;
26165 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
26166 				cn->weightPercentage=100;
26167 			}
26168 			else{
26169 				//cn->compulsory=false;
26170 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
26171 				cn->weightPercentage=0;
26172 			}
26173 		}
26174 		else if(xmlReader.name()==QString("Subject")){
26175 			QString text=xmlReader.readElementText();
26176 			cn->subjectName=text;
26177 			xmlReadingLog+="    Read subject="+cn->subjectName+"\n";
26178 		}
26179 		else if(xmlReader.name()==QString("Room")){
26180 			QString text=xmlReader.readElementText();
26181 			cn->roomName=text;
26182 			xmlReadingLog+="    Read room="+cn->roomName+"\n";
26183 		}
26184 		else{
26185 			unrecognizedXmlTags.append(xmlReader.name().toString());
26186 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
26187 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
26188 
26189 			xmlReader.skipCurrentElement();
26190 			xmlReaderNumberOfUnrecognizedFields++;
26191 		}
26192 	}
26193 	return cn;
26194 }
26195 
readSubjectPreferredRooms(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)26196 SpaceConstraint* Rules::readSubjectPreferredRooms(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
26197 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintSubjectPreferredRooms"));
26198 	int _n_preferred_rooms=0;
26199 	ConstraintSubjectPreferredRooms* cn=new ConstraintSubjectPreferredRooms();
26200 	while(xmlReader.readNextStartElement()){
26201 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
26202 		if(xmlReader.name()==QString("Weight")){
26203 			//cn->weight=customFETStrToDouble(text);
26204 			xmlReader.skipCurrentElement();
26205 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
26206 			cn->weightPercentage=100;
26207 		}
26208 		else if(xmlReader.name()==QString("Weight_Percentage")){
26209 			QString text=xmlReader.readElementText();
26210 			cn->weightPercentage=customFETStrToDouble(text);
26211 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
26212 		}
26213 		else if(xmlReader.name()==QString("Active")){
26214 			QString text=xmlReader.readElementText();
26215 			if(text=="false"){
26216 				cn->active=false;
26217 			}
26218 		}
26219 		else if(xmlReader.name()==QString("Comments")){
26220 			QString text=xmlReader.readElementText();
26221 			cn->comments=text;
26222 		}
26223 		else if(xmlReader.name()==QString("Compulsory")){
26224 			QString text=xmlReader.readElementText();
26225 			if(text=="yes"){
26226 				//cn->compulsory=true;
26227 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
26228 				cn->weightPercentage=100;
26229 			}
26230 			else{
26231 				//cn->compulsory=false;
26232 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
26233 				cn->weightPercentage=0;
26234 			}
26235 		}
26236 		else if(xmlReader.name()==QString("Subject")){
26237 			QString text=xmlReader.readElementText();
26238 			cn->subjectName=text;
26239 			xmlReadingLog+="    Read subject="+cn->subjectName+"\n";
26240 		}
26241 		else if(xmlReader.name()==QString("Number_of_Preferred_Rooms")){
26242 			QString text=xmlReader.readElementText();
26243 			_n_preferred_rooms=text.toInt();
26244 			xmlReadingLog+="    Read number of preferred rooms: "+CustomFETString::number(_n_preferred_rooms)+"\n";
26245 			//assert(_n_preferred_rooms>=2);
26246 		}
26247 		else if(xmlReader.name()==QString("Preferred_Room")){
26248 			QString text=xmlReader.readElementText();
26249 			cn->roomsNames.append(text);
26250 			xmlReadingLog+="    Read room="+text+"\n";
26251 		}
26252 		else{
26253 			unrecognizedXmlTags.append(xmlReader.name().toString());
26254 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
26255 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
26256 
26257 			xmlReader.skipCurrentElement();
26258 			xmlReaderNumberOfUnrecognizedFields++;
26259 		}
26260 	}
26261 	if(!(_n_preferred_rooms==cn->roomsNames.count())){
26262 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Preferred_Rooms").arg("Preferred_Room"));
26263 		delete cn;
26264 		cn=nullptr;
26265 		return nullptr;
26266 	}
26267 	assert(_n_preferred_rooms==cn->roomsNames.count());
26268 	return cn;
26269 }
26270 
readSubjectSubjectTagPreferredRoom(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)26271 SpaceConstraint* Rules::readSubjectSubjectTagPreferredRoom(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
26272 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintSubjectSubjectTagPreferredRoom"));
26273 	ConstraintSubjectActivityTagPreferredRoom* cn=new ConstraintSubjectActivityTagPreferredRoom();
26274 	while(xmlReader.readNextStartElement()){
26275 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
26276 		if(xmlReader.name()==QString("Weight")){
26277 			//cn->weight=customFETStrToDouble(text);
26278 			xmlReader.skipCurrentElement();
26279 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
26280 			cn->weightPercentage=100;
26281 		}
26282 		else if(xmlReader.name()==QString("Weight_Percentage")){
26283 			QString text=xmlReader.readElementText();
26284 			cn->weightPercentage=customFETStrToDouble(text);
26285 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
26286 		}
26287 		else if(xmlReader.name()==QString("Active")){
26288 			QString text=xmlReader.readElementText();
26289 			if(text=="false"){
26290 				cn->active=false;
26291 			}
26292 		}
26293 		else if(xmlReader.name()==QString("Comments")){
26294 			QString text=xmlReader.readElementText();
26295 			cn->comments=text;
26296 		}
26297 		else if(xmlReader.name()==QString("Compulsory")){
26298 			QString text=xmlReader.readElementText();
26299 			if(text=="yes"){
26300 				//cn->compulsory=true;
26301 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
26302 				cn->weightPercentage=100;
26303 			}
26304 			else{
26305 				//cn->compulsory=false;
26306 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
26307 				cn->weightPercentage=0;
26308 			}
26309 		}
26310 		else if(xmlReader.name()==QString("Subject")){
26311 			QString text=xmlReader.readElementText();
26312 			cn->subjectName=text;
26313 			xmlReadingLog+="    Read subject="+cn->subjectName+"\n";
26314 		}
26315 		else if(xmlReader.name()==QString("Subject_Tag")){
26316 			QString text=xmlReader.readElementText();
26317 			cn->activityTagName=text;
26318 			xmlReadingLog+="    Read activity tag="+cn->activityTagName+"\n";
26319 		}
26320 		else if(xmlReader.name()==QString("Room")){
26321 			QString text=xmlReader.readElementText();
26322 			cn->roomName=text;
26323 			xmlReadingLog+="    Read room="+cn->roomName+"\n";
26324 		}
26325 		else{
26326 			unrecognizedXmlTags.append(xmlReader.name().toString());
26327 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
26328 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
26329 
26330 			xmlReader.skipCurrentElement();
26331 			xmlReaderNumberOfUnrecognizedFields++;
26332 		}
26333 	}
26334 	return cn;
26335 }
26336 
readSubjectSubjectTagPreferredRooms(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)26337 SpaceConstraint* Rules::readSubjectSubjectTagPreferredRooms(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
26338 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintSubjectSubjectTagPreferredRooms"));
26339 	int _n_preferred_rooms=0;
26340 	ConstraintSubjectActivityTagPreferredRooms* cn=new ConstraintSubjectActivityTagPreferredRooms();
26341 	while(xmlReader.readNextStartElement()){
26342 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
26343 		if(xmlReader.name()==QString("Weight")){
26344 			//cn->weight=customFETStrToDouble(text);
26345 			xmlReader.skipCurrentElement();
26346 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
26347 			cn->weightPercentage=100;
26348 		}
26349 		else if(xmlReader.name()==QString("Weight_Percentage")){
26350 			QString text=xmlReader.readElementText();
26351 			cn->weightPercentage=customFETStrToDouble(text);
26352 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
26353 		}
26354 		else if(xmlReader.name()==QString("Active")){
26355 			QString text=xmlReader.readElementText();
26356 			if(text=="false"){
26357 				cn->active=false;
26358 			}
26359 		}
26360 		else if(xmlReader.name()==QString("Comments")){
26361 			QString text=xmlReader.readElementText();
26362 			cn->comments=text;
26363 		}
26364 		else if(xmlReader.name()==QString("Compulsory")){
26365 			QString text=xmlReader.readElementText();
26366 			if(text=="yes"){
26367 				//cn->compulsory=true;
26368 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
26369 				cn->weightPercentage=100;
26370 			}
26371 			else{
26372 				//cn->compulsory=false;
26373 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
26374 				cn->weightPercentage=0;
26375 			}
26376 		}
26377 		else if(xmlReader.name()==QString("Subject")){
26378 			QString text=xmlReader.readElementText();
26379 			cn->subjectName=text;
26380 			xmlReadingLog+="    Read subject="+cn->subjectName+"\n";
26381 		}
26382 		else if(xmlReader.name()==QString("Subject_Tag")){
26383 			QString text=xmlReader.readElementText();
26384 			cn->activityTagName=text;
26385 			xmlReadingLog+="    Read activity tag="+cn->activityTagName+"\n";
26386 		}
26387 		else if(xmlReader.name()==QString("Number_of_Preferred_Rooms")){
26388 			QString text=xmlReader.readElementText();
26389 			_n_preferred_rooms=text.toInt();
26390 			xmlReadingLog+="    Read number of preferred rooms: "+CustomFETString::number(_n_preferred_rooms)+"\n";
26391 			//assert(_n_preferred_rooms>=2);
26392 		}
26393 		else if(xmlReader.name()==QString("Preferred_Room")){
26394 			QString text=xmlReader.readElementText();
26395 			cn->roomsNames.append(text);
26396 			xmlReadingLog+="    Read room="+text+"\n";
26397 		}
26398 		else{
26399 			unrecognizedXmlTags.append(xmlReader.name().toString());
26400 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
26401 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
26402 
26403 			xmlReader.skipCurrentElement();
26404 			xmlReaderNumberOfUnrecognizedFields++;
26405 		}
26406 	}
26407 	if(!(_n_preferred_rooms==cn->roomsNames.count())){
26408 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Preferred_Rooms").arg("Preferred_Room"));
26409 		delete cn;
26410 		cn=nullptr;
26411 		return nullptr;
26412 	}
26413 	assert(_n_preferred_rooms==cn->roomsNames.count());
26414 	return cn;
26415 }
26416 
readSubjectActivityTagPreferredRoom(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)26417 SpaceConstraint* Rules::readSubjectActivityTagPreferredRoom(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
26418 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintSubjectActivityTagPreferredRoom"));
26419 	ConstraintSubjectActivityTagPreferredRoom* cn=new ConstraintSubjectActivityTagPreferredRoom();
26420 	while(xmlReader.readNextStartElement()){
26421 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
26422 		if(xmlReader.name()==QString("Weight")){
26423 			//cn->weight=customFETStrToDouble(text);
26424 			xmlReader.skipCurrentElement();
26425 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
26426 			cn->weightPercentage=100;
26427 		}
26428 		else if(xmlReader.name()==QString("Weight_Percentage")){
26429 			QString text=xmlReader.readElementText();
26430 			cn->weightPercentage=customFETStrToDouble(text);
26431 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
26432 		}
26433 		else if(xmlReader.name()==QString("Active")){
26434 			QString text=xmlReader.readElementText();
26435 			if(text=="false"){
26436 				cn->active=false;
26437 			}
26438 		}
26439 		else if(xmlReader.name()==QString("Comments")){
26440 			QString text=xmlReader.readElementText();
26441 			cn->comments=text;
26442 		}
26443 		else if(xmlReader.name()==QString("Compulsory")){
26444 			QString text=xmlReader.readElementText();
26445 			if(text=="yes"){
26446 				//cn->compulsory=true;
26447 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
26448 				cn->weightPercentage=100;
26449 			}
26450 			else{
26451 				//cn->compulsory=false;
26452 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
26453 				cn->weightPercentage=0;
26454 			}
26455 		}
26456 		else if(xmlReader.name()==QString("Subject")){
26457 			QString text=xmlReader.readElementText();
26458 			cn->subjectName=text;
26459 			xmlReadingLog+="    Read subject="+cn->subjectName+"\n";
26460 		}
26461 		else if(xmlReader.name()==QString("Activity_Tag")){
26462 			QString text=xmlReader.readElementText();
26463 			cn->activityTagName=text;
26464 			xmlReadingLog+="    Read activity tag="+cn->activityTagName+"\n";
26465 		}
26466 		else if(xmlReader.name()==QString("Room")){
26467 			QString text=xmlReader.readElementText();
26468 			cn->roomName=text;
26469 			xmlReadingLog+="    Read room="+cn->roomName+"\n";
26470 		}
26471 		else{
26472 			unrecognizedXmlTags.append(xmlReader.name().toString());
26473 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
26474 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
26475 
26476 			xmlReader.skipCurrentElement();
26477 			xmlReaderNumberOfUnrecognizedFields++;
26478 		}
26479 	}
26480 	return cn;
26481 }
26482 
readSubjectActivityTagPreferredRooms(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)26483 SpaceConstraint* Rules::readSubjectActivityTagPreferredRooms(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
26484 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintSubjectActivityTagPreferredRooms"));
26485 	int _n_preferred_rooms=0;
26486 	ConstraintSubjectActivityTagPreferredRooms* cn=new ConstraintSubjectActivityTagPreferredRooms();
26487 	while(xmlReader.readNextStartElement()){
26488 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
26489 		if(xmlReader.name()==QString("Weight")){
26490 			//cn->weight=customFETStrToDouble(text);
26491 			xmlReader.skipCurrentElement();
26492 			xmlReadingLog+="    Ignoring old tag - weight - making weight percentage=100\n";
26493 			cn->weightPercentage=100;
26494 		}
26495 		else if(xmlReader.name()==QString("Weight_Percentage")){
26496 			QString text=xmlReader.readElementText();
26497 			cn->weightPercentage=customFETStrToDouble(text);
26498 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
26499 		}
26500 		else if(xmlReader.name()==QString("Active")){
26501 			QString text=xmlReader.readElementText();
26502 			if(text=="false"){
26503 				cn->active=false;
26504 			}
26505 		}
26506 		else if(xmlReader.name()==QString("Comments")){
26507 			QString text=xmlReader.readElementText();
26508 			cn->comments=text;
26509 		}
26510 		else if(xmlReader.name()==QString("Compulsory")){
26511 			QString text=xmlReader.readElementText();
26512 			if(text=="yes"){
26513 				//cn->compulsory=true;
26514 				xmlReadingLog+="    Ignoring old tag - Current constraint is compulsory\n";
26515 				cn->weightPercentage=100;
26516 			}
26517 			else{
26518 				//cn->compulsory=false;
26519 				xmlReadingLog+="    Old tag - current constraint is not compulsory - making weightPercentage=0%\n";
26520 				cn->weightPercentage=0;
26521 			}
26522 		}
26523 		else if(xmlReader.name()==QString("Subject")){
26524 			QString text=xmlReader.readElementText();
26525 			cn->subjectName=text;
26526 			xmlReadingLog+="    Read subject="+cn->subjectName+"\n";
26527 		}
26528 		else if(xmlReader.name()==QString("Activity_Tag")){
26529 			QString text=xmlReader.readElementText();
26530 			cn->activityTagName=text;
26531 			xmlReadingLog+="    Read activity tag="+cn->activityTagName+"\n";
26532 		}
26533 		else if(xmlReader.name()==QString("Number_of_Preferred_Rooms")){
26534 			QString text=xmlReader.readElementText();
26535 			_n_preferred_rooms=text.toInt();
26536 			xmlReadingLog+="    Read number of preferred rooms: "+CustomFETString::number(_n_preferred_rooms)+"\n";
26537 			//assert(_n_preferred_rooms>=2);
26538 		}
26539 		else if(xmlReader.name()==QString("Preferred_Room")){
26540 			QString text=xmlReader.readElementText();
26541 			cn->roomsNames.append(text);
26542 			xmlReadingLog+="    Read room="+text+"\n";
26543 		}
26544 		else{
26545 			unrecognizedXmlTags.append(xmlReader.name().toString());
26546 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
26547 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
26548 
26549 			xmlReader.skipCurrentElement();
26550 			xmlReaderNumberOfUnrecognizedFields++;
26551 		}
26552 	}
26553 	if(!(_n_preferred_rooms==cn->roomsNames.count())){
26554 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Preferred_Rooms").arg("Preferred_Room"));
26555 		delete cn;
26556 		cn=nullptr;
26557 		return nullptr;
26558 	}
26559 	assert(_n_preferred_rooms==cn->roomsNames.count());
26560 	return cn;
26561 }
26562 
readActivityTagPreferredRoom(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)26563 SpaceConstraint* Rules::readActivityTagPreferredRoom(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
26564 	//added 6 apr 2009
26565 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivityTagPreferredRoom"));
26566 	ConstraintActivityTagPreferredRoom* cn=new ConstraintActivityTagPreferredRoom();
26567 	while(xmlReader.readNextStartElement()){
26568 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
26569 		if(xmlReader.name()==QString("Weight_Percentage")){
26570 			QString text=xmlReader.readElementText();
26571 			cn->weightPercentage=customFETStrToDouble(text);
26572 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
26573 		}
26574 		else if(xmlReader.name()==QString("Active")){
26575 			QString text=xmlReader.readElementText();
26576 			if(text=="false"){
26577 				cn->active=false;
26578 			}
26579 		}
26580 		else if(xmlReader.name()==QString("Comments")){
26581 			QString text=xmlReader.readElementText();
26582 			cn->comments=text;
26583 		}
26584 		else if(xmlReader.name()==QString("Activity_Tag")){
26585 			QString text=xmlReader.readElementText();
26586 			cn->activityTagName=text;
26587 			xmlReadingLog+="    Read activity tag="+cn->activityTagName+"\n";
26588 		}
26589 		else if(xmlReader.name()==QString("Room")){
26590 			QString text=xmlReader.readElementText();
26591 			cn->roomName=text;
26592 			xmlReadingLog+="    Read room="+cn->roomName+"\n";
26593 		}
26594 		else{
26595 			unrecognizedXmlTags.append(xmlReader.name().toString());
26596 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
26597 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
26598 
26599 			xmlReader.skipCurrentElement();
26600 			xmlReaderNumberOfUnrecognizedFields++;
26601 		}
26602 	}
26603 	return cn;
26604 }
26605 
readActivityTagPreferredRooms(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)26606 SpaceConstraint* Rules::readActivityTagPreferredRooms(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
26607 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivityTagPreferredRooms"));
26608 	int _n_preferred_rooms=0;
26609 	ConstraintActivityTagPreferredRooms* cn=new ConstraintActivityTagPreferredRooms();
26610 	while(xmlReader.readNextStartElement()){
26611 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
26612 		if(xmlReader.name()==QString("Weight_Percentage")){
26613 			QString text=xmlReader.readElementText();
26614 			cn->weightPercentage=customFETStrToDouble(text);
26615 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
26616 		}
26617 		else if(xmlReader.name()==QString("Active")){
26618 			QString text=xmlReader.readElementText();
26619 			if(text=="false"){
26620 				cn->active=false;
26621 			}
26622 		}
26623 		else if(xmlReader.name()==QString("Comments")){
26624 			QString text=xmlReader.readElementText();
26625 			cn->comments=text;
26626 		}
26627 		else if(xmlReader.name()==QString("Activity_Tag")){
26628 			QString text=xmlReader.readElementText();
26629 			cn->activityTagName=text;
26630 			xmlReadingLog+="    Read activity tag="+cn->activityTagName+"\n";
26631 		}
26632 		else if(xmlReader.name()==QString("Number_of_Preferred_Rooms")){
26633 			QString text=xmlReader.readElementText();
26634 			_n_preferred_rooms=text.toInt();
26635 			xmlReadingLog+="    Read number of preferred rooms: "+CustomFETString::number(_n_preferred_rooms)+"\n";
26636 			//assert(_n_preferred_rooms>=2);
26637 		}
26638 		else if(xmlReader.name()==QString("Preferred_Room")){
26639 			QString text=xmlReader.readElementText();
26640 			cn->roomsNames.append(text);
26641 			xmlReadingLog+="    Read room="+text+"\n";
26642 		}
26643 		else{
26644 			unrecognizedXmlTags.append(xmlReader.name().toString());
26645 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
26646 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
26647 
26648 			xmlReader.skipCurrentElement();
26649 			xmlReaderNumberOfUnrecognizedFields++;
26650 		}
26651 	}
26652 	if(!(_n_preferred_rooms==cn->roomsNames.count())){
26653 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Preferred_Rooms").arg("Preferred_Room"));
26654 		delete cn;
26655 		cn=nullptr;
26656 		return nullptr;
26657 	}
26658 	assert(_n_preferred_rooms==cn->roomsNames.count());
26659 	return cn;
26660 }
26661 
readStudentsSetHomeRoom(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)26662 SpaceConstraint* Rules::readStudentsSetHomeRoom(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
26663 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetHomeRoom"));
26664 	ConstraintStudentsSetHomeRoom* cn=new ConstraintStudentsSetHomeRoom();
26665 	while(xmlReader.readNextStartElement()){
26666 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
26667 		if(xmlReader.name()==QString("Weight_Percentage")){
26668 			QString text=xmlReader.readElementText();
26669 			cn->weightPercentage=customFETStrToDouble(text);
26670 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
26671 		}
26672 		else if(xmlReader.name()==QString("Active")){
26673 			QString text=xmlReader.readElementText();
26674 			if(text=="false"){
26675 				cn->active=false;
26676 			}
26677 		}
26678 		else if(xmlReader.name()==QString("Comments")){
26679 			QString text=xmlReader.readElementText();
26680 			cn->comments=text;
26681 		}
26682 		else if(xmlReader.name()==QString("Students")){
26683 			QString text=xmlReader.readElementText();
26684 			cn->studentsName=text;
26685 			xmlReadingLog+="    Read students="+cn->studentsName+"\n";
26686 		}
26687 		else if(xmlReader.name()==QString("Room")){
26688 			QString text=xmlReader.readElementText();
26689 			cn->roomName=text;
26690 			xmlReadingLog+="    Read room="+cn->roomName+"\n";
26691 		}
26692 		else{
26693 			unrecognizedXmlTags.append(xmlReader.name().toString());
26694 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
26695 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
26696 
26697 			xmlReader.skipCurrentElement();
26698 			xmlReaderNumberOfUnrecognizedFields++;
26699 		}
26700 	}
26701 	return cn;
26702 }
26703 
readStudentsSetHomeRooms(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)26704 SpaceConstraint* Rules::readStudentsSetHomeRooms(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
26705 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetHomeRooms"));
26706 	int _n_preferred_rooms=0;
26707 	ConstraintStudentsSetHomeRooms* cn=new ConstraintStudentsSetHomeRooms();
26708 	while(xmlReader.readNextStartElement()){
26709 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
26710 		if(xmlReader.name()==QString("Weight_Percentage")){
26711 			QString text=xmlReader.readElementText();
26712 			cn->weightPercentage=customFETStrToDouble(text);
26713 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
26714 		}
26715 		else if(xmlReader.name()==QString("Active")){
26716 			QString text=xmlReader.readElementText();
26717 			if(text=="false"){
26718 				cn->active=false;
26719 			}
26720 		}
26721 		else if(xmlReader.name()==QString("Comments")){
26722 			QString text=xmlReader.readElementText();
26723 			cn->comments=text;
26724 		}
26725 		else if(xmlReader.name()==QString("Students")){
26726 			QString text=xmlReader.readElementText();
26727 			cn->studentsName=text;
26728 			xmlReadingLog+="    Read students="+cn->studentsName+"\n";
26729 		}
26730 		else if(xmlReader.name()==QString("Number_of_Preferred_Rooms")){
26731 			QString text=xmlReader.readElementText();
26732 			_n_preferred_rooms=text.toInt();
26733 			xmlReadingLog+="    Read number of preferred rooms: "+CustomFETString::number(_n_preferred_rooms)+"\n";
26734 			//assert(_n_preferred_rooms>=2);
26735 		}
26736 		else if(xmlReader.name()==QString("Preferred_Room")){
26737 			QString text=xmlReader.readElementText();
26738 			cn->roomsNames.append(text);
26739 			xmlReadingLog+="    Read room="+text+"\n";
26740 		}
26741 		else{
26742 			unrecognizedXmlTags.append(xmlReader.name().toString());
26743 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
26744 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
26745 
26746 			xmlReader.skipCurrentElement();
26747 			xmlReaderNumberOfUnrecognizedFields++;
26748 		}
26749 	}
26750 	if(!(_n_preferred_rooms==cn->roomsNames.count())){
26751 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Preferred_Rooms").arg("Preferred_Room"));
26752 		delete cn;
26753 		cn=nullptr;
26754 		return nullptr;
26755 	}
26756 	assert(_n_preferred_rooms==cn->roomsNames.count());
26757 	return cn;
26758 }
26759 
readTeacherHomeRoom(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)26760 SpaceConstraint* Rules::readTeacherHomeRoom(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
26761 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherHomeRoom"));
26762 	ConstraintTeacherHomeRoom* cn=new ConstraintTeacherHomeRoom();
26763 	while(xmlReader.readNextStartElement()){
26764 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
26765 		if(xmlReader.name()==QString("Weight_Percentage")){
26766 			QString text=xmlReader.readElementText();
26767 			cn->weightPercentage=customFETStrToDouble(text);
26768 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
26769 		}
26770 		else if(xmlReader.name()==QString("Active")){
26771 			QString text=xmlReader.readElementText();
26772 			if(text=="false"){
26773 				cn->active=false;
26774 			}
26775 		}
26776 		else if(xmlReader.name()==QString("Comments")){
26777 			QString text=xmlReader.readElementText();
26778 			cn->comments=text;
26779 		}
26780 		else if(xmlReader.name()==QString("Teacher")){
26781 			QString text=xmlReader.readElementText();
26782 			cn->teacherName=text;
26783 			xmlReadingLog+="    Read teacher="+cn->teacherName+"\n";
26784 		}
26785 		else if(xmlReader.name()==QString("Room")){
26786 			QString text=xmlReader.readElementText();
26787 			cn->roomName=text;
26788 			xmlReadingLog+="    Read room="+cn->roomName+"\n";
26789 		}
26790 		else{
26791 			unrecognizedXmlTags.append(xmlReader.name().toString());
26792 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
26793 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
26794 
26795 			xmlReader.skipCurrentElement();
26796 			xmlReaderNumberOfUnrecognizedFields++;
26797 		}
26798 	}
26799 	return cn;
26800 }
26801 
readTeacherHomeRooms(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)26802 SpaceConstraint* Rules::readTeacherHomeRooms(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
26803 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherHomeRooms"));
26804 	int _n_preferred_rooms=0;
26805 	ConstraintTeacherHomeRooms* cn=new ConstraintTeacherHomeRooms();
26806 	while(xmlReader.readNextStartElement()){
26807 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
26808 		if(xmlReader.name()==QString("Weight_Percentage")){
26809 			QString text=xmlReader.readElementText();
26810 			cn->weightPercentage=customFETStrToDouble(text);
26811 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
26812 		}
26813 		else if(xmlReader.name()==QString("Active")){
26814 			QString text=xmlReader.readElementText();
26815 			if(text=="false"){
26816 				cn->active=false;
26817 			}
26818 		}
26819 		else if(xmlReader.name()==QString("Comments")){
26820 			QString text=xmlReader.readElementText();
26821 			cn->comments=text;
26822 		}
26823 		else if(xmlReader.name()==QString("Teacher")){
26824 			QString text=xmlReader.readElementText();
26825 			cn->teacherName=text;
26826 			xmlReadingLog+="    Read teacher="+cn->teacherName+"\n";
26827 		}
26828 		else if(xmlReader.name()==QString("Number_of_Preferred_Rooms")){
26829 			QString text=xmlReader.readElementText();
26830 			_n_preferred_rooms=text.toInt();
26831 			xmlReadingLog+="    Read number of preferred rooms: "+CustomFETString::number(_n_preferred_rooms)+"\n";
26832 			//assert(_n_preferred_rooms>=2);
26833 		}
26834 		else if(xmlReader.name()==QString("Preferred_Room")){
26835 			QString text=xmlReader.readElementText();
26836 			cn->roomsNames.append(text);
26837 			xmlReadingLog+="    Read room="+text+"\n";
26838 		}
26839 		else{
26840 			unrecognizedXmlTags.append(xmlReader.name().toString());
26841 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
26842 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
26843 
26844 			xmlReader.skipCurrentElement();
26845 			xmlReaderNumberOfUnrecognizedFields++;
26846 		}
26847 	}
26848 	if(!(_n_preferred_rooms==cn->roomsNames.count())){
26849 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Preferred_Rooms").arg("Preferred_Room"));
26850 		delete cn;
26851 		cn=nullptr;
26852 		return nullptr;
26853 	}
26854 	assert(_n_preferred_rooms==cn->roomsNames.count());
26855 	return cn;
26856 }
26857 
readTeacherMaxBuildingChangesPerDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)26858 SpaceConstraint* Rules::readTeacherMaxBuildingChangesPerDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
26859 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxBuildingChangesPerDay"));
26860 	ConstraintTeacherMaxBuildingChangesPerDay* cn=new ConstraintTeacherMaxBuildingChangesPerDay();
26861 	while(xmlReader.readNextStartElement()){
26862 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
26863 		if(xmlReader.name()==QString("Weight_Percentage")){
26864 			QString text=xmlReader.readElementText();
26865 			cn->weightPercentage=customFETStrToDouble(text);
26866 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
26867 		}
26868 		else if(xmlReader.name()==QString("Active")){
26869 			QString text=xmlReader.readElementText();
26870 			if(text=="false"){
26871 				cn->active=false;
26872 			}
26873 		}
26874 		else if(xmlReader.name()==QString("Comments")){
26875 			QString text=xmlReader.readElementText();
26876 			cn->comments=text;
26877 		}
26878 		else if(xmlReader.name()==QString("Teacher")){
26879 			QString text=xmlReader.readElementText();
26880 			cn->teacherName=text;
26881 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
26882 		}
26883 		else if(xmlReader.name()==QString("Max_Building_Changes_Per_Day")){
26884 			QString text=xmlReader.readElementText();
26885 			cn->maxBuildingChangesPerDay=text.toInt();
26886 			xmlReadingLog+="    Max. building changes per day="+CustomFETString::number(cn->maxBuildingChangesPerDay)+"\n";
26887 		}
26888 		else{
26889 			unrecognizedXmlTags.append(xmlReader.name().toString());
26890 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
26891 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
26892 
26893 			xmlReader.skipCurrentElement();
26894 			xmlReaderNumberOfUnrecognizedFields++;
26895 		}
26896 	}
26897 	return cn;
26898 }
26899 
readTeachersMaxBuildingChangesPerDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)26900 SpaceConstraint* Rules::readTeachersMaxBuildingChangesPerDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
26901 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxBuildingChangesPerDay"));
26902 	ConstraintTeachersMaxBuildingChangesPerDay* cn=new ConstraintTeachersMaxBuildingChangesPerDay();
26903 	while(xmlReader.readNextStartElement()){
26904 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
26905 		if(xmlReader.name()==QString("Weight_Percentage")){
26906 			QString text=xmlReader.readElementText();
26907 			cn->weightPercentage=customFETStrToDouble(text);
26908 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
26909 		}
26910 		else if(xmlReader.name()==QString("Active")){
26911 			QString text=xmlReader.readElementText();
26912 			if(text=="false"){
26913 				cn->active=false;
26914 			}
26915 		}
26916 		else if(xmlReader.name()==QString("Comments")){
26917 			QString text=xmlReader.readElementText();
26918 			cn->comments=text;
26919 		}
26920 		else if(xmlReader.name()==QString("Max_Building_Changes_Per_Day")){
26921 			QString text=xmlReader.readElementText();
26922 			cn->maxBuildingChangesPerDay=text.toInt();
26923 			xmlReadingLog+="    Max. building changes per day="+CustomFETString::number(cn->maxBuildingChangesPerDay)+"\n";
26924 		}
26925 		else{
26926 			unrecognizedXmlTags.append(xmlReader.name().toString());
26927 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
26928 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
26929 
26930 			xmlReader.skipCurrentElement();
26931 			xmlReaderNumberOfUnrecognizedFields++;
26932 		}
26933 	}
26934 	return cn;
26935 }
26936 
readTeacherMaxBuildingChangesPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)26937 SpaceConstraint* Rules::readTeacherMaxBuildingChangesPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
26938 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxBuildingChangesPerWeek"));
26939 	ConstraintTeacherMaxBuildingChangesPerWeek* cn=new ConstraintTeacherMaxBuildingChangesPerWeek();
26940 	while(xmlReader.readNextStartElement()){
26941 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
26942 		if(xmlReader.name()==QString("Weight_Percentage")){
26943 			QString text=xmlReader.readElementText();
26944 			cn->weightPercentage=customFETStrToDouble(text);
26945 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
26946 		}
26947 		else if(xmlReader.name()==QString("Active")){
26948 			QString text=xmlReader.readElementText();
26949 			if(text=="false"){
26950 				cn->active=false;
26951 			}
26952 		}
26953 		else if(xmlReader.name()==QString("Comments")){
26954 			QString text=xmlReader.readElementText();
26955 			cn->comments=text;
26956 		}
26957 		else if(xmlReader.name()==QString("Teacher")){
26958 			QString text=xmlReader.readElementText();
26959 			cn->teacherName=text;
26960 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
26961 		}
26962 		else if(xmlReader.name()==QString("Max_Building_Changes_Per_Week")){
26963 			QString text=xmlReader.readElementText();
26964 			cn->maxBuildingChangesPerWeek=text.toInt();
26965 			xmlReadingLog+="    Max. building changes per week="+CustomFETString::number(cn->maxBuildingChangesPerWeek)+"\n";
26966 		}
26967 		else{
26968 			unrecognizedXmlTags.append(xmlReader.name().toString());
26969 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
26970 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
26971 
26972 			xmlReader.skipCurrentElement();
26973 			xmlReaderNumberOfUnrecognizedFields++;
26974 		}
26975 	}
26976 	return cn;
26977 }
26978 
readTeachersMaxBuildingChangesPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)26979 SpaceConstraint* Rules::readTeachersMaxBuildingChangesPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
26980 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxBuildingChangesPerWeek"));
26981 	ConstraintTeachersMaxBuildingChangesPerWeek* cn=new ConstraintTeachersMaxBuildingChangesPerWeek();
26982 	while(xmlReader.readNextStartElement()){
26983 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
26984 		if(xmlReader.name()==QString("Weight_Percentage")){
26985 			QString text=xmlReader.readElementText();
26986 			cn->weightPercentage=customFETStrToDouble(text);
26987 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
26988 		}
26989 		else if(xmlReader.name()==QString("Active")){
26990 			QString text=xmlReader.readElementText();
26991 			if(text=="false"){
26992 				cn->active=false;
26993 			}
26994 		}
26995 		else if(xmlReader.name()==QString("Comments")){
26996 			QString text=xmlReader.readElementText();
26997 			cn->comments=text;
26998 		}
26999 		else if(xmlReader.name()==QString("Max_Building_Changes_Per_Week")){
27000 			QString text=xmlReader.readElementText();
27001 			cn->maxBuildingChangesPerWeek=text.toInt();
27002 			xmlReadingLog+="    Max. building changes per week="+CustomFETString::number(cn->maxBuildingChangesPerWeek)+"\n";
27003 		}
27004 		else{
27005 			unrecognizedXmlTags.append(xmlReader.name().toString());
27006 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
27007 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
27008 
27009 			xmlReader.skipCurrentElement();
27010 			xmlReaderNumberOfUnrecognizedFields++;
27011 		}
27012 	}
27013 	return cn;
27014 }
27015 
readTeacherMinGapsBetweenBuildingChanges(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)27016 SpaceConstraint* Rules::readTeacherMinGapsBetweenBuildingChanges(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
27017 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMinGapsBetweenBuildingChanges"));
27018 	ConstraintTeacherMinGapsBetweenBuildingChanges* cn=new ConstraintTeacherMinGapsBetweenBuildingChanges();
27019 	while(xmlReader.readNextStartElement()){
27020 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
27021 		if(xmlReader.name()==QString("Weight_Percentage")){
27022 			QString text=xmlReader.readElementText();
27023 			cn->weightPercentage=customFETStrToDouble(text);
27024 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
27025 		}
27026 		else if(xmlReader.name()==QString("Active")){
27027 			QString text=xmlReader.readElementText();
27028 			if(text=="false"){
27029 				cn->active=false;
27030 			}
27031 		}
27032 		else if(xmlReader.name()==QString("Comments")){
27033 			QString text=xmlReader.readElementText();
27034 			cn->comments=text;
27035 		}
27036 		else if(xmlReader.name()==QString("Teacher")){
27037 			QString text=xmlReader.readElementText();
27038 			cn->teacherName=text;
27039 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
27040 		}
27041 		else if(xmlReader.name()==QString("Min_Gaps_Between_Building_Changes")){
27042 			QString text=xmlReader.readElementText();
27043 			cn->minGapsBetweenBuildingChanges=text.toInt();
27044 			xmlReadingLog+="    Min gaps between building changes="+CustomFETString::number(cn->minGapsBetweenBuildingChanges)+"\n";
27045 		}
27046 		else{
27047 			unrecognizedXmlTags.append(xmlReader.name().toString());
27048 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
27049 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
27050 
27051 			xmlReader.skipCurrentElement();
27052 			xmlReaderNumberOfUnrecognizedFields++;
27053 		}
27054 	}
27055 	return cn;
27056 }
27057 
readTeachersMinGapsBetweenBuildingChanges(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)27058 SpaceConstraint* Rules::readTeachersMinGapsBetweenBuildingChanges(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
27059 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMinGapsBetweenBuildingChanges"));
27060 	ConstraintTeachersMinGapsBetweenBuildingChanges* cn=new ConstraintTeachersMinGapsBetweenBuildingChanges();
27061 	while(xmlReader.readNextStartElement()){
27062 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
27063 		if(xmlReader.name()==QString("Weight_Percentage")){
27064 			QString text=xmlReader.readElementText();
27065 			cn->weightPercentage=customFETStrToDouble(text);
27066 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
27067 		}
27068 		else if(xmlReader.name()==QString("Active")){
27069 			QString text=xmlReader.readElementText();
27070 			if(text=="false"){
27071 				cn->active=false;
27072 			}
27073 		}
27074 		else if(xmlReader.name()==QString("Comments")){
27075 			QString text=xmlReader.readElementText();
27076 			cn->comments=text;
27077 		}
27078 		else if(xmlReader.name()==QString("Min_Gaps_Between_Building_Changes")){
27079 			QString text=xmlReader.readElementText();
27080 			cn->minGapsBetweenBuildingChanges=text.toInt();
27081 			xmlReadingLog+="    Min gaps between building changes="+CustomFETString::number(cn->minGapsBetweenBuildingChanges)+"\n";
27082 		}
27083 		else{
27084 			unrecognizedXmlTags.append(xmlReader.name().toString());
27085 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
27086 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
27087 
27088 			xmlReader.skipCurrentElement();
27089 			xmlReaderNumberOfUnrecognizedFields++;
27090 		}
27091 	}
27092 	return cn;
27093 }
27094 
readStudentsSetMaxBuildingChangesPerDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)27095 SpaceConstraint* Rules::readStudentsSetMaxBuildingChangesPerDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
27096 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMaxBuildingChangesPerDay"));
27097 	ConstraintStudentsSetMaxBuildingChangesPerDay* cn=new ConstraintStudentsSetMaxBuildingChangesPerDay();
27098 	while(xmlReader.readNextStartElement()){
27099 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
27100 		if(xmlReader.name()==QString("Weight_Percentage")){
27101 			QString text=xmlReader.readElementText();
27102 			cn->weightPercentage=customFETStrToDouble(text);
27103 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
27104 		}
27105 		else if(xmlReader.name()==QString("Active")){
27106 			QString text=xmlReader.readElementText();
27107 			if(text=="false"){
27108 				cn->active=false;
27109 			}
27110 		}
27111 		else if(xmlReader.name()==QString("Comments")){
27112 			QString text=xmlReader.readElementText();
27113 			cn->comments=text;
27114 		}
27115 		else if(xmlReader.name()==QString("Students")){
27116 			QString text=xmlReader.readElementText();
27117 			cn->studentsName=text;
27118 			xmlReadingLog+="    Read students name="+cn->studentsName+"\n";
27119 		}
27120 		else if(xmlReader.name()==QString("Max_Building_Changes_Per_Day")){
27121 			QString text=xmlReader.readElementText();
27122 			cn->maxBuildingChangesPerDay=text.toInt();
27123 			xmlReadingLog+="    Max. building changes per day="+CustomFETString::number(cn->maxBuildingChangesPerDay)+"\n";
27124 		}
27125 		else{
27126 			unrecognizedXmlTags.append(xmlReader.name().toString());
27127 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
27128 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
27129 
27130 			xmlReader.skipCurrentElement();
27131 			xmlReaderNumberOfUnrecognizedFields++;
27132 		}
27133 	}
27134 	return cn;
27135 }
27136 
readStudentsMaxBuildingChangesPerDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)27137 SpaceConstraint* Rules::readStudentsMaxBuildingChangesPerDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
27138 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMaxBuildingChangesPerDay"));
27139 	ConstraintStudentsMaxBuildingChangesPerDay* cn=new ConstraintStudentsMaxBuildingChangesPerDay();
27140 	while(xmlReader.readNextStartElement()){
27141 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
27142 		if(xmlReader.name()==QString("Weight_Percentage")){
27143 			QString text=xmlReader.readElementText();
27144 			cn->weightPercentage=customFETStrToDouble(text);
27145 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
27146 		}
27147 		else if(xmlReader.name()==QString("Active")){
27148 			QString text=xmlReader.readElementText();
27149 			if(text=="false"){
27150 				cn->active=false;
27151 			}
27152 		}
27153 		else if(xmlReader.name()==QString("Comments")){
27154 			QString text=xmlReader.readElementText();
27155 			cn->comments=text;
27156 		}
27157 		else if(xmlReader.name()==QString("Max_Building_Changes_Per_Day")){
27158 			QString text=xmlReader.readElementText();
27159 			cn->maxBuildingChangesPerDay=text.toInt();
27160 			xmlReadingLog+="    Max. building changes per day="+CustomFETString::number(cn->maxBuildingChangesPerDay)+"\n";
27161 		}
27162 		else{
27163 			unrecognizedXmlTags.append(xmlReader.name().toString());
27164 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
27165 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
27166 
27167 			xmlReader.skipCurrentElement();
27168 			xmlReaderNumberOfUnrecognizedFields++;
27169 		}
27170 	}
27171 	return cn;
27172 }
27173 
readStudentsSetMaxBuildingChangesPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)27174 SpaceConstraint* Rules::readStudentsSetMaxBuildingChangesPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
27175 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMaxBuildingChangesPerWeek"));
27176 	ConstraintStudentsSetMaxBuildingChangesPerWeek* cn=new ConstraintStudentsSetMaxBuildingChangesPerWeek();
27177 	while(xmlReader.readNextStartElement()){
27178 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
27179 		if(xmlReader.name()==QString("Weight_Percentage")){
27180 			QString text=xmlReader.readElementText();
27181 			cn->weightPercentage=customFETStrToDouble(text);
27182 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
27183 		}
27184 		else if(xmlReader.name()==QString("Active")){
27185 			QString text=xmlReader.readElementText();
27186 			if(text=="false"){
27187 				cn->active=false;
27188 			}
27189 		}
27190 		else if(xmlReader.name()==QString("Comments")){
27191 			QString text=xmlReader.readElementText();
27192 			cn->comments=text;
27193 		}
27194 		else if(xmlReader.name()==QString("Students")){
27195 			QString text=xmlReader.readElementText();
27196 			cn->studentsName=text;
27197 			xmlReadingLog+="    Read students name="+cn->studentsName+"\n";
27198 		}
27199 		else if(xmlReader.name()==QString("Max_Building_Changes_Per_Week")){
27200 			QString text=xmlReader.readElementText();
27201 			cn->maxBuildingChangesPerWeek=text.toInt();
27202 			xmlReadingLog+="    Max. building changes per week="+CustomFETString::number(cn->maxBuildingChangesPerWeek)+"\n";
27203 		}
27204 		else{
27205 			unrecognizedXmlTags.append(xmlReader.name().toString());
27206 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
27207 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
27208 
27209 			xmlReader.skipCurrentElement();
27210 			xmlReaderNumberOfUnrecognizedFields++;
27211 		}
27212 	}
27213 	return cn;
27214 }
27215 
readStudentsMaxBuildingChangesPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)27216 SpaceConstraint* Rules::readStudentsMaxBuildingChangesPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
27217 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMaxBuildingChangesPerWeek"));
27218 	ConstraintStudentsMaxBuildingChangesPerWeek* cn=new ConstraintStudentsMaxBuildingChangesPerWeek();
27219 	while(xmlReader.readNextStartElement()){
27220 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
27221 		if(xmlReader.name()==QString("Weight_Percentage")){
27222 			QString text=xmlReader.readElementText();
27223 			cn->weightPercentage=customFETStrToDouble(text);
27224 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
27225 		}
27226 		else if(xmlReader.name()==QString("Active")){
27227 			QString text=xmlReader.readElementText();
27228 			if(text=="false"){
27229 				cn->active=false;
27230 			}
27231 		}
27232 		else if(xmlReader.name()==QString("Comments")){
27233 			QString text=xmlReader.readElementText();
27234 			cn->comments=text;
27235 		}
27236 		else if(xmlReader.name()==QString("Max_Building_Changes_Per_Week")){
27237 			QString text=xmlReader.readElementText();
27238 			cn->maxBuildingChangesPerWeek=text.toInt();
27239 			xmlReadingLog+="    Max. building changes per week="+CustomFETString::number(cn->maxBuildingChangesPerWeek)+"\n";
27240 		}
27241 		else{
27242 			unrecognizedXmlTags.append(xmlReader.name().toString());
27243 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
27244 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
27245 
27246 			xmlReader.skipCurrentElement();
27247 			xmlReaderNumberOfUnrecognizedFields++;
27248 		}
27249 	}
27250 	return cn;
27251 }
27252 
readStudentsSetMinGapsBetweenBuildingChanges(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)27253 SpaceConstraint* Rules::readStudentsSetMinGapsBetweenBuildingChanges(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
27254 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMinGapsBetweenBuildingChanges"));
27255 	ConstraintStudentsSetMinGapsBetweenBuildingChanges* cn=new ConstraintStudentsSetMinGapsBetweenBuildingChanges();
27256 	while(xmlReader.readNextStartElement()){
27257 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
27258 		if(xmlReader.name()==QString("Weight_Percentage")){
27259 			QString text=xmlReader.readElementText();
27260 			cn->weightPercentage=customFETStrToDouble(text);
27261 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
27262 		}
27263 		else if(xmlReader.name()==QString("Active")){
27264 			QString text=xmlReader.readElementText();
27265 			if(text=="false"){
27266 				cn->active=false;
27267 			}
27268 		}
27269 		else if(xmlReader.name()==QString("Comments")){
27270 			QString text=xmlReader.readElementText();
27271 			cn->comments=text;
27272 		}
27273 		else if(xmlReader.name()==QString("Students")){
27274 			QString text=xmlReader.readElementText();
27275 			cn->studentsName=text;
27276 			xmlReadingLog+="    Read students name="+cn->studentsName+"\n";
27277 		}
27278 		else if(xmlReader.name()==QString("Min_Gaps_Between_Building_Changes")){
27279 			QString text=xmlReader.readElementText();
27280 			cn->minGapsBetweenBuildingChanges=text.toInt();
27281 			xmlReadingLog+="    min gaps between building changes="+CustomFETString::number(cn->minGapsBetweenBuildingChanges)+"\n";
27282 		}
27283 		else{
27284 			unrecognizedXmlTags.append(xmlReader.name().toString());
27285 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
27286 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
27287 
27288 			xmlReader.skipCurrentElement();
27289 			xmlReaderNumberOfUnrecognizedFields++;
27290 		}
27291 	}
27292 	return cn;
27293 }
27294 
readStudentsMinGapsBetweenBuildingChanges(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)27295 SpaceConstraint* Rules::readStudentsMinGapsBetweenBuildingChanges(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
27296 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMinGapsBetweenBuildingChanges"));
27297 	ConstraintStudentsMinGapsBetweenBuildingChanges* cn=new ConstraintStudentsMinGapsBetweenBuildingChanges();
27298 	while(xmlReader.readNextStartElement()){
27299 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
27300 		if(xmlReader.name()==QString("Weight_Percentage")){
27301 			QString text=xmlReader.readElementText();
27302 			cn->weightPercentage=customFETStrToDouble(text);
27303 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
27304 		}
27305 		else if(xmlReader.name()==QString("Active")){
27306 			QString text=xmlReader.readElementText();
27307 			if(text=="false"){
27308 				cn->active=false;
27309 			}
27310 		}
27311 		else if(xmlReader.name()==QString("Comments")){
27312 			QString text=xmlReader.readElementText();
27313 			cn->comments=text;
27314 		}
27315 		else if(xmlReader.name()==QString("Min_Gaps_Between_Building_Changes")){
27316 			QString text=xmlReader.readElementText();
27317 			cn->minGapsBetweenBuildingChanges=text.toInt();
27318 			xmlReadingLog+="    min gaps between building changes="+CustomFETString::number(cn->minGapsBetweenBuildingChanges)+"\n";
27319 		}
27320 		else{
27321 			unrecognizedXmlTags.append(xmlReader.name().toString());
27322 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
27323 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
27324 
27325 			xmlReader.skipCurrentElement();
27326 			xmlReaderNumberOfUnrecognizedFields++;
27327 		}
27328 	}
27329 	return cn;
27330 }
27331 
27332 //2019-11-14
readTeacherMaxRoomChangesPerDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)27333 SpaceConstraint* Rules::readTeacherMaxRoomChangesPerDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
27334 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxRoomChangesPerDay"));
27335 	ConstraintTeacherMaxRoomChangesPerDay* cn=new ConstraintTeacherMaxRoomChangesPerDay();
27336 	while(xmlReader.readNextStartElement()){
27337 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
27338 		if(xmlReader.name()==QString("Weight_Percentage")){
27339 			QString text=xmlReader.readElementText();
27340 			cn->weightPercentage=customFETStrToDouble(text);
27341 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
27342 		}
27343 		else if(xmlReader.name()==QString("Active")){
27344 			QString text=xmlReader.readElementText();
27345 			if(text=="false"){
27346 				cn->active=false;
27347 			}
27348 		}
27349 		else if(xmlReader.name()==QString("Comments")){
27350 			QString text=xmlReader.readElementText();
27351 			cn->comments=text;
27352 		}
27353 		else if(xmlReader.name()==QString("Teacher")){
27354 			QString text=xmlReader.readElementText();
27355 			cn->teacherName=text;
27356 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
27357 		}
27358 		else if(xmlReader.name()==QString("Max_Room_Changes_Per_Day")){
27359 			QString text=xmlReader.readElementText();
27360 			cn->maxRoomChangesPerDay=text.toInt();
27361 			xmlReadingLog+="    Max. room changes per day="+CustomFETString::number(cn->maxRoomChangesPerDay)+"\n";
27362 		}
27363 		else{
27364 			unrecognizedXmlTags.append(xmlReader.name().toString());
27365 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
27366 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
27367 
27368 			xmlReader.skipCurrentElement();
27369 			xmlReaderNumberOfUnrecognizedFields++;
27370 		}
27371 	}
27372 	return cn;
27373 }
27374 
readTeachersMaxRoomChangesPerDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)27375 SpaceConstraint* Rules::readTeachersMaxRoomChangesPerDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
27376 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxRoomChangesPerDay"));
27377 	ConstraintTeachersMaxRoomChangesPerDay* cn=new ConstraintTeachersMaxRoomChangesPerDay();
27378 	while(xmlReader.readNextStartElement()){
27379 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
27380 		if(xmlReader.name()==QString("Weight_Percentage")){
27381 			QString text=xmlReader.readElementText();
27382 			cn->weightPercentage=customFETStrToDouble(text);
27383 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
27384 		}
27385 		else if(xmlReader.name()==QString("Active")){
27386 			QString text=xmlReader.readElementText();
27387 			if(text=="false"){
27388 				cn->active=false;
27389 			}
27390 		}
27391 		else if(xmlReader.name()==QString("Comments")){
27392 			QString text=xmlReader.readElementText();
27393 			cn->comments=text;
27394 		}
27395 		else if(xmlReader.name()==QString("Max_Room_Changes_Per_Day")){
27396 			QString text=xmlReader.readElementText();
27397 			cn->maxRoomChangesPerDay=text.toInt();
27398 			xmlReadingLog+="    Max. room changes per day="+CustomFETString::number(cn->maxRoomChangesPerDay)+"\n";
27399 		}
27400 		else{
27401 			unrecognizedXmlTags.append(xmlReader.name().toString());
27402 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
27403 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
27404 
27405 			xmlReader.skipCurrentElement();
27406 			xmlReaderNumberOfUnrecognizedFields++;
27407 		}
27408 	}
27409 	return cn;
27410 }
27411 
readTeacherMaxRoomChangesPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)27412 SpaceConstraint* Rules::readTeacherMaxRoomChangesPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
27413 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxRoomChangesPerWeek"));
27414 	ConstraintTeacherMaxRoomChangesPerWeek* cn=new ConstraintTeacherMaxRoomChangesPerWeek();
27415 	while(xmlReader.readNextStartElement()){
27416 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
27417 		if(xmlReader.name()==QString("Weight_Percentage")){
27418 			QString text=xmlReader.readElementText();
27419 			cn->weightPercentage=customFETStrToDouble(text);
27420 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
27421 		}
27422 		else if(xmlReader.name()==QString("Active")){
27423 			QString text=xmlReader.readElementText();
27424 			if(text=="false"){
27425 				cn->active=false;
27426 			}
27427 		}
27428 		else if(xmlReader.name()==QString("Comments")){
27429 			QString text=xmlReader.readElementText();
27430 			cn->comments=text;
27431 		}
27432 		else if(xmlReader.name()==QString("Teacher")){
27433 			QString text=xmlReader.readElementText();
27434 			cn->teacherName=text;
27435 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
27436 		}
27437 		else if(xmlReader.name()==QString("Max_Room_Changes_Per_Week")){
27438 			QString text=xmlReader.readElementText();
27439 			cn->maxRoomChangesPerWeek=text.toInt();
27440 			xmlReadingLog+="    Max. room changes per week="+CustomFETString::number(cn->maxRoomChangesPerWeek)+"\n";
27441 		}
27442 		else{
27443 			unrecognizedXmlTags.append(xmlReader.name().toString());
27444 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
27445 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
27446 
27447 			xmlReader.skipCurrentElement();
27448 			xmlReaderNumberOfUnrecognizedFields++;
27449 		}
27450 	}
27451 	return cn;
27452 }
27453 
readTeachersMaxRoomChangesPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)27454 SpaceConstraint* Rules::readTeachersMaxRoomChangesPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
27455 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxRoomChangesPerWeek"));
27456 	ConstraintTeachersMaxRoomChangesPerWeek* cn=new ConstraintTeachersMaxRoomChangesPerWeek();
27457 	while(xmlReader.readNextStartElement()){
27458 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
27459 		if(xmlReader.name()==QString("Weight_Percentage")){
27460 			QString text=xmlReader.readElementText();
27461 			cn->weightPercentage=customFETStrToDouble(text);
27462 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
27463 		}
27464 		else if(xmlReader.name()==QString("Active")){
27465 			QString text=xmlReader.readElementText();
27466 			if(text=="false"){
27467 				cn->active=false;
27468 			}
27469 		}
27470 		else if(xmlReader.name()==QString("Comments")){
27471 			QString text=xmlReader.readElementText();
27472 			cn->comments=text;
27473 		}
27474 		else if(xmlReader.name()==QString("Max_Room_Changes_Per_Week")){
27475 			QString text=xmlReader.readElementText();
27476 			cn->maxRoomChangesPerWeek=text.toInt();
27477 			xmlReadingLog+="    Max. room changes per week="+CustomFETString::number(cn->maxRoomChangesPerWeek)+"\n";
27478 		}
27479 		else{
27480 			unrecognizedXmlTags.append(xmlReader.name().toString());
27481 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
27482 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
27483 
27484 			xmlReader.skipCurrentElement();
27485 			xmlReaderNumberOfUnrecognizedFields++;
27486 		}
27487 	}
27488 	return cn;
27489 }
27490 
readTeacherMinGapsBetweenRoomChanges(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)27491 SpaceConstraint* Rules::readTeacherMinGapsBetweenRoomChanges(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
27492 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMinGapsBetweenRoomChanges"));
27493 	ConstraintTeacherMinGapsBetweenRoomChanges* cn=new ConstraintTeacherMinGapsBetweenRoomChanges();
27494 	while(xmlReader.readNextStartElement()){
27495 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
27496 		if(xmlReader.name()==QString("Weight_Percentage")){
27497 			QString text=xmlReader.readElementText();
27498 			cn->weightPercentage=customFETStrToDouble(text);
27499 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
27500 		}
27501 		else if(xmlReader.name()==QString("Active")){
27502 			QString text=xmlReader.readElementText();
27503 			if(text=="false"){
27504 				cn->active=false;
27505 			}
27506 		}
27507 		else if(xmlReader.name()==QString("Comments")){
27508 			QString text=xmlReader.readElementText();
27509 			cn->comments=text;
27510 		}
27511 		else if(xmlReader.name()==QString("Teacher")){
27512 			QString text=xmlReader.readElementText();
27513 			cn->teacherName=text;
27514 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
27515 		}
27516 		else if(xmlReader.name()==QString("Min_Gaps_Between_Room_Changes")){
27517 			QString text=xmlReader.readElementText();
27518 			cn->minGapsBetweenRoomChanges=text.toInt();
27519 			xmlReadingLog+="    Min gaps between room changes="+CustomFETString::number(cn->minGapsBetweenRoomChanges)+"\n";
27520 		}
27521 		else{
27522 			unrecognizedXmlTags.append(xmlReader.name().toString());
27523 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
27524 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
27525 
27526 			xmlReader.skipCurrentElement();
27527 			xmlReaderNumberOfUnrecognizedFields++;
27528 		}
27529 	}
27530 	return cn;
27531 }
27532 
readTeachersMinGapsBetweenRoomChanges(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)27533 SpaceConstraint* Rules::readTeachersMinGapsBetweenRoomChanges(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
27534 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMinGapsBetweenRoomChanges"));
27535 	ConstraintTeachersMinGapsBetweenRoomChanges* cn=new ConstraintTeachersMinGapsBetweenRoomChanges();
27536 	while(xmlReader.readNextStartElement()){
27537 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
27538 		if(xmlReader.name()==QString("Weight_Percentage")){
27539 			QString text=xmlReader.readElementText();
27540 			cn->weightPercentage=customFETStrToDouble(text);
27541 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
27542 		}
27543 		else if(xmlReader.name()==QString("Active")){
27544 			QString text=xmlReader.readElementText();
27545 			if(text=="false"){
27546 				cn->active=false;
27547 			}
27548 		}
27549 		else if(xmlReader.name()==QString("Comments")){
27550 			QString text=xmlReader.readElementText();
27551 			cn->comments=text;
27552 		}
27553 		else if(xmlReader.name()==QString("Min_Gaps_Between_Room_Changes")){
27554 			QString text=xmlReader.readElementText();
27555 			cn->minGapsBetweenRoomChanges=text.toInt();
27556 			xmlReadingLog+="    Min gaps between room changes="+CustomFETString::number(cn->minGapsBetweenRoomChanges)+"\n";
27557 		}
27558 		else{
27559 			unrecognizedXmlTags.append(xmlReader.name().toString());
27560 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
27561 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
27562 
27563 			xmlReader.skipCurrentElement();
27564 			xmlReaderNumberOfUnrecognizedFields++;
27565 		}
27566 	}
27567 	return cn;
27568 }
27569 
readStudentsSetMaxRoomChangesPerDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)27570 SpaceConstraint* Rules::readStudentsSetMaxRoomChangesPerDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
27571 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMaxRoomChangesPerDay"));
27572 	ConstraintStudentsSetMaxRoomChangesPerDay* cn=new ConstraintStudentsSetMaxRoomChangesPerDay();
27573 	while(xmlReader.readNextStartElement()){
27574 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
27575 		if(xmlReader.name()==QString("Weight_Percentage")){
27576 			QString text=xmlReader.readElementText();
27577 			cn->weightPercentage=customFETStrToDouble(text);
27578 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
27579 		}
27580 		else if(xmlReader.name()==QString("Active")){
27581 			QString text=xmlReader.readElementText();
27582 			if(text=="false"){
27583 				cn->active=false;
27584 			}
27585 		}
27586 		else if(xmlReader.name()==QString("Comments")){
27587 			QString text=xmlReader.readElementText();
27588 			cn->comments=text;
27589 		}
27590 		else if(xmlReader.name()==QString("Students")){
27591 			QString text=xmlReader.readElementText();
27592 			cn->studentsName=text;
27593 			xmlReadingLog+="    Read students name="+cn->studentsName+"\n";
27594 		}
27595 		else if(xmlReader.name()==QString("Max_Room_Changes_Per_Day")){
27596 			QString text=xmlReader.readElementText();
27597 			cn->maxRoomChangesPerDay=text.toInt();
27598 			xmlReadingLog+="    Max. room changes per day="+CustomFETString::number(cn->maxRoomChangesPerDay)+"\n";
27599 		}
27600 		else{
27601 			unrecognizedXmlTags.append(xmlReader.name().toString());
27602 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
27603 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
27604 
27605 			xmlReader.skipCurrentElement();
27606 			xmlReaderNumberOfUnrecognizedFields++;
27607 		}
27608 	}
27609 	return cn;
27610 }
27611 
readStudentsMaxRoomChangesPerDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)27612 SpaceConstraint* Rules::readStudentsMaxRoomChangesPerDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
27613 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMaxRoomChangesPerDay"));
27614 	ConstraintStudentsMaxRoomChangesPerDay* cn=new ConstraintStudentsMaxRoomChangesPerDay();
27615 	while(xmlReader.readNextStartElement()){
27616 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
27617 		if(xmlReader.name()==QString("Weight_Percentage")){
27618 			QString text=xmlReader.readElementText();
27619 			cn->weightPercentage=customFETStrToDouble(text);
27620 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
27621 		}
27622 		else if(xmlReader.name()==QString("Active")){
27623 			QString text=xmlReader.readElementText();
27624 			if(text=="false"){
27625 				cn->active=false;
27626 			}
27627 		}
27628 		else if(xmlReader.name()==QString("Comments")){
27629 			QString text=xmlReader.readElementText();
27630 			cn->comments=text;
27631 		}
27632 		else if(xmlReader.name()==QString("Max_Room_Changes_Per_Day")){
27633 			QString text=xmlReader.readElementText();
27634 			cn->maxRoomChangesPerDay=text.toInt();
27635 			xmlReadingLog+="    Max. room changes per day="+CustomFETString::number(cn->maxRoomChangesPerDay)+"\n";
27636 		}
27637 		else{
27638 			unrecognizedXmlTags.append(xmlReader.name().toString());
27639 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
27640 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
27641 
27642 			xmlReader.skipCurrentElement();
27643 			xmlReaderNumberOfUnrecognizedFields++;
27644 		}
27645 	}
27646 	return cn;
27647 }
27648 
readStudentsSetMaxRoomChangesPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)27649 SpaceConstraint* Rules::readStudentsSetMaxRoomChangesPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
27650 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMaxRoomChangesPerWeek"));
27651 	ConstraintStudentsSetMaxRoomChangesPerWeek* cn=new ConstraintStudentsSetMaxRoomChangesPerWeek();
27652 	while(xmlReader.readNextStartElement()){
27653 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
27654 		if(xmlReader.name()==QString("Weight_Percentage")){
27655 			QString text=xmlReader.readElementText();
27656 			cn->weightPercentage=customFETStrToDouble(text);
27657 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
27658 		}
27659 		else if(xmlReader.name()==QString("Active")){
27660 			QString text=xmlReader.readElementText();
27661 			if(text=="false"){
27662 				cn->active=false;
27663 			}
27664 		}
27665 		else if(xmlReader.name()==QString("Comments")){
27666 			QString text=xmlReader.readElementText();
27667 			cn->comments=text;
27668 		}
27669 		else if(xmlReader.name()==QString("Students")){
27670 			QString text=xmlReader.readElementText();
27671 			cn->studentsName=text;
27672 			xmlReadingLog+="    Read students name="+cn->studentsName+"\n";
27673 		}
27674 		else if(xmlReader.name()==QString("Max_Room_Changes_Per_Week")){
27675 			QString text=xmlReader.readElementText();
27676 			cn->maxRoomChangesPerWeek=text.toInt();
27677 			xmlReadingLog+="    Max. room changes per week="+CustomFETString::number(cn->maxRoomChangesPerWeek)+"\n";
27678 		}
27679 		else{
27680 			unrecognizedXmlTags.append(xmlReader.name().toString());
27681 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
27682 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
27683 
27684 			xmlReader.skipCurrentElement();
27685 			xmlReaderNumberOfUnrecognizedFields++;
27686 		}
27687 	}
27688 	return cn;
27689 }
27690 
readStudentsMaxRoomChangesPerWeek(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)27691 SpaceConstraint* Rules::readStudentsMaxRoomChangesPerWeek(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
27692 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMaxRoomChangesPerWeek"));
27693 	ConstraintStudentsMaxRoomChangesPerWeek* cn=new ConstraintStudentsMaxRoomChangesPerWeek();
27694 	while(xmlReader.readNextStartElement()){
27695 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
27696 		if(xmlReader.name()==QString("Weight_Percentage")){
27697 			QString text=xmlReader.readElementText();
27698 			cn->weightPercentage=customFETStrToDouble(text);
27699 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
27700 		}
27701 		else if(xmlReader.name()==QString("Active")){
27702 			QString text=xmlReader.readElementText();
27703 			if(text=="false"){
27704 				cn->active=false;
27705 			}
27706 		}
27707 		else if(xmlReader.name()==QString("Comments")){
27708 			QString text=xmlReader.readElementText();
27709 			cn->comments=text;
27710 		}
27711 		else if(xmlReader.name()==QString("Max_Room_Changes_Per_Week")){
27712 			QString text=xmlReader.readElementText();
27713 			cn->maxRoomChangesPerWeek=text.toInt();
27714 			xmlReadingLog+="    Max. room changes per week="+CustomFETString::number(cn->maxRoomChangesPerWeek)+"\n";
27715 		}
27716 		else{
27717 			unrecognizedXmlTags.append(xmlReader.name().toString());
27718 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
27719 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
27720 
27721 			xmlReader.skipCurrentElement();
27722 			xmlReaderNumberOfUnrecognizedFields++;
27723 		}
27724 	}
27725 	return cn;
27726 }
27727 
readStudentsSetMinGapsBetweenRoomChanges(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)27728 SpaceConstraint* Rules::readStudentsSetMinGapsBetweenRoomChanges(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
27729 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMinGapsBetweenRoomChanges"));
27730 	ConstraintStudentsSetMinGapsBetweenRoomChanges* cn=new ConstraintStudentsSetMinGapsBetweenRoomChanges();
27731 	while(xmlReader.readNextStartElement()){
27732 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
27733 		if(xmlReader.name()==QString("Weight_Percentage")){
27734 			QString text=xmlReader.readElementText();
27735 			cn->weightPercentage=customFETStrToDouble(text);
27736 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
27737 		}
27738 		else if(xmlReader.name()==QString("Active")){
27739 			QString text=xmlReader.readElementText();
27740 			if(text=="false"){
27741 				cn->active=false;
27742 			}
27743 		}
27744 		else if(xmlReader.name()==QString("Comments")){
27745 			QString text=xmlReader.readElementText();
27746 			cn->comments=text;
27747 		}
27748 		else if(xmlReader.name()==QString("Students")){
27749 			QString text=xmlReader.readElementText();
27750 			cn->studentsName=text;
27751 			xmlReadingLog+="    Read students name="+cn->studentsName+"\n";
27752 		}
27753 		else if(xmlReader.name()==QString("Min_Gaps_Between_Room_Changes")){
27754 			QString text=xmlReader.readElementText();
27755 			cn->minGapsBetweenRoomChanges=text.toInt();
27756 			xmlReadingLog+="    min gaps between room changes="+CustomFETString::number(cn->minGapsBetweenRoomChanges)+"\n";
27757 		}
27758 		else{
27759 			unrecognizedXmlTags.append(xmlReader.name().toString());
27760 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
27761 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
27762 
27763 			xmlReader.skipCurrentElement();
27764 			xmlReaderNumberOfUnrecognizedFields++;
27765 		}
27766 	}
27767 	return cn;
27768 }
27769 
readStudentsMinGapsBetweenRoomChanges(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)27770 SpaceConstraint* Rules::readStudentsMinGapsBetweenRoomChanges(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
27771 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMinGapsBetweenRoomChanges"));
27772 	ConstraintStudentsMinGapsBetweenRoomChanges* cn=new ConstraintStudentsMinGapsBetweenRoomChanges();
27773 	while(xmlReader.readNextStartElement()){
27774 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
27775 		if(xmlReader.name()==QString("Weight_Percentage")){
27776 			QString text=xmlReader.readElementText();
27777 			cn->weightPercentage=customFETStrToDouble(text);
27778 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
27779 		}
27780 		else if(xmlReader.name()==QString("Active")){
27781 			QString text=xmlReader.readElementText();
27782 			if(text=="false"){
27783 				cn->active=false;
27784 			}
27785 		}
27786 		else if(xmlReader.name()==QString("Comments")){
27787 			QString text=xmlReader.readElementText();
27788 			cn->comments=text;
27789 		}
27790 		else if(xmlReader.name()==QString("Min_Gaps_Between_Room_Changes")){
27791 			QString text=xmlReader.readElementText();
27792 			cn->minGapsBetweenRoomChanges=text.toInt();
27793 			xmlReadingLog+="    min gaps between room changes="+CustomFETString::number(cn->minGapsBetweenRoomChanges)+"\n";
27794 		}
27795 		else{
27796 			unrecognizedXmlTags.append(xmlReader.name().toString());
27797 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
27798 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
27799 
27800 			xmlReader.skipCurrentElement();
27801 			xmlReaderNumberOfUnrecognizedFields++;
27802 		}
27803 	}
27804 	return cn;
27805 }
27806 
27807 //2012-04-29
readActivitiesOccupyMaxDifferentRooms(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)27808 SpaceConstraint* Rules::readActivitiesOccupyMaxDifferentRooms(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
27809 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivitiesOccupyMaxDifferentRooms"));
27810 	ConstraintActivitiesOccupyMaxDifferentRooms* cn=new ConstraintActivitiesOccupyMaxDifferentRooms();
27811 
27812 	int ac=0;
27813 
27814 	while(xmlReader.readNextStartElement()){
27815 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
27816 
27817 		if(xmlReader.name()==QString("Weight_Percentage")){
27818 			QString text=xmlReader.readElementText();
27819 			cn->weightPercentage=customFETStrToDouble(text);
27820 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
27821 		}
27822 		else if(xmlReader.name()==QString("Active")){
27823 			QString text=xmlReader.readElementText();
27824 			if(text=="false"){
27825 				cn->active=false;
27826 			}
27827 		}
27828 		else if(xmlReader.name()==QString("Comments")){
27829 			QString text=xmlReader.readElementText();
27830 			cn->comments=text;
27831 		}
27832 		else if(xmlReader.name()==QString("Number_of_Activities")){
27833 			QString text=xmlReader.readElementText();
27834 			ac=text.toInt();
27835 			xmlReadingLog+="    Read number of activities="+CustomFETString::number(ac)+"\n";
27836 		}
27837 		else if(xmlReader.name()==QString("Activity_Id")){
27838 			QString text=xmlReader.readElementText();
27839 			cn->activitiesIds.append(text.toInt());
27840 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activitiesIds[cn->activitiesIds.count()-1])+"\n";
27841 		}
27842 		else if(xmlReader.name()==QString("Max_Number_of_Different_Rooms")){
27843 			QString text=xmlReader.readElementText();
27844 			cn->maxDifferentRooms=text.toInt();
27845 			xmlReadingLog+="    Read max number of different rooms="+CustomFETString::number(cn->maxDifferentRooms)+"\n";
27846 		}
27847 		else{
27848 			unrecognizedXmlTags.append(xmlReader.name().toString());
27849 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
27850 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
27851 
27852 			xmlReader.skipCurrentElement();
27853 			xmlReaderNumberOfUnrecognizedFields++;
27854 		}
27855 	}
27856 
27857 	if(!(ac==cn->activitiesIds.count())){
27858 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Activities").arg("Activity_Id"));
27859 		delete cn;
27860 		cn=nullptr;
27861 		return nullptr;
27862 	}
27863 	assert(ac==cn->activitiesIds.count());
27864 
27865 	return cn;
27866 }
27867 
27868 ////////////////
27869 
27870 //2013-09-14
readActivitiesSameRoomIfConsecutive(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)27871 SpaceConstraint* Rules::readActivitiesSameRoomIfConsecutive(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
27872 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintActivitiesSameRoomIfConsecutive"));
27873 	ConstraintActivitiesSameRoomIfConsecutive* cn=new ConstraintActivitiesSameRoomIfConsecutive();
27874 
27875 	int ac=0;
27876 
27877 	while(xmlReader.readNextStartElement()){
27878 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
27879 
27880 		if(xmlReader.name()==QString("Weight_Percentage")){
27881 			QString text=xmlReader.readElementText();
27882 			cn->weightPercentage=customFETStrToDouble(text);
27883 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
27884 		}
27885 		else if(xmlReader.name()==QString("Active")){
27886 			QString text=xmlReader.readElementText();
27887 			if(text=="false"){
27888 				cn->active=false;
27889 			}
27890 		}
27891 		else if(xmlReader.name()==QString("Comments")){
27892 			QString text=xmlReader.readElementText();
27893 			cn->comments=text;
27894 		}
27895 		else if(xmlReader.name()==QString("Number_of_Activities")){
27896 			QString text=xmlReader.readElementText();
27897 			ac=text.toInt();
27898 			xmlReadingLog+="    Read number of activities="+CustomFETString::number(ac)+"\n";
27899 		}
27900 		else if(xmlReader.name()==QString("Activity_Id")){
27901 			QString text=xmlReader.readElementText();
27902 			cn->activitiesIds.append(text.toInt());
27903 			xmlReadingLog+="    Read activity id="+CustomFETString::number(cn->activitiesIds[cn->activitiesIds.count()-1])+"\n";
27904 		}
27905 		else{
27906 			unrecognizedXmlTags.append(xmlReader.name().toString());
27907 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
27908 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
27909 
27910 			xmlReader.skipCurrentElement();
27911 			xmlReaderNumberOfUnrecognizedFields++;
27912 		}
27913 	}
27914 
27915 	if(!(ac==cn->activitiesIds.count())){
27916 		xmlReader.raiseError(tr("%1 does not coincide with the number of read %2").arg("Number_of_Activities").arg("Activity_Id"));
27917 		delete cn;
27918 		cn=nullptr;
27919 		return nullptr;
27920 	}
27921 	assert(ac==cn->activitiesIds.count());
27922 
27923 	return cn;
27924 }
27925 
27926 //mornings-afternoons
readOldMATeacherMaxRoomChangesPerDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)27927 SpaceConstraint* Rules::readOldMATeacherMaxRoomChangesPerDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
27928 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxRoomChangesPerDay"));
27929 	ConstraintTeacherMaxRoomChangesPerRealDay* cn=new ConstraintTeacherMaxRoomChangesPerRealDay();
27930 	while(xmlReader.readNextStartElement()){
27931 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
27932 		if(xmlReader.name()==QString("Weight_Percentage")){
27933 			QString text=xmlReader.readElementText();
27934 			cn->weightPercentage=customFETStrToDouble(text);
27935 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
27936 		}
27937 		else if(xmlReader.name()==QString("Active")){
27938 			QString text=xmlReader.readElementText();
27939 			if(text=="false"){
27940 				cn->active=false;
27941 			}
27942 		}
27943 		else if(xmlReader.name()==QString("Comments")){
27944 			QString text=xmlReader.readElementText();
27945 			cn->comments=text;
27946 		}
27947 		else if(xmlReader.name()==QString("Teacher")){
27948 			QString text=xmlReader.readElementText();
27949 			cn->teacherName=text;
27950 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
27951 		}
27952 		else if(xmlReader.name()==QString("Max_Room_Changes_Per_Day")){
27953 			QString text=xmlReader.readElementText();
27954 			cn->maxRoomChangesPerDay=text.toInt();
27955 			xmlReadingLog+="    Max. room changes per day="+CustomFETString::number(cn->maxRoomChangesPerDay)+"\n";
27956 		}
27957 		else{
27958 			unrecognizedXmlTags.append(xmlReader.name().toString());
27959 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
27960 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
27961 
27962 			xmlReader.skipCurrentElement();
27963 			xmlReaderNumberOfUnrecognizedFields++;
27964 		}
27965 	}
27966 	return cn;
27967 }
27968 
readTeacherMaxRoomChangesPerRealDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)27969 SpaceConstraint* Rules::readTeacherMaxRoomChangesPerRealDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
27970 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeacherMaxRoomChangesPerRealDay"));
27971 	ConstraintTeacherMaxRoomChangesPerRealDay* cn=new ConstraintTeacherMaxRoomChangesPerRealDay();
27972 	while(xmlReader.readNextStartElement()){
27973 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
27974 		if(xmlReader.name()==QString("Weight_Percentage")){
27975 			QString text=xmlReader.readElementText();
27976 			cn->weightPercentage=customFETStrToDouble(text);
27977 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
27978 		}
27979 		else if(xmlReader.name()==QString("Active")){
27980 			QString text=xmlReader.readElementText();
27981 			if(text=="false"){
27982 				cn->active=false;
27983 			}
27984 		}
27985 		else if(xmlReader.name()==QString("Comments")){
27986 			QString text=xmlReader.readElementText();
27987 			cn->comments=text;
27988 		}
27989 		else if(xmlReader.name()==QString("Teacher")){
27990 			QString text=xmlReader.readElementText();
27991 			cn->teacherName=text;
27992 			xmlReadingLog+="    Read teacher name="+cn->teacherName+"\n";
27993 		}
27994 		else if(xmlReader.name()==QString("Max_Room_Changes_Per_Day")){
27995 			QString text=xmlReader.readElementText();
27996 			cn->maxRoomChangesPerDay=text.toInt();
27997 			xmlReadingLog+="    Max. room changes per day="+CustomFETString::number(cn->maxRoomChangesPerDay)+"\n";
27998 		}
27999 		else{
28000 			unrecognizedXmlTags.append(xmlReader.name().toString());
28001 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
28002 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
28003 
28004 			xmlReader.skipCurrentElement();
28005 			xmlReaderNumberOfUnrecognizedFields++;
28006 		}
28007 	}
28008 	return cn;
28009 }
28010 
readOldMATeachersMaxRoomChangesPerDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)28011 SpaceConstraint* Rules::readOldMATeachersMaxRoomChangesPerDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
28012 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxRoomChangesPerDay"));
28013 	ConstraintTeachersMaxRoomChangesPerRealDay* cn=new ConstraintTeachersMaxRoomChangesPerRealDay();
28014 	while(xmlReader.readNextStartElement()){
28015 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
28016 		if(xmlReader.name()==QString("Weight_Percentage")){
28017 			QString text=xmlReader.readElementText();
28018 			cn->weightPercentage=customFETStrToDouble(text);
28019 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
28020 		}
28021 		else if(xmlReader.name()==QString("Active")){
28022 			QString text=xmlReader.readElementText();
28023 			if(text=="false"){
28024 				cn->active=false;
28025 			}
28026 		}
28027 		else if(xmlReader.name()==QString("Comments")){
28028 			QString text=xmlReader.readElementText();
28029 			cn->comments=text;
28030 		}
28031 		else if(xmlReader.name()==QString("Max_Room_Changes_Per_Day")){
28032 			QString text=xmlReader.readElementText();
28033 			cn->maxRoomChangesPerDay=text.toInt();
28034 			xmlReadingLog+="    Max. room changes per day="+CustomFETString::number(cn->maxRoomChangesPerDay)+"\n";
28035 		}
28036 		else{
28037 			unrecognizedXmlTags.append(xmlReader.name().toString());
28038 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
28039 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
28040 
28041 			xmlReader.skipCurrentElement();
28042 			xmlReaderNumberOfUnrecognizedFields++;
28043 		}
28044 	}
28045 	return cn;
28046 }
28047 
readTeachersMaxRoomChangesPerRealDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)28048 SpaceConstraint* Rules::readTeachersMaxRoomChangesPerRealDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
28049 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintTeachersMaxRoomChangesPerRealDay"));
28050 	ConstraintTeachersMaxRoomChangesPerRealDay* cn=new ConstraintTeachersMaxRoomChangesPerRealDay();
28051 	while(xmlReader.readNextStartElement()){
28052 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
28053 		if(xmlReader.name()==QString("Weight_Percentage")){
28054 			QString text=xmlReader.readElementText();
28055 			cn->weightPercentage=customFETStrToDouble(text);
28056 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
28057 		}
28058 		else if(xmlReader.name()==QString("Active")){
28059 			QString text=xmlReader.readElementText();
28060 			if(text=="false"){
28061 				cn->active=false;
28062 			}
28063 		}
28064 		else if(xmlReader.name()==QString("Comments")){
28065 			QString text=xmlReader.readElementText();
28066 			cn->comments=text;
28067 		}
28068 		else if(xmlReader.name()==QString("Max_Room_Changes_Per_Day")){
28069 			QString text=xmlReader.readElementText();
28070 			cn->maxRoomChangesPerDay=text.toInt();
28071 			xmlReadingLog+="    Max. room changes per day="+CustomFETString::number(cn->maxRoomChangesPerDay)+"\n";
28072 		}
28073 		else{
28074 			unrecognizedXmlTags.append(xmlReader.name().toString());
28075 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
28076 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
28077 
28078 			xmlReader.skipCurrentElement();
28079 			xmlReaderNumberOfUnrecognizedFields++;
28080 		}
28081 	}
28082 	return cn;
28083 }
28084 
readOldMAStudentsSetMaxRoomChangesPerDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)28085 SpaceConstraint* Rules::readOldMAStudentsSetMaxRoomChangesPerDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
28086 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMaxRoomChangesPerDay"));
28087 	ConstraintStudentsSetMaxRoomChangesPerRealDay* cn=new ConstraintStudentsSetMaxRoomChangesPerRealDay();
28088 	while(xmlReader.readNextStartElement()){
28089 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
28090 		if(xmlReader.name()==QString("Weight_Percentage")){
28091 			QString text=xmlReader.readElementText();
28092 			cn->weightPercentage=customFETStrToDouble(text);
28093 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
28094 		}
28095 		else if(xmlReader.name()==QString("Active")){
28096 			QString text=xmlReader.readElementText();
28097 			if(text=="false"){
28098 				cn->active=false;
28099 			}
28100 		}
28101 		else if(xmlReader.name()==QString("Comments")){
28102 			QString text=xmlReader.readElementText();
28103 			cn->comments=text;
28104 		}
28105 		else if(xmlReader.name()==QString("Students")){
28106 			QString text=xmlReader.readElementText();
28107 			cn->studentsName=text;
28108 			xmlReadingLog+="    Read students name="+cn->studentsName+"\n";
28109 		}
28110 		else if(xmlReader.name()==QString("Max_Room_Changes_Per_Day")){
28111 			QString text=xmlReader.readElementText();
28112 			cn->maxRoomChangesPerDay=text.toInt();
28113 			xmlReadingLog+="    Max. room changes per day="+CustomFETString::number(cn->maxRoomChangesPerDay)+"\n";
28114 		}
28115 		else{
28116 			unrecognizedXmlTags.append(xmlReader.name().toString());
28117 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
28118 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
28119 
28120 			xmlReader.skipCurrentElement();
28121 			xmlReaderNumberOfUnrecognizedFields++;
28122 		}
28123 	}
28124 	return cn;
28125 }
28126 
readStudentsSetMaxRoomChangesPerRealDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)28127 SpaceConstraint* Rules::readStudentsSetMaxRoomChangesPerRealDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
28128 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsSetMaxRoomChangesPerRealDay"));
28129 	ConstraintStudentsSetMaxRoomChangesPerRealDay* cn=new ConstraintStudentsSetMaxRoomChangesPerRealDay();
28130 	while(xmlReader.readNextStartElement()){
28131 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
28132 		if(xmlReader.name()==QString("Weight_Percentage")){
28133 			QString text=xmlReader.readElementText();
28134 			cn->weightPercentage=customFETStrToDouble(text);
28135 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
28136 		}
28137 		else if(xmlReader.name()==QString("Active")){
28138 			QString text=xmlReader.readElementText();
28139 			if(text=="false"){
28140 				cn->active=false;
28141 			}
28142 		}
28143 		else if(xmlReader.name()==QString("Comments")){
28144 			QString text=xmlReader.readElementText();
28145 			cn->comments=text;
28146 		}
28147 		else if(xmlReader.name()==QString("Students")){
28148 			QString text=xmlReader.readElementText();
28149 			cn->studentsName=text;
28150 			xmlReadingLog+="    Read students name="+cn->studentsName+"\n";
28151 		}
28152 		else if(xmlReader.name()==QString("Max_Room_Changes_Per_Day")){
28153 			QString text=xmlReader.readElementText();
28154 			cn->maxRoomChangesPerDay=text.toInt();
28155 			xmlReadingLog+="    Max. room changes per day="+CustomFETString::number(cn->maxRoomChangesPerDay)+"\n";
28156 		}
28157 		else{
28158 			unrecognizedXmlTags.append(xmlReader.name().toString());
28159 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
28160 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
28161 
28162 			xmlReader.skipCurrentElement();
28163 			xmlReaderNumberOfUnrecognizedFields++;
28164 		}
28165 	}
28166 	return cn;
28167 }
28168 
readOldMAStudentsMaxRoomChangesPerDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)28169 SpaceConstraint* Rules::readOldMAStudentsMaxRoomChangesPerDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
28170 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMaxRoomChangesPerDay"));
28171 	ConstraintStudentsMaxRoomChangesPerRealDay* cn=new ConstraintStudentsMaxRoomChangesPerRealDay();
28172 	while(xmlReader.readNextStartElement()){
28173 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
28174 		if(xmlReader.name()==QString("Weight_Percentage")){
28175 			QString text=xmlReader.readElementText();
28176 			cn->weightPercentage=customFETStrToDouble(text);
28177 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
28178 		}
28179 		else if(xmlReader.name()==QString("Active")){
28180 			QString text=xmlReader.readElementText();
28181 			if(text=="false"){
28182 				cn->active=false;
28183 			}
28184 		}
28185 		else if(xmlReader.name()==QString("Comments")){
28186 			QString text=xmlReader.readElementText();
28187 			cn->comments=text;
28188 		}
28189 		else if(xmlReader.name()==QString("Max_Room_Changes_Per_Day")){
28190 			QString text=xmlReader.readElementText();
28191 			cn->maxRoomChangesPerDay=text.toInt();
28192 			xmlReadingLog+="    Max. room changes per day="+CustomFETString::number(cn->maxRoomChangesPerDay)+"\n";
28193 		}
28194 		else{
28195 			unrecognizedXmlTags.append(xmlReader.name().toString());
28196 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
28197 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
28198 
28199 			xmlReader.skipCurrentElement();
28200 			xmlReaderNumberOfUnrecognizedFields++;
28201 		}
28202 	}
28203 	return cn;
28204 }
28205 
readStudentsMaxRoomChangesPerRealDay(QXmlStreamReader & xmlReader,FakeString & xmlReadingLog)28206 SpaceConstraint* Rules::readStudentsMaxRoomChangesPerRealDay(QXmlStreamReader& xmlReader, FakeString& xmlReadingLog){
28207 	assert(xmlReader.isStartElement() && xmlReader.name()==QString("ConstraintStudentsMaxRoomChangesPerRealDay"));
28208 	ConstraintStudentsMaxRoomChangesPerRealDay* cn=new ConstraintStudentsMaxRoomChangesPerRealDay();
28209 	while(xmlReader.readNextStartElement()){
28210 		xmlReadingLog+="    Found "+xmlReader.name().toString()+" tag\n";
28211 		if(xmlReader.name()==QString("Weight_Percentage")){
28212 			QString text=xmlReader.readElementText();
28213 			cn->weightPercentage=customFETStrToDouble(text);
28214 			xmlReadingLog+="    Adding weight percentage="+CustomFETString::number(cn->weightPercentage)+"\n";
28215 		}
28216 		else if(xmlReader.name()==QString("Active")){
28217 			QString text=xmlReader.readElementText();
28218 			if(text=="false"){
28219 				cn->active=false;
28220 			}
28221 		}
28222 		else if(xmlReader.name()==QString("Comments")){
28223 			QString text=xmlReader.readElementText();
28224 			cn->comments=text;
28225 		}
28226 		else if(xmlReader.name()==QString("Max_Room_Changes_Per_Day")){
28227 			QString text=xmlReader.readElementText();
28228 			cn->maxRoomChangesPerDay=text.toInt();
28229 			xmlReadingLog+="    Max. room changes per day="+CustomFETString::number(cn->maxRoomChangesPerDay)+"\n";
28230 		}
28231 		else{
28232 			unrecognizedXmlTags.append(xmlReader.name().toString());
28233 			unrecognizedXmlLineNumbers.append(xmlReader.lineNumber());
28234 			unrecognizedXmlColumnNumbers.append(xmlReader.columnNumber());
28235 
28236 			xmlReader.skipCurrentElement();
28237 			xmlReaderNumberOfUnrecognizedFields++;
28238 		}
28239 	}
28240 	return cn;
28241 }
28242 
28243 ////////////////
28244