1 //
2 //
3 // Description: This file is part of FET
4 //
5 //
6 // Author: Liviu Lalescu <Please see https://lalescu.ro/liviu/ for details about contacting Liviu Lalescu (in particular, you can find here the e-mail address)>
7 // Copyright (C) 2003 Liviu Lalescu <https://lalescu.ro/liviu/>
8 //
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software: you can redistribute it and/or modify  *
12  *   it under the terms of the GNU Affero General Public License as        *
13  *   published by the Free Software Foundation, either version 3 of the    *
14  *   License, or (at your option) any later version.                       *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #include "studentsset.h"
19 #include "rules.h"
20 #include "timetable.h"
21 
22 extern Timetable gt;
23 
StudentsSet()24 StudentsSet::StudentsSet()
25 {
26 	this->type=STUDENTS_SET;
27 	this->numberOfStudents=0;
28 	comments=QString("");
29 }
30 
~StudentsSet()31 StudentsSet::~StudentsSet()
32 {
33 }
34 
StudentsYear()35 StudentsYear::StudentsYear()
36 	: StudentsSet()
37 {
38 	this->type=STUDENTS_YEAR;
39 
40 	divisions.clear();
41 	separator=QString(" ");
42 
43 	indexInAugmentedYearsList=-1;
44 }
45 
~StudentsYear()46 StudentsYear::~StudentsYear()
47 {
48 }
49 
getXmlDescription()50 QString StudentsYear::getXmlDescription()
51 {
52 	QString s="";
53 	s+="<Year>\n";
54 	s+="	<Name>"+protect(this->name)+"</Name>\n";
55 	s+="	<Number_of_Students>"+CustomFETString::number(this->numberOfStudents)+"</Number_of_Students>\n";
56 	s+="	<Comments>"+protect(comments)+"</Comments>\n";
57 
58 	s+="	<!-- The information regarding categories, divisions of each category, and separator is only used in the divide year automatically by categories dialog. -->\n";
59 	s+="	<Number_of_Categories>"+QString::number(divisions.count())+"</Number_of_Categories>\n";
60 	for(const QStringList& tl : qAsConst(divisions)){
61 		s+="	<Category>\n";
62 		s+="		<Number_of_Divisions>"+QString::number(tl.count())+"</Number_of_Divisions>\n";
63 		for(const QString& dn : qAsConst(tl))
64 			s+="		<Division>"+protect(dn)+"</Division>\n";
65 		s+="	</Category>\n";
66 	}
67 	s+="	<Separator>"+protect(separator)+"</Separator>\n";
68 
69 	for(int i=0; i<this->groupsList.size(); i++){
70 		StudentsGroup* stg=this->groupsList[i];
71 		s+=stg->getXmlDescription();
72 	}
73 	s+="</Year>\n";
74 
75 	return s;
76 }
77 
getDescription()78 QString StudentsYear::getDescription()
79 {
80 	QString s;
81 	s+=tr("YN:%1", "Year name").arg(this->name);
82 	s+=", ";
83 	s+=tr("NoS:%1", "Number of students").arg(this->numberOfStudents);
84 
85 	QString end=QString("");
86 	if(!comments.isEmpty())
87 		end=QString(", ")+tr("C: %1", "Comments").arg(comments);
88 
89 	return s+end;
90 }
91 
getDetailedDescription()92 QString StudentsYear::getDetailedDescription()
93 {
94 	QString s="";
95 	s+=tr("Students set - year");
96 	s+="\n";
97 	s+=tr("Year name=%1").arg(this->name);
98 	s+="\n";
99 	s+=tr("Number of students=%1").arg(this->numberOfStudents);
100 	s+="\n";
101 
102 	//Has comments?
103 	if(!comments.isEmpty()){
104 		s+=tr("Comments=%1").arg(comments);
105 		s+="\n";
106 	}
107 
108 	return s;
109 }
110 
getDetailedDescriptionWithConstraints(Rules & r)111 QString StudentsYear::getDetailedDescriptionWithConstraints(Rules& r)
112 {
113 	QString s=this->getDetailedDescription();
114 
115 	s+="--------------------------------------------------\n";
116 	s+=tr("Time constraints directly related to this students year:");
117 	s+="\n";
118 	for(int i=0; i<r.timeConstraintsList.size(); i++){
119 		TimeConstraint* c=r.timeConstraintsList[i];
120 		if(c->isRelatedToStudentsSet(r, this)){
121 			s+="\n";
122 			s+=c->getDetailedDescription(r);
123 		}
124 	}
125 
126 	s+="--------------------------------------------------\n";
127 	s+=tr("Space constraints directly related to this students year:");
128 	s+="\n";
129 	for(int i=0; i<r.spaceConstraintsList.size(); i++){
130 		SpaceConstraint* c=r.spaceConstraintsList[i];
131 		if(c->isRelatedToStudentsSet(r, this)){
132 			s+="\n";
133 			s+=c->getDetailedDescription(r);
134 		}
135 	}
136 	s+="--------------------------------------------------\n";
137 
138 	return s;
139 }
140 
141 
StudentsGroup()142 StudentsGroup::StudentsGroup()
143 	: StudentsSet()
144 {
145 	this->type=STUDENTS_GROUP;
146 
147 	indexInInternalGroupsList=-1;
148 }
149 
~StudentsGroup()150 StudentsGroup::~StudentsGroup()
151 {
152 }
153 
getXmlDescription()154 QString StudentsGroup::getXmlDescription()
155 {
156 	QString s="";
157 	s+="	<Group>\n";
158 	s+="		<Name>"+protect(this->name)+"</Name>\n";
159 	s+="		<Number_of_Students>"+CustomFETString::number(this->numberOfStudents)+"</Number_of_Students>\n";
160 	s+="		<Comments>"+protect(comments)+"</Comments>\n";
161 	for(int i=0; i<this->subgroupsList.size(); i++){
162 		StudentsSubgroup* sts=this->subgroupsList[i];
163 		s+=sts->getXmlDescription();
164 	}
165 	s+="	</Group>\n";
166 
167 	return s;
168 }
169 
getDescription()170 QString StudentsGroup::getDescription()
171 {
172 	QString s="";
173 	s+=tr("GN:%1", "Group name").arg(this->name);
174 	s+=", ";
175 	s+=tr("NoS:%1", "Number of students").arg(this->numberOfStudents);
176 
177 	QString end=QString("");
178 	if(!comments.isEmpty())
179 		end=QString(", ")+tr("C: %1", "Comments").arg(comments);
180 
181 	return s+end;
182 }
183 
getDetailedDescription()184 QString StudentsGroup::getDetailedDescription()
185 {
186 	QString s="";
187 	s+=tr("Students set - group");
188 	s+="\n";
189 	s+=tr("Group name=%1").arg(this->name);
190 	s+="\n";
191 	s+=tr("Number of students=%1").arg(this->numberOfStudents);
192 	s+="\n";
193 
194 	//Has comments?
195 	if(!comments.isEmpty()){
196 		s+=tr("Comments=%1").arg(comments);
197 		s+="\n";
198 	}
199 
200 	return s;
201 }
202 
getDetailedDescriptionWithConstraints(Rules & r)203 QString StudentsGroup::getDetailedDescriptionWithConstraints(Rules& r)
204 {
205 	QString s=this->getDetailedDescription();
206 
207 	s+="--------------------------------------------------\n";
208 	s+=tr("Time constraints directly related to this students group:");
209 	s+="\n";
210 	for(int i=0; i<r.timeConstraintsList.size(); i++){
211 		TimeConstraint* c=r.timeConstraintsList[i];
212 		if(c->isRelatedToStudentsSet(r, this)){
213 			s+="\n";
214 			s+=c->getDetailedDescription(r);
215 		}
216 	}
217 
218 	s+="--------------------------------------------------\n";
219 	s+=tr("Space constraints directly related to this students group:");
220 	s+="\n";
221 	for(int i=0; i<r.spaceConstraintsList.size(); i++){
222 		SpaceConstraint* c=r.spaceConstraintsList[i];
223 		if(c->isRelatedToStudentsSet(r, this)){
224 			s+="\n";
225 			s+=c->getDetailedDescription(r);
226 		}
227 	}
228 	s+="--------------------------------------------------\n";
229 
230 	return s;
231 }
232 
233 
StudentsSubgroup()234 StudentsSubgroup::StudentsSubgroup()
235 	: StudentsSet()
236 {
237 	this->type=STUDENTS_SUBGROUP;
238 
239 	indexInInternalSubgroupsList=-1;
240 }
241 
~StudentsSubgroup()242 StudentsSubgroup::~StudentsSubgroup()
243 {
244 }
245 
getXmlDescription()246 QString StudentsSubgroup::getXmlDescription()
247 {
248 	QString s="";
249 	s+="		<Subgroup>\n";
250 	s+="			<Name>"+protect(this->name)+"</Name>\n";
251 	s+="			<Number_of_Students>"+CustomFETString::number(this->numberOfStudents)+"</Number_of_Students>\n";
252 	s+="			<Comments>"+protect(comments)+"</Comments>\n";
253 	s+="		</Subgroup>\n";
254 
255 	return s;
256 }
257 
getDescription()258 QString StudentsSubgroup::getDescription()
259 {
260 	QString s="";
261 	s+=tr("SgN:%1", "Subgroup name").arg(this->name);
262 	s+=", ";
263 	s+=tr("NoS:%1", "Number of students").arg(this->numberOfStudents);
264 
265 	QString end=QString("");
266 	if(!comments.isEmpty())
267 		end=QString(", ")+tr("C: %1", "Comments").arg(comments);
268 
269 	return s+end;
270 }
271 
getDetailedDescription()272 QString StudentsSubgroup::getDetailedDescription()
273 {
274 	QString s="";
275 	s+=tr("Students set - subgroup");
276 	s+="\n";
277 	s+=tr("Subgroup name=%1").arg(this->name);
278 	s+="\n";
279 	s+=tr("Number of students=%1").arg(this->numberOfStudents);
280 	s+="\n";
281 
282 	//Has comments?
283 	if(!comments.isEmpty()){
284 		s+=tr("Comments=%1").arg(comments);
285 		s+="\n";
286 	}
287 
288 	return s;
289 }
290 
getDetailedDescriptionWithConstraints(Rules & r)291 QString StudentsSubgroup::getDetailedDescriptionWithConstraints(Rules& r)
292 {
293 	QString s=this->getDetailedDescription();
294 
295 	s+="--------------------------------------------------\n";
296 	s+=tr("Time constraints directly related to this students subgroup:");
297 	s+="\n";
298 	for(int i=0; i<r.timeConstraintsList.size(); i++){
299 		TimeConstraint* c=r.timeConstraintsList[i];
300 		if(c->isRelatedToStudentsSet(r, this)){
301 			s+="\n";
302 			s+=c->getDetailedDescription(r);
303 		}
304 	}
305 
306 	s+="--------------------------------------------------\n";
307 	s+=tr("Space constraints directly related to this students subgroup:");
308 	s+="\n";
309 	for(int i=0; i<r.spaceConstraintsList.size(); i++){
310 		SpaceConstraint* c=r.spaceConstraintsList[i];
311 		if(c->isRelatedToStudentsSet(r, this)){
312 			s+="\n";
313 			s+=c->getDetailedDescription(r);
314 		}
315 	}
316 	s+="--------------------------------------------------\n";
317 
318 	return s;
319 }
320 
yearsAscending(const StudentsYear * y1,const StudentsYear * y2)321 int yearsAscending(const StudentsYear* y1, const StudentsYear* y2)
322 {
323 	//return y1->name < y2->name;
324 	//by Rodolfo Ribeiro Gomes
325 	return y1->name.localeAwareCompare(y2->name)<0;
326 }
327 
groupsAscending(const StudentsGroup * g1,const StudentsGroup * g2)328 int groupsAscending(const StudentsGroup* g1, const StudentsGroup* g2)
329 {
330 	//return g1->name < g2->name;
331 	//by Rodolfo Ribeiro Gomes
332 	return g1->name.localeAwareCompare(g2->name)<0;
333 }
334 
subgroupsAscending(const StudentsSubgroup * s1,const StudentsSubgroup * s2)335 int subgroupsAscending(const StudentsSubgroup* s1, const StudentsSubgroup* s2)
336 {
337 	//return s1->name < s2->name;
338 	//by Rodolfo Ribeiro Gomes
339 	return s1->name.localeAwareCompare(s2->name)<0;
340 }
341