Back to index

fet  5.18.0
timetablegenerateform.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                           timetablegenerateform.cpp  -  description
00003                              -------------------
00004     begin                : Tue Apr 22 2003
00005     copyright            : (C) 2003 by Lalescu Liviu
00006     email                : Please see http://lalescu.ro/liviu/ for details about contacting Liviu Lalescu (in particular, you can find here the e-mail address)
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #include "generate.h"
00019 
00020 #include "timetablegenerateform.h"
00021 #include "timetable_defs.h"
00022 #include "timetable.h"
00023 #include "fet.h"
00024 #include "timetableexport.h"
00025 
00026 #include <QString>
00027 
00028 #include <QPlainTextEdit>
00029 
00030 #include <QDateTime>
00031 #include <QLocale>
00032 
00033 #include <iostream>
00034 #include <fstream>
00035 using namespace std;
00036 
00037 #include <QMessageBox>
00038 
00039 #include <QMutex>
00040 
00041 #include <QDir>
00042 
00043 #include "longtextmessagebox.h"
00044 
00045 QMutex mutex;
00046 
00047 static GenerateThread generateThread;
00048 
00049 #include <QSemaphore>
00050 
00051 QSemaphore semaphorePlacedActivity; //used to update when an activity is placed
00052 
00053 QSemaphore finishedSemaphore;
00054 
00055 //Represents the current status of the simulation - running or stopped.
00056 extern bool simulation_running;
00057 
00058 extern bool students_schedule_ready;
00059 extern bool teachers_schedule_ready;
00060 extern bool rooms_schedule_ready;
00061 
00062 extern Solution best_solution;
00063 
00064 extern Solution highestStageSolution;
00065 
00066 extern QString conflictsStringTitle;
00067 extern QString conflictsString;
00068 
00069 Generate gen;
00070 
00071 QString initialOrderOfActivities;
00072 
00073 int initialOrderOfActivitiesIndices[MAX_ACTIVITIES];
00074 
00075 extern int maxActivitiesPlaced;
00076 
00077 extern QDateTime generationStartDateTime;
00078 extern QDateTime generationHighestStageDateTime;
00079 
00080 QString getActivityDetailedDescription(Rules& r, int id);
00081 
00082 const QString settingsName=QString("TimetableGenerateUnsuccessfulForm");
00083 
00084 void GenerateThread::run()
00085 {
00086        const int INF=2000000000;
00087        bool impossible, timeExceeded;
00088 
00089        gen.generate(INF, impossible, timeExceeded, true); //true means threaded
00090 }
00091 
00092 TimetableGenerateForm::TimetableGenerateForm(QWidget* parent): QDialog(parent)
00093 {
00094        setupUi(this);
00095 
00096        currentResultsTextEdit->setReadOnly(true);
00097        
00098        connect(startPushButton, SIGNAL(clicked()), this, SLOT(start()));
00099        connect(stopPushButton, SIGNAL(clicked()), this, SLOT(stop()));
00100        connect(writeResultsPushButton, SIGNAL(clicked()), this, SLOT(write()));
00101        connect(closePushButton, SIGNAL(clicked()), this, SLOT(closePressed()));
00102        connect(helpPushButton, SIGNAL(clicked()), this, SLOT(help()));
00103        connect(seeImpossiblePushButton, SIGNAL(clicked()), this, SLOT(seeImpossible()));
00104        connect(seeInitialOrderPushButton, SIGNAL(clicked()), this, SLOT(seeInitialOrder()));
00105        connect(writeHighestStagePushButton, SIGNAL(clicked()), this, SLOT(writeHighestStage()));
00106        connect(stopHighestPushButton, SIGNAL(clicked()), this, SLOT(stopHighest()));
00107 
00108        centerWidgetOnScreen(this);
00109        restoreFETDialogGeometry(this);
00110        
00111        simulation_running=false;
00112 
00113        startPushButton->setDefault(true);
00114 
00115        startPushButton->setEnabled(TRUE);
00116        stopPushButton->setDisabled(TRUE);
00117        stopHighestPushButton->setDisabled(TRUE);
00118        closePushButton->setEnabled(TRUE);
00119        writeResultsPushButton->setDisabled(TRUE);
00120        writeHighestStagePushButton->setDisabled(TRUE);
00121        seeImpossiblePushButton->setDisabled(TRUE);
00122        seeInitialOrderPushButton->setDisabled(TRUE);
00123 
00124        connect(&gen, SIGNAL(activityPlaced(int)),
00125         this, SLOT(activityPlaced(int)));
00126        connect(&gen, SIGNAL(simulationFinished()),
00127         this, SLOT(simulationFinished()));
00128        connect(&gen, SIGNAL(impossibleToSolve()),
00129         this, SLOT(impossibleToSolve()));
00130 }
00131 
00132 TimetableGenerateForm::~TimetableGenerateForm()
00133 {
00134        saveFETDialogGeometry(this);
00135        if(simulation_running)
00136               this->stop();
00137 }
00138 
00139 void TimetableGenerateForm::start(){
00140        if(!gt.rules.internalStructureComputed){
00141               if(!gt.rules.computeInternalStructure(this)){
00142                      QMessageBox::warning(this, TimetableGenerateForm::tr("FET warning"), TimetableGenerateForm::tr("Data is wrong. Please correct and try again"));
00143                      return;
00144               }
00145        }
00146 
00147        if(!gt.rules.initialized || gt.rules.activitiesList.isEmpty()){
00148               QMessageBox::critical(this, TimetableGenerateForm::tr("FET information"),
00149                      TimetableGenerateForm::tr("You have entered simulation with uninitialized rules or 0 activities...aborting"));
00150               assert(0);
00151               exit(1);
00152               return;
00153        }
00154 
00155        currentResultsTextEdit->setPlainText(TimetableGenerateForm::tr("Entering simulation....precomputing, please be patient"));
00156        
00157        gen.abortOptimization=false;
00158        bool ok=gen.precompute(this);
00159        
00160        if(!ok){
00161               currentResultsTextEdit->setPlainText(TimetableGenerateForm::tr("Cannot generate - please modify your data"));
00162               currentResultsTextEdit->update();
00163 
00164               QMessageBox::information(this, TimetableGenerateForm::tr("FET information"),
00165                TimetableGenerateForm::tr("Your data cannot be processed - please modify it as instructed"));
00166 
00167               return;
00168        }
00169 
00170        startPushButton->setDisabled(TRUE);
00171        stopPushButton->setEnabled(TRUE);
00172        stopHighestPushButton->setEnabled(TRUE);
00173        closePushButton->setDisabled(TRUE);
00174        writeResultsPushButton->setEnabled(TRUE);
00175        writeHighestStagePushButton->setEnabled(TRUE);
00176        seeImpossiblePushButton->setEnabled(TRUE);
00177        seeInitialOrderPushButton->setEnabled(TRUE);
00178 
00179        simulation_running=true;
00180        
00181        gen.c.makeUnallocated(gt.rules);
00182        
00183        TimetableExport::writeRandomSeed(this, true); //true represents 'before' state
00184 
00185        generateThread.start();
00186 }
00187 
00188 void TimetableGenerateForm::stop()
00189 {
00190        if(!simulation_running){
00191               return;
00192        }
00193 
00194        simulation_running=false;
00195 
00196        mutex.lock();
00197        gen.abortOptimization=true;
00198        mutex.unlock();
00199 
00200        mutex.lock();
00201 
00202        Solution& c=gen.c;
00203 
00204        //needed to find the conflicts strings
00205        QString tmp;
00206        c.fitness(gt.rules, &tmp);
00207 
00208        TimetableExport::getStudentsTimetable(c);
00209        TimetableExport::getTeachersTimetable(c);
00210        TimetableExport::getRoomsTimetable(c);
00211 
00212        //update the string representing the conflicts
00213        conflictsStringTitle=TimetableGenerateForm::tr("Conflicts", "Title of dialog");
00214        conflictsString="";
00215        conflictsString+=TimetableGenerateForm::tr("Total conflicts:");
00216        conflictsString+=" ";
00217        conflictsString+=CustomFETString::number(c.conflictsTotal);
00218        conflictsString+="\n";
00219        conflictsString+=TimetableGenerateForm::tr("Conflicts listing (in decreasing order):");
00220        conflictsString+="\n";
00221 
00222        foreach(QString t, c.conflictsDescriptionList)
00223               conflictsString+=t+"\n";
00224 
00225        TimetableExport::writeSimulationResults(this);
00226 
00227        QString s=TimetableGenerateForm::tr("Simulation interrupted! FET could not find a timetable."
00228         " Maybe you can consider lowering the constraints.");
00229 
00230        s+=" ";
00231        
00232        QString kk;
00233        kk=FILE_SEP;
00234        if(INPUT_FILENAME_XML=="")
00235               kk.append("unnamed");
00236        else{
00237               kk.append(INPUT_FILENAME_XML.right(INPUT_FILENAME_XML.length()-INPUT_FILENAME_XML.lastIndexOf(FILE_SEP)-1));
00238 
00239               if(kk.right(4)==".fet")
00240                      kk=kk.left(kk.length()-4);
00241        }
00242        kk.append("-single");
00243 
00244        s+=TimetableGenerateForm::tr("The partial results were saved in the directory %1")
00245         .arg(QDir::toNativeSeparators(OUTPUT_DIR+FILE_SEP+"timetables"+kk));
00246 
00247        s+="\n\n";
00248 
00249        s+=TimetableGenerateForm::tr("Additional information relating impossible to schedule activities:");
00250        s+="\n\n";
00251 
00252        s+=tr("FET managed to schedule correctly the first %1 most difficult activities."
00253         " You can see initial order of placing the activities in the generate dialog. The activity which might cause problems"
00254         " might be the next activity in the initial order of evaluation. This activity is listed below:")
00255         .arg(maxActivitiesPlaced);
00256         
00257        s+="\n\n";
00258        
00259        s+=tr("Please check constraints related to following possibly problematic activity (or teacher(s), or students set(s)):");
00260        s+="\n";
00261        s+="-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- ";
00262        s+="\n";
00263        
00264        if(maxActivitiesPlaced>=0 && maxActivitiesPlaced<gt.rules.nInternalActivities 
00265         && initialOrderOfActivitiesIndices[maxActivitiesPlaced]>=0 && initialOrderOfActivitiesIndices[maxActivitiesPlaced]<gt.rules.nInternalActivities){
00266               int ai=initialOrderOfActivitiesIndices[maxActivitiesPlaced];
00267 
00268               s+=TimetableGenerateForm::tr("Id: %1 (%2)", "%1 is id of activity, %2 is detailed description of activity")
00269                      .arg(gt.rules.internalActivitiesList[ai].id)
00270                      .arg(getActivityDetailedDescription(gt.rules, gt.rules.internalActivitiesList[ai].id));
00271        }
00272        else
00273               s+=tr("Difficult activity cannot be computed - please report possible bug");
00274 
00275        s+="\n";
00276        s+="-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- ";
00277 
00278        s+="\n\n";
00279 
00280        s+=TimetableGenerateForm::tr("Please check the constraints related to the last "
00281         "activities in the list below, which might be impossible to schedule:");
00282        s+="\n\n";
00283        s+=TimetableGenerateForm::tr("Here are the placed activities which lead to an inconsistency, "
00284         "in order from the first one to the last (the last one FET failed to schedule "
00285         "and the last ones are most likely impossible):");
00286        s+="\n\n";
00287        for(int i=0; i<gen.nDifficultActivities; i++){
00288               int ai=gen.difficultActivities[i];
00289 
00290               s+=TimetableGenerateForm::tr("No: %1").arg(i+1);
00291 
00292               s+=", ";
00293 
00294               s+=TimetableGenerateForm::tr("Id: %1 (%2)", "%1 is id of activity, %2 is detailed description of activity")
00295                      .arg(gt.rules.internalActivitiesList[ai].id)
00296                      .arg(getActivityDetailedDescription(gt.rules, gt.rules.internalActivitiesList[ai].id));
00297 
00298               s+="\n";
00299        }
00300 
00301        mutex.unlock();
00302 
00303        //show the message in a dialog
00304        QDialog dialog(this);
00305        
00306        dialog.setWindowTitle(TimetableGenerateForm::tr("Generation stopped", "The title of a dialog, meaning that the generation of the timetable was stopped."));
00307 
00308        QVBoxLayout* vl=new QVBoxLayout(&dialog);
00309        QPlainTextEdit* te=new QPlainTextEdit();
00310        te->setPlainText(s);
00311        te->setReadOnly(true);
00312        QPushButton* pb=new QPushButton(TimetableGenerateForm::tr("OK"));
00313 
00314        QHBoxLayout* hl=new QHBoxLayout(0);
00315        hl->addStretch(1);
00316        hl->addWidget(pb);
00317 
00318        vl->addWidget(te);
00319        vl->addLayout(hl);
00320        connect(pb, SIGNAL(clicked()), &dialog, SLOT(close()));
00321        
00322        dialog.resize(700,500);
00323        centerWidgetOnScreen(&dialog);
00324        restoreFETDialogGeometry(&dialog, settingsName);
00325        
00326        setParentAndOtherThings(&dialog, this);
00327        dialog.exec();
00328        saveFETDialogGeometry(&dialog, settingsName);
00329 
00330        startPushButton->setEnabled(TRUE);
00331        stopPushButton->setDisabled(TRUE);
00332        stopHighestPushButton->setDisabled(TRUE);
00333        closePushButton->setEnabled(TRUE);
00334        writeResultsPushButton->setDisabled(TRUE);
00335        writeHighestStagePushButton->setDisabled(TRUE);
00336        seeImpossiblePushButton->setDisabled(TRUE);
00337 }
00338 
00339 void TimetableGenerateForm::stopHighest()
00340 {
00341        if(!simulation_running){
00342               return;
00343        }
00344 
00345        simulation_running=false;
00346 
00347        mutex.lock();
00348        gen.abortOptimization=true;
00349        mutex.unlock();
00350 
00351        mutex.lock();
00352 
00353        Solution& c=highestStageSolution;
00354 
00355        //needed to find the conflicts strings
00356        QString tmp;
00357        c.fitness(gt.rules, &tmp);
00358 
00359        TimetableExport::getStudentsTimetable(c);
00360        TimetableExport::getTeachersTimetable(c);
00361        TimetableExport::getRoomsTimetable(c);
00362 
00363        //update the string representing the conflicts
00364        conflictsStringTitle=TimetableGenerateForm::tr("Conflicts", "Title of dialog");
00365        conflictsString="";
00366        conflictsString+=TimetableGenerateForm::tr("Total conflicts:");
00367        conflictsString+=" ";
00368        conflictsString+=CustomFETString::number(c.conflictsTotal);
00369        conflictsString+="\n";
00370        conflictsString+=TimetableGenerateForm::tr("Conflicts listing (in decreasing order):");
00371        conflictsString+="\n";
00372 
00373        foreach(QString t, c.conflictsDescriptionList)
00374               conflictsString+=t+"\n";
00375 
00376        TimetableExport::writeHighestStageResults(this);
00377 
00378        QString s=TimetableGenerateForm::tr("Simulation interrupted! FET could not find a timetable."
00379         " Maybe you can consider lowering the constraints.");
00380 
00381        s+=" ";
00382        
00383        QString kk;
00384        kk=FILE_SEP;
00385        if(INPUT_FILENAME_XML=="")
00386               kk.append("unnamed");
00387        else{
00388               kk.append(INPUT_FILENAME_XML.right(INPUT_FILENAME_XML.length()-INPUT_FILENAME_XML.lastIndexOf(FILE_SEP)-1));
00389 
00390               if(kk.right(4)==".fet")
00391                      kk=kk.left(kk.length()-4);
00392        }
00393        kk.append("-highest");
00394 
00395        s+=TimetableGenerateForm::tr("The partial highest-stage results were saved in the directory %1")
00396         .arg(QDir::toNativeSeparators(OUTPUT_DIR+FILE_SEP+"timetables"+kk));
00397 
00398        s+="\n\n";
00399 
00400        s+=TimetableGenerateForm::tr("Additional information relating impossible to schedule activities:");
00401        s+="\n\n";
00402 
00403        s+=tr("FET managed to schedule correctly the first %1 most difficult activities."
00404         " You can see initial order of placing the activities in the generate dialog. The activity which might cause problems"
00405         " might be the next activity in the initial order of evaluation. This activity is listed below:")
00406         .arg(maxActivitiesPlaced);
00407         
00408        s+="\n\n";
00409        
00410        s+=tr("Please check constraints related to following possibly problematic activity (or teacher(s), or students set(s)):");
00411        s+="\n";
00412        s+="-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- ";
00413        s+="\n";
00414        
00415        if(maxActivitiesPlaced>=0 && maxActivitiesPlaced<gt.rules.nInternalActivities 
00416         && initialOrderOfActivitiesIndices[maxActivitiesPlaced]>=0 && initialOrderOfActivitiesIndices[maxActivitiesPlaced]<gt.rules.nInternalActivities){
00417               int ai=initialOrderOfActivitiesIndices[maxActivitiesPlaced];
00418 
00419               s+=TimetableGenerateForm::tr("Id: %1 (%2)", "%1 is id of activity, %2 is detailed description of activity")
00420                      .arg(gt.rules.internalActivitiesList[ai].id)
00421                      .arg(getActivityDetailedDescription(gt.rules, gt.rules.internalActivitiesList[ai].id));
00422        }
00423        else
00424               s+=tr("Difficult activity cannot be computed - please report possible bug");
00425 
00426        s+="\n";
00427 
00428        mutex.unlock();
00429 
00430        //show the message in a dialog
00431        QDialog dialog(this);
00432 
00433        dialog.setWindowTitle(TimetableGenerateForm::tr("Generation stopped (highest stage)", "The title of a dialog, meaning that the generation of the timetable was stopped "
00434               "and highest stage timetable written."));
00435 
00436        QVBoxLayout* vl=new QVBoxLayout(&dialog);
00437        QPlainTextEdit* te=new QPlainTextEdit();
00438        te->setPlainText(s);
00439        te->setReadOnly(true);
00440        QPushButton* pb=new QPushButton(TimetableGenerateForm::tr("OK"));
00441 
00442        QHBoxLayout* hl=new QHBoxLayout(0);
00443        hl->addStretch(1);
00444        hl->addWidget(pb);
00445 
00446        vl->addWidget(te);
00447        vl->addLayout(hl);
00448        connect(pb, SIGNAL(clicked()), &dialog, SLOT(close()));
00449 
00450        dialog.resize(700,500);
00451        centerWidgetOnScreen(&dialog);
00452        restoreFETDialogGeometry(&dialog, settingsName);
00453        
00454        setParentAndOtherThings(&dialog, this);
00455        dialog.exec();
00456        saveFETDialogGeometry(&dialog, settingsName);
00457 
00458        startPushButton->setEnabled(TRUE);
00459        stopPushButton->setDisabled(TRUE);
00460        stopHighestPushButton->setDisabled(TRUE);
00461        closePushButton->setEnabled(TRUE);
00462        writeResultsPushButton->setDisabled(TRUE);
00463        writeHighestStagePushButton->setDisabled(TRUE);
00464        seeImpossiblePushButton->setDisabled(TRUE);
00465 }
00466 
00467 void TimetableGenerateForm::impossibleToSolve()
00468 {
00469        if(!simulation_running){
00470               return;
00471        }
00472 
00473        simulation_running=false;
00474 
00475        mutex.lock();
00476        gen.abortOptimization=true;
00477        mutex.unlock();
00478 
00479        mutex.lock();
00480 
00481 
00482 
00483        Solution& c=gen.c;
00484 
00485        //needed to find the conflicts strings
00486        QString tmp;
00487        c.fitness(gt.rules, &tmp);
00488 
00489        TimetableExport::getStudentsTimetable(c);
00490        TimetableExport::getTeachersTimetable(c);
00491        TimetableExport::getRoomsTimetable(c);
00492 
00493        //update the string representing the conflicts
00494        conflictsStringTitle=TimetableGenerateForm::tr("Conflicts", "Title of dialog");
00495        conflictsString="";
00496        conflictsString+=TimetableGenerateForm::tr("Total conflicts:");
00497        conflictsString+=" ";
00498        conflictsString+=CustomFETString::number(c.conflictsTotal);
00499        conflictsString+="\n";
00500        conflictsString+=TimetableGenerateForm::tr("Conflicts listing (in decreasing order):");
00501        conflictsString+="\n";
00502 
00503        foreach(QString t, c.conflictsDescriptionList)
00504               conflictsString+=t+"\n";
00505 
00506        TimetableExport::writeSimulationResults(this);
00507 
00508 
00509        QString s=TimetableGenerateForm::tr("Simulation impossible! Maybe you can consider lowering the constraints.");
00510 
00511        s+=" ";
00512 
00513        QString kk;
00514        kk=FILE_SEP;
00515        if(INPUT_FILENAME_XML=="")
00516               kk.append("unnamed");
00517        else{
00518               kk.append(INPUT_FILENAME_XML.right(INPUT_FILENAME_XML.length()-INPUT_FILENAME_XML.lastIndexOf(FILE_SEP)-1));
00519 
00520               if(kk.right(4)==".fet")
00521                      kk=kk.left(kk.length()-4);
00522        }
00523        kk.append("-single");
00524 
00525        s+=TimetableGenerateForm::tr("The partial results were saved in the directory %1")
00526         .arg(QDir::toNativeSeparators(OUTPUT_DIR+FILE_SEP+"timetables"+kk));
00527 
00528        s+="\n\n";
00529 
00530        s+=TimetableGenerateForm::tr("Additional information relating impossible to schedule activities:");
00531        s+="\n\n";
00532        s+=TimetableGenerateForm::tr("Please check the constraints related to the "
00533         "activity below, which might be impossible to schedule:");
00534        s+="\n\n";
00535        for(int i=0; i<gen.nDifficultActivities; i++){
00536               int ai=gen.difficultActivities[i];
00537 
00538               s+=TimetableGenerateForm::tr("No: %1").arg(i+1);
00539 
00540               s+=", ";
00541 
00542               s+=TimetableGenerateForm::tr("Id: %1 (%2)", "%1 is id of activity, %2 is detailed description of activity")
00543                      .arg(gt.rules.internalActivitiesList[ai].id)
00544                      .arg(getActivityDetailedDescription(gt.rules, gt.rules.internalActivitiesList[ai].id));
00545 
00546               s+="\n";
00547        }
00548 
00549        mutex.unlock();
00550 
00551        //show the message in a dialog
00552        QDialog dialog(this);
00553 
00554        dialog.setWindowTitle(TimetableGenerateForm::tr("Generation impossible", "The title of a dialog, meaning that the generation of the timetable is impossible."));
00555 
00556        QVBoxLayout* vl=new QVBoxLayout(&dialog);
00557        QPlainTextEdit* te=new QPlainTextEdit();
00558        te->setPlainText(s);
00559        te->setReadOnly(true);
00560        QPushButton* pb=new QPushButton(TimetableGenerateForm::tr("OK"));
00561 
00562        QHBoxLayout* hl=new QHBoxLayout(0);
00563        hl->addStretch(1);
00564        hl->addWidget(pb);
00565 
00566        vl->addWidget(te);
00567        vl->addLayout(hl);
00568        connect(pb, SIGNAL(clicked()), &dialog, SLOT(close()));
00569 
00570        dialog.resize(700,500);
00571        centerWidgetOnScreen(&dialog);
00572        restoreFETDialogGeometry(&dialog, settingsName);
00573 
00574        setParentAndOtherThings(&dialog, this);
00575        dialog.exec();
00576        saveFETDialogGeometry(&dialog, settingsName);
00577 
00578        startPushButton->setEnabled(TRUE);
00579        stopPushButton->setDisabled(TRUE);
00580        stopHighestPushButton->setDisabled(TRUE);
00581        closePushButton->setEnabled(TRUE);
00582        writeResultsPushButton->setDisabled(TRUE);
00583        writeHighestStagePushButton->setDisabled(TRUE);
00584        seeImpossiblePushButton->setDisabled(TRUE);
00585 }
00586 
00587 void TimetableGenerateForm::simulationFinished()
00588 {
00589        if(!simulation_running){
00590               return;
00591        }
00592 
00593        simulation_running=false;
00594 
00595        finishedSemaphore.acquire();
00596 
00597        TimetableExport::writeRandomSeed(this, false); //false represents 'before' state
00598 
00599        Solution& c=gen.c;
00600 
00601        //needed to find the conflicts strings
00602        QString tmp;
00603        c.fitness(gt.rules, &tmp);
00604 
00605        TimetableExport::getStudentsTimetable(c);
00606        TimetableExport::getTeachersTimetable(c);
00607        TimetableExport::getRoomsTimetable(c);
00608 
00609        //update the string representing the conflicts
00610        conflictsStringTitle=TimetableGenerateForm::tr("Soft conflicts", "Title of dialog");
00611        conflictsString="";
00612        conflictsString+=tr("Total soft conflicts:");
00613        conflictsString+=" ";
00614        conflictsString+=CustomFETString::number(c.conflictsTotal);
00615        conflictsString+="\n";
00616        conflictsString+=TimetableGenerateForm::tr("Soft conflicts listing (in decreasing order):");
00617        conflictsString+="\n";
00618 
00619        foreach(QString t, c.conflictsDescriptionList)
00620               conflictsString+=t+"\n";
00621 
00622        TimetableExport::writeSimulationResults(this);
00623 
00624        QString kk;
00625        kk=FILE_SEP;
00626        if(INPUT_FILENAME_XML=="")
00627               kk.append("unnamed");
00628        else{
00629               kk.append(INPUT_FILENAME_XML.right(INPUT_FILENAME_XML.length()-INPUT_FILENAME_XML.lastIndexOf(FILE_SEP)-1));
00630 
00631               if(kk.right(4)==".fet")
00632                      kk=kk.left(kk.length()-4);
00633        }
00634        kk.append("-single");
00635 
00636 /*     QMessageBox::information(this, TimetableGenerateForm::tr("FET information"),
00637               TimetableGenerateForm::tr("Allocation terminated successfully, remaining %1 weighted"
00638               " soft conflicts from constraints with weight percentage lower than 100%"
00639               " (see menu Timetable/Show soft conflicts or the text file in"
00640               " the output directory for details)."
00641               "\n\nSimulation results should be now written. You may check now Timetable/View."
00642               " The results are also saved in the directory %2 in"
00643               " html and xml mode and the soft conflicts in txt mode").arg(c.conflictsTotal).arg(QDir::toNativeSeparators(OUTPUT_DIR+FILE_SEP+"timetables"+kk))
00644               +". "+tr("Data+timetable is saved as a .fet data file (with activities locked by constraints)"
00645               ", so that you can open/modify/regenerate the current timetable later"));
00646 */
00647 
00648        QString s=QString("");
00649        s+=tr("Generation successful!");
00650        s+=QString("\n\n");
00651        s+=tr("Weighted soft conflicts: %1").arg(CustomFETString::number(c.conflictsTotal));
00652        s+=QString("\n\n");
00653        s+=tr("Results were saved in the directory %1").arg(QDir::toNativeSeparators(OUTPUT_DIR+FILE_SEP+"timetables"+kk));
00654        QMessageBox::information(this, TimetableGenerateForm::tr("FET information"), s);
00655 
00656        startPushButton->setEnabled(TRUE);
00657        stopPushButton->setDisabled(TRUE);
00658        stopHighestPushButton->setDisabled(TRUE);
00659        closePushButton->setEnabled(TRUE);
00660        writeResultsPushButton->setDisabled(TRUE);
00661        writeHighestStagePushButton->setDisabled(TRUE);
00662        seeImpossiblePushButton->setDisabled(TRUE);
00663 }
00664 
00665 void TimetableGenerateForm::activityPlaced(int na){
00666        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
00667 
00668        mutex.lock();
00669        int t=gen.searchTime; //seconds
00670        int mact=maxActivitiesPlaced;
00671        int seconds=gen.timeToHighestStage;
00672        mutex.unlock();
00673 
00674        //write to the Qt interface
00675        QString s;
00676        s+=TimetableGenerateForm::tr("%1 out of %2 activities placed").arg(na).arg(gt.rules.nInternalActivities)+"\n";
00677 
00678        s+=TimetableGenerateForm::tr("Elapsed time:");
00679        int h=t/3600;
00680        if(h>0){
00681               s+=" ";
00682               s+=TimetableGenerateForm::tr("%1 h", "hours").arg(h);
00683        }
00684        t=t%3600;
00685        int m=t/60;
00686        if(m>0){
00687               s+=" ";
00688               s+=TimetableGenerateForm::tr("%1 m", "minutes").arg(m);
00689        }
00690        t=t%60;
00691        if(t>0){
00692               s+=" ";
00693               s+=TimetableGenerateForm::tr("%1 s", "seconds").arg(t);
00694        }
00695        
00696        bool zero=false;
00697        if(seconds==0)
00698               zero=true;
00699        int hh=seconds/3600;
00700        seconds%=3600;
00701        int mm=seconds/60;
00702        seconds%=60;
00703        int ss=seconds;
00704 
00705        QString tim;
00706        if(hh>0){
00707               tim+=" ";
00708               tim+=tr("%1 h", "hours").arg(hh);
00709        }
00710        if(mm>0){
00711               tim+=" ";
00712               tim+=tr("%1 m", "minutes").arg(mm);
00713        }
00714        if(ss>0 || zero){
00715               tim+=" ";
00716               tim+=tr("%1 s", "seconds").arg(ss);
00717        }
00718        tim.remove(0, 1);
00719        s+="\n\n";
00720        s+=tr("Max placed activities: %1 (at %2)", "%1 represents the maximum number of activities placed, %2 is a time interval").arg(mact).arg(tim);
00721 
00722        currentResultsTextEdit->setPlainText(s);
00723 
00724        semaphorePlacedActivity.release();
00725 }
00726 
00727 void TimetableGenerateForm::help()
00728 {
00729        QString s;
00730        
00731        s+=TimetableGenerateForm::tr("Please wait. It might take 5 to 20 minutes or even more for very difficult timetables");
00732        s+="\n\n";
00733        s+=TimetableGenerateForm::tr("Activities are placed in order, most difficult ones first");
00734        s+="\n\n";
00735        s+=TimetableGenerateForm::tr("The process of searching is semi-randomized, which means that "
00736         "you will get different timetables and running times each time. You can choose the best timetable from several runs");
00737        s+="\n\n";
00738        s+=TimetableGenerateForm::tr("Usually, there is no need to stop and restart the search."
00739         " But for very difficult timetables this can help. Sometimes in such cases FET can become stuck and cycle forever,"
00740         " and restarting might produce a very fast solution.");
00741        s+="\n\n";
00742        s+=TimetableGenerateForm::tr("It is recommended to strengthen the constraints step by step (for"
00743         " instance min days between activities weight or teacher(s) max gaps), as you obtain feasible timetables.");
00744        s+="\n\n";
00745        s+=TimetableGenerateForm::tr("If your timetable gets stuck on a certain activity number k (and then"
00746         " begins going back), please check the initial evaluation order and see activity number k+1 in this list. You may find"
00747         " errors this way.");
00748        s+="\n\n";
00749        s+=TimetableGenerateForm::tr("If the generation is successful, you cannot have hard conflicts. You can have only soft conflicts,"
00750         " corresponding to constraints with weight lower than 100.0%, which are reported in detail.");
00751        s+="\n\n";
00752        s+=TimetableGenerateForm::tr("After the generation (successful or interrupted), you can view the current (complete or incomplete) timetable"
00753         " in the corresponding view timetable dialogs, and the list of conflicts in the view conflicts dialog.");
00754        s+="\n\n";
00755        s+=TimetableGenerateForm::tr("The results are saved in your selected results directory in HTML and XML mode and the soft conflicts"
00756         " in text mode, along with the current data and timetable, saved as a .fet data file (with activities locked by constraints), so"
00757         " that you can open, modify and regenerate the current timetable later");
00758        
00759        LongTextMessageBox::largeInformation(this, tr("FET help"), s);
00760 }
00761 
00762 void TimetableGenerateForm::write(){
00763        mutex.lock();
00764 
00765        Solution& c=gen.c;
00766 
00767        //needed to find the conflicts strings
00768        QString tmp;
00769        c.fitness(gt.rules, &tmp);
00770 
00771        TimetableExport::getStudentsTimetable(c);
00772        TimetableExport::getTeachersTimetable(c);
00773        TimetableExport::getRoomsTimetable(c);
00774 
00775        //update the string representing the conflicts
00776        conflictsStringTitle=TimetableGenerateForm::tr("Conflicts", "Title of dialog");
00777        conflictsString="";
00778        conflictsString+=TimetableGenerateForm::tr("Total conflicts:");
00779        conflictsString+=" ";
00780        conflictsString+=CustomFETString::number(c.conflictsTotal);
00781        conflictsString+="\n";
00782        conflictsString+=TimetableGenerateForm::tr("Conflicts listing (in decreasing order):");
00783        conflictsString+="\n";
00784 
00785        foreach(QString t, c.conflictsDescriptionList)
00786               conflictsString+=t+"\n";
00787 
00788        TimetableExport::writeSimulationResults(this);
00789 
00790        mutex.unlock();
00791 
00792        QString kk;
00793        kk=FILE_SEP;
00794        if(INPUT_FILENAME_XML=="")
00795               kk.append("unnamed");
00796        else{
00797               kk.append(INPUT_FILENAME_XML.right(INPUT_FILENAME_XML.length()-INPUT_FILENAME_XML.lastIndexOf(FILE_SEP)-1));
00798 
00799               if(kk.right(4)==".fet")
00800                      kk=kk.left(kk.length()-4);
00801        }
00802        kk.append("-single");
00803 
00804        QMessageBox::information(this, TimetableGenerateForm::tr("FET information"),
00805               TimetableGenerateForm::tr("Simulation results should now be written in the directory %1 in html and xml mode"
00806               " and the conflicts in txt mode").arg(QDir::toNativeSeparators(OUTPUT_DIR+FILE_SEP+"timetables"+kk)));
00807 }
00808 
00809 void TimetableGenerateForm::writeHighestStage(){
00810        mutex.lock();
00811 
00812        Solution& c=highestStageSolution;
00813 
00814        //needed to find the conflicts strings
00815        QString tmp;
00816        c.fitness(gt.rules, &tmp);
00817 
00818        TimetableExport::getStudentsTimetable(c);
00819        TimetableExport::getTeachersTimetable(c);
00820        TimetableExport::getRoomsTimetable(c);
00821 
00822        //update the string representing the conflicts
00823        conflictsStringTitle=TimetableGenerateForm::tr("Conflicts", "Title of dialog");
00824        conflictsString="";
00825        conflictsString+=TimetableGenerateForm::tr("Total conflicts:");
00826        conflictsString+=" ";
00827        conflictsString+=CustomFETString::number(c.conflictsTotal);
00828        conflictsString+="\n";
00829        conflictsString+=TimetableGenerateForm::tr("Conflicts listing (in decreasing order):");
00830        conflictsString+="\n";
00831 
00832        foreach(QString t, c.conflictsDescriptionList)
00833               conflictsString+=t+"\n";
00834 
00835        TimetableExport::writeHighestStageResults(this);
00836 
00837        mutex.unlock();
00838 
00839        QString kk;
00840        kk=FILE_SEP;
00841        if(INPUT_FILENAME_XML=="")
00842               kk.append("unnamed");
00843        else{
00844               kk.append(INPUT_FILENAME_XML.right(INPUT_FILENAME_XML.length()-INPUT_FILENAME_XML.lastIndexOf(FILE_SEP)-1));
00845 
00846               if(kk.right(4)==".fet")
00847                      kk=kk.left(kk.length()-4);
00848        }
00849        kk.append("-highest");
00850 
00851        QMessageBox::information(this, TimetableGenerateForm::tr("FET information"),
00852               TimetableGenerateForm::tr("Highest stage results should now be written in the directory %1 in html and xml mode"
00853               " and the conflicts in txt mode").arg(QDir::toNativeSeparators(OUTPUT_DIR+FILE_SEP+"timetables"+kk)));
00854 }
00855 
00856 void TimetableGenerateForm::closePressed()
00857 {
00858        if(!generateThread.isRunning())
00859               this->close();
00860 }
00861 
00862 void TimetableGenerateForm::seeImpossible()
00863 {
00864        QString s;
00865 
00866        mutex.lock();
00867 
00868        s+=TimetableGenerateForm::tr("Information relating difficult to schedule activities:");
00869        s+="\n\n";
00870        s+=TimetableGenerateForm::tr("Please check the constraints related to the last "
00871         "activities in the list below, which might be difficult to schedule:");
00872        s+="\n\n";
00873        s+=TimetableGenerateForm::tr("Here are the placed activities which lead to a difficulty, "
00874         "in order from the first one to the last (the last one FET failed to schedule "
00875         "and the last ones are difficult):");
00876        s+="\n\n";
00877        for(int i=0; i<gen.nDifficultActivities; i++){
00878               int ai=gen.difficultActivities[i];
00879 
00880               s+=TimetableGenerateForm::tr("No: %1").arg(i+1);
00881 
00882               s+=", ";
00883 
00884               s+=TimetableGenerateForm::tr("Id: %1 (%2)", "%1 is id of activity, %2 is detailed description of activity")
00885                      .arg(gt.rules.internalActivitiesList[ai].id)
00886                      .arg(getActivityDetailedDescription(gt.rules, gt.rules.internalActivitiesList[ai].id));
00887 
00888               s+="\n";
00889        }
00890 
00891        mutex.unlock();
00892        
00893        //show the message in a dialog
00894        QDialog dialog(this);
00895        
00896        dialog.setWindowTitle(tr("FET - information about difficult activities"));
00897 
00898        QVBoxLayout* vl=new QVBoxLayout(&dialog);
00899        QPlainTextEdit* te=new QPlainTextEdit();
00900        te->setPlainText(s);
00901        te->setReadOnly(true);
00902        QPushButton* pb=new QPushButton(tr("OK"));
00903 
00904        QHBoxLayout* hl=new QHBoxLayout(0);
00905        hl->addStretch(1);
00906        hl->addWidget(pb);
00907 
00908        vl->addWidget(te);
00909        vl->addLayout(hl);
00910        connect(pb, SIGNAL(clicked()), &dialog, SLOT(close()));
00911 
00912        dialog.resize(700,500);
00913        centerWidgetOnScreen(&dialog);
00914        restoreFETDialogGeometry(&dialog, settingsName);
00915 
00916        setParentAndOtherThings(&dialog, this);
00917        dialog.exec();
00918        saveFETDialogGeometry(&dialog, settingsName);
00919 }
00920 
00921 void TimetableGenerateForm::seeInitialOrder()
00922 {
00923        QString s=initialOrderOfActivities;
00924 
00925        //show the message in a dialog
00926        QDialog dialog(this);
00927        
00928        dialog.setWindowTitle(tr("FET - information about initial order of evaluation of activities"));
00929 
00930        QVBoxLayout* vl=new QVBoxLayout(&dialog);
00931        QPlainTextEdit* te=new QPlainTextEdit();
00932        te->setPlainText(s);
00933        te->setReadOnly(true);
00934        QPushButton* pb=new QPushButton(tr("OK"));
00935 
00936        QHBoxLayout* hl=new QHBoxLayout(0);
00937        hl->addStretch(1);
00938        hl->addWidget(pb);
00939 
00940        vl->addWidget(te);
00941        vl->addLayout(hl);
00942        connect(pb, SIGNAL(clicked()), &dialog, SLOT(close()));
00943 
00944        dialog.resize(700,500);
00945        centerWidgetOnScreen(&dialog);
00946        restoreFETDialogGeometry(&dialog, settingsName);
00947 
00948        setParentAndOtherThings(&dialog, this);
00949        dialog.exec();
00950        saveFETDialogGeometry(&dialog, settingsName);
00951 }
00952