Back to index

fet  5.18.0
activity.cpp
Go to the documentation of this file.
00001 /*
00002 File activity.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 "activity.h"
00027 #include "rules.h"
00028 
00029 Activity::Activity()
00030 {
00031        comments=QString("");
00032 }
00033 
00034 Activity::Activity(
00035        Rules& r,
00036        int _id,
00037        int _activityGroupId,
00038        const QStringList& _teachersNames,
00039        const QString& _subjectName,
00040        const QStringList& _activityTagsNames,
00041        const QStringList& _studentsNames,
00042        int _duration,
00043        int _totalDuration,
00044        bool _active,
00045        bool _computeNTotalStudents,
00046        int _nTotalStudents)
00047 {
00048        comments=QString("");
00049 
00050        this->id=_id;
00051        this->activityGroupId=_activityGroupId;
00052        this->teachersNames = _teachersNames;
00053        this->subjectName = _subjectName;
00054        this->activityTagsNames = _activityTagsNames;
00055        this->studentsNames = _studentsNames;
00056        this->duration=_duration;
00057        this->totalDuration=_totalDuration;
00058        this->active=_active;
00059        this->computeNTotalStudents=_computeNTotalStudents;
00060        
00061        if(_computeNTotalStudents==true){  
00062               this->nTotalStudents=0;
00063               for(QStringList::Iterator it=this->studentsNames.begin(); it!=this->studentsNames.end(); it++){
00064                      StudentsSet* ss=r.searchStudentsSet(*it);
00065                      this->nTotalStudents += ss->numberOfStudents;
00066               }
00067        }
00068        else{
00069               assert(_nTotalStudents>=0);
00070               this->nTotalStudents=_nTotalStudents;
00071        }
00072 }
00073 
00074 Activity::Activity(
00075        Rules& r,
00076        int _id,
00077        int _activityGroupId,
00078        const QStringList& _teachersNames,
00079        const QString& _subjectName,
00080        const QStringList& _activityTagsNames,
00081        const QStringList& _studentsNames,
00082        int _duration,
00083        int _totalDuration,
00084        bool _active,
00085        bool _computeNTotalStudents,
00086        int _nTotalStudents,
00087        int _computedNumberOfStudents)
00088 {
00089        Q_UNUSED(r);
00090        Q_UNUSED(_nTotalStudents);
00091 
00092        comments=QString("");
00093 
00094        this->id=_id;
00095        this->activityGroupId=_activityGroupId;
00096        this->teachersNames = _teachersNames;
00097        this->subjectName = _subjectName;
00098        this->activityTagsNames = _activityTagsNames;
00099        this->studentsNames = _studentsNames;
00100        this->duration=_duration;
00101        this->totalDuration=_totalDuration;
00102        this->active=_active;
00103        this->computeNTotalStudents=_computeNTotalStudents;
00104        
00105        assert(_computeNTotalStudents);
00106        this->nTotalStudents=_computedNumberOfStudents;
00107 }
00108 
00109 bool Activity::operator==(Activity& a)
00110 {
00111        if(this->teachersNames != a.teachersNames)
00112               return false;
00113        if(this->subjectName != a.subjectName)
00114               return false;
00115        if(this->activityTagsNames != a.activityTagsNames)
00116               return false;
00117        if(this->studentsNames != a.studentsNames)
00118               return false;
00119        //if(this->duration != a.duration)
00120          //  return false;
00121        if((this->activityGroupId==0 && a.activityGroupId!=0) || (this->activityGroupId!=0 && a.activityGroupId==0))
00122               return false;
00123        return true;
00124 }
00125 
00126 bool Activity::searchTeacher(const QString& teacherName)
00127 {
00128        return this->teachersNames.indexOf(teacherName)!=-1;
00129 }
00130 
00131 bool Activity::removeTeacher(const QString& teacherName)
00132 {
00133        int t=this->teachersNames.removeAll(teacherName);
00134        
00135        return t>0;
00136 }
00137 
00138 void Activity::renameTeacher(const QString& initialTeacherName, const QString& finalTeacherName)
00139 {
00140        int t=0;
00141        for(QStringList::iterator it=this->teachersNames.begin(); it!=this->teachersNames.end(); it++)
00142               if((*it)==initialTeacherName){
00143                      *it=finalTeacherName;
00144                      t++;
00145               }
00146        assert(t<=1);
00147 }
00148 
00149 bool Activity::searchStudents(const QString& studentsName)
00150 {
00151        return this->studentsNames.indexOf(studentsName)!=-1;
00152 }
00153 
00154 bool Activity::removeStudents(Rules& r, const QString& studentsName, int nStudents)
00155 {
00156        Q_UNUSED(r);
00157 
00158        int t=this->studentsNames.removeAll(studentsName);
00159 
00160        if(t>0 && this->computeNTotalStudents==true){
00161               /*StudentsSet* s=r.searchStudentsSet(studentsName);
00162               assert(s!=NULL);
00163               this->nTotalStudents-=s->numberOfStudents;*/
00164               this->nTotalStudents-=nStudents;
00165               assert(this->nTotalStudents>=0);
00166        }
00167        
00168        return t>0;
00169 }
00170 
00171 void Activity::renameStudents(Rules& r, const QString& initialStudentsName, const QString& finalStudentsName, int initialNumberOfStudents, int finalNumberOfStudents)
00172 {
00173        Q_UNUSED(r);
00174 
00175        int t=0;
00176        for(QStringList::iterator it=this->studentsNames.begin(); it!=this->studentsNames.end(); it++)
00177               if((*it)==initialStudentsName){
00178                      /*if(this->computeNTotalStudents==true){
00179                             StudentsSet* s=r.searchStudentsSet(initialStudentsName);
00180                             assert(s!=NULL);
00181                             this->nTotalStudents-=s->numberOfStudents;
00182                             
00183                             StudentsSet* s2=r.searchStudentsSet(finalStudentsName);
00184                             assert(s2!=NULL);
00185                             this->nTotalStudents+=s2->numberOfStudents;
00186                             
00187                             assert(this->nTotalStudents>=0);
00188                      }*/
00189               
00190                      *it=finalStudentsName;
00191                      t++;
00192                      
00193                      if(this->computeNTotalStudents){
00194                             assert(initialNumberOfStudents>=0);
00195                             assert(finalNumberOfStudents>=0);
00196                      
00197                             nTotalStudents-=initialNumberOfStudents;
00198                             assert(nTotalStudents>=0);
00199                             nTotalStudents+=finalNumberOfStudents;
00200                      }
00201               }
00202        assert(t<=1);
00203 }
00204 
00205 void Activity::computeInternalStructure(Rules& r)
00206 {
00207        //the internal subgroups list must be computed before entering here.
00208 
00209        //teachers
00210        //this->nTeachers=0;
00211        this->iTeachersList.clear();
00212        for(QStringList::Iterator it=this->teachersNames.begin(); it!=this->teachersNames.end(); it++){
00213               int tmp;
00214               for(tmp=0; tmp<r.nInternalTeachers; tmp++){
00215                      if(r.internalTeachersList[tmp]->name == (*it))
00216                             break;
00217               }
00218               assert(tmp < r.nInternalTeachers);
00219               //assert(this->nTeachers<MAX_TEACHERS_PER_ACTIVITY);
00220               //this->teachers[this->nTeachers++]=tmp;
00221               this->iTeachersList.append(tmp);
00222        }
00223 
00224        //subjects
00225        this->subjectIndex = r.searchSubject(this->subjectName);
00226        assert(this->subjectIndex>=0);
00227 
00228        //activity tags
00229        this->iActivityTagsSet.clear();
00230        foreach(QString tag, this->activityTagsNames){
00231               assert(tag!="");
00232               int index=r.searchActivityTag(tag);
00233               assert(index>=0);
00234               this->iActivityTagsSet.insert(index);
00235        }
00236        //this->activityTagIndex = r.searchActivityTag(this->activityTagName);
00237 
00238        //students    
00239        //this->nSubgroups=0;
00240        this->iSubgroupsList.clear();
00241        for(QStringList::Iterator it=this->studentsNames.begin(); it!=this->studentsNames.end(); it++){
00242               StudentsSet* ss=r.searchAugmentedStudentsSet(*it);
00243               assert(ss);
00244               if(ss->type==STUDENTS_SUBGROUP){
00245                      int tmp;
00246                      /*for(tmp=0; tmp<r.nInternalSubgroups; tmp++)
00247                             if(r.internalSubgroupsList[tmp]->name == ss->name)
00248                                    break;*/
00249                      tmp=((StudentsSubgroup*)ss)->indexInInternalSubgroupsList;
00250                      assert(tmp>=0);
00251                      assert(tmp<r.nInternalSubgroups);
00252                      //assert(this->nSubgroups<MAX_SUBGROUPS_PER_ACTIVITY);
00253                      
00254                      bool duplicate=false;
00255                      if(this->iSubgroupsList.contains(tmp))
00256                      //for(int j=0; j<this->nSubgroups; j++)
00257                      //     if(this->subgroups[j]==tmp)
00258                                    duplicate=true;
00259                      if(duplicate){
00260                             /*QString s;
00261                             s=QString("Warning: activity with id=%1 contains duplicated subgroups. Automatically correcting...")
00262                                    .arg(this->id);
00263                             cout<<qPrintable(s)<<endl;*/
00264                      }
00265                      else
00266                             this->iSubgroupsList.append(tmp);
00267                             //this->subgroups[this->nSubgroups++]=tmp;
00268               }
00269               else if(ss->type==STUDENTS_GROUP){
00270                      StudentsGroup* stg=(StudentsGroup*)ss;
00271                      for(int k=0; k<stg->subgroupsList.size(); k++){
00272                             StudentsSubgroup* sts=stg->subgroupsList[k];
00273                             int tmp;
00274                             /*for(tmp=0; tmp<r.nInternalSubgroups; tmp++)
00275                                    if(r.internalSubgroupsList[tmp]->name == sts->name)
00276                                           break;*/
00277                             tmp=sts->indexInInternalSubgroupsList;
00278                             assert(tmp>=0);
00279                             assert(tmp<r.nInternalSubgroups);
00280                             //assert(this->nSubgroups<MAX_SUBGROUPS_PER_ACTIVITY);
00281 
00282                             bool duplicate=false;
00283                             if(this->iSubgroupsList.contains(tmp))
00284                             //for(int j=0; j<this->nSubgroups; j++)
00285                             //     if(this->subgroups[j]==tmp)
00286                                           duplicate=true;
00287                             if(duplicate){
00288                                    /*QString s;
00289                                    s=QString("Warning: activity with id=%1 contains duplicated subgroups. Automatically correcting...")
00290                                           .arg(this->id);
00291                                    cout<<qPrintable(s)<<endl;*/
00292                             }
00293                             else
00294                                    //this->subgroups[this->nSubgroups++]=tmp;
00295                                    this->iSubgroupsList.append(tmp);
00296                      }
00297               }
00298               else if(ss->type==STUDENTS_YEAR){
00299                      StudentsYear* sty=(StudentsYear*)ss;
00300                      for(int k=0; k<sty->groupsList.size(); k++){
00301                             StudentsGroup* stg=sty->groupsList[k];
00302                             for(int l=0; l<stg->subgroupsList.size(); l++){
00303                                    StudentsSubgroup* sts=stg->subgroupsList[l];
00304                                    int tmp;
00305                                    /*for(tmp=0; tmp<r.nInternalSubgroups; tmp++)
00306                                           if(r.internalSubgroupsList[tmp]->name == sts->name)
00307                                                  break;*/
00308                                    tmp=sts->indexInInternalSubgroupsList;
00309                                    assert(tmp>=0);
00310                                    assert(tmp<r.nInternalSubgroups);
00311                                    //assert(this->nSubgroups<MAX_SUBGROUPS_PER_ACTIVITY);
00312 
00313                                    bool duplicate=false;
00314                                    if(this->iSubgroupsList.contains(tmp))
00315                                    //for(int j=0; j<this->nSubgroups; j++)
00316                                    //     if(this->subgroups[j]==tmp)
00317                                                  duplicate=true;
00318                                    if(duplicate){
00319                                           /*QString s;
00320                                           s=QString("Warning: activity with id=%1 contains duplicated subgroups. Automatically correcting...")
00321                                                  .arg(this->id);
00322                                           cout<<qPrintable(s)<<endl;*/
00323                                    }
00324                                    else{
00325                                           //this->subgroups[this->nSubgroups++]=tmp;
00326                                           this->iSubgroupsList.append(tmp);
00327                                    }
00328                             }
00329                      }
00330               }
00331               else
00332                      assert(0);
00333        }
00334 }
00335 
00336 QString Activity::getXmlDescription(Rules& r)
00337 {
00338        Q_UNUSED(r);
00339 
00340        QString s="<Activity>\n";
00341 
00342        for(QStringList::Iterator it=this->teachersNames.begin(); it!=this->teachersNames.end(); it++)
00343               s+="   <Teacher>" + protect(*it) + "</Teacher>\n";
00344 
00345        s+="   <Subject>" + protect(this->subjectName) + "</Subject>\n";
00346 
00347        foreach(QString tag, this->activityTagsNames)
00348               s+="   <Activity_Tag>" + protect(tag) + "</Activity_Tag>\n";
00349 
00350        for(QStringList::Iterator it=this->studentsNames.begin(); it!=this->studentsNames.end(); it++)
00351               s+="   <Students>" + protect(*it) + "</Students>\n";
00352 
00353        s+="   <Duration>"+CustomFETString::number(this->duration)+"</Duration>\n";
00354        s+="   <Total_Duration>"+CustomFETString::number(this->totalDuration)+"</Total_Duration>\n";
00355        s+="   <Id>"+CustomFETString::number(this->id)+"</Id>\n";
00356        s+="   <Activity_Group_Id>"+CustomFETString::number(this->activityGroupId)+"</Activity_Group_Id>\n";
00357 
00358        if(this->computeNTotalStudents==false)
00359               s+="   <Number_Of_Students>"+CustomFETString::number(this->nTotalStudents)+"</Number_Of_Students>\n";
00360 
00361        s+="   <Active>";
00362        if(this->active==true)
00363               s+="true";
00364        else
00365               s+="false";
00366        s+="</Active>\n";
00367 
00368        s+="   <Comments>"+protect(comments)+"</Comments>\n";
00369 
00370        s+="</Activity>";
00371 
00372        return s;
00373 }
00374 
00375 QString Activity::getDescription(Rules& r)
00376 {
00377        const int INDENT=4;
00378 
00379        Q_UNUSED(r);
00380        
00381        bool _indent;
00382        if(this->isSplit() && this->id!=this->activityGroupId)
00383               _indent=true;
00384        else
00385               _indent=false;
00386               
00387        bool indentRepr;
00388        if(this->isSplit() && this->id==this->activityGroupId)
00389               indentRepr=true;
00390        else
00391               indentRepr=false;
00392               
00393        QString _teachers="";
00394        if(teachersNames.count()==0)
00395               _teachers=tr("no teachers");
00396        else
00397               _teachers=this->teachersNames.join(",");
00398 
00399        QString _subject=this->subjectName;
00400        
00401        QString _activityTags=this->activityTagsNames.join(",");
00402 
00403        QString _students="";
00404        if(studentsNames.count()==0)
00405               _students=tr("no students");
00406        else
00407               _students=this->studentsNames.join(",");
00408 
00409        QString _id;
00410        _id = CustomFETString::number(id);
00411 
00412        QString _agid="";
00413        if(this->isSplit())
00414               _agid = CustomFETString::number(this->activityGroupId);
00415 
00416        QString _duration=CustomFETString::number(this->duration);
00417        
00418        QString _totalDuration="";
00419        if(this->isSplit())
00420               _totalDuration = CustomFETString::number(this->totalDuration);
00421 
00422        QString _active;
00423        if(this->active==true)
00424               _active="";
00425        else
00426               _active="X";
00427 
00428        QString _nstudents="";
00429        if(this->computeNTotalStudents==false)
00430               _nstudents=CustomFETString::number(this->nTotalStudents);
00431 
00433        QString s="";
00434        if(_indent)
00435               s+=QString(INDENT, ' ');
00436               
00437        s+=_id;
00438        s+=" - ";
00439 
00440        if(indentRepr)
00441               s+=QString(INDENT, ' ');
00442               
00443        if(_active!=""){
00444               s+=_active;
00445               s+=" - ";
00446        }
00447        
00448        s+=_duration;
00449        if(this->isSplit()){
00450               s+="/";
00451               s+=_totalDuration;
00452        }
00453        s+=" - ";
00454        
00455        s+=_teachers;
00456        s+=" - ";
00457        s+=_subject;
00458        s+=" - ";
00459        if(_activityTags!=""){
00460               s+=_activityTags;
00461               s+=" - ";
00462        }
00463        s+=_students;
00464 
00465        if(_nstudents!=""){
00466               s+=" - ";
00467               s+=_nstudents;
00468        }
00469        
00470        if(!comments.isEmpty()){
00471               s+=" - ";
00472               s+=comments;
00473        }
00474 
00475        return s;
00476 }
00477 
00478 QString Activity::getDetailedDescription(Rules& r)
00479 {
00480        Q_UNUSED(r);
00481 
00482        QString s;
00483 
00484        s=tr("Activity:");
00485        s+="\n";
00486 
00487        //Id, AGId
00488        s += tr("Id=%1").arg(CustomFETString::number(id));
00489        s+="\n";
00490        if(this->isSplit()){
00491               s += tr("Activity group id=%1").arg(CustomFETString::number(this->activityGroupId));
00492               s+="\n";
00493        }
00494 
00495        //Dur, TD
00496        s+=tr("Duration=%1").arg(CustomFETString::number(this->duration));
00497        s+="\n";
00498        if(this->isSplit()){
00499               s += tr("Total duration=%1").arg(CustomFETString::number(this->totalDuration));
00500               s+="\n";
00501        }
00502        
00503        if(teachersNames.count()==0){
00504               s+=tr("No teachers for this activity");
00505               s+="\n";
00506        }
00507        else
00508               for(QStringList::Iterator it=this->teachersNames.begin(); it!=this->teachersNames.end(); it++){
00509                      s+=tr("Teacher=%1").arg(*it);
00510                      s+="\n";
00511               }
00512 
00513        s+=tr("Subject=%1").arg(this->subjectName);
00514        s+="\n";
00515        foreach(QString tag, this->activityTagsNames){
00516               assert(tag!="");
00517               s+=tr("Activity tag=%1").arg(tag);
00518               s+="\n";
00519        }
00520 
00521        if(studentsNames.count()==0){
00522               s+=tr("No students sets for this activity");
00523               s+="\n";
00524        }
00525        else
00526               for(QStringList::Iterator it=this->studentsNames.begin(); it!=this->studentsNames.end(); it++){
00527                      s += tr("Students=%1").arg(*it);
00528                      s+="\n";
00529               }
00530               
00531        if(this->computeNTotalStudents==true){
00532               /*int nStud=0;
00533               for(QStringList::Iterator it=this->studentsNames.begin(); it!=this->studentsNames.end(); it++){
00534                      StudentsSet* ss=r.searchStudentsSet(*it);
00535                      nStud += ss->numberOfStudents;
00536               }*/
00537               int nStud=this->nTotalStudents;
00538               s+=tr("Total number of students=%1").arg(nStud);
00539               s+="\n";
00540        }
00541        else{
00542               s+=tr("Total number of students=%1").arg(this->nTotalStudents);
00543               s+=" ("+tr("specified", "Specified means that the total number of students was specified separately for the activity")+")";
00544               s+="\n";
00545        }
00546        
00547        //Not active?
00548        QString activeYesNo;
00549        if(this->active==true)
00550               activeYesNo=tr("yes");
00551        else
00552               activeYesNo=tr("no");
00553        if(!active){
00554               s+=tr("Active=%1", "Represents a boolean value, if activity is active or not, %1 is yes or no").arg(activeYesNo);
00555               s+="\n";
00556        }
00557 
00558        //Has comments?
00559        if(!comments.isEmpty()){
00560               s+=tr("Comments=%1").arg(comments);
00561               s+="\n";
00562        }
00563 
00564        return s;
00565 }
00566 
00567 QString Activity::getDetailedDescriptionWithConstraints(Rules& r)
00568 {
00569        QString s=this->getDetailedDescription(r);
00570 
00571        s+="--------------------------------------------------\n";
00572        s+=tr("Time constraints directly related to this activity:");
00573        s+="\n";
00574        for(int i=0; i<r.timeConstraintsList.size(); i++){
00575               TimeConstraint* c=r.timeConstraintsList[i];
00576               if(c->isRelatedToActivity(r, this)){
00577                      s+="\n";
00578                      s+=c->getDetailedDescription(r);
00579               }
00580        }
00581 
00582        s+="--------------------------------------------------\n";
00583        s+=tr("Space constraints directly related to this activity:");
00584        s+="\n";
00585        for(int i=0; i<r.spaceConstraintsList.size(); i++){
00586               SpaceConstraint* c=r.spaceConstraintsList[i];
00587               if(c->isRelatedToActivity(this)){
00588                      s+="\n";
00589                      s+=c->getDetailedDescription(r);
00590               }
00591        }
00592        s+="--------------------------------------------------\n";
00593 
00594        return s;
00595 }
00596 
00597 bool Activity::isSplit()
00598 {
00599        return this->totalDuration != this->duration;
00600 }
00601 
00602 bool Activity::representsComponentNumber(int index)
00603 {
00604        if(this->activityGroupId==0)
00605               return index==1;
00606               //return false;
00607               
00608        //assert(this->activityGroupId>0);
00609        
00610        return index == (this->id - this->activityGroupId + 1);
00611 }