Back to index

fet  5.18.0
rules.cpp
Go to the documentation of this file.
00001 /*
00002 File rules.cpp
00003 */
00004 
00005 /*
00006 Copyright 2002, 2003 Lalescu Liviu.
00007 
00008 This file is part of FET.
00009 
00010 FET is free software; you can redistribute it and/or modify
00011 it under the terms of the GNU General Public License as published by
00012 the Free Software Foundation; either version 2 of the License, or
00013 (at your option) any later version.
00014 
00015 FET is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with FET; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023 */
00024 
00025 #include "timetable_defs.h"
00026 #include "rules.h"
00027 
00028 #include <QDir>
00029 
00030 #include <iostream>
00031 using namespace std;
00032 
00033 #include <QTextStream>
00034 #include <QFile>
00035 #include <QFileInfo>
00036 
00037 #include <QDate>
00038 #include <QTime>
00039 #include <QLocale>
00040 
00041 #include <QString>
00042 
00043 #include <QtXml>
00044 
00045 #include <QString>
00046 #include <QTranslator>
00047 #include <QMessageBox>
00048 
00049 #include <QtAlgorithms>
00050 
00051 #include <QSet>
00052 #include <QHash>
00053 
00054 #include <QApplication>
00055 #include <QProgressDialog>
00056 
00057 #include <QRegExp>
00058 
00059 #include "longtextmessagebox.h"
00060 
00061 #include "lockunlock.h"
00062 
00063 #include "centerwidgetonscreen.h"
00064 
00065 //static bool toSkipTime[MAX_TIME_CONSTRAINTS];
00066 //static bool toSkipSpace[MAX_SPACE_CONSTRAINTS];
00067 
00068 extern QApplication* pqapplication;
00069 
00070 extern bool students_schedule_ready;
00071 extern bool rooms_schedule_ready;
00072 extern bool teachers_schedule_ready;
00073 
00074 
00075 FakeString::FakeString()
00076 {
00077 }
00078 
00079 void FakeString::operator=(const QString& other)
00080 {
00081        Q_UNUSED(other);
00082 }
00083 
00084 void FakeString::operator=(const char* str)
00085 {
00086        Q_UNUSED(str);
00087 }
00088 
00089 void FakeString::operator+=(const QString& other)
00090 {
00091        Q_UNUSED(other);
00092 }
00093 
00094 void FakeString::operator+=(const char* str)
00095 {
00096        Q_UNUSED(str);
00097 }
00098 
00099 
00100 void Rules::init() //initializes the rules (empty, but with default hours and days)
00101 {
00102        //defaults
00103        this->nHoursPerDay=12;
00104        this->hoursOfTheDay[0]="08:00";
00105        this->hoursOfTheDay[1]="09:00";
00106        this->hoursOfTheDay[2]="10:00";
00107        this->hoursOfTheDay[3]="11:00";
00108        this->hoursOfTheDay[4]="12:00";
00109        this->hoursOfTheDay[5]="13:00";
00110        this->hoursOfTheDay[6]="14:00";
00111        this->hoursOfTheDay[7]="15:00";
00112        this->hoursOfTheDay[8]="16:00";
00113        this->hoursOfTheDay[9]="17:00";
00114        this->hoursOfTheDay[10]="18:00";
00115        this->hoursOfTheDay[11]="19:00";
00116        this->hoursOfTheDay[12]="20:00";
00117 
00118        this->nDaysPerWeek=5;
00119        this->daysOfTheWeek[0] = tr("Monday");
00120        this->daysOfTheWeek[1] = tr("Tuesday");
00121        this->daysOfTheWeek[2] = tr("Wednesday");
00122        this->daysOfTheWeek[3] = tr("Thursday");
00123        this->daysOfTheWeek[4] = tr("Friday");
00124        
00125        this->institutionName=tr("Default institution");
00126        this->comments=tr("Default comments");
00127 
00128        this->initialized=true;
00129 }
00130 
00131 bool Rules::computeInternalStructure(QWidget* parent)
00132 {
00133        //To fix a bug reported by Frans on forum, on 7 May 2010.
00134        //If user generates, then changes some activities (changes teachers of them), then tries to generate but FET cannot precompute in generate_pre.cpp,
00135        //then if user views the timetable, the timetable of a teacher contains activities of other teacher.
00136        //The bug appeared because it is possible to compute internal structure, so internal activities change the teacher, but the timetables remain the same,
00137        //with the same activities indexes.
00138        teachers_schedule_ready=false;
00139        students_schedule_ready=false;
00140        rooms_schedule_ready=false;
00141 
00142        //The order is important - firstly the teachers, subjects, activity tags and students.
00143        //After that, the buildings.
00144        //After that, the rooms.
00145        //After that, the activities.
00146        //After that, the time constraints.
00147        //After that, the space constraints.
00148 
00149        if(this->teachersList.size()>MAX_TEACHERS){
00150               QMessageBox::warning(parent, tr("FET information"),
00151                tr("You have too many teachers. You need to increase the variable MAX_TEACHERS (which is currently %1).")
00152                .arg(MAX_TEACHERS));
00153               return false;
00154        }
00155        if(this->subjectsList.size()>MAX_SUBJECTS){
00156               QMessageBox::warning(parent, tr("FET information"),
00157                tr("You have too many subjects. You need to increase the variable MAX_SUBJECTS (which is currently %1).")
00158                .arg(MAX_SUBJECTS));
00159               return false;
00160        }
00161        
00162        //kill augmented students sets
00163        QList<StudentsYear*> ayears;
00164        QList<StudentsGroup*> agroups;
00165        QList<StudentsSubgroup*> asubgroups;
00166        foreach(StudentsYear* year, augmentedYearsList){
00167               if(!ayears.contains(year))
00168                      ayears.append(year);
00169               foreach(StudentsGroup* group, year->groupsList){
00170                      if(!agroups.contains(group))
00171                             agroups.append(group);
00172                      foreach(StudentsSubgroup* subgroup, group->subgroupsList){
00173                             if(!asubgroups.contains(subgroup))
00174                                    asubgroups.append(subgroup);
00175                      }
00176               }
00177        }
00178        foreach(StudentsYear* year, ayears){
00179               assert(year!=NULL);
00180               delete year;
00181        }
00182        foreach(StudentsGroup* group, agroups){
00183               assert(group!=NULL);
00184               delete group;
00185        }
00186        foreach(StudentsSubgroup* subgroup, asubgroups){
00187               assert(subgroup!=NULL);
00188               delete subgroup;
00189        }
00190        augmentedYearsList.clear();
00192        
00193        //copy list of students sets into augmented list
00194        QHash<QString, StudentsSet*> augmentedHash;
00195        
00196        foreach(StudentsYear* y, yearsList){
00197               StudentsYear* ay=new StudentsYear();
00198               ay->name=y->name;
00199               ay->numberOfStudents=y->numberOfStudents;
00200               ay->groupsList.clear();
00201               augmentedYearsList << ay;
00202               
00203               assert(!augmentedHash.contains(ay->name));
00204               augmentedHash.insert(ay->name, ay);
00205               
00206               foreach(StudentsGroup* g, y->groupsList){
00207                      if(augmentedHash.contains(g->name)){
00208                             StudentsSet* tmpg=augmentedHash.value(g->name);
00209                             assert(tmpg->type==STUDENTS_GROUP);
00210                             ay->groupsList<<((StudentsGroup*)tmpg);
00211                      }
00212                      else{
00213                             StudentsGroup* ag=new StudentsGroup();
00214                             ag->name=g->name;
00215                             ag->numberOfStudents=g->numberOfStudents;
00216                             ag->subgroupsList.clear();
00217                             ay->groupsList << ag;
00218                             
00219                             assert(!augmentedHash.contains(ag->name));
00220                             augmentedHash.insert(ag->name, ag);
00221                      
00222                             foreach(StudentsSubgroup* s, g->subgroupsList){
00223                                    if(augmentedHash.contains(s->name)){
00224                                           StudentsSet* tmps=augmentedHash.value(s->name);
00225                                           assert(tmps->type==STUDENTS_SUBGROUP);
00226                                           ag->subgroupsList<<((StudentsSubgroup*)tmps);
00227                                    }
00228                                    else{
00229                                           StudentsSubgroup* as=new StudentsSubgroup();
00230                                           as->name=s->name;
00231                                           as->numberOfStudents=s->numberOfStudents;
00232                                           ag->subgroupsList << as;
00233                                           
00234                                           assert(!augmentedHash.contains(as->name));
00235                                           augmentedHash.insert(as->name, as);
00236                                    }
00237                             }
00238                      }
00239               }
00240        }
00241 
00243        for(int i=0; i<this->augmentedYearsList.size(); i++){
00244               StudentsYear* sty=this->augmentedYearsList[i];
00245 
00246               //if this year has no groups, insert something to simulate the whole year
00247               if(sty->groupsList.count()==0){
00248                      StudentsGroup* tmpGroup = new StudentsGroup();
00249                      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 "
00250                       "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)"
00251                       ". In the empty year there will be added a group with name = yearName+a space character+your translation of 'Automatic Group'.");
00252                      tmpGroup->numberOfStudents = sty->numberOfStudents;
00253                      sty->groupsList << tmpGroup;
00254               }
00255               
00256               for(int j=0; j<sty->groupsList.size(); j++){
00257                      StudentsGroup* stg=sty->groupsList[j];
00258 
00259                      //if this group has no subgroups, insert something to simulate the whole group
00260                      if(stg->subgroupsList.size()==0){
00261                             StudentsSubgroup* tmpSubgroup = new StudentsSubgroup();
00262                             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 "
00263                              "is added in the group, in the timetable (when viewing the students timetable from FET and also in the html timetables for students subgroups)"
00264                              ". In the empty group there will be added a subgroup with name = groupName+a space character+your translation of 'Automatic Subgroup'.");
00265                             tmpSubgroup->numberOfStudents=stg->numberOfStudents;
00266                             stg->subgroupsList << tmpSubgroup;
00267                      }
00268               }
00269        }
00271        
00272        QSet<StudentsGroup*> allGroupsSet;
00273        QSet<StudentsSubgroup*> allSubgroupsSet;
00274        QList<StudentsGroup*> allGroupsList;
00275        QList<StudentsSubgroup*> allSubgroupsList;
00276        
00277        for(int i=0; i<this->augmentedYearsList.size(); i++){
00278               StudentsYear* sty=this->augmentedYearsList.at(i);
00279               sty->indexInAugmentedYearsList=i;
00280 
00281               for(int j=0; j<sty->groupsList.size(); j++){
00282                      StudentsGroup* stg=sty->groupsList.at(j);
00283                      if(!allGroupsSet.contains(stg)){
00284                             allGroupsSet.insert(stg);
00285                             allGroupsList.append(stg);
00286                             stg->indexInInternalGroupsList=allGroupsSet.count()-1;
00287                      }
00288                      
00289                      for(int k=0; k<stg->subgroupsList.size(); k++)
00290                             if(!allSubgroupsSet.contains(stg->subgroupsList.at(k))){
00291                                    allSubgroupsSet.insert(stg->subgroupsList.at(k));
00292                                    allSubgroupsList.append(stg->subgroupsList.at(k));
00293                                    stg->subgroupsList.at(k)->indexInInternalSubgroupsList=allSubgroupsSet.count()-1;
00294                             }
00295               }
00296        }
00297        int tmpNSubgroups=allSubgroupsList.count();
00298        if(tmpNSubgroups>MAX_TOTAL_SUBGROUPS){
00299               QMessageBox::warning(parent, tr("FET information"),
00300                tr("You have too many total subgroups. You need to increase the variable MAX_TOTAL_SUBGROUPS (which is currently %1).")
00301                .arg(MAX_TOTAL_SUBGROUPS));
00302               return false;
00303        }
00304        this->internalSubgroupsList.resize(tmpNSubgroups);
00305 
00306        int counter=0;
00307        for(int i=0; i<this->activitiesList.size(); i++){
00308               Activity* act=this->activitiesList.at(i);
00309               if(act->active)
00310                      counter++;
00311        }
00312        if(counter>MAX_ACTIVITIES){
00313               QMessageBox::warning(parent, tr("FET information"),
00314                tr("You have too many active activities. You need to increase the variable MAX_ACTIVITIES (which is currently %1).")
00315                .arg(MAX_ACTIVITIES));
00316               return false;
00317        }
00318 
00319        if(this->buildingsList.size()>MAX_BUILDINGS){
00320               QMessageBox::warning(parent, tr("FET information"),
00321                tr("You have too many buildings. You need to increase the variable MAX_BUILDINGS (which is currently %1).")
00322                .arg(MAX_BUILDINGS));
00323               return false;
00324        }
00325        
00326        if(this->roomsList.size()>MAX_ROOMS){
00327               QMessageBox::warning(parent, tr("FET information"),
00328                tr("You have too many rooms. You need to increase the variable MAX_ROOMS (which is currently %1).")
00329                .arg(MAX_ROOMS));
00330               return false;
00331        }
00332        
00333        assert(this->initialized);
00334 
00335        //days and hours
00336        assert(this->nHoursPerDay>0);
00337        assert(this->nDaysPerWeek>0);
00338        this->nHoursPerWeek=this->nHoursPerDay*this->nDaysPerWeek;
00339 
00340        //teachers
00341        int i;
00342        Teacher* tch;
00343        this->nInternalTeachers=this->teachersList.size();
00344        assert(this->nInternalTeachers<=MAX_TEACHERS);
00345        this->internalTeachersList.resize(this->nInternalTeachers);
00346        for(i=0; i<this->teachersList.size(); i++){
00347               tch=teachersList[i];
00348               this->internalTeachersList[i]=tch;
00349        }
00350        assert(i==this->nInternalTeachers);
00351 
00352        //subjects
00353        Subject* sbj;
00354        this->nInternalSubjects=this->subjectsList.size();
00355        assert(this->nInternalSubjects<=MAX_SUBJECTS);
00356        this->internalSubjectsList.resize(this->nInternalSubjects);
00357        for(i=0; i<this->subjectsList.size(); i++){
00358               sbj=this->subjectsList[i];
00359               this->internalSubjectsList[i]=sbj;
00360        }
00361        assert(i==this->nInternalSubjects);
00362 
00363        //activity tags
00364        ActivityTag* at;
00365        this->nInternalActivityTags=this->activityTagsList.size();
00366        this->internalActivityTagsList.resize(this->nInternalActivityTags);
00367        for(i=0; i<this->activityTagsList.size(); i++){
00368               at=this->activityTagsList[i];
00369               this->internalActivityTagsList[i]=at;
00370        }
00371        assert(i==this->nInternalActivityTags);
00372 
00373        //students
00374        this->nInternalSubgroups=0;
00375        for(int i=0; i<allSubgroupsList.count(); i++){
00376               assert(allSubgroupsList.at(i)->indexInInternalSubgroupsList==i);
00377               this->internalSubgroupsList[this->nInternalSubgroups]=allSubgroupsList.at(i);
00378               this->nInternalSubgroups++;
00379        }
00380 
00381        this->internalGroupsList.clear();
00382        for(int i=0; i<allGroupsList.count(); i++){
00383               assert(allGroupsList.at(i)->indexInInternalGroupsList==i);
00384               this->internalGroupsList.append(allGroupsList.at(i));
00385        }
00386        
00387 /*     for(int i=0; i<this->augmentedYearsList.size(); i++){
00388               StudentsYear* sty=this->augmentedYearsList[i];
00389               
00390               assert(sty->groupsList.count()>0);
00391 
00392               for(int j=0; j<sty->groupsList.size(); j++){
00393                      StudentsGroup* stg=sty->groupsList[j];
00394                      
00395                      assert(stg->subgroupsList.count()>0);
00396 
00397                      for(int k=0; k<stg->subgroupsList.size(); k++){
00398                             StudentsSubgroup* sts=stg->subgroupsList[k];
00399 
00400                             bool existing=false;
00401                             for(int i=0; i<this->nInternalSubgroups; i++)
00402                                    if(this->internalSubgroupsList[i]->name==sts->name){
00403                                           existing=true;
00404                                           sts->indexInInternalSubgroupsList=i;
00405                                           break;
00406                                    }
00407                             if(!existing){
00408                                    assert(this->nInternalSubgroups<MAX_TOTAL_SUBGROUPS);
00409                                    assert(this->nInternalSubgroups<tmpNSubgroups);
00410                                    sts->indexInInternalSubgroupsList=this->nInternalSubgroups;
00411                                    this->internalSubgroupsList[this->nInternalSubgroups++]=sts;
00412                             }
00413                      }
00414               }
00415        }*/
00416        assert(this->nInternalSubgroups==tmpNSubgroups);
00417 
00418        //buildings
00419        internalBuildingsList.resize(buildingsList.size());
00420        this->nInternalBuildings=0;
00421        assert(this->buildingsList.size()<=MAX_BUILDINGS);
00422        for(int i=0; i<this->buildingsList.size(); i++){
00423               Building* bu=this->buildingsList[i];
00424               bu->computeInternalStructure(*this);
00425        }
00426        
00427        for(int i=0; i<this->buildingsList.size(); i++){
00428               Building* bu=this->buildingsList[i];
00429               this->internalBuildingsList[this->nInternalBuildings++]=bu;
00430        }
00431        assert(this->nInternalBuildings==this->buildingsList.size());
00432 
00433        //rooms
00434        internalRoomsList.resize(roomsList.size());
00435        this->nInternalRooms=0;
00436        assert(this->roomsList.size()<=MAX_ROOMS);
00437        for(int i=0; i<this->roomsList.size(); i++){
00438               Room* rm=this->roomsList[i];
00439               rm->computeInternalStructure(*this);
00440        }
00441        
00442        for(int i=0; i<this->roomsList.size(); i++){
00443               Room* rm=this->roomsList[i];
00444               this->internalRoomsList[this->nInternalRooms++]=rm;
00445        }
00446        assert(this->nInternalRooms==this->roomsList.size());
00447 
00448 
00449        //activities
00450        int range=0;
00451        foreach(Activity* act, this->activitiesList)
00452               if(act->active)
00453                      range++;
00454        QProgressDialog progress(parent);
00455        progress.setWindowTitle(tr("Computing internal structure", "Title of a progress dialog"));
00456        progress.setLabelText(tr("Processing internally the activities ... please wait"));
00457        progress.setRange(0, range);
00458        progress.setModal(true);
00459        int ttt=0;
00460               
00461        Activity* act;
00462        counter=0;
00463        
00464        this->inactiveActivities.clear();
00465        
00466        for(int i=0; i<this->activitiesList.size(); i++){
00467               act=this->activitiesList[i];
00468               if(act->active){
00469                      progress.setValue(ttt);
00470                      //pqapplication->processEvents();
00471                      if(progress.wasCanceled()){
00472                             QMessageBox::information(parent, tr("FET information"), tr("Canceled"));
00473                             return false;
00474                      }
00475                      ttt++;
00476 
00477                      counter++;
00478                      act->computeInternalStructure(*this);
00479               }
00480               else
00481                      inactiveActivities.insert(act->id);
00482        }
00483        
00484        progress.setValue(range);
00485 
00486        for(int i=0; i<nInternalSubgroups; i++)
00487               internalSubgroupsList[i]->activitiesForSubgroup.clear();
00488        for(int i=0; i<nInternalTeachers; i++)
00489               internalTeachersList[i]->activitiesForTeacher.clear();
00490 
00491        assert(counter<=MAX_ACTIVITIES);
00492        this->nInternalActivities=counter;
00493        this->internalActivitiesList.resize(this->nInternalActivities);
00494        int activei=0;
00495        for(int ai=0; ai<this->activitiesList.size(); ai++){
00496               act=this->activitiesList[ai];
00497               if(act->active){
00498                      this->internalActivitiesList[activei]=*act;
00499                      
00500                      for(int j=0; j<act->iSubgroupsList.count(); j++){
00501                             int k=act->iSubgroupsList.at(j);
00502                             assert(!internalSubgroupsList[k]->activitiesForSubgroup.contains(activei));
00503                             internalSubgroupsList[k]->activitiesForSubgroup.append(activei);
00504                      }
00505                      
00506                      for(int j=0; j<act->iTeachersList.count(); j++){
00507                             int k=act->iTeachersList.at(j);
00508                             assert(!internalTeachersList[k]->activitiesForTeacher.contains(activei));
00509                             internalTeachersList[k]->activitiesForTeacher.append(activei);
00510                      }
00511                      
00512                      activei++;
00513               }
00514        }
00515 
00516        //activities list for each subject - used for subjects timetable - in order for students and teachers
00517        activitiesForSubject.resize(nInternalSubjects);
00518        for(int sb=0; sb<nInternalSubjects; sb++)
00519               activitiesForSubject[sb].clear();
00520 
00521        for(int i=0; i<this->augmentedYearsList.size(); i++){
00522               StudentsYear* sty=this->augmentedYearsList[i];
00523 
00524               for(int j=0; j<sty->groupsList.size(); j++){
00525                      StudentsGroup* stg=sty->groupsList[j];
00526 
00527                      for(int k=0; k<stg->subgroupsList.size(); k++){
00528                             StudentsSubgroup* sts=stg->subgroupsList[k];
00529                             
00530                             foreach(int ai, internalSubgroupsList[sts->indexInInternalSubgroupsList]->activitiesForSubgroup)
00531                                    if(!activitiesForSubject[internalActivitiesList[ai].subjectIndex].contains(ai))
00532                                           activitiesForSubject[internalActivitiesList[ai].subjectIndex].append(ai);
00533                      }
00534               }
00535        }
00536        
00537        for(int i=0; i<nInternalTeachers; i++){
00538               foreach(int ai, internalTeachersList[i]->activitiesForTeacher)
00539                      if(!activitiesForSubject[internalActivitiesList[ai].subjectIndex].contains(ai))
00540                             activitiesForSubject[internalActivitiesList[ai].subjectIndex].append(ai);
00541        }
00543 
00544 
00545        bool ok=true;
00546 
00547        //time constraints
00548        //progress.reset();
00549        
00550        bool skipInactiveTimeConstraints=false;
00551        
00552        TimeConstraint* tctr;
00553        
00554        QSet<int> toSkipTimeSet;
00555        
00556        int _c=0;
00557        
00558        for(int tctrindex=0; tctrindex<this->timeConstraintsList.size(); tctrindex++){
00559               tctr=this->timeConstraintsList[tctrindex];
00560 
00561               if(!tctr->active){
00562                      toSkipTimeSet.insert(tctrindex);
00563               }
00564               else if(tctr->hasInactiveActivities(*this)){
00565                      //toSkipTime[tctrindex]=true;
00566                      toSkipTimeSet.insert(tctrindex);
00567               
00568                      if(!skipInactiveTimeConstraints){
00569                             QString s=tr("The following time constraint is ignored, because it refers to inactive activities:");
00570                             s+="\n";
00571                             s+=tctr->getDetailedDescription(*this);
00572                             
00573                             int t=LongTextMessageBox::mediumConfirmation(parent, tr("FET information"), s,
00574                              tr("Skip rest"), tr("See next"), QString(),
00575                              1, 0 );
00576 
00577                             if(t==0)
00578                                    skipInactiveTimeConstraints=true;
00579                      }
00580               }
00581               else{
00582                      //toSkipTime[tctrindex]=false;
00583                      _c++;
00584               }
00585        }
00586        
00587        internalTimeConstraintsList.resize(_c);
00588        
00589        progress.setLabelText(tr("Processing internally the time constraints ... please wait"));
00590        progress.setRange(0, timeConstraintsList.size());
00591        ttt=0;
00592               
00593        //assert(this->timeConstraintsList.size()<=MAX_TIME_CONSTRAINTS);
00594        int tctri=0;
00595        
00596        for(int tctrindex=0; tctrindex<this->timeConstraintsList.size(); tctrindex++){
00597               progress.setValue(ttt);
00598               //pqapplication->processEvents();
00599               if(progress.wasCanceled()){
00600                      QMessageBox::information(parent, tr("FET information"), tr("Canceled"));
00601                      return false;
00602               }
00603               ttt++;
00604 
00605               tctr=this->timeConstraintsList[tctrindex];
00606               
00607               if(toSkipTimeSet.contains(tctrindex))
00608                      continue;
00609               
00610               if(!tctr->computeInternalStructure(parent, *this)){
00611                      //assert(0);
00612                      ok=false;
00613                      continue;
00614               }
00615               this->internalTimeConstraintsList[tctri++]=tctr;
00616        }
00617 
00618        progress.setValue(timeConstraintsList.size());
00619 
00620        this->nInternalTimeConstraints=tctri;
00621        cout<<_c<<" time constraints after first pass (after removing inactive ones)"<<endl;
00622        cout<<"  "<<this->nInternalTimeConstraints<<" time constraints after second pass (after removing wrong ones)"<<endl;
00623        assert(_c>=this->nInternalTimeConstraints); //because some constraints may have toSkipTime false, but computeInternalStructure also false
00624        //assert(this->nInternalTimeConstraints<=MAX_TIME_CONSTRAINTS);
00625        
00626        //space constraints
00627        //progress.reset();
00628        
00629        bool skipInactiveSpaceConstraints=false;
00630        
00631        SpaceConstraint* sctr;
00632        
00633        QSet<int> toSkipSpaceSet;
00634        
00635        _c=0;
00636 
00637        for(int sctrindex=0; sctrindex<this->spaceConstraintsList.size(); sctrindex++){
00638               sctr=this->spaceConstraintsList[sctrindex];
00639 
00640               if(!sctr->active){
00641                      toSkipSpaceSet.insert(sctrindex);
00642               }
00643               else if(sctr->hasInactiveActivities(*this)){
00644                      //toSkipSpace[sctrindex]=true;
00645                      toSkipSpaceSet.insert(sctrindex);
00646               
00647                      if(!skipInactiveSpaceConstraints){
00648                             QString s=tr("The following space constraint is ignored, because it refers to inactive activities:");
00649                             s+="\n";
00650                             s+=sctr->getDetailedDescription(*this);
00651                             
00652                             int t=LongTextMessageBox::mediumConfirmation(parent, tr("FET information"), s,
00653                              tr("Skip rest"), tr("See next"), QString(),
00654                              1, 0 );
00655 
00656                             if(t==0)
00657                                    skipInactiveSpaceConstraints=true;
00658                      }
00659               }
00660               else{
00661                      _c++;
00662                      //toSkipSpace[sctrindex]=false;
00663               }
00664        }
00665        
00666        internalSpaceConstraintsList.resize(_c);
00667        
00668        progress.setLabelText(tr("Processing internally the space constraints ... please wait"));
00669        progress.setRange(0, spaceConstraintsList.size());
00670        ttt=0;
00671        //assert(this->spaceConstraintsList.size()<=MAX_SPACE_CONSTRAINTS);
00672 
00673        int sctri=0;
00674 
00675        for(int sctrindex=0; sctrindex<this->spaceConstraintsList.size(); sctrindex++){
00676               progress.setValue(ttt);
00677               //pqapplication->processEvents();
00678               if(progress.wasCanceled()){
00679                      QMessageBox::information(parent, tr("FET information"), tr("Canceled"));
00680                      return false;
00681               }
00682               ttt++;
00683 
00684               sctr=this->spaceConstraintsList[sctrindex];
00685        
00686               if(toSkipSpaceSet.contains(sctrindex))
00687                      continue;
00688               
00689               if(!sctr->computeInternalStructure(parent, *this)){
00690                      //assert(0);
00691                      ok=false;
00692                      continue;
00693               }
00694               this->internalSpaceConstraintsList[sctri++]=sctr;
00695        }
00696 
00697        progress.setValue(spaceConstraintsList.size());
00698 
00699        this->nInternalSpaceConstraints=sctri;
00700        cout<<_c<<" space constraints after first pass (after removing inactive ones)"<<endl;
00701        cout<<"  "<<this->nInternalSpaceConstraints<<" space constraints after second pass (after removing wrong ones)"<<endl;
00702        assert(_c>=this->nInternalSpaceConstraints); //because some constraints may have toSkipSpace false, but computeInternalStructure also false
00703        //assert(this->nInternalSpaceConstraints<=MAX_SPACE_CONSTRAINTS);
00704 
00705        //done.
00706        this->internalStructureComputed=ok;
00707        
00708        return ok;
00709 }
00710 
00711 void Rules::kill() //clears memory for the rules, destroys them
00712 {
00713        //Teachers
00714        while(!teachersList.isEmpty())
00715               delete teachersList.takeFirst();
00716 
00717        //Subjects
00718        while(!subjectsList.isEmpty())
00719               delete subjectsList.takeFirst();
00720 
00721        //Activity tags
00722        while(!activityTagsList.isEmpty())
00723               delete activityTagsList.takeFirst();
00724 
00725        //Years
00726        /*while(!yearsList.isEmpty())
00727               delete yearsList.takeFirst();*/
00728               
00729        //students sets
00730        QList<StudentsYear*> iyears;
00731        QList<StudentsGroup*> igroups;
00732        QList<StudentsSubgroup*> isubgroups;
00733        foreach(StudentsYear* year, yearsList){
00734               if(!iyears.contains(year))
00735                      iyears.append(year);
00736               foreach(StudentsGroup* group, year->groupsList){
00737                      if(!igroups.contains(group))
00738                             igroups.append(group);
00739                      foreach(StudentsSubgroup* subgroup, group->subgroupsList){
00740                             if(!isubgroups.contains(subgroup))
00741                                    isubgroups.append(subgroup);
00742                      }
00743               }
00744        }
00745        foreach(StudentsYear* year, iyears){
00746               assert(year!=NULL);
00747               delete year;
00748        }
00749        foreach(StudentsGroup* group, igroups){
00750               assert(group!=NULL);
00751               delete group;
00752        }
00753        foreach(StudentsSubgroup* subgroup, isubgroups){
00754               assert(subgroup!=NULL);
00755               delete subgroup;
00756        }      
00757        yearsList.clear();
00759 
00760        //kill augmented students sets
00761        QList<StudentsYear*> ayears;
00762        QList<StudentsGroup*> agroups;
00763        QList<StudentsSubgroup*> asubgroups;
00764        foreach(StudentsYear* year, augmentedYearsList){
00765               if(!ayears.contains(year))
00766                      ayears.append(year);
00767               foreach(StudentsGroup* group, year->groupsList){
00768                      if(!agroups.contains(group))
00769                             agroups.append(group);
00770                      foreach(StudentsSubgroup* subgroup, group->subgroupsList){
00771                             if(!asubgroups.contains(subgroup))
00772                                    asubgroups.append(subgroup);
00773                      }
00774               }
00775        }
00776        foreach(StudentsYear* year, ayears){
00777               assert(year!=NULL);
00778               delete year;
00779        }
00780        foreach(StudentsGroup* group, agroups){
00781               assert(group!=NULL);
00782               delete group;
00783        }
00784        foreach(StudentsSubgroup* subgroup, asubgroups){
00785               assert(subgroup!=NULL);
00786               delete subgroup;
00787        }      
00788        augmentedYearsList.clear();
00790        
00791        //Activities
00792        while(!activitiesList.isEmpty())
00793               delete activitiesList.takeFirst();
00794 
00795        //Time constraints
00796        while(!timeConstraintsList.isEmpty())
00797               delete timeConstraintsList.takeFirst();
00798 
00799        //Space constraints
00800        while(!spaceConstraintsList.isEmpty())
00801               delete spaceConstraintsList.takeFirst();
00802 
00803        //Buildings
00804        while(!buildingsList.isEmpty())
00805               delete buildingsList.takeFirst();
00806 
00807        //Rooms
00808        while(!roomsList.isEmpty())
00809               delete roomsList.takeFirst();
00810 
00811        //done
00812        this->internalStructureComputed=false;
00813        this->initialized=false;
00814 }
00815 
00816 Rules::Rules()
00817 {
00818        this->initialized=false;
00819        this->modified=false;
00820 }
00821 
00822 Rules::~Rules()
00823 {
00824        if(this->initialized)
00825               this->kill();
00826 }
00827 
00828 void Rules::setInstitutionName(const QString& newInstitutionName)
00829 {
00830        this->institutionName=newInstitutionName;
00831        this->internalStructureComputed=false;
00832        setRulesModifiedAndOtherThings(this);
00833 }
00834 
00835 void Rules::setComments(const QString& newComments)
00836 {
00837        this->comments=newComments;
00838        this->internalStructureComputed=false;
00839        setRulesModifiedAndOtherThings(this);
00840 }
00841 
00842 bool Rules::addTeacher(Teacher* teacher)
00843 {
00844        for(int i=0; i<this->teachersList.size(); i++){
00845               Teacher* tch=this->teachersList[i];
00846               if(tch->name==teacher->name)
00847                      return false;
00848        }
00849        
00850        this->internalStructureComputed=false;
00851        setRulesModifiedAndOtherThings(this);
00852 
00853        teachers_schedule_ready=false;
00854        students_schedule_ready=false;
00855        rooms_schedule_ready=false;
00856 
00857        this->teachersList.append(teacher);
00858        return true;
00859 }
00860 
00861 bool Rules::addTeacherFast(Teacher* teacher)
00862 {
00863        this->internalStructureComputed=false;
00864        setRulesModifiedAndOtherThings(this);
00865 
00866        teachers_schedule_ready=false;
00867        students_schedule_ready=false;
00868        rooms_schedule_ready=false;
00869 
00870        this->teachersList.append(teacher);
00871        return true;
00872 }
00873 
00874 int Rules::searchTeacher(const QString& teacherName)
00875 {
00876        for(int i=0; i<this->teachersList.size(); i++)
00877               if(this->teachersList.at(i)->name==teacherName)
00878                      return i;
00879 
00880        return -1;
00881 }
00882 
00883 bool Rules::removeTeacher(const QString& teacherName)
00884 {
00885        for(int i=0; i<this->activitiesList.size(); ){
00886               Activity* act=this->activitiesList[i];
00887               bool t=act->removeTeacher(teacherName);
00888               if(t && act->teachersNames.size()==0){
00889                      this->removeActivity(act->id, act->activityGroupId);
00890                      i=0;
00891                      //(You have to be careful, there can be erased more activities here)
00892               }
00893               else
00894                      i++;
00895        }
00896        
00897        for(int i=0; i<this->timeConstraintsList.size(); ){
00898               TimeConstraint* ctr=this->timeConstraintsList[i];
00899               if(ctr->type==CONSTRAINT_TEACHER_NOT_AVAILABLE_TIMES){
00900                      ConstraintTeacherNotAvailableTimes* crt_constraint=(ConstraintTeacherNotAvailableTimes*)ctr;
00901                      if(teacherName==crt_constraint->teacher)
00902                             this->removeTimeConstraint(ctr); //single constraint removal
00903                      else
00904                             i++;
00905               }
00906               else
00907                      i++;
00908        }
00909 
00910        for(int i=0; i<this->timeConstraintsList.size(); ){
00911               TimeConstraint* ctr=this->timeConstraintsList[i];
00912               if(ctr->type==CONSTRAINT_TEACHER_MAX_GAPS_PER_WEEK){
00913                      ConstraintTeacherMaxGapsPerWeek* crt_constraint=(ConstraintTeacherMaxGapsPerWeek*)ctr;
00914                      if(teacherName==crt_constraint->teacherName)
00915                             this->removeTimeConstraint(ctr); //single constraint removal
00916                      else
00917                             i++;
00918               }
00919               else
00920                      i++;
00921        }
00922 
00923        for(int i=0; i<this->timeConstraintsList.size(); ){
00924               TimeConstraint* ctr=this->timeConstraintsList[i];
00925               if(ctr->type==CONSTRAINT_TEACHER_MAX_GAPS_PER_DAY){
00926                      ConstraintTeacherMaxGapsPerDay* crt_constraint=(ConstraintTeacherMaxGapsPerDay*)ctr;
00927                      if(teacherName==crt_constraint->teacherName)
00928                             this->removeTimeConstraint(ctr); //single constraint removal
00929                      else
00930                             i++;
00931               }
00932               else
00933                      i++;
00934        }
00935 
00936        for(int i=0; i<this->timeConstraintsList.size(); ){
00937               TimeConstraint* ctr=this->timeConstraintsList[i];
00938               if(ctr->type==CONSTRAINT_TEACHER_MAX_HOURS_DAILY){
00939                      ConstraintTeacherMaxHoursDaily* crt_constraint=(ConstraintTeacherMaxHoursDaily*)ctr;
00940                      if(teacherName==crt_constraint->teacherName)
00941                             this->removeTimeConstraint(ctr); //single constraint removal
00942                      else
00943                             i++;
00944               }
00945               else
00946                      i++;
00947        }
00948 
00949        for(int i=0; i<this->timeConstraintsList.size(); ){
00950               TimeConstraint* ctr=this->timeConstraintsList[i];
00951               if(ctr->type==CONSTRAINT_TEACHER_MAX_HOURS_CONTINUOUSLY){
00952                      ConstraintTeacherMaxHoursContinuously* crt_constraint=(ConstraintTeacherMaxHoursContinuously*)ctr;
00953                      if(teacherName==crt_constraint->teacherName)
00954                             this->removeTimeConstraint(ctr); //single constraint removal
00955                      else
00956                             i++;
00957               }
00958               else
00959                      i++;
00960        }
00961 
00962        for(int i=0; i<this->timeConstraintsList.size(); ){
00963               TimeConstraint* ctr=this->timeConstraintsList[i];
00964               if(ctr->type==CONSTRAINT_TEACHER_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
00965                      ConstraintTeacherActivityTagMaxHoursContinuously* crt_constraint=(ConstraintTeacherActivityTagMaxHoursContinuously*)ctr;
00966                      if(teacherName==crt_constraint->teacherName)
00967                             this->removeTimeConstraint(ctr); //single constraint removal
00968                      else
00969                             i++;
00970               }
00971               else
00972                      i++;
00973        }
00974 
00975        for(int i=0; i<this->timeConstraintsList.size(); ){
00976               TimeConstraint* ctr=this->timeConstraintsList[i];
00977               if(ctr->type==CONSTRAINT_TEACHER_ACTIVITY_TAG_MAX_HOURS_DAILY){
00978                      ConstraintTeacherActivityTagMaxHoursDaily* crt_constraint=(ConstraintTeacherActivityTagMaxHoursDaily*)ctr;
00979                      if(teacherName==crt_constraint->teacherName)
00980                             this->removeTimeConstraint(ctr); //single constraint removal
00981                      else
00982                             i++;
00983               }
00984               else
00985                      i++;
00986        }
00987 
00988        for(int i=0; i<this->timeConstraintsList.size(); ){
00989               TimeConstraint* ctr=this->timeConstraintsList[i];
00990               if(ctr->type==CONSTRAINT_TEACHER_MIN_HOURS_DAILY){
00991                      ConstraintTeacherMinHoursDaily* crt_constraint=(ConstraintTeacherMinHoursDaily*)ctr;
00992                      if(teacherName==crt_constraint->teacherName)
00993                             this->removeTimeConstraint(ctr); //single constraint removal
00994                      else
00995                             i++;
00996               }
00997               else
00998                      i++;
00999        }
01000 
01001        for(int i=0; i<this->timeConstraintsList.size(); ){
01002               TimeConstraint* ctr=this->timeConstraintsList[i];
01003               if(ctr->type==CONSTRAINT_TEACHER_MAX_DAYS_PER_WEEK){
01004                      ConstraintTeacherMaxDaysPerWeek* crt_constraint=(ConstraintTeacherMaxDaysPerWeek*)ctr;
01005                      if(teacherName==crt_constraint->teacherName)
01006                             this->removeTimeConstraint(ctr); //single constraint removal
01007                      else
01008                             i++;
01009               }
01010               else
01011                      i++;
01012        }
01013 
01014        for(int i=0; i<this->timeConstraintsList.size(); ){
01015               TimeConstraint* ctr=this->timeConstraintsList[i];
01016               if(ctr->type==CONSTRAINT_TEACHER_MIN_DAYS_PER_WEEK){
01017                      ConstraintTeacherMinDaysPerWeek* crt_constraint=(ConstraintTeacherMinDaysPerWeek*)ctr;
01018                      if(teacherName==crt_constraint->teacherName)
01019                             this->removeTimeConstraint(ctr); //single constraint removal
01020                      else
01021                             i++;
01022               }
01023               else
01024                      i++;
01025        }
01026 
01027        for(int i=0; i<this->timeConstraintsList.size(); ){
01028               TimeConstraint* ctr=this->timeConstraintsList[i];
01029               if(ctr->type==CONSTRAINT_TEACHER_INTERVAL_MAX_DAYS_PER_WEEK){
01030                      ConstraintTeacherIntervalMaxDaysPerWeek* crt_constraint=(ConstraintTeacherIntervalMaxDaysPerWeek*)ctr;
01031                      if(teacherName==crt_constraint->teacherName)
01032                             this->removeTimeConstraint(ctr); //single constraint removal
01033                      else
01034                             i++;
01035               }
01036               else
01037                      i++;
01038        }
01039 
01040        for(int i=0; i<this->timeConstraintsList.size(); ){
01041               TimeConstraint* ctr=this->timeConstraintsList[i];
01042               if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_TIME_SLOTS){
01043                      ConstraintActivitiesPreferredTimeSlots* crt_constraint=(ConstraintActivitiesPreferredTimeSlots*)ctr;
01044                      if(teacherName==crt_constraint->p_teacherName)
01045                             this->removeTimeConstraint(ctr); //single constraint removal
01046                      else
01047                             i++;
01048               }
01049               else
01050                      i++;
01051        }
01052 
01053        for(int i=0; i<this->timeConstraintsList.size(); ){
01054               TimeConstraint* ctr=this->timeConstraintsList[i];
01055               if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_STARTING_TIMES){
01056                      ConstraintActivitiesPreferredStartingTimes* crt_constraint=(ConstraintActivitiesPreferredStartingTimes*)ctr;
01057                      if(teacherName==crt_constraint->teacherName)
01058                             this->removeTimeConstraint(ctr); //single constraint removal
01059                      else
01060                             i++;
01061               }
01062               else
01063                      i++;
01064        }
01065 
01066        for(int i=0; i<this->timeConstraintsList.size(); ){
01067               TimeConstraint* ctr=this->timeConstraintsList[i];
01068               if(ctr->type==CONSTRAINT_ACTIVITIES_END_STUDENTS_DAY){
01069                      ConstraintActivitiesEndStudentsDay* crt_constraint=(ConstraintActivitiesEndStudentsDay*)ctr;
01070                      if(teacherName==crt_constraint->teacherName)
01071                             this->removeTimeConstraint(ctr); //single constraint removal
01072                      else
01073                             i++;
01074               }
01075               else
01076                      i++;
01077        }
01078 
01079        for(int i=0; i<this->timeConstraintsList.size(); ){
01080               TimeConstraint* ctr=this->timeConstraintsList[i];
01081               if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_TIME_SLOTS){
01082                      ConstraintSubactivitiesPreferredTimeSlots* crt_constraint=(ConstraintSubactivitiesPreferredTimeSlots*)ctr;
01083                      if(teacherName==crt_constraint->p_teacherName)
01084                             this->removeTimeConstraint(ctr); //single constraint removal
01085                      else
01086                             i++;
01087               }
01088               else
01089                      i++;
01090        }
01091 
01092        for(int i=0; i<this->timeConstraintsList.size(); ){
01093               TimeConstraint* ctr=this->timeConstraintsList[i];
01094               if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_STARTING_TIMES){
01095                      ConstraintSubactivitiesPreferredStartingTimes* crt_constraint=(ConstraintSubactivitiesPreferredStartingTimes*)ctr;
01096                      if(teacherName==crt_constraint->teacherName)
01097                             this->removeTimeConstraint(ctr); //single constraint removal
01098                      else
01099                             i++;
01100               }
01101               else
01102                      i++;
01103        }
01104 
01105 
01106        for(int i=0; i<this->spaceConstraintsList.size(); ){
01107               SpaceConstraint* ctr=this->spaceConstraintsList[i];
01108               if(ctr->type==CONSTRAINT_TEACHER_HOME_ROOM){
01109                      ConstraintTeacherHomeRoom* crt_constraint=(ConstraintTeacherHomeRoom*)ctr;
01110                      if(teacherName==crt_constraint->teacherName)
01111                             this->removeSpaceConstraint(ctr); //single constraint removal
01112                      else
01113                             i++;
01114               }
01115               else
01116                      i++;
01117        }
01118 
01119        for(int i=0; i<this->spaceConstraintsList.size(); ){
01120               SpaceConstraint* ctr=this->spaceConstraintsList[i];
01121               if(ctr->type==CONSTRAINT_TEACHER_HOME_ROOMS){
01122                      ConstraintTeacherHomeRooms* crt_constraint=(ConstraintTeacherHomeRooms*)ctr;
01123                      if(teacherName==crt_constraint->teacherName)
01124                             this->removeSpaceConstraint(ctr); //single constraint removal
01125                      else
01126                             i++;
01127               }
01128               else
01129                      i++;
01130        }
01131 
01132        for(int i=0; i<this->spaceConstraintsList.size(); ){
01133               SpaceConstraint* ctr=this->spaceConstraintsList[i];
01134               if(ctr->type==CONSTRAINT_TEACHER_MAX_BUILDING_CHANGES_PER_DAY){
01135                      ConstraintTeacherMaxBuildingChangesPerDay* crt_constraint=(ConstraintTeacherMaxBuildingChangesPerDay*)ctr;
01136                      if(teacherName==crt_constraint->teacherName)
01137                             this->removeSpaceConstraint(ctr); //single constraint removal
01138                      else
01139                             i++;
01140               }
01141               else
01142                      i++;
01143        }
01144        for(int i=0; i<this->spaceConstraintsList.size(); ){
01145               SpaceConstraint* ctr=this->spaceConstraintsList[i];
01146               if(ctr->type==CONSTRAINT_TEACHER_MAX_BUILDING_CHANGES_PER_WEEK){
01147                      ConstraintTeacherMaxBuildingChangesPerWeek* crt_constraint=(ConstraintTeacherMaxBuildingChangesPerWeek*)ctr;
01148                      if(teacherName==crt_constraint->teacherName)
01149                             this->removeSpaceConstraint(ctr); //single constraint removal
01150                      else
01151                             i++;
01152               }
01153               else
01154                      i++;
01155        }
01156        for(int i=0; i<this->spaceConstraintsList.size(); ){
01157               SpaceConstraint* ctr=this->spaceConstraintsList[i];
01158               if(ctr->type==CONSTRAINT_TEACHER_MIN_GAPS_BETWEEN_BUILDING_CHANGES){
01159                      ConstraintTeacherMinGapsBetweenBuildingChanges* crt_constraint=(ConstraintTeacherMinGapsBetweenBuildingChanges*)ctr;
01160                      if(teacherName==crt_constraint->teacherName)
01161                             this->removeSpaceConstraint(ctr); //single constraint removal
01162                      else
01163                             i++;
01164               }
01165               else
01166                      i++;
01167        }
01168 
01169 
01170 
01171        for(int i=0; i<this->teachersList.size(); i++)
01172               if(this->teachersList.at(i)->name==teacherName){
01173                      Teacher* tch=this->teachersList[i];
01174                      this->teachersList.removeAt(i);
01175                      delete tch;
01176                      break;
01177               }
01178        
01179        this->internalStructureComputed=false;
01180        setRulesModifiedAndOtherThings(this);
01181 
01182        teachers_schedule_ready=false;
01183        students_schedule_ready=false;
01184        rooms_schedule_ready=false;
01185 
01186        return true;
01187 }
01188 
01189 bool Rules::modifyTeacher(const QString& initialTeacherName, const QString& finalTeacherName)
01190 {
01191        assert(this->searchTeacher(finalTeacherName)==-1);
01192        assert(this->searchTeacher(initialTeacherName)>=0);
01193 
01194        //TODO: improve this part
01195        for(int i=0; i<this->activitiesList.size(); i++)
01196               this->activitiesList.at(i)->renameTeacher(initialTeacherName, finalTeacherName);
01197 
01198        for(int i=0; i<this->timeConstraintsList.size(); i++){
01199               TimeConstraint* ctr=this->timeConstraintsList[i];       
01200 
01201               if(ctr->type==CONSTRAINT_TEACHER_NOT_AVAILABLE_TIMES){
01202                      ConstraintTeacherNotAvailableTimes* crt_constraint=(ConstraintTeacherNotAvailableTimes*)ctr;
01203                      if(initialTeacherName == crt_constraint->teacher)
01204                             crt_constraint->teacher=finalTeacherName;
01205               }
01206        }
01207 
01208        for(int i=0; i<this->timeConstraintsList.size(); i++){
01209               TimeConstraint* ctr=this->timeConstraintsList[i];       
01210 
01211               if(ctr->type==CONSTRAINT_TEACHER_MAX_GAPS_PER_WEEK){
01212                      ConstraintTeacherMaxGapsPerWeek* crt_constraint=(ConstraintTeacherMaxGapsPerWeek*)ctr;
01213                      if(initialTeacherName == crt_constraint->teacherName)
01214                             crt_constraint->teacherName=finalTeacherName;
01215               }
01216        }
01217 
01218        for(int i=0; i<this->timeConstraintsList.size(); i++){
01219               TimeConstraint* ctr=this->timeConstraintsList[i];       
01220 
01221               if(ctr->type==CONSTRAINT_TEACHER_MAX_GAPS_PER_DAY){
01222                      ConstraintTeacherMaxGapsPerDay* crt_constraint=(ConstraintTeacherMaxGapsPerDay*)ctr;
01223                      if(initialTeacherName == crt_constraint->teacherName)
01224                             crt_constraint->teacherName=finalTeacherName;
01225               }
01226        }
01227 
01228        for(int i=0; i<this->timeConstraintsList.size(); i++){
01229               TimeConstraint* ctr=this->timeConstraintsList[i];       
01230 
01231               if(ctr->type==CONSTRAINT_TEACHER_MAX_HOURS_DAILY){
01232                      ConstraintTeacherMaxHoursDaily* crt_constraint=(ConstraintTeacherMaxHoursDaily*)ctr;
01233                      if(initialTeacherName == crt_constraint->teacherName)
01234                             crt_constraint->teacherName=finalTeacherName;
01235               }
01236        }
01237 
01238        for(int i=0; i<this->timeConstraintsList.size(); i++){
01239               TimeConstraint* ctr=this->timeConstraintsList[i];       
01240 
01241               if(ctr->type==CONSTRAINT_TEACHER_MAX_HOURS_CONTINUOUSLY){
01242                      ConstraintTeacherMaxHoursContinuously* crt_constraint=(ConstraintTeacherMaxHoursContinuously*)ctr;
01243                      if(initialTeacherName == crt_constraint->teacherName)
01244                             crt_constraint->teacherName=finalTeacherName;
01245               }
01246        }
01247 
01248        for(int i=0; i<this->timeConstraintsList.size(); i++){
01249               TimeConstraint* ctr=this->timeConstraintsList[i];       
01250 
01251               if(ctr->type==CONSTRAINT_TEACHER_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
01252                      ConstraintTeacherActivityTagMaxHoursContinuously* crt_constraint=(ConstraintTeacherActivityTagMaxHoursContinuously*)ctr;
01253                      if(initialTeacherName == crt_constraint->teacherName)
01254                             crt_constraint->teacherName=finalTeacherName;
01255               }
01256        }
01257 
01258        for(int i=0; i<this->timeConstraintsList.size(); i++){
01259               TimeConstraint* ctr=this->timeConstraintsList[i];       
01260 
01261               if(ctr->type==CONSTRAINT_TEACHER_ACTIVITY_TAG_MAX_HOURS_DAILY){
01262                      ConstraintTeacherActivityTagMaxHoursDaily* crt_constraint=(ConstraintTeacherActivityTagMaxHoursDaily*)ctr;
01263                      if(initialTeacherName == crt_constraint->teacherName)
01264                             crt_constraint->teacherName=finalTeacherName;
01265               }
01266        }
01267 
01268        for(int i=0; i<this->timeConstraintsList.size(); i++){
01269               TimeConstraint* ctr=this->timeConstraintsList[i];       
01270 
01271               if(ctr->type==CONSTRAINT_TEACHER_MIN_HOURS_DAILY){
01272                      ConstraintTeacherMinHoursDaily* crt_constraint=(ConstraintTeacherMinHoursDaily*)ctr;
01273                      if(initialTeacherName == crt_constraint->teacherName)
01274                             crt_constraint->teacherName=finalTeacherName;
01275               }
01276        }
01277 
01278        for(int i=0; i<this->timeConstraintsList.size(); i++){
01279               TimeConstraint* ctr=this->timeConstraintsList[i];       
01280 
01281               if(ctr->type==CONSTRAINT_TEACHER_MAX_DAYS_PER_WEEK){
01282                      ConstraintTeacherMaxDaysPerWeek* crt_constraint=(ConstraintTeacherMaxDaysPerWeek*)ctr;
01283                      if(initialTeacherName == crt_constraint->teacherName)
01284                             crt_constraint->teacherName=finalTeacherName;
01285               }
01286        }
01287        
01288        for(int i=0; i<this->timeConstraintsList.size(); i++){
01289               TimeConstraint* ctr=this->timeConstraintsList[i];       
01290 
01291               if(ctr->type==CONSTRAINT_TEACHER_MIN_DAYS_PER_WEEK){
01292                      ConstraintTeacherMinDaysPerWeek* crt_constraint=(ConstraintTeacherMinDaysPerWeek*)ctr;
01293                      if(initialTeacherName == crt_constraint->teacherName)
01294                             crt_constraint->teacherName=finalTeacherName;
01295               }
01296        }
01297        
01298        for(int i=0; i<this->timeConstraintsList.size(); i++){
01299               TimeConstraint* ctr=this->timeConstraintsList[i];       
01300 
01301               if(ctr->type==CONSTRAINT_TEACHER_INTERVAL_MAX_DAYS_PER_WEEK){
01302                      ConstraintTeacherIntervalMaxDaysPerWeek* crt_constraint=(ConstraintTeacherIntervalMaxDaysPerWeek*)ctr;
01303                      if(initialTeacherName == crt_constraint->teacherName)
01304                             crt_constraint->teacherName=finalTeacherName;
01305               }
01306        }
01307        
01308        for(int i=0; i<this->timeConstraintsList.size(); i++){
01309               TimeConstraint* ctr=this->timeConstraintsList[i];       
01310 
01311               if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_TIME_SLOTS){
01312                      ConstraintActivitiesPreferredTimeSlots* crt_constraint=(ConstraintActivitiesPreferredTimeSlots*)ctr;
01313                      if(initialTeacherName == crt_constraint->p_teacherName)
01314                             crt_constraint->p_teacherName=finalTeacherName;
01315               }
01316        }
01317        
01318        for(int i=0; i<this->timeConstraintsList.size(); i++){
01319               TimeConstraint* ctr=this->timeConstraintsList[i];       
01320 
01321               if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_STARTING_TIMES){
01322                      ConstraintActivitiesPreferredStartingTimes* crt_constraint=(ConstraintActivitiesPreferredStartingTimes*)ctr;
01323                      if(initialTeacherName == crt_constraint->teacherName)
01324                             crt_constraint->teacherName=finalTeacherName;
01325               }
01326        }
01327        
01328        for(int i=0; i<this->timeConstraintsList.size(); i++){
01329               TimeConstraint* ctr=this->timeConstraintsList[i];       
01330 
01331               if(ctr->type==CONSTRAINT_ACTIVITIES_END_STUDENTS_DAY){
01332                      ConstraintActivitiesEndStudentsDay* crt_constraint=(ConstraintActivitiesEndStudentsDay*)ctr;
01333                      if(initialTeacherName == crt_constraint->teacherName)
01334                             crt_constraint->teacherName=finalTeacherName;
01335               }
01336        }
01337        
01338        for(int i=0; i<this->timeConstraintsList.size(); i++){
01339               TimeConstraint* ctr=this->timeConstraintsList[i];       
01340 
01341               if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_TIME_SLOTS){
01342                      ConstraintSubactivitiesPreferredTimeSlots* crt_constraint=(ConstraintSubactivitiesPreferredTimeSlots*)ctr;
01343                      if(initialTeacherName == crt_constraint->p_teacherName)
01344                             crt_constraint->p_teacherName=finalTeacherName;
01345               }
01346        }
01347        
01348        for(int i=0; i<this->timeConstraintsList.size(); i++){
01349               TimeConstraint* ctr=this->timeConstraintsList[i];       
01350 
01351               if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_STARTING_TIMES){
01352                      ConstraintSubactivitiesPreferredStartingTimes* crt_constraint=(ConstraintSubactivitiesPreferredStartingTimes*)ctr;
01353                      if(initialTeacherName == crt_constraint->teacherName)
01354                             crt_constraint->teacherName=finalTeacherName;
01355               }
01356        }
01357        
01358 
01359        for(int i=0; i<this->spaceConstraintsList.size(); i++){
01360               SpaceConstraint* ctr=this->spaceConstraintsList[i];     
01361 
01362               if(ctr->type==CONSTRAINT_TEACHER_HOME_ROOM){
01363                      ConstraintTeacherHomeRoom* crt_constraint=(ConstraintTeacherHomeRoom*)ctr;
01364                      if(initialTeacherName == crt_constraint->teacherName)
01365                             crt_constraint->teacherName=finalTeacherName;
01366               }
01367        }
01368        
01369        for(int i=0; i<this->spaceConstraintsList.size(); i++){
01370               SpaceConstraint* ctr=this->spaceConstraintsList[i];     
01371 
01372               if(ctr->type==CONSTRAINT_TEACHER_HOME_ROOMS){
01373                      ConstraintTeacherHomeRooms* crt_constraint=(ConstraintTeacherHomeRooms*)ctr;
01374                      if(initialTeacherName == crt_constraint->teacherName)
01375                             crt_constraint->teacherName=finalTeacherName;
01376               }
01377        }
01378        
01379        for(int i=0; i<this->spaceConstraintsList.size(); i++){
01380               SpaceConstraint* ctr=this->spaceConstraintsList[i];     
01381 
01382               if(ctr->type==CONSTRAINT_TEACHER_MAX_BUILDING_CHANGES_PER_DAY){
01383                      ConstraintTeacherMaxBuildingChangesPerDay* crt_constraint=(ConstraintTeacherMaxBuildingChangesPerDay*)ctr;
01384                      if(initialTeacherName == crt_constraint->teacherName)
01385                             crt_constraint->teacherName=finalTeacherName;
01386               }
01387        }
01388        for(int i=0; i<this->spaceConstraintsList.size(); i++){
01389               SpaceConstraint* ctr=this->spaceConstraintsList[i];     
01390 
01391               if(ctr->type==CONSTRAINT_TEACHER_MAX_BUILDING_CHANGES_PER_WEEK){
01392                      ConstraintTeacherMaxBuildingChangesPerWeek* crt_constraint=(ConstraintTeacherMaxBuildingChangesPerWeek*)ctr;
01393                      if(initialTeacherName == crt_constraint->teacherName)
01394                             crt_constraint->teacherName=finalTeacherName;
01395               }
01396        }
01397        for(int i=0; i<this->spaceConstraintsList.size(); i++){
01398               SpaceConstraint* ctr=this->spaceConstraintsList[i];     
01399 
01400               if(ctr->type==CONSTRAINT_TEACHER_MIN_GAPS_BETWEEN_BUILDING_CHANGES){
01401                      ConstraintTeacherMinGapsBetweenBuildingChanges* crt_constraint=(ConstraintTeacherMinGapsBetweenBuildingChanges*)ctr;
01402                      if(initialTeacherName == crt_constraint->teacherName)
01403                             crt_constraint->teacherName=finalTeacherName;
01404               }
01405        }
01406        
01407 
01408 
01409        int t=0;
01410        for(int i=0; i<this->teachersList.size(); i++){
01411               Teacher* tch=this->teachersList[i];
01412 
01413               if(tch->name==initialTeacherName){
01414                      tch->name=finalTeacherName;
01415                      t++;
01416               }
01417        }
01418        assert(t<=1);
01419 
01420        this->internalStructureComputed=false;
01421        setRulesModifiedAndOtherThings(this);
01422 
01423        if(t==0)
01424               return false;
01425        else
01426               return true;
01427 }
01428 
01429 void Rules::sortTeachersAlphabetically()
01430 {
01431        qSort(this->teachersList.begin(), this->teachersList.end(), teachersAscending);
01432 
01433        this->internalStructureComputed=false;
01434        setRulesModifiedAndOtherThings(this);
01435 }
01436 
01437 bool Rules::addSubject(Subject* subject)
01438 {
01439        for(int i=0; i<this->subjectsList.size(); i++){
01440               Subject* sbj=this->subjectsList[i];       
01441               if(sbj->name==subject->name)
01442                      return false;
01443        }
01444        
01445        this->internalStructureComputed=false;
01446        setRulesModifiedAndOtherThings(this);
01447 
01448        teachers_schedule_ready=false;
01449        students_schedule_ready=false;
01450        rooms_schedule_ready=false;
01451 
01452        this->subjectsList << subject;
01453        return true;
01454 }
01455 
01456 bool Rules::addSubjectFast(Subject* subject)
01457 {
01458        this->internalStructureComputed=false;
01459        setRulesModifiedAndOtherThings(this);
01460 
01461        teachers_schedule_ready=false;
01462        students_schedule_ready=false;
01463        rooms_schedule_ready=false;
01464 
01465        this->subjectsList << subject;
01466        return true;
01467 }
01468 
01469 int Rules::searchSubject(const QString& subjectName)
01470 {
01471        for(int i=0; i<this->subjectsList.size(); i++)
01472               if(this->subjectsList.at(i)->name == subjectName)
01473                      return i;
01474 
01475        return -1;
01476 }
01477 
01478 bool Rules::removeSubject(const QString& subjectName)
01479 {
01480        //check the activities first
01481        for(int i=0; i<this->activitiesList.size(); ){
01482               Activity* act=this->activitiesList[i];
01483               if(act->subjectName==subjectName){
01484                      this->removeActivity(act->id, act->activityGroupId);
01485                      i=0;
01486                      //(You have to be careful, there can be erased more activities here)
01487               }
01488               else
01489                      i++;
01490        }
01491        
01492        //delete the time constraints related to this subject
01493 
01494        for(int i=0; i<this->timeConstraintsList.size(); ){
01495               TimeConstraint* ctr=this->timeConstraintsList[i];
01496               if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_TIME_SLOTS){
01497                      ConstraintActivitiesPreferredTimeSlots* crt_constraint=(ConstraintActivitiesPreferredTimeSlots*)ctr;
01498                      if(subjectName==crt_constraint->p_subjectName)
01499                             this->removeTimeConstraint(ctr); //single constraint removal
01500                      else
01501                             i++;
01502               }
01503               else
01504                      i++;
01505        }
01506 
01507        for(int i=0; i<this->timeConstraintsList.size(); ){
01508               TimeConstraint* ctr=this->timeConstraintsList[i];
01509               if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_STARTING_TIMES){
01510                      ConstraintActivitiesPreferredStartingTimes* crt_constraint=(ConstraintActivitiesPreferredStartingTimes*)ctr;
01511                      if(subjectName==crt_constraint->subjectName)
01512                             this->removeTimeConstraint(ctr); //single constraint removal
01513                      else
01514                             i++;
01515               }
01516               else
01517                      i++;
01518        }
01519 
01520        for(int i=0; i<this->timeConstraintsList.size(); ){
01521               TimeConstraint* ctr=this->timeConstraintsList[i];
01522               if(ctr->type==CONSTRAINT_ACTIVITIES_END_STUDENTS_DAY){
01523                      ConstraintActivitiesEndStudentsDay* crt_constraint=(ConstraintActivitiesEndStudentsDay*)ctr;
01524                      if(subjectName==crt_constraint->subjectName)
01525                             this->removeTimeConstraint(ctr); //single constraint removal
01526                      else
01527                             i++;
01528               }
01529               else
01530                      i++;
01531        }
01532 
01533        for(int i=0; i<this->timeConstraintsList.size(); ){
01534               TimeConstraint* ctr=this->timeConstraintsList[i];
01535               if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_TIME_SLOTS){
01536                      ConstraintSubactivitiesPreferredTimeSlots* crt_constraint=(ConstraintSubactivitiesPreferredTimeSlots*)ctr;
01537                      if(subjectName==crt_constraint->p_subjectName)
01538                             this->removeTimeConstraint(ctr); //single constraint removal
01539                      else
01540                             i++;
01541               }
01542               else
01543                      i++;
01544        }
01545 
01546        for(int i=0; i<this->timeConstraintsList.size(); ){
01547               TimeConstraint* ctr=this->timeConstraintsList[i];
01548               if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_STARTING_TIMES){
01549                      ConstraintSubactivitiesPreferredStartingTimes* crt_constraint=(ConstraintSubactivitiesPreferredStartingTimes*)ctr;
01550                      if(subjectName==crt_constraint->subjectName)
01551                             this->removeTimeConstraint(ctr); //single constraint removal
01552                      else
01553                             i++;
01554               }
01555               else
01556                      i++;
01557        }
01558 
01559        //delete the space constraints related to this subject
01560        for(int i=0; i<this->spaceConstraintsList.size(); ){
01561               SpaceConstraint* ctr=this->spaceConstraintsList[i];
01562 
01563               if(ctr->type==CONSTRAINT_SUBJECT_PREFERRED_ROOM){
01564                      ConstraintSubjectPreferredRoom* c=(ConstraintSubjectPreferredRoom*)ctr;
01565 
01566                      if(c->subjectName == subjectName)
01567                             this->removeSpaceConstraint(ctr);
01568                      else
01569                             i++;
01570               }
01571               else if(ctr->type==CONSTRAINT_SUBJECT_PREFERRED_ROOMS){
01572                      ConstraintSubjectPreferredRooms* c=(ConstraintSubjectPreferredRooms*)ctr;
01573 
01574                      if(c->subjectName == subjectName)
01575                             this->removeSpaceConstraint(ctr);
01576                      else
01577                             i++;
01578               }
01579               else if(ctr->type==CONSTRAINT_SUBJECT_ACTIVITY_TAG_PREFERRED_ROOM){
01580                      ConstraintSubjectActivityTagPreferredRoom* c=(ConstraintSubjectActivityTagPreferredRoom*)ctr;
01581 
01582                      if(c->subjectName == subjectName)
01583                             this->removeSpaceConstraint(ctr);
01584                      else
01585                             i++;
01586               }
01587               else if(ctr->type==CONSTRAINT_SUBJECT_ACTIVITY_TAG_PREFERRED_ROOMS){
01588                      ConstraintSubjectActivityTagPreferredRooms* c=(ConstraintSubjectActivityTagPreferredRooms*)ctr;
01589 
01590                      if(c->subjectName == subjectName)
01591                             this->removeSpaceConstraint(ctr);
01592                      else
01593                             i++;
01594               }
01595               else
01596                      i++;
01597        }
01598 
01599        //remove the subject from the list
01600        for(int i=0; i<this->subjectsList.size(); i++)
01601               if(this->subjectsList[i]->name==subjectName){
01602                      Subject* sbj=this->subjectsList[i];
01603                      this->subjectsList.removeAt(i);
01604                      delete sbj;
01605                      break;
01606               }
01607        
01608        this->internalStructureComputed=false;
01609        setRulesModifiedAndOtherThings(this);
01610 
01611        teachers_schedule_ready=false;
01612        students_schedule_ready=false;
01613        rooms_schedule_ready=false;
01614 
01615        return true;
01616 }
01617 
01618 bool Rules::modifySubject(const QString& initialSubjectName, const QString& finalSubjectName)
01619 {
01620        assert(this->searchSubject(finalSubjectName)==-1);
01621        assert(this->searchSubject(initialSubjectName)>=0);
01622 
01623        //check the activities first
01624        for(int i=0; i<this->activitiesList.size(); i++){
01625               Activity* act=this->activitiesList[i];
01626 
01627               if( act->subjectName == initialSubjectName)
01628                      act->subjectName=finalSubjectName;
01629        }
01630        
01631        //modify the time constraints related to this subject
01632        for(int i=0; i<this->timeConstraintsList.size(); i++){
01633               TimeConstraint* ctr=this->timeConstraintsList[i];
01634 
01635               if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_TIME_SLOTS){
01636                      ConstraintActivitiesPreferredTimeSlots* crt_constraint=(ConstraintActivitiesPreferredTimeSlots*)ctr;
01637                      if(initialSubjectName == crt_constraint->p_subjectName)
01638                             crt_constraint->p_subjectName=finalSubjectName;
01639               }
01640        }
01641 
01642        //modify the time constraints related to this subject
01643        for(int i=0; i<this->timeConstraintsList.size(); i++){
01644               TimeConstraint* ctr=this->timeConstraintsList[i];
01645 
01646               if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_STARTING_TIMES){
01647                      ConstraintActivitiesPreferredStartingTimes* crt_constraint=(ConstraintActivitiesPreferredStartingTimes*)ctr;
01648                      if(initialSubjectName == crt_constraint->subjectName)
01649                             crt_constraint->subjectName=finalSubjectName;
01650               }
01651        }
01652 
01653        //modify the time constraints related to this subject
01654        for(int i=0; i<this->timeConstraintsList.size(); i++){
01655               TimeConstraint* ctr=this->timeConstraintsList[i];
01656 
01657               if(ctr->type==CONSTRAINT_ACTIVITIES_END_STUDENTS_DAY){
01658                      ConstraintActivitiesEndStudentsDay* crt_constraint=(ConstraintActivitiesEndStudentsDay*)ctr;
01659                      if(initialSubjectName == crt_constraint->subjectName)
01660                             crt_constraint->subjectName=finalSubjectName;
01661               }
01662        }
01663 
01664        //modify the time constraints related to this subject
01665        for(int i=0; i<this->timeConstraintsList.size(); i++){
01666               TimeConstraint* ctr=this->timeConstraintsList[i];
01667 
01668               if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_TIME_SLOTS){
01669                      ConstraintSubactivitiesPreferredTimeSlots* crt_constraint=(ConstraintSubactivitiesPreferredTimeSlots*)ctr;
01670                      if(initialSubjectName == crt_constraint->p_subjectName)
01671                             crt_constraint->p_subjectName=finalSubjectName;
01672               }
01673        }
01674 
01675        //modify the time constraints related to this subject
01676        for(int i=0; i<this->timeConstraintsList.size(); i++){
01677               TimeConstraint* ctr=this->timeConstraintsList[i];
01678 
01679               if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_STARTING_TIMES){
01680                      ConstraintSubactivitiesPreferredStartingTimes* crt_constraint=(ConstraintSubactivitiesPreferredStartingTimes*)ctr;
01681                      if(initialSubjectName == crt_constraint->subjectName)
01682                             crt_constraint->subjectName=finalSubjectName;
01683               }
01684        }
01685 
01686        //modify the space constraints related to this subject
01687        for(int i=0; i<this->spaceConstraintsList.size(); i++){
01688               SpaceConstraint* ctr=this->spaceConstraintsList[i];
01689 
01690               if(ctr->type==CONSTRAINT_SUBJECT_PREFERRED_ROOM){
01691                      ConstraintSubjectPreferredRoom* c=(ConstraintSubjectPreferredRoom*)ctr;
01692                      if(c->subjectName == initialSubjectName)
01693                             c->subjectName=finalSubjectName;
01694               }
01695               else if(ctr->type==CONSTRAINT_SUBJECT_PREFERRED_ROOMS){
01696                      ConstraintSubjectPreferredRooms* c=(ConstraintSubjectPreferredRooms*)ctr;
01697                      if(c->subjectName == initialSubjectName)
01698                             c->subjectName=finalSubjectName;
01699               }
01700               else if(ctr->type==CONSTRAINT_SUBJECT_ACTIVITY_TAG_PREFERRED_ROOM){
01701                      ConstraintSubjectActivityTagPreferredRoom* c=(ConstraintSubjectActivityTagPreferredRoom*)ctr;
01702                      if(c->subjectName == initialSubjectName)
01703                             c->subjectName=finalSubjectName;
01704               }
01705               else if(ctr->type==CONSTRAINT_SUBJECT_ACTIVITY_TAG_PREFERRED_ROOMS){
01706                      ConstraintSubjectActivityTagPreferredRooms* c=(ConstraintSubjectActivityTagPreferredRooms*)ctr;
01707                      if(c->subjectName == initialSubjectName)
01708                             c->subjectName=finalSubjectName;
01709               }
01710        }
01711 
01712 
01713        //rename the subject in the list
01714        int t=0;
01715        for(int i=0; i<this->subjectsList.size(); i++){
01716               Subject* sbj=this->subjectsList[i];
01717 
01718               if(sbj->name==initialSubjectName){
01719                      t++;
01720                      sbj->name=finalSubjectName;
01721               }
01722        }
01723        assert(t<=1);
01724 
01725        this->internalStructureComputed=false;
01726        setRulesModifiedAndOtherThings(this);
01727 
01728        return true;
01729 }
01730 
01731 void Rules::sortSubjectsAlphabetically()
01732 {
01733        qSort(this->subjectsList.begin(), this->subjectsList.end(), subjectsAscending);
01734 
01735        this->internalStructureComputed=false;
01736        setRulesModifiedAndOtherThings(this);
01737 }
01738 
01739 bool Rules::addActivityTag(ActivityTag* activityTag)
01740 {
01741        for(int i=0; i<this->activityTagsList.size(); i++){
01742               ActivityTag* sbt=this->activityTagsList[i];
01743 
01744               if(sbt->name==activityTag->name)
01745                      return false;
01746        }
01747 
01748        this->internalStructureComputed=false;
01749        setRulesModifiedAndOtherThings(this);
01750 
01751        teachers_schedule_ready=false;
01752        students_schedule_ready=false;
01753        rooms_schedule_ready=false;
01754 
01755        this->activityTagsList << activityTag;
01756        return true;
01757 }
01758 
01759 bool Rules::addActivityTagFast(ActivityTag* activityTag)
01760 {
01761        this->internalStructureComputed=false;
01762        setRulesModifiedAndOtherThings(this);
01763 
01764        teachers_schedule_ready=false;
01765        students_schedule_ready=false;
01766        rooms_schedule_ready=false;
01767 
01768        this->activityTagsList << activityTag;
01769        return true;
01770 }
01771 
01772 int Rules::searchActivityTag(const QString& activityTagName)
01773 {
01774        for(int i=0; i<this->activityTagsList.size(); i++)
01775               if(this->activityTagsList.at(i)->name==activityTagName)
01776                      return i;
01777 
01778        return -1;
01779 }
01780 
01781 bool Rules::removeActivityTag(const QString& activityTagName)
01782 {
01783        //check the activities first
01784        for(int i=0; i<this->activitiesList.size(); i++){
01785               Activity* act=this->activitiesList[i];
01786 
01787               //if( act->activityTagName == activityTagName)
01788               //     act->activityTagName="";
01789               if( act->activityTagsNames.contains(activityTagName) )
01790                      act->activityTagsNames.removeAll(activityTagName);
01791        }
01792        
01793        //delete the time constraints related to this activity tag
01794        for(int i=0; i<this->timeConstraintsList.size(); ){
01795               TimeConstraint* ctr=this->timeConstraintsList[i];
01796               
01797               if(ctr->type==CONSTRAINT_TEACHER_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
01798                      ConstraintTeacherActivityTagMaxHoursContinuously* crt_constraint=(ConstraintTeacherActivityTagMaxHoursContinuously*)ctr;
01799                      if(activityTagName == crt_constraint->activityTagName)
01800                             this->removeTimeConstraint(ctr); //single constraint removal
01801                      else
01802                             i++;
01803               }
01804               else
01805                      i++;
01806        }
01807        //delete the time constraints related to this activity tag
01808        for(int i=0; i<this->timeConstraintsList.size(); ){
01809               TimeConstraint* ctr=this->timeConstraintsList[i];
01810               
01811               if(ctr->type==CONSTRAINT_TEACHER_ACTIVITY_TAG_MAX_HOURS_DAILY){
01812                      ConstraintTeacherActivityTagMaxHoursDaily* crt_constraint=(ConstraintTeacherActivityTagMaxHoursDaily*)ctr;
01813                      if(activityTagName == crt_constraint->activityTagName)
01814                             this->removeTimeConstraint(ctr); //single constraint removal
01815                      else
01816                             i++;
01817               }
01818               else
01819                      i++;
01820        }
01821        //delete the time constraints related to this activity tag
01822        for(int i=0; i<this->timeConstraintsList.size(); ){
01823               TimeConstraint* ctr=this->timeConstraintsList[i];
01824               
01825               if(ctr->type==CONSTRAINT_TEACHERS_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
01826                      ConstraintTeachersActivityTagMaxHoursContinuously* crt_constraint=(ConstraintTeachersActivityTagMaxHoursContinuously*)ctr;
01827                      if(activityTagName == crt_constraint->activityTagName)
01828                             this->removeTimeConstraint(ctr); //single constraint removal
01829                      else
01830                             i++;
01831               }
01832               else
01833                      i++;
01834        }
01835        //delete the time constraints related to this activity tag
01836        for(int i=0; i<this->timeConstraintsList.size(); ){
01837               TimeConstraint* ctr=this->timeConstraintsList[i];
01838               
01839               if(ctr->type==CONSTRAINT_TEACHERS_ACTIVITY_TAG_MAX_HOURS_DAILY){
01840                      ConstraintTeachersActivityTagMaxHoursDaily* crt_constraint=(ConstraintTeachersActivityTagMaxHoursDaily*)ctr;
01841                      if(activityTagName == crt_constraint->activityTagName)
01842                             this->removeTimeConstraint(ctr); //single constraint removal
01843                      else
01844                             i++;
01845               }
01846               else
01847                      i++;
01848        }
01849        //delete the time constraints related to this activity tag
01850        for(int i=0; i<this->timeConstraintsList.size(); ){
01851               TimeConstraint* ctr=this->timeConstraintsList[i];
01852               
01853               if(ctr->type==CONSTRAINT_STUDENTS_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
01854                      ConstraintStudentsActivityTagMaxHoursContinuously* crt_constraint=(ConstraintStudentsActivityTagMaxHoursContinuously*)ctr;
01855                      if(activityTagName == crt_constraint->activityTagName)
01856                             this->removeTimeConstraint(ctr); //single constraint removal
01857                      else
01858                             i++;
01859               }
01860               else
01861                      i++;
01862        }
01863        //delete the time constraints related to this activity tag
01864        for(int i=0; i<this->timeConstraintsList.size(); ){
01865               TimeConstraint* ctr=this->timeConstraintsList[i];
01866               
01867               if(ctr->type==CONSTRAINT_STUDENTS_ACTIVITY_TAG_MAX_HOURS_DAILY){
01868                      ConstraintStudentsActivityTagMaxHoursDaily* crt_constraint=(ConstraintStudentsActivityTagMaxHoursDaily*)ctr;
01869                      if(activityTagName == crt_constraint->activityTagName)
01870                             this->removeTimeConstraint(ctr); //single constraint removal
01871                      else
01872                             i++;
01873               }
01874               else
01875                      i++;
01876        }
01877        //delete the time constraints related to this activity tag
01878        for(int i=0; i<this->timeConstraintsList.size(); ){
01879               TimeConstraint* ctr=this->timeConstraintsList[i];
01880               
01881               if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
01882                      ConstraintStudentsSetActivityTagMaxHoursContinuously* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursContinuously*)ctr;
01883                      if(activityTagName == crt_constraint->activityTagName)
01884                             this->removeTimeConstraint(ctr); //single constraint removal
01885                      else
01886                             i++;
01887               }
01888               else
01889                      i++;
01890        }
01891        //delete the time constraints related to this activity tag
01892        for(int i=0; i<this->timeConstraintsList.size(); ){
01893               TimeConstraint* ctr=this->timeConstraintsList[i];
01894               
01895               if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_DAILY){
01896                      ConstraintStudentsSetActivityTagMaxHoursDaily* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursDaily*)ctr;
01897                      if(activityTagName == crt_constraint->activityTagName)
01898                             this->removeTimeConstraint(ctr); //single constraint removal
01899                      else
01900                             i++;
01901               }
01902               else
01903                      i++;
01904        }
01905 
01906        //delete the time constraints related to this activity tag
01907        for(int i=0; i<this->timeConstraintsList.size(); ){
01908               TimeConstraint* ctr=this->timeConstraintsList[i];
01909               
01910               if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_TIME_SLOTS){
01911                      ConstraintActivitiesPreferredTimeSlots* crt_constraint=(ConstraintActivitiesPreferredTimeSlots*)ctr;
01912                      if(activityTagName == crt_constraint->p_activityTagName)
01913                             this->removeTimeConstraint(ctr); //single constraint removal
01914                      else
01915                             i++;
01916               }
01917               else
01918                      i++;
01919        }
01920 
01921        //delete the time constraints related to this activity tag
01922        for(int i=0; i<this->timeConstraintsList.size(); ){
01923               TimeConstraint* ctr=this->timeConstraintsList[i];
01924               
01925               if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_STARTING_TIMES){
01926                      ConstraintActivitiesPreferredStartingTimes* crt_constraint=(ConstraintActivitiesPreferredStartingTimes*)ctr;
01927                      if(activityTagName == crt_constraint->activityTagName)
01928                             this->removeTimeConstraint(ctr); //single constraint removal
01929                      else
01930                             i++;
01931               }
01932               else
01933                      i++;
01934        }
01935 
01936        //delete the time constraints related to this activity tag
01937        for(int i=0; i<this->timeConstraintsList.size(); ){
01938               TimeConstraint* ctr=this->timeConstraintsList[i];
01939               
01940               if(ctr->type==CONSTRAINT_ACTIVITIES_END_STUDENTS_DAY){
01941                      ConstraintActivitiesEndStudentsDay* crt_constraint=(ConstraintActivitiesEndStudentsDay*)ctr;
01942                      if(activityTagName == crt_constraint->activityTagName)
01943                             this->removeTimeConstraint(ctr); //single constraint removal
01944                      else
01945                             i++;
01946               }
01947               else
01948                      i++;
01949        }
01950 
01951        //delete the time constraints related to this activity tag
01952        for(int i=0; i<this->timeConstraintsList.size(); ){
01953               TimeConstraint* ctr=this->timeConstraintsList[i];
01954               
01955               if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_TIME_SLOTS){
01956                      ConstraintSubactivitiesPreferredTimeSlots* crt_constraint=(ConstraintSubactivitiesPreferredTimeSlots*)ctr;
01957                      if(activityTagName == crt_constraint->p_activityTagName)
01958                             this->removeTimeConstraint(ctr); //single constraint removal
01959                      else
01960                             i++;
01961               }
01962               else
01963                      i++;
01964        }
01965 
01966        //delete the time constraints related to this activity tag
01967        for(int i=0; i<this->timeConstraintsList.size(); ){
01968               TimeConstraint* ctr=this->timeConstraintsList[i];
01969               
01970               if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_STARTING_TIMES){
01971                      ConstraintSubactivitiesPreferredStartingTimes* crt_constraint=(ConstraintSubactivitiesPreferredStartingTimes*)ctr;
01972                      if(activityTagName == crt_constraint->activityTagName)
01973                             this->removeTimeConstraint(ctr); //single constraint removal
01974                      else
01975                             i++;
01976               }
01977               else
01978                      i++;
01979        }
01980 
01981        //delete the space constraints related to this activity tag
01982        for(int i=0; i<this->spaceConstraintsList.size(); ){
01983               SpaceConstraint* ctr=this->spaceConstraintsList[i];
01984               
01985               if(ctr->type==CONSTRAINT_SUBJECT_ACTIVITY_TAG_PREFERRED_ROOM){
01986                      ConstraintSubjectActivityTagPreferredRoom* c=(ConstraintSubjectActivityTagPreferredRoom*)ctr;
01987 
01988                      if(c->activityTagName == activityTagName)
01989                             this->removeSpaceConstraint(ctr);
01990                      else
01991                             i++;
01992               }
01993               else if(ctr->type==CONSTRAINT_SUBJECT_ACTIVITY_TAG_PREFERRED_ROOMS){
01994                      ConstraintSubjectActivityTagPreferredRooms* c=(ConstraintSubjectActivityTagPreferredRooms*)ctr;
01995 
01996                      if(c->activityTagName == activityTagName)
01997                             this->removeSpaceConstraint(ctr);
01998                      else
01999                             i++;
02000               }
02001               else if(ctr->type==CONSTRAINT_ACTIVITY_TAG_PREFERRED_ROOM){
02002                      ConstraintActivityTagPreferredRoom* c=(ConstraintActivityTagPreferredRoom*)ctr;
02003 
02004                      if(c->activityTagName == activityTagName)
02005                             this->removeSpaceConstraint(ctr);
02006                      else
02007                             i++;
02008               }
02009               else if(ctr->type==CONSTRAINT_ACTIVITY_TAG_PREFERRED_ROOMS){
02010                      ConstraintActivityTagPreferredRooms* c=(ConstraintActivityTagPreferredRooms*)ctr;
02011 
02012                      if(c->activityTagName == activityTagName)
02013                             this->removeSpaceConstraint(ctr);
02014                      else
02015                             i++;
02016               }
02017               else
02018                      i++;
02019        }
02020 
02021        //remove the activity tag from the list
02022        for(int i=0; i<this->activityTagsList.size(); i++)
02023               if(this->activityTagsList[i]->name==activityTagName){
02024                      ActivityTag* sbt=this->activityTagsList[i];
02025                      this->activityTagsList.removeAt(i);
02026                      delete sbt;
02027                      break;
02028               }
02029        
02030        this->internalStructureComputed=false;
02031        setRulesModifiedAndOtherThings(this);
02032 
02033        teachers_schedule_ready=false;
02034        students_schedule_ready=false;
02035        rooms_schedule_ready=false;
02036 
02037        return true;
02038 }
02039 
02040 bool Rules::modifyActivityTag(const QString& initialActivityTagName, const QString& finalActivityTagName)
02041 {
02042        assert(this->searchActivityTag(finalActivityTagName)==-1);
02043        assert(this->searchActivityTag(initialActivityTagName)>=0);
02044 
02045        //check the activities first
02046        for(int i=0; i<this->activitiesList.size(); i++){
02047               Activity* act=this->activitiesList[i];
02048 
02049               //if( act->activityTagName == initialActivityTagName)
02050               //     act->activityTagName=finalActivityTagName;
02051               for(int kk=0; kk<act->activityTagsNames.count(); kk++)
02052                      if(act->activityTagsNames.at(kk)==initialActivityTagName)
02053                             act->activityTagsNames[kk]=finalActivityTagName;
02054        }
02055        
02056        //modify the constraints related to this activity tag
02057        for(int i=0; i<this->timeConstraintsList.size(); i++){
02058               TimeConstraint* ctr=this->timeConstraintsList[i];
02059        
02060               if(ctr->type==CONSTRAINT_TEACHER_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
02061                      ConstraintTeacherActivityTagMaxHoursContinuously* crt_constraint=(ConstraintTeacherActivityTagMaxHoursContinuously*)ctr;
02062                      if(initialActivityTagName == crt_constraint->activityTagName)
02063                             crt_constraint->activityTagName=finalActivityTagName;
02064               }
02065        }
02066        for(int i=0; i<this->timeConstraintsList.size(); i++){
02067               TimeConstraint* ctr=this->timeConstraintsList[i];
02068        
02069               if(ctr->type==CONSTRAINT_TEACHER_ACTIVITY_TAG_MAX_HOURS_DAILY){
02070                      ConstraintTeacherActivityTagMaxHoursDaily* crt_constraint=(ConstraintTeacherActivityTagMaxHoursDaily*)ctr;
02071                      if(initialActivityTagName == crt_constraint->activityTagName)
02072                             crt_constraint->activityTagName=finalActivityTagName;
02073               }
02074        }
02075        for(int i=0; i<this->timeConstraintsList.size(); i++){
02076               TimeConstraint* ctr=this->timeConstraintsList[i];
02077        
02078               if(ctr->type==CONSTRAINT_TEACHERS_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
02079                      ConstraintTeachersActivityTagMaxHoursContinuously* crt_constraint=(ConstraintTeachersActivityTagMaxHoursContinuously*)ctr;
02080                      if(initialActivityTagName == crt_constraint->activityTagName)
02081                             crt_constraint->activityTagName=finalActivityTagName;
02082               }
02083        }
02084        for(int i=0; i<this->timeConstraintsList.size(); i++){
02085               TimeConstraint* ctr=this->timeConstraintsList[i];
02086        
02087               if(ctr->type==CONSTRAINT_TEACHERS_ACTIVITY_TAG_MAX_HOURS_DAILY){
02088                      ConstraintTeachersActivityTagMaxHoursDaily* crt_constraint=(ConstraintTeachersActivityTagMaxHoursDaily*)ctr;
02089                      if(initialActivityTagName == crt_constraint->activityTagName)
02090                             crt_constraint->activityTagName=finalActivityTagName;
02091               }
02092        }
02093        for(int i=0; i<this->timeConstraintsList.size(); i++){
02094               TimeConstraint* ctr=this->timeConstraintsList[i];
02095        
02096               if(ctr->type==CONSTRAINT_STUDENTS_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
02097                      ConstraintStudentsActivityTagMaxHoursContinuously* crt_constraint=(ConstraintStudentsActivityTagMaxHoursContinuously*)ctr;
02098                      if(initialActivityTagName == crt_constraint->activityTagName)
02099                             crt_constraint->activityTagName=finalActivityTagName;
02100               }
02101        }
02102        for(int i=0; i<this->timeConstraintsList.size(); i++){
02103               TimeConstraint* ctr=this->timeConstraintsList[i];
02104        
02105               if(ctr->type==CONSTRAINT_STUDENTS_ACTIVITY_TAG_MAX_HOURS_DAILY){
02106                      ConstraintStudentsActivityTagMaxHoursDaily* crt_constraint=(ConstraintStudentsActivityTagMaxHoursDaily*)ctr;
02107                      if(initialActivityTagName == crt_constraint->activityTagName)
02108                             crt_constraint->activityTagName=finalActivityTagName;
02109               }
02110        }
02111        for(int i=0; i<this->timeConstraintsList.size(); i++){
02112               TimeConstraint* ctr=this->timeConstraintsList[i];
02113        
02114               if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
02115                      ConstraintStudentsSetActivityTagMaxHoursContinuously* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursContinuously*)ctr;
02116                      if(initialActivityTagName == crt_constraint->activityTagName)
02117                             crt_constraint->activityTagName=finalActivityTagName;
02118               }
02119        }
02120        for(int i=0; i<this->timeConstraintsList.size(); i++){
02121               TimeConstraint* ctr=this->timeConstraintsList[i];
02122        
02123               if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_DAILY){
02124                      ConstraintStudentsSetActivityTagMaxHoursDaily* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursDaily*)ctr;
02125                      if(initialActivityTagName == crt_constraint->activityTagName)
02126                             crt_constraint->activityTagName=finalActivityTagName;
02127               }
02128        }
02129 
02130        //modify the constraints related to this activity tag
02131        for(int i=0; i<this->timeConstraintsList.size(); i++){
02132               TimeConstraint* ctr=this->timeConstraintsList[i];
02133        
02134               if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_TIME_SLOTS){
02135                      ConstraintActivitiesPreferredTimeSlots* crt_constraint=(ConstraintActivitiesPreferredTimeSlots*)ctr;
02136                      if(initialActivityTagName == crt_constraint->p_activityTagName)
02137                             crt_constraint->p_activityTagName=finalActivityTagName;
02138               }
02139        }
02140 
02141        //modify the constraints related to this activity tag
02142        for(int i=0; i<this->timeConstraintsList.size(); i++){
02143               TimeConstraint* ctr=this->timeConstraintsList[i];
02144        
02145               if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_STARTING_TIMES){
02146                      ConstraintActivitiesPreferredStartingTimes* crt_constraint=(ConstraintActivitiesPreferredStartingTimes*)ctr;
02147                      if(initialActivityTagName == crt_constraint->activityTagName)
02148                             crt_constraint->activityTagName=finalActivityTagName;
02149               }
02150        }
02151 
02152        //modify the constraints related to this activity tag
02153        for(int i=0; i<this->timeConstraintsList.size(); i++){
02154               TimeConstraint* ctr=this->timeConstraintsList[i];
02155        
02156               if(ctr->type==CONSTRAINT_ACTIVITIES_END_STUDENTS_DAY){
02157                      ConstraintActivitiesEndStudentsDay* crt_constraint=(ConstraintActivitiesEndStudentsDay*)ctr;
02158                      if(initialActivityTagName == crt_constraint->activityTagName)
02159                             crt_constraint->activityTagName=finalActivityTagName;
02160               }
02161        }
02162 
02163        //modify the constraints related to this activity tag
02164        for(int i=0; i<this->timeConstraintsList.size(); i++){
02165               TimeConstraint* ctr=this->timeConstraintsList[i];
02166        
02167               if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_TIME_SLOTS){
02168                      ConstraintSubactivitiesPreferredTimeSlots* crt_constraint=(ConstraintSubactivitiesPreferredTimeSlots*)ctr;
02169                      if(initialActivityTagName == crt_constraint->p_activityTagName)
02170                             crt_constraint->p_activityTagName=finalActivityTagName;
02171               }
02172        }
02173 
02174        //modify the constraints related to this activity tag
02175        for(int i=0; i<this->timeConstraintsList.size(); i++){
02176               TimeConstraint* ctr=this->timeConstraintsList[i];
02177        
02178               if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_STARTING_TIMES){
02179                      ConstraintSubactivitiesPreferredStartingTimes* crt_constraint=(ConstraintSubactivitiesPreferredStartingTimes*)ctr;
02180                      if(initialActivityTagName == crt_constraint->activityTagName)
02181                             crt_constraint->activityTagName=finalActivityTagName;
02182               }
02183        }
02184 
02185        //modify the space constraints related to this subject tag
02186        for(int i=0; i<this->spaceConstraintsList.size(); i++){
02187               SpaceConstraint* ctr=this->spaceConstraintsList[i];
02188 
02189               if(ctr->type==CONSTRAINT_SUBJECT_ACTIVITY_TAG_PREFERRED_ROOM){
02190                      ConstraintSubjectActivityTagPreferredRoom* c=(ConstraintSubjectActivityTagPreferredRoom*)ctr;
02191                      if(c->activityTagName == initialActivityTagName)
02192                             c->activityTagName=finalActivityTagName;
02193               }
02194               else if(ctr->type==CONSTRAINT_SUBJECT_ACTIVITY_TAG_PREFERRED_ROOMS){
02195                      ConstraintSubjectActivityTagPreferredRooms* c=(ConstraintSubjectActivityTagPreferredRooms*)ctr;
02196                      if(c->activityTagName == initialActivityTagName)
02197                             c->activityTagName=finalActivityTagName;
02198               }
02199               else if(ctr->type==CONSTRAINT_ACTIVITY_TAG_PREFERRED_ROOM){
02200                      ConstraintActivityTagPreferredRoom* c=(ConstraintActivityTagPreferredRoom*)ctr;
02201                      if(c->activityTagName == initialActivityTagName)
02202                             c->activityTagName=finalActivityTagName;
02203               }
02204               else if(ctr->type==CONSTRAINT_ACTIVITY_TAG_PREFERRED_ROOMS){
02205                      ConstraintActivityTagPreferredRooms* c=(ConstraintActivityTagPreferredRooms*)ctr;
02206                      if(c->activityTagName == initialActivityTagName)
02207                             c->activityTagName=finalActivityTagName;
02208               }
02209        }
02210 
02211        //rename the activity tag in the list
02212        int t=0;
02213        
02214        for(int i=0; i<this->activityTagsList.size(); i++){
02215               ActivityTag* sbt=this->activityTagsList[i];
02216 
02217               if(sbt->name==initialActivityTagName){
02218                      t++;
02219                      sbt->name=finalActivityTagName;
02220               }
02221        }
02222        
02223        assert(t<=1);
02224 
02225        this->internalStructureComputed=false;
02226        setRulesModifiedAndOtherThings(this);
02227 
02228        return true;
02229 }
02230 
02231 void Rules::sortActivityTagsAlphabetically()
02232 {
02233        qSort(this->activityTagsList.begin(), this->activityTagsList.end(), activityTagsAscending);
02234 
02235        this->internalStructureComputed=false;
02236        setRulesModifiedAndOtherThings(this);
02237 }
02238 
02239 bool Rules::setsShareStudents(const QString& studentsSet1, const QString& studentsSet2)
02240 {
02241        StudentsSet* s1=this->searchStudentsSet(studentsSet1);
02242        StudentsSet* s2=this->searchStudentsSet(studentsSet2);
02243        assert(s1!=NULL);
02244        assert(s2!=NULL);
02245        
02246        QSet<QString> downwardSets1;
02247        
02248        if(s1->type==STUDENTS_YEAR){
02249               StudentsYear* year1=(StudentsYear*)s1;
02250               downwardSets1.insert(year1->name);
02251               foreach(StudentsGroup* group1, year1->groupsList){
02252                      downwardSets1.insert(group1->name);
02253                      foreach(StudentsSubgroup* subgroup1, group1->subgroupsList)
02254                             downwardSets1.insert(subgroup1->name);
02255               }
02256        }
02257        else if(s1->type==STUDENTS_GROUP){
02258               StudentsGroup* group1=(StudentsGroup*)s1;
02259               downwardSets1.insert(group1->name);
02260               foreach(StudentsSubgroup* subgroup1, group1->subgroupsList)
02261                      downwardSets1.insert(subgroup1->name);
02262        }
02263        else if(s1->type==STUDENTS_SUBGROUP){
02264               StudentsSubgroup* subgroup1=(StudentsSubgroup*)s1;
02265               downwardSets1.insert(subgroup1->name);
02266        }
02267        else
02268               assert(0);
02269               
02270        if(s2->type==STUDENTS_YEAR){
02271               StudentsYear* year2=(StudentsYear*)s2;
02272               if(downwardSets1.contains(year2->name))
02273                      return true;
02274               foreach(StudentsGroup* group2, year2->groupsList){
02275                      if(downwardSets1.contains(group2->name))
02276                             return true;
02277                      foreach(StudentsSubgroup* subgroup2, group2->subgroupsList)
02278                             if(downwardSets1.contains(subgroup2->name))
02279                                    return true;
02280               }
02281        }
02282        else if(s2->type==STUDENTS_GROUP){
02283               StudentsGroup* group2=(StudentsGroup*)s2;
02284               if(downwardSets1.contains(group2->name))
02285                      return true;
02286               foreach(StudentsSubgroup* subgroup2, group2->subgroupsList)
02287                      if(downwardSets1.contains(subgroup2->name))
02288                             return true;
02289        }
02290        else if(s2->type==STUDENTS_SUBGROUP){
02291               StudentsSubgroup* subgroup2=(StudentsSubgroup*)s2;
02292               if(downwardSets1.contains(subgroup2->name))
02293                      return true;
02294        }
02295        else
02296               assert(0);
02297        
02298        return false;
02299        
02300 }
02301 
02302 StudentsSet* Rules::searchStudentsSet(const QString& setName)
02303 {
02304        for(int i=0; i<this->yearsList.size(); i++){
02305               StudentsYear* sty=this->yearsList[i];
02306               if(sty->name==setName)
02307                      return sty;
02308               for(int j=0; j<sty->groupsList.size(); j++){
02309                      StudentsGroup* stg=sty->groupsList[j];
02310                      if(stg->name==setName)
02311                             return stg;
02312                      for(int k=0; k<stg->subgroupsList.size(); k++){
02313                             StudentsSubgroup* sts=stg->subgroupsList[k];
02314                             if(sts->name==setName)
02315                                    return sts;
02316                      }
02317               }
02318        }
02319        return NULL;
02320 }
02321 
02322 StudentsSet* Rules::searchAugmentedStudentsSet(const QString& setName)
02323 {
02324        for(int i=0; i<this->augmentedYearsList.size(); i++){
02325               StudentsYear* sty=this->augmentedYearsList[i];
02326               if(sty->name==setName)
02327                      return sty;
02328               for(int j=0; j<sty->groupsList.size(); j++){
02329                      StudentsGroup* stg=sty->groupsList[j];
02330                      if(stg->name==setName)
02331                             return stg;
02332                      for(int k=0; k<stg->subgroupsList.size(); k++){
02333                             StudentsSubgroup* sts=stg->subgroupsList[k];
02334                             if(sts->name==setName)
02335                                    return sts;
02336                      }
02337               }
02338        }
02339        return NULL;
02340 }
02341 
02342 bool Rules::addYear(StudentsYear* year)
02343 {
02344        //already existing?
02345        if(this->searchStudentsSet(year->name)!=NULL)
02346               return false;
02347        this->yearsList << year;
02348        this->internalStructureComputed=false;
02349        setRulesModifiedAndOtherThings(this);
02350        return true;
02351 }
02352 
02353 bool Rules::addYearFast(StudentsYear* year)
02354 {
02355        this->yearsList << year;
02356        this->internalStructureComputed=false;
02357        setRulesModifiedAndOtherThings(this);
02358        return true;
02359 }
02360 
02361 bool Rules::removeYear(const QString& yearName)
02362 {
02363        StudentsYear* year=NULL;
02364        foreach(StudentsYear* ty, this->yearsList){
02365               if(ty->name==yearName){
02366                      year=ty;
02367                      break;
02368               }
02369        }
02370 
02371        //StudentsYear* year=(StudentsYear*)searchStudentsSet(yearName);
02372        assert(year!=NULL);
02373        int nStudents=year->numberOfStudents;
02374        while(year->groupsList.size()>0){
02375               QString groupName=year->groupsList[0]->name;
02376               this->removeGroup(yearName, groupName);
02377        }
02378 
02379        for(int i=0; i<this->activitiesList.size(); ){
02380               Activity* act=this->activitiesList[i];
02381               bool t=act->removeStudents(*this, yearName, nStudents);
02382               
02383               if(t && act->studentsNames.count()==0){
02384                      this->removeActivity(act->id, act->activityGroupId);
02385                      i=0;
02386                      //(You have to be careful, there can be erased more activities here)
02387               }
02388               else
02389                      i++;
02390        }
02391        
02392        for(int i=0; i<this->timeConstraintsList.size(); ){
02393               TimeConstraint* ctr=this->timeConstraintsList[i];
02394        
02395               bool erased=false;
02396 
02397               if(ctr->type==CONSTRAINT_STUDENTS_SET_NOT_AVAILABLE_TIMES){
02398                      ConstraintStudentsSetNotAvailableTimes* crt_constraint=(ConstraintStudentsSetNotAvailableTimes*)ctr;
02399                      if(yearName == crt_constraint->students){
02400                             this->removeTimeConstraint(ctr);
02401                             erased=true;
02402                      }
02403               }
02404               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_DAILY){
02405                      ConstraintStudentsSetMaxHoursDaily* crt_constraint=(ConstraintStudentsSetMaxHoursDaily*)ctr;
02406                      if(yearName == crt_constraint->students){
02407                             this->removeTimeConstraint(ctr);
02408                             erased=true;
02409                      }
02410               }
02411               else if(ctr->type==CONSTRAINT_STUDENTS_SET_INTERVAL_MAX_DAYS_PER_WEEK){
02412                      ConstraintStudentsSetIntervalMaxDaysPerWeek* crt_constraint=(ConstraintStudentsSetIntervalMaxDaysPerWeek*)ctr;
02413                      if(yearName == crt_constraint->students){
02414                             this->removeTimeConstraint(ctr);
02415                             erased=true;
02416                      }
02417               }
02418               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_CONTINUOUSLY){
02419                      ConstraintStudentsSetMaxHoursContinuously* crt_constraint=(ConstraintStudentsSetMaxHoursContinuously*)ctr;
02420                      if(yearName == crt_constraint->students){
02421                             this->removeTimeConstraint(ctr);
02422                             erased=true;
02423                      }
02424               }
02425               else if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
02426                      ConstraintStudentsSetActivityTagMaxHoursContinuously* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursContinuously*)ctr;
02427                      if(yearName == crt_constraint->students){
02428                             this->removeTimeConstraint(ctr);
02429                             erased=true;
02430                      }
02431               }
02432               else if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_DAILY){
02433                      ConstraintStudentsSetActivityTagMaxHoursDaily* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursDaily*)ctr;
02434                      if(yearName == crt_constraint->students){
02435                             this->removeTimeConstraint(ctr);
02436                             erased=true;
02437                      }
02438               }
02439               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_HOURS_DAILY){
02440                      ConstraintStudentsSetMinHoursDaily* crt_constraint=(ConstraintStudentsSetMinHoursDaily*)ctr;
02441                      if(yearName == crt_constraint->students){
02442                             this->removeTimeConstraint(ctr);
02443                             erased=true;
02444                      }
02445               }
02446               else if(ctr->type==CONSTRAINT_STUDENTS_SET_EARLY_MAX_BEGINNINGS_AT_SECOND_HOUR){
02447                      ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour* crt_constraint=(ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour*)ctr;
02448                      if(yearName == crt_constraint->students){
02449                             this->removeTimeConstraint(ctr);
02450                             erased=true;
02451                      }
02452               }
02453               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_WEEK){
02454                      ConstraintStudentsSetMaxGapsPerWeek* crt_constraint=(ConstraintStudentsSetMaxGapsPerWeek*)ctr;
02455                      if(yearName == crt_constraint->students){
02456                             this->removeTimeConstraint(ctr);
02457                             erased=true;
02458                      }
02459               }
02460               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_DAY){
02461                      ConstraintStudentsSetMaxGapsPerDay* crt_constraint=(ConstraintStudentsSetMaxGapsPerDay*)ctr;
02462                      if(yearName == crt_constraint->students){
02463                             this->removeTimeConstraint(ctr);
02464                             erased=true;
02465                      }
02466               }
02467               else if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_TIME_SLOTS){
02468                      ConstraintActivitiesPreferredTimeSlots* crt_constraint=(ConstraintActivitiesPreferredTimeSlots*)ctr;
02469                      if(yearName == crt_constraint->p_studentsName){
02470                             this->removeTimeConstraint(ctr);
02471                             erased=true;
02472                      }
02473               }
02474               else if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_STARTING_TIMES){
02475                      ConstraintActivitiesPreferredStartingTimes* crt_constraint=(ConstraintActivitiesPreferredStartingTimes*)ctr;
02476                      if(yearName == crt_constraint->studentsName){
02477                             this->removeTimeConstraint(ctr);
02478                             erased=true;
02479                      }
02480               }
02481               else if(ctr->type==CONSTRAINT_ACTIVITIES_END_STUDENTS_DAY){
02482                      ConstraintActivitiesEndStudentsDay* crt_constraint=(ConstraintActivitiesEndStudentsDay*)ctr;
02483                      if(yearName == crt_constraint->studentsName){
02484                             this->removeTimeConstraint(ctr);
02485                             erased=true;
02486                      }
02487               }
02488               else if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_TIME_SLOTS){
02489                      ConstraintSubactivitiesPreferredTimeSlots* crt_constraint=(ConstraintSubactivitiesPreferredTimeSlots*)ctr;
02490                      if(yearName == crt_constraint->p_studentsName){
02491                             this->removeTimeConstraint(ctr);
02492                             erased=true;
02493                      }
02494               }
02495               else if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_STARTING_TIMES){
02496                      ConstraintSubactivitiesPreferredStartingTimes* crt_constraint=(ConstraintSubactivitiesPreferredStartingTimes*)ctr;
02497                      if(yearName == crt_constraint->studentsName){
02498                             this->removeTimeConstraint(ctr);
02499                             erased=true;
02500                      }
02501               }
02502 
02503               if(!erased)
02504                      i++;
02505        }
02506 
02507        for(int i=0; i<this->spaceConstraintsList.size(); ){
02508               SpaceConstraint* ctr=this->spaceConstraintsList[i];
02509        
02510               bool erased=false;
02511 
02512               if(ctr->type==CONSTRAINT_STUDENTS_SET_HOME_ROOM){
02513                      ConstraintStudentsSetHomeRoom* crt_constraint=(ConstraintStudentsSetHomeRoom*)ctr;
02514                      if(yearName == crt_constraint->studentsName){
02515                             this->removeSpaceConstraint(ctr);
02516                             erased=true;
02517                      }
02518               }
02519               else if(ctr->type==CONSTRAINT_STUDENTS_SET_HOME_ROOMS){
02520                      ConstraintStudentsSetHomeRooms* crt_constraint=(ConstraintStudentsSetHomeRooms*)ctr;
02521                      if(yearName == crt_constraint->studentsName){
02522                             this->removeSpaceConstraint(ctr);
02523                             erased=true;
02524                      }
02525               }
02526               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_BUILDING_CHANGES_PER_DAY){
02527                      ConstraintStudentsSetMaxBuildingChangesPerDay* crt_constraint=(ConstraintStudentsSetMaxBuildingChangesPerDay*)ctr;
02528                      if(yearName == crt_constraint->studentsName){
02529                             this->removeSpaceConstraint(ctr);
02530                             erased=true;
02531                      }
02532               }
02533               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_BUILDING_CHANGES_PER_WEEK){
02534                      ConstraintStudentsSetMaxBuildingChangesPerWeek* crt_constraint=(ConstraintStudentsSetMaxBuildingChangesPerWeek*)ctr;
02535                      if(yearName == crt_constraint->studentsName){
02536                             this->removeSpaceConstraint(ctr);
02537                             erased=true;
02538                      }
02539               }
02540               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_GAPS_BETWEEN_BUILDING_CHANGES){
02541                      ConstraintStudentsSetMinGapsBetweenBuildingChanges* crt_constraint=(ConstraintStudentsSetMinGapsBetweenBuildingChanges*)ctr;
02542                      if(yearName == crt_constraint->studentsName){
02543                             this->removeSpaceConstraint(ctr);
02544                             erased=true;
02545                      }
02546               }
02547 
02548               if(!erased)
02549                      i++;
02550        }
02551 
02552        for(int i=0; i<this->yearsList.size(); i++)
02553               if(this->yearsList.at(i)->name==yearName){
02554                      delete this->yearsList[i]; //added in version 4.0.2
02555                      this->yearsList.removeAt(i);
02556                      break;
02557               }
02558 
02559        this->internalStructureComputed=false;
02560        setRulesModifiedAndOtherThings(this);
02561        return true;
02562 }
02563 
02564 int Rules::searchYear(const QString& yearName)
02565 {
02566        for(int i=0; i<this->yearsList.size(); i++)
02567               if(this->yearsList[i]->name==yearName)
02568                      return i;
02569 
02570        return -1;
02571 }
02572 
02573 int Rules::searchAugmentedYear(const QString& yearName)
02574 {
02575        for(int i=0; i<this->augmentedYearsList.size(); i++)
02576               if(this->augmentedYearsList[i]->name==yearName)
02577                      return i;
02578 
02579        return -1;
02580 }
02581 
02582 bool Rules::modifyYear(const QString& initialYearName, const QString& finalYearName, int finalNumberOfStudents)
02583 {
02584        StudentsSet* _initialSet=searchStudentsSet(initialYearName);
02585        assert(_initialSet!=NULL);
02586        int _initialNumberOfStudents=_initialSet->numberOfStudents;
02587 
02588        QString _initialYearName=initialYearName;
02589 
02590        assert(searchYear(_initialYearName)>=0);
02591        StudentsSet* _ss=searchStudentsSet(finalYearName);
02592        assert(_ss==NULL || _initialYearName==finalYearName);
02593 
02594        for(int i=0; i<this->activitiesList.size(); i++){
02595               Activity* act=this->activitiesList[i];
02596               act->renameStudents(*this, _initialYearName, finalYearName, _initialNumberOfStudents, finalNumberOfStudents);
02597        }
02598 
02599        for(int i=0; i<this->timeConstraintsList.size(); i++){
02600               TimeConstraint* ctr=this->timeConstraintsList[i];
02601 
02602               if(ctr->type==CONSTRAINT_STUDENTS_SET_NOT_AVAILABLE_TIMES){
02603                      ConstraintStudentsSetNotAvailableTimes* crt_constraint=(ConstraintStudentsSetNotAvailableTimes*)ctr;
02604                      if(_initialYearName == crt_constraint->students)
02605                             crt_constraint->students=finalYearName;
02606               }
02607               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_DAILY){
02608                      ConstraintStudentsSetMaxHoursDaily* crt_constraint=(ConstraintStudentsSetMaxHoursDaily*)ctr;
02609                      if(_initialYearName == crt_constraint->students)
02610                             crt_constraint->students=finalYearName;
02611               }
02612               else if(ctr->type==CONSTRAINT_STUDENTS_SET_INTERVAL_MAX_DAYS_PER_WEEK){
02613                      ConstraintStudentsSetIntervalMaxDaysPerWeek* crt_constraint=(ConstraintStudentsSetIntervalMaxDaysPerWeek*)ctr;
02614                      if(_initialYearName == crt_constraint->students)
02615                             crt_constraint->students=finalYearName;
02616               }
02617               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_CONTINUOUSLY){
02618                      ConstraintStudentsSetMaxHoursContinuously* crt_constraint=(ConstraintStudentsSetMaxHoursContinuously*)ctr;
02619                      if(_initialYearName == crt_constraint->students)
02620                             crt_constraint->students=finalYearName;
02621               }
02622               else if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
02623                      ConstraintStudentsSetActivityTagMaxHoursContinuously* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursContinuously*)ctr;
02624                      if(_initialYearName == crt_constraint->students)
02625                             crt_constraint->students=finalYearName;
02626               }
02627               else if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_DAILY){
02628                      ConstraintStudentsSetActivityTagMaxHoursDaily* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursDaily*)ctr;
02629                      if(_initialYearName == crt_constraint->students)
02630                             crt_constraint->students=finalYearName;
02631               }
02632               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_HOURS_DAILY){
02633                      ConstraintStudentsSetMinHoursDaily* crt_constraint=(ConstraintStudentsSetMinHoursDaily*)ctr;
02634                      if(_initialYearName == crt_constraint->students)
02635                             crt_constraint->students=finalYearName;
02636               }
02637               else if(ctr->type==CONSTRAINT_STUDENTS_SET_EARLY_MAX_BEGINNINGS_AT_SECOND_HOUR){
02638                      ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour* crt_constraint=(ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour*)ctr;
02639                      if(_initialYearName == crt_constraint->students)
02640                             crt_constraint->students=finalYearName;
02641               }
02642               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_WEEK){
02643                      ConstraintStudentsSetMaxGapsPerWeek* crt_constraint=(ConstraintStudentsSetMaxGapsPerWeek*)ctr;
02644                      if(_initialYearName == crt_constraint->students)
02645                             crt_constraint->students=finalYearName;
02646               }
02647               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_DAY){
02648                      ConstraintStudentsSetMaxGapsPerDay* crt_constraint=(ConstraintStudentsSetMaxGapsPerDay*)ctr;
02649                      if(_initialYearName == crt_constraint->students)
02650                             crt_constraint->students=finalYearName;
02651               }
02652               else if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_TIME_SLOTS){
02653                      ConstraintActivitiesPreferredTimeSlots* crt_constraint=(ConstraintActivitiesPreferredTimeSlots*)ctr;
02654                      if(_initialYearName == crt_constraint->p_studentsName)
02655                             crt_constraint->p_studentsName=finalYearName;
02656               }
02657               else if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_STARTING_TIMES){
02658                      ConstraintActivitiesPreferredStartingTimes* crt_constraint=(ConstraintActivitiesPreferredStartingTimes*)ctr;
02659                      if(_initialYearName == crt_constraint->studentsName)
02660                             crt_constraint->studentsName=finalYearName;
02661               }
02662               else if(ctr->type==CONSTRAINT_ACTIVITIES_END_STUDENTS_DAY){
02663                      ConstraintActivitiesEndStudentsDay* crt_constraint=(ConstraintActivitiesEndStudentsDay*)ctr;
02664                      if(_initialYearName == crt_constraint->studentsName)
02665                             crt_constraint->studentsName=finalYearName;
02666               }
02667               else if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_TIME_SLOTS){
02668                      ConstraintSubactivitiesPreferredTimeSlots* crt_constraint=(ConstraintSubactivitiesPreferredTimeSlots*)ctr;
02669                      if(_initialYearName == crt_constraint->p_studentsName)
02670                             crt_constraint->p_studentsName=finalYearName;
02671               }
02672               else if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_STARTING_TIMES){
02673                      ConstraintSubactivitiesPreferredStartingTimes* crt_constraint=(ConstraintSubactivitiesPreferredStartingTimes*)ctr;
02674                      if(_initialYearName == crt_constraint->studentsName)
02675                             crt_constraint->studentsName=finalYearName;
02676               }
02677        }
02678 
02679        for(int i=0; i<this->spaceConstraintsList.size(); i++){
02680               SpaceConstraint* ctr=this->spaceConstraintsList[i];
02681 
02682               if(ctr->type==CONSTRAINT_STUDENTS_SET_HOME_ROOM){
02683                      ConstraintStudentsSetHomeRoom* crt_constraint=(ConstraintStudentsSetHomeRoom*)ctr;
02684                      if(_initialYearName == crt_constraint->studentsName)
02685                             crt_constraint->studentsName=finalYearName;
02686               }
02687               else if(ctr->type==CONSTRAINT_STUDENTS_SET_HOME_ROOMS){
02688                      ConstraintStudentsSetHomeRooms* crt_constraint=(ConstraintStudentsSetHomeRooms*)ctr;
02689                      if(_initialYearName == crt_constraint->studentsName)
02690                             crt_constraint->studentsName=finalYearName;
02691               }
02692               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_BUILDING_CHANGES_PER_DAY){
02693                      ConstraintStudentsSetMaxBuildingChangesPerDay* crt_constraint=(ConstraintStudentsSetMaxBuildingChangesPerDay*)ctr;
02694                      if(_initialYearName == crt_constraint->studentsName)
02695                             crt_constraint->studentsName=finalYearName;
02696               }
02697               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_BUILDING_CHANGES_PER_WEEK){
02698                      ConstraintStudentsSetMaxBuildingChangesPerWeek* crt_constraint=(ConstraintStudentsSetMaxBuildingChangesPerWeek*)ctr;
02699                      if(_initialYearName == crt_constraint->studentsName)
02700                             crt_constraint->studentsName=finalYearName;
02701               }
02702               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_GAPS_BETWEEN_BUILDING_CHANGES){
02703                      ConstraintStudentsSetMinGapsBetweenBuildingChanges* crt_constraint=(ConstraintStudentsSetMinGapsBetweenBuildingChanges*)ctr;
02704                      if(_initialYearName == crt_constraint->studentsName)
02705                             crt_constraint->studentsName=finalYearName;
02706               }
02707        }
02708 
02709        int t=0;
02710        
02711        for(int i=0; i<this->yearsList.size(); i++){
02712               StudentsYear* sty=this->yearsList[i];
02713        
02714               if(sty->name==_initialYearName){
02715                      sty->name=finalYearName;
02716                      sty->numberOfStudents=finalNumberOfStudents;
02717                      t++;
02718                      
02719                      /*for(int j=0; j<sty->groupsList.size(); j++){
02720                             StudentsGroup* stg=sty->groupsList[j];
02721 
02722                             if(stg->name.right(11)==" WHOLE YEAR" && stg->name.left(stg->name.length()-11)==_initialYearName)
02723                                    this->modifyGroup(sty->name, stg->name, sty->name+" WHOLE YEAR", stg->numberOfStudents);
02724                      }*/
02725               }
02726        }
02727               
02728        assert(t<=1);
02729 
02730        this->internalStructureComputed=false;
02731        setRulesModifiedAndOtherThings(this);
02732        
02733        if(t==0)
02734               return false;
02735        else
02736               return true;
02737 }
02738 
02739 void Rules::sortYearsAlphabetically()
02740 {
02741        qSort(this->yearsList.begin(), this->yearsList.end(), yearsAscending);
02742 
02743        this->internalStructureComputed=false;
02744        setRulesModifiedAndOtherThings(this);
02745 }
02746 
02747 bool Rules::addGroup(const QString& yearName, StudentsGroup* group)
02748 {
02749        StudentsYear* sty=NULL;
02750        for(int i=0; i<this->yearsList.size(); i++){
02751               sty=yearsList[i];
02752               if(sty->name==yearName)
02753                      break;
02754        }
02755        assert(sty);
02756        
02757        for(int i=0; i<sty->groupsList.size(); i++){
02758               StudentsGroup* stg=sty->groupsList[i];
02759               if(stg->name==group->name)
02760                      return false;
02761        }
02762        
02763        sty->groupsList << group; //append
02764 
02765        /*
02766        foreach(StudentsYear* y, yearsList)
02767               foreach(StudentsGroup* g, y->groupsList)
02768                      if(g->name==group->name)
02769                             g->numberOfStudents=group->numberOfStudents;*/
02770 
02771        this->internalStructureComputed=false;
02772        setRulesModifiedAndOtherThings(this);
02773        return true;
02774 }
02775 
02776 bool Rules::addGroupFast(StudentsYear* year, StudentsGroup* group)
02777 {
02778        year->groupsList << group; //append
02779 
02780        this->internalStructureComputed=false;
02781        setRulesModifiedAndOtherThings(this);
02782        return true;
02783 }
02784 
02785 bool Rules::removeGroup(const QString& yearName, const QString& groupName)
02786 {
02787        this->internalStructureComputed=false;
02788        setRulesModifiedAndOtherThings(this);
02789        
02790        StudentsYear* year=NULL;
02791        foreach(StudentsYear* ty, this->yearsList){
02792               if(ty->name==yearName){
02793                      year=ty;
02794                      break;
02795               }
02796        }
02797        assert(year!=NULL);
02798        
02799        StudentsGroup* group=NULL;
02800        foreach(StudentsGroup* tg, year->groupsList){
02801               if(tg->name==groupName){
02802                      group=tg;
02803                      break;
02804               }
02805        }
02806 
02807        //StudentsGroup* group=(StudentsGroup*)searchStudentsSet(groupName);
02808        assert(group!=NULL);
02809        int nStudents=group->numberOfStudents;
02810        
02811        bool stillExistsWithSamePointer=false;
02812        foreach(StudentsYear* ty, this->yearsList){
02813               if(ty->name!=yearName){
02814                      foreach(StudentsGroup* tg, ty->groupsList){
02815                             if(tg==group){
02816                                    stillExistsWithSamePointer=true;
02817                                    break;
02818                             }
02819                      }
02820               }
02821               if(stillExistsWithSamePointer)
02822                      break;
02823        }
02824        
02825        if(!stillExistsWithSamePointer){
02826               while(group->subgroupsList.size()>0){
02827                      QString subgroupName=group->subgroupsList[0]->name;
02828                      this->removeSubgroup(yearName, groupName, subgroupName);
02829               }
02830        }
02831 
02832        StudentsYear* sty=NULL;
02833        for(int i=0; i<this->yearsList.size(); i++){
02834               sty=yearsList[i];
02835               if(sty->name==yearName)
02836                      break;
02837        }
02838        assert(sty);
02839        assert(sty==year);
02840 
02841        StudentsGroup* stg=NULL;
02842        for(int i=0; i<sty->groupsList.size(); i++){
02843               stg=sty->groupsList[i];
02844               if(stg->name==groupName){
02845                      sty->groupsList.removeAt(i);
02846                      break;
02847               }
02848        }
02849 
02850        if(this->searchStudentsSet(stg->name)!=NULL){
02851               //group still exists
02852               
02853               //with the same pointer??? (leak bug fix on 6 Jan 2010 in FET-5.12.1)
02854               bool foundSamePointer=false;
02855               foreach(StudentsYear* year, yearsList){
02856                      foreach(StudentsGroup* group, year->groupsList){
02857                             if(group==stg){
02858                                    foundSamePointer=true;
02859                                    break;
02860                             }
02861                      }
02862                      if(foundSamePointer)
02863                             break;
02864               }
02865               
02866               if(!foundSamePointer)
02867                      delete stg;
02869               
02870               return true;
02871        }
02872 
02873        delete stg;
02874 
02875        for(int i=0; i<this->activitiesList.size(); ){
02876               Activity* act=this->activitiesList[i];
02877 
02878               bool t=act->removeStudents(*this, groupName, nStudents);
02879               if(t && act->studentsNames.count()==0){
02880                      this->removeActivity(act->id, act->activityGroupId);
02881                      i=0;
02882                      //(You have to be careful, there can be erased more activities here)
02883               }
02884               else
02885                      i++;
02886        }
02887 
02888        for(int i=0; i<this->timeConstraintsList.size(); ){
02889               TimeConstraint* ctr=this->timeConstraintsList[i];
02890 
02891               bool erased=false;
02892               if(ctr->type==CONSTRAINT_STUDENTS_SET_NOT_AVAILABLE_TIMES){
02893                      ConstraintStudentsSetNotAvailableTimes* crt_constraint=(ConstraintStudentsSetNotAvailableTimes*)ctr;
02894                      if(groupName == crt_constraint->students){
02895                             this->removeTimeConstraint(ctr);
02896                             erased=true;
02897                      }
02898               }
02899               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_DAILY){
02900                      ConstraintStudentsSetMaxHoursDaily* crt_constraint=(ConstraintStudentsSetMaxHoursDaily*)ctr;
02901                      if(groupName == crt_constraint->students){
02902                             this->removeTimeConstraint(ctr);
02903                             erased=true;
02904                      }
02905               }
02906               else if(ctr->type==CONSTRAINT_STUDENTS_SET_INTERVAL_MAX_DAYS_PER_WEEK){
02907                      ConstraintStudentsSetIntervalMaxDaysPerWeek* crt_constraint=(ConstraintStudentsSetIntervalMaxDaysPerWeek*)ctr;
02908                      if(groupName == crt_constraint->students){
02909                             this->removeTimeConstraint(ctr);
02910                             erased=true;
02911                      }
02912               }
02913               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_CONTINUOUSLY){
02914                      ConstraintStudentsSetMaxHoursContinuously* crt_constraint=(ConstraintStudentsSetMaxHoursContinuously*)ctr;
02915                      if(groupName == crt_constraint->students){
02916                             this->removeTimeConstraint(ctr);
02917                             erased=true;
02918                      }
02919               }
02920               else if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
02921                      ConstraintStudentsSetActivityTagMaxHoursContinuously* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursContinuously*)ctr;
02922                      if(groupName == crt_constraint->students){
02923                             this->removeTimeConstraint(ctr);
02924                             erased=true;
02925                      }
02926               }
02927               else if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_DAILY){
02928                      ConstraintStudentsSetActivityTagMaxHoursDaily* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursDaily*)ctr;
02929                      if(groupName == crt_constraint->students){
02930                             this->removeTimeConstraint(ctr);
02931                             erased=true;
02932                      }
02933               }
02934               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_HOURS_DAILY){
02935                      ConstraintStudentsSetMinHoursDaily* crt_constraint=(ConstraintStudentsSetMinHoursDaily*)ctr;
02936                      if(groupName == crt_constraint->students){
02937                             this->removeTimeConstraint(ctr);
02938                             erased=true;
02939                      }
02940               }
02941               else if(ctr->type==CONSTRAINT_STUDENTS_SET_EARLY_MAX_BEGINNINGS_AT_SECOND_HOUR){
02942                      ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour* crt_constraint=(ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour*)ctr;
02943                      if(groupName == crt_constraint->students){
02944                             this->removeTimeConstraint(ctr);
02945                             erased=true;
02946                      }
02947               }
02948               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_WEEK){
02949                      ConstraintStudentsSetMaxGapsPerWeek* crt_constraint=(ConstraintStudentsSetMaxGapsPerWeek*)ctr;
02950                      if(groupName == crt_constraint->students){
02951                             this->removeTimeConstraint(ctr);
02952                             erased=true;
02953                      }
02954               }
02955               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_DAY){
02956                      ConstraintStudentsSetMaxGapsPerDay* crt_constraint=(ConstraintStudentsSetMaxGapsPerDay*)ctr;
02957                      if(groupName == crt_constraint->students){
02958                             this->removeTimeConstraint(ctr);
02959                             erased=true;
02960                      }
02961               }
02962               else if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_TIME_SLOTS){
02963                      ConstraintActivitiesPreferredTimeSlots* crt_constraint=(ConstraintActivitiesPreferredTimeSlots*)ctr;
02964                      if(groupName == crt_constraint->p_studentsName){
02965                             this->removeTimeConstraint(ctr);
02966                             erased=true;
02967                      }
02968               }
02969               else if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_STARTING_TIMES){
02970                      ConstraintActivitiesPreferredStartingTimes* crt_constraint=(ConstraintActivitiesPreferredStartingTimes*)ctr;
02971                      if(groupName == crt_constraint->studentsName){
02972                             this->removeTimeConstraint(ctr);
02973                             erased=true;
02974                      }
02975               }
02976               else if(ctr->type==CONSTRAINT_ACTIVITIES_END_STUDENTS_DAY){
02977                      ConstraintActivitiesEndStudentsDay* crt_constraint=(ConstraintActivitiesEndStudentsDay*)ctr;
02978                      if(groupName == crt_constraint->studentsName){
02979                             this->removeTimeConstraint(ctr);
02980                             erased=true;
02981                      }
02982               }
02983               else if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_TIME_SLOTS){
02984                      ConstraintSubactivitiesPreferredTimeSlots* crt_constraint=(ConstraintSubactivitiesPreferredTimeSlots*)ctr;
02985                      if(groupName == crt_constraint->p_studentsName){
02986                             this->removeTimeConstraint(ctr);
02987                             erased=true;
02988                      }
02989               }
02990               else if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_STARTING_TIMES){
02991                      ConstraintSubactivitiesPreferredStartingTimes* crt_constraint=(ConstraintSubactivitiesPreferredStartingTimes*)ctr;
02992                      if(groupName == crt_constraint->studentsName){
02993                             this->removeTimeConstraint(ctr);
02994                             erased=true;
02995                      }
02996               }
02997 
02998               if(!erased)
02999                      i++;
03000        }
03001 
03002        for(int i=0; i<this->spaceConstraintsList.size(); ){
03003               SpaceConstraint* ctr=this->spaceConstraintsList[i];
03004 
03005               bool erased=false;
03006               if(ctr->type==CONSTRAINT_STUDENTS_SET_HOME_ROOM){
03007                      ConstraintStudentsSetHomeRoom* crt_constraint=(ConstraintStudentsSetHomeRoom*)ctr;
03008                      if(groupName == crt_constraint->studentsName){
03009                             this->removeSpaceConstraint(ctr);
03010                             erased=true;
03011                      }
03012               }
03013               else if(ctr->type==CONSTRAINT_STUDENTS_SET_HOME_ROOMS){
03014                      ConstraintStudentsSetHomeRooms* crt_constraint=(ConstraintStudentsSetHomeRooms*)ctr;
03015                      if(groupName == crt_constraint->studentsName){
03016                             this->removeSpaceConstraint(ctr);
03017                             erased=true;
03018                      }
03019               }
03020               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_BUILDING_CHANGES_PER_DAY){
03021                      ConstraintStudentsSetMaxBuildingChangesPerDay* crt_constraint=(ConstraintStudentsSetMaxBuildingChangesPerDay*)ctr;
03022                      if(groupName == crt_constraint->studentsName){
03023                             this->removeSpaceConstraint(ctr);
03024                             erased=true;
03025                      }
03026               }
03027               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_BUILDING_CHANGES_PER_WEEK){
03028                      ConstraintStudentsSetMaxBuildingChangesPerWeek* crt_constraint=(ConstraintStudentsSetMaxBuildingChangesPerWeek*)ctr;
03029                      if(groupName == crt_constraint->studentsName){
03030                             this->removeSpaceConstraint(ctr);
03031                             erased=true;
03032                      }
03033               }
03034               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_GAPS_BETWEEN_BUILDING_CHANGES){
03035                      ConstraintStudentsSetMinGapsBetweenBuildingChanges* crt_constraint=(ConstraintStudentsSetMinGapsBetweenBuildingChanges*)ctr;
03036                      if(groupName == crt_constraint->studentsName){
03037                             this->removeSpaceConstraint(ctr);
03038                             erased=true;
03039                      }
03040               }
03041 
03042               if(!erased)
03043                      i++;
03044        }
03045 
03046        return true;
03047 }
03048 
03049 int Rules::searchGroup(const QString& yearName, const QString& groupName)
03050 {
03051        StudentsYear* sty=this->yearsList[this->searchYear(yearName)];
03052        assert(sty);
03053        
03054        for(int i=0; i<sty->groupsList.size(); i++)
03055               if(sty->groupsList[i]->name==groupName)
03056                      return i;
03057        
03058        return -1;
03059 }
03060 
03061 int Rules::searchAugmentedGroup(const QString& yearName, const QString& groupName)
03062 {
03063        StudentsYear* sty=this->augmentedYearsList[this->searchAugmentedYear(yearName)];
03064        assert(sty);
03065        
03066        for(int i=0; i<sty->groupsList.size(); i++)
03067               if(sty->groupsList[i]->name==groupName)
03068                      return i;
03069        
03070        return -1;
03071 }
03072 
03073 bool Rules::modifyGroup(const QString& yearName, const QString& initialGroupName, const QString& finalGroupName, int finalNumberOfStudents)
03074 {
03075        StudentsSet* _initialSet=searchStudentsSet(initialGroupName);
03076        assert(_initialSet!=NULL);
03077        int _initialNumberOfStudents=_initialSet->numberOfStudents;
03078 
03079        //cout<<"Begin: initialGroupName=='"<<qPrintableinitialGroupName<<"'"<<endl;
03080        
03081        QString _initialGroupName=initialGroupName;
03082 
03083        assert(searchGroup(yearName, _initialGroupName)>=0);
03084        StudentsSet* _ss=searchStudentsSet(finalGroupName);
03085        assert(_ss==NULL || _initialGroupName==finalGroupName);
03086 
03087        StudentsYear* sty=NULL;
03088        for(int i=0; i<this->yearsList.size(); i++){
03089               sty=this->yearsList[i];
03090               if(sty->name==yearName)
03091                      break;
03092        }
03093        assert(sty);
03094        
03095        StudentsGroup* stg=NULL;
03096        for(int i=0; i<sty->groupsList.size(); i++){
03097               stg=sty->groupsList[i];
03098               if(stg->name==_initialGroupName){
03099                      stg->name=finalGroupName;
03100                      stg->numberOfStudents=finalNumberOfStudents;
03101 
03102                      break;
03103               }
03104        }
03105        assert(stg);
03106        
03107        if(_ss!=NULL){ //In case it only changes the number of students, make the same number of students in all groups with this name
03108               assert(_initialGroupName==finalGroupName);
03109               foreach(StudentsYear* year, yearsList)
03110                      foreach(StudentsGroup* group, year->groupsList)
03111                             if(group->name==finalGroupName)
03112                                    group->numberOfStudents=finalNumberOfStudents;
03113        }
03114 
03115        for(int i=0; i<this->activitiesList.size(); i++)
03116               this->activitiesList[i]->renameStudents(*this, _initialGroupName, finalGroupName, _initialNumberOfStudents, finalNumberOfStudents);
03117        
03118        for(int i=0; i<this->timeConstraintsList.size(); i++){
03119               TimeConstraint* ctr=this->timeConstraintsList[i];
03120 
03121               if(ctr->type==CONSTRAINT_STUDENTS_SET_NOT_AVAILABLE_TIMES){
03122                      ConstraintStudentsSetNotAvailableTimes* crt_constraint=(ConstraintStudentsSetNotAvailableTimes*)ctr;
03123                      if(_initialGroupName == crt_constraint->students)
03124                             crt_constraint->students=finalGroupName;
03125               }
03126               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_DAILY){
03127                      ConstraintStudentsSetMaxHoursDaily* crt_constraint=(ConstraintStudentsSetMaxHoursDaily*)ctr;
03128                      if(_initialGroupName == crt_constraint->students)
03129                             crt_constraint->students=finalGroupName;
03130               }
03131               else if(ctr->type==CONSTRAINT_STUDENTS_SET_INTERVAL_MAX_DAYS_PER_WEEK){
03132                      ConstraintStudentsSetIntervalMaxDaysPerWeek* crt_constraint=(ConstraintStudentsSetIntervalMaxDaysPerWeek*)ctr;
03133                      if(_initialGroupName == crt_constraint->students)
03134                             crt_constraint->students=finalGroupName;
03135               }
03136               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_CONTINUOUSLY){
03137                      ConstraintStudentsSetMaxHoursContinuously* crt_constraint=(ConstraintStudentsSetMaxHoursContinuously*)ctr;
03138                      if(_initialGroupName == crt_constraint->students)
03139                             crt_constraint->students=finalGroupName;
03140               }
03141               else if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
03142                      ConstraintStudentsSetActivityTagMaxHoursContinuously* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursContinuously*)ctr;
03143                      if(_initialGroupName == crt_constraint->students)
03144                             crt_constraint->students=finalGroupName;
03145               }
03146               else if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_DAILY){
03147                      ConstraintStudentsSetActivityTagMaxHoursDaily* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursDaily*)ctr;
03148                      if(_initialGroupName == crt_constraint->students)
03149                             crt_constraint->students=finalGroupName;
03150               }
03151               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_HOURS_DAILY){
03152                      ConstraintStudentsSetMinHoursDaily* crt_constraint=(ConstraintStudentsSetMinHoursDaily*)ctr;
03153                      if(_initialGroupName == crt_constraint->students)
03154                             crt_constraint->students=finalGroupName;
03155               }
03156               else if(ctr->type==CONSTRAINT_STUDENTS_SET_EARLY_MAX_BEGINNINGS_AT_SECOND_HOUR){
03157                      ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour* crt_constraint=(ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour*)ctr;
03158                      if(_initialGroupName == crt_constraint->students)
03159                             crt_constraint->students=finalGroupName;
03160               }
03161               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_WEEK){
03162                      ConstraintStudentsSetMaxGapsPerWeek* crt_constraint=(ConstraintStudentsSetMaxGapsPerWeek*)ctr;
03163                      if(_initialGroupName == crt_constraint->students)
03164                             crt_constraint->students=finalGroupName;
03165               }
03166               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_DAY){
03167                      ConstraintStudentsSetMaxGapsPerDay* crt_constraint=(ConstraintStudentsSetMaxGapsPerDay*)ctr;
03168                      if(_initialGroupName == crt_constraint->students)
03169                             crt_constraint->students=finalGroupName;
03170               }
03171               else if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_TIME_SLOTS){
03172                      ConstraintActivitiesPreferredTimeSlots* crt_constraint=(ConstraintActivitiesPreferredTimeSlots*)ctr;
03173                      if(_initialGroupName == crt_constraint->p_studentsName)
03174                             crt_constraint->p_studentsName=finalGroupName;
03175               }
03176               else if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_STARTING_TIMES){
03177                      ConstraintActivitiesPreferredStartingTimes* crt_constraint=(ConstraintActivitiesPreferredStartingTimes*)ctr;
03178                      if(_initialGroupName == crt_constraint->studentsName)
03179                             crt_constraint->studentsName=finalGroupName;
03180               }
03181               else if(ctr->type==CONSTRAINT_ACTIVITIES_END_STUDENTS_DAY){
03182                      ConstraintActivitiesEndStudentsDay* crt_constraint=(ConstraintActivitiesEndStudentsDay*)ctr;
03183                      if(_initialGroupName == crt_constraint->studentsName)
03184                             crt_constraint->studentsName=finalGroupName;
03185               }
03186               else if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_TIME_SLOTS){
03187                      ConstraintSubactivitiesPreferredTimeSlots* crt_constraint=(ConstraintSubactivitiesPreferredTimeSlots*)ctr;
03188                      if(_initialGroupName == crt_constraint->p_studentsName)
03189                             crt_constraint->p_studentsName=finalGroupName;
03190               }
03191               else if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_STARTING_TIMES){
03192                      ConstraintSubactivitiesPreferredStartingTimes* crt_constraint=(ConstraintSubactivitiesPreferredStartingTimes*)ctr;
03193                      if(_initialGroupName == crt_constraint->studentsName)
03194                             crt_constraint->studentsName=finalGroupName;
03195               }
03196        }
03197 
03198        for(int i=0; i<this->spaceConstraintsList.size(); i++){
03199               SpaceConstraint* ctr=this->spaceConstraintsList[i];
03200 
03201               if(ctr->type==CONSTRAINT_STUDENTS_SET_HOME_ROOM){
03202                      ConstraintStudentsSetHomeRoom* crt_constraint=(ConstraintStudentsSetHomeRoom*)ctr;
03203                      if(_initialGroupName == crt_constraint->studentsName)
03204                             crt_constraint->studentsName=finalGroupName;
03205               }
03206               else if(ctr->type==CONSTRAINT_STUDENTS_SET_HOME_ROOMS){
03207                      ConstraintStudentsSetHomeRooms* crt_constraint=(ConstraintStudentsSetHomeRooms*)ctr;
03208                      if(_initialGroupName == crt_constraint->studentsName)
03209                             crt_constraint->studentsName=finalGroupName;
03210               }
03211               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_BUILDING_CHANGES_PER_DAY){
03212                      ConstraintStudentsSetMaxBuildingChangesPerDay* crt_constraint=(ConstraintStudentsSetMaxBuildingChangesPerDay*)ctr;
03213                      if(_initialGroupName == crt_constraint->studentsName)
03214                             crt_constraint->studentsName=finalGroupName;
03215               }
03216               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_BUILDING_CHANGES_PER_WEEK){
03217                      ConstraintStudentsSetMaxBuildingChangesPerWeek* crt_constraint=(ConstraintStudentsSetMaxBuildingChangesPerWeek*)ctr;
03218                      if(_initialGroupName == crt_constraint->studentsName)
03219                             crt_constraint->studentsName=finalGroupName;
03220               }
03221               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_GAPS_BETWEEN_BUILDING_CHANGES){
03222                      ConstraintStudentsSetMinGapsBetweenBuildingChanges* crt_constraint=(ConstraintStudentsSetMinGapsBetweenBuildingChanges*)ctr;
03223                      if(_initialGroupName == crt_constraint->studentsName)
03224                             crt_constraint->studentsName=finalGroupName;
03225               }
03226        }
03227 
03228        this->internalStructureComputed=false;
03229        setRulesModifiedAndOtherThings(this);
03230 
03231        return true;
03232 }
03233 
03234 void Rules::sortGroupsAlphabetically(const QString& yearName)
03235 {
03236        StudentsYear* sty=this->yearsList[this->searchYear(yearName)];
03237        assert(sty);
03238 
03239        qSort(sty->groupsList.begin(), sty->groupsList.end(), groupsAscending);
03240 
03241        this->internalStructureComputed=false;
03242        setRulesModifiedAndOtherThings(this);
03243 }
03244 
03245 bool Rules::addSubgroup(const QString& yearName, const QString& groupName, StudentsSubgroup* subgroup)
03246 {
03247        StudentsYear* sty=this->yearsList.at(this->searchYear(yearName));
03248        assert(sty);
03249        StudentsGroup* stg=sty->groupsList.at(this->searchGroup(yearName, groupName));
03250        assert(stg);
03251 
03252 
03253        for(int i=0; i<stg->subgroupsList.size(); i++){
03254               StudentsSubgroup* sts=stg->subgroupsList[i];
03255               if(sts->name==subgroup->name)
03256                      return false;
03257        }
03258        
03259        stg->subgroupsList << subgroup; //append
03260 
03261        /*
03262        foreach(StudentsYear* y, yearsList)
03263               foreach(StudentsGroup* g, y->groupsList)
03264                      foreach(StudentsSubgroup* s, g->subgroupsList)
03265                             if(s->name==subgroup->name)
03266                                    s->numberOfStudents=subgroup->numberOfStudents;*/
03267 
03268        this->internalStructureComputed=false;
03269        setRulesModifiedAndOtherThings(this);
03270        return true;
03271 }
03272 
03273 bool Rules::addSubgroupFast(StudentsYear* year, StudentsGroup* group, StudentsSubgroup* subgroup)
03274 {
03275        Q_UNUSED(year);
03276 
03277        group->subgroupsList << subgroup; //append
03278 
03279        this->internalStructureComputed=false;
03280        setRulesModifiedAndOtherThings(this);
03281        return true;
03282 }
03283 
03284 bool Rules::removeSubgroup(const QString& yearName, const QString& groupName, const QString& subgroupName)
03285 {
03286        this->internalStructureComputed=false;
03287        setRulesModifiedAndOtherThings(this);
03288 
03289        StudentsSubgroup* subgroup=(StudentsSubgroup*)searchStudentsSet(subgroupName);
03290        assert(subgroup!=NULL);
03291        int nStudents=subgroup->numberOfStudents;
03292 
03293        StudentsYear* sty=this->yearsList.at(this->searchYear(yearName));
03294        assert(sty);
03295        StudentsGroup* stg=sty->groupsList.at(this->searchGroup(yearName, groupName));
03296        assert(stg);
03297 
03298        StudentsSubgroup* sts=NULL;
03299        for(int i=0; i<stg->subgroupsList.size(); i++){
03300               sts=stg->subgroupsList[i];
03301               if(sts->name==subgroupName){
03302                      stg->subgroupsList.removeAt(i);
03303                      break;
03304               }
03305        }
03306        
03307        assert(sts!=NULL);
03308 
03309        if(this->searchStudentsSet(sts->name)!=NULL){
03310               //subgroup still exists, in other group
03311               
03312               //with the same pointer??? (leak bug fix on 6 Jan 2010 in FET-5.12.1)
03313               bool foundSamePointer=false;
03314               foreach(StudentsYear* year, yearsList){
03315                      foreach(StudentsGroup* group, year->groupsList){
03316                             foreach(StudentsSubgroup* subgroup, group->subgroupsList){
03317                                    if(subgroup==sts){
03318                                           foundSamePointer=true;
03319                                           break;
03320                                    }
03321                             }
03322                             if(foundSamePointer)
03323                                    break;
03324                      }
03325                      if(foundSamePointer)
03326                             break;
03327               }
03328               
03329               if(!foundSamePointer)
03330                      delete sts;
03332               
03333               return true;
03334        }
03335 
03336        delete sts;
03337 
03338        for(int i=0; i<this->activitiesList.size(); ){
03339               Activity* act=this->activitiesList[i];
03340 
03341               bool t=act->removeStudents(*this, subgroupName, nStudents);
03342               if(t && act->studentsNames.count()==0){
03343                      this->removeActivity(act->id, act->activityGroupId);
03344                      i=0;
03345                      //(You have to be careful, there can be erased more activities here)
03346               }
03347               else
03348                      i++;
03349        }
03350        
03351        for(int i=0; i<this->timeConstraintsList.size(); ){
03352               TimeConstraint* ctr=this->timeConstraintsList[i];
03353 
03354               bool erased=false;
03355               if(ctr->type==CONSTRAINT_STUDENTS_SET_NOT_AVAILABLE_TIMES){
03356                      ConstraintStudentsSetNotAvailableTimes* crt_constraint=(ConstraintStudentsSetNotAvailableTimes*)ctr;
03357                      if(subgroupName == crt_constraint->students){
03358                             this->removeTimeConstraint(ctr);
03359                             erased=true;
03360                      }
03361               }
03362               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_DAILY){
03363                      ConstraintStudentsSetMaxHoursDaily* crt_constraint=(ConstraintStudentsSetMaxHoursDaily*)ctr;
03364                      if(subgroupName == crt_constraint->students){
03365                             this->removeTimeConstraint(ctr);
03366                             erased=true;
03367                      }
03368               }
03369               else if(ctr->type==CONSTRAINT_STUDENTS_SET_INTERVAL_MAX_DAYS_PER_WEEK){
03370                      ConstraintStudentsSetIntervalMaxDaysPerWeek* crt_constraint=(ConstraintStudentsSetIntervalMaxDaysPerWeek*)ctr;
03371                      if(subgroupName == crt_constraint->students){
03372                             this->removeTimeConstraint(ctr);
03373                             erased=true;
03374                      }
03375               }
03376               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_CONTINUOUSLY){
03377                      ConstraintStudentsSetMaxHoursContinuously* crt_constraint=(ConstraintStudentsSetMaxHoursContinuously*)ctr;
03378                      if(subgroupName == crt_constraint->students){
03379                             this->removeTimeConstraint(ctr);
03380                             erased=true;
03381                      }
03382               }
03383               else if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
03384                      ConstraintStudentsSetActivityTagMaxHoursContinuously* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursContinuously*)ctr;
03385                      if(subgroupName == crt_constraint->students){
03386                             this->removeTimeConstraint(ctr);
03387                             erased=true;
03388                      }
03389               }
03390               else if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_DAILY){
03391                      ConstraintStudentsSetActivityTagMaxHoursDaily* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursDaily*)ctr;
03392                      if(subgroupName == crt_constraint->students){
03393                             this->removeTimeConstraint(ctr);
03394                             erased=true;
03395                      }
03396               }
03397               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_HOURS_DAILY){
03398                      ConstraintStudentsSetMinHoursDaily* crt_constraint=(ConstraintStudentsSetMinHoursDaily*)ctr;
03399                      if(subgroupName == crt_constraint->students){
03400                             this->removeTimeConstraint(ctr);
03401                             erased=true;
03402                      }
03403               }
03404               else if(ctr->type==CONSTRAINT_STUDENTS_SET_EARLY_MAX_BEGINNINGS_AT_SECOND_HOUR){
03405                      ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour* crt_constraint=(ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour*)ctr;
03406                      if(subgroupName == crt_constraint->students){
03407                             this->removeTimeConstraint(ctr);
03408                             erased=true;
03409                      }
03410               }
03411               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_WEEK){
03412                      ConstraintStudentsSetMaxGapsPerWeek* crt_constraint=(ConstraintStudentsSetMaxGapsPerWeek*)ctr;
03413                      if(subgroupName == crt_constraint->students){
03414                             this->removeTimeConstraint(ctr);
03415                             erased=true;
03416                      }
03417               }
03418               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_DAY){
03419                      ConstraintStudentsSetMaxGapsPerDay* crt_constraint=(ConstraintStudentsSetMaxGapsPerDay*)ctr;
03420                      if(subgroupName == crt_constraint->students){
03421                             this->removeTimeConstraint(ctr);
03422                             erased=true;
03423                      }
03424               }
03425               else if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_TIME_SLOTS){
03426                      ConstraintActivitiesPreferredTimeSlots* crt_constraint=(ConstraintActivitiesPreferredTimeSlots*)ctr;
03427                      if(subgroupName == crt_constraint->p_studentsName){
03428                             this->removeTimeConstraint(ctr);
03429                             erased=true;
03430                      }
03431               }
03432               else if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_STARTING_TIMES){
03433                      ConstraintActivitiesPreferredStartingTimes* crt_constraint=(ConstraintActivitiesPreferredStartingTimes*)ctr;
03434                      if(subgroupName == crt_constraint->studentsName){
03435                             this->removeTimeConstraint(ctr);
03436                             erased=true;
03437                      }
03438               }
03439               else if(ctr->type==CONSTRAINT_ACTIVITIES_END_STUDENTS_DAY){
03440                      ConstraintActivitiesEndStudentsDay* crt_constraint=(ConstraintActivitiesEndStudentsDay*)ctr;
03441                      if(subgroupName == crt_constraint->studentsName){
03442                             this->removeTimeConstraint(ctr);
03443                             erased=true;
03444                      }
03445               }
03446               else if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_TIME_SLOTS){
03447                      ConstraintSubactivitiesPreferredTimeSlots* crt_constraint=(ConstraintSubactivitiesPreferredTimeSlots*)ctr;
03448                      if(subgroupName == crt_constraint->p_studentsName){
03449                             this->removeTimeConstraint(ctr);
03450                             erased=true;
03451                      }
03452               }
03453               else if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_STARTING_TIMES){
03454                      ConstraintSubactivitiesPreferredStartingTimes* crt_constraint=(ConstraintSubactivitiesPreferredStartingTimes*)ctr;
03455                      if(subgroupName == crt_constraint->studentsName){
03456                             this->removeTimeConstraint(ctr);
03457                             erased=true;
03458                      }
03459               }
03460 
03461               if(!erased)
03462                      i++;
03463        }
03464        
03465        for(int i=0; i<this->spaceConstraintsList.size(); ){
03466               SpaceConstraint* ctr=this->spaceConstraintsList[i];
03467 
03468               bool erased=false;
03469               if(ctr->type==CONSTRAINT_STUDENTS_SET_HOME_ROOM){
03470                      ConstraintStudentsSetHomeRoom* crt_constraint=(ConstraintStudentsSetHomeRoom*)ctr;
03471                      if(subgroupName == crt_constraint->studentsName){
03472                             this->removeSpaceConstraint(ctr);
03473                             erased=true;
03474                      }
03475               }
03476               else if(ctr->type==CONSTRAINT_STUDENTS_SET_HOME_ROOMS){
03477                      ConstraintStudentsSetHomeRooms* crt_constraint=(ConstraintStudentsSetHomeRooms*)ctr;
03478                      if(subgroupName == crt_constraint->studentsName){
03479                             this->removeSpaceConstraint(ctr);
03480                             erased=true;
03481                      }
03482               }
03483               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_BUILDING_CHANGES_PER_DAY){
03484                      ConstraintStudentsSetMaxBuildingChangesPerDay* crt_constraint=(ConstraintStudentsSetMaxBuildingChangesPerDay*)ctr;
03485                      if(subgroupName == crt_constraint->studentsName){
03486                             this->removeSpaceConstraint(ctr);
03487                             erased=true;
03488                      }
03489               }
03490               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_BUILDING_CHANGES_PER_WEEK){
03491                      ConstraintStudentsSetMaxBuildingChangesPerWeek* crt_constraint=(ConstraintStudentsSetMaxBuildingChangesPerWeek*)ctr;
03492                      if(subgroupName == crt_constraint->studentsName){
03493                             this->removeSpaceConstraint(ctr);
03494                             erased=true;
03495                      }
03496               }
03497               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_GAPS_BETWEEN_BUILDING_CHANGES){
03498                      ConstraintStudentsSetMinGapsBetweenBuildingChanges* crt_constraint=(ConstraintStudentsSetMinGapsBetweenBuildingChanges*)ctr;
03499                      if(subgroupName == crt_constraint->studentsName){
03500                             this->removeSpaceConstraint(ctr);
03501                             erased=true;
03502                      }
03503               }
03504 
03505               if(!erased)
03506                      i++;
03507        }
03508 
03509        return true;
03510 }
03511 
03512 int Rules::searchSubgroup(const QString& yearName, const QString& groupName, const QString& subgroupName)
03513 {
03514        StudentsYear* sty=this->yearsList.at(this->searchYear(yearName));
03515        assert(sty);
03516        StudentsGroup* stg=sty->groupsList.at(this->searchGroup(yearName, groupName));
03517        assert(stg);
03518        
03519        for(int i=0; i<stg->subgroupsList.size(); i++)
03520               if(stg->subgroupsList[i]->name==subgroupName)
03521                      return i;
03522        
03523        return -1;
03524 }
03525 
03526 int Rules::searchAugmentedSubgroup(const QString& yearName, const QString& groupName, const QString& subgroupName)
03527 {
03528        StudentsYear* sty=this->augmentedYearsList.at(this->searchAugmentedYear(yearName));
03529        assert(sty);
03530        StudentsGroup* stg=sty->groupsList.at(this->searchAugmentedGroup(yearName, groupName));
03531        assert(stg);
03532        
03533        for(int i=0; i<stg->subgroupsList.size(); i++)
03534               if(stg->subgroupsList[i]->name==subgroupName)
03535                      return i;
03536        
03537        return -1;
03538 }
03539 
03540 bool Rules::modifySubgroup(const QString& yearName, const QString& groupName, const QString& initialSubgroupName, const QString& finalSubgroupName, int finalNumberOfStudents)
03541 {
03542        StudentsSet* _initialSet=searchStudentsSet(initialSubgroupName);
03543        assert(_initialSet!=NULL);
03544        int _initialNumberOfStudents=_initialSet->numberOfStudents;
03545 
03546        QString _initialSubgroupName=initialSubgroupName;
03547 
03548        assert(searchSubgroup(yearName, groupName, _initialSubgroupName)>=0);
03549        StudentsSet* _ss=searchStudentsSet(finalSubgroupName);
03550        assert(_ss==NULL || _initialSubgroupName==finalSubgroupName);
03551 
03552        StudentsYear* sty=this->yearsList.at(this->searchYear(yearName));
03553        assert(sty);
03554        StudentsGroup* stg=sty->groupsList.at(this->searchGroup(yearName, groupName));
03555        assert(stg);
03556 
03557        StudentsSubgroup* sts=NULL;
03558        for(int i=0; i<stg->subgroupsList.size(); i++){
03559               sts=stg->subgroupsList[i];
03560 
03561               if(sts->name==_initialSubgroupName){
03562                      sts->name=finalSubgroupName;
03563                      sts->numberOfStudents=finalNumberOfStudents;
03564                      break;
03565               }
03566        }
03567        assert(sts);
03568 
03569        if(_ss!=NULL){ //In case it only changes the number of students, make the same number of students in all subgroups with this name
03570               assert(_initialSubgroupName==finalSubgroupName);
03571               foreach(StudentsYear* year, yearsList)
03572                      foreach(StudentsGroup* group, year->groupsList)
03573                             foreach(StudentsSubgroup* subgroup, group->subgroupsList)
03574                                    if(subgroup->name==finalSubgroupName)
03575                                           subgroup->numberOfStudents=finalNumberOfStudents;
03576        }
03577 
03578        //TODO: improve this part
03579        for(int i=0; i<this->activitiesList.size(); i++)
03580               this->activitiesList[i]->renameStudents(*this, _initialSubgroupName, finalSubgroupName, _initialNumberOfStudents, finalNumberOfStudents);
03581 
03582        for(int i=0; i<this->timeConstraintsList.size(); i++){
03583               TimeConstraint* ctr=this->timeConstraintsList[i];
03584 
03585               if(ctr->type==CONSTRAINT_STUDENTS_SET_NOT_AVAILABLE_TIMES){
03586                      ConstraintStudentsSetNotAvailableTimes* crt_constraint=(ConstraintStudentsSetNotAvailableTimes*)ctr;
03587                      if(_initialSubgroupName == crt_constraint->students)
03588                             crt_constraint->students=finalSubgroupName;
03589               }
03590               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_DAILY){
03591                      ConstraintStudentsSetMaxHoursDaily* crt_constraint=(ConstraintStudentsSetMaxHoursDaily*)ctr;
03592                      if(_initialSubgroupName == crt_constraint->students)
03593                             crt_constraint->students=finalSubgroupName;
03594               }
03595               else if(ctr->type==CONSTRAINT_STUDENTS_SET_INTERVAL_MAX_DAYS_PER_WEEK){
03596                      ConstraintStudentsSetIntervalMaxDaysPerWeek* crt_constraint=(ConstraintStudentsSetIntervalMaxDaysPerWeek*)ctr;
03597                      if(_initialSubgroupName == crt_constraint->students)
03598                             crt_constraint->students=finalSubgroupName;
03599               }
03600               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_CONTINUOUSLY){
03601                      ConstraintStudentsSetMaxHoursContinuously* crt_constraint=(ConstraintStudentsSetMaxHoursContinuously*)ctr;
03602                      if(_initialSubgroupName == crt_constraint->students)
03603                             crt_constraint->students=finalSubgroupName;
03604               }
03605               else if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
03606                      ConstraintStudentsSetActivityTagMaxHoursContinuously* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursContinuously*)ctr;
03607                      if(_initialSubgroupName == crt_constraint->students)
03608                             crt_constraint->students=finalSubgroupName;
03609               }
03610               else if(ctr->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_DAILY){
03611                      ConstraintStudentsSetActivityTagMaxHoursDaily* crt_constraint=(ConstraintStudentsSetActivityTagMaxHoursDaily*)ctr;
03612                      if(_initialSubgroupName == crt_constraint->students)
03613                             crt_constraint->students=finalSubgroupName;
03614               }
03615               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_HOURS_DAILY){
03616                      ConstraintStudentsSetMinHoursDaily* crt_constraint=(ConstraintStudentsSetMinHoursDaily*)ctr;
03617                      if(_initialSubgroupName == crt_constraint->students)
03618                             crt_constraint->students=finalSubgroupName;
03619               }
03620               else if(ctr->type==CONSTRAINT_STUDENTS_SET_EARLY_MAX_BEGINNINGS_AT_SECOND_HOUR){
03621                      ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour* crt_constraint=(ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour*)ctr;
03622                      if(_initialSubgroupName == crt_constraint->students)
03623                             crt_constraint->students=finalSubgroupName;
03624               }
03625               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_WEEK){
03626                      ConstraintStudentsSetMaxGapsPerWeek* crt_constraint=(ConstraintStudentsSetMaxGapsPerWeek*)ctr;
03627                      if(_initialSubgroupName == crt_constraint->students)
03628                             crt_constraint->students=finalSubgroupName;
03629               }
03630               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_DAY){
03631                      ConstraintStudentsSetMaxGapsPerDay* crt_constraint=(ConstraintStudentsSetMaxGapsPerDay*)ctr;
03632                      if(_initialSubgroupName == crt_constraint->students)
03633                             crt_constraint->students=finalSubgroupName;
03634               }
03635               else if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_TIME_SLOTS){
03636                      ConstraintActivitiesPreferredTimeSlots* crt_constraint=(ConstraintActivitiesPreferredTimeSlots*)ctr;
03637                      if(_initialSubgroupName == crt_constraint->p_studentsName)
03638                             crt_constraint->p_studentsName=finalSubgroupName;
03639               }
03640               else if(ctr->type==CONSTRAINT_ACTIVITIES_PREFERRED_STARTING_TIMES){
03641                      ConstraintActivitiesPreferredStartingTimes* crt_constraint=(ConstraintActivitiesPreferredStartingTimes*)ctr;
03642                      if(_initialSubgroupName == crt_constraint->studentsName)
03643                             crt_constraint->studentsName=finalSubgroupName;
03644               }
03645               else if(ctr->type==CONSTRAINT_ACTIVITIES_END_STUDENTS_DAY){
03646                      ConstraintActivitiesEndStudentsDay* crt_constraint=(ConstraintActivitiesEndStudentsDay*)ctr;
03647                      if(_initialSubgroupName == crt_constraint->studentsName)
03648                             crt_constraint->studentsName=finalSubgroupName;
03649               }
03650               else if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_TIME_SLOTS){
03651                      ConstraintSubactivitiesPreferredTimeSlots* crt_constraint=(ConstraintSubactivitiesPreferredTimeSlots*)ctr;
03652                      if(_initialSubgroupName == crt_constraint->p_studentsName)
03653                             crt_constraint->p_studentsName=finalSubgroupName;
03654               }
03655               else if(ctr->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_STARTING_TIMES){
03656                      ConstraintSubactivitiesPreferredStartingTimes* crt_constraint=(ConstraintSubactivitiesPreferredStartingTimes*)ctr;
03657                      if(_initialSubgroupName == crt_constraint->studentsName)
03658                             crt_constraint->studentsName=finalSubgroupName;
03659               }
03660        }
03661 
03662        for(int i=0; i<this->spaceConstraintsList.size(); i++){
03663               SpaceConstraint* ctr=this->spaceConstraintsList[i];
03664 
03665               if(ctr->type==CONSTRAINT_STUDENTS_SET_HOME_ROOM){
03666                      ConstraintStudentsSetHomeRoom* crt_constraint=(ConstraintStudentsSetHomeRoom*)ctr;
03667                      if(_initialSubgroupName == crt_constraint->studentsName)
03668                             crt_constraint->studentsName=finalSubgroupName;
03669               }
03670               else if(ctr->type==CONSTRAINT_STUDENTS_SET_HOME_ROOMS){
03671                      ConstraintStudentsSetHomeRooms* crt_constraint=(ConstraintStudentsSetHomeRooms*)ctr;
03672                      if(_initialSubgroupName == crt_constraint->studentsName)
03673                             crt_constraint->studentsName=finalSubgroupName;
03674               }
03675               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_BUILDING_CHANGES_PER_DAY){
03676                      ConstraintStudentsSetMaxBuildingChangesPerDay* crt_constraint=(ConstraintStudentsSetMaxBuildingChangesPerDay*)ctr;
03677                      if(_initialSubgroupName == crt_constraint->studentsName)
03678                             crt_constraint->studentsName=finalSubgroupName;
03679               }
03680               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_BUILDING_CHANGES_PER_WEEK){
03681                      ConstraintStudentsSetMaxBuildingChangesPerWeek* crt_constraint=(ConstraintStudentsSetMaxBuildingChangesPerWeek*)ctr;
03682                      if(_initialSubgroupName == crt_constraint->studentsName)
03683                             crt_constraint->studentsName=finalSubgroupName;
03684               }
03685               else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_GAPS_BETWEEN_BUILDING_CHANGES){
03686                      ConstraintStudentsSetMinGapsBetweenBuildingChanges* crt_constraint=(ConstraintStudentsSetMinGapsBetweenBuildingChanges*)ctr;
03687                      if(_initialSubgroupName == crt_constraint->studentsName)
03688                             crt_constraint->studentsName=finalSubgroupName;
03689               }
03690        }
03691 
03692        this->internalStructureComputed=false;
03693        setRulesModifiedAndOtherThings(this);
03694 
03695        return true;
03696 }
03697 
03698 void Rules::sortSubgroupsAlphabetically(const QString& yearName, const QString& groupName)
03699 {
03700        StudentsYear* sty=this->yearsList.at(this->searchYear(yearName));
03701        assert(sty);
03702        StudentsGroup* stg=sty->groupsList.at(this->searchGroup(yearName, groupName));
03703        assert(stg);
03704 
03705        qSort(stg->subgroupsList.begin(), stg->subgroupsList.end(), subgroupsAscending);
03706        
03707        this->internalStructureComputed=false;
03708        setRulesModifiedAndOtherThings(this);
03709 }
03710 
03711 bool Rules::addSimpleActivity(
03712        QWidget* parent,
03713        int _id,
03714        int _activityGroupId,
03715        const QStringList& _teachersNames,
03716        const QString& _subjectName,
03717        const QStringList& _activityTagsNames,
03718        const QStringList& _studentsNames,
03719        int _duration, /*duration, in hours*/
03720        int _totalDuration,
03721        bool _active,
03722        bool _computeNTotalStudents,
03723        int _nTotalStudents)
03724 {
03725        //check for duplicates - idea and code by Volker Dirr
03726        int t=QStringList(_teachersNames).removeDuplicates();
03727        if(t>0)
03728               QMessageBox::warning(parent, tr("FET warning"), tr("Activity with Id=%1 contains %2 duplicate teachers - please correct that")
03729                .arg(_id).arg(t));
03730 
03731        t=QStringList(_studentsNames).removeDuplicates();
03732        if(t>0)
03733               QMessageBox::warning(parent, tr("FET warning"), tr("Activity with Id=%1 contains %2 duplicate students sets - please correct that")
03734                .arg(_id).arg(t));
03735 
03736        t=QStringList(_activityTagsNames).removeDuplicates();
03737        if(t>0)
03738               QMessageBox::warning(parent, tr("FET warning"), tr("Activity with Id=%1 contains %2 duplicate activity tags - please correct that")
03739                .arg(_id).arg(t));
03740 
03741        Activity *act=new Activity(*this, _id, _activityGroupId, _teachersNames, _subjectName, _activityTagsNames,
03742               _studentsNames, _duration, _totalDuration, _active, _computeNTotalStudents, _nTotalStudents);
03743 
03744        this->activitiesList << act; //append
03745 
03746        this->internalStructureComputed=false;
03747        setRulesModifiedAndOtherThings(this);
03748 
03749        return true;
03750 }
03751 
03752 bool Rules::addSimpleActivityRulesFast(
03753        QWidget* parent,
03754        int _id,
03755        int _activityGroupId,
03756        const QStringList& _teachersNames,
03757        const QString& _subjectName,
03758        const QStringList& _activityTagsNames,
03759        const QStringList& _studentsNames,
03760        int _duration, /*duration, in hours*/
03761        int _totalDuration,
03762        bool _active,
03763        bool _computeNTotalStudents,
03764        int _nTotalStudents,
03765        int _computedNumberOfStudents)
03766 {
03767        //check for duplicates - idea and code by Volker Dirr
03768        int t=QStringList(_teachersNames).removeDuplicates();
03769        if(t>0)
03770               QMessageBox::warning(parent, tr("FET warning"), tr("Activity with Id=%1 contains %2 duplicate teachers - please correct that")
03771                .arg(_id).arg(t));
03772 
03773        t=QStringList(_studentsNames).removeDuplicates();
03774        if(t>0)
03775               QMessageBox::warning(parent, tr("FET warning"), tr("Activity with Id=%1 contains %2 duplicate students sets - please correct that")
03776                .arg(_id).arg(t));
03777 
03778        t=QStringList(_activityTagsNames).removeDuplicates();
03779        if(t>0)
03780               QMessageBox::warning(parent, tr("FET warning"), tr("Activity with Id=%1 contains %2 duplicate activity tags - please correct that")
03781                .arg(_id).arg(t));
03782 
03783        Activity *act=new Activity(*this, _id, _activityGroupId, _teachersNames, _subjectName, _activityTagsNames,
03784               _studentsNames, _duration, _totalDuration, _active, _computeNTotalStudents, _nTotalStudents, _computedNumberOfStudents);
03785 
03786        this->activitiesList << act; //append
03787 
03788        this->internalStructureComputed=false;
03789        setRulesModifiedAndOtherThings(this);
03790 
03791        return true;
03792 }
03793 
03794 bool Rules::addSplitActivity(
03795        QWidget* parent,
03796        int _firstActivityId,
03797        int _activityGroupId,
03798        const QStringList& _teachersNames,
03799        const QString& _subjectName,
03800        const QStringList& _activityTagsNames,
03801        const QStringList& _studentsNames,
03802        int _nSplits,
03803        int _totalDuration,
03804        int _durations[],
03805        bool _active[],
03806        int _minDayDistance,
03807        double _weightPercentage,
03808        bool _consecutiveIfSameDay,
03809        bool _computeNTotalStudents,
03810        int _nTotalStudents)
03811 {
03812        //check for duplicates - idea and code by Volker Dirr
03813        int t=QStringList(_teachersNames).removeDuplicates();
03814        if(t>0)
03815               QMessageBox::warning(parent, tr("FET warning"), tr("Activities with group_Id=%1 contain %2 duplicate teachers - please correct that")
03816                .arg(_activityGroupId).arg(t));
03817 
03818        t=QStringList(_studentsNames).removeDuplicates();
03819        if(t>0)
03820               QMessageBox::warning(parent, tr("FET warning"), tr("Activities with group_Id=%1 contain %2 duplicate students sets - please correct that")
03821                .arg(_activityGroupId).arg(t));
03822 
03823        t=QStringList(_activityTagsNames).removeDuplicates();
03824        if(t>0)
03825               QMessageBox::warning(parent, tr("FET warning"), tr("Activities with group_Id=%1 contain %2 duplicate activity tags - please correct that")
03826                .arg(_activityGroupId).arg(t));
03827 
03828        assert(_firstActivityId==_activityGroupId);
03829 
03830        QList<int> acts;
03831 
03832        acts.clear();
03833        for(int i=0; i<_nSplits; i++){
03834               Activity *act;
03835               if(i==0)
03836                      act=new Activity(*this, _firstActivityId+i, _activityGroupId,
03837                             _teachersNames, _subjectName, _activityTagsNames, _studentsNames,
03838                             _durations[i], _totalDuration, _active[i], _computeNTotalStudents, _nTotalStudents);
03839               else
03840                      act=new Activity(*this, _firstActivityId+i, _activityGroupId,
03841                             _teachersNames, _subjectName, _activityTagsNames, _studentsNames,
03842                             _durations[i], _totalDuration, _active[i], _computeNTotalStudents, _nTotalStudents);
03843 
03844               this->activitiesList << act; //append
03845 
03846               acts.append(_firstActivityId+i);
03847        }
03848 
03849        if(_minDayDistance>0){
03850               TimeConstraint *constr=new ConstraintMinDaysBetweenActivities(_weightPercentage, _consecutiveIfSameDay, _nSplits, acts, _minDayDistance);
03851               bool tmp=this->addTimeConstraint(constr);
03852               assert(tmp);
03853        }
03854 
03855        this->internalStructureComputed=false;
03856        setRulesModifiedAndOtherThings(this);
03857 
03858        return true;
03859 }
03860 
03861 void Rules::removeActivity(int _id)
03862 {
03863        bool recomputeTime=false, recomputeSpace=false;
03864 
03865        for(int i=0; i<this->activitiesList.size(); i++){
03866               Activity* act=this->activitiesList[i];
03867               if(_id==act->id){
03868                      //removing ConstraintActivityPreferredTime-s referring to this activity
03869                      for(int j=0; j<this->timeConstraintsList.size(); ){
03870                             TimeConstraint* ctr=this->timeConstraintsList[j];
03871                             if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_STARTING_TIME){
03872                                    ConstraintActivityPreferredStartingTime *apt=(ConstraintActivityPreferredStartingTime*)ctr;
03873                                    if(apt->activityId==act->id){
03874                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
03875                                           this->removeTimeConstraint(ctr);
03876                                           recomputeTime=true;
03877                                    }
03878                                    else
03879                                           j++;
03880                             }
03881                             else
03882                                    j++;
03883                      }
03884                      //removing ConstraintTwoActivitiesConsecutive-s referring to this activity
03885                      for(int j=0; j<this->timeConstraintsList.size(); ){
03886                             TimeConstraint* ctr=this->timeConstraintsList[j];
03887                             if(ctr->type==CONSTRAINT_TWO_ACTIVITIES_CONSECUTIVE){
03888                                    ConstraintTwoActivitiesConsecutive *apt=(ConstraintTwoActivitiesConsecutive*)ctr;
03889                                    if(apt->firstActivityId==act->id){
03890                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
03891                                           this->removeTimeConstraint(ctr);
03892                                    }
03893                                    else if(apt->secondActivityId==act->id){
03894                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
03895                                           this->removeTimeConstraint(ctr);
03896                                    }
03897                                    else
03898                                           j++;
03899                             }
03900                             else
03901                                    j++;
03902                      }
03903                      //removing ConstraintTwoActivitiesGrouped-s referring to this activity
03904                      for(int j=0; j<this->timeConstraintsList.size(); ){
03905                             TimeConstraint* ctr=this->timeConstraintsList[j];
03906                             if(ctr->type==CONSTRAINT_TWO_ACTIVITIES_GROUPED){
03907                                    ConstraintTwoActivitiesGrouped *apt=(ConstraintTwoActivitiesGrouped*)ctr;
03908                                    if(apt->firstActivityId==act->id){
03909                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
03910                                           this->removeTimeConstraint(ctr);
03911                                    }
03912                                    else if(apt->secondActivityId==act->id){
03913                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
03914                                           this->removeTimeConstraint(ctr);
03915                                    }
03916                                    else
03917                                           j++;
03918                             }
03919                             else
03920                                    j++;
03921                      }
03922                      //removing ConstraintThreeActivitiesGrouped-s referring to this activity
03923                      for(int j=0; j<this->timeConstraintsList.size(); ){
03924                             TimeConstraint* ctr=this->timeConstraintsList[j];
03925                             if(ctr->type==CONSTRAINT_THREE_ACTIVITIES_GROUPED){
03926                                    ConstraintThreeActivitiesGrouped *apt=(ConstraintThreeActivitiesGrouped*)ctr;
03927                                    if(apt->firstActivityId==act->id){
03928                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
03929                                           this->removeTimeConstraint(ctr);
03930                                    }
03931                                    else if(apt->secondActivityId==act->id){
03932                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
03933                                           this->removeTimeConstraint(ctr);
03934                                    }
03935                                    else if(apt->thirdActivityId==act->id){
03936                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
03937                                           this->removeTimeConstraint(ctr);
03938                                    }
03939                                    else
03940                                           j++;
03941                             }
03942                             else
03943                                    j++;
03944                      }
03945                      //removing ConstraintTwoActivitiesOrdered-s referring to this activity
03946                      for(int j=0; j<this->timeConstraintsList.size(); ){
03947                             TimeConstraint* ctr=this->timeConstraintsList[j];
03948                             if(ctr->type==CONSTRAINT_TWO_ACTIVITIES_ORDERED){
03949                                    ConstraintTwoActivitiesOrdered *apt=(ConstraintTwoActivitiesOrdered*)ctr;
03950                                    if(apt->firstActivityId==act->id){
03951                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
03952                                           this->removeTimeConstraint(ctr);
03953                                    }
03954                                    else if(apt->secondActivityId==act->id){
03955                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
03956                                           this->removeTimeConstraint(ctr);
03957                                    }
03958                                    else
03959                                           j++;
03960                             }
03961                             else
03962                                    j++;
03963                      }
03964                      //removing ConstraintActivityPreferredTimes-s referring to this activity
03965                      for(int j=0; j<this->timeConstraintsList.size(); ){
03966                             TimeConstraint* ctr=this->timeConstraintsList[j];
03967                             if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_TIME_SLOTS){
03968                                    ConstraintActivityPreferredTimeSlots *apt=(ConstraintActivityPreferredTimeSlots*)ctr;
03969                                    if(apt->p_activityId==act->id){
03970                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
03971                                           this->removeTimeConstraint(ctr);
03972                                    }
03973                                    else
03974                                           j++;
03975                             }
03976                             else
03977                                    j++;
03978                      }
03979                      //removing ConstraintActivityPreferredStartingTimes-s referring to this activity
03980                      for(int j=0; j<this->timeConstraintsList.size(); ){
03981                             TimeConstraint* ctr=this->timeConstraintsList[j];
03982                             if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_STARTING_TIMES){
03983                                    ConstraintActivityPreferredStartingTimes *apt=(ConstraintActivityPreferredStartingTimes*)ctr;
03984                                    if(apt->activityId==act->id){
03985                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
03986                                           this->removeTimeConstraint(ctr);
03987                                    }
03988                                    else
03989                                           j++;
03990                             }
03991                             else
03992                                    j++;
03993                      }
03994                      //removing ConstraintActivityEndsStudentsDay-s referring to this activity
03995                      for(int j=0; j<this->timeConstraintsList.size(); ){
03996                             TimeConstraint* ctr=this->timeConstraintsList[j];
03997                             if(ctr->type==CONSTRAINT_ACTIVITY_ENDS_STUDENTS_DAY){
03998                                    ConstraintActivityEndsStudentsDay *apt=(ConstraintActivityEndsStudentsDay*)ctr;
03999                                    if(apt->activityId==act->id){
04000                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
04001                                           this->removeTimeConstraint(ctr);
04002                                    }
04003                                    else
04004                                           j++;
04005                             }
04006                             else
04007                                    j++;
04008                      }
04009 
04010                      //removing ConstraintActivityPreferredRoom-s referring to this activity
04011                      for(int j=0; j<this->spaceConstraintsList.size(); ){
04012                             SpaceConstraint* ctr=this->spaceConstraintsList[j];
04013                             if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOM){
04014                                    if(((ConstraintActivityPreferredRoom*)ctr)->activityId==act->id){
04015                                           this->removeSpaceConstraint(ctr);
04016                                           recomputeSpace=true;
04017                                    }
04018                                    else
04019                                           j++;
04020                             }
04021                             else
04022                                    j++;
04023                      }
04024                      //removing ConstraintActivityPreferredRooms-s referring to this activity
04025                      for(int j=0; j<this->spaceConstraintsList.size(); ){
04026                             SpaceConstraint* ctr=this->spaceConstraintsList[j];
04027                             if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOMS){
04028                                    if(((ConstraintActivityPreferredRooms*)ctr)->activityId==act->id)
04029                                           this->removeSpaceConstraint(ctr);
04030                                    else
04031                                           j++;
04032                             }
04033                             else
04034                                    j++;
04035                      }
04036 
04037                      //remove the activity
04038                      delete this->activitiesList[i];
04039                      this->activitiesList.removeAt(i); 
04040                      break;
04041               }
04042        }
04043 
04044        for(int i=0; i<this->timeConstraintsList.size(); ){
04045               TimeConstraint* ctr=this->timeConstraintsList[i];
04046               if(ctr->type==CONSTRAINT_MIN_DAYS_BETWEEN_ACTIVITIES){
04047                      ((ConstraintMinDaysBetweenActivities*)ctr)->removeUseless(*this);
04048                      if(((ConstraintMinDaysBetweenActivities*)ctr)->n_activities<2)
04049                             this->removeTimeConstraint(ctr);
04050                      else
04051                             i++;
04052               }
04053               else
04054                      i++;
04055        }
04056 
04057        for(int i=0; i<this->timeConstraintsList.size(); ){
04058               TimeConstraint* ctr=this->timeConstraintsList[i];
04059               if(ctr->type==CONSTRAINT_ACTIVITIES_OCCUPY_MAX_TIME_SLOTS_FROM_SELECTION){
04060                      ((ConstraintActivitiesOccupyMaxTimeSlotsFromSelection*)ctr)->removeUseless(*this);
04061                      if(((ConstraintActivitiesOccupyMaxTimeSlotsFromSelection*)ctr)->activitiesIds.count()<1)
04062                             this->removeTimeConstraint(ctr);
04063                      else
04064                             i++;
04065               }
04066               else
04067                      i++;
04068        }
04069 
04070        for(int i=0; i<this->timeConstraintsList.size(); ){
04071               TimeConstraint* ctr=this->timeConstraintsList[i];
04072               if(ctr->type==CONSTRAINT_ACTIVITIES_MAX_SIMULTANEOUS_IN_SELECTED_TIME_SLOTS){
04073                      ((ConstraintActivitiesMaxSimultaneousInSelectedTimeSlots*)ctr)->removeUseless(*this);
04074                      if(((ConstraintActivitiesMaxSimultaneousInSelectedTimeSlots*)ctr)->activitiesIds.count()<1)
04075                             this->removeTimeConstraint(ctr);
04076                      else
04077                             i++;
04078               }
04079               else
04080                      i++;
04081        }
04082 
04083        for(int i=0; i<this->timeConstraintsList.size(); ){
04084               TimeConstraint* ctr=this->timeConstraintsList[i];
04085               if(ctr->type==CONSTRAINT_MAX_DAYS_BETWEEN_ACTIVITIES){
04086                      ((ConstraintMaxDaysBetweenActivities*)ctr)->removeUseless(*this);
04087                      if(((ConstraintMaxDaysBetweenActivities*)ctr)->n_activities<2)
04088                             this->removeTimeConstraint(ctr);
04089                      else
04090                             i++;
04091               }
04092               else
04093                      i++;
04094        }
04095 
04096        for(int i=0; i<this->timeConstraintsList.size(); ){
04097               TimeConstraint* ctr=this->timeConstraintsList[i];
04098               if(ctr->type==CONSTRAINT_MIN_GAPS_BETWEEN_ACTIVITIES){
04099                      ((ConstraintMinGapsBetweenActivities*)ctr)->removeUseless(*this);
04100                      if(((ConstraintMinGapsBetweenActivities*)ctr)->n_activities<2)
04101                             this->removeTimeConstraint(ctr);
04102                      else
04103                             i++;
04104               }
04105               else
04106                      i++;
04107        }
04108 
04109        for(int i=0; i<this->timeConstraintsList.size(); ){
04110               TimeConstraint* ctr=this->timeConstraintsList[i];
04111               if(ctr->type==CONSTRAINT_ACTIVITIES_SAME_STARTING_TIME){
04112                      ((ConstraintActivitiesSameStartingTime*)ctr)->removeUseless(*this);
04113                      if(((ConstraintActivitiesSameStartingTime*)ctr)->n_activities<2)
04114                             this->removeTimeConstraint(ctr);
04115                      else
04116                             i++;
04117               }
04118               else
04119                      i++;
04120        }
04121 
04122        for(int i=0; i<this->timeConstraintsList.size(); ){
04123               TimeConstraint* ctr=this->timeConstraintsList[i];
04124               if(ctr->type==CONSTRAINT_ACTIVITIES_SAME_STARTING_HOUR){
04125                      ((ConstraintActivitiesSameStartingHour*)ctr)->removeUseless(*this);
04126                      if(((ConstraintActivitiesSameStartingHour*)ctr)->n_activities<2)
04127                             this->removeTimeConstraint(ctr);
04128                      else
04129                             i++;
04130               }
04131               else
04132                      i++;
04133        }
04134 
04135        for(int i=0; i<this->timeConstraintsList.size(); ){
04136               TimeConstraint* ctr=this->timeConstraintsList[i];
04137               if(ctr->type==CONSTRAINT_ACTIVITIES_SAME_STARTING_DAY){
04138                      ((ConstraintActivitiesSameStartingDay*)ctr)->removeUseless(*this);
04139                      if(((ConstraintActivitiesSameStartingDay*)ctr)->n_activities<2)
04140                             this->removeTimeConstraint(ctr);
04141                      else
04142                             i++;
04143               }
04144               else
04145                      i++;
04146        }
04147 
04148        for(int i=0; i<this->timeConstraintsList.size(); ){
04149               TimeConstraint* ctr=this->timeConstraintsList[i];
04150               if(ctr->type==CONSTRAINT_ACTIVITIES_NOT_OVERLAPPING){
04151                      ((ConstraintActivitiesNotOverlapping*)ctr)->removeUseless(*this);
04152                      if(((ConstraintActivitiesNotOverlapping*)ctr)->n_activities<2)
04153                             this->removeTimeConstraint(ctr);
04154                      else
04155                             i++;
04156               }
04157               else
04158                      i++;
04159        }
04160        
04161        for(int i=0; i<this->spaceConstraintsList.size(); ){
04162               SpaceConstraint* ctr=this->spaceConstraintsList[i];
04163               if(ctr->type==CONSTRAINT_ACTIVITIES_OCCUPY_MAX_DIFFERENT_ROOMS){
04164                      ((ConstraintActivitiesOccupyMaxDifferentRooms*)ctr)->removeUseless(*this);
04165                      if(((ConstraintActivitiesOccupyMaxDifferentRooms*)ctr)->activitiesIds.count()<2)
04166                             this->removeSpaceConstraint(ctr);
04167                      else
04168                             i++;
04169               }
04170               else
04171                      i++;
04172        }
04173 
04174        if(recomputeTime){
04175               LockUnlock::computeLockedUnlockedActivitiesOnlyTime();
04176        }
04177        if(recomputeSpace){
04178               LockUnlock::computeLockedUnlockedActivitiesOnlySpace();
04179        }
04180        if(recomputeTime || recomputeSpace){
04181               LockUnlock::increaseCommunicationSpinBox();
04182        }
04183 
04184        this->internalStructureComputed=false;
04185        setRulesModifiedAndOtherThings(this);
04186 }
04187 
04188 void Rules::removeActivity(int _id, int _activityGroupId)
04189 {
04190        bool recomputeTime=false;
04191        bool recomputeSpace=false;
04192        
04193        for(int i=0; i<this->activitiesList.size(); ){
04194               Activity* act=this->activitiesList[i];
04195 
04196               if(_id==act->id || (_activityGroupId>0 && _activityGroupId==act->activityGroupId)){
04197 
04198                      //removing ConstraintActivityPreferredTime-s referring to this activity
04199                      for(int j=0; j<this->timeConstraintsList.size(); ){
04200                             TimeConstraint* ctr=this->timeConstraintsList[j];
04201                             if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_STARTING_TIME){
04202                                    ConstraintActivityPreferredStartingTime *apt=(ConstraintActivityPreferredStartingTime*)ctr;
04203                                    if(apt->activityId==act->id){
04204                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
04205                                           this->removeTimeConstraint(ctr);
04206                                           recomputeTime=true;
04207                                    }
04208                                    else
04209                                           j++;
04210                             }
04211                             else
04212                                    j++;
04213                      }
04214                      //removing ConstraintTwoActivitiesConsecutive-s referring to this activity
04215                      for(int j=0; j<this->timeConstraintsList.size(); ){
04216                             TimeConstraint* ctr=this->timeConstraintsList[j];
04217                             if(ctr->type==CONSTRAINT_TWO_ACTIVITIES_CONSECUTIVE){
04218                                    ConstraintTwoActivitiesConsecutive *apt=(ConstraintTwoActivitiesConsecutive*)ctr;
04219                                    if(apt->firstActivityId==act->id){
04220                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
04221                                           this->removeTimeConstraint(ctr);
04222                                    }
04223                                    else if(apt->secondActivityId==act->id){
04224                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
04225                                           this->removeTimeConstraint(ctr);
04226                                    }
04227                                    else
04228                                           j++;
04229                             }
04230                             else
04231                                    j++;
04232                      }
04233                      //removing ConstraintTwoActivitiesGrouped-s referring to this activity
04234                      for(int j=0; j<this->timeConstraintsList.size(); ){
04235                             TimeConstraint* ctr=this->timeConstraintsList[j];
04236                             if(ctr->type==CONSTRAINT_TWO_ACTIVITIES_GROUPED){
04237                                    ConstraintTwoActivitiesGrouped *apt=(ConstraintTwoActivitiesGrouped*)ctr;
04238                                    if(apt->firstActivityId==act->id){
04239                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
04240                                           this->removeTimeConstraint(ctr);
04241                                    }
04242                                    else if(apt->secondActivityId==act->id){
04243                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
04244                                           this->removeTimeConstraint(ctr);
04245                                    }
04246                                    else
04247                                           j++;
04248                             }
04249                             else
04250                                    j++;
04251                      }
04252                      //removing ConstraintThreeActivitiesGrouped-s referring to this activity
04253                      for(int j=0; j<this->timeConstraintsList.size(); ){
04254                             TimeConstraint* ctr=this->timeConstraintsList[j];
04255                             if(ctr->type==CONSTRAINT_THREE_ACTIVITIES_GROUPED){
04256                                    ConstraintThreeActivitiesGrouped *apt=(ConstraintThreeActivitiesGrouped*)ctr;
04257                                    if(apt->firstActivityId==act->id){
04258                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
04259                                           this->removeTimeConstraint(ctr);
04260                                    }
04261                                    else if(apt->secondActivityId==act->id){
04262                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
04263                                           this->removeTimeConstraint(ctr);
04264                                    }
04265                                    else if(apt->thirdActivityId==act->id){
04266                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
04267                                           this->removeTimeConstraint(ctr);
04268                                    }
04269                                    else
04270                                           j++;
04271                             }
04272                             else
04273                                    j++;
04274                      }
04275                      //removing ConstraintTwoActivitiesOrdered-s referring to this activity
04276                      for(int j=0; j<this->timeConstraintsList.size(); ){
04277                             TimeConstraint* ctr=this->timeConstraintsList[j];
04278                             if(ctr->type==CONSTRAINT_TWO_ACTIVITIES_ORDERED){
04279                                    ConstraintTwoActivitiesOrdered *apt=(ConstraintTwoActivitiesOrdered*)ctr;
04280                                    if(apt->firstActivityId==act->id){
04281                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
04282                                           this->removeTimeConstraint(ctr);
04283                                    }
04284                                    else if(apt->secondActivityId==act->id){
04285                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
04286                                           this->removeTimeConstraint(ctr);
04287                                    }
04288                                    else
04289                                           j++;
04290                             }
04291                             else
04292                                    j++;
04293                      }
04294                      //removing ConstraintActivityPreferredTimes-s referring to this activity
04295                      for(int j=0; j<this->timeConstraintsList.size(); ){
04296                             TimeConstraint* ctr=this->timeConstraintsList[j];
04297                             if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_TIME_SLOTS){
04298                                    ConstraintActivityPreferredTimeSlots *apt=(ConstraintActivityPreferredTimeSlots*)ctr;
04299                                    if(apt->p_activityId==act->id){
04300                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
04301                                           this->removeTimeConstraint(ctr);
04302                                    }
04303                                    else
04304                                           j++;
04305                             }
04306                             else
04307                                    j++;
04308                      }
04309                      //removing ConstraintActivityPreferredStartingTimes-s referring to this activity
04310                      for(int j=0; j<this->timeConstraintsList.size(); ){
04311                             TimeConstraint* ctr=this->timeConstraintsList[j];
04312                             if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_STARTING_TIMES){
04313                                    ConstraintActivityPreferredStartingTimes *apt=(ConstraintActivityPreferredStartingTimes*)ctr;
04314                                    if(apt->activityId==act->id){
04315                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
04316                                           this->removeTimeConstraint(ctr);
04317                                    }
04318                                    else
04319                                           j++;
04320                             }
04321                             else
04322                                    j++;
04323                      }
04324                      //removing ConstraintActivityEndsStudentsDay-s referring to this activity
04325                      for(int j=0; j<this->timeConstraintsList.size(); ){
04326                             TimeConstraint* ctr=this->timeConstraintsList[j];
04327                             if(ctr->type==CONSTRAINT_ACTIVITY_ENDS_STUDENTS_DAY){
04328                                    ConstraintActivityEndsStudentsDay *apt=(ConstraintActivityEndsStudentsDay*)ctr;
04329                                    if(apt->activityId==act->id){
04330                                           //cout<<"Removing constraint "<<qPrintable(apt->getDescription(*this))<<endl;
04331                                           this->removeTimeConstraint(ctr);
04332                                    }
04333                                    else
04334                                           j++;
04335                             }
04336                             else
04337                                    j++;
04338                      }
04339 
04340                      //removing ConstraintActivityPreferredRoom-s referring to this activity
04341                      for(int j=0; j<this->spaceConstraintsList.size(); ){
04342                             SpaceConstraint* ctr=this->spaceConstraintsList[j];
04343                             if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOM){
04344                                    if(((ConstraintActivityPreferredRoom*)ctr)->activityId==act->id){
04345                                           this->removeSpaceConstraint(ctr);
04346                                           recomputeSpace=true;
04347                                    }
04348                                    else
04349                                           j++;
04350                             }
04351                             else
04352                                    j++;
04353                      }
04354                      //removing ConstraintActivityPreferredRooms-s referring to this activity
04355                      for(int j=0; j<this->spaceConstraintsList.size(); ){
04356                             SpaceConstraint* ctr=this->spaceConstraintsList[j];
04357                             if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOMS){
04358                                    if(((ConstraintActivityPreferredRooms*)ctr)->activityId==act->id)
04359                                           this->removeSpaceConstraint(ctr);
04360                                    else
04361                                           j++;
04362                             }
04363                             else
04364                                    j++;
04365                      }
04366 
04367                      delete this->activitiesList[i];
04368                      this->activitiesList.removeAt(i); //if this is the last activity, then we will make one more comparison above
04369               }
04370               else
04371                      i++;
04372        }
04373 
04374        for(int i=0; i<this->timeConstraintsList.size(); ){
04375               TimeConstraint* ctr=this->timeConstraintsList[i];
04376               if(ctr->type==CONSTRAINT_MIN_DAYS_BETWEEN_ACTIVITIES){
04377                      ((ConstraintMinDaysBetweenActivities*)ctr)->removeUseless(*this);
04378                      if(((ConstraintMinDaysBetweenActivities*)ctr)->n_activities<2)
04379                             this->removeTimeConstraint(ctr);
04380                      else
04381                             i++;
04382               }
04383               else
04384                      i++;
04385        }
04386 
04387        for(int i=0; i<this->timeConstraintsList.size(); ){
04388               TimeConstraint* ctr=this->timeConstraintsList[i];
04389               if(ctr->type==CONSTRAINT_ACTIVITIES_OCCUPY_MAX_TIME_SLOTS_FROM_SELECTION){
04390                      ((ConstraintActivitiesOccupyMaxTimeSlotsFromSelection*)ctr)->removeUseless(*this);
04391                      if(((ConstraintActivitiesOccupyMaxTimeSlotsFromSelection*)ctr)->activitiesIds.count()<1)
04392                             this->removeTimeConstraint(ctr);
04393                      else
04394                             i++;
04395               }
04396               else
04397                      i++;
04398        }
04399 
04400        for(int i=0; i<this->timeConstraintsList.size(); ){
04401               TimeConstraint* ctr=this->timeConstraintsList[i];
04402               if(ctr->type==CONSTRAINT_ACTIVITIES_MAX_SIMULTANEOUS_IN_SELECTED_TIME_SLOTS){
04403                      ((ConstraintActivitiesMaxSimultaneousInSelectedTimeSlots*)ctr)->removeUseless(*this);
04404                      if(((ConstraintActivitiesMaxSimultaneousInSelectedTimeSlots*)ctr)->activitiesIds.count()<1)
04405                             this->removeTimeConstraint(ctr);
04406                      else
04407                             i++;
04408               }
04409               else
04410                      i++;
04411        }
04412 
04413        for(int i=0; i<this->timeConstraintsList.size(); ){
04414               TimeConstraint* ctr=this->timeConstraintsList[i];
04415               if(ctr->type==CONSTRAINT_MAX_DAYS_BETWEEN_ACTIVITIES){
04416                      ((ConstraintMaxDaysBetweenActivities*)ctr)->removeUseless(*this);
04417                      if(((ConstraintMaxDaysBetweenActivities*)ctr)->n_activities<2)
04418                             this->removeTimeConstraint(ctr);
04419                      else
04420                             i++;
04421               }
04422               else
04423                      i++;
04424        }
04425 
04426        for(int i=0; i<this->timeConstraintsList.size(); ){
04427               TimeConstraint* ctr=this->timeConstraintsList[i];
04428               if(ctr->type==CONSTRAINT_MIN_GAPS_BETWEEN_ACTIVITIES){
04429                      ((ConstraintMinGapsBetweenActivities*)ctr)->removeUseless(*this);
04430                      if(((ConstraintMinGapsBetweenActivities*)ctr)->n_activities<2)
04431                             this->removeTimeConstraint(ctr);
04432                      else
04433                             i++;
04434               }
04435               else
04436                      i++;
04437        }
04438 
04439        for(int i=0; i<this->timeConstraintsList.size(); ){
04440               TimeConstraint* ctr=this->timeConstraintsList[i];
04441               if(ctr->type==CONSTRAINT_ACTIVITIES_SAME_STARTING_TIME){
04442                      ((ConstraintActivitiesSameStartingTime*)ctr)->removeUseless(*this);
04443                      if(((ConstraintActivitiesSameStartingTime*)ctr)->n_activities<2)
04444                             this->removeTimeConstraint(ctr);
04445                      else
04446                             i++;
04447               }
04448               else
04449                      i++;
04450        }
04451 
04452        for(int i=0; i<this->timeConstraintsList.size(); ){
04453               TimeConstraint* ctr=this->timeConstraintsList[i];
04454               if(ctr->type==CONSTRAINT_ACTIVITIES_SAME_STARTING_HOUR){
04455                      ((ConstraintActivitiesSameStartingHour*)ctr)->removeUseless(*this);
04456                      if(((ConstraintActivitiesSameStartingHour*)ctr)->n_activities<2)
04457                             this->removeTimeConstraint(ctr);
04458                      else
04459                             i++;
04460               }
04461               else
04462                      i++;
04463        }
04464 
04465        for(int i=0; i<this->timeConstraintsList.size(); ){
04466               TimeConstraint* ctr=this->timeConstraintsList[i];
04467               if(ctr->type==CONSTRAINT_ACTIVITIES_SAME_STARTING_DAY){
04468                      ((ConstraintActivitiesSameStartingDay*)ctr)->removeUseless(*this);
04469                      if(((ConstraintActivitiesSameStartingDay*)ctr)->n_activities<2)
04470                             this->removeTimeConstraint(ctr);
04471                      else
04472                             i++;
04473               }
04474               else
04475                      i++;
04476        }
04477 
04478        for(int i=0; i<this->timeConstraintsList.size(); ){
04479               TimeConstraint* ctr=this->timeConstraintsList[i];
04480               if(ctr->type==CONSTRAINT_ACTIVITIES_NOT_OVERLAPPING){
04481                      ((ConstraintActivitiesNotOverlapping*)ctr)->removeUseless(*this);
04482                      if(((ConstraintActivitiesNotOverlapping*)ctr)->n_activities<2)
04483                             this->removeTimeConstraint(ctr);
04484                      else
04485                             i++;
04486               }
04487               else
04488                      i++;
04489        }
04490 
04491        for(int i=0; i<this->spaceConstraintsList.size(); ){
04492               SpaceConstraint* ctr=this->spaceConstraintsList[i];
04493               if(ctr->type==CONSTRAINT_ACTIVITIES_OCCUPY_MAX_DIFFERENT_ROOMS){
04494                      ((ConstraintActivitiesOccupyMaxDifferentRooms*)ctr)->removeUseless(*this);
04495                      if(((ConstraintActivitiesOccupyMaxDifferentRooms*)ctr)->activitiesIds.count()<2)
04496                             this->removeSpaceConstraint(ctr);
04497                      else
04498                             i++;
04499               }
04500               else
04501                      i++;
04502        }
04503 
04504        if(recomputeTime){
04505               LockUnlock::computeLockedUnlockedActivitiesOnlyTime();
04506        }
04507        if(recomputeSpace){
04508               LockUnlock::computeLockedUnlockedActivitiesOnlySpace();
04509        }
04510        if(recomputeTime || recomputeSpace){
04511               LockUnlock::increaseCommunicationSpinBox();
04512        }
04513 
04514        this->internalStructureComputed=false;
04515        setRulesModifiedAndOtherThings(this);
04516 }
04517 
04518 void Rules::modifyActivity(
04519        int _id,
04520        int _activityGroupId,
04521        const QStringList& _teachersNames,
04522        const QString& _subjectName,
04523        const QStringList& _activityTagsNames,
04524        const QStringList& _studentsNames,
04525        //int _nTotalStudents,
04526        int _nSplits,
04527        int _totalDuration,
04528        int _durations[],
04529        //int _parities[],
04530        bool _active[],
04531        bool _computeNTotalStudents,
04532        int _nTotalStudents)
04533 {
04534        int i=0;
04535        for(int j=0; j<this->activitiesList.size(); j++){
04536               Activity* act=this->activitiesList[j];
04537               if((_activityGroupId==0 && act->id==_id) || (_activityGroupId!=0 && act->activityGroupId==_activityGroupId)){
04538                      act->teachersNames=_teachersNames;
04539                      act->subjectName=_subjectName;
04540                      act->activityTagsNames=_activityTagsNames;
04541                      act->studentsNames=_studentsNames;
04542                      act->duration=_durations[i];
04543                      //act->parity=_parities[i];
04544                      act->active=_active[i];
04545                      act->totalDuration=_totalDuration;
04546                      act->computeNTotalStudents=_computeNTotalStudents;
04547                      act->nTotalStudents=_nTotalStudents;
04548                      i++;
04549               }
04550        }
04551               
04552        assert(i==_nSplits);
04553        
04554        this->internalStructureComputed=false;
04555        setRulesModifiedAndOtherThings(this);
04556 }
04557 
04558 void Rules::modifySubactivity(
04559        int _id,
04560        int _activityGroupId,
04561        const QStringList& _teachersNames,
04562        const QString& _subjectName,
04563        const QStringList& _activityTagsNames,
04564        const QStringList& _studentsNames,
04565        int _duration,
04566        bool _active,
04567        bool _computeNTotalStudents,
04568        int _nTotalStudents)
04569 {
04570        QList<Activity*> actsList;
04571        Activity* crtAct=NULL;
04572        
04573        foreach(Activity* act, this->activitiesList){
04574               if(act->id==_id && act->activityGroupId==_activityGroupId){
04575                      crtAct=act;
04576                      //actsList.append(act);
04577               }
04578               else if(act->activityGroupId!=0 && _activityGroupId!=0 && act->activityGroupId==_activityGroupId){
04579                      actsList.append(act);
04580               }
04581        }
04582        
04583        assert(crtAct!=NULL);
04584        
04585        int td=0;
04586        foreach(Activity* act, actsList)
04587               td+=act->duration;
04588        td+=_duration; //crtAct->duration;
04589        foreach(Activity* act, actsList)
04590               act->totalDuration=td;
04591 
04592        crtAct->teachersNames=_teachersNames;
04593        crtAct->subjectName=_subjectName;
04594        crtAct->activityTagsNames=_activityTagsNames;
04595        crtAct->studentsNames=_studentsNames;
04596        crtAct->duration=_duration;
04597        crtAct->totalDuration=td;
04598        crtAct->active=_active;
04599        crtAct->computeNTotalStudents=_computeNTotalStudents;
04600        crtAct->nTotalStudents=_nTotalStudents;
04601        
04602        this->internalStructureComputed=false;
04603        setRulesModifiedAndOtherThings(this);
04604 }
04605 
04606 bool Rules::addRoom(Room* rm)
04607 {
04608        if(this->searchRoom(rm->name) >= 0)
04609               return false;
04610        this->roomsList << rm; //append
04611        this->internalStructureComputed=false;
04612        setRulesModifiedAndOtherThings(this);
04613 
04614        teachers_schedule_ready=false;
04615        students_schedule_ready=false;
04616        rooms_schedule_ready=false;
04617 
04618        return true;
04619 }
04620 
04621 bool Rules::addRoomFast(Room* rm)
04622 {
04623        this->roomsList << rm; //append
04624        this->internalStructureComputed=false;
04625        setRulesModifiedAndOtherThings(this);
04626 
04627        teachers_schedule_ready=false;
04628        students_schedule_ready=false;
04629        rooms_schedule_ready=false;
04630 
04631        return true;
04632 }
04633 
04634 int Rules::searchRoom(const QString& roomName)
04635 {
04636        for(int i=0; i<this->roomsList.size(); i++)
04637               if(this->roomsList[i]->name==roomName)
04638                      return i;
04639        
04640        return -1;
04641 }
04642 
04643 bool Rules::removeRoom(QWidget* parent, const QString& roomName)
04644 {
04645        bool recomputeSpace=false;
04646 
04647        int i=this->searchRoom(roomName);
04648        if(i<0)
04649               return false;
04650 
04651        Room* searchedRoom=this->roomsList[i];
04652        assert(searchedRoom->name==roomName);
04653 
04654        for(int j=0; j<this->spaceConstraintsList.size(); ){
04655               SpaceConstraint* ctr=this->spaceConstraintsList[j];
04656               if(ctr->type==CONSTRAINT_ROOM_NOT_AVAILABLE_TIMES){
04657                      ConstraintRoomNotAvailableTimes* crna=(ConstraintRoomNotAvailableTimes*)ctr;
04658                      if(crna->room==roomName)
04659                             this->removeSpaceConstraint(ctr);
04660                      else
04661                             j++;
04662               }
04663               else if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOM){
04664                      ConstraintActivityPreferredRoom* c=(ConstraintActivityPreferredRoom*)ctr;
04665                      if(c->roomName==roomName){
04666                             this->removeSpaceConstraint(ctr);
04667                             
04668                             recomputeSpace=true;
04669                      }
04670                      else
04671                             j++;
04672               }
04673               else if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOMS){
04674                      ConstraintActivityPreferredRooms* c=(ConstraintActivityPreferredRooms*)ctr;
04675                      int t=c->roomsNames.removeAll(roomName);
04676                      assert(t<=1);
04677                      if(t==1 && c->roomsNames.count()==0)
04678                             this->removeSpaceConstraint(ctr);
04679                      else if(t==1 && c->roomsNames.count()==1){
04680                             ConstraintActivityPreferredRoom* c2=new ConstraintActivityPreferredRoom
04681                              (c->weightPercentage, c->activityId, c->roomsNames.at(0), true); //true means permanently locked
04682 
04683                             QMessageBox::information(parent, tr("FET information"), 
04684                              tr("The constraint\n%1 will be modified into constraint\n%2 because"
04685                              " there is only one room left in the constraint")
04686                              .arg(c->getDetailedDescription(*this))
04687                              .arg(c2->getDetailedDescription(*this)));
04688 
04689                             this->removeSpaceConstraint(ctr);
04690                             this->addSpaceConstraint(c2);
04691                             
04692                             recomputeSpace=true;
04693                      }
04694                      else
04695                             j++;
04696               }
04697               else if(ctr->type==CONSTRAINT_STUDENTS_SET_HOME_ROOM){
04698                      ConstraintStudentsSetHomeRoom* c=(ConstraintStudentsSetHomeRoom*)ctr;
04699                      if(c->roomName==roomName)
04700                             this->removeSpaceConstraint(ctr);
04701                      else
04702                             j++;
04703               }
04704               else if(ctr->type==CONSTRAINT_STUDENTS_SET_HOME_ROOMS){
04705                      ConstraintStudentsSetHomeRooms* c=(ConstraintStudentsSetHomeRooms*)ctr;
04706                      int t=c->roomsNames.removeAll(roomName);
04707                      assert(t<=1);
04708                      if(t==1 && c->roomsNames.count()==0)
04709                             this->removeSpaceConstraint(ctr);
04710                      else if(t==1 && c->roomsNames.count()==1){
04711                             ConstraintStudentsSetHomeRoom* c2=new ConstraintStudentsSetHomeRoom
04712                              (c->weightPercentage, c->studentsName, c->roomsNames.at(0));
04713 
04714                             QMessageBox::information(parent, tr("FET information"), 
04715                              tr("The constraint\n%1 will be modified into constraint\n%2 because"
04716                              " there is only one room left in the constraint")
04717                              .arg(c->getDetailedDescription(*this))
04718                              .arg(c2->getDetailedDescription(*this)));
04719 
04720                             this->removeSpaceConstraint(ctr);
04721                             this->addSpaceConstraint(c2);
04722                      }
04723                      else
04724                             j++;
04725               }
04726               else if(ctr->type==CONSTRAINT_TEACHER_HOME_ROOM){
04727                      ConstraintTeacherHomeRoom* c=(ConstraintTeacherHomeRoom*)ctr;
04728                      if(c->roomName==roomName)
04729                             this->removeSpaceConstraint(ctr);
04730                      else
04731                             j++;
04732               }
04733               else if(ctr->type==CONSTRAINT_TEACHER_HOME_ROOMS){
04734                      ConstraintTeacherHomeRooms* c=(ConstraintTeacherHomeRooms*)ctr;
04735                      int t=c->roomsNames.removeAll(roomName);
04736                      assert(t<=1);
04737                      if(t==1 && c->roomsNames.count()==0)
04738                             this->removeSpaceConstraint(ctr);
04739                      else if(t==1 && c->roomsNames.count()==1){
04740                             ConstraintTeacherHomeRoom* c2=new ConstraintTeacherHomeRoom
04741                              (c->weightPercentage, c->teacherName, c->roomsNames.at(0));
04742 
04743                             QMessageBox::information(parent, tr("FET information"), 
04744                              tr("The constraint\n%1 will be modified into constraint\n%2 because"
04745                              " there is only one room left in the constraint")
04746                              .arg(c->getDetailedDescription(*this))
04747                              .arg(c2->getDetailedDescription(*this)));
04748 
04749                             this->removeSpaceConstraint(ctr);
04750                             this->addSpaceConstraint(c2);
04751                      }
04752                      else
04753                             j++;
04754               }
04755               else if(ctr->type==CONSTRAINT_SUBJECT_PREFERRED_ROOM){
04756                      ConstraintSubjectPreferredRoom* c=(ConstraintSubjectPreferredRoom*)ctr;
04757                      if(c->roomName==roomName)
04758                             this->removeSpaceConstraint(ctr);
04759                      else
04760                             j++;
04761               }
04762               else if(ctr->type==CONSTRAINT_SUBJECT_PREFERRED_ROOMS){
04763                      ConstraintSubjectPreferredRooms* c=(ConstraintSubjectPreferredRooms*)ctr;
04764                      int t=c->roomsNames.removeAll(roomName);
04765                      assert(t<=1);
04766                      if(t==1 && c->roomsNames.count()==0)
04767                             this->removeSpaceConstraint(ctr);
04768                      else if(t==1 && c->roomsNames.count()==1){
04769                             ConstraintSubjectPreferredRoom* c2=new ConstraintSubjectPreferredRoom
04770                              (c->weightPercentage, c->subjectName, c->roomsNames.at(0));
04771 
04772                             QMessageBox::information(parent, tr("FET information"), 
04773                              tr("The constraint\n%1 will be modified into constraint\n%2 because"
04774                              " there is only one room left in the constraint")
04775                              .arg(c->getDetailedDescription(*this))
04776                              .arg(c2->getDetailedDescription(*this)));
04777 
04778                             this->removeSpaceConstraint(ctr);
04779                             this->addSpaceConstraint(c2);
04780                      }
04781                      else
04782                             j++;
04783               }
04784               else if(ctr->type==CONSTRAINT_SUBJECT_ACTIVITY_TAG_PREFERRED_ROOM){
04785                      ConstraintSubjectActivityTagPreferredRoom* c=(ConstraintSubjectActivityTagPreferredRoom*)ctr;
04786                      if(c->roomName==roomName)
04787                             this->removeSpaceConstraint(ctr);
04788                      else
04789                             j++;
04790               }
04791               else if(ctr->type==CONSTRAINT_SUBJECT_ACTIVITY_TAG_PREFERRED_ROOMS){
04792                      ConstraintSubjectActivityTagPreferredRooms* c=(ConstraintSubjectActivityTagPreferredRooms*)ctr;
04793                      int t=c->roomsNames.removeAll(roomName);
04794                      assert(t<=1);
04795                      if(t==1 && c->roomsNames.count()==0)
04796                             this->removeSpaceConstraint(ctr);
04797                      else if(t==1 && c->roomsNames.count()==1){
04798                             ConstraintSubjectActivityTagPreferredRoom* c2=new ConstraintSubjectActivityTagPreferredRoom
04799                              (c->weightPercentage, c->subjectName, c->activityTagName, c->roomsNames.at(0));
04800 
04801                             QMessageBox::information(parent, tr("FET information"), 
04802                              tr("The constraint\n%1 will be modified into constraint\n%2 because"
04803                              " there is only one room left in the constraint")
04804                              .arg(c->getDetailedDescription(*this))
04805                              .arg(c2->getDetailedDescription(*this)));
04806 
04807                             this->removeSpaceConstraint(ctr);
04808                             this->addSpaceConstraint(c2);
04809                      }
04810                      else
04811                             j++;
04812               }
04813 
04814               else if(ctr->type==CONSTRAINT_ACTIVITY_TAG_PREFERRED_ROOM){
04815                      ConstraintActivityTagPreferredRoom* c=(ConstraintActivityTagPreferredRoom*)ctr;
04816                      if(c->roomName==roomName)
04817                             this->removeSpaceConstraint(ctr);
04818                      else
04819                             j++;
04820               }
04821               else if(ctr->type==CONSTRAINT_ACTIVITY_TAG_PREFERRED_ROOMS){
04822                      ConstraintActivityTagPreferredRooms* c=(ConstraintActivityTagPreferredRooms*)ctr;
04823                      int t=c->roomsNames.removeAll(roomName);
04824                      assert(t<=1);
04825                      if(t==1 && c->roomsNames.count()==0)
04826                             this->removeSpaceConstraint(ctr);
04827                      else if(t==1 && c->roomsNames.count()==1){
04828                             ConstraintActivityTagPreferredRoom* c2=new ConstraintActivityTagPreferredRoom
04829                              (c->weightPercentage, c->activityTagName, c->roomsNames.at(0));
04830 
04831                             QMessageBox::information(parent, tr("FET information"), 
04832                              tr("The constraint\n%1 will be modified into constraint\n%2 because"
04833                              " there is only one room left in the constraint")
04834                              .arg(c->getDetailedDescription(*this))
04835                              .arg(c2->getDetailedDescription(*this)));
04836 
04837                             this->removeSpaceConstraint(ctr);
04838                             this->addSpaceConstraint(c2);
04839                      }
04840                      else
04841                             j++;
04842               }
04843 
04844               else
04845                      j++;
04846        }
04847 
04848        delete this->roomsList[i];
04849        this->roomsList.removeAt(i);
04850 
04851        if(recomputeSpace){
04852               LockUnlock::computeLockedUnlockedActivitiesOnlySpace();
04853               LockUnlock::increaseCommunicationSpinBox();
04854        }
04855 
04856        this->internalStructureComputed=false;
04857        setRulesModifiedAndOtherThings(this);
04858 
04859        teachers_schedule_ready=false;
04860        students_schedule_ready=false;
04861        rooms_schedule_ready=false;
04862 
04863        return true;
04864 }
04865 
04866 bool Rules::modifyRoom(const QString& initialRoomName, const QString& finalRoomName, const QString& building, int capacity)
04867 {
04868        int i=this->searchRoom(initialRoomName);
04869        if(i<0)
04870               return false;
04871 
04872        Room* searchedRoom=this->roomsList[i];
04873        assert(searchedRoom->name==initialRoomName);
04874 
04875        for(int j=0; j<this->spaceConstraintsList.size(); ){
04876               SpaceConstraint* ctr=this->spaceConstraintsList[j];
04877               if(ctr->type==CONSTRAINT_ROOM_NOT_AVAILABLE_TIMES){
04878                      ConstraintRoomNotAvailableTimes* crna=(ConstraintRoomNotAvailableTimes*)ctr;
04879                      if(crna->room==initialRoomName)
04880                             crna->room=finalRoomName;
04881                      j++;
04882               }
04883               else if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOM){
04884                      ConstraintActivityPreferredRoom* c=(ConstraintActivityPreferredRoom*)ctr;
04885                      if(c->roomName==initialRoomName)
04886                             c->roomName=finalRoomName;
04887                      j++;
04888               }
04889               else if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOMS){
04890                      ConstraintActivityPreferredRooms* c=(ConstraintActivityPreferredRooms*)ctr;
04891                      int t=0;
04892                      for(QStringList::Iterator it=c->roomsNames.begin(); it!=c->roomsNames.end(); it++){
04893                             if((*it)==initialRoomName){
04894                                    *it=finalRoomName;
04895                                    t++;
04896                             }
04897                      }
04898                      assert(t<=1);
04899                      j++;
04900               }
04901               else if(ctr->type==CONSTRAINT_STUDENTS_SET_HOME_ROOM){
04902                      ConstraintStudentsSetHomeRoom* c=(ConstraintStudentsSetHomeRoom*)ctr;
04903                      if(c->roomName==initialRoomName)
04904                             c->roomName=finalRoomName;
04905                      j++;
04906               }
04907               else if(ctr->type==CONSTRAINT_STUDENTS_SET_HOME_ROOMS){
04908                      ConstraintStudentsSetHomeRooms* c=(ConstraintStudentsSetHomeRooms*)ctr;
04909                      int t=0;
04910                      for(QStringList::Iterator it=c->roomsNames.begin(); it!=c->roomsNames.end(); it++){
04911                             if((*it)==initialRoomName){
04912                                    *it=finalRoomName;
04913                                    t++;
04914                             }
04915                      }
04916                      assert(t<=1);
04917                      j++;
04918               }
04919               else if(ctr->type==CONSTRAINT_TEACHER_HOME_ROOM){
04920                      ConstraintTeacherHomeRoom* c=(ConstraintTeacherHomeRoom*)ctr;
04921                      if(c->roomName==initialRoomName)
04922                             c->roomName=finalRoomName;
04923                      j++;
04924               }
04925               else if(ctr->type==CONSTRAINT_TEACHER_HOME_ROOMS){
04926                      ConstraintTeacherHomeRooms* c=(ConstraintTeacherHomeRooms*)ctr;
04927                      int t=0;
04928                      for(QStringList::Iterator it=c->roomsNames.begin(); it!=c->roomsNames.end(); it++){
04929                             if((*it)==initialRoomName){
04930                                    *it=finalRoomName;
04931                                    t++;
04932                             }
04933                      }
04934                      assert(t<=1);
04935                      j++;
04936               }
04937               else if(ctr->type==CONSTRAINT_SUBJECT_PREFERRED_ROOM){
04938                      ConstraintSubjectPreferredRoom* c=(ConstraintSubjectPreferredRoom*)ctr;
04939                      if(c->roomName==initialRoomName)
04940                             c->roomName=finalRoomName;
04941                      j++;
04942               }
04943               else if(ctr->type==CONSTRAINT_SUBJECT_PREFERRED_ROOMS){
04944                      ConstraintSubjectPreferredRooms* c=(ConstraintSubjectPreferredRooms*)ctr;
04945                      int t=0;
04946                      for(QStringList::Iterator it=c->roomsNames.begin(); it!=c->roomsNames.end(); it++){
04947                             if((*it)==initialRoomName){
04948                                    *it=finalRoomName;
04949                                    t++;
04950                             }
04951                      }
04952                      assert(t<=1);
04953                      j++;
04954               }
04955               else if(ctr->type==CONSTRAINT_SUBJECT_ACTIVITY_TAG_PREFERRED_ROOM){
04956                      ConstraintSubjectActivityTagPreferredRoom* c=(ConstraintSubjectActivityTagPreferredRoom*)ctr;
04957                      if(c->roomName==initialRoomName)
04958                             c->roomName=finalRoomName;
04959                      j++;
04960               }
04961               else if(ctr->type==CONSTRAINT_SUBJECT_ACTIVITY_TAG_PREFERRED_ROOMS){
04962                      ConstraintSubjectActivityTagPreferredRooms* c=(ConstraintSubjectActivityTagPreferredRooms*)ctr;
04963                      int t=0;
04964                      for(QStringList::Iterator it=c->roomsNames.begin(); it!=c->roomsNames.end(); it++){
04965                             if((*it)==initialRoomName){
04966                                    *it=finalRoomName;
04967                                    t++;
04968                             }
04969                      }
04970                      assert(t<=1);
04971                      j++;
04972               }
04973 
04974               else if(ctr->type==CONSTRAINT_ACTIVITY_TAG_PREFERRED_ROOM){
04975                      ConstraintActivityTagPreferredRoom* c=(ConstraintActivityTagPreferredRoom*)ctr;
04976                      if(c->roomName==initialRoomName)
04977                             c->roomName=finalRoomName;
04978                      j++;
04979               }
04980               else if(ctr->type==CONSTRAINT_ACTIVITY_TAG_PREFERRED_ROOMS){
04981                      ConstraintActivityTagPreferredRooms* c=(ConstraintActivityTagPreferredRooms*)ctr;
04982                      int t=0;
04983                      for(QStringList::Iterator it=c->roomsNames.begin(); it!=c->roomsNames.end(); it++){
04984                             if((*it)==initialRoomName){
04985                                    *it=finalRoomName;
04986                                    t++;
04987                             }
04988                      }
04989                      assert(t<=1);
04990                      j++;
04991               }
04992 
04993               else
04994                      j++;
04995        }
04996 
04997        searchedRoom->name=finalRoomName;
04998        searchedRoom->building=building;
04999        searchedRoom->capacity=capacity;
05000 
05001        this->internalStructureComputed=false;
05002        setRulesModifiedAndOtherThings(this);
05003        return true;
05004 }
05005 
05006 void Rules::sortRoomsAlphabetically()
05007 {
05008        qSort(this->roomsList.begin(), this->roomsList.end(), roomsAscending);
05009 
05010        this->internalStructureComputed=false;
05011        setRulesModifiedAndOtherThings(this);
05012 }
05013 
05014 bool Rules::addBuilding(Building* bu)
05015 {
05016        if(this->searchBuilding(bu->name) >= 0)
05017               return false;
05018        this->buildingsList << bu; //append
05019        this->internalStructureComputed=false;
05020        setRulesModifiedAndOtherThings(this);
05021 
05022        teachers_schedule_ready=false;
05023        students_schedule_ready=false;
05024        rooms_schedule_ready=false;
05025 
05026        return true;
05027 }
05028 
05029 bool Rules::addBuildingFast(Building* bu)
05030 {
05031        this->buildingsList << bu; //append
05032        this->internalStructureComputed=false;
05033        setRulesModifiedAndOtherThings(this);
05034 
05035        teachers_schedule_ready=false;
05036        students_schedule_ready=false;
05037        rooms_schedule_ready=false;
05038 
05039        return true;
05040 }
05041 
05042 int Rules::searchBuilding(const QString& buildingName)
05043 {
05044        for(int i=0; i<this->buildingsList.size(); i++)
05045               if(this->buildingsList[i]->name==buildingName)
05046                      return i;
05047        
05048        return -1;
05049 }
05050 
05051 bool Rules::removeBuilding(const QString& buildingName)
05052 {
05053        foreach(Room* rm, this->roomsList)
05054               if(rm->building==buildingName)
05055                      rm->building="";
05056 
05057        int i=this->searchBuilding(buildingName);
05058        if(i<0)
05059               return false;
05060 
05061        Building* searchedBuilding=this->buildingsList[i];
05062        assert(searchedBuilding->name==buildingName);
05063 
05064        delete this->buildingsList[i];
05065        this->buildingsList.removeAt(i);
05066        
05067        this->internalStructureComputed=false;
05068        setRulesModifiedAndOtherThings(this);
05069 
05070        teachers_schedule_ready=false;
05071        students_schedule_ready=false;
05072        rooms_schedule_ready=false;
05073 
05074        return true;
05075 }
05076 
05077 bool Rules::modifyBuilding(const QString& initialBuildingName, const QString& finalBuildingName)
05078 {
05079        foreach(Room* rm, roomsList)
05080               if(rm->building==initialBuildingName)
05081                      rm->building=finalBuildingName;
05082 
05083        int i=this->searchBuilding(initialBuildingName);
05084        if(i<0)
05085               return false;
05086 
05087        Building* searchedBuilding=this->buildingsList[i];
05088        assert(searchedBuilding->name==initialBuildingName);
05089        searchedBuilding->name=finalBuildingName;
05090 
05091        this->internalStructureComputed=false;
05092        setRulesModifiedAndOtherThings(this);
05093        return true;
05094 }
05095 
05096 void Rules::sortBuildingsAlphabetically()
05097 {
05098        qSort(this->buildingsList.begin(), this->buildingsList.end(), buildingsAscending);
05099 
05100        this->internalStructureComputed=false;
05101        setRulesModifiedAndOtherThings(this);
05102 }
05103 
05104 bool Rules::addTimeConstraint(TimeConstraint *ctr)
05105 {
05106        bool ok=true;
05107 
05108        //TODO: improve this
05109 
05110        //check if this constraint is already added, for ConstraintActivityPreferredStartingTime
05111        if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_STARTING_TIME){
05112               int i;
05113               for(i=0; i<this->timeConstraintsList.size(); i++){
05114                      TimeConstraint* ctr2=this->timeConstraintsList[i];
05115                      if(ctr2->type==CONSTRAINT_ACTIVITY_PREFERRED_STARTING_TIME) 
05116                             if(
05117                              *((ConstraintActivityPreferredStartingTime*)ctr2)
05118                              ==
05119                              *((ConstraintActivityPreferredStartingTime*)ctr)
05120                             )
05121                                    break;
05122               }
05123                             
05124               if(i<this->timeConstraintsList.size())
05125                      ok=false;
05126        }
05127 
05128        //check if this constraint is already added, for ConstraintMinDaysBetweenActivities
05129        else if(ctr->type==CONSTRAINT_MIN_DAYS_BETWEEN_ACTIVITIES){
05130               int i;
05131               for(i=0; i<this->timeConstraintsList.size(); i++){
05132                      TimeConstraint* ctr2=this->timeConstraintsList[i];
05133                      if(ctr2->type==CONSTRAINT_MIN_DAYS_BETWEEN_ACTIVITIES)
05134                             if(
05135                              *((ConstraintMinDaysBetweenActivities*)ctr2)
05136                              ==
05137                              *((ConstraintMinDaysBetweenActivities*)ctr)
05138                              )
05139                                    break;
05140               }
05141 
05142               if(i<this->timeConstraintsList.size())
05143                      ok=false;
05144        }
05145        
05146        else if(ctr->type==CONSTRAINT_STUDENTS_SET_NOT_AVAILABLE_TIMES){
05147               int i;
05148               ConstraintStudentsSetNotAvailableTimes* ssna=(ConstraintStudentsSetNotAvailableTimes*)ctr;
05149               for(i=0; i<this->timeConstraintsList.size(); i++){
05150                      TimeConstraint* ctr2=this->timeConstraintsList[i];
05151                      if(ctr2->type==CONSTRAINT_STUDENTS_SET_NOT_AVAILABLE_TIMES) {
05152                             ConstraintStudentsSetNotAvailableTimes* ssna2=(ConstraintStudentsSetNotAvailableTimes*)ctr2;
05153                             if(ssna->students==ssna2->students)
05154                                    break;
05155                      }
05156               }
05157                             
05158               if(i<this->timeConstraintsList.size())
05159                      ok=false;
05160        }
05161        
05162        else if(ctr->type==CONSTRAINT_TEACHER_NOT_AVAILABLE_TIMES){
05163               int i;
05164               ConstraintTeacherNotAvailableTimes* tna=(ConstraintTeacherNotAvailableTimes*)ctr;
05165               for(i=0; i<this->timeConstraintsList.size(); i++){
05166                      TimeConstraint* ctr2=this->timeConstraintsList[i];
05167                      if(ctr2->type==CONSTRAINT_TEACHER_NOT_AVAILABLE_TIMES) {
05168                             ConstraintTeacherNotAvailableTimes* tna2=(ConstraintTeacherNotAvailableTimes*)ctr2;
05169                             if(tna->teacher==tna2->teacher)
05170                                    break;
05171                      }
05172               }
05173                             
05174               if(i<this->timeConstraintsList.size())
05175                      ok=false;
05176        }
05177        
05178        else if(ctr->type==CONSTRAINT_BREAK_TIMES){
05179               int i;
05180               for(i=0; i<this->timeConstraintsList.size(); i++){
05181                      TimeConstraint* ctr2=this->timeConstraintsList[i];
05182                      if(ctr2->type==CONSTRAINT_BREAK_TIMES)
05183                             break;
05184               }
05185                             
05186               if(i<this->timeConstraintsList.size())
05187                      ok=false;
05188        }
05189        
05190        else if(ctr->type==CONSTRAINT_BASIC_COMPULSORY_TIME){
05191               int i;
05192               for(i=0; i<this->timeConstraintsList.size(); i++){
05193                      TimeConstraint* ctr2=this->timeConstraintsList[i];
05194                      if(ctr2->type==CONSTRAINT_BASIC_COMPULSORY_TIME)
05195                             break;
05196               }
05197                             
05198               if(i<this->timeConstraintsList.size())
05199                      ok=false;
05200        }
05201        
05202        if(ok){
05203               this->timeConstraintsList << ctr; //append
05204               this->internalStructureComputed=false;
05205               setRulesModifiedAndOtherThings(this);
05206               return true;
05207        }
05208        else
05209               return false;
05210 }
05211 
05212 bool Rules::removeTimeConstraint(TimeConstraint *ctr)
05213 {
05214        for(int i=0; i<this->timeConstraintsList.size(); i++)
05215               if(this->timeConstraintsList[i]==ctr){
05216                      delete ctr;
05217                      this->timeConstraintsList.removeAt(i);
05218                      this->internalStructureComputed=false;
05219                      setRulesModifiedAndOtherThings(this);
05220 
05221                      return true;
05222               }
05223 
05224        return false;
05225 }
05226 
05227 bool Rules::addSpaceConstraint(SpaceConstraint *ctr)
05228 {
05229        bool ok=true;
05230 
05231        //TODO: check if this constraint is already added...(if any possibility of duplicates)
05232        if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOM){
05233               int i;
05234               for(i=0; i<this->spaceConstraintsList.size(); i++){
05235                      SpaceConstraint* ctr2=this->spaceConstraintsList[i];
05236                      if(ctr2->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOM)
05237                             if(
05238                              *((ConstraintActivityPreferredRoom*)ctr2)
05239                              ==
05240                              *((ConstraintActivityPreferredRoom*)ctr)
05241                             )
05242                                    break;
05243               }
05244               
05245               if(i<this->spaceConstraintsList.size())
05246                      ok=false;
05247        }
05248 /*     else if(ctr->type==CONSTRAINT_ROOM_NOT_AVAILABLE_TIMES){
05249               int i;
05250               ConstraintRoomNotAvailableTimes* c=(ConstraintRoomNotAvailableTimes*)ctr;
05251               for(i=0; i<this->spaceConstraintsList.size(); i++){
05252                      SpaceConstraint* ctr2=this->spaceConstraintsList[i];
05253                      if(ctr2->type==CONSTRAINT_ROOM_NOT_AVAILABLE_TIMES){
05254                             ConstraintRoomNotAvailableTimes* c2=(ConstraintRoomNotAvailableTimes*)ctr2;                       
05255                             if(c->room==c2->room)
05256                                    break;
05257                      }
05258               }
05259               
05260               if(i<this->spaceConstraintsList.size())
05261                      ok=false;
05262        }*/
05263        else if(ctr->type==CONSTRAINT_BASIC_COMPULSORY_SPACE){
05264               int i;
05265               for(i=0; i<this->spaceConstraintsList.size(); i++){
05266                      SpaceConstraint* ctr2=this->spaceConstraintsList[i];
05267                      if(ctr2->type==CONSTRAINT_BASIC_COMPULSORY_SPACE)
05268                             break;
05269               }
05270                             
05271               if(i<this->spaceConstraintsList.size())
05272                      ok=false;
05273        }
05274 
05275        if(ok){
05276               this->spaceConstraintsList << ctr; //append
05277               this->internalStructureComputed=false;
05278               setRulesModifiedAndOtherThings(this);
05279               return true;
05280        }
05281        else
05282               return false;
05283 }
05284 
05285 bool Rules::removeSpaceConstraint(SpaceConstraint *ctr)
05286 {
05287        for(int i=0; i<this->spaceConstraintsList.size(); i++)
05288               if(this->spaceConstraintsList[i]==ctr){
05289                      delete ctr;
05290                      this->spaceConstraintsList.removeAt(i);
05291                      this->internalStructureComputed=false;
05292                      setRulesModifiedAndOtherThings(this);
05293 
05294                      return true;
05295               }
05296 
05297        return false;
05298 }
05299 
05300 bool Rules::read(QWidget* parent, const QString& filename, bool commandLine, QString commandLineDirectory) //commandLineDirectory has trailing FILE_SEP
05301 {
05302        //bool reportWhole=true;
05303 
05304        QFile file(filename);
05305        if(!file.open(QIODevice::ReadOnly)){
05306               //cout<<"Could not open file - not existing or in use\n";
05307               QMessageBox::warning(parent, tr("FET warning"), tr("Could not open file - not existing or in use"));
05308               return false;
05309        }
05310        //QDomDocument doc("xml_rules");
05311        QDomDocument doc;
05312        
05313        QString errorStr;
05314        int errorLine;
05315        int errorColumn;
05316        
05317        if(!doc.setContent(&file, true, &errorStr, &errorLine, &errorColumn)){
05318               QMessageBox::warning(parent, tr("FET warning"),
05319                tr("Could not read file - XML parse error at line %1, column %2:\n%3", "The error description is %3")
05320                .arg(errorLine)
05321                .arg(errorColumn)
05322                .arg(errorStr));
05323        
05324               file.close();
05325               return false;
05326        }
05327        file.close();
05328 
05330 
05331        if(!commandLine){
05332               //logging part
05333               QDir dir;
05334               bool t=true;
05335               if(!dir.exists(OUTPUT_DIR+FILE_SEP+"logs"))
05336                      t=dir.mkpath(OUTPUT_DIR+FILE_SEP+"logs");
05337               if(!t){
05338                      QMessageBox::warning(parent, tr("FET warning"), tr("Cannot create or use directory %1 - cannot continue").arg(QDir::toNativeSeparators(OUTPUT_DIR+FILE_SEP+"logs")));
05339                      return false;
05340               }
05341               assert(t);
05342        }
05343        else{
05344               QDir dir;
05345               bool t=true;
05346               if(!dir.exists(commandLineDirectory+"logs"))
05347                      t=dir.mkpath(commandLineDirectory+"logs");
05348               if(!t){
05349                      QMessageBox::warning(parent, tr("FET warning"), tr("Cannot create or use directory %1 - cannot continue").arg(QDir::toNativeSeparators(commandLineDirectory+"logs")));
05350                      return false;
05351               }
05352               assert(t);
05353        }
05354        
05355        FakeString xmlReadingLog;
05356        xmlReadingLog="";
05357 
05358        QDate dat=QDate::currentDate();
05359        QTime tim=QTime::currentTime();
05360        QLocale loc(FET_LANGUAGE);
05361        QString sTime=loc.toString(dat, QLocale::ShortFormat)+" "+loc.toString(tim, QLocale::ShortFormat);
05362 
05363        QString reducedXmlLog="";
05364        reducedXmlLog+="Log generated by FET "+FET_VERSION+" on "+sTime+"\n\n";
05365        QString shortFilename=filename.right(filename.length()-filename.lastIndexOf(FILE_SEP)-1);
05366        reducedXmlLog+="Reading file "+shortFilename+"\n";
05367        QFileInfo fileinfo(filename);
05368        reducedXmlLog+="Complete file name, including path: "+QDir::toNativeSeparators(fileinfo.absoluteFilePath())+"\n";
05369        reducedXmlLog+="\n";
05370 
05371        QString tmp;
05372        if(commandLine)
05373               tmp=commandLineDirectory+"logs"+FILE_SEP+XML_PARSING_LOG_FILENAME;
05374        else
05375               tmp=OUTPUT_DIR+FILE_SEP+"logs"+FILE_SEP+XML_PARSING_LOG_FILENAME;
05376        QFile file2(tmp);
05377        bool canWriteLogFile=true;
05378        if(!file2.open(QIODevice::WriteOnly)){
05379               QString s=tr("FET cannot open the log file %1 for writing. This might mean that you don't"
05380                      " have write permissions in this location. You can continue operation, but you might not be able to save the generated timetables"
05381                      " as html files").arg(QDir::toNativeSeparators(tmp))+
05382                      "\n\n"+tr("A solution is to remove that file (if it exists already) or set its permissions to allow writing")+
05383                      "\n\n"+tr("Please report possible bug");
05384               QMessageBox::critical(parent, tr("FET critical"), s);
05385               canWriteLogFile=false;
05386        }
05387        QTextStream logStream;
05388        if(canWriteLogFile){
05389               logStream.setDevice(&file2);
05390               logStream.setCodec("UTF-8");
05391               logStream.setGenerateByteOrderMark(true);
05392        }
05393        
05394        QDomElement elem1=doc.documentElement();
05395        xmlReadingLog+=" Found "+elem1.tagName()+" tag\n";
05396        bool okAbove3_12_17=true;
05397        bool version5AndAbove=false;
05398        bool warning=false;
05399        
05400        QString file_version;
05401        
05402        bool okfetTag;
05403        if(elem1.tagName()=="fet" || elem1.tagName()=="FET") //the new tag is fet, the old tag - FET
05404               okfetTag=true;
05405        else
05406               okfetTag=false;
05407        
05408        if(!okfetTag)
05409               okAbove3_12_17=false;
05410        else{
05411               assert(okAbove3_12_17==true);
05412               /*QDomDocumentType dt=doc.doctype();
05413               if(dt.isNull() || dt.name()!="FET")
05414                      okAbove3_12_17=false;
05415               else*/
05416               int filev[3], fetv[3];
05417               
05418               QDomAttr a=elem1.attributeNode("version");
05419               
05420               QString version=a.value();
05421               file_version=version;
05422 
05423               QRegExp fileVerReCap("^(\\d+)\\.(\\d+)\\.(\\d+)(.*)$");
05424 
05425               int tfile=fileVerReCap.indexIn(file_version);
05426               filev[0]=filev[1]=filev[2]=-1;
05427               if(tfile!=0){
05428                      QMessageBox::warning(parent, tr("FET warning"), tr("File contains a version numbering scheme which"
05429                      " 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 adviced"
05430                      " 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"+
05431                      tr("If you are opening a file older than FET format version 5, it will be converted to latest FET data format"));
05432                      cout<<"Opened file version not matched by regexp"<<endl;
05433               }
05434               else{
05435                      bool ok;
05436                      filev[0]=fileVerReCap.cap(1).toInt(&ok);
05437                      assert(ok);
05438                      filev[1]=fileVerReCap.cap(2).toInt(&ok);
05439                      assert(ok);
05440                      filev[2]=fileVerReCap.cap(3).toInt(&ok);
05441                      assert(ok);
05442                      cout<<"Opened file version matched by regexp: major="<<filev[0]<<", minor="<<filev[1]<<", revision="<<filev[2];
05443                      cout<<", additional text="<<qPrintable(fileVerReCap.cap(4))<<"."<<endl;
05444               }
05445               
05446               QRegExp fetVerReCap("^(\\d+)\\.(\\d+)\\.(\\d+)(.*)$");
05447 
05448               int tfet=fetVerReCap.indexIn(FET_VERSION);
05449               fetv[0]=fetv[1]=fetv[2]=-1;
05450               if(tfet!=0){
05451                      QMessageBox::warning(parent, tr("FET warning"), tr("FET version does not respect the format v.v.va"
05452                      " (3 numbers separated by points, followed by any string a, which may be empty). This is probably a bug in FET - please report it"));
05453                      cout<<"FET version not matched by regexp"<<endl;
05454               }
05455               else{
05456                      bool ok;
05457                      fetv[0]=fetVerReCap.cap(1).toInt(&ok);
05458                      assert(ok);
05459                      fetv[1]=fetVerReCap.cap(2).toInt(&ok);
05460                      assert(ok);
05461                      fetv[2]=fetVerReCap.cap(3).toInt(&ok);
05462                      assert(ok);
05463                      cout<<"FET version matched by regexp: major="<<fetv[0]<<", minor="<<fetv[1]<<", revision="<<fetv[2];
05464                      cout<<", additional text="<<qPrintable(fetVerReCap.cap(4))<<"."<<endl;
05465               }
05466               
05467               if(filev[0]>=0 && fetv[0]>=0 && filev[1]>=0 && fetv[1]>=0 && filev[2]>=0 && fetv[2]>=0){
05468                      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])){
05469                             warning=true;
05470                      }
05471               }
05472               
05473               if(filev[0]>=5 || (filev[0]==-1 && filev[1]==-1 && filev[2]==-1))
05474               //if major is >= 5 or major cannot be read
05475                      version5AndAbove=true;
05476        }
05477        if(!okAbove3_12_17){
05478               cout<<"Invalid fet 3.12.17 or above"<<endl;
05479               file2.close();
05480               QMessageBox::warning(parent, tr("FET warning"), tr("File does not have a corresponding beginning tag - it should be %1 or %2. File is incorrect..."
05481                      "it cannot be opened").arg("fet").arg("FET"));
05482               return false;
05483        }
05484        
05485        if(!version5AndAbove){
05486               QMessageBox::warning(parent, tr("FET information"), 
05487                tr("Opening older file - it will be converted to latest format, automatically "
05488                "assigning weight percentages to constraints and dropping parity for activities. "
05489                "You are adviced to make a backup of your old file before saving in new format.\n\n"
05490                "Please note that the default weight percentage of constraints min days between activities "
05491                "will be 95% (mainly satisfied, not always) and 'force consecutive if same day' will be set to true "
05492                "(meaning that if the activities are in the same day, they will be placed continuously, in a bigger duration activity)"
05493                "If you want, you can modify this percent to be 100%, manually in the fet input file "
05494                "or from the interface"));
05495        }
05496        
05497        if(warning){
05498               QMessageBox::warning(parent, tr("FET information"), 
05499                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")
05500                +"\n\n"+tr("Your FET version: %1, file version: %2").arg(FET_VERSION).arg(file_version));
05501        }
05502        
05503        //Clear old rules, initialize new rules
05504        if(this->initialized)
05505               this->kill();
05506        this->init();
05507        
05508        this->nHoursPerDay=12;
05509        this->hoursOfTheDay[0]="08:00";
05510        this->hoursOfTheDay[1]="09:00";
05511        this->hoursOfTheDay[2]="10:00";
05512        this->hoursOfTheDay[3]="11:00";
05513        this->hoursOfTheDay[4]="12:00";
05514        this->hoursOfTheDay[5]="13:00";
05515        this->hoursOfTheDay[6]="14:00";
05516        this->hoursOfTheDay[7]="15:00";
05517        this->hoursOfTheDay[8]="16:00";
05518        this->hoursOfTheDay[9]="17:00";
05519        this->hoursOfTheDay[10]="18:00";
05520        this->hoursOfTheDay[11]="19:00";
05521        //this->hoursOfTheDay[12]="20:00";
05522 
05523        this->nDaysPerWeek=5;
05524        this->daysOfTheWeek[0] = tr("Monday");
05525        this->daysOfTheWeek[1] = tr("Tuesday");
05526        this->daysOfTheWeek[2] = tr("Wednesday");
05527        this->daysOfTheWeek[3] = tr("Thursday");
05528        this->daysOfTheWeek[4] = tr("Friday");
05529 
05530        this->institutionName=tr("Default institution");
05531        this->comments=tr("Default comments");
05532 
05533        bool skipDeprecatedConstraints=false;
05534        
05535        bool skipDuplicatedStudentsSets=false;
05536        
05537        for(QDomNode node2=elem1.firstChild(); !node2.isNull(); node2=node2.nextSibling()){
05538               QDomElement elem2=node2.toElement();
05539               if(elem2.isNull())
05540                      xmlReadingLog+="  Null node here\n";
05541               xmlReadingLog+="  Found "+elem2.tagName()+" tag\n";
05542               if(elem2.tagName()=="Institution_Name"){
05543                      this->institutionName=elem2.text();
05544                      xmlReadingLog+="  Found institution name="+this->institutionName+"\n";
05545                      reducedXmlLog+="Read institution name="+this->institutionName+"\n";
05546               }
05547               else if(elem2.tagName()=="Comments"){
05548                      this->comments=elem2.text();
05549                      xmlReadingLog+="  Found comments="+this->comments+"\n";
05550                      reducedXmlLog+="Read comments="+this->comments+"\n";
05551               }
05552               else if(elem2.tagName()=="Hours_List"){
05553                      int tmp=0;
05554                      for(QDomNode node3=elem2.firstChild(); !node3.isNull(); node3=node3.nextSibling()){
05555                             QDomElement elem3=node3.toElement();
05556                             if(elem3.isNull()){
05557                                    xmlReadingLog+="   Null node here\n";
05558                                    continue;
05559                             }
05560                             xmlReadingLog+="   Found "+elem3.tagName()+" tag\n";
05561                             if(elem3.tagName()=="Number"){
05562                                    this->nHoursPerDay=elem3.text().toInt();
05563                                    xmlReadingLog+="   Found the number of hours per day = "+
05564                                     CustomFETString::number(this->nHoursPerDay)+"\n";
05565                                    reducedXmlLog+="Added "+
05566                                     CustomFETString::number(this->nHoursPerDay)+" hours per day\n";
05567                                    assert(this->nHoursPerDay>0);
05568                             }
05569                             else if(elem3.tagName()=="Name"){
05570                                    this->hoursOfTheDay[tmp]=elem3.text();
05571                                    xmlReadingLog+="   Found hour "+this->hoursOfTheDay[tmp]+"\n";
05572                                    tmp++;
05573                             }
05574                      }
05575                      //don't do assert tmp == nHoursPerDay, because some older files contain also the end of day hour, so tmp==nHoursPerDay+1 in this case
05576               }
05577               else if(elem2.tagName()=="Days_List"){
05578                      int tmp=0;
05579                      for(QDomNode node3=elem2.firstChild(); !node3.isNull(); node3=node3.nextSibling()){
05580                             QDomElement elem3=node3.toElement();
05581                             if(elem3.isNull()){
05582                                    xmlReadingLog+="   Null node here\n";
05583                                    continue;
05584                             }
05585                             xmlReadingLog+="   Found "+elem3.tagName()+" tag\n";
05586                             if(elem3.tagName()=="Number"){
05587                                    this->nDaysPerWeek=elem3.text().toInt();
05588                                    xmlReadingLog+="   Found the number of days per week = "+
05589                                     CustomFETString::number(this->nDaysPerWeek)+"\n";
05590                                    reducedXmlLog+="Added "+
05591                                     CustomFETString::number(this->nDaysPerWeek)+" days per week\n";
05592                                    assert(this->nDaysPerWeek>0);
05593                             }
05594                             else if(elem3.tagName()=="Name"){
05595                                    this->daysOfTheWeek[tmp]=elem3.text();
05596                                    xmlReadingLog+="   Found day "+this->daysOfTheWeek[tmp]+"\n";
05597                                    tmp++;
05598                             }
05599                      }
05600                      assert(tmp==this->nDaysPerWeek);
05601               }
05602               else if(elem2.tagName()=="Teachers_List"){
05603                      QSet<QString> teachersRead;
05604               
05605                      int tmp=0;
05606                      for(QDomNode node3=elem2.firstChild(); !node3.isNull(); node3=node3.nextSibling()){
05607                             QDomElement elem3=node3.toElement();
05608                             if(elem3.isNull()){
05609                                    xmlReadingLog+="   Null node here\n";
05610                                    continue;
05611                             }
05612                             xmlReadingLog+="   Found "+elem3.tagName()+" tag\n";
05613                             if(elem3.tagName()=="Teacher"){
05614                                    Teacher* teacher=new Teacher();
05615                                    for(QDomNode node4=elem3.firstChild(); !node4.isNull(); node4=node4.nextSibling()){
05616                                           QDomElement elem4=node4.toElement();
05617                                           if(elem4.isNull()){
05618                                                  xmlReadingLog+="    Null node here\n";
05619                                                  continue;
05620                                           }
05621                                           xmlReadingLog+="    Found "+elem4.tagName()+" tag\n";
05622                                           if(elem4.tagName()=="Name"){
05623                                                  teacher->name=elem4.text();
05624                                                  xmlReadingLog+="    Read teacher name: "+teacher->name+"\n";
05625                                           }
05626                                    }
05627                                    bool tmp2=teachersRead.contains(teacher->name);
05628                                    if(tmp2){
05629                                           QMessageBox::warning(parent, tr("FET warning"),
05630                                            tr("Duplicate teacher %1 found - ignoring").arg(teacher->name));
05631                                           xmlReadingLog+="   Teacher not added - duplicate\n";
05632                                    }
05633                                    else{
05634                                           teachersRead.insert(teacher->name);
05635                                           this->addTeacherFast(teacher);
05636                                           tmp++;
05637                                           xmlReadingLog+="   Teacher added\n";
05638                                    }
05639                             }
05640                      }
05641                      assert(tmp==this->teachersList.size());
05642                      xmlReadingLog+="  Added "+CustomFETString::number(tmp)+" teachers\n";
05643                      reducedXmlLog+="Added "+CustomFETString::number(tmp)+" teachers\n";
05644               }
05645               else if(elem2.tagName()=="Subjects_List"){
05646                      QSet<QString> subjectsRead;
05647               
05648                      int tmp=0;
05649                      for(QDomNode node3=elem2.firstChild(); !node3.isNull(); node3=node3.nextSibling()){
05650                             QDomElement elem3=node3.toElement();
05651                             if(elem3.isNull()){
05652                                    xmlReadingLog+="   Null node here\n";
05653                                    continue;
05654                             }
05655                             xmlReadingLog+="   Found "+elem3.tagName()+" tag\n";
05656                             if(elem3.tagName()=="Subject"){
05657                                    Subject* subject=new Subject();
05658                                    for(QDomNode node4=elem3.firstChild(); !node4.isNull(); node4=node4.nextSibling()){
05659                                           QDomElement elem4=node4.toElement();
05660                                           if(elem4.isNull()){
05661                                                  xmlReadingLog+="    Null node here\n";
05662                                                  continue;
05663                                           }
05664                                           xmlReadingLog+="    Found "+elem4.tagName()+" tag\n";
05665                                           if(elem4.tagName()=="Name"){
05666                                                  subject->name=elem4.text();
05667                                                  xmlReadingLog+="    Read subject name: "+subject->name+"\n";
05668                                           }
05669                                    }
05670                                    bool tmp2=subjectsRead.contains(subject->name);
05671                                    if(tmp2){
05672                                           QMessageBox::warning(parent, tr("FET warning"),
05673                                            tr("Duplicate subject %1 found - ignoring").arg(subject->name));
05674                                           xmlReadingLog+="   Subject not added - duplicate\n";
05675                                    }
05676                                    else{
05677                                           subjectsRead.insert(subject->name);
05678                                           this->addSubjectFast(subject);
05679                                           tmp++;
05680                                           xmlReadingLog+="   Subject inserted\n";
05681                                    }
05682                             }
05683                      }
05684                      assert(tmp==this->subjectsList.size());
05685                      xmlReadingLog+="  Added "+CustomFETString::number(tmp)+" subjects\n";
05686                      reducedXmlLog+="Added "+CustomFETString::number(tmp)+" subjects\n";
05687               }
05688               else if(elem2.tagName()=="Subject_Tags_List"){
05689                      QSet<QString> activityTagsRead;
05690               
05691                      QMessageBox::information(parent, tr("FET information"), tr("Your file contains subject tags list"
05692                        ", which is named in versions>=5.5.0 activity tags list"));
05693               
05694                      int tmp=0;
05695                      for(QDomNode node3=elem2.firstChild(); !node3.isNull(); node3=node3.nextSibling()){
05696                             QDomElement elem3=node3.toElement();
05697                             if(elem3.isNull()){
05698                                    xmlReadingLog+="   Null node here\n";
05699                                    continue;
05700                             }
05701                             xmlReadingLog+="   Found "+elem3.tagName()+" tag\n";
05702                             if(elem3.tagName()=="Subject_Tag"){
05703                                    ActivityTag* activityTag=new ActivityTag();
05704                                    for(QDomNode node4=elem3.firstChild(); !node4.isNull(); node4=node4.nextSibling()){
05705                                           QDomElement elem4=node4.toElement();
05706                                           if(elem4.isNull()){
05707                                                  xmlReadingLog+="    Null node here\n";
05708                                                  continue;
05709                                           }
05710                                           xmlReadingLog+="    Found "+elem4.tagName()+" tag\n";
05711                                           if(elem4.tagName()=="Name"){
05712                                                  activityTag->name=elem4.text();
05713                                                  xmlReadingLog+="    Read activity tag name: "+activityTag->name+"\n";
05714                                           }
05715                                    }
05716                                    bool tmp2=activityTagsRead.contains(activityTag->name);
05717                                    if(tmp2){
05718                                           QMessageBox::warning(parent, tr("FET warning"),
05719                                            tr("Duplicate activity tag %1 found - ignoring").arg(activityTag->name));
05720                                           xmlReadingLog+="   Activity tag not added - duplicate\n";
05721                                    }
05722                                    else{
05723                                           activityTagsRead.insert(activityTag->name);
05724                                           addActivityTagFast(activityTag);
05725                                           tmp++;
05726                                           xmlReadingLog+="   Activity tag inserted\n";
05727                                    }
05728                             }
05729                      }
05730                      assert(tmp==this->activityTagsList.size());
05731                      xmlReadingLog+="  Added "+CustomFETString::number(tmp)+" activity tags\n";
05732                      reducedXmlLog+="Added "+CustomFETString::number(tmp)+" activity tags\n";
05733               }
05734               else if(elem2.tagName()=="Activity_Tags_List"){
05735                      QSet<QString> activityTagsRead;
05736               
05737                      int tmp=0;
05738                      for(QDomNode node3=elem2.firstChild(); !node3.isNull(); node3=node3.nextSibling()){
05739                             QDomElement elem3=node3.toElement();
05740                             if(elem3.isNull()){
05741                                    xmlReadingLog+="   Null node here\n";
05742                                    continue;
05743                             }
05744                             xmlReadingLog+="   Found "+elem3.tagName()+" tag\n";
05745                             if(elem3.tagName()=="Activity_Tag"){
05746                                    ActivityTag* activityTag=new ActivityTag();
05747                                    for(QDomNode node4=elem3.firstChild(); !node4.isNull(); node4=node4.nextSibling()){
05748                                           QDomElement elem4=node4.toElement();
05749                                           if(elem4.isNull()){
05750                                                  xmlReadingLog+="    Null node here\n";
05751                                                  continue;
05752                                           }
05753                                           xmlReadingLog+="    Found "+elem4.tagName()+" tag\n";
05754                                           if(elem4.tagName()=="Name"){
05755                                                  activityTag->name=elem4.text();
05756                                                  xmlReadingLog+="    Read activity tag name: "+activityTag->name+"\n";
05757                                           }
05758                                    }
05759                                    bool tmp2=activityTagsRead.contains(activityTag->name);
05760                                    if(tmp2){
05761                                           QMessageBox::warning(parent, tr("FET warning"),
05762                                            tr("Duplicate activity tag %1 found - ignoring").arg(activityTag->name));
05763                                           xmlReadingLog+="   Activity tag not added - duplicate\n";
05764                                    }
05765                                    else{
05766                                           activityTagsRead.insert(activityTag->name);
05767                                           addActivityTagFast(activityTag);
05768                                           tmp++;
05769                                           xmlReadingLog+="   Activity tag inserted\n";
05770                                    }
05771                             }
05772                      }
05773                      assert(tmp==this->activityTagsList.size());
05774                      xmlReadingLog+="  Added "+CustomFETString::number(tmp)+" activity tags\n";
05775                      reducedXmlLog+="Added "+CustomFETString::number(tmp)+" activity tags\n";
05776               }
05777               else if(elem2.tagName()=="Students_List"){
05778                      QHash<QString, StudentsSet*> studentsHash;
05779               
05780                      int tsgr=0;
05781                      int tgr=0;
05782               
05783                      int ny=0;
05784                      for(QDomNode node3=elem2.firstChild(); !node3.isNull(); node3=node3.nextSibling()){
05785                             QDomElement elem3=node3.toElement();
05786                             if(elem3.isNull()){
05787                                    xmlReadingLog+="   Null node here\n";
05788                                    continue;
05789                             }
05790                             xmlReadingLog+="   Found "+elem3.tagName()+" tag\n";
05791                             if(elem3.tagName()=="Year"){
05792                                    StudentsYear* sty=new StudentsYear();
05793                                    int ng=0;
05794                                    
05795                                    QSet<QString> groupsInYear;
05796 
05797                                    bool tmp2=this->addYearFast(sty);
05798                                    assert(tmp2==true);
05799                                    ny++;
05800 
05801                                    for(QDomNode node4=elem3.firstChild(); !node4.isNull(); node4=node4.nextSibling()){
05802                                           QDomElement elem4=node4.toElement();
05803                                           if(elem4.isNull()){
05804                                                  xmlReadingLog+="    Null node here\n";
05805                                                  continue;
05806                                           }
05807                                           xmlReadingLog+="    Found "+elem4.tagName()+" tag\n";
05808                                           if(elem4.tagName()=="Name"){
05809                                                  if(!skipDuplicatedStudentsSets){
05810                                                         QString nn=elem4.text();
05811                                                         //StudentsSet* ss=this->searchStudentsSet(nn);
05812                                                         StudentsSet* ss=studentsHash.value(nn, NULL);
05813                                                         if(ss!=NULL){
05814                                                                QString str;
05815                                                                
05816                                                                if(ss->type==STUDENTS_YEAR)
05817                                                                       str=tr("Trying to add year %1, which is already added as another year - your file will be loaded but probably contains errors, please correct them after loading").arg(nn);
05818                                                                else if(ss->type==STUDENTS_GROUP)
05819                                                                       str=tr("Trying to add year %1, which is already added as another group - your file will be loaded but probably contains errors, please correct them after loading").arg(nn);
05820                                                                else if(ss->type==STUDENTS_SUBGROUP)
05821                                                                       str=tr("Trying to add year %1, which is already added as another subgroup - your file will be loaded but probably contains errors, please correct them after loading").arg(nn);
05822                                                         
05823                                                                int t=QMessageBox::warning(parent, tr("FET warning"), str,
05824                                                                 tr("Skip rest"), tr("See next"), QString(),
05825                                                                 1, 0 );
05826                                    
05827                                                                if(t==0)
05828                                                                       skipDuplicatedStudentsSets=true;
05829                                                         }
05830                                                  }                                         
05831                                           
05832                                                  sty->name=elem4.text();
05833                                                  if(!studentsHash.contains(sty->name))
05834                                                         studentsHash.insert(sty->name, sty);
05835                                                  xmlReadingLog+="    Read year name: "+sty->name+"\n";
05836                                           }
05837                                           else if(elem4.tagName()=="Number_of_Students"){
05838                                                  sty->numberOfStudents=elem4.text().toInt();
05839                                                  xmlReadingLog+="    Read year number of students: "+CustomFETString::number(sty->numberOfStudents)+"\n";
05840                                           }
05841                                           else if(elem4.tagName()=="Group"){
05842                                                  StudentsGroup* stg=new StudentsGroup();
05843                                                  int ns=0;
05844 
05845                                                  QSet<QString> subgroupsInGroup;
05846                                                  
05847                                                  /*bool tmp4=this->addGroupFast(sty, stg);
05848                                                  assert(tmp4==true);
05849                                                  ng++;*/
05850 
05851                                                  for(QDomNode node5=elem4.firstChild(); !node5.isNull(); node5=node5.nextSibling()){
05852                                                         QDomElement elem5=node5.toElement();
05853                                                         if(elem5.isNull()){
05854                                                                xmlReadingLog+="     Null node here\n";
05855                                                                continue;
05856                                                         }
05857                                                         xmlReadingLog+="     Found "+elem5.tagName()+" tag\n";
05858                                                         if(elem5.tagName()=="Name"){
05859                                                                if(!skipDuplicatedStudentsSets){
05860                                                                       QString nn=elem5.text();
05861                                                                       StudentsSet* ss=studentsHash.value(nn, NULL);
05862                                                                       if(ss!=NULL){
05863                                                                              QString str;
05864                                                                
05865                                                                              if(ss->type==STUDENTS_YEAR)
05866                                                                                     str=tr("Trying to add group %1, which is already added as another year - your file will be loaded but probably contains errors, please correct them after loading").arg(nn);
05867                                                                              else if(ss->type==STUDENTS_GROUP){
05868                                                                                     if(groupsInYear.contains(nn)){
05869                                                                                            str=tr("Trying to add group %1 in year %2 but it is already added - your file will be loaded but probably contains errors, please correct them after loading").arg(nn).arg(sty->name);
05870                                                                                     }
05871                                                                                     else
05872                                                                                            str="";
05873                                                                              }
05874                                                                              else if(ss->type==STUDENTS_SUBGROUP)
05875                                                                                     str=tr("Trying to add group %1, which is already added as another subgroup - your file will be loaded but probably contains errors, please correct them after loading").arg(nn);
05876                                                         
05877                                                                              int t=1;
05878                                                                              if(str!=""){
05879                                                                                     t=QMessageBox::warning(parent, tr("FET warning"), str,
05880                                                                                      tr("Skip rest"), tr("See next"), QString(),
05881                                                                                      1, 0 );
05882                                                                              }
05883                                    
05884                                                                              if(t==0)
05885                                                                                     skipDuplicatedStudentsSets=true;
05886                                                                       }
05887                                                                }
05888                                                                
05889                                                                groupsInYear.insert(elem5.text());
05890 
05891                                                                if(studentsHash.contains(elem5.text())){
05892                                                                       delete stg;
05893                                                                       stg=(StudentsGroup*)(studentsHash.value(elem5.text()));
05894 
05895                                                                       bool tmp4=this->addGroupFast(sty, stg);
05896                                                                       assert(tmp4==true);
05897                                                                       //ng++;
05898                                                                       break;
05899                                                                }
05900 
05901                                                                bool tmp4=this->addGroupFast(sty, stg);
05902                                                                assert(tmp4==true);
05903                                                                ng++;
05904 
05905                                                                stg->name=elem5.text();
05906                                                                if(!studentsHash.contains(stg->name))
05907                                                                       studentsHash.insert(stg->name, stg);
05908                                                                xmlReadingLog+="     Read group name: "+stg->name+"\n";
05909                                                         }
05910                                                         else if(elem5.tagName()=="Number_of_Students"){
05911                                                                stg->numberOfStudents=elem5.text().toInt();
05912                                                                xmlReadingLog+="     Read group number of students: "+CustomFETString::number(stg->numberOfStudents)+"\n";
05913                                                         }
05914                                                         else if(elem5.tagName()=="Subgroup"){
05915                                                                StudentsSubgroup* sts=new StudentsSubgroup();
05916 
05917                                                                /*bool tmp6=this->addSubgroupFast(sty, stg, sts);
05918                                                                assert(tmp6==true);
05919                                                                ns++;*/
05920 
05921                                                                for(QDomNode node6=elem5.firstChild(); !node6.isNull(); node6=node6.nextSibling()){
05922                                                                       QDomElement elem6=node6.toElement();
05923                                                                       if(elem6.isNull()){
05924                                                                              xmlReadingLog+="     Null node here\n";
05925                                                                              continue;
05926                                                                       }
05927                                                                       xmlReadingLog+="     Found "+elem6.tagName()+" tag\n";
05928                                                                       if(elem6.tagName()=="Name"){
05929                                                                              if(!skipDuplicatedStudentsSets){
05930                                                                                     QString nn=elem6.text();
05931                                                                                     StudentsSet* ss=studentsHash.value(nn, NULL);
05932                                                                                     if(ss!=NULL){
05933                                                                                            QString str;
05934                                                                
05935                                                                                            if(ss->type==STUDENTS_YEAR)
05936                                                                                                   str=tr("Trying to add subgroup %1, which is already added as another year - your file will be loaded but probably contains errors, please correct them after loading").arg(nn);
05937                                                                                            else if(ss->type==STUDENTS_GROUP)
05938                                                                                                   str=tr("Trying to add subgroup %1, which is already added as another group - your file will be loaded but probably contains errors, please correct them after loading").arg(nn);
05939                                                                                            else if(ss->type==STUDENTS_SUBGROUP){
05940                                                                                                   if(subgroupsInGroup.contains(nn)){
05941                                                                                                          str=tr("Trying to add subgroup %1 in year %2, group %3 but it is already added - your file will be loaded but probably contains errors, please correct them after loading").arg(nn).arg(sty->name).arg(stg->name);
05942                                                                                                   }
05943                                                                                                   else
05944                                                                                                          str="";
05945                                                                                            }
05946                                                         
05947                                                                                            int t=1;
05948                                                                                            if(str!=""){
05949                                                                                                   t=QMessageBox::warning(parent, tr("FET warning"), str,
05950                                                                                                    tr("Skip rest"), tr("See next"), QString(),
05951                                                                                                    1, 0 );
05952                                                                                            }
05953                                                  
05954                                                                                            if(t==0)
05955                                                                                                   skipDuplicatedStudentsSets=true;
05956                                                                                     }
05957                                                                              }
05958                                                                              
05959                                                                              subgroupsInGroup.insert(elem6.text());
05960 
05961                                                                              if(studentsHash.contains(elem6.text())){
05962                                                                                     delete sts;
05963                                                                                     sts=(StudentsSubgroup*)(studentsHash.value(elem6.text()));
05964 
05965                                                                                     bool tmp6=this->addSubgroupFast(sty, stg, sts);
05966                                                                                     assert(tmp6==true);
05967                                                                                     //ns++;
05968                                                                                     break;
05969                                                                              }
05970 
05971                                                                              bool tmp6=this->addSubgroupFast(sty, stg, sts);
05972                                                                              assert(tmp6==true);
05973                                                                              ns++;
05974                                                                              
05975                                                                              sts->name=elem6.text();
05976                                                                              if(!studentsHash.contains(sts->name))
05977                                                                                     studentsHash.insert(sts->name, sts);
05978                                                                              xmlReadingLog+="     Read subgroup name: "+sts->name+"\n";
05979                                                                       }
05980                                                                       else if(elem6.tagName()=="Number_of_Students"){
05981                                                                              sts->numberOfStudents=elem6.text().toInt();
05982                                                                              xmlReadingLog+="     Read subgroup number of students: "+CustomFETString::number(sts->numberOfStudents)+"\n";
05983                                                                       }
05984                                                                }
05985                                                         }
05986                                                  }
05987                                                  if(ns == stg->subgroupsList.size()){
05988                                                         xmlReadingLog+="    Added "+CustomFETString::number(ns)+" subgroups\n";
05989                                                         tsgr+=ns;
05990                                                  //reducedXmlLog+="          Added "+CustomFETString::number(ns)+" subgroups\n";
05991                                                  }
05992                                           }
05993                                    }
05994                                    if(ng == sty->groupsList.size()){
05995                                           xmlReadingLog+="   Added "+CustomFETString::number(ng)+" groups\n";
05996                                           tgr+=ng;
05997                                           //reducedXmlLog+="   Added "+CustomFETString::number(ng)+" groups\n";
05998                                    }
05999                             }
06000                      }
06001                      xmlReadingLog+="  Added "+CustomFETString::number(ny)+" years\n";
06002                      reducedXmlLog+="Added "+CustomFETString::number(ny)+" students years\n";
06003                      //reducedXmlLog+="Added "+CustomFETString::number(tgr)+" students groups (see note below)\n";
06004                      reducedXmlLog+="Added "+CustomFETString::number(tgr)+" students groups\n";
06005                      //reducedXmlLog+="Added "+CustomFETString::number(tsgr)+" students subgroups (see note below)\n";
06006                      reducedXmlLog+="Added "+CustomFETString::number(tsgr)+" students subgroups\n";
06007                      assert(this->yearsList.size()==ny);
06008 
06009                      //BEGIN test for number of students is the same in all sets with the same name
06010                      bool reportWrongNumberOfStudents=true;
06011                      foreach(StudentsYear* year, yearsList){
06012                             assert(studentsHash.contains(year->name));
06013                             StudentsSet* sy=studentsHash.value(year->name);
06014                             if(sy->numberOfStudents!=year->numberOfStudents){
06015                                    if(reportWrongNumberOfStudents){
06016                                           QString str=tr("Minor problem found and corrected: year %1 has different number of students in two places (%2 and %3)", "%2 and %3 are number of students")
06017                                                  .arg(year->name).arg(sy->numberOfStudents).arg(year->numberOfStudents)
06018                                                  +
06019                                                  "\n\n"+
06020                                                  tr("Explanation: this is a minor problem, which appears if using overlapping students set, due to a bug in FET previous to version %1."
06021                                                  " FET will now correct this problem by setting the number of students for this year, in all places where it appears,"
06022                                                  " to the number that was found in the first appearance (%2). It is advisable to check the number of students for this year.")
06023                                                  .arg("5.12.1").arg(sy->numberOfStudents);
06024                                           int t=QMessageBox::warning(parent, tr("FET warning"), str,
06025                                                   tr("Skip rest"), tr("See next"), QString(),
06026                                                   1, 0 );
06027        
06028                                           if(t==0)
06029                                                  reportWrongNumberOfStudents=false;
06030                                    }
06031                                    year->numberOfStudents=sy->numberOfStudents;
06032                             }
06033                             
06034                             foreach(StudentsGroup* group, year->groupsList){
06035                                    assert(studentsHash.contains(group->name));
06036                                    StudentsSet* sg=studentsHash.value(group->name);
06037                                    if(sg->numberOfStudents!=group->numberOfStudents){
06038                                           if(reportWrongNumberOfStudents){
06039                                                  QString str=tr("Minor problem found and corrected: group %1 has different number of students in two places (%2 and %3)", "%2 and %3 are number of students")
06040                                                         .arg(group->name).arg(sg->numberOfStudents).arg(group->numberOfStudents)
06041                                                         +
06042                                                         "\n\n"+
06043                                                         tr("Explanation: this is a minor problem, which appears if using overlapping students set, due to a bug in FET previous to version %1."
06044                                                         " FET will now correct this problem by setting the number of students for this group, in all places where it appears,"
06045                                                         " to the number that was found in the first appearance (%2). It is advisable to check the number of students for this group.")
06046                                                         .arg("5.12.1").arg(sg->numberOfStudents);
06047                                                  int t=QMessageBox::warning(parent, tr("FET warning"), str,
06048                                                          tr("Skip rest"), tr("See next"), QString(),
06049                                                          1, 0 );
06050               
06051                                                  if(t==0)
06052                                                         reportWrongNumberOfStudents=false;
06053                                           }
06054                                           group->numberOfStudents=sg->numberOfStudents;
06055                                    }
06056 
06057                                    foreach(StudentsSubgroup* subgroup, group->subgroupsList){
06058                                           assert(studentsHash.contains(subgroup->name));
06059                                           StudentsSet* ss=studentsHash.value(subgroup->name);
06060                                           if(ss->numberOfStudents!=subgroup->numberOfStudents){
06061                                                  if(reportWrongNumberOfStudents){
06062                                                         QString str=tr("Minor problem found and corrected: subgroup %1 has different number of students in two places (%2 and %3)", "%2 and %3 are number of students")
06063                                                                .arg(subgroup->name).arg(ss->numberOfStudents).arg(subgroup->numberOfStudents)
06064                                                                +
06065                                                                "\n\n"+
06066                                                                tr("Explanation: this is a minor problem, which appears if using overlapping students set, due to a bug in FET previous to version %1."
06067                                                                " FET will now correct this problem by setting the number of students for this subgroup, in all places where it appears,"
06068                                                                " to the number that was found in the first appearance (%2). It is advisable to check the number of students for this subgroup.")
06069                                                                .arg("5.12.1").arg(ss->numberOfStudents);
06070                                                         int t=QMessageBox::warning(parent, tr("FET warning"), str,
06071                                                                 tr("Skip rest"), tr("See next"), QString(),
06072                                                                 1, 0 );
06073                      
06074                                                         if(t==0)
06075                                                                reportWrongNumberOfStudents=false;
06076                                                  }
06077                                                  subgroup->numberOfStudents=ss->numberOfStudents;
06078                                           }
06079                                    }
06080                             }
06081                      }
06082                      //END test for number of students is the same in all sets with the same name
06083               }
06084               else if(elem2.tagName()=="Activities_List"){
06085                      QSet<QString> allTeachers;
06086                      QHash<QString, int> studentsSetsCount;
06087                      QSet<QString> allSubjects;
06088                      QSet<QString> allActivityTags;
06089                      
06090                      foreach(Teacher* tch, this->teachersList)
06091                             allTeachers.insert(tch->name);
06092 
06093                      foreach(Subject* sbj, this->subjectsList)
06094                             allSubjects.insert(sbj->name);
06095 
06096                      foreach(ActivityTag* at, this->activityTagsList)
06097                             allActivityTags.insert(at->name);
06098 
06099                      foreach(StudentsYear* year, this->yearsList){
06100                             if(!studentsSetsCount.contains(year->name))
06101                                    studentsSetsCount.insert(year->name, year->numberOfStudents);
06102                             else if(studentsSetsCount.value(year->name)!=year->numberOfStudents){
06103                                    //cout<<"Mistake: year "<<qPrintable(year->name)<<" appears in more places with different number of students"<<endl;
06104                             }
06105 
06106                             foreach(StudentsGroup* group, year->groupsList){
06107                                    if(!studentsSetsCount.contains(group->name))
06108                                           studentsSetsCount.insert(group->name, group->numberOfStudents);
06109                                    else if(studentsSetsCount.value(group->name)!=group->numberOfStudents){
06110                                           //cout<<"Mistake: group "<<qPrintable(group->name)<<" appears in more places with different number of students"<<endl;
06111                                    }
06112                      
06113                                    foreach(StudentsSubgroup* subgroup, group->subgroupsList){
06114                                           if(!studentsSetsCount.contains(subgroup->name))
06115                                                  studentsSetsCount.insert(subgroup->name, subgroup->numberOfStudents);
06116                                           else if(studentsSetsCount.value(subgroup->name)!=subgroup->numberOfStudents){
06117                                                  //cout<<"Mistake: subgroup "<<qPrintable(subgroup->name)<<" appears in more places with different number of students"<<endl;
06118                                           }
06119                                    }
06120                             }
06121                      }
06122 
06123                      //int nchildrennodes=elem2.childNodes().length();
06124                      
06125                      /*QProgressDialog progress(parent);
06126                      progress.setLabelText(tr("Loading activities ... please wait"));
06127                      progress.setRange(0, nchildrennodes);
06128                      progress.setModal(true);*/
06129                      //progress.setCancelButton(parent);
06130                      
06131                      //int ttt=0;
06132               
06133                      int na=0;
06134                      for(QDomNode node3=elem2.firstChild(); !node3.isNull(); node3=node3.nextSibling()){
06135                      
06136                             /*progress.setValue(ttt);
06137                             pqapplication->processEvents();
06138                             if(progress.wasCanceled()){
06139                                    QMessageBox::information(parent, tr("FET information"), tr("Interrupted - only partial file was loaded"));
06140                                    return true;
06141                             }
06142                             
06143                             ttt++;*/
06144                      
06145                             QDomElement elem3=node3.toElement();
06146                             if(elem3.isNull()){
06147                                    xmlReadingLog+="   Null node here\n";
06148                                    continue;
06149                             }
06150                             xmlReadingLog+="   Found "+elem3.tagName()+" tag\n";
06151                             if(elem3.tagName()=="Activity"){
06152                                    bool correct=true;
06153                             
06154                                    QString cm=QString(""); //comments
06155                                    QString tn="";
06156                                    QStringList tl;
06157                                    QString sjn="";
06158                                    QString atn="";
06159                                    QStringList atl;
06160                                    QString stn="";
06161                                    QStringList stl;
06162                                    //int p=PARITY_NOT_INITIALIZED;
06163                                    int td=-1;
06164                                    int d=-1;
06165                                    int id=-1;
06166                                    int gid=-1;
06167                                    bool ac=true;
06168                                    int nos=-1;
06169                                    bool cnos=true;
06170                                    for(QDomNode node4=elem3.firstChild(); !node4.isNull(); node4=node4.nextSibling()){
06171                                           QDomElement elem4=node4.toElement();
06172                                           if(elem4.isNull()){
06173                                                  xmlReadingLog+="   Null node here\n";
06174                                                  continue;
06175                                           }
06176                                           xmlReadingLog+="    Found "+elem4.tagName()+" tag\n";
06177                                           if(elem4.tagName()=="Weekly"){
06178                                                  xmlReadingLog+="    Current activity is weekly - ignoring tag\n";
06179                                                  //assert(p==PARITY_NOT_INITIALIZED);
06180                                                  //p=PARITY_WEEKLY;
06181                                           }
06182                                           //old tag
06183                                           else if(elem4.tagName()=="Biweekly"){
06184                                                  xmlReadingLog+="    Current activity is fortnightly - ignoring tag\n";
06185                                                  //assert(p==PARITY_NOT_INITIALIZED);
06186                                                  //p=PARITY_FORTNIGHTLY;
06187                                           }
06188                                           else if(elem4.tagName()=="Fortnightly"){
06189                                                  xmlReadingLog+="    Current activity is fortnightly - ignoring tag\n";
06190                                                  //assert(p==PARITY_NOT_INITIALIZED);
06191                                                  //p=PARITY_FORTNIGHTLY;
06192                                           }
06193                                           else if(elem4.tagName()=="Active"){
06194                                                  if(elem4.text()=="yes" || elem4.text()=="true" || elem4.text()=="1"){
06195                                                         ac=true;
06196                                                         xmlReadingLog+="     Current activity is active\n";
06197                                                  }
06198                                                  else{
06199                                                         if(!(elem4.text()=="no" || elem4.text()=="false" || elem4.text()=="0")){
06200                                                                QMessageBox::warning(parent, tr("FET warning"),
06201                                                                 tr("Found activity active tag which is not 'true', 'false', 'yes', 'no', '1' or '0'."
06202                                                                 " The activity will be considered not active",
06203                                                                 "Instructions for translators: please leave the 'true', 'false', 'yes' and 'no' fields untranslated, as they are in English"));
06204                                                         }
06205                                                         //assert(elem4.text()=="no" || elem4.text()=="false" || elem4.text()=="0");
06206                                                         ac=false;
06207                                                         xmlReadingLog+="     Current activity is not active\n";
06208                                                  }
06209                                           }
06210                                           else if(elem4.tagName()=="Comments"){
06211                                                  cm=elem4.text();
06212                                                  xmlReadingLog+="    Crt. activity comments="+cm+"\n";
06213                                           }
06214                                           else if(elem4.tagName()=="Teacher"){
06215                                                  tn=elem4.text();
06216                                                  xmlReadingLog+="    Crt. activity teacher="+tn+"\n";
06217                                                  tl.append(tn);
06218                                                  if(!allTeachers.contains(tn))
06219                                                  //if(this->searchTeacher(tn)<0)
06220                                                         correct=false;
06221                                           }
06222                                           else if(elem4.tagName()=="Subject"){
06223                                                  sjn=elem4.text();
06224                                                  xmlReadingLog+="    Crt. activity subject="+sjn+"\n";
06225                                                  if(!allSubjects.contains(sjn))
06226                                                  //if(this->searchSubject(sjn)<0)
06227                                                         correct=false;
06228                                           }
06229                                           else if(elem4.tagName()=="Subject_Tag"){
06230                                                  atn=elem4.text();
06231                                                  xmlReadingLog+="    Crt. activity activity_tag="+atn+"\n";
06232                                                  if(atn!="")
06233                                                         atl.append(atn);
06234                                                  if(atn!="" && !allActivityTags.contains(atn))
06235                                                  //if(atn!="" && this->searchActivityTag(atn)<0)
06236                                                         correct=false;
06237                                           }
06238                                           else if(elem4.tagName()=="Activity_Tag"){
06239                                                  atn=elem4.text();
06240                                                  xmlReadingLog+="    Crt. activity activity_tag="+atn+"\n";
06241                                                  if(atn!="")
06242                                                         atl.append(atn);
06243                                                  if(atn!="" && !allActivityTags.contains(atn))
06244                                                  //if(atn!="" && this->searchActivityTag(atn)<0)
06245                                                         correct=false;
06246                                           }
06247                                           else if(elem4.tagName()=="Students"){
06248                                                  stn=elem4.text();
06249                                                  xmlReadingLog+="    Crt. activity students+="+stn+"\n";
06250                                                  stl.append(stn);
06251                                                  if(!studentsSetsCount.contains(stn))
06252                                                  //if(this->searchStudentsSet(stn)==NULL)
06253                                                         correct=false;
06254                                           }
06255                                           else if(elem4.tagName()=="Duration"){
06256                                                  d=elem4.text().toInt();
06257                                                  xmlReadingLog+="    Crt. activity duration="+CustomFETString::number(d)+"\n";
06258                                           }
06259                                           else if(elem4.tagName()=="Total_Duration"){
06260                                                  td=elem4.text().toInt();
06261                                                  xmlReadingLog+="    Crt. activity total duration="+CustomFETString::number(td)+"\n";
06262                                           }
06263                                           else if(elem4.tagName()=="Id"){
06264                                                  id=elem4.text().toInt();
06265                                                  xmlReadingLog+="    Crt. activity id="+CustomFETString::number(id)+"\n";
06266                                           }
06267                                           else if(elem4.tagName()=="Activity_Group_Id"){
06268                                                  gid=elem4.text().toInt();
06269                                                  xmlReadingLog+="    Crt. activity group id="+CustomFETString::number(gid)+"\n";
06270                                           }
06271                                           else if(elem4.tagName()=="Number_Of_Students"){
06272                                                  cnos=false;
06273                                                  nos=elem4.text().toInt();
06274                                                  xmlReadingLog+="    Crt. activity number of students="+CustomFETString::number(nos)+"\n";
06275                                           }
06276                                    }
06277                                    if(correct){
06278                                           assert(id>=0 && gid>=0);
06279                                           assert(d>0);
06280                                           if(td<0)
06281                                                  td=d;
06282                                           
06283                                           if(cnos==true){
06284                                                  assert(nos==-1);
06285                                                  int _ns=0;
06286                                                  foreach(QString _s, stl){
06287                                                         assert(studentsSetsCount.contains(_s));
06288                                                         _ns+=studentsSetsCount.value(_s);
06289                                                  }
06290                                                  this->addSimpleActivityRulesFast(parent, id, gid, tl, sjn, atl, stl,
06291                                                         d, td, ac, cnos, nos, _ns);
06292                                           }
06293                                           else{
06294                                                  this->addSimpleActivity(parent, id, gid, tl, sjn, atl, stl,
06295                                                         d, td, ac, cnos, nos);
06296                                           }
06297                                           
06298                                           this->activitiesList[this->activitiesList.count()-1]->comments=cm;
06299                                           
06300                                           na++;
06301                                           xmlReadingLog+="   Added the activity\n";
06302                                    }
06303                                    else{
06304                                           xmlReadingLog+="   Activity with id ="+CustomFETString::number(id)+" contains invalid data - skipping\n";
06305                                           QMessageBox::warning(parent, tr("FET information"), 
06306                                            tr("Activity with id=%1 contains invalid data - skipping").arg(id));
06307                                    }
06308                             }
06309                      }
06310                      xmlReadingLog+="  Added "+CustomFETString::number(na)+" activities\n";
06311                      reducedXmlLog+="Added "+CustomFETString::number(na)+" activities\n";
06312               }
06313               else if(elem2.tagName()=="Equipments_List"){
06314                      QMessageBox::warning(parent, tr("FET warning"),
06315                       tr("File contains deprecated equipments list - will be ignored\n"));
06316               }
06317               else if(elem2.tagName()=="Buildings_List"){
06318                      QSet<QString> buildingsRead;
06319               
06320                      int tmp=0;
06321                      for(QDomNode node3=elem2.firstChild(); !node3.isNull(); node3=node3.nextSibling()){
06322                             QDomElement elem3=node3.toElement();
06323                             if(elem3.isNull()){
06324                                    xmlReadingLog+="   Null node here\n";
06325                                    continue;
06326                             }
06327                             xmlReadingLog+="   Found "+elem3.tagName()+" tag\n";
06328                             if(elem3.tagName()=="Building"){
06329                                    Building* bu=new Building();
06330                                    bu->name="";
06331                                    
06332                                    for(QDomNode node4=elem3.firstChild(); !node4.isNull(); node4=node4.nextSibling()){
06333                                           QDomElement elem4=node4.toElement();
06334                                           if(elem4.isNull()){
06335                                                  xmlReadingLog+="    Null node here\n";
06336                                                  continue;
06337                                           }
06338                                           xmlReadingLog+="    Found "+elem4.tagName()+" tag\n";
06339                                           if(elem4.tagName()=="Name"){
06340                                                  bu->name=elem4.text();
06341                                                  xmlReadingLog+="    Read building name: "+bu->name+"\n";
06342                                           }
06343                                    }
06344 
06345                                    bool tmp2=buildingsRead.contains(bu->name);
06346                                    if(tmp2){
06347                                           QMessageBox::warning(parent, tr("FET warning"),
06348                                            tr("Duplicate building %1 found - ignoring").arg(bu->name));
06349                                           xmlReadingLog+="   Building not added - duplicate\n";
06350                                    }
06351                                    else{
06352                                           buildingsRead.insert(bu->name);
06353                                           addBuildingFast(bu);
06354                                           tmp++;
06355                                           xmlReadingLog+="   Building inserted\n";
06356                                    }
06357                             }
06358                      }
06359                      assert(tmp==this->buildingsList.size());
06360                      xmlReadingLog+="  Added "+CustomFETString::number(tmp)+" buildings\n";
06361                      reducedXmlLog+="Added "+CustomFETString::number(tmp)+" buildings\n";
06362               }
06363               else if(elem2.tagName()=="Rooms_List"){
06364                      QSet<QString> roomsRead;
06365               
06366                      int tmp=0;
06367                      for(QDomNode node3=elem2.firstChild(); !node3.isNull(); node3=node3.nextSibling()){
06368                             QDomElement elem3=node3.toElement();
06369                             if(elem3.isNull()){
06370                                    xmlReadingLog+="   Null node here\n";
06371                                    continue;
06372                             }
06373                             xmlReadingLog+="   Found "+elem3.tagName()+" tag\n";
06374                             if(elem3.tagName()=="Room"){
06375                                    Room* rm=new Room();
06376                                    rm->name="";
06377                                    rm->capacity=MAX_ROOM_CAPACITY; //infinite, if not specified
06378                                    rm->building="";
06379                                    for(QDomNode node4=elem3.firstChild(); !node4.isNull(); node4=node4.nextSibling()){
06380                                           QDomElement elem4=node4.toElement();
06381                                           if(elem4.isNull()){
06382                                                  xmlReadingLog+="    Null node here\n";
06383                                                  continue;
06384                                           }
06385                                           xmlReadingLog+="    Found "+elem4.tagName()+" tag\n";
06386                                           if(elem4.tagName()=="Name"){
06387                                                  rm->name=elem4.text();
06388                                                  xmlReadingLog+="    Read room name: "+rm->name+"\n";
06389                                           }
06390                                           else if(elem4.tagName()=="Type"){
06391                                                  //rm->type=elem4.text();
06392                                                  xmlReadingLog+="    Ignoring old tag room type:\n";
06393                                           }
06394                                           else if(elem4.tagName()=="Capacity"){
06395                                                  rm->capacity=elem4.text().toInt();
06396                                                  xmlReadingLog+="    Read room capacity: "+CustomFETString::number(rm->capacity)+"\n";
06397                                           }
06398                                           else if(elem4.tagName()=="Equipment"){
06399                                                  //rm->addEquipment(elem4.text());
06400                                                  xmlReadingLog+="    Ignoring old tag - room equipment:\n";
06401                                           }
06402                                           else if(elem4.tagName()=="Building"){
06403                                                  rm->building=elem4.text();
06404                                                  xmlReadingLog+="    Read room building:\n"+rm->building;
06405                                           }
06406                                    }
06407                                    bool tmp2=roomsRead.contains(rm->name);
06408                                    if(tmp2){
06409                                           QMessageBox::warning(parent, tr("FET warning"),
06410                                            tr("Duplicate room %1 found - ignoring").arg(rm->name));
06411                                           xmlReadingLog+="   Room not added - duplicate\n";
06412                                    }
06413                                    else{
06414                                           roomsRead.insert(rm->name);
06415                                           addRoomFast(rm);
06416                                           tmp++;
06417                                           xmlReadingLog+="   Room inserted\n";
06418                                    }
06419                             }
06420                      }
06421                      assert(tmp==this->roomsList.size());
06422                      xmlReadingLog+="  Added "+CustomFETString::number(tmp)+" rooms\n";
06423                      reducedXmlLog+="Added "+CustomFETString::number(tmp)+" rooms\n";
06424               }
06425               else if(elem2.tagName()=="Time_Constraints_List"){
06426                      bool reportMaxBeginningsAtSecondHourChange=true;
06427                      bool reportMaxGapsChange=true;
06428                      bool reportStudentsSetNotAvailableChange=true;
06429                      bool reportTeacherNotAvailableChange=true;
06430                      bool reportBreakChange=true;
06431                      
06432                      bool reportActivityPreferredTimeChange=true;
06433                      
06434                      bool reportActivityPreferredTimesChange=true;
06435                      bool reportActivitiesPreferredTimesChange=true;
06436                      
06437                      bool reportUnspecifiedPermanentlyLockedTime=true;
06438                      
06439                      bool reportUnspecifiedDayOrHourPreferredStartingTime=true;
06440                      
06441 #if 0
06442                      bool reportIncorrectMinDays=true;
06443 #endif
06444               
06445                      int nc=0;
06446                      TimeConstraint *crt_constraint;
06447                      for(QDomNode node3=elem2.firstChild(); !node3.isNull(); node3=node3.nextSibling()){
06448                             crt_constraint=NULL;
06449                             QDomElement elem3=node3.toElement();
06450                             if(elem3.isNull()){
06451                                    xmlReadingLog+="   Null node here\n";
06452                                    continue;
06453                             }
06454                             xmlReadingLog+="   Found "+elem3.tagName()+" tag\n";
06455                             if(elem3.tagName()=="ConstraintBasicCompulsoryTime"){
06456                                    crt_constraint=readBasicCompulsoryTime(elem3, xmlReadingLog);
06457                             }
06458                             else if(elem3.tagName()=="ConstraintTeacherNotAvailable"){
06459                                    if(reportTeacherNotAvailableChange){
06460                                           int t=QMessageBox::information(parent, tr("FET information"),
06461                                            tr("File contains constraint teacher not available, which is old (it was improved in FET 5.5.0), and will be converted"
06462                                            " to the similar constraint of this type, constraint teacher not available times (a matrix)."),
06463                                             tr("Skip rest"), tr("See next"), QString(), 1, 0 );
06464                                           if(t==0)
06465                                                  reportTeacherNotAvailableChange=false;
06466                                    }
06467 
06468                                    crt_constraint=readTeacherNotAvailable(parent, elem3, xmlReadingLog);
06469                             }
06470                             else if(elem3.tagName()=="ConstraintTeacherNotAvailableTimes"){
06471                                    crt_constraint=readTeacherNotAvailableTimes(parent, elem3, xmlReadingLog);
06472                             }
06473                             else if(elem3.tagName()=="ConstraintTeacherMaxDaysPerWeek"){
06474                                    crt_constraint=readTeacherMaxDaysPerWeek(parent, elem3, xmlReadingLog);
06475                             }
06476                             else if(elem3.tagName()=="ConstraintTeachersMaxDaysPerWeek"){
06477                                    crt_constraint=readTeachersMaxDaysPerWeek(parent, elem3, xmlReadingLog);
06478                             }
06479 
06480                             else if(elem3.tagName()=="ConstraintTeacherMinDaysPerWeek"){
06481                                    crt_constraint=readTeacherMinDaysPerWeek(parent, elem3, xmlReadingLog);
06482                             }
06483                             else if(elem3.tagName()=="ConstraintTeachersMinDaysPerWeek"){
06484                                    crt_constraint=readTeachersMinDaysPerWeek(parent, elem3, xmlReadingLog);
06485                             }
06486 
06487                             else if(elem3.tagName()=="ConstraintTeacherIntervalMaxDaysPerWeek"){
06488                                    crt_constraint=readTeacherIntervalMaxDaysPerWeek(parent, elem3, xmlReadingLog);
06489                             }
06490                             else if(elem3.tagName()=="ConstraintTeachersIntervalMaxDaysPerWeek"){
06491                                    crt_constraint=readTeachersIntervalMaxDaysPerWeek(parent, elem3, xmlReadingLog);
06492                             }
06493                             else if(elem3.tagName()=="ConstraintStudentsSetIntervalMaxDaysPerWeek"){
06494                                    crt_constraint=readStudentsSetIntervalMaxDaysPerWeek(parent, elem3, xmlReadingLog);
06495                             }
06496                             else if(elem3.tagName()=="ConstraintStudentsIntervalMaxDaysPerWeek"){
06497                                    crt_constraint=readStudentsIntervalMaxDaysPerWeek(parent, elem3, xmlReadingLog);
06498                             }
06499                             else if(elem3.tagName()=="ConstraintStudentsSetNotAvailable"){
06500                                    if(reportStudentsSetNotAvailableChange){
06501                                           int t=QMessageBox::information(parent, tr("FET information"),
06502                                            tr("File contains constraint students set not available, which is old (it was improved in FET 5.5.0), and will be converted"
06503                                            " to the similar constraint of this type, constraint students set not available times (a matrix)."),
06504                                             tr("Skip rest"), tr("See next"), QString(), 1, 0 );
06505                                           if(t==0)
06506                                                  reportStudentsSetNotAvailableChange=false;
06507                                    }
06508 
06509                                    crt_constraint=readStudentsSetNotAvailable(parent, elem3, xmlReadingLog);
06510                             }
06511                             else if(elem3.tagName()=="ConstraintStudentsSetNotAvailableTimes"){
06512                                    crt_constraint=readStudentsSetNotAvailableTimes(parent, elem3, xmlReadingLog);
06513                             }
06514                             else if(elem3.tagName()=="ConstraintMinNDaysBetweenActivities"){
06515                                    crt_constraint=readMinNDaysBetweenActivities(parent, elem3, xmlReadingLog);
06516                             }
06517                             else if(elem3.tagName()=="ConstraintMinDaysBetweenActivities"){
06518                                    crt_constraint=readMinDaysBetweenActivities(parent, elem3, xmlReadingLog);
06519                             }
06520                             else if(elem3.tagName()=="ConstraintMaxDaysBetweenActivities"){
06521                                    crt_constraint=readMaxDaysBetweenActivities(elem3, xmlReadingLog);
06522                             }
06523                             else if(elem3.tagName()=="ConstraintMinGapsBetweenActivities"){
06524                                    crt_constraint=readMinGapsBetweenActivities(elem3, xmlReadingLog);
06525                             }
06526                             else if(elem3.tagName()=="ConstraintActivitiesNotOverlapping"){
06527                                    crt_constraint=readActivitiesNotOverlapping(elem3, xmlReadingLog);
06528                             }
06529                             else if(elem3.tagName()=="ConstraintActivitiesSameStartingTime"){
06530                                    crt_constraint=readActivitiesSameStartingTime(elem3, xmlReadingLog);
06531                             }
06532                             else if(elem3.tagName()=="ConstraintActivitiesSameStartingHour"){
06533                                    crt_constraint=readActivitiesSameStartingHour(elem3, xmlReadingLog);
06534                             }
06535                             else if(elem3.tagName()=="ConstraintActivitiesSameStartingDay"){
06536                                    crt_constraint=readActivitiesSameStartingDay(elem3, xmlReadingLog);
06537                             }
06538                             else if(elem3.tagName()=="ConstraintTeachersMaxHoursDaily"){
06539                                    crt_constraint=readTeachersMaxHoursDaily(elem3, xmlReadingLog);
06540                             }
06541                             else if(elem3.tagName()=="ConstraintTeacherMaxHoursDaily"){
06542                                    crt_constraint=readTeacherMaxHoursDaily(elem3, xmlReadingLog);
06543                             }
06544                             else if(elem3.tagName()=="ConstraintTeachersMaxHoursContinuously"){
06545                                    crt_constraint=readTeachersMaxHoursContinuously(elem3, xmlReadingLog);
06546                             }
06547                             else if(elem3.tagName()=="ConstraintTeacherMaxHoursContinuously"){
06548                                    crt_constraint=readTeacherMaxHoursContinuously(elem3, xmlReadingLog);
06549                             }
06550                             else if(elem3.tagName()=="ConstraintTeacherActivityTagMaxHoursContinuously"){
06551                                    crt_constraint=readTeacherActivityTagMaxHoursContinuously(elem3, xmlReadingLog);
06552                             }
06553                             else if(elem3.tagName()=="ConstraintTeachersActivityTagMaxHoursContinuously"){
06554                                    crt_constraint=readTeachersActivityTagMaxHoursContinuously(elem3, xmlReadingLog);
06555                             }
06556 
06557                             else if(elem3.tagName()=="ConstraintTeacherActivityTagMaxHoursDaily"){
06558                                    crt_constraint=readTeacherActivityTagMaxHoursDaily(elem3, xmlReadingLog);
06559                             }
06560                             else if(elem3.tagName()=="ConstraintTeachersActivityTagMaxHoursDaily"){
06561                                    crt_constraint=readTeachersActivityTagMaxHoursDaily(elem3, xmlReadingLog);
06562                             }
06563 
06564                             else if(elem3.tagName()=="ConstraintTeachersMinHoursDaily"){
06565                                    crt_constraint=readTeachersMinHoursDaily(parent, elem3, xmlReadingLog);
06566                             }
06567                             else if(elem3.tagName()=="ConstraintTeacherMinHoursDaily"){
06568                                    crt_constraint=readTeacherMinHoursDaily(parent, elem3, xmlReadingLog);
06569                             }
06570                             else if((elem3.tagName()=="ConstraintTeachersSubgroupsMaxHoursDaily"
06571                              //TODO: erase the line below. It is only kept for compatibility with older versions
06572                              || elem3.tagName()=="ConstraintTeachersSubgroupsNoMoreThanXHoursDaily") && !skipDeprecatedConstraints){
06573                                    int t=QMessageBox::warning(parent, tr("FET warning"),
06574                                     tr("File contains deprecated constraint teachers subgroups max hours daily - will be ignored\n"),
06575                                     tr("Skip rest"), tr("See next"), QString(),
06576                                     1, 0 );
06577                                    
06578                                    if(t==0)
06579                                           skipDeprecatedConstraints=true;
06580                                    crt_constraint=NULL;
06581                             }
06582                             else if(elem3.tagName()=="ConstraintStudentsNHoursDaily" && !skipDeprecatedConstraints){
06583                                    int t=QMessageBox::warning(parent, tr("FET warning"),
06584                                     tr("File contains deprecated constraint students n hours daily - will be ignored\n"),
06585                                     tr("Skip rest"), tr("See next"), QString(),
06586                                     1, 0 );
06587                                    
06588                                    if(t==0)
06589                                           skipDeprecatedConstraints=true;
06590                                    crt_constraint=NULL;
06591                             }
06592                             else if(elem3.tagName()=="ConstraintStudentsSetNHoursDaily" && !skipDeprecatedConstraints){
06593                                    int t=QMessageBox::warning(parent, tr("FET warning"),
06594                                     tr("File contains deprecated constraint students set n hours daily - will be ignored\n"),
06595                                     tr("Skip rest"), tr("See next"), QString(),
06596                                     1, 0 );
06597                                    
06598                                    if(t==0)
06599                                           skipDeprecatedConstraints=true;
06600                                    crt_constraint=NULL;
06601                             }
06602                             else if(elem3.tagName()=="ConstraintStudentsMaxHoursDaily"){
06603                                    crt_constraint=readStudentsMaxHoursDaily(elem3, xmlReadingLog);
06604                             }
06605                             else if(elem3.tagName()=="ConstraintStudentsSetMaxHoursDaily"){
06606                                    crt_constraint=readStudentsSetMaxHoursDaily(elem3, xmlReadingLog);
06607                             }
06608                             else if(elem3.tagName()=="ConstraintStudentsMaxHoursContinuously"){
06609                                    crt_constraint=readStudentsMaxHoursContinuously(elem3, xmlReadingLog);
06610                             }
06611                             else if(elem3.tagName()=="ConstraintStudentsSetMaxHoursContinuously"){
06612                                    crt_constraint=readStudentsSetMaxHoursContinuously(elem3, xmlReadingLog);
06613                             }
06614                             else if(elem3.tagName()=="ConstraintStudentsSetActivityTagMaxHoursContinuously"){
06615                                    crt_constraint=readStudentsSetActivityTagMaxHoursContinuously(elem3, xmlReadingLog);
06616                             }
06617                             else if(elem3.tagName()=="ConstraintStudentsActivityTagMaxHoursContinuously"){
06618                                    crt_constraint=readStudentsActivityTagMaxHoursContinuously(elem3, xmlReadingLog);
06619                             }
06620 
06621                             else if(elem3.tagName()=="ConstraintStudentsSetActivityTagMaxHoursDaily"){
06622                                    crt_constraint=readStudentsSetActivityTagMaxHoursDaily(elem3, xmlReadingLog);
06623                             }
06624                             else if(elem3.tagName()=="ConstraintStudentsActivityTagMaxHoursDaily"){
06625                                    crt_constraint=readStudentsActivityTagMaxHoursDaily(elem3, xmlReadingLog);
06626                             }
06627 
06628                             else if(elem3.tagName()=="ConstraintStudentsMinHoursDaily"){
06629                                    crt_constraint=readStudentsMinHoursDaily(parent, elem3, xmlReadingLog);
06630                             }
06631                             else if(elem3.tagName()=="ConstraintStudentsSetMinHoursDaily"){
06632                                    crt_constraint=readStudentsSetMinHoursDaily(parent, elem3, xmlReadingLog);
06633                             }
06634                             else if(elem3.tagName()=="ConstraintActivityPreferredTime"){
06635                                    if(reportActivityPreferredTimeChange){
06636                                           int t=QMessageBox::information(parent, tr("FET information"),
06637                                            tr("File contains old constraint type activity preferred time, which will be converted"
06638                                            " to the newer similar constraint of this type, constraint activity preferred STARTING time."
06639                                            " This improvement is done in versions 5.5.9 and above"),
06640                                             tr("Skip rest"), tr("See next"), QString(), 1, 0 );
06641                                           if(t==0)
06642                                                  reportActivityPreferredTimeChange=false;
06643                                    }
06644                                    
06645                                    crt_constraint=readActivityPreferredTime(parent, elem3, xmlReadingLog,
06646                                           reportUnspecifiedPermanentlyLockedTime, reportUnspecifiedDayOrHourPreferredStartingTime);
06647                             }
06648                             
06649                             else if(elem3.tagName()=="ConstraintActivityPreferredStartingTime"){
06650                                    crt_constraint=readActivityPreferredStartingTime(parent, elem3, xmlReadingLog,
06651                                           reportUnspecifiedPermanentlyLockedTime, reportUnspecifiedDayOrHourPreferredStartingTime);
06652                             }
06653                             else if(elem3.tagName()=="ConstraintActivityEndsStudentsDay"){
06654                                    crt_constraint=readActivityEndsStudentsDay(elem3, xmlReadingLog);
06655                             }
06656                             else if(elem3.tagName()=="ConstraintActivitiesEndStudentsDay"){
06657                                    crt_constraint=readActivitiesEndStudentsDay(elem3, xmlReadingLog);
06658                             }
06659                             //old, with 2 and 3
06660                             else if(elem3.tagName()=="Constraint2ActivitiesConsecutive"){
06661                                    crt_constraint=read2ActivitiesConsecutive(elem3, xmlReadingLog);
06662                             }
06663                             else if(elem3.tagName()=="Constraint2ActivitiesGrouped"){
06664                                    crt_constraint=read2ActivitiesGrouped(elem3, xmlReadingLog);
06665                             }
06666                             else if(elem3.tagName()=="Constraint3ActivitiesGrouped"){
06667                                    crt_constraint=read3ActivitiesGrouped(elem3, xmlReadingLog);
06668                             }
06669                             else if(elem3.tagName()=="Constraint2ActivitiesOrdered"){
06670                                    crt_constraint=read2ActivitiesOrdered(elem3, xmlReadingLog);
06671                             }
06672                             //end old
06673                             else if(elem3.tagName()=="ConstraintTwoActivitiesConsecutive"){
06674                                    crt_constraint=readTwoActivitiesConsecutive(elem3, xmlReadingLog);
06675                             }
06676                             else if(elem3.tagName()=="ConstraintTwoActivitiesGrouped"){
06677                                    crt_constraint=readTwoActivitiesGrouped(elem3, xmlReadingLog);
06678                             }
06679                             else if(elem3.tagName()=="ConstraintThreeActivitiesGrouped"){
06680                                    crt_constraint=readThreeActivitiesGrouped(elem3, xmlReadingLog);
06681                             }
06682                             else if(elem3.tagName()=="ConstraintTwoActivitiesOrdered"){
06683                                    crt_constraint=readTwoActivitiesOrdered(elem3, xmlReadingLog);
06684                             }
06685                             else if(elem3.tagName()=="ConstraintActivityEndsDay" && !skipDeprecatedConstraints ){
06686                                    int t=QMessageBox::warning(parent, tr("FET warning"),
06687                                     tr("File contains deprecated constraint activity ends day - will be ignored\n"),
06688                                     tr("Skip rest"), tr("See next"), QString(),
06689                                     1, 0 );
06690                                    
06691                                    if(t==0)
06692                                           skipDeprecatedConstraints=true;
06693                                    crt_constraint=NULL;
06694                             }
06695                             else if(elem3.tagName()=="ConstraintActivityPreferredTimes"){
06696                                    if(reportActivityPreferredTimesChange){
06697                                           int t=QMessageBox::information(parent, tr("FET information"),
06698                                            tr("Your file contains old constraint activity preferred times, which will be converted to"
06699                                            " new equivalent constraint activity preferred starting times. Beginning with FET-5.5.9 it is possible"
06700                                            " to specify: 1. the starting times of an activity (constraint activity preferred starting times)"
06701                                            " or: 2. the accepted time slots (constraint activity preferred time slots)."
06702                                            " If what you need is type 2 of this constraint, you will have to add it by yourself from the interface."),
06703                                             tr("Skip rest"), tr("See next"), QString(), 1, 0 );
06704                                           if(t==0)
06705                                                  reportActivityPreferredTimesChange=false;
06706                                    }
06707                                    
06708                                    crt_constraint=readActivityPreferredTimes(parent, elem3, xmlReadingLog);
06709                             }
06710                             else if(elem3.tagName()=="ConstraintActivityPreferredTimeSlots"){
06711                                    crt_constraint=readActivityPreferredTimeSlots(parent, elem3, xmlReadingLog);
06712                             }
06713                             else if(elem3.tagName()=="ConstraintActivityPreferredStartingTimes"){
06714                                    crt_constraint=readActivityPreferredStartingTimes(parent, elem3, xmlReadingLog);
06715                             }
06716                             else if(elem3.tagName()=="ConstraintBreak"){
06717                                    if(reportBreakChange){
06718                                           int t=QMessageBox::information(parent, tr("FET information"),
06719                                            tr("File contains constraint break, which is old (it was improved in FET 5.5.0), and will be converted"
06720                                            " to the similar constraint of this type, constraint break times (a matrix)."),
06721                                             tr("Skip rest"), tr("See next"), QString(), 1, 0 );
06722                                           if(t==0)
06723                                                  reportBreakChange=false;
06724                                    }
06725                                    
06726                                    crt_constraint=readBreak(parent, elem3, xmlReadingLog);
06727                             }
06728                             else if(elem3.tagName()=="ConstraintBreakTimes"){
06729                                    crt_constraint=readBreakTimes(parent, elem3, xmlReadingLog);
06730                             }
06731                             else if(elem3.tagName()=="ConstraintTeachersNoGaps"){
06732                                    crt_constraint=readTeachersNoGaps(elem3, xmlReadingLog);
06733                             }
06734                             else if(elem3.tagName()=="ConstraintTeachersMaxGapsPerWeek"){
06735                                    crt_constraint=readTeachersMaxGapsPerWeek(elem3, xmlReadingLog);
06736                             }
06737                             else if(elem3.tagName()=="ConstraintTeacherMaxGapsPerWeek"){
06738                                    crt_constraint=readTeacherMaxGapsPerWeek(elem3, xmlReadingLog);
06739                             }
06740                             else if(elem3.tagName()=="ConstraintTeachersMaxGapsPerDay"){
06741                                    crt_constraint=readTeachersMaxGapsPerDay(elem3, xmlReadingLog);
06742                             }
06743                             else if(elem3.tagName()=="ConstraintTeacherMaxGapsPerDay"){
06744                                    crt_constraint=readTeacherMaxGapsPerDay(elem3, xmlReadingLog);
06745                             }
06746                             else if(elem3.tagName()=="ConstraintStudentsNoGaps"){
06747                                    if(reportMaxGapsChange){
06748                                           int t=QMessageBox::information(parent, tr("FET information"),
06749                                            tr("File contains constraint students no gaps, which is old (it was improved in FET 5.5.0), and will be converted"
06750                                            " to the similar constraint of this type, constraint students max gaps per week,"
06751                                            " with max gaps=0. If you like, you can modify this constraint to allow"
06752                                            " more gaps per week (normally not accepted in schools)"),
06753                                             tr("Skip rest"), tr("See next"), QString(), 1, 0 );
06754                                           if(t==0)
06755                                                  reportMaxGapsChange=false;
06756                                    }
06757                                    
06758                                    crt_constraint=readStudentsNoGaps(elem3, xmlReadingLog);
06759                             }
06760                             else if(elem3.tagName()=="ConstraintStudentsSetNoGaps"){
06761                                    if(reportMaxGapsChange){
06762                                           int t=QMessageBox::information(parent, tr("FET information"),
06763                                            tr("File contains constraint students set no gaps, which is old (it was improved in FET 5.5.0), and will be converted"
06764                                            " to the similar constraint of this type, constraint students set max gaps per week,"
06765                                            " with max gaps=0. If you like, you can modify this constraint to allow"
06766                                            " more gaps per week (normally not accepted in schools)"),
06767                                             tr("Skip rest"), tr("See next"), QString(), 1, 0 );
06768                                           if(t==0)
06769                                                  reportMaxGapsChange=false;
06770                                    }
06771                                    
06772                                    crt_constraint=readStudentsSetNoGaps(elem3, xmlReadingLog);
06773                             }
06774                             else if(elem3.tagName()=="ConstraintStudentsMaxGapsPerWeek"){
06775                                    crt_constraint=readStudentsMaxGapsPerWeek(elem3, xmlReadingLog);
06776                             }
06777                             else if(elem3.tagName()=="ConstraintStudentsSetMaxGapsPerWeek"){
06778                                    crt_constraint=readStudentsSetMaxGapsPerWeek(elem3, xmlReadingLog);
06779                             }
06780 
06781                             else if(elem3.tagName()=="ConstraintStudentsMaxGapsPerDay"){
06782                                    crt_constraint=readStudentsMaxGapsPerDay(elem3, xmlReadingLog);
06783                             }
06784                             else if(elem3.tagName()=="ConstraintStudentsSetMaxGapsPerDay"){
06785                                    crt_constraint=readStudentsSetMaxGapsPerDay(elem3, xmlReadingLog);
06786                             }
06787 
06788                             else if(elem3.tagName()=="ConstraintStudentsEarly"){
06789                                    if(reportMaxBeginningsAtSecondHourChange){
06790                                           int t=QMessageBox::information(parent, tr("FET information"),
06791                                            tr("File contains constraint students early, which is old (it was improved in FET 5.5.0), and will be converted"
06792                                            " to the similar constraint of this type, constraint students early max beginnings at second hour,"
06793                                            " with max beginnings=0. If you like, you can modify this constraint to allow"
06794                                            " more beginnings at second available hour (above 0 - this will make the timetable easier)"),
06795                                             tr("Skip rest"), tr("See next"), QString(), 1, 0 );
06796                                           if(t==0)
06797                                                  reportMaxBeginningsAtSecondHourChange=false;
06798                                    }
06799                                    
06800                                    crt_constraint=readStudentsEarly(elem3, xmlReadingLog);
06801                             }
06802                             else if(elem3.tagName()=="ConstraintStudentsEarlyMaxBeginningsAtSecondHour"){
06803                                    crt_constraint=readStudentsEarlyMaxBeginningsAtSecondHour(elem3, xmlReadingLog);
06804                             }
06805                             else if(elem3.tagName()=="ConstraintStudentsSetEarly"){
06806                                    if(reportMaxBeginningsAtSecondHourChange){
06807                                           int t=QMessageBox::information(parent, tr("FET information"),
06808                                            tr("File contains constraint students set early, which is old (it was improved in FET 5.5.0), and will be converted"
06809                                            " to the similar constraint of this type, constraint students set early max beginnings at second hour,"
06810                                            " with max beginnings=0. If you like, you can modify this constraint to allow"
06811                                            " more beginnings at second available hour (above 0 - this will make the timetable easier)"),
06812                                             tr("Skip rest"), tr("See next"), QString(), 1, 0 );
06813                                           if(t==0)
06814                                                  reportMaxBeginningsAtSecondHourChange=false;
06815                                    }
06816                                    
06817                                    crt_constraint=readStudentsSetEarly(elem3, xmlReadingLog);
06818                             }
06819                             else if(elem3.tagName()=="ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour"){
06820                                    crt_constraint=readStudentsSetEarlyMaxBeginningsAtSecondHour(elem3, xmlReadingLog);
06821                             }
06822                             else if(elem3.tagName()=="ConstraintActivitiesPreferredTimes"){
06823                                    if(reportActivitiesPreferredTimesChange){
06824                                           int t=QMessageBox::information(parent, tr("FET information"),
06825                                            tr("Your file contains old constraint activities preferred times, which will be converted to"
06826                                            " new equivalent constraint activities preferred starting times. Beginning with FET-5.5.9 it is possible"
06827                                            " to specify: 1. the starting times of several activities (constraint activities preferred starting times)"
06828                                            " or: 2. the accepted time slots (constraint activities preferred time slots)."
06829                                            " If what you need is type 2 of this constraint, you will have to add it by yourself from the interface."),
06830                                             tr("Skip rest"), tr("See next"), QString(), 1, 0 );
06831                                           if(t==0)
06832                                                  reportActivitiesPreferredTimesChange=false;
06833                                    }
06834                                    
06835                                    crt_constraint=readActivitiesPreferredTimes(parent, elem3, xmlReadingLog);
06836                             }
06837                             else if(elem3.tagName()=="ConstraintActivitiesPreferredTimeSlots"){
06838                                    crt_constraint=readActivitiesPreferredTimeSlots(parent, elem3, xmlReadingLog);
06839                             }
06840                             else if(elem3.tagName()=="ConstraintActivitiesPreferredStartingTimes"){
06841                                    crt_constraint=readActivitiesPreferredStartingTimes(parent, elem3, xmlReadingLog);
06842                             }
06844                             else if(elem3.tagName()=="ConstraintSubactivitiesPreferredTimeSlots"){
06845                                    crt_constraint=readSubactivitiesPreferredTimeSlots(parent, elem3, xmlReadingLog);
06846                             }
06847                             else if(elem3.tagName()=="ConstraintSubactivitiesPreferredStartingTimes"){
06848                                    crt_constraint=readSubactivitiesPreferredStartingTimes(parent, elem3, xmlReadingLog);
06849                             }
06851                             else if(elem3.tagName()=="ConstraintActivitiesOccupyMaxTimeSlotsFromSelection"){
06852                                    crt_constraint=readActivitiesOccupyMaxTimeSlotsFromSelection(parent, elem3, xmlReadingLog);
06853                             }
06856                             else if(elem3.tagName()=="ConstraintActivitiesMaxSimultaneousInSelectedTimeSlots"){
06857                                    crt_constraint=readActivitiesMaxSimultaneousInSelectedTimeSlots(parent, elem3, xmlReadingLog);
06858                             }
06860 
06861                             else if(elem3.tagName()=="ConstraintTeachersSubjectTagsMaxHoursContinuously" && !skipDeprecatedConstraints){
06862                                    int t=QMessageBox::warning(parent, tr("FET warning"),
06863                                     tr("File contains deprecated constraint teachers subject tags max hours continuously - will be ignored\n"),
06864                                     tr("Skip rest"), tr("See next"), QString(),
06865                                     1, 0 );
06866                                                                                             
06867                                    if(t==0)
06868                                           skipDeprecatedConstraints=true;
06869                                    crt_constraint=NULL;
06870                             }
06871                             else if(elem3.tagName()=="ConstraintTeachersSubjectTagMaxHoursContinuously" && !skipDeprecatedConstraints){
06872                                    int t=QMessageBox::warning(parent, tr("FET warning"),
06873                                     tr("File contains deprecated constraint teachers subject tag max hours continuously - will be ignored\n"),
06874                                     tr("Skip rest"), tr("See next"), QString(),
06875                                     1, 0 );
06876                                                                                             
06877                                    if(t==0)
06878                                           skipDeprecatedConstraints=true;
06879                                    crt_constraint=NULL;
06880                             }
06881 
06882 //corruptConstraintTime:
06883                             //here we skip invalid constraint or add valid one
06884                             if(crt_constraint!=NULL){
06885                                    assert(crt_constraint!=NULL);
06886                                    bool tmp=this->addTimeConstraint(crt_constraint);
06887                                    if(!tmp){
06888                                           QMessageBox::warning(parent, tr("FET information"),
06889                                            tr("Constraint\n%1\nnot added - must be a duplicate").
06890                                            arg(crt_constraint->getDetailedDescription(*this)));
06891                                           delete crt_constraint;
06892                                    }
06893                                    else
06894                                           nc++;
06895                             }
06896                      }
06897                      xmlReadingLog+="  Added "+CustomFETString::number(nc)+" time constraints\n";
06898                      reducedXmlLog+="Added "+CustomFETString::number(nc)+" time constraints\n";
06899               }
06900               else if(elem2.tagName()=="Space_Constraints_List"){
06901                      bool reportRoomNotAvailableChange=true;
06902 
06903                      bool reportUnspecifiedPermanentlyLockedSpace=true;
06904 
06905                      int nc=0;
06906                      SpaceConstraint *crt_constraint;
06907                      
06908                      for(QDomNode node3=elem2.firstChild(); !node3.isNull(); node3=node3.nextSibling()){
06909                             crt_constraint=NULL;
06910                             QDomElement elem3=node3.toElement();
06911                             if(elem3.isNull()){
06912                                    xmlReadingLog+="   Null node here\n";
06913                                    continue;
06914                             }
06915                             xmlReadingLog+="   Found "+elem3.tagName()+" tag\n";
06916                             if(elem3.tagName()=="ConstraintBasicCompulsorySpace"){
06917                                    crt_constraint=readBasicCompulsorySpace(elem3, xmlReadingLog);
06918                             }
06919                             else if(elem3.tagName()=="ConstraintRoomNotAvailable"){
06920                                    if(reportRoomNotAvailableChange){
06921                                           int t=QMessageBox::information(parent, tr("FET information"),
06922                                            tr("File contains constraint room not available, which is old (it was improved in FET 5.5.0), and will be converted"
06923                                            " to the similar constraint of this type, constraint room not available times (a matrix)."),
06924                                             tr("Skip rest"), tr("See next"), QString(), 1, 0 );
06925                                           if(t==0)
06926                                                  reportRoomNotAvailableChange=false;
06927                                    }
06928                                    
06929                                    crt_constraint=readRoomNotAvailable(parent, elem3, xmlReadingLog);
06930                             }
06931                             else if(elem3.tagName()=="ConstraintRoomNotAvailableTimes"){
06932                                    crt_constraint=readRoomNotAvailableTimes(parent, elem3, xmlReadingLog);
06933                             }
06934                             else if(elem3.tagName()=="ConstraintRoomTypeNotAllowedSubjects" && !skipDeprecatedConstraints){
06935                             
06936                                    int t=QMessageBox::warning(parent, tr("FET warning"),
06937                                     tr("File contains deprecated constraint room type not allowed subjects - will be ignored\n"),
06938                                     tr("Skip rest"), tr("See next"), QString(),
06939                                     1, 0);
06940                                     
06941                                    if(t==0)
06942                                           skipDeprecatedConstraints=true;
06943                                    crt_constraint=NULL;
06944                             }
06945                             else if(elem3.tagName()=="ConstraintSubjectRequiresEquipments" && !skipDeprecatedConstraints){
06946                             
06947                                    int t=QMessageBox::warning(parent, tr("FET warning"),
06948                                     tr("File contains deprecated constraint subject requires equipments - will be ignored\n"),
06949                                     tr("Skip rest"), tr("See next"), QString(),
06950                                     1, 0);
06951                                     
06952                                    if(t==0)
06953                                           skipDeprecatedConstraints=true;
06954                             
06955                                    crt_constraint=NULL;
06956                             }
06957                             else if(elem3.tagName()=="ConstraintSubjectSubjectTagRequireEquipments" && !skipDeprecatedConstraints){
06958                             
06959                                    int t=QMessageBox::warning(parent, tr("FET warning"),
06960                                     tr("File contains deprecated constraint subject tag requires equipments - will be ignored\n"),
06961                                     tr("Skip rest"), tr("See next"), QString(),
06962                                     1, 0);
06963                                     
06964                                    if(t==0)
06965                                           skipDeprecatedConstraints=true;
06966                                    crt_constraint=NULL;
06967                             }
06968                             else if(elem3.tagName()=="ConstraintTeacherRequiresRoom" && !skipDeprecatedConstraints){
06969                             
06970                                    int t=QMessageBox::warning(parent, tr("FET warning"),
06971                                     tr("File contains deprecated constraint teacher requires room - will be ignored\n"),
06972                                     tr("Skip rest"), tr("See next"), QString(),
06973                                     1, 0);
06974                                     
06975                                    if(t==0)
06976                                           skipDeprecatedConstraints=true;
06977                                    crt_constraint=NULL;
06978                             }
06979                             else if(elem3.tagName()=="ConstraintTeacherSubjectRequireRoom" && !skipDeprecatedConstraints){
06980                             
06981                                    int t=QMessageBox::warning(parent, tr("FET warning"),
06982                                     tr("File contains deprecated constraint teacher subject require room - will be ignored\n"),
06983                                     tr("Skip rest"), tr("See next"), QString(),
06984                                     1, 0);
06985                                     
06986                                    if(t==0)
06987                                           skipDeprecatedConstraints=true;
06988                                    crt_constraint=NULL;
06989                             }
06990                             else if(elem3.tagName()=="ConstraintMinimizeNumberOfRoomsForStudents" && !skipDeprecatedConstraints){
06991                             
06992                                    int t=QMessageBox::warning(parent, tr("FET warning"),
06993                                     tr("File contains deprecated constraint minimize number of rooms for students - will be ignored\n"),
06994                                     tr("Skip rest"), tr("See next"), QString(),
06995                                     1, 0);
06996                                     
06997                                    if(t==0)
06998                                           skipDeprecatedConstraints=true;
06999                                    crt_constraint=NULL;
07000                             }
07001                             else if(elem3.tagName()=="ConstraintMinimizeNumberOfRoomsForTeachers" && !skipDeprecatedConstraints){
07002                             
07003                                    int t=QMessageBox::warning(parent, tr("FET warning"),
07004                                     tr("File contains deprecated constraint minimize number of rooms for teachers - will be ignored\n"),
07005                                     tr("Skip rest"), tr("See next"), QString(),
07006                                     1, 0);
07007                                     
07008                                    if(t==0)
07009                                           skipDeprecatedConstraints=true;
07010                                    crt_constraint=NULL;
07011                             }
07012                             else if(elem3.tagName()=="ConstraintActivityPreferredRoom"){
07013                                    crt_constraint=readActivityPreferredRoom(parent, elem3, xmlReadingLog, reportUnspecifiedPermanentlyLockedSpace);
07014                             }
07015                             else if(elem3.tagName()=="ConstraintActivityPreferredRooms"){
07016                                    crt_constraint=readActivityPreferredRooms(elem3, xmlReadingLog);
07017                             }
07018                             else if(elem3.tagName()=="ConstraintActivitiesSameRoom" && !skipDeprecatedConstraints){
07019                             
07020                                    int t=QMessageBox::warning(parent, tr("FET warning"),
07021                                     tr("File contains deprecated constraint activities same room - will be ignored\n"),
07022                                     tr("Skip rest"), tr("See next"), QString(),
07023                                     1, 0);
07024                                     
07025                                    if(t==0)
07026                                           skipDeprecatedConstraints=true;
07027                                    crt_constraint=NULL;
07028                             }
07029                             else if(elem3.tagName()=="ConstraintSubjectPreferredRoom"){
07030                                    crt_constraint=readSubjectPreferredRoom(elem3, xmlReadingLog);
07031                             }
07032                             else if(elem3.tagName()=="ConstraintSubjectPreferredRooms"){
07033                                    crt_constraint=readSubjectPreferredRooms(elem3, xmlReadingLog);
07034                             }
07035                             else if(elem3.tagName()=="ConstraintSubjectSubjectTagPreferredRoom"){
07036                                    crt_constraint=readSubjectSubjectTagPreferredRoom(elem3, xmlReadingLog);
07037                             }
07038                             else if(elem3.tagName()=="ConstraintSubjectSubjectTagPreferredRooms"){
07039                                    crt_constraint=readSubjectSubjectTagPreferredRooms(elem3, xmlReadingLog);
07040                             }
07041                             else if(elem3.tagName()=="ConstraintSubjectActivityTagPreferredRoom"){
07042                                    crt_constraint=readSubjectActivityTagPreferredRoom(elem3, xmlReadingLog);
07043                             }
07044                             else if(elem3.tagName()=="ConstraintSubjectActivityTagPreferredRooms"){
07045                                    crt_constraint=readSubjectActivityTagPreferredRooms(elem3, xmlReadingLog);
07046                             }
07047                             //added 6 apr 2009
07048                             else if(elem3.tagName()=="ConstraintActivityTagPreferredRoom"){
07049                                    crt_constraint=readActivityTagPreferredRoom(elem3, xmlReadingLog);
07050                             }
07051                             else if(elem3.tagName()=="ConstraintActivityTagPreferredRooms"){
07052                                    crt_constraint=readActivityTagPreferredRooms(elem3, xmlReadingLog);
07053                             }
07054                             else if(elem3.tagName()=="ConstraintStudentsSetHomeRoom"){
07055                                    crt_constraint=readStudentsSetHomeRoom(elem3, xmlReadingLog);
07056                             }
07057                             else if(elem3.tagName()=="ConstraintStudentsSetHomeRooms"){
07058                                    crt_constraint=readStudentsSetHomeRooms(elem3, xmlReadingLog);
07059                             }
07060                             else if(elem3.tagName()=="ConstraintTeacherHomeRoom"){
07061                                    crt_constraint=readTeacherHomeRoom(elem3, xmlReadingLog);
07062                             }
07063                             else if(elem3.tagName()=="ConstraintTeacherHomeRooms"){
07064                                    crt_constraint=readTeacherHomeRooms(elem3, xmlReadingLog);
07065                             }
07066                             else if(elem3.tagName()=="ConstraintMaxBuildingChangesPerDayForTeachers" && !skipDeprecatedConstraints){
07067                             
07068                                    int t=QMessageBox::warning(parent, tr("FET warning"),
07069                                     tr("File contains deprecated constraint max building changes per day for teachers - will be ignored\n"),
07070                                     tr("Skip rest"), tr("See next"), QString(),
07071                                     1, 0);
07072                                     
07073                                    if(t==0)
07074                                           skipDeprecatedConstraints=true;
07075                                    crt_constraint=NULL;
07076                             }
07077                             else if(elem3.tagName()=="ConstraintMaxBuildingChangesPerDayForStudents" && !skipDeprecatedConstraints){
07078                             
07079                                    int t=QMessageBox::warning(parent, tr("FET warning"),
07080                                     tr("File contains deprecated constraint max building changes per day for students - will be ignored\n"),
07081                                     tr("Skip rest"), tr("See next"), QString(),
07082                                     1, 0);
07083                                     
07084                                    if(t==0)
07085                                           skipDeprecatedConstraints=true;
07086                                    crt_constraint=NULL;
07087                             }
07088                             else if(elem3.tagName()=="ConstraintMaxRoomChangesPerDayForTeachers" && !skipDeprecatedConstraints){
07089                             
07090                                    int t=QMessageBox::warning(parent, tr("FET warning"),
07091                                     tr("File contains deprecated constraint max room changes per day for teachers - will be ignored\n"),
07092                                     tr("Skip rest"), tr("See next"), QString(),
07093                                     1, 0);
07094                                     
07095                                    if(t==0)
07096                                           skipDeprecatedConstraints=true;
07097                                    crt_constraint=NULL;
07098                             }
07099                             else if(elem3.tagName()=="ConstraintMaxRoomChangesPerDayForStudents" && !skipDeprecatedConstraints){
07100                             
07101                                    int t=QMessageBox::warning(parent, tr("FET warning"),
07102                                     tr("File contains deprecated constraint max room changes per day for students - will be ignored\n"),
07103                                     tr("Skip rest"), tr("See next"), QString(),
07104                                     1, 0);
07105                                     
07106                                    if(t==0)
07107                                           skipDeprecatedConstraints=true;
07108 
07109                                    crt_constraint=NULL;
07110                             }
07111                             else if(elem3.tagName()=="ConstraintTeacherMaxBuildingChangesPerDay"){
07112                                    crt_constraint=readTeacherMaxBuildingChangesPerDay(elem3, xmlReadingLog);
07113                             }
07114                             else if(elem3.tagName()=="ConstraintTeachersMaxBuildingChangesPerDay"){
07115                                    crt_constraint=readTeachersMaxBuildingChangesPerDay(elem3, xmlReadingLog);
07116                             }
07117                             else if(elem3.tagName()=="ConstraintTeacherMaxBuildingChangesPerWeek"){
07118                                    crt_constraint=readTeacherMaxBuildingChangesPerWeek(elem3, xmlReadingLog);
07119                             }
07120                             else if(elem3.tagName()=="ConstraintTeachersMaxBuildingChangesPerWeek"){
07121                                    crt_constraint=readTeachersMaxBuildingChangesPerWeek(elem3, xmlReadingLog);
07122                             }
07123                             else if(elem3.tagName()=="ConstraintTeacherMinGapsBetweenBuildingChanges"){
07124                                    crt_constraint=readTeacherMinGapsBetweenBuildingChanges(elem3, xmlReadingLog);
07125                             }
07126                             else if(elem3.tagName()=="ConstraintTeachersMinGapsBetweenBuildingChanges"){
07127                                    crt_constraint=readTeachersMinGapsBetweenBuildingChanges(elem3, xmlReadingLog);
07128                             }
07129                             else if(elem3.tagName()=="ConstraintStudentsSetMaxBuildingChangesPerDay"){
07130                                    crt_constraint=readStudentsSetMaxBuildingChangesPerDay(elem3, xmlReadingLog);
07131                             }
07132                             else if(elem3.tagName()=="ConstraintStudentsMaxBuildingChangesPerDay"){
07133                                    crt_constraint=readStudentsMaxBuildingChangesPerDay(elem3, xmlReadingLog);
07134                             }
07135                             else if(elem3.tagName()=="ConstraintStudentsSetMaxBuildingChangesPerWeek"){
07136                                    crt_constraint=readStudentsSetMaxBuildingChangesPerWeek(elem3, xmlReadingLog);
07137                             }
07138                             else if(elem3.tagName()=="ConstraintStudentsMaxBuildingChangesPerWeek"){
07139                                    crt_constraint=readStudentsMaxBuildingChangesPerWeek(elem3, xmlReadingLog);
07140                             }
07141                             else if(elem3.tagName()=="ConstraintStudentsSetMinGapsBetweenBuildingChanges"){
07142                                    crt_constraint=readStudentsSetMinGapsBetweenBuildingChanges(elem3, xmlReadingLog);
07143                             }
07144                             else if(elem3.tagName()=="ConstraintStudentsMinGapsBetweenBuildingChanges"){
07145                                    crt_constraint=readStudentsMinGapsBetweenBuildingChanges(elem3, xmlReadingLog);
07146                             }
07148                             else if(elem3.tagName()=="ConstraintActivitiesOccupyMaxDifferentRooms"){
07149                                    crt_constraint=readActivitiesOccupyMaxDifferentRooms(elem3, xmlReadingLog);
07150                             }
07152 
07153 //corruptConstraintSpace:
07154                             //here we skip invalid constraint or add valid one
07155                             if(crt_constraint!=NULL){
07156                                    assert(crt_constraint!=NULL);
07157                                    
07158                                    bool tmp=this->addSpaceConstraint(crt_constraint);
07159                                    if(!tmp){
07160                                           QMessageBox::warning(parent, tr("FET information"),
07161                                            tr("Constraint\n%1\nnot added - must be a duplicate").
07162                                            arg(crt_constraint->getDetailedDescription(*this)));
07163                                           delete crt_constraint;
07164                                    }
07165                                    else
07166                                           nc++;
07167                             }
07168                      }
07169                      xmlReadingLog+="  Added "+CustomFETString::number(nc)+" space constraints\n";
07170                      reducedXmlLog+="Added "+CustomFETString::number(nc)+" space constraints\n";
07171               }
07172        }
07173 
07174        this->internalStructureComputed=false;
07175        
07176        /*reducedXmlLog+="\n";
07177        reducedXmlLog+="Note: if you have overlapping students sets (years or groups), a group or a subgroup may be counted more than once. "
07178               "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";*/
07179 
07180        if(canWriteLogFile){
07181               //logStream<<xmlReadingLog;
07182               logStream<<reducedXmlLog;
07183        }
07184 
07185        if(file2.error()>0){
07186               QMessageBox::critical(parent, tr("FET critical"),
07187                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")
07188                .arg(file2.error()));
07189        }
07190 
07191        if(canWriteLogFile)
07192               file2.close();
07193 
07195 
07196        return true;
07197 }
07198 
07199 bool Rules::write(QWidget* parent, const QString& filename)
07200 {
07201        assert(this->initialized);
07202 
07203        QString s;
07204        
07205        bool exists=false;
07206        QString filenameTmp=filename;
07207        if(QFile::exists(filenameTmp)){
07208               exists=true;
07209 
07210               filenameTmp.append(QString(".tmp"));
07211               
07212               if(QFile::exists(filenameTmp)){
07213                      int i=1;
07214                      for(;;){
07215                             QString t2=filenameTmp+CustomFETString::number(i);
07216                             if(!QFile::exists(t2)){
07217                                    filenameTmp=t2;
07218                                    break;
07219                             }
07220                             i++;
07221                      }
07222               }
07223        }
07224 
07225        assert(!QFile::exists(filenameTmp));
07226 
07227        QFile file(filenameTmp);
07228        if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate)){
07229               QMessageBox::critical(parent, tr("FET critical"),
07230                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()));
07231               
07232               return false;
07233        }
07234 
07235        QTextStream tos(&file);
07236        
07237        tos.setCodec("UTF-8");
07238        tos.setGenerateByteOrderMark(true);
07239        //tos.setEncoding(QTextStream::UnicodeUTF8);
07240        
07241        s+="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n";
07242 
07243 //     s+="<!DOCTYPE FET><FET version=\""+FET_VERSION+"\">\n\n";
07244        s+="<fet version=\""+FET_VERSION+"\">\n\n";
07245        
07246        //the institution name and comments
07247        s+="<Institution_Name>"+protect(this->institutionName)+"</Institution_Name>\n\n";
07248        s+="<Comments>"+protect(this->comments)+"</Comments>\n\n";
07249 
07250        //the hours and days
07251        s+="<Hours_List>\n   <Number>"+CustomFETString::number(this->nHoursPerDay)+"</Number>\n";
07252        for(int i=0; i<this->nHoursPerDay; i++)
07253               s+="   <Name>"+protect(this->hoursOfTheDay[i])+"</Name>\n";
07254        s+="</Hours_List>\n\n";
07255        s+="<Days_List>\n    <Number>"+CustomFETString::number(this->nDaysPerWeek)+"</Number>\n";
07256        for(int i=0; i<this->nDaysPerWeek; i++)
07257               s+="   <Name>"+protect(this->daysOfTheWeek[i])+"</Name>\n";
07258        s+="</Days_List>\n\n";
07259 
07260        //students list
07261        s+="<Students_List>\n";
07262        for(int i=0; i<this->yearsList.size(); i++){
07263               StudentsYear* sty=this->yearsList[i];
07264               s += sty->getXmlDescription();
07265        }
07266        s+="</Students_List>\n\n";
07267 
07268        //teachers list
07269        s += "<Teachers_List>\n";
07270        for(int i=0; i<this->teachersList.size(); i++){
07271               Teacher* tch=this->teachersList[i];
07272               s += tch->getXmlDescription();
07273        }
07274        s += "</Teachers_List>\n\n";
07275 
07276        //subjects list
07277        s += "<Subjects_List>\n";
07278        for(int i=0; i<this->subjectsList.size(); i++){
07279               Subject* sbj=this->subjectsList[i];
07280               s += sbj->getXmlDescription();
07281        }
07282        s += "</Subjects_List>\n\n";
07283 
07284        //activity tags list
07285        s += "<Activity_Tags_List>\n";
07286        for(int i=0; i<this->activityTagsList.size(); i++){
07287               ActivityTag* stg=this->activityTagsList[i];
07288               s += stg->getXmlDescription();
07289        }
07290        s += "</Activity_Tags_List>\n\n";
07291 
07292        //activities list
07293        s += "<Activities_List>\n";
07294        for(int i=0; i<this->activitiesList.size(); i++){
07295               Activity* act=this->activitiesList[i];
07296               s += act->getXmlDescription(*this);
07297               s += "\n";
07298        }
07299        s += "</Activities_List>\n\n";
07300 
07301        //buildings list
07302        s += "<Buildings_List>\n";
07303        for(int i=0; i<this->buildingsList.size(); i++){
07304               Building* bu=this->buildingsList[i];
07305               s += bu->getXmlDescription();
07306        }
07307        s += "</Buildings_List>\n\n";
07308 
07309        //rooms list
07310        s += "<Rooms_List>\n";
07311        for(int i=0; i<this->roomsList.size(); i++){
07312               Room* rm=this->roomsList[i];
07313               s += rm->getXmlDescription();
07314        }
07315        s += "</Rooms_List>\n\n";
07316 
07317        //time constraints list
07318        s += "<Time_Constraints_List>\n";
07319        for(int i=0; i<this->timeConstraintsList.size(); i++){
07320               TimeConstraint* ctr=this->timeConstraintsList[i];
07321               s += ctr->getXmlDescription(*this);
07322        }
07323        s += "</Time_Constraints_List>\n\n";
07324 
07325        //constraints list
07326        s += "<Space_Constraints_List>\n";
07327        for(int i=0; i<this->spaceConstraintsList.size(); i++){
07328               SpaceConstraint* ctr=this->spaceConstraintsList[i];
07329               s += ctr->getXmlDescription(*this);
07330        }
07331        s += "</Space_Constraints_List>\n\n";
07332 
07333 //     s+="</FET>\n";
07334        s+="</fet>\n";
07335 
07336        tos<<s;
07337        
07338        if(file.error()>0){
07339               QMessageBox::critical(parent, tr("FET critical"),
07340                tr("Saved file gave error code %1, which means saving is compromised. Please check your disk free space")
07341                .arg(file.error()));
07342               
07343               file.close();
07344               return false;
07345        }
07346        
07347        file.close();
07348        
07349        if(exists){
07350               bool tf=QFile::remove(filename);
07351               assert(tf);
07352               tf=QFile::rename(filenameTmp, filename);
07353               assert(tf);
07354        }
07355        
07356        return true;
07357 }
07358 
07359 int Rules::activateTeacher(const QString& teacherName)
07360 {
07361        int count=0;
07362        for(int i=0; i<this->activitiesList.size(); i++){
07363