Back to index

fet  5.18.0
timetableexport.cpp
Go to the documentation of this file.
00001 /*
00002 File timetableexport.cpp
00003 */
00004 
00005 /***************************************************************************
00006                           timetableexport.cpp  -  description
00007                           -------------------
00008     begin                : Tue Apr 22 2003
00009     copyright            : (C) 2003 by Lalescu Liviu
00010     email                : Please see http://lalescu.ro/liviu/ for details about contacting Liviu Lalescu (in particular, you can find here the e-mail address)
00011  ***************************************************************************/
00012 
00013 /***************************************************************************
00014  *                                                                         *
00015  *   This program is free software; you can redistribute it and/or modify  *
00016  *   it under the terms of the GNU General Public License as published by  *
00017  *   the Free Software Foundation; either version 2 of the License, or     *
00018  *   (at your option) any later version.                                   *
00019  *                                                                         *
00020  ***************************************************************************/
00021 
00022 //**********************************************************************************************************************/
00023 //August 2007
00024 //XHTML generation code by Volker Dirr (timetabling.de)
00025 //Features:   - XHTML 1.0 strict valid
00026 //            - using colspan and rowspan
00027 //            - table of contents with hyperlinks
00028 //            - CSS and JavaScript support
00029 //            - index HTML file
00030 //            - TIMETABLE_HTML_LEVEL
00031 //            - days/time horizontal/vertical
00032 //            - subgroups, groups, years, teachers, rooms, subjects, activities timetable
00033 //            - teachers free periods
00034 //            - daily timetable
00035 //            - activities with same starting time
00036 //            - reorganized functions. now they can be also used for printing
00037 //            - split times tables after X names (TIMETABLE_HTML_SPLIT?) and choose if activity tags should be printed (TIMETABLE_HTML_PRINT_ACTIVITY_TAGS?)
00038 
00039 //TODO: all must be internal here. so maybe also do daysOfTheWeek and hoursPerDay also internal
00040 //maybe TODO: use back_odd and back_even (or back0 and back1, because easier to code!) like in printing. so don't use the table_odd and table_even anymore
00041 //maybe TODO: make printActivityTags as a global setting in FET for html export? (TIMETABLE_HTML_PRINT_ACTIVITY_TAGS?)
00042 //maybe TODO: make TIMETABLE_HTML_SPLIT? (similar to TIMETABLE_HTML_LEVEL)
00043 //maybe TODO: rename augmentedYearsList into internalYearsList to have it similar to others?
00044 //maybe TODO: some "stg" stuff can be replaced by gt.rules.internalGroupsList. I don't want to do that now, because id-s will change. That is not critical, but I want to diff tables with old release.
00045 
00046 #include "timetable_defs.h"
00047 #include "timetable.h"
00048 #include "timetableexport.h"
00049 #include "solution.h"
00050 
00051 #include "matrix.h"
00052 
00053 #include <iostream>
00054 #include <fstream>
00055 using namespace std;
00056 
00057 #include <QString>
00058 #include <QTextStream>
00059 #include <QFile>
00060 
00061 #include <QList>
00062 
00063 #include <QHash>
00064 
00065 #include <QDesktopWidget>
00066 
00067 #include <QMessageBox>
00068 
00069 #include <QLocale>
00070 #include <QTime>
00071 #include <QDate>
00072 
00073 #include <QDir>
00074 
00075 //Represents the current status of the simulation - running or stopped.
00076 extern bool simulation_running;
00077 
00078 extern bool students_schedule_ready;
00079 extern bool teachers_schedule_ready;
00080 extern bool rooms_schedule_ready;
00081 
00082 extern Solution best_solution;
00083 extern bool LANGUAGE_STYLE_RIGHT_TO_LEFT;
00084 extern QString LANGUAGE_FOR_HTML;
00085 
00086 extern Timetable gt;
00087 /*extern qint16 teachers_timetable_weekly[MAX_TEACHERS][MAX_DAYS_PER_WEEK][MAX_HOURS_PER_DAY];
00088 extern qint16 students_timetable_weekly[MAX_TOTAL_SUBGROUPS][MAX_DAYS_PER_WEEK][MAX_HOURS_PER_DAY];
00089 extern qint16 rooms_timetable_weekly[MAX_ROOMS][MAX_DAYS_PER_WEEK][MAX_HOURS_PER_DAY];*/
00090 extern Matrix3D<qint16> teachers_timetable_weekly;
00091 extern Matrix3D<qint16> students_timetable_weekly;
00092 extern Matrix3D<qint16> rooms_timetable_weekly;
00093 
00094 //extern QList<qint16> teachers_free_periods_timetable_weekly[TEACHERS_FREE_PERIODS_N_CATEGORIES][MAX_DAYS_PER_WEEK][MAX_HOURS_PER_DAY];
00095 extern Matrix3D<QList<qint16> > teachers_free_periods_timetable_weekly;
00096 
00097 //extern bool breakDayHour[MAX_DAYS_PER_WEEK][MAX_HOURS_PER_DAY];
00098 extern Matrix2D<bool> breakDayHour;
00099 /*extern bool teacherNotAvailableDayHour[MAX_TEACHERS][MAX_DAYS_PER_WEEK][MAX_HOURS_PER_DAY];
00100 extern double notAllowedRoomTimePercentages[MAX_ROOMS][MAX_HOURS_PER_WEEK];
00101 extern bool subgroupNotAvailableDayHour[MAX_TOTAL_SUBGROUPS][MAX_DAYS_PER_WEEK][MAX_HOURS_PER_DAY];*/
00102 extern Matrix3D<bool> teacherNotAvailableDayHour;
00103 extern Matrix2D<double> notAllowedRoomTimePercentages;
00104 extern Matrix3D<bool> subgroupNotAvailableDayHour;
00105 
00106 static QList<int> activitiesForCurrentSubject[MAX_DAYS_PER_WEEK][MAX_HOURS_PER_DAY];
00107 
00108 static QList<int> activitiesAtTime[MAX_DAYS_PER_WEEK][MAX_HOURS_PER_DAY];
00109 
00110 extern Rules rules2;
00111 
00112 const QString STRING_EMPTY_SLOT="---";
00113 
00114 const QString STRING_SEVERAL_ACTIVITIES_IN_LESS_DETAILED_TABLES="???";
00115 
00116 const QString STRING_NOT_AVAILABLE_TIME_SLOT="-x-";
00117 
00118 const QString STRING_BREAK_SLOT="-X-";
00119 
00120 //these hashes are needed to get the IDs for html and css in timetableexport and statistics
00121 static QHash<QString, QString> hashSubjectIDsTimetable;
00122 static QHash<QString, QString> hashActivityTagIDsTimetable;
00123 static QHash<QString, QString> hashStudentIDsTimetable;
00124 static QHash<QString, QString> hashTeacherIDsTimetable;
00125 static QHash<QString, QString> hashRoomIDsTimetable;
00126 static QHash<QString, QString> hashDayIDsTimetable;
00127 
00128 //this hash is needed to care about sctivities with same starting time
00129 static QHash<int, QList<int> >activitiesWithSameStartingTime;
00130 
00131 //Now the filenames of the output files are following (for xml and all html tables)
00132 const QString SUBGROUPS_TIMETABLE_FILENAME_XML="subgroups.xml";
00133 const QString TEACHERS_TIMETABLE_FILENAME_XML="teachers.xml";
00134 const QString ACTIVITIES_TIMETABLE_FILENAME_XML="activities.xml";
00135 const QString ROOMS_TIMETABLE_FILENAME_XML="rooms.xml";
00136 
00137 const QString CONFLICTS_FILENAME="soft_conflicts.txt";
00138 const QString INDEX_HTML="index.html";
00139 const QString STYLESHEET_CSS="stylesheet.css";
00140 
00141 const QString SUBGROUPS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML="subgroups_days_horizontal.html";
00142 const QString SUBGROUPS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML="subgroups_days_vertical.html";
00143 const QString SUBGROUPS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML="subgroups_time_horizontal.html";
00144 const QString SUBGROUPS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML="subgroups_time_vertical.html";
00145 
00146 const QString GROUPS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML="groups_days_horizontal.html";
00147 const QString GROUPS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML="groups_days_vertical.html";
00148 const QString GROUPS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML="groups_time_horizontal.html";
00149 const QString GROUPS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML="groups_time_vertical.html";
00150 
00151 const QString YEARS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML="years_days_horizontal.html";
00152 const QString YEARS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML="years_days_vertical.html";
00153 const QString YEARS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML="years_time_horizontal.html";
00154 const QString YEARS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML="years_time_vertical.html";
00155 
00156 const QString TEACHERS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML="teachers_days_horizontal.html";
00157 const QString TEACHERS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML="teachers_days_vertical.html";
00158 const QString TEACHERS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML="teachers_time_horizontal.html";
00159 const QString TEACHERS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML="teachers_time_vertical.html";
00160 
00161 const QString ROOMS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML="rooms_days_horizontal.html";
00162 const QString ROOMS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML="rooms_days_vertical.html";
00163 const QString ROOMS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML="rooms_time_horizontal.html";
00164 const QString ROOMS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML="rooms_time_vertical.html";
00165 
00166 const QString SUBJECTS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML="subjects_days_horizontal.html";
00167 const QString SUBJECTS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML="subjects_days_vertical.html";
00168 const QString SUBJECTS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML="subjects_time_horizontal.html";
00169 const QString SUBJECTS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML="subjects_time_vertical.html";
00170 
00171 const QString ALL_ACTIVITIES_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML="activities_days_horizontal.html";
00172 const QString ALL_ACTIVITIES_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML="activities_days_vertical.html";
00173 const QString ALL_ACTIVITIES_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML="activities_time_horizontal.html";
00174 const QString ALL_ACTIVITIES_TIMETABLE_TIME_VERTICAL_FILENAME_HTML="activities_time_vertical.html";
00175 
00176 const QString TEACHERS_FREE_PERIODS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML="teachers_free_periods_days_horizontal.html";
00177 const QString TEACHERS_FREE_PERIODS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML="teachers_free_periods_days_vertical.html";
00178 
00179 const QString MULTIPLE_TIMETABLE_DATA_RESULTS_FILE="data_and_timetable.fet";
00180 
00181 //now the XML tags used for identification of the output file (is that comment correct? it's the old comment)
00182 const QString STUDENTS_TIMETABLE_TAG="Students_Timetable";
00183 const QString TEACHERS_TIMETABLE_TAG="Teachers_Timetable";
00184 const QString ACTIVITIES_TIMETABLE_TAG="Activities_Timetable";
00185 const QString ROOMS_TIMETABLE_TAG="Rooms_Timetable";
00186 
00187 const QString RANDOM_SEED_FILENAME_BEFORE="random_seed_before.txt";
00188 const QString RANDOM_SEED_FILENAME_AFTER="random_seed_after.txt";
00189 
00190 extern int XX;
00191 extern int YY;
00192 
00193 QString generationLocalizedTime=QString(""); //to be used in timetableprintform.cpp
00194 
00195 TimetableExport::TimetableExport()
00196 {
00197 }
00198 
00199 TimetableExport::~TimetableExport()
00200 {
00201 }
00202 
00203 void TimetableExport::getStudentsTimetable(Solution &c){
00204        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
00205 
00206        c.getSubgroupsTimetable(gt.rules, students_timetable_weekly);
00207        best_solution.copy(gt.rules, c);
00208        students_schedule_ready=true;
00209 }
00210 
00211 void TimetableExport::getTeachersTimetable(Solution &c){
00212        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
00213 
00214        c.getTeachersTimetable(gt.rules, teachers_timetable_weekly, teachers_free_periods_timetable_weekly);
00215        best_solution.copy(gt.rules, c);
00216        teachers_schedule_ready=true;
00217 }
00218 
00219 void TimetableExport::getRoomsTimetable(Solution &c){
00220        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
00221 
00222        c.getRoomsTimetable(gt.rules, rooms_timetable_weekly);
00223        best_solution.copy(gt.rules, c);
00224        rooms_schedule_ready=true;
00225 }
00226 
00227 void TimetableExport::getNumberOfPlacedActivities(int& number1, int& number2)
00228 {
00229        number1=0;
00230        for(int i=0; i<gt.rules.nInternalActivities; i++)
00231               if(best_solution.times[i]!=UNALLOCATED_TIME)
00232                      number1++;
00233 
00234        number2=0;
00235        for(int i=0; i<gt.rules.nInternalActivities; i++)
00236               if(best_solution.rooms[i]!=UNALLOCATED_SPACE)
00237                      number2++;
00238 }
00239 
00240 void TimetableExport::writeSimulationResults(QWidget* parent){
00241        QDir dir;
00242        
00243        QString OUTPUT_DIR_TIMETABLES=OUTPUT_DIR+FILE_SEP+"timetables";
00244        
00245        OUTPUT_DIR_TIMETABLES.append(FILE_SEP);
00246        if(INPUT_FILENAME_XML=="")
00247               OUTPUT_DIR_TIMETABLES.append("unnamed");
00248        else{
00249               OUTPUT_DIR_TIMETABLES.append(INPUT_FILENAME_XML.right(INPUT_FILENAME_XML.length()-INPUT_FILENAME_XML.lastIndexOf(FILE_SEP)-1));
00250               if(OUTPUT_DIR_TIMETABLES.right(4)==".fet")
00251                      OUTPUT_DIR_TIMETABLES=OUTPUT_DIR_TIMETABLES.left(OUTPUT_DIR_TIMETABLES.length()-4);
00252               //else if(INPUT_FILENAME_XML!="")
00253               //     cout<<"Minor problem - input file does not end in .fet extension - might be a problem when saving the timetables"<<" (file:"<<__FILE__<<", line:"<<__LINE__<<")"<<endl;
00254        }
00255        OUTPUT_DIR_TIMETABLES.append("-single");
00256        
00257        //make sure that the output directory exists
00258        if(!dir.exists(OUTPUT_DIR_TIMETABLES))
00259               dir.mkpath(OUTPUT_DIR_TIMETABLES);
00260 
00261        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
00262        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
00263        assert(TIMETABLE_HTML_LEVEL>=0);
00264        assert(TIMETABLE_HTML_LEVEL<=6);
00265 
00266        computeHashForIDsTimetable();
00267        computeActivitiesAtTime();
00268        computeActivitiesWithSameStartingTime();
00269 
00270        QString s;
00271        QString bar;
00272        if(INPUT_FILENAME_XML=="")
00273               bar="";
00274        else
00275               bar="_";
00276        QString s2=INPUT_FILENAME_XML.right(INPUT_FILENAME_XML.length()-INPUT_FILENAME_XML.lastIndexOf(FILE_SEP)-1);
00277        if(s2.right(4)==".fet")
00278               s2=s2.left(s2.length()-4);
00279        //else if(INPUT_FILENAME_XML!="")
00280        //     cout<<"Minor problem - input file does not end in .fet extension - might be a problem when saving the timetables"<<" (file:"<<__FILE__<<", line:"<<__LINE__<<")"<<endl;
00281        
00282        //now write the solution in xml files
00283        //subgroups
00284        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBGROUPS_TIMETABLE_FILENAME_XML;
00285        writeSubgroupsTimetableXml(parent, s);
00286        //teachers
00287        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+TEACHERS_TIMETABLE_FILENAME_XML;
00288        writeTeachersTimetableXml(parent, s);
00289        //activities
00290        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ACTIVITIES_TIMETABLE_FILENAME_XML;
00291        writeActivitiesTimetableXml(parent, s);
00292 
00293        //now get the time. TODO: maybe write it in xml too? so do it a few lines earlier!
00294        QDate dat=QDate::currentDate();
00295        QTime tim=QTime::currentTime();
00296        QLocale loc(FET_LANGUAGE);
00297        QString sTime=loc.toString(dat, QLocale::ShortFormat)+" "+loc.toString(tim, QLocale::ShortFormat);
00298        generationLocalizedTime=sTime;
00299        
00300        //now get the number of placed activities. TODO: maybe write it in xml too? so do it a few lines earlier!
00301        int na=0;
00302        int na2=0;
00303        getNumberOfPlacedActivities(na, na2);
00304        
00305        if(na==gt.rules.nInternalActivities && na==na2){
00306               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+MULTIPLE_TIMETABLE_DATA_RESULTS_FILE;
00307               cout<<"Since simulation is complete, FET will write also the timetable data file"<<endl;
00308               writeTimetableDataFile(parent, s);
00309        }
00310        
00311        //write the conflicts in txt mode
00312        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+CONFLICTS_FILENAME;
00313        writeConflictsTxt(parent, s, sTime, na);
00314        
00315        //now write the solution in html files
00316        if(TIMETABLE_HTML_LEVEL>=1){
00317               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+STYLESHEET_CSS;
00318               writeStylesheetCss(parent, s, sTime, na);
00319        }
00320        
00321        //indexHtml
00322        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+INDEX_HTML;
00323        writeIndexHtml(parent, s, sTime, na);
00324        
00325        //subgroups
00326        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBGROUPS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
00327        writeSubgroupsTimetableDaysHorizontalHtml(parent, s, sTime, na);
00328        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBGROUPS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
00329        writeSubgroupsTimetableDaysVerticalHtml(parent, s, sTime, na);
00330        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
00331               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBGROUPS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00332               writeSubgroupsTimetableTimeHorizontalHtml(parent, s, sTime, na);
00333               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBGROUPS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00334               writeSubgroupsTimetableTimeVerticalHtml(parent, s, sTime, na);
00335        } else {
00336               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBGROUPS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00337               writeSubgroupsTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
00338               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBGROUPS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00339               writeSubgroupsTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
00340        }
00341        //groups
00342        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+GROUPS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
00343        writeGroupsTimetableDaysHorizontalHtml(parent, s, sTime, na);
00344        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+GROUPS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
00345        writeGroupsTimetableDaysVerticalHtml(parent, s, sTime, na);
00346        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
00347               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+GROUPS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00348               writeGroupsTimetableTimeHorizontalHtml(parent, s, sTime, na);
00349               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+GROUPS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00350               writeGroupsTimetableTimeVerticalHtml(parent, s, sTime, na);
00351        } else {
00352               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+GROUPS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00353               writeGroupsTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
00354               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+GROUPS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00355               writeGroupsTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
00356        }
00357        //years
00358        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+YEARS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
00359        writeYearsTimetableDaysHorizontalHtml(parent, s, sTime, na);
00360        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+YEARS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
00361        writeYearsTimetableDaysVerticalHtml(parent, s, sTime, na);
00362        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
00363               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+YEARS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00364               writeYearsTimetableTimeHorizontalHtml(parent, s, sTime, na);
00365               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+YEARS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00366               writeYearsTimetableTimeVerticalHtml(parent, s, sTime, na);
00367        } else {
00368               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+YEARS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00369               writeYearsTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
00370               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+YEARS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00371               writeYearsTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
00372        }
00373        //teachers
00374        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+TEACHERS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
00375        writeTeachersTimetableDaysHorizontalHtml(parent, s, sTime, na);
00376        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+TEACHERS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
00377        writeTeachersTimetableDaysVerticalHtml(parent, s, sTime, na);
00378        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
00379               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+TEACHERS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00380               writeTeachersTimetableTimeHorizontalHtml(parent, s, sTime, na);
00381               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+TEACHERS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00382               writeTeachersTimetableTimeVerticalHtml(parent, s, sTime, na);
00383        } else {
00384               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+TEACHERS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00385               writeTeachersTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
00386               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+TEACHERS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00387               writeTeachersTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
00388        }
00389        //rooms
00390        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ROOMS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
00391        writeRoomsTimetableDaysHorizontalHtml(parent, s, sTime, na);
00392        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ROOMS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
00393        writeRoomsTimetableDaysVerticalHtml(parent, s, sTime, na);
00394        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
00395               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ROOMS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00396               writeRoomsTimetableTimeHorizontalHtml(parent, s, sTime, na);
00397               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ROOMS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00398               writeRoomsTimetableTimeVerticalHtml(parent, s, sTime, na);
00399        } else {
00400               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ROOMS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00401               writeRoomsTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
00402               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ROOMS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00403               writeRoomsTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
00404        }
00405        //subjects
00406        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBJECTS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
00407        writeSubjectsTimetableDaysHorizontalHtml(parent, s, sTime, na);
00408        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBJECTS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
00409        writeSubjectsTimetableDaysVerticalHtml(parent, s, sTime, na);
00410        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
00411               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBJECTS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00412               writeSubjectsTimetableTimeHorizontalHtml(parent, s, sTime, na);
00413               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBJECTS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00414               writeSubjectsTimetableTimeVerticalHtml(parent, s, sTime, na);
00415        } else {
00416               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBJECTS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00417               writeSubjectsTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
00418               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBJECTS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00419               writeSubjectsTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
00420        }
00421        //all activities
00422        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ALL_ACTIVITIES_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
00423        writeAllActivitiesTimetableDaysHorizontalHtml(parent, s, sTime, na);
00424        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ALL_ACTIVITIES_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
00425        writeAllActivitiesTimetableDaysVerticalHtml(parent, s, sTime, na);
00426        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
00427               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ALL_ACTIVITIES_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00428               writeAllActivitiesTimetableTimeHorizontalHtml(parent, s, sTime, na);
00429               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ALL_ACTIVITIES_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00430               writeAllActivitiesTimetableTimeVerticalHtml(parent, s, sTime, na);
00431        } else {
00432               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ALL_ACTIVITIES_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00433               writeAllActivitiesTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
00434               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ALL_ACTIVITIES_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00435               writeAllActivitiesTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
00436        }
00437        //teachers free periods
00438        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+TEACHERS_FREE_PERIODS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
00439        writeTeachersFreePeriodsTimetableDaysHorizontalHtml(parent, s, sTime, na);
00440        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+TEACHERS_FREE_PERIODS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
00441        writeTeachersFreePeriodsTimetableDaysVerticalHtml(parent, s, sTime, na);
00442 
00443        hashSubjectIDsTimetable.clear();
00444        hashActivityTagIDsTimetable.clear();
00445        hashStudentIDsTimetable.clear();
00446        hashTeacherIDsTimetable.clear();
00447        hashRoomIDsTimetable.clear();
00448        hashDayIDsTimetable.clear();
00449 
00450        cout<<"Writing simulation results to disk completed successfully"<<endl;
00451 }
00452 
00453 void TimetableExport::writeHighestStageResults(QWidget* parent){
00454        QDir dir;
00455        
00456        QString OUTPUT_DIR_TIMETABLES=OUTPUT_DIR+FILE_SEP+"timetables";
00457        
00458        OUTPUT_DIR_TIMETABLES.append(FILE_SEP);
00459        if(INPUT_FILENAME_XML=="")
00460               OUTPUT_DIR_TIMETABLES.append("unnamed");
00461        else{
00462               OUTPUT_DIR_TIMETABLES.append(INPUT_FILENAME_XML.right(INPUT_FILENAME_XML.length()-INPUT_FILENAME_XML.lastIndexOf(FILE_SEP)-1));
00463               if(OUTPUT_DIR_TIMETABLES.right(4)==".fet")
00464                      OUTPUT_DIR_TIMETABLES=OUTPUT_DIR_TIMETABLES.left(OUTPUT_DIR_TIMETABLES.length()-4);
00465               //else if(INPUT_FILENAME_XML!="")
00466               //     cout<<"Minor problem - input file does not end in .fet extension - might be a problem when saving the timetables"<<" (file:"<<__FILE__<<", line:"<<__LINE__<<")"<<endl;
00467        }
00468        OUTPUT_DIR_TIMETABLES.append("-highest");
00469        
00470        //make sure that the output directory exists
00471        if(!dir.exists(OUTPUT_DIR_TIMETABLES))
00472               dir.mkpath(OUTPUT_DIR_TIMETABLES);
00473 
00474        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
00475        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
00476        assert(TIMETABLE_HTML_LEVEL>=0);
00477        assert(TIMETABLE_HTML_LEVEL<=6);
00478 
00479        computeHashForIDsTimetable();
00480        computeActivitiesAtTime();
00481        computeActivitiesWithSameStartingTime();
00482 
00483        QString s;
00484        QString bar;
00485        if(INPUT_FILENAME_XML=="")
00486               bar="";
00487        else
00488               bar="_";
00489        QString s2=INPUT_FILENAME_XML.right(INPUT_FILENAME_XML.length()-INPUT_FILENAME_XML.lastIndexOf(FILE_SEP)-1);
00490        if(s2.right(4)==".fet")
00491               s2=s2.left(s2.length()-4);
00492        //else if(INPUT_FILENAME_XML!="")
00493        //     cout<<"Minor problem - input file does not end in .fet extension - might be a problem when saving the timetables"<<" (file:"<<__FILE__<<", line:"<<__LINE__<<")"<<endl;
00494        
00495        //now write the solution in xml files
00496        //subgroups
00497        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBGROUPS_TIMETABLE_FILENAME_XML;
00498        writeSubgroupsTimetableXml(parent, s);
00499        //teachers
00500        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+TEACHERS_TIMETABLE_FILENAME_XML;
00501        writeTeachersTimetableXml(parent, s);
00502        //activities
00503        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ACTIVITIES_TIMETABLE_FILENAME_XML;
00504        writeActivitiesTimetableXml(parent, s);
00505 
00506        //now get the time. TODO: maybe write it in xml too? so do it a few lines earlier!
00507        QDate dat=QDate::currentDate();
00508        QTime tim=QTime::currentTime();
00509        QLocale loc(FET_LANGUAGE);
00510        QString sTime=loc.toString(dat, QLocale::ShortFormat)+" "+loc.toString(tim, QLocale::ShortFormat);
00511        generationLocalizedTime=sTime;
00512        
00513        //now get the number of placed activities. TODO: maybe write it in xml too? so do it a few lines earlier!
00514        int na=0;
00515        int na2=0;
00516        getNumberOfPlacedActivities(na, na2);
00517        
00518        if(na==gt.rules.nInternalActivities && na==na2){
00519               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+MULTIPLE_TIMETABLE_DATA_RESULTS_FILE;
00520               cout<<"Since simulation is complete, FET will write also the timetable data file"<<endl;
00521               writeTimetableDataFile(parent, s);
00522        }
00523        
00524        //write the conflicts in txt mode
00525        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+CONFLICTS_FILENAME;
00526        writeConflictsTxt(parent, s, sTime, na);
00527        
00528        //now write the solution in html files
00529        if(TIMETABLE_HTML_LEVEL>=1){
00530               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+STYLESHEET_CSS;
00531               writeStylesheetCss(parent, s, sTime, na);
00532        }
00533        
00534        //indexHtml
00535        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+INDEX_HTML;
00536        writeIndexHtml(parent, s, sTime, na);
00537        
00538        //subgroups
00539        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBGROUPS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
00540        writeSubgroupsTimetableDaysHorizontalHtml(parent, s, sTime, na);
00541        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBGROUPS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
00542        writeSubgroupsTimetableDaysVerticalHtml(parent, s, sTime, na);
00543        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
00544               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBGROUPS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00545               writeSubgroupsTimetableTimeHorizontalHtml(parent, s, sTime, na);
00546               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBGROUPS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00547               writeSubgroupsTimetableTimeVerticalHtml(parent, s, sTime, na);
00548        } else {
00549               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBGROUPS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00550               writeSubgroupsTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
00551               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBGROUPS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00552               writeSubgroupsTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
00553        }
00554        //groups
00555        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+GROUPS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
00556        writeGroupsTimetableDaysHorizontalHtml(parent, s, sTime, na);
00557        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+GROUPS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
00558        writeGroupsTimetableDaysVerticalHtml(parent, s, sTime, na);
00559        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
00560               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+GROUPS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00561               writeGroupsTimetableTimeHorizontalHtml(parent, s, sTime, na);
00562               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+GROUPS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00563               writeGroupsTimetableTimeVerticalHtml(parent, s, sTime, na);
00564        } else {
00565               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+GROUPS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00566               writeGroupsTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
00567               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+GROUPS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00568               writeGroupsTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
00569        }
00570        //years
00571        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+YEARS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
00572        writeYearsTimetableDaysHorizontalHtml(parent, s, sTime, na);
00573        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+YEARS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
00574        writeYearsTimetableDaysVerticalHtml(parent, s, sTime, na);
00575        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
00576               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+YEARS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00577               writeYearsTimetableTimeHorizontalHtml(parent, s, sTime, na);
00578               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+YEARS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00579               writeYearsTimetableTimeVerticalHtml(parent, s, sTime, na);
00580        } else {
00581               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+YEARS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00582               writeYearsTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
00583               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+YEARS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00584               writeYearsTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
00585        }
00586        //teachers
00587        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+TEACHERS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
00588        writeTeachersTimetableDaysHorizontalHtml(parent, s, sTime, na);
00589        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+TEACHERS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
00590        writeTeachersTimetableDaysVerticalHtml(parent, s, sTime, na);
00591        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
00592               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+TEACHERS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00593               writeTeachersTimetableTimeHorizontalHtml(parent, s, sTime, na);
00594               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+TEACHERS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00595               writeTeachersTimetableTimeVerticalHtml(parent, s, sTime, na);
00596        } else {
00597               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+TEACHERS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00598               writeTeachersTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
00599               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+TEACHERS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00600               writeTeachersTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
00601        }
00602        //rooms
00603        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ROOMS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
00604        writeRoomsTimetableDaysHorizontalHtml(parent, s, sTime, na);
00605        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ROOMS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
00606        writeRoomsTimetableDaysVerticalHtml(parent, s, sTime, na);
00607        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
00608               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ROOMS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00609               writeRoomsTimetableTimeHorizontalHtml(parent, s, sTime, na);
00610               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ROOMS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00611               writeRoomsTimetableTimeVerticalHtml(parent, s, sTime, na);
00612        } else {
00613               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ROOMS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00614               writeRoomsTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
00615               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ROOMS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00616               writeRoomsTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
00617        }
00618        //subjects
00619        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBJECTS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
00620        writeSubjectsTimetableDaysHorizontalHtml(parent, s, sTime, na);
00621        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBJECTS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
00622        writeSubjectsTimetableDaysVerticalHtml(parent, s, sTime, na);
00623        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
00624               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBJECTS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00625               writeSubjectsTimetableTimeHorizontalHtml(parent, s, sTime, na);
00626               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBJECTS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00627               writeSubjectsTimetableTimeVerticalHtml(parent, s, sTime, na);
00628        } else {
00629               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBJECTS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00630               writeSubjectsTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
00631               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+SUBJECTS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00632               writeSubjectsTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
00633        }
00634        //all activities
00635        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ALL_ACTIVITIES_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
00636        writeAllActivitiesTimetableDaysHorizontalHtml(parent, s, sTime, na);
00637        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ALL_ACTIVITIES_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
00638        writeAllActivitiesTimetableDaysVerticalHtml(parent, s, sTime, na);
00639        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
00640               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ALL_ACTIVITIES_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00641               writeAllActivitiesTimetableTimeHorizontalHtml(parent, s, sTime, na);
00642               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ALL_ACTIVITIES_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00643               writeAllActivitiesTimetableTimeVerticalHtml(parent, s, sTime, na);
00644        } else {
00645               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ALL_ACTIVITIES_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
00646               writeAllActivitiesTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
00647               s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+ALL_ACTIVITIES_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
00648               writeAllActivitiesTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
00649        }
00650        //teachers free periods
00651        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+TEACHERS_FREE_PERIODS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
00652        writeTeachersFreePeriodsTimetableDaysHorizontalHtml(parent, s, sTime, na);
00653        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+TEACHERS_FREE_PERIODS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
00654        writeTeachersFreePeriodsTimetableDaysVerticalHtml(parent, s, sTime, na);
00655 
00656        hashSubjectIDsTimetable.clear();
00657        hashActivityTagIDsTimetable.clear();
00658        hashStudentIDsTimetable.clear();
00659        hashTeacherIDsTimetable.clear();
00660        hashRoomIDsTimetable.clear();
00661        hashDayIDsTimetable.clear();
00662 
00663        cout<<"Writing highest stage results to disk completed successfully"<<endl;
00664 }
00665 
00666 void TimetableExport::writeRandomSeed(QWidget* parent, bool before)
00667 {
00668        QString RANDOM_SEED_FILENAME;
00669        if(before)
00670               RANDOM_SEED_FILENAME=RANDOM_SEED_FILENAME_BEFORE;
00671        else
00672               RANDOM_SEED_FILENAME=RANDOM_SEED_FILENAME_AFTER;
00673 
00674        QDir dir;
00675        
00676        QString OUTPUT_DIR_TIMETABLES=OUTPUT_DIR+FILE_SEP+"timetables";
00677        
00678        OUTPUT_DIR_TIMETABLES.append(FILE_SEP);
00679        if(INPUT_FILENAME_XML=="")
00680               OUTPUT_DIR_TIMETABLES.append("unnamed");
00681        else{
00682               OUTPUT_DIR_TIMETABLES.append(INPUT_FILENAME_XML.right(INPUT_FILENAME_XML.length()-INPUT_FILENAME_XML.lastIndexOf(FILE_SEP)-1));
00683               if(OUTPUT_DIR_TIMETABLES.right(4)==".fet")
00684                      OUTPUT_DIR_TIMETABLES=OUTPUT_DIR_TIMETABLES.left(OUTPUT_DIR_TIMETABLES.length()-4);
00685               //else if(INPUT_FILENAME_XML!="")
00686               //     cout<<"Minor problem - input file does not end in .fet extension - might be a problem when saving the timetables"<<" (file:"<<__FILE__<<", line:"<<__LINE__<<")"<<endl;
00687        }
00688        OUTPUT_DIR_TIMETABLES.append("-single");
00689        
00690        //make sure that the output directory exists
00691        if(!dir.exists(OUTPUT_DIR_TIMETABLES))
00692               dir.mkpath(OUTPUT_DIR_TIMETABLES);
00693 
00694        QString s;
00695        QString bar;
00696        if(INPUT_FILENAME_XML=="")
00697               bar="";
00698        else
00699               bar="_";
00700        QString s2=INPUT_FILENAME_XML.right(INPUT_FILENAME_XML.length()-INPUT_FILENAME_XML.lastIndexOf(FILE_SEP)-1);
00701        if(s2.right(4)==".fet")
00702               s2=s2.left(s2.length()-4);
00703 
00704        s=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+bar+RANDOM_SEED_FILENAME;
00705        
00706        writeRandomSeedFile(parent, s, before);
00707 }
00708 
00709 void TimetableExport::writeRandomSeedFile(QWidget* parent, const QString& filename, bool before)
00710 {
00711        QString s=filename;
00712 
00713        QFile file(s);
00714        if(!file.open(QIODevice::WriteOnly)){
00715               QMessageBox::critical(parent, tr("FET critical"),
00716                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(s));
00717               return;
00718               assert(0);
00719        }
00720        QTextStream tos(&file);
00721        tos.setCodec("UTF-8");
00722        tos.setGenerateByteOrderMark(true);
00723 
00724        QDate dat=QDate::currentDate();
00725        QTime tim=QTime::currentTime();
00726        QLocale loc(FET_LANGUAGE);
00727        QString sTime=loc.toString(dat, QLocale::ShortFormat)+" "+loc.toString(tim, QLocale::ShortFormat);
00728        
00729        if(before){
00730               tos<<tr("Generation started on: %1", "%1 is the time").arg(sTime);
00731               tos<<endl<<endl;
00732               tos<<tr("Random seed at the start of generation is: X=%1, Y=%2", "The random seed has two components, X and Y").arg(XX).arg(YY);
00733               tos<<endl<<endl;
00734               tos<<tr("This file was automatically generated by FET %1.").arg(FET_VERSION);
00735               tos<<endl;
00736        }
00737        else{
00738               tos<<tr("Generation ended on: %1", "%1 is the time").arg(sTime);
00739               tos<<endl<<endl;
00740               tos<<tr("Random seed at the end of generation is: X=%1, Y=%2", "The random seed has two components, X and Y").arg(XX).arg(YY);
00741               tos<<endl<<endl;
00742               tos<<tr("This file was automatically generated by FET %1.").arg(FET_VERSION);
00743               tos<<endl;
00744        }
00745        
00746        if(file.error()>0){
00747               QMessageBox::critical(parent, tr("FET critical"),
00748                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(s).arg(file.error()));
00749        }
00750        file.close();
00751 }
00752 
00753 void TimetableExport::writeTimetableDataFile(QWidget* parent, const QString& filename){
00754        if(!students_schedule_ready || !teachers_schedule_ready || !rooms_schedule_ready){
00755               QMessageBox::critical(parent, tr("FET - Critical"), tr("Timetable not generated - cannot save it - this should not happen (please report bug)"));
00756               return;       
00757        }
00758 
00759        Solution* tc=&best_solution;
00760 
00761        for(int ai=0; ai<gt.rules.nInternalActivities; ai++){
00762               //Activity* act=&gt.rules.internalActivitiesList[ai];
00763               int time=tc->times[ai];
00764               if(time==UNALLOCATED_TIME){
00765                      QMessageBox::critical(parent, tr("FET - Critical"), tr("Incomplete timetable - this should not happen - please report bug"));
00766                      return;       
00767               }
00768               
00769               int ri=tc->rooms[ai];
00770               if(ri==UNALLOCATED_SPACE){
00771                      QMessageBox::critical(parent, tr("FET - Critical"), tr("Incomplete timetable - this should not happen - please report bug"));
00772                      return;       
00773               }
00774        }
00775        
00776        rules2.initialized=true;
00777        
00778        rules2.institutionName=gt.rules.institutionName;
00779        rules2.comments=gt.rules.comments;
00780        
00781        rules2.nHoursPerDay=gt.rules.nHoursPerDay;
00782        for(int i=0; i<gt.rules.nHoursPerDay; i++)
00783               rules2.hoursOfTheDay[i]=gt.rules.hoursOfTheDay[i];
00784 
00785        rules2.nDaysPerWeek=gt.rules.nDaysPerWeek;
00786        for(int i=0; i<gt.rules.nDaysPerWeek; i++)
00787               rules2.daysOfTheWeek[i]=gt.rules.daysOfTheWeek[i];
00788               
00789        rules2.yearsList=gt.rules.yearsList;
00790        
00791        rules2.teachersList=gt.rules.teachersList;
00792        
00793        rules2.subjectsList=gt.rules.subjectsList;
00794        
00795        rules2.activityTagsList=gt.rules.activityTagsList;
00796 
00797        rules2.activitiesList=gt.rules.activitiesList;
00798 
00799        rules2.buildingsList=gt.rules.buildingsList;
00800 
00801        rules2.roomsList=gt.rules.roomsList;
00802 
00803        rules2.timeConstraintsList=gt.rules.timeConstraintsList;
00804        
00805        rules2.spaceConstraintsList=gt.rules.spaceConstraintsList;
00806 
00807 
00808        //add locking constraints
00809        TimeConstraintsList lockTimeConstraintsList;
00810        SpaceConstraintsList lockSpaceConstraintsList;
00811 
00812 
00813        bool report=false;
00814        
00815        int addedTime=0, duplicatesTime=0;
00816        int addedSpace=0, duplicatesSpace=0;
00817 
00818        //lock selected activities
00819        for(int ai=0; ai<gt.rules.nInternalActivities; ai++){
00820               Activity* act=&gt.rules.internalActivitiesList[ai];
00821               int time=tc->times[ai];
00822               if(time>=0 && time<gt.rules.nDaysPerWeek*gt.rules.nHoursPerDay){
00823                      int hour=time/gt.rules.nDaysPerWeek;
00824                      int day=time%gt.rules.nDaysPerWeek;
00825 
00826                      ConstraintActivityPreferredStartingTime* ctr=new ConstraintActivityPreferredStartingTime(100.0, act->id, day, hour, false); //permanently locked is false
00827                      bool t=rules2.addTimeConstraint(ctr);
00828                                           
00829                      if(t){
00830                             addedTime++;
00831                             lockTimeConstraintsList.append(ctr);
00832                      }
00833                      else
00834                             duplicatesTime++;
00835 
00836                      QString s;
00837                                           
00838                      if(t)
00839                             s=tr("Added the following constraint to saved file:")+"\n"+ctr->getDetailedDescription(gt.rules);
00840                      else{
00841                             s=tr("Constraint\n%1 NOT added to saved file - duplicate").arg(ctr->getDetailedDescription(gt.rules));
00842                             delete ctr;
00843                      }
00844                                           
00845                      if(report){
00846                             int k;
00847                             if(t)
00848                                    k=QMessageBox::information(parent, tr("FET information"), s,
00849                                     tr("Skip information"), tr("See next"), QString(), 1, 0 );
00850                             else
00851                                    k=QMessageBox::warning(parent, tr("FET warning"), s,
00852                                     tr("Skip information"), tr("See next"), QString(), 1, 0 );
00853                             if(k==0)
00854                                    report=false;
00855                      }
00856               }
00857                                    
00858               int ri=tc->rooms[ai];
00859               if(ri!=UNALLOCATED_SPACE && ri!=UNSPECIFIED_ROOM && ri>=0 && ri<gt.rules.nInternalRooms){
00860                      ConstraintActivityPreferredRoom* ctr=new ConstraintActivityPreferredRoom(100, act->id, (gt.rules.internalRoomsList[ri])->name, false); //permanently locked is false
00861                      bool t=rules2.addSpaceConstraint(ctr);
00862 
00863                      QString s;
00864                                           
00865                      if(t){
00866                             addedSpace++;
00867                             lockSpaceConstraintsList.append(ctr);
00868                      }
00869                      else
00870                             duplicatesSpace++;
00871 
00872                      if(t)
00873                             s=tr("Added the following constraint to saved file:")+"\n"+ctr->getDetailedDescription(gt.rules);
00874                      else{
00875                             s=tr("Constraint\n%1 NOT added to saved file - duplicate").arg(ctr->getDetailedDescription(gt.rules));
00876                             delete ctr;
00877                      }
00878                                           
00879                      if(report){
00880                             int k;
00881                             if(t)
00882                                    k=QMessageBox::information(parent, tr("FET information"), s,
00883                                     tr("Skip information"), tr("See next"), QString(), 1, 0 );
00884                             else
00885                                    k=QMessageBox::warning(parent, tr("FET warning"), s,
00886                                     tr("Skip information"), tr("See next"), QString(), 1, 0 );
00887                             if(k==0)
00888                                    report=false;
00889                      }
00890               }
00891        }
00892 
00893        //QMessageBox::information(parent, tr("FET information"), tr("Added %1 locking time constraints and %2 locking space constraints to saved file,"
00894        // " ignored %3 activities which were already fixed in time and %4 activities which were already fixed in space").arg(addedTime).arg(addedSpace).arg(duplicatesTime).arg(duplicatesSpace));
00895               
00896        bool result=rules2.write(parent, filename);
00897        
00898        while(!lockTimeConstraintsList.isEmpty())
00899               delete lockTimeConstraintsList.takeFirst();
00900        while(!lockSpaceConstraintsList.isEmpty())
00901               delete lockSpaceConstraintsList.takeFirst();
00902 
00903        //if(result)  
00904        //     QMessageBox::information(parent, tr("FET information"),
00905        //            tr("File saved successfully. You can see it on the hard disk. Current data file remained untouched (of locking constraints),"
00906        //            " so you can save it also, or generate different timetables."));
00907 
00908        rules2.nHoursPerDay=0;
00909        rules2.nDaysPerWeek=0;
00910 
00911        rules2.yearsList.clear();
00912        
00913        rules2.teachersList.clear();
00914        
00915        rules2.subjectsList.clear();
00916        
00917        rules2.activityTagsList.clear();
00918 
00919        rules2.activitiesList.clear();
00920 
00921        rules2.buildingsList.clear();
00922 
00923        rules2.roomsList.clear();
00924 
00925        rules2.timeConstraintsList.clear();
00926        
00927        rules2.spaceConstraintsList.clear();
00928        
00929        if(!result){
00930               QMessageBox::critical(parent, tr("FET critical"), tr("Could not save the data + timetable file on the hard disk - maybe hard disk is full"));
00931        }
00932 }
00933 
00934 void TimetableExport::writeSimulationResults(QWidget* parent, int n){
00935        QDir dir;
00936        
00937        QString OUTPUT_DIR_TIMETABLES=OUTPUT_DIR+FILE_SEP+"timetables";
00938 
00939        //make sure that the output directory exists
00940        if(!dir.exists(OUTPUT_DIR_TIMETABLES))
00941               dir.mkpath(OUTPUT_DIR_TIMETABLES);
00942 
00943        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
00944        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
00945        assert(TIMETABLE_HTML_LEVEL>=0);
00946        assert(TIMETABLE_HTML_LEVEL<=6);
00947 
00948        computeHashForIDsTimetable();
00949        computeActivitiesAtTime();
00950        computeActivitiesWithSameStartingTime();
00951 
00952        QString s;
00953        QString s2=INPUT_FILENAME_XML.right(INPUT_FILENAME_XML.length()-INPUT_FILENAME_XML.lastIndexOf(FILE_SEP)-1);
00954        if(s2.right(4)==".fet")
00955               s2=s2.left(s2.length()-4);
00956        //else if(INPUT_FILENAME_XML!="")
00957        //     cout<<"Minor problem - input file does not end in .fet extension - might be a problem when saving the timetables"<<" (file:"<<__FILE__<<", line:"<<__LINE__<<")"<<endl;
00958        
00959        QString destDir=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+"-multi";
00960        
00961        if(!dir.exists(destDir))
00962               dir.mkpath(destDir);
00963               
00964        QString finalDestDir=destDir+FILE_SEP+CustomFETString::number(n);
00965 
00966        if(!dir.exists(finalDestDir))
00967               dir.mkpath(finalDestDir);
00968               
00969        finalDestDir+=FILE_SEP;
00970 
00971 
00972        QString s3=INPUT_FILENAME_XML.right(INPUT_FILENAME_XML.length()-INPUT_FILENAME_XML.lastIndexOf(FILE_SEP)-1);
00973 
00974        if(s3.right(4)==".fet")
00975               s3=s3.left(s3.length()-4);
00976        //else if(INPUT_FILENAME_XML!="")
00977        //     cout<<"Minor problem - input file does not end in .fet extension - might be a problem when saving the timetables"<<" (file:"<<__FILE__<<", line:"<<__LINE__<<")"<<endl;
00978 
00979        finalDestDir+=s3+"_";
00980        
00981        //write data+timetable in .fet format
00982        writeTimetableDataFile(parent, finalDestDir+MULTIPLE_TIMETABLE_DATA_RESULTS_FILE);
00983 
00984        //now write the solution in xml files
00985        //subgroups
00986        s=finalDestDir+SUBGROUPS_TIMETABLE_FILENAME_XML;
00987        writeSubgroupsTimetableXml(parent, s);
00988        //teachers
00989        s=finalDestDir+TEACHERS_TIMETABLE_FILENAME_XML;
00990        writeTeachersTimetableXml(parent, s);
00991        //activities
00992        s=finalDestDir+ACTIVITIES_TIMETABLE_FILENAME_XML;
00993        writeActivitiesTimetableXml(parent, s);
00994 
00995        //now get the time. TODO: maybe write it in xml too? so do it a few lines earlier!
00996        QDate dat=QDate::currentDate();
00997        QTime tim=QTime::currentTime();
00998        QLocale loc(FET_LANGUAGE);
00999        QString sTime=loc.toString(dat, QLocale::ShortFormat)+" "+loc.toString(tim, QLocale::ShortFormat);
01000        generationLocalizedTime=sTime;
01001 
01002        //now get the number of placed activities. TODO: maybe write it in xml too? so do it a few lines earlier!
01003        int na=0;
01004        int na2=0;
01005        getNumberOfPlacedActivities(na, na2);
01006        
01007        //write the conflicts in txt mode
01008        s=finalDestDir+CONFLICTS_FILENAME;
01009        writeConflictsTxt(parent, s, sTime, na);
01010        
01011        //now write the solution in html files
01012        if(TIMETABLE_HTML_LEVEL>=1){
01013               s=finalDestDir+STYLESHEET_CSS;
01014               writeStylesheetCss(parent, s, sTime, na);
01015        }
01016        //indexHtml
01017        s=finalDestDir+INDEX_HTML;
01018        writeIndexHtml(parent, s, sTime, na);
01019        //subgroups
01020        s=finalDestDir+SUBGROUPS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
01021        writeSubgroupsTimetableDaysHorizontalHtml(parent, s, sTime, na);
01022        s=finalDestDir+SUBGROUPS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
01023        writeSubgroupsTimetableDaysVerticalHtml(parent, s, sTime, na);
01024        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
01025               s=finalDestDir+SUBGROUPS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01026               writeSubgroupsTimetableTimeHorizontalHtml(parent, s, sTime, na);
01027               s=finalDestDir+SUBGROUPS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01028               writeSubgroupsTimetableTimeVerticalHtml(parent, s, sTime, na);
01029        } else {
01030               s=finalDestDir+SUBGROUPS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01031               writeSubgroupsTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
01032               s=finalDestDir+SUBGROUPS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01033               writeSubgroupsTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
01034        }
01035        //groups
01036        s=finalDestDir+GROUPS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
01037        writeGroupsTimetableDaysHorizontalHtml(parent, s, sTime, na);
01038        s=finalDestDir+GROUPS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
01039        writeGroupsTimetableDaysVerticalHtml(parent, s, sTime, na);
01040        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
01041               s=finalDestDir+GROUPS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01042               writeGroupsTimetableTimeHorizontalHtml(parent, s, sTime, na);
01043               s=finalDestDir+GROUPS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01044               writeGroupsTimetableTimeVerticalHtml(parent, s, sTime, na);
01045        } else {
01046               s=finalDestDir+GROUPS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01047               writeGroupsTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
01048               s=finalDestDir+GROUPS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01049               writeGroupsTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
01050        }
01051        //years
01052        s=finalDestDir+YEARS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
01053        writeYearsTimetableDaysHorizontalHtml(parent, s, sTime, na);
01054        s=finalDestDir+YEARS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
01055        writeYearsTimetableDaysVerticalHtml(parent, s, sTime, na);
01056        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
01057               s=finalDestDir+YEARS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01058               writeYearsTimetableTimeHorizontalHtml(parent, s, sTime, na);
01059               s=finalDestDir+YEARS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01060               writeYearsTimetableTimeVerticalHtml(parent, s, sTime, na);
01061        } else {
01062               s=finalDestDir+YEARS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01063               writeYearsTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
01064               s=finalDestDir+YEARS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01065               writeYearsTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
01066        }
01067        //teachers
01068        s=finalDestDir+TEACHERS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
01069        writeTeachersTimetableDaysHorizontalHtml(parent, s, sTime, na);
01070        s=finalDestDir+TEACHERS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
01071        writeTeachersTimetableDaysVerticalHtml(parent, s, sTime, na);
01072        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
01073               s=finalDestDir+TEACHERS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01074               writeTeachersTimetableTimeHorizontalHtml(parent, s, sTime, na);
01075               s=finalDestDir+TEACHERS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01076               writeTeachersTimetableTimeVerticalHtml(parent, s, sTime, na);
01077        } else {
01078               s=finalDestDir+TEACHERS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01079               writeTeachersTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
01080               s=finalDestDir+TEACHERS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01081               writeTeachersTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
01082        }
01083        //rooms
01084        s=finalDestDir+ROOMS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
01085        writeRoomsTimetableDaysHorizontalHtml(parent, s, sTime, na);
01086        s=finalDestDir+ROOMS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
01087        writeRoomsTimetableDaysVerticalHtml(parent, s, sTime, na);
01088        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
01089               s=finalDestDir+ROOMS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01090               writeRoomsTimetableTimeHorizontalHtml(parent, s, sTime, na);
01091               s=finalDestDir+ROOMS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01092               writeRoomsTimetableTimeVerticalHtml(parent, s, sTime, na);
01093        } else {
01094               s=finalDestDir+ROOMS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01095               writeRoomsTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
01096               s=finalDestDir+ROOMS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01097               writeRoomsTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
01098        }
01099        //subjects
01100        s=finalDestDir+SUBJECTS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
01101        writeSubjectsTimetableDaysHorizontalHtml(parent, s, sTime, na);
01102        s=finalDestDir+SUBJECTS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
01103        writeSubjectsTimetableDaysVerticalHtml(parent, s, sTime, na);
01104        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
01105               s=finalDestDir+SUBJECTS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01106               writeSubjectsTimetableTimeHorizontalHtml(parent, s, sTime, na);
01107               s=finalDestDir+SUBJECTS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01108               writeSubjectsTimetableTimeVerticalHtml(parent, s, sTime, na);
01109        } else {
01110               s=finalDestDir+SUBJECTS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01111               writeSubjectsTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
01112               s=finalDestDir+SUBJECTS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01113               writeSubjectsTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
01114        }
01115        //all activities
01116        s=finalDestDir+ALL_ACTIVITIES_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
01117        writeAllActivitiesTimetableDaysHorizontalHtml(parent, s, sTime, na);
01118        s=finalDestDir+ALL_ACTIVITIES_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
01119        writeAllActivitiesTimetableDaysVerticalHtml(parent, s, sTime, na);
01120        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
01121               s=finalDestDir+ALL_ACTIVITIES_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01122               writeAllActivitiesTimetableTimeHorizontalHtml(parent, s, sTime, na);
01123               s=finalDestDir+ALL_ACTIVITIES_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01124               writeAllActivitiesTimetableTimeVerticalHtml(parent, s, sTime, na);
01125        } else {
01126               s=finalDestDir+ALL_ACTIVITIES_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01127               writeAllActivitiesTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
01128               s=finalDestDir+ALL_ACTIVITIES_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01129               writeAllActivitiesTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
01130        }
01131        //teachers free periods
01132        s=finalDestDir+TEACHERS_FREE_PERIODS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
01133        writeTeachersFreePeriodsTimetableDaysHorizontalHtml(parent, s, sTime, na);
01134        s=finalDestDir+TEACHERS_FREE_PERIODS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
01135        writeTeachersFreePeriodsTimetableDaysVerticalHtml(parent, s, sTime, na);
01136        
01137        hashSubjectIDsTimetable.clear();
01138        hashActivityTagIDsTimetable.clear();
01139        hashStudentIDsTimetable.clear();
01140        hashTeacherIDsTimetable.clear();
01141        hashRoomIDsTimetable.clear();
01142        hashDayIDsTimetable.clear();
01143 
01144        cout<<"Writing multiple simulation results to disk completed successfully"<<endl;
01145 }
01146 
01147 void TimetableExport::writeRandomSeed(QWidget* parent, int n, bool before){
01148        QString RANDOM_SEED_FILENAME;
01149        if(before)
01150               RANDOM_SEED_FILENAME=RANDOM_SEED_FILENAME_BEFORE;
01151        else
01152               RANDOM_SEED_FILENAME=RANDOM_SEED_FILENAME_AFTER;
01153 
01154        QDir dir;
01155        
01156        QString OUTPUT_DIR_TIMETABLES=OUTPUT_DIR+FILE_SEP+"timetables";
01157 
01158        //make sure that the output directory exists
01159        if(!dir.exists(OUTPUT_DIR_TIMETABLES))
01160               dir.mkpath(OUTPUT_DIR_TIMETABLES);
01161 
01162        QString s;
01163        QString s2=INPUT_FILENAME_XML.right(INPUT_FILENAME_XML.length()-INPUT_FILENAME_XML.lastIndexOf(FILE_SEP)-1);
01164        if(s2.right(4)==".fet")
01165               s2=s2.left(s2.length()-4);
01166        //else if(INPUT_FILENAME_XML!="")
01167        //     cout<<"Minor problem - input file does not end in .fet extension - might be a problem when saving the timetables"<<" (file:"<<__FILE__<<", line:"<<__LINE__<<")"<<endl;
01168        
01169        QString destDir=OUTPUT_DIR_TIMETABLES+FILE_SEP+s2+"-multi";
01170        
01171        if(!dir.exists(destDir))
01172               dir.mkpath(destDir);
01173               
01174        QString finalDestDir=destDir+FILE_SEP+CustomFETString::number(n);
01175 
01176        if(!dir.exists(finalDestDir))
01177               dir.mkpath(finalDestDir);
01178               
01179        finalDestDir+=FILE_SEP;
01180 
01181        QString s3=INPUT_FILENAME_XML.right(INPUT_FILENAME_XML.length()-INPUT_FILENAME_XML.lastIndexOf(FILE_SEP)-1);
01182 
01183        if(s3.right(4)==".fet")
01184               s3=s3.left(s3.length()-4);
01185        //else if(INPUT_FILENAME_XML!="")
01186        //     cout<<"Minor problem - input file does not end in .fet extension - might be a problem when saving the timetables"<<" (file:"<<__FILE__<<", line:"<<__LINE__<<")"<<endl;
01187 
01188        finalDestDir+=s3+"_";
01189        
01190        s=finalDestDir+RANDOM_SEED_FILENAME;
01191 
01192        writeRandomSeedFile(parent, s, before);
01193 }
01194 
01195 void TimetableExport::writeSimulationResultsCommandLine(QWidget* parent, const QString& outputDirectory){ //outputDirectory contains trailing FILE_SEP
01196        QString add=INPUT_FILENAME_XML.right(INPUT_FILENAME_XML.length()-INPUT_FILENAME_XML.lastIndexOf(FILE_SEP)-1);
01197        if(add.right(4)==".fet")
01198               add=add.left(add.length()-4);
01199        //else if(INPUT_FILENAME_XML!="")
01200        //     cout<<"Minor problem - input file does not end in .fet extension - might be a problem when saving the timetables"<<" (file:"<<__FILE__<<", line:"<<__LINE__<<")"<<endl;
01201 
01202        if(add!="")
01203               add.append("_");
01204 
01206 
01207        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
01208        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
01209        assert(TIMETABLE_HTML_LEVEL>=0);
01210        assert(TIMETABLE_HTML_LEVEL<=6);
01211 
01212        computeHashForIDsTimetable();
01213        computeActivitiesAtTime();
01214        computeActivitiesWithSameStartingTime();
01215 
01216        TimetableExport::writeSubgroupsTimetableXml(parent, outputDirectory+add+SUBGROUPS_TIMETABLE_FILENAME_XML);
01217        TimetableExport::writeTeachersTimetableXml(parent, outputDirectory+add+TEACHERS_TIMETABLE_FILENAME_XML);
01218        TimetableExport::writeActivitiesTimetableXml(parent, outputDirectory+add+ACTIVITIES_TIMETABLE_FILENAME_XML);
01219        
01220        //get the time
01221        QDate dat=QDate::currentDate();
01222        QTime tim=QTime::currentTime();
01223        QLocale loc(FET_LANGUAGE);
01224        QString sTime=loc.toString(dat, QLocale::ShortFormat)+" "+loc.toString(tim, QLocale::ShortFormat);
01225        generationLocalizedTime=sTime; //really unneeded, but just to be similar to the other parts
01226        
01227        //now get the number of placed activities. TODO: maybe write it in xml too? so do it a few lines earlier!
01228        int na=0;
01229        int na2=0;
01230        getNumberOfPlacedActivities(na, na2);
01231        
01232        if(na==gt.rules.nInternalActivities && na==na2){
01233               QString s=outputDirectory+add+MULTIPLE_TIMETABLE_DATA_RESULTS_FILE;
01234               cout<<"Since simulation is complete, FET will write also the timetable data file"<<endl;
01235               writeTimetableDataFile(parent, s);
01236        }
01237 
01238        //write the conflicts in txt mode
01239        QString s=add+CONFLICTS_FILENAME;
01240        s.prepend(outputDirectory);
01241        TimetableExport::writeConflictsTxt(parent, s, sTime, na);
01242        
01243        //now write the solution in html files
01244        if(TIMETABLE_HTML_LEVEL>=1){
01245               s=add+STYLESHEET_CSS;
01246               s.prepend(outputDirectory);
01247               TimetableExport::writeStylesheetCss(parent, s, sTime, na);
01248        }
01249        //indexHtml
01250        s=add+INDEX_HTML;
01251        s.prepend(outputDirectory);
01252        writeIndexHtml(parent, s, sTime, na);
01253        //subgroups
01254        s=add+SUBGROUPS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
01255        s.prepend(outputDirectory);
01256        TimetableExport::writeSubgroupsTimetableDaysHorizontalHtml(parent, s, sTime, na);
01257        s=add+SUBGROUPS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
01258        s.prepend(outputDirectory);
01259        TimetableExport::writeSubgroupsTimetableDaysVerticalHtml(parent, s, sTime, na);
01260        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
01261               s=add+SUBGROUPS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01262               s.prepend(outputDirectory);
01263               TimetableExport::writeSubgroupsTimetableTimeHorizontalHtml(parent, s, sTime, na);
01264               s=add+SUBGROUPS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01265               s.prepend(outputDirectory);
01266               TimetableExport::writeSubgroupsTimetableTimeVerticalHtml(parent, s, sTime, na);
01267        } else {
01268               s=add+SUBGROUPS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01269               s.prepend(outputDirectory);
01270               TimetableExport::writeSubgroupsTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
01271               s=add+SUBGROUPS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01272               s.prepend(outputDirectory);
01273               TimetableExport::writeSubgroupsTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
01274        }
01275        //groups
01276        s=add+GROUPS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
01277        s.prepend(outputDirectory);
01278        TimetableExport::writeGroupsTimetableDaysHorizontalHtml(parent, s, sTime, na);
01279        s=add+GROUPS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
01280        s.prepend(outputDirectory);
01281        TimetableExport::writeGroupsTimetableDaysVerticalHtml(parent, s, sTime, na);
01282        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
01283               s=add+GROUPS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01284               s.prepend(outputDirectory);
01285               TimetableExport::writeGroupsTimetableTimeHorizontalHtml(parent, s, sTime, na);
01286               s=add+GROUPS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01287               s.prepend(outputDirectory);
01288               TimetableExport::writeGroupsTimetableTimeVerticalHtml(parent, s, sTime, na);
01289        } else {
01290               s=add+GROUPS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01291               s.prepend(outputDirectory);
01292               TimetableExport::writeGroupsTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
01293               s=add+GROUPS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01294               s.prepend(outputDirectory);
01295               TimetableExport::writeGroupsTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
01296        }
01297        //years
01298        s=add+YEARS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
01299        s.prepend(outputDirectory);
01300        TimetableExport::writeYearsTimetableDaysHorizontalHtml(parent, s, sTime, na);
01301        s=add+YEARS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
01302        s.prepend(outputDirectory);
01303        TimetableExport::writeYearsTimetableDaysVerticalHtml(parent, s, sTime, na);
01304        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
01305               s=add+YEARS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01306               s.prepend(outputDirectory);
01307               TimetableExport::writeYearsTimetableTimeHorizontalHtml(parent, s, sTime, na);
01308               s=add+YEARS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01309               s.prepend(outputDirectory);
01310               TimetableExport::writeYearsTimetableTimeVerticalHtml(parent, s, sTime, na);
01311        } else {
01312               s=add+YEARS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01313               s.prepend(outputDirectory);
01314               TimetableExport::writeYearsTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
01315               s=add+YEARS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01316               s.prepend(outputDirectory);
01317               TimetableExport::writeYearsTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
01318        }
01319        //teachers
01320        s=add+TEACHERS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
01321        s.prepend(outputDirectory);
01322        TimetableExport::writeTeachersTimetableDaysHorizontalHtml(parent, s, sTime, na);
01323        s=add+TEACHERS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
01324        s.prepend(outputDirectory);
01325        TimetableExport::writeTeachersTimetableDaysVerticalHtml(parent, s, sTime, na);
01326        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
01327               s=add+TEACHERS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01328               s.prepend(outputDirectory);
01329               TimetableExport::writeTeachersTimetableTimeHorizontalHtml(parent, s, sTime, na);
01330               s=add+TEACHERS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01331               s.prepend(outputDirectory);
01332               TimetableExport::writeTeachersTimetableTimeVerticalHtml(parent, s, sTime, na);
01333        } else {
01334               s=add+TEACHERS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01335               s.prepend(outputDirectory);
01336               TimetableExport::writeTeachersTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
01337               s=add+TEACHERS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01338               s.prepend(outputDirectory);
01339               TimetableExport::writeTeachersTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
01340        }
01341        //rooms
01342        s=add+ROOMS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
01343        s.prepend(outputDirectory);
01344        TimetableExport::writeRoomsTimetableDaysHorizontalHtml(parent, s, sTime, na);
01345        s=add+ROOMS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
01346        s.prepend(outputDirectory);
01347        TimetableExport::writeRoomsTimetableDaysVerticalHtml(parent, s, sTime, na);
01348        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
01349               s=add+ROOMS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01350               s.prepend(outputDirectory);
01351               TimetableExport::writeRoomsTimetableTimeHorizontalHtml(parent, s, sTime, na);
01352               s=add+ROOMS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01353               s.prepend(outputDirectory);
01354               TimetableExport::writeRoomsTimetableTimeVerticalHtml(parent, s, sTime, na);
01355        } else {
01356               s=add+ROOMS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01357               s.prepend(outputDirectory);
01358               TimetableExport::writeRoomsTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
01359               s=add+ROOMS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01360               s.prepend(outputDirectory);
01361               TimetableExport::writeRoomsTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
01362        }
01363        //subjects
01364        s=add+SUBJECTS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
01365        s.prepend(outputDirectory);
01366        TimetableExport::writeSubjectsTimetableDaysHorizontalHtml(parent, s, sTime, na);
01367        s=add+SUBJECTS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
01368        s.prepend(outputDirectory);
01369        TimetableExport::writeSubjectsTimetableDaysVerticalHtml(parent, s, sTime, na);
01370        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
01371               s=add+SUBJECTS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01372               s.prepend(outputDirectory);
01373               TimetableExport::writeSubjectsTimetableTimeHorizontalHtml(parent, s, sTime, na);
01374               s=add+SUBJECTS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01375               s.prepend(outputDirectory);
01376               TimetableExport::writeSubjectsTimetableTimeVerticalHtml(parent, s, sTime, na);
01377        } else {
01378               s=add+SUBJECTS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01379               s.prepend(outputDirectory);
01380               TimetableExport::writeSubjectsTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
01381               s=add+SUBJECTS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01382               s.prepend(outputDirectory);
01383               TimetableExport::writeSubjectsTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
01384        }
01385        //all activities
01386        s=add+ALL_ACTIVITIES_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
01387        s.prepend(outputDirectory);
01388        TimetableExport::writeAllActivitiesTimetableDaysHorizontalHtml(parent, s, sTime, na);
01389        s=add+ALL_ACTIVITIES_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
01390        s.prepend(outputDirectory);
01391        TimetableExport::writeAllActivitiesTimetableDaysVerticalHtml(parent, s, sTime, na);
01392        if(!DIVIDE_HTML_TIMETABLES_WITH_TIME_AXIS_BY_DAYS){
01393               s=add+ALL_ACTIVITIES_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01394               s.prepend(outputDirectory);
01395               TimetableExport::writeAllActivitiesTimetableTimeHorizontalHtml(parent, s, sTime, na);
01396               s=add+ALL_ACTIVITIES_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01397               s.prepend(outputDirectory);
01398               TimetableExport::writeAllActivitiesTimetableTimeVerticalHtml(parent, s, sTime, na);
01399        } else {
01400               s=add+ALL_ACTIVITIES_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML;
01401               s.prepend(outputDirectory);
01402               TimetableExport::writeAllActivitiesTimetableTimeHorizontalDailyHtml(parent, s, sTime, na);
01403               s=add+ALL_ACTIVITIES_TIMETABLE_TIME_VERTICAL_FILENAME_HTML;
01404               s.prepend(outputDirectory);
01405               TimetableExport::writeAllActivitiesTimetableTimeVerticalDailyHtml(parent, s, sTime, na);
01406        }
01407        //teachers free periods
01408        s=add+TEACHERS_FREE_PERIODS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML;
01409        s.prepend(outputDirectory);
01410        TimetableExport::writeTeachersFreePeriodsTimetableDaysHorizontalHtml(parent, s, sTime, na);
01411        s=add+TEACHERS_FREE_PERIODS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML;
01412        s.prepend(outputDirectory);
01413        TimetableExport::writeTeachersFreePeriodsTimetableDaysVerticalHtml(parent, s, sTime, na);
01414 
01415        hashSubjectIDsTimetable.clear();
01416        hashActivityTagIDsTimetable.clear();
01417        hashStudentIDsTimetable.clear();
01418        hashTeacherIDsTimetable.clear();
01419        hashRoomIDsTimetable.clear();
01420        hashDayIDsTimetable.clear();
01421 }
01422 
01423 void TimetableExport::writeRandomSeedCommandLine(QWidget* parent, const QString& outputDirectory, bool before){ //outputDirectory contains trailing FILE_SEP
01424        QString RANDOM_SEED_FILENAME;
01425        if(before)
01426               RANDOM_SEED_FILENAME=RANDOM_SEED_FILENAME_BEFORE;
01427        else
01428               RANDOM_SEED_FILENAME=RANDOM_SEED_FILENAME_AFTER;
01429 
01430        QString add=INPUT_FILENAME_XML.right(INPUT_FILENAME_XML.length()-INPUT_FILENAME_XML.lastIndexOf(FILE_SEP)-1);
01431        if(add.right(4)==".fet")
01432               add=add.left(add.length()-4);
01433        //else if(INPUT_FILENAME_XML!="")
01434        //     cout<<"Minor problem - input file does not end in .fet extension - might be a problem when saving the timetables"<<" (file:"<<__FILE__<<", line:"<<__LINE__<<")"<<endl;
01435 
01436        if(add!="")
01437               add.append("_");
01438 
01439        QString s=add+RANDOM_SEED_FILENAME;
01440        s.prepend(outputDirectory);
01441        
01442        writeRandomSeedFile(parent, s, before);
01443 }
01444 
01445 //by Volker Dirr (timetabling.de)
01446 void TimetableExport::writeConflictsTxt(QWidget* parent, const QString& filename, const QString& saveTime, int placedActivities){
01447        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
01448        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
01449 
01450        QFile file(filename);
01451        if(!file.open(QIODevice::WriteOnly)){
01452               QMessageBox::critical(parent, tr("FET critical"),
01453                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(filename));
01454               return;
01455               assert(0);
01456        }
01457        QTextStream tos(&file);
01458        tos.setCodec("UTF-8");
01459        tos.setGenerateByteOrderMark(true);
01460        
01461        if(placedActivities==gt.rules.nInternalActivities){
01462               QString tt=INPUT_FILENAME_XML.right(INPUT_FILENAME_XML.length()-INPUT_FILENAME_XML.lastIndexOf(FILE_SEP)-1);
01463               if(INPUT_FILENAME_XML=="")
01464                      tt=tr("unnamed");
01465               tos<<TimetableExport::tr("Soft conflicts of %1", "%1 is the file name").arg(tt);
01466               tos<<"\n";
01467               tos<<TimetableExport::tr("Generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)<<"\n\n";
01468 
01469               tos<<TimetableExport::tr("Total soft conflicts:")<<QString(" ")<<best_solution.conflictsTotal<<endl<<endl;
01470               tos<<TimetableExport::tr("Soft conflicts list (in decreasing order):")<<endl<<endl;
01471               foreach(QString t, best_solution.conflictsDescriptionList)
01472                      tos<<t<<endl;
01473               tos<<endl<<TimetableExport::tr("End of file.")<<"\n";
01474        }
01475        else{
01476               QString tt=INPUT_FILENAME_XML.right(INPUT_FILENAME_XML.length()-INPUT_FILENAME_XML.lastIndexOf(FILE_SEP)-1);
01477               if(INPUT_FILENAME_XML=="")
01478                      tt=tr("unnamed");
01479               tos<<TimetableExport::tr("Conflicts of %1").arg(tt);
01480               tos<<"\n";
01481               tos<<TimetableExport::tr("Warning! Only %1 out of %2 activities placed!").arg(placedActivities).arg(gt.rules.nInternalActivities)<<"\n";
01482               tos<<TimetableExport::tr("Generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)<<"\n\n";
01483 
01484               tos<<TimetableExport::tr("Total conflicts:")<<QString(" ")<<best_solution.conflictsTotal<<endl<<endl;
01485               tos<<TimetableExport::tr("Conflicts list (in decreasing order):")<<endl<<endl;
01486               foreach(QString t, best_solution.conflictsDescriptionList)
01487                      tos<<t<<endl;
01488               tos<<endl<<TimetableExport::tr("End of file.")<<"\n";
01489        }
01490        
01491        if(file.error()>0){
01492               QMessageBox::critical(parent, tr("FET critical"),
01493                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(filename).arg(file.error()));
01494        }
01495        file.close();
01496 }
01497 
01498 void TimetableExport::writeSubgroupsTimetableXml(QWidget* parent, const QString& xmlfilename){
01499        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
01500        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
01501 
01502        //Now we print the results to an XML file
01503        QFile file(xmlfilename);
01504        if(!file.open(QIODevice::WriteOnly)){
01505               QMessageBox::critical(parent, tr("FET critical"),
01506                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(xmlfilename));
01507               return;
01508               assert(0);
01509        }
01510        QTextStream tos(&file);
01511        tos.setCodec("UTF-8");
01512        tos.setGenerateByteOrderMark(true);
01513        tos<<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
01514        tos<<"<"<<protect(STUDENTS_TIMETABLE_TAG)<<">\n";
01515 
01516        for(int subgroup=0; subgroup<gt.rules.nInternalSubgroups; subgroup++){
01517               tos<< "  <Subgroup name=\"";
01518               QString subgroup_name = gt.rules.internalSubgroupsList[subgroup]->name;
01519               tos<< protect(subgroup_name) << "\">\n";
01520 
01521               for(int day=0; day<gt.rules.nDaysPerWeek; day++){
01522                      tos<<"   <Day name=\""<<protect(gt.rules.daysOfTheWeek[day])<<"\">\n";
01523                      for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
01524                             tos << "    <Hour name=\"" << protect(gt.rules.hoursOfTheDay[hour]) << "\">\n";
01525                             tos<<"     ";
01526                             int ai=students_timetable_weekly[subgroup][day][hour]; //activity index
01527                             if(ai!=UNALLOCATED_ACTIVITY){
01528                                    //Activity* act=gt.rules.activitiesList.at(ai);
01529                                    Activity* act=&gt.rules.internalActivitiesList[ai];
01530                                    for(QStringList::Iterator it=act->teachersNames.begin(); it!=act->teachersNames.end(); it++)
01531                                           tos<<" <Teacher name=\""<<protect(*it)<<"\"></Teacher>";
01532                                    tos<<"<Subject name=\""<<protect(act->subjectName)<<"\"></Subject>";
01533                                    foreach(QString atn, act->activityTagsNames)
01534                                           tos<<"<Activity_Tag name=\""<<protect(atn)<<"\"></Activity_Tag>";
01535 
01536                                    int r=best_solution.rooms[ai];
01537                                    if(r!=UNALLOCATED_SPACE && r!=UNSPECIFIED_ROOM){
01538                                           tos<<"<Room name=\""<<protect(gt.rules.internalRoomsList[r]->name)<<"\"></Room>";
01539                                    }
01540                             }
01541                             tos<<"\n";
01542                             tos << "    </Hour>\n";
01543                      }
01544                      tos<<"   </Day>\n";
01545               }
01546               tos<<"  </Subgroup>\n";
01547        }
01548 
01549        tos << "</" << protect(STUDENTS_TIMETABLE_TAG) << ">\n";
01550 
01551        if(file.error()>0){
01552               QMessageBox::critical(parent, tr("FET critical"),
01553                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(xmlfilename).arg(file.error()));
01554        }
01555        file.close();
01556 }
01557 
01558 void TimetableExport::writeTeachersTimetableXml(QWidget* parent, const QString& xmlfilename){
01559        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
01560        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
01561 
01562        //Writing the timetable in xml format
01563        QFile file(xmlfilename);
01564        if(!file.open(QIODevice::WriteOnly)){
01565               QMessageBox::critical(parent, tr("FET critical"),
01566                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(xmlfilename));
01567               return;
01568               assert(0);
01569        }
01570        QTextStream tos(&file);
01571        tos.setCodec("UTF-8");
01572        tos.setGenerateByteOrderMark(true);
01573        tos<<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
01574        tos << "<" << protect(TEACHERS_TIMETABLE_TAG) << ">\n";
01575 
01576        for(int i=0; i<gt.rules.nInternalTeachers; i++){
01577               tos << "  <Teacher name=\"" << protect(gt.rules.internalTeachersList[i]->name) << "\">\n";
01578               for(int day=0; day<gt.rules.nDaysPerWeek; day++){
01579                      tos << "   <Day name=\"" << protect(gt.rules.daysOfTheWeek[day]) << "\">\n";
01580                      for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
01581                             tos << "    <Hour name=\"" << protect(gt.rules.hoursOfTheDay[hour]) << "\">\n";
01582 
01583                             tos<<"     ";
01584                             int ai=teachers_timetable_weekly[i][day][hour]; //activity index
01585                             //Activity* act=gt.rules.activitiesList.at(ai);
01586                             if(ai!=UNALLOCATED_ACTIVITY){
01587                                    Activity* act=&gt.rules.internalActivitiesList[ai];
01588                                    tos<<"<Subject name=\""<<protect(act->subjectName)<<"\"></Subject>";
01589                                    foreach(QString atn, act->activityTagsNames)
01590                                           tos<<"<Activity_Tag name=\""<<protect(atn)<<"\"></Activity_Tag>";
01591                                    for(QStringList::Iterator it=act->studentsNames.begin(); it!=act->studentsNames.end(); it++)
01592                                           tos << "<Students name=\"" << protect(*it) << "\"></Students>";
01593 
01594                                    int r=best_solution.rooms[ai];
01595                                    if(r!=UNALLOCATED_SPACE && r!=UNSPECIFIED_ROOM){
01596                                           tos<<"<Room name=\""<<protect(gt.rules.internalRoomsList[r]->name)<<"\"></Room>";
01597                                    }
01598                             }
01599                             tos<<"\n";
01600                             tos << "    </Hour>\n";
01601                      }
01602                      tos << "   </Day>\n";
01603               }
01604               tos<<"  </Teacher>\n";
01605        }
01606 
01607        tos << "</" << protect(TEACHERS_TIMETABLE_TAG) << ">\n";
01608 
01609        if(file.error()>0){
01610               QMessageBox::critical(parent, tr("FET critical"),
01611                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(xmlfilename).arg(file.error()));
01612        }
01613        file.close();
01614 }
01615 
01616 void TimetableExport::writeActivitiesTimetableXml(QWidget* parent, const QString& xmlfilename){
01617        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
01618        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
01619 
01620        //Writing the timetable in xml format
01621        QFile file(xmlfilename);
01622        if(!file.open(QIODevice::WriteOnly)){
01623               QMessageBox::critical(parent, tr("FET critical"),
01624                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(xmlfilename));
01625               return;
01626               assert(0);
01627        }
01628        QTextStream tos(&file);
01629        tos.setCodec("UTF-8");
01630        tos.setGenerateByteOrderMark(true);
01631        tos<<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
01632        tos << "<" << protect(ACTIVITIES_TIMETABLE_TAG) << ">\n";
01633        
01634        for(int i=0; i<gt.rules.nInternalActivities; i++){
01635               tos<<"<Activity>"<<endl;
01636               
01637               tos<<" <Id>"<<gt.rules.internalActivitiesList[i].id<<"</Id>"<<endl;
01638               
01639               QString day="";
01640               if(best_solution.times[i]!=UNALLOCATED_TIME){
01641                      int d=best_solution.times[i]%gt.rules.nDaysPerWeek;
01642                      day=gt.rules.daysOfTheWeek[d];
01643               }
01644               tos<<" <Day>"<<protect(day)<<"</Day>"<<endl;
01645               
01646               QString hour="";
01647               if(best_solution.times[i]!=UNALLOCATED_TIME){
01648                      int h=best_solution.times[i]/gt.rules.nDaysPerWeek;
01649                      hour=gt.rules.hoursOfTheDay[h];
01650               }
01651               tos<<" <Hour>"<<protect(hour)<<"</Hour>"<<endl;
01652               
01653               QString room="";
01654               if(best_solution.rooms[i]!=UNALLOCATED_SPACE && best_solution.rooms[i]!=UNSPECIFIED_ROOM){
01655                      int r=best_solution.rooms[i];
01656                      room=gt.rules.internalRoomsList[r]->name;
01657               }
01658               tos<<" <Room>"<<protect(room)<<"</Room>"<<endl;
01659               
01660               tos<<"</Activity>"<<endl;
01661        }
01662 
01663        tos << "</" << protect(ACTIVITIES_TIMETABLE_TAG) << ">\n";
01664 
01665        if(file.error()>0){
01666               QMessageBox::critical(parent, tr("FET critical"),
01667                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(xmlfilename).arg(file.error()));
01668        }
01669        file.close();
01670 }
01671 
01672 // writing the index html file by Volker Dirr.
01673 void TimetableExport::writeIndexHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
01674        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
01675        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
01676 
01677        //Now we print the results to an HTML file
01678        QFile file(htmlfilename);
01679        if(!file.open(QIODevice::WriteOnly)){
01680               QMessageBox::critical(parent, tr("FET critical"),
01681                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
01682               return;
01683               assert(0);
01684        }
01685        QTextStream tos(&file);
01686        tos.setCodec("UTF-8");
01687        tos.setGenerateByteOrderMark(true);
01688 
01689        tos<<writeHead(false, placedActivities, true);
01690 
01691        QString bar;
01692        QString s2="";
01693        if(INPUT_FILENAME_XML=="")
01694               bar="";
01695        else{
01696               bar="_";
01697               s2=INPUT_FILENAME_XML.right(INPUT_FILENAME_XML.length()-INPUT_FILENAME_XML.lastIndexOf(FILE_SEP)-1);
01698 
01699               if(s2.right(4)==".fet")
01700                      s2=s2.left(s2.length()-4);
01701               //else if(INPUT_FILENAME_XML!="")
01702               //     cout<<"Minor problem - input file does not end in .fet extension - might be a problem when saving the timetables"<<" (file:"<<__FILE__<<", line:"<<__LINE__<<")"<<endl;
01703        }
01704        tos<<"    <p>\n";
01705 
01706        tos<<"      <a href=\""<<s2+bar+CONFLICTS_FILENAME<<"\">"<<tr("View the soft conflicts list.")<<"</a><br />\n";
01707        //     tos<<"    </p>\n";
01708        //     tos<<"    <p>\n";
01709 
01710        QString tmp1="<a href=\""+s2+bar+SUBGROUPS_TIMETABLE_FILENAME_XML+"\">"+tr("subgroups")+"</a>";
01711        QString tmp2="<a href=\""+s2+bar+TEACHERS_TIMETABLE_FILENAME_XML+"\">"+tr("teachers")+"</a>";
01712        QString tmp3="<a href=\""+s2+bar+ACTIVITIES_TIMETABLE_FILENAME_XML+"\">"+tr("activities")+"</a>";
01713        QString tmp4=TimetableExport::tr("View XML: %1, %2, %3.", "%1, %2 and %3 are three files in XML format, subgroups, teachers and activities timetables. The user can click on one file to view it").arg(tmp1).arg(tmp2).arg(tmp3);
01714        tos<<"      "<<tmp4<<"\n";
01715 
01716        tos<<"    </p>\n\n";
01717 
01718        tos<<"    <table border=\"1\">\n";
01719 
01720        tos<<"      <caption>"<<protect2(gt.rules.institutionName)<<"</caption>\n";
01721 
01722        tos<<"      <thead>\n        <tr><td rowspan=\"2\"></td><th colspan=\"4\">"+tr("Timetables")+"</th></tr>\n";
01723        tos<<"        <tr>\n          <!-- span -->\n";
01724        tos<<"          <th>"+tr("Days Horizontal")+"</th><th>"+tr("Days Vertical")+"</th><th>"+tr("Time Horizontal")+"</th><th>"+tr("Time Vertical")+"</th>";
01725        tos<<"        </tr>\n";
01726        tos<<"      </thead>\n";
01727        tos<<"      <tbody>\n";
01728        
01729        /* workaround
01730        tos<<"      <tfoot><tr><td></td><td colspan=\"4\">"<<TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)<<"</td></tr></tfoot>\n";
01731        */
01732 
01733        tos<<"        <tr>\n";
01734        tos<<"          <th>"+tr("Subgroups")+"</th>\n";
01735        tos<<"          <td><a href=\""<<s2+bar+SUBGROUPS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01736        tos<<"          <td><a href=\""<<s2+bar+SUBGROUPS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01737        tos<<"          <td><a href=\""<<s2+bar+SUBGROUPS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01738        tos<<"          <td><a href=\""<<s2+bar+SUBGROUPS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01739        tos<<"        </tr>\n";
01740        tos<<"        <tr>\n";
01741        tos<<"          <th>"+tr("Groups")+"</th>\n";
01742        tos<<"          <td><a href=\""<<s2+bar+GROUPS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01743        tos<<"          <td><a href=\""<<s2+bar+GROUPS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01744        tos<<"          <td><a href=\""<<s2+bar+GROUPS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01745        tos<<"          <td><a href=\""<<s2+bar+GROUPS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01746        tos<<"        </tr>\n";
01747        tos<<"        <tr>\n";
01748        tos<<"          <th>"+tr("Years")+"</th>\n";
01749        tos<<"          <td><a href=\""<<s2+bar+YEARS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01750        tos<<"          <td><a href=\""<<s2+bar+YEARS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01751        tos<<"          <td><a href=\""<<s2+bar+YEARS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01752        tos<<"          <td><a href=\""<<s2+bar+YEARS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01753        tos<<"        </tr>\n";
01754        tos<<"        <tr>\n";
01755        tos<<"          <th>"+tr("Teachers")+"</th>\n";
01756        tos<<"          <td><a href=\""<<s2+bar+TEACHERS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01757        tos<<"          <td><a href=\""<<s2+bar+TEACHERS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01758        tos<<"          <td><a href=\""<<s2+bar+TEACHERS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01759        tos<<"          <td><a href=\""<<s2+bar+TEACHERS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01760        tos<<"        </tr>\n";
01761        tos<<"        <tr>\n";
01762        tos<<"          <th>"+tr("Teachers Free Periods")+"</th>\n";
01763        tos<<"          <td><a href=\""<<s2+bar+TEACHERS_FREE_PERIODS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01764        tos<<"          <td><a href=\""<<s2+bar+TEACHERS_FREE_PERIODS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01765        tos<<"          <td>"<<protect2(STRING_EMPTY_SLOT)<<"</td>\n";
01766        tos<<"          <td>"<<protect2(STRING_EMPTY_SLOT)<<"</td>\n";
01767        tos<<"        </tr>\n";
01768        tos<<"        <tr>\n";
01769        tos<<"          <th>"+tr("Rooms")+"</th>\n";
01770        tos<<"          <td><a href=\""<<s2+bar+ROOMS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01771        tos<<"          <td><a href=\""<<s2+bar+ROOMS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01772        tos<<"          <td><a href=\""<<s2+bar+ROOMS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01773        tos<<"          <td><a href=\""<<s2+bar+ROOMS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01774        tos<<"        </tr>\n";
01775        tos<<"        <tr>\n";
01776        tos<<"          <th>"+tr("Subjects")+"</th>\n";
01777        tos<<"          <td><a href=\""<<s2+bar+SUBJECTS_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01778        tos<<"          <td><a href=\""<<s2+bar+SUBJECTS_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01779        tos<<"          <td><a href=\""<<s2+bar+SUBJECTS_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01780        tos<<"          <td><a href=\""<<s2+bar+SUBJECTS_TIMETABLE_TIME_VERTICAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01781        tos<<"        </tr>\n";
01782        tos<<"        <tr>\n";
01783        tos<<"          <th>"+tr("Activities")+"</th>\n";
01784        tos<<"          <td><a href=\""<<s2+bar+ALL_ACTIVITIES_TIMETABLE_DAYS_HORIZONTAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01785        tos<<"          <td><a href=\""<<s2+bar+ALL_ACTIVITIES_TIMETABLE_DAYS_VERTICAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01786        tos<<"          <td><a href=\""<<s2+bar+ALL_ACTIVITIES_TIMETABLE_TIME_HORIZONTAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01787        tos<<"          <td><a href=\""<<s2+bar+ALL_ACTIVITIES_TIMETABLE_TIME_VERTICAL_FILENAME_HTML<<"\">"+tr("view")+"</a></td>\n";
01788        tos<<"        </tr>\n";
01789        //workaround begin.
01790        tos<<"      <tr class=\"foot\"><td></td><td colspan=\"4\">"<<TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)<<"</td></tr>\n";
01791        //workaround end.
01792        tos<<"      </tbody>\n";
01793        tos<<"    </table>\n";
01794 
01795        tos<<"  </body>\n</html>\n";
01796 
01797        if(file.error()>0){
01798               QMessageBox::critical(parent, tr("FET critical"),
01799                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
01800        }
01801        file.close();
01802 }
01803 
01804 // writing the stylesheet in css format to a file by Volker Dirr.
01805 void TimetableExport::writeStylesheetCss(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
01806        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
01807        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
01808 
01809        //get used students  //TODO: do it the same way in statistics.cpp
01810        QSet<QString> usedStudents;
01811        for(int i=0; i<gt.rules.nInternalActivities; i++){
01812               foreach(QString st, gt.rules.internalActivitiesList[i].studentsNames){
01813                      if(!usedStudents.contains(st))
01814                             usedStudents<<st;
01815               }
01816        }
01817 
01818        //Now we print the results to an CSS file
01819        QFile file(htmlfilename);
01820        if(!file.open(QIODevice::WriteOnly)){
01821               QMessageBox::critical(parent, tr("FET critical"),
01822                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
01823               return;
01824               assert(0);
01825        }
01826        QTextStream tos(&file);
01827        tos.setCodec("UTF-8");
01828        tos.setGenerateByteOrderMark(true);
01829        
01830        tos<<"@charset \"UTF-8\";"<<"\n\n";
01831 
01832        QString tt=INPUT_FILENAME_XML.right(INPUT_FILENAME_XML.length()-INPUT_FILENAME_XML.lastIndexOf(FILE_SEP)-1);
01833        if(INPUT_FILENAME_XML=="")
01834               tt=tr("unnamed");
01835        tos<<"/* "<<TimetableExport::tr("CSS Stylesheet of %1", "%1 is the file name").arg(tt);
01836        tos<<"\n";
01837        if(placedActivities!=gt.rules.nInternalActivities)
01838               tos<<"   "<<TimetableExport::tr("Warning! Only %1 out of %2 activities placed!").arg(placedActivities).arg(gt.rules.nInternalActivities)<<"\n";
01839        tos<<"   "<<TimetableExport::tr("Stylesheet generated with FET %1 on %2", "%1 is FET version, %2 is date and time").arg(FET_VERSION).arg(saveTime)<<" */\n\n";
01840 
01841        tos<<"/* "<<TimetableExport::tr("To do a page-break only after every second timetable, delete \"page-break-before: always;\" in \"table.even_table\".",
01842               "Please keep fields in quotes as they are, untranslated.")<<" */\n";
01843        tos<<"/* "<<TimetableExport::tr("To hide an element just write the following phrase into the element: %1 (without quotes).",
01844               "%1 is a short phrase beginning and ending with quotes, and we want the user to be able to add it, but without quotes").arg("\"display:none;\"")<<" */\n\n";
01845        tos<<"p.back {\n  margin-top: 4ex;\n  margin-bottom: 5ex;\n}\n\n";
01846        tos<<"table {\n  text-align: center;\n}\n\n";
01847        tos<<"table.odd_table {\n  page-break-before: always;\n}\n\n";
01848        tos<<"table.even_table {\n  page-break-before: always;\n}\n\n";
01849        tos<<"table.detailed {\n  margin-left:auto; margin-right:auto;\n  text-align: center;\n  border: 0px;\n  border-spacing: 0;\n  border-collapse: collapse;\n}\n\n";
01850        tos<<"caption {\n\n}\n\n";
01851        tos<<"thead {\n\n}\n\n";
01852        
01853        //workaround begin.
01854        tos<<"/* "<<TimetableExport::tr("Some programs import \"tfoot\" incorrectly. So we use \"tr.foot\" instead of \"tfoot\".",
01855         "Please keep tfoot and tr.foot untranslated, as they are in the original English phrase")<<" */\n\n";
01856        //tos<<"tfoot {\n\n}\n\n";
01857        tos<<"tr.foot {\n\n}\n\n";
01858        //workaround end
01859 
01860        tos<<"tbody {\n\n}\n\n";
01861        tos<<"th {\n\n}\n\n";
01862        tos<<"td {\n\n}\n\n";
01863        tos<<"td.detailed {\n  border: 1px dashed silver;\n  border-bottom: 0;\n  border-top: 0;\n}\n\n";
01864        if(TIMETABLE_HTML_LEVEL>=2){
01865               tos<<"th.xAxis {\n/* width: 8em; */\n}\n\n";
01866               tos<<"th.yAxis {\n  height: 8ex;\n}\n\n";
01867        }
01868        if(TIMETABLE_HTML_LEVEL>=4){ // must be written before LEVEL 3, because LEVEL 3 should have higher priority
01869               for(int i=0; i<gt.rules.nInternalSubjects; i++){
01870                      tos << "span.s_"<<hashSubjectIDsTimetable.value(gt.rules.internalSubjectsList[i]->name)<<" { /* subject "<<gt.rules.internalSubjectsList[i]->name<<" */\n\n}\n\n";
01871               }
01872               for(int i=0; i<gt.rules.nInternalActivityTags; i++){
01873                      tos << "span.at_"<<hashActivityTagIDsTimetable.value(gt.rules.internalActivityTagsList[i]->name)<<" { /* activity tag "<<gt.rules.internalActivityTagsList[i]->name<<" */\n\n}\n\n";
01874               }
01875               for(int i=0; i<gt.rules.augmentedYearsList.size(); i++){
01876                      StudentsYear* sty=gt.rules.augmentedYearsList[i];
01877                      if(usedStudents.contains(sty->name))
01878                             tos << "span.ss_"<<hashStudentIDsTimetable.value(sty->name)<<" { /* students set "<<sty->name<<" */\n\n}\n\n";
01879                      for(int j=0; j<sty->groupsList.size(); j++){
01880                             StudentsGroup* stg=sty->groupsList[j];
01881                             if(usedStudents.contains(stg->name))
01882                                    tos << "span.ss_"<<hashStudentIDsTimetable.value(stg->name)<<" { /* students set "<<stg->name<<" */\n\n}\n\n";
01883                             for(int k=0; k<stg->subgroupsList.size(); k++){
01884                                    StudentsSubgroup* sts=stg->subgroupsList[k];
01885                                    if(usedStudents.contains(sts->name))
01886                                           tos << "span.ss_"<<hashStudentIDsTimetable.value(sts->name)<<" { /* students set "<<sts->name<<" */\n\n}\n\n";
01887                             }
01888                      }
01889               }
01890               for(int i=0; i<gt.rules.nInternalTeachers; i++){
01891                      tos << "span.t_"<<hashTeacherIDsTimetable.value(gt.rules.internalTeachersList[i]->name)<<" { /* teacher "<<gt.rules.internalTeachersList[i]->name<<" */\n\n}\n\n";
01892               }
01893               for(int room=0; room<gt.rules.nInternalRooms; room++){
01894                      tos << "span.r_"<<hashRoomIDsTimetable.value(gt.rules.internalRoomsList[room]->name)<<" { /* room "<<gt.rules.internalRoomsList[room]->name<<" */\n\n}\n\n";
01895               }
01896        }
01897        if(TIMETABLE_HTML_LEVEL>=3){
01898               tos<<"span.subject {\n\n}\n\n";
01899               tos<<"span.activitytag {\n\n}\n\n";
01900 
01901               tos<<"span.empty {\n  color: gray;\n}\n\n";
01902               tos<<"td.empty {\n  border-color:silver;\n  border-right-style:none;\n  border-bottom-style:none;\n  border-left-style:dotted;\n  border-top-style:dotted;\n}\n\n";
01903 
01904               tos<<"span.notAvailable {\n  color: gray;\n}\n\n";
01905               tos<<"td.notAvailable {\n  border-color:silver;\n  border-right-style:none;\n  border-bottom-style:none;\n  border-left-style:dotted;\n  border-top-style:dotted;\n}\n\n";
01906 
01907               tos<<"span.break {\n  color: gray;\n}\n\n";
01908               tos<<"td.break {\n  border-color:silver;\n  border-right-style:none;\n  border-bottom-style:none;\n  border-left-style:dotted;\n  border-top-style:dotted;\n}\n\n";
01909 
01910               tos<<"td.student, div.student {\n\n}\n\n";
01911               tos<<"td.teacher, div.teacher {\n\n}\n\n";
01912               tos<<"td.room, div.room {\n\n}\n\n";
01913               tos<<"tr.line0 {\n  font-size: smaller;\n}\n\n";
01914               tos<<"tr.line1, div.line1 {\n\n}\n\n";
01915               tos<<"tr.line2, div.line2 {\n  font-size: smaller;\n  color: gray;\n}\n\n";
01916               tos<<"tr.line3, div.line3 {\n  font-size: smaller;\n  color: silver;\n}\n\n";
01917        }
01918        if(TIMETABLE_HTML_LEVEL==6){
01919               tos<<endl<<"/* "<<TimetableExport::tr("Be careful. You might get mutual and ambiguous styles. CSS means that the last definition will be used.")<<" */\n\n";
01920               for(int i=0; i<gt.rules.nInternalSubjects; i++){
01921                      tos << "td.s_"<<hashSubjectIDsTimetable.value(gt.rules.internalSubjectsList[i]->name)<<" { /* subject "<<gt.rules.internalSubjectsList[i]->name<<" */\n\n}\n\n";
01922               }
01923               for(int i=0; i<gt.rules.nInternalActivityTags; i++){
01924                      tos << "td.at_"<<hashActivityTagIDsTimetable.value(gt.rules.internalActivityTagsList[i]->name)<<" { /* activity tag "<<gt.rules.internalActivityTagsList[i]->name<<" */\n\n}\n\n";
01925               }
01926               for(int i=0; i<gt.rules.augmentedYearsList.size(); i++){
01927                      StudentsYear* sty=gt.rules.augmentedYearsList[i];
01928                      if(usedStudents.contains(sty->name))
01929                             tos << "td.ss_"<<hashStudentIDsTimetable.value(sty->name)<<" { /* students set "<<sty->name<<" */\n\n}\n\n";
01930                      for(int j=0; j<sty->groupsList.size(); j++){
01931                             StudentsGroup* stg=sty->groupsList[j];
01932                             if(usedStudents.contains(stg->name))
01933                                    tos << "td.ss_"<<hashStudentIDsTimetable.value(stg->name)<<" { /* students set "<<stg->name<<" */\n\n}\n\n";
01934                             for(int k=0; k<stg->subgroupsList.size(); k++){
01935                                    StudentsSubgroup* sts=stg->subgroupsList[k];
01936                                    if(usedStudents.contains(sts->name))
01937                                           tos << "td.ss_"<<hashStudentIDsTimetable.value(sts->name)<<" { /* students set "<<sts->name<<" */\n\n}\n\n";
01938                             }
01939                      }
01940               }
01941               for(int i=0; i<gt.rules.nInternalTeachers; i++){
01942                      tos << "td.t_"<<hashTeacherIDsTimetable.value(gt.rules.internalTeachersList[i]->name)<<" { /* teacher "<<gt.rules.internalTeachersList[i]->name<<" */\n\n}\n\n";
01943               }
01944 
01945               //not included yet
01946               //for(int room=0; room<gt.rules.nInternalRooms; room++){
01947               //     tos << "span.r_"<<hashRoomIDsTimetable.value(gt.rules.internalRoomsList[room]->name)<<" { /* room "<<gt.rules.internalRoomsList[room]->name<<" */\n\n}\n\n";
01948               //}
01949        }
01950        tos<<"/* "<<TimetableExport::tr("Style the teachers free periods")<<" */\n\n";
01951        if(TIMETABLE_HTML_LEVEL>=2){
01952               tos<<"div.DESCRIPTION {\n  text-align: left;\n  font-size: smaller;\n}\n\n";
01953        }
01954        if(TIMETABLE_HTML_LEVEL>=3){
01955               tos<<"div.TEACHER_HAS_SINGLE_GAP {\n  color: black;\n}\n\n";
01956               tos<<"div.TEACHER_HAS_BORDER_GAP {\n  color: gray;\n}\n\n";
01957               tos<<"div.TEACHER_HAS_BIG_GAP {\n  color: silver;\n}\n\n";
01958               tos<<"div.TEACHER_MUST_COME_EARLIER {\n  color: purple;\n}\n\n";
01959               tos<<"div.TEACHER_MUST_COME_MUCH_EARLIER {\n  font-size: smaller;\n  color: fuchsia;\n}\n\n";
01960               tos<<"div.TEACHER_MUST_STAY_LONGER {\n  color: teal;\n}\n\n";
01961               tos<<"div.TEACHER_MUST_STAY_MUCH_LONGER {\n  font-size: smaller;\n  color: aqua;\n}\n\n";
01962               tos<<"div.TEACHER_HAS_A_FREE_DAY {\n  font-size: smaller;\n  color: red;\n}\n\n";
01963               tos<<"div.TEACHER_IS_NOT_AVAILABLE {\n  font-size: smaller;\n  color: olive;\n}\n\n";
01964        }
01965        tos<<"/* "<<TimetableExport::tr("End of file.")<<" */\n";
01966 
01967        if(file.error()>0){
01968               QMessageBox::critical(parent, tr("FET critical"),
01969                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
01970        }
01971        file.close();
01972 }
01973 
01974 //XHTML generation code modified by Volker Dirr (timetabling.de) from old html generation code
01975 void TimetableExport::writeSubgroupsTimetableDaysHorizontalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
01976        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
01977        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
01978 
01979        //Now we print the results to an HTML file
01980        QFile file(htmlfilename);
01981        if(!file.open(QIODevice::WriteOnly)){
01982               QMessageBox::critical(parent, tr("FET critical"),
01983                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
01984               return;
01985               assert(0);
01986        }
01987        QTextStream tos(&file);
01988        tos.setCodec("UTF-8");
01989        tos.setGenerateByteOrderMark(true);
01990 
01991        tos<<writeHead(true, placedActivities, true);
01992        
01993        tos<<"    <p><strong>"<<TimetableExport::tr("Table of contents")<<"</strong></p>\n";
01994        tos<<"    <ul>\n";
01995        for(int i=0; i<gt.rules.augmentedYearsList.size(); i++){
01996               StudentsYear* sty=gt.rules.augmentedYearsList[i];
01997               tos<<"      <li>\n        "<<TimetableExport::tr("Year")<<" "<<protect2(sty->name)<<"\n        <ul>\n";
01998               for(int j=0; j<sty->groupsList.size(); j++){
01999                      StudentsGroup* stg=sty->groupsList[j];
02000                      tos<<"          <li>\n            "<<TimetableExport::tr("Group")<<" "<<protect2(stg->name)<<": \n";
02001                      for(int k=0; k<stg->subgroupsList.size(); k++){
02002                             StudentsSubgroup* sts=stg->subgroupsList[k];
02003                             tos<<"              <a href=\""<<"#table_"<<hashStudentIDsTimetable.value(sts->name)<<"\">"<<protect2(sts->name)<<"</a>\n";
02004                      }
02005                      tos<<"          </li>\n";
02006               }
02007               tos<<"        </ul>\n      </li>\n";
02008        }
02009        tos<<"    </ul>\n    <p>&nbsp;</p>\n\n";
02010 
02011        for(int subgroup=0; subgroup<gt.rules.nInternalSubgroups; subgroup++){
02012               tos<<singleSubgroupsTimetableDaysHorizontalHtml(TIMETABLE_HTML_LEVEL, subgroup, saveTime, true);
02013               tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
02014        }
02015        tos<<"  </body>\n</html>\n";
02016 
02017        if(file.error()>0){
02018               QMessageBox::critical(parent, tr("FET critical"),
02019                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02020        }
02021        file.close();
02022 }
02023 
02024 //XHTML generation code modified by Volker Dirr (timetabling.de) from old html generation code
02025 void TimetableExport::writeSubgroupsTimetableDaysVerticalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02026        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02027        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02028 
02029        //Now we print the results to an HTML file
02030        QFile file(htmlfilename);
02031        if(!file.open(QIODevice::WriteOnly)){
02032               QMessageBox::critical(parent, tr("FET critical"),
02033                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02034               return;
02035               assert(0);
02036        }
02037        QTextStream tos(&file);
02038        tos.setCodec("UTF-8");
02039        tos.setGenerateByteOrderMark(true);
02040 
02041        tos<<writeHead(true, placedActivities, true);
02042               
02043        tos<<"    <p><strong>"<<TimetableExport::tr("Table of contents")<<"</strong></p>\n";
02044        tos<<"    <ul>\n";
02045        for(int i=0; i<gt.rules.augmentedYearsList.size(); i++){
02046               StudentsYear* sty=gt.rules.augmentedYearsList[i];
02047               tos<<"      <li>\n        "<<TimetableExport::tr("Year")<<" "<<protect2(sty->name)<<"\n        <ul>\n";
02048               for(int j=0; j<sty->groupsList.size(); j++){
02049                      StudentsGroup* stg=sty->groupsList[j];
02050                      tos<<"          <li>\n            "<<TimetableExport::tr("Group")<<" "<<protect2(stg->name)<<": \n";
02051                      for(int k=0; k<stg->subgroupsList.size(); k++){
02052                             StudentsSubgroup* sts=stg->subgroupsList[k];
02053                             tos<<"              <a href=\""<<"#table_"<<hashStudentIDsTimetable.value(sts->name)<<"\">"<<protect2(sts->name)<<"</a>\n";
02054                      }
02055                      tos<<"          </li>\n";
02056               }
02057               tos<<"        </ul>\n      </li>\n";
02058        }
02059        tos<<"    </ul>\n    <p>&nbsp;</p>\n";
02060 
02061        for(int subgroup=0; subgroup<gt.rules.nInternalSubgroups; subgroup++){
02062               tos<<singleSubgroupsTimetableDaysVerticalHtml(TIMETABLE_HTML_LEVEL, subgroup, saveTime, true);
02063               tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
02064        }
02065 
02066        tos<<"  </body>\n</html>\n";
02067 
02068        if(file.error()>0){
02069               QMessageBox::critical(parent, tr("FET critical"),
02070                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02071        }
02072        file.close();
02073 }
02074 
02075 //XHTML generation code by Volker Dirr (http://timetabling.de/)
02076 void TimetableExport::writeSubgroupsTimetableTimeVerticalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02077        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02078        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02079 
02080        //Now we print the results to an HTML file
02081        QFile file(htmlfilename);
02082        if(!file.open(QIODevice::WriteOnly)){
02083               QMessageBox::critical(parent, tr("FET critical"),
02084                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02085               return;
02086               assert(0);
02087        }
02088        QTextStream tos(&file);
02089        tos.setCodec("UTF-8");
02090        tos.setGenerateByteOrderMark(true);
02091 
02092        tos<<writeHead(true, placedActivities, false);
02093        
02094        QSet<int> tmp;
02095        tos << singleSubgroupsTimetableTimeVerticalHtml(TIMETABLE_HTML_LEVEL, gt.rules.nInternalSubgroups, tmp, saveTime, true);
02096 
02097        tos << "  </body>\n</html>\n";
02098 
02099        if(file.error()>0){
02100               QMessageBox::critical(parent, tr("FET critical"),
02101                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02102        }      
02103        file.close();
02104 }
02105 
02106 //XHTML generation code modified by Volker Dirr (timetabling.de) from old html generation code
02107 void TimetableExport::writeSubgroupsTimetableTimeHorizontalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02108        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02109        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02110 
02111        //Now we print the results to an HTML file
02112        QFile file(htmlfilename);
02113        if(!file.open(QIODevice::WriteOnly)){
02114               QMessageBox::critical(parent, tr("FET critical"),
02115                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02116               return;
02117               assert(0);
02118        }
02119        QTextStream tos(&file);
02120        tos.setCodec("UTF-8");
02121        tos.setGenerateByteOrderMark(true);
02122 
02123        tos<<writeHead(true, placedActivities, false);
02124        
02125        QSet<int> tmp;
02126        tos << singleSubgroupsTimetableTimeHorizontalHtml(TIMETABLE_HTML_LEVEL, gt.rules.nInternalSubgroups, tmp, saveTime, true);
02127 
02128        tos << "  </body>\n</html>\n";
02129 
02130        if(file.error()>0){
02131               QMessageBox::critical(parent, tr("FET critical"),
02132                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02133        }
02134        file.close();
02135 }
02136 
02137 // by Volker Dirr
02138 void TimetableExport::writeSubgroupsTimetableTimeVerticalDailyHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02139        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02140        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02141 
02142        //Now we print the results to an HTML file
02143        QFile file(htmlfilename);
02144        if(!file.open(QIODevice::WriteOnly)){
02145               QMessageBox::critical(parent, tr("FET critical"),
02146                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02147               return;
02148               assert(0);
02149        }
02150        QTextStream tos(&file);
02151        tos.setCodec("UTF-8");
02152        tos.setGenerateByteOrderMark(true);
02153 
02154        tos<<writeHead(true, placedActivities, true);
02155        tos<<writeTOCDays(false);
02156 
02157        for(int day=0; day<gt.rules.nDaysPerWeek; day++){
02158               QSet<int> tmp;
02159               tos<<singleSubgroupsTimetableTimeVerticalDailyHtml(TIMETABLE_HTML_LEVEL, day, gt.rules.nInternalSubgroups, tmp, saveTime, true);
02160               tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
02161        }
02162 
02163        tos << "  </body>\n</html>\n";
02164 
02165        if(file.error()>0){
02166               QMessageBox::critical(parent, tr("FET critical"),
02167                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02168        }      
02169        file.close();
02170 }
02171 
02172 // by Volker Dirr
02173 void TimetableExport::writeSubgroupsTimetableTimeHorizontalDailyHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02174        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02175        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02176 
02177        //Now we print the results to an HTML file
02178        QFile file(htmlfilename);
02179        if(!file.open(QIODevice::WriteOnly)){
02180               QMessageBox::critical(parent, tr("FET critical"),
02181                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02182               return;
02183               assert(0);
02184        }
02185        QTextStream tos(&file);
02186        tos.setCodec("UTF-8");
02187        tos.setGenerateByteOrderMark(true);
02188 
02189        tos<<writeHead(true, placedActivities, true);
02190        tos<<writeTOCDays(false);
02191        
02192        for(int day=0; day<gt.rules.nDaysPerWeek; day++){
02193               QSet<int> tmp;
02194               tos<<singleSubgroupsTimetableTimeHorizontalDailyHtml(TIMETABLE_HTML_LEVEL, day, gt.rules.nInternalSubgroups, tmp, saveTime, true);
02195               tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
02196        }
02197        tos << "  </body>\n</html>\n";
02198 
02199        if(file.error()>0){
02200               QMessageBox::critical(parent, tr("FET critical"),
02201                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02202        }
02203        file.close();
02204 }
02205 
02206 //Now print the groups
02207 //XHTML generation code by Volker Dirr (http://timetabling.de/)
02208 void TimetableExport::writeGroupsTimetableDaysHorizontalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02209        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02210        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02211 
02212        //Now we print the results to an HTML file
02213        QFile file(htmlfilename);
02214        if(!file.open(QIODevice::WriteOnly)){
02215               QMessageBox::critical(parent, tr("FET critical"),
02216                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02217               return;
02218               assert(0);
02219        }
02220        QTextStream tos(&file);
02221        tos.setCodec("UTF-8");
02222        tos.setGenerateByteOrderMark(true);
02223 
02224        tos<<writeHead(true, placedActivities, true);
02225               
02226        tos<<"    <p><strong>"<<TimetableExport::tr("Table of contents")<<"</strong></p>\n";
02227        tos<<"    <ul>\n";
02228        for(int i=0; i<gt.rules.augmentedYearsList.size(); i++){
02229               StudentsYear* sty=gt.rules.augmentedYearsList[i];
02230               tos<<"      <li>\n        "<<TimetableExport::tr("Year")<<" "<<protect2(sty->name)<<"\n        <ul>\n";
02231               for(int j=0; j<sty->groupsList.size(); j++){
02232                      StudentsGroup* stg=sty->groupsList[j];
02233                      tos<<"          <li>\n            "<<TimetableExport::tr("Group");
02234                      tos<<" <a href=\""<<"#table_"<<hashStudentIDsTimetable.value(stg->name)<<"_DETAILED\">"<<protect2(stg->name)<<" ("<<tr("Detailed")<<")</a> /";
02235                      tos<<" <a href=\""<<"#table_"<<hashStudentIDsTimetable.value(stg->name)<<"\">"<<protect2(stg->name)<<" ("<<tr("Less detailed")<<")</a>\n";
02236                      tos<<"          </li>\n";
02237               }
02238               tos<<"        </ul>\n      </li>\n";
02239        }
02240        tos<<"    </ul>\n    <p>&nbsp;</p>\n\n";
02241 
02242        bool PRINT_DETAILED=true;
02243        do{
02244               for(int group=0; group<gt.rules.internalGroupsList.size(); group++){
02245                      tos << singleGroupsTimetableDaysHorizontalHtml(TIMETABLE_HTML_LEVEL, group, saveTime, true, PRINT_DETAILED);
02246                      tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
02247               }
02248               if(PRINT_DETAILED) PRINT_DETAILED=false;
02249               else PRINT_DETAILED=true;
02250        } while(!PRINT_DETAILED);
02251        tos<<"  </body>\n</html>\n";
02252 
02253        if(file.error()>0){
02254               QMessageBox::critical(parent, tr("FET critical"),
02255                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02256        }
02257        file.close();
02258 }
02259 
02260 //XHTML generation code by Volker Dirr (http://timetabling.de/)
02261 void TimetableExport::writeGroupsTimetableDaysVerticalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02262        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02263        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02264 
02265        //Now we print the results to an HTML file
02266        QFile file(htmlfilename);
02267        if(!file.open(QIODevice::WriteOnly)){
02268               QMessageBox::critical(parent, tr("FET critical"),
02269                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02270               return;
02271               assert(0);
02272        }
02273        QTextStream tos(&file);
02274        tos.setCodec("UTF-8");
02275        tos.setGenerateByteOrderMark(true);
02276 
02277        tos<<writeHead(true, placedActivities, true);
02278               
02279        tos<<"    <p><strong>"<<TimetableExport::tr("Table of contents")<<"</strong></p>\n";
02280        tos<<"    <ul>\n";
02281        for(int i=0; i<gt.rules.augmentedYearsList.size(); i++){
02282               StudentsYear* sty=gt.rules.augmentedYearsList[i];
02283               tos<<"      <li>\n        "<<TimetableExport::tr("Year")<<" "<<protect2(sty->name)<<"\n        <ul>\n";
02284               for(int j=0; j<sty->groupsList.size(); j++){
02285                      StudentsGroup* stg=sty->groupsList[j];
02286                      tos<<"          <li>\n            "<<TimetableExport::tr("Group");
02287                      tos<<" <a href=\""<<"#table_"<<hashStudentIDsTimetable.value(stg->name)<<"_DETAILED\">"<<protect2(stg->name)<<" ("<<tr("Detailed")<<")</a> /";
02288                      tos<<" <a href=\""<<"#table_"<<hashStudentIDsTimetable.value(stg->name)<<"\">"<<protect2(stg->name)<<" ("<<tr("Less detailed")<<")</a>\n";
02289                      tos<<"          </li>\n";
02290               }
02291               tos<<"        </ul>\n      </li>\n";
02292        }
02293        tos<<"    </ul>\n    <p>&nbsp;</p>\n";
02294 
02295        bool PRINT_DETAILED=true;
02296        do{
02297               for(int group=0; group<gt.rules.internalGroupsList.size(); group++){
02298                      tos<<singleGroupsTimetableDaysVerticalHtml(TIMETABLE_HTML_LEVEL, group, saveTime, true, PRINT_DETAILED);
02299                      tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
02300               }
02301               if(PRINT_DETAILED) PRINT_DETAILED=false;
02302               else PRINT_DETAILED=true;
02303        } while(!PRINT_DETAILED);
02304        tos<<"  </body>\n</html>\n";
02305 
02306        if(file.error()>0){
02307               QMessageBox::critical(parent, tr("FET critical"),
02308                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02309        }
02310        file.close();
02311 }
02312 
02313 //XHTML generation code by Volker Dirr (http://timetabling.de/)
02314 void TimetableExport::writeGroupsTimetableTimeVerticalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02315        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02316        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02317 
02318        //Now we print the results to an HTML file
02319        QFile file(htmlfilename);
02320        if(!file.open(QIODevice::WriteOnly)){
02321               QMessageBox::critical(parent, tr("FET critical"),
02322                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02323               return;
02324               assert(0);
02325        }
02326        QTextStream tos(&file);
02327        tos.setCodec("UTF-8");
02328        tos.setGenerateByteOrderMark(true);
02329 
02330        tos<<writeHead(true, placedActivities, false);
02331        
02332        bool PRINT_DETAILED=true;
02333        do{
02334               QSet<int> tmp;
02335               tos<<singleGroupsTimetableTimeVerticalHtml(TIMETABLE_HTML_LEVEL, gt.rules.internalGroupsList.size(), tmp, saveTime, true, PRINT_DETAILED);
02336 
02337               tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
02338               if(PRINT_DETAILED) PRINT_DETAILED=false;
02339               else PRINT_DETAILED=true;
02340        } while(!PRINT_DETAILED);
02341        tos << "  </body>\n</html>\n";
02342 
02343        if(file.error()>0){
02344               QMessageBox::critical(parent, tr("FET critical"),
02345                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02346        }
02347        file.close();
02348 }
02349 
02350 //XHTML generation code by Volker Dirr (http://timetabling.de/)
02351 void TimetableExport::writeGroupsTimetableTimeHorizontalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02352        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02353        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02354 
02355        //Now we print the results to an HTML file
02356        QFile file(htmlfilename);
02357        if(!file.open(QIODevice::WriteOnly)){
02358               QMessageBox::critical(parent, tr("FET critical"),
02359                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02360               return;
02361               assert(0);
02362        }
02363        QTextStream tos(&file);
02364        tos.setCodec("UTF-8");
02365        tos.setGenerateByteOrderMark(true);
02366 
02367        tos<<writeHead(true, placedActivities, false);
02368        
02369        bool PRINT_DETAILED=true;
02370        do{
02371               QSet<int> tmp;
02372               tos<<singleGroupsTimetableTimeHorizontalHtml(TIMETABLE_HTML_LEVEL, gt.rules.internalGroupsList.size(), tmp, saveTime, true, PRINT_DETAILED);
02373               tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
02374               if(PRINT_DETAILED) PRINT_DETAILED=false;
02375               else PRINT_DETAILED=true;
02376        } while(!PRINT_DETAILED);
02377        tos << "  </body>\n</html>\n";
02378 
02379        if(file.error()>0){
02380               QMessageBox::critical(parent, tr("FET critical"),
02381                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02382        }
02383        file.close();
02384 }
02385 
02386 //XHTML generation code by Volker Dirr (http://timetabling.de/)
02387 void TimetableExport::writeGroupsTimetableTimeVerticalDailyHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02388        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02389        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02390 
02391        //Now we print the results to an HTML file
02392        QFile file(htmlfilename);
02393        if(!file.open(QIODevice::WriteOnly)){
02394               QMessageBox::critical(parent, tr("FET critical"),
02395                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02396               return;
02397               assert(0);
02398        }
02399        QTextStream tos(&file);
02400        tos.setCodec("UTF-8");
02401        tos.setGenerateByteOrderMark(true);
02402 
02403        tos<<writeHead(true, placedActivities, true);
02404        tos<<writeTOCDays(true);
02405 
02406        bool PRINT_DETAILED=true;
02407        do{
02408               for(int day=0; day<gt.rules.nDaysPerWeek; day++){
02409                      QSet<int> tmp;
02410                      tos<<singleGroupsTimetableTimeVerticalDailyHtml(TIMETABLE_HTML_LEVEL, day, gt.rules.internalGroupsList.size(), tmp, saveTime, true, PRINT_DETAILED);
02411 
02412                      tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
02413               }
02414               if(PRINT_DETAILED) PRINT_DETAILED=false;
02415               else PRINT_DETAILED=true;
02416        } while(!PRINT_DETAILED);
02417        tos << "  </body>\n</html>\n";
02418 
02419        if(file.error()>0){
02420               QMessageBox::critical(parent, tr("FET critical"),
02421                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02422        }
02423        file.close();
02424 }
02425 
02426 //XHTML generation code by Volker Dirr (http://timetabling.de/)
02427 void TimetableExport::writeGroupsTimetableTimeHorizontalDailyHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02428        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02429        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02430 
02431        //Now we print the results to an HTML file
02432        QFile file(htmlfilename);
02433        if(!file.open(QIODevice::WriteOnly)){
02434               QMessageBox::critical(parent, tr("FET critical"),
02435                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02436               return;
02437               assert(0);
02438        }
02439        QTextStream tos(&file);
02440        tos.setCodec("UTF-8");
02441        tos.setGenerateByteOrderMark(true);
02442 
02443        tos<<writeHead(true, placedActivities, true);
02444        tos<<writeTOCDays(true);
02445        
02446        bool PRINT_DETAILED=true;
02447        do{
02448               for(int day=0; day<gt.rules.nDaysPerWeek; day++){
02449                      QSet<int> tmp;
02450                      tos<<singleGroupsTimetableTimeHorizontalDailyHtml(TIMETABLE_HTML_LEVEL, day, gt.rules.internalGroupsList.size(), tmp, saveTime, true, PRINT_DETAILED);
02451 
02452                      tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
02453               }
02454               if(PRINT_DETAILED) PRINT_DETAILED=false;
02455               else PRINT_DETAILED=true;
02456        } while(!PRINT_DETAILED);
02457        tos << "  </body>\n</html>\n";
02458 
02459        if(file.error()>0){
02460               QMessageBox::critical(parent, tr("FET critical"),
02461                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02462        }
02463        file.close();
02464 }
02465 
02466 //Now print the years
02467 
02468 //XHTML generation code by Volker Dirr (http://timetabling.de/)
02469 void TimetableExport::writeYearsTimetableDaysHorizontalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02470        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02471        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02472 
02473        //Now we print the results to an HTML file
02474        QFile file(htmlfilename);
02475        if(!file.open(QIODevice::WriteOnly)){
02476               QMessageBox::critical(parent, tr("FET critical"),
02477                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02478               return;
02479               assert(0);
02480        }
02481        QTextStream tos(&file);
02482        tos.setCodec("UTF-8");
02483        tos.setGenerateByteOrderMark(true);
02484 
02485        tos<<writeHead(true, placedActivities, true);
02486               
02487        tos<<"    <p><strong>"<<TimetableExport::tr("Table of contents")<<"</strong></p>\n";
02488        tos<<"    <ul>\n";
02489        for(int year=0; year<gt.rules.augmentedYearsList.size(); year++){
02490               StudentsYear* sty=gt.rules.augmentedYearsList[year];
02491               tos<<"      <li>\n        "<<TimetableExport::tr("Year");
02492               tos<<" <a href=\""<<"#table_"<<hashStudentIDsTimetable.value(sty->name)<<"_DETAILED\">"<<protect2(sty->name)<<" ("<<tr("Detailed")<<")</a> /";
02493               tos<<" <a href=\""<<"#table_"<<hashStudentIDsTimetable.value(sty->name)<<"\">"<<protect2(sty->name)<<" ("<<tr("Less detailed")<<")</a>\n";
02494               tos<<"      </li>\n";
02495        }
02496        tos<<"    </ul>\n    <p>&nbsp;</p>\n\n";
02497 
02498        bool PRINT_DETAILED=true;
02499        do{
02500               for(int year=0; year<gt.rules.augmentedYearsList.size(); year++){
02501                      tos << singleYearsTimetableDaysHorizontalHtml(TIMETABLE_HTML_LEVEL, year, saveTime, true, PRINT_DETAILED);
02502                      tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
02503               }
02504               if(PRINT_DETAILED) PRINT_DETAILED=false;
02505               else PRINT_DETAILED=true;
02506        } while(!PRINT_DETAILED);
02507        tos<<"  </body>\n</html>\n";
02508 
02509        if(file.error()>0){
02510               QMessageBox::critical(parent, tr("FET critical"),
02511                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02512        }
02513        file.close();
02514 }
02515 
02516 //XHTML generation code by Volker Dirr (http://timetabling.de/)
02517 void TimetableExport::writeYearsTimetableDaysVerticalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02518        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02519        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02520 
02521        //Now we print the results to an HTML file
02522        QFile file(htmlfilename);
02523        if(!file.open(QIODevice::WriteOnly)){
02524               QMessageBox::critical(parent, tr("FET critical"),
02525                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02526               return;
02527               assert(0);
02528        }
02529        QTextStream tos(&file);
02530        tos.setCodec("UTF-8");
02531        tos.setGenerateByteOrderMark(true);
02532 
02533        tos<<writeHead(true, placedActivities, true);
02534               
02535        tos<<"    <p><strong>"<<TimetableExport::tr("Table of contents")<<"</strong></p>\n";
02536        tos<<"    <ul>\n";
02537        for(int year=0; year<gt.rules.augmentedYearsList.size(); year++){
02538               StudentsYear* sty=gt.rules.augmentedYearsList[year];
02539               tos<<"      <li>\n        "<<TimetableExport::tr("Year");
02540               tos<<" <a href=\""<<"#table_"<<hashStudentIDsTimetable.value(sty->name)<<"_DETAILED\">"<<protect2(sty->name)<<" ("<<tr("Detailed")<<")</a> /";
02541               tos<<" <a href=\""<<"#table_"<<hashStudentIDsTimetable.value(sty->name)<<"\">"<<protect2(sty->name)<<" ("<<tr("Less detailed")<<")</a>\n";
02542               tos<<"      </li>\n";
02543        }
02544        tos<<"    </ul>\n    <p>&nbsp;</p>\n\n";
02545 
02546        bool PRINT_DETAILED=true;
02547        do{
02548               for(int year=0; year<gt.rules.augmentedYearsList.size(); year++){
02549                      tos << singleYearsTimetableDaysVerticalHtml(TIMETABLE_HTML_LEVEL, year, saveTime, true, PRINT_DETAILED);
02550                      tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
02551               }
02552               if(PRINT_DETAILED) PRINT_DETAILED=false;
02553               else PRINT_DETAILED=true;
02554        } while(!PRINT_DETAILED);
02555        tos<<"  </body>\n</html>\n";
02556 
02557        if(file.error()>0){
02558               QMessageBox::critical(parent, tr("FET critical"),
02559                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02560        }
02561        file.close();
02562 }
02563 
02564 //XHTML generation code by Volker Dirr (http://timetabling.de/)
02565 void TimetableExport::writeYearsTimetableTimeVerticalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02566        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02567        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02568 
02569        //Now we print the results to an HTML file
02570        QFile file(htmlfilename);
02571        if(!file.open(QIODevice::WriteOnly)){
02572               QMessageBox::critical(parent, tr("FET critical"),
02573                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02574               return;
02575               assert(0);
02576        }
02577        QTextStream tos(&file);
02578        tos.setCodec("UTF-8");
02579        tos.setGenerateByteOrderMark(true);
02580 
02581        tos<<writeHead(true, placedActivities, false);
02582        
02583        bool PRINT_DETAILED=true;
02584        do{
02585               QSet<int> tmp;
02586               tos<<singleYearsTimetableTimeVerticalHtml(TIMETABLE_HTML_LEVEL, gt.rules.augmentedYearsList.size(), tmp, saveTime, true, PRINT_DETAILED);
02587 
02588               tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
02589               if(PRINT_DETAILED) PRINT_DETAILED=false;
02590               else PRINT_DETAILED=true;
02591        } while(!PRINT_DETAILED);
02592        tos << "  </body>\n</html>\n";
02593 
02594        if(file.error()>0){
02595               QMessageBox::critical(parent, tr("FET critical"),
02596                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02597        }
02598        file.close();
02599 }
02600 
02601 //XHTML generation code by Volker Dirr (http://timetabling.de/)
02602 void TimetableExport::writeYearsTimetableTimeHorizontalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02603        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02604        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02605 
02606        //Now we print the results to an HTML file
02607        QFile file(htmlfilename);
02608        if(!file.open(QIODevice::WriteOnly)){
02609               QMessageBox::critical(parent, tr("FET critical"),
02610                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02611               return;
02612               assert(0);
02613        }
02614        QTextStream tos(&file);
02615        tos.setCodec("UTF-8");
02616        tos.setGenerateByteOrderMark(true);
02617 
02618        tos<<writeHead(true, placedActivities, false);
02619        
02620        bool PRINT_DETAILED=true;
02621        do{
02622               QSet<int> tmp;
02623               tos<<singleYearsTimetableTimeHorizontalHtml(TIMETABLE_HTML_LEVEL, gt.rules.augmentedYearsList.size(), tmp, saveTime, true, PRINT_DETAILED);
02624 
02625               tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
02626               if(PRINT_DETAILED) PRINT_DETAILED=false;
02627               else PRINT_DETAILED=true;
02628        } while(!PRINT_DETAILED);
02629        tos << "  </body>\n</html>\n";
02630 
02631        if(file.error()>0){
02632               QMessageBox::critical(parent, tr("FET critical"),
02633                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02634        }
02635        file.close();
02636 }
02637 
02638 //XHTML generation code by Volker Dirr (http://timetabling.de/)
02639 void TimetableExport::writeYearsTimetableTimeVerticalDailyHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02640        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02641        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02642 
02643        //Now we print the results to an HTML file
02644        QFile file(htmlfilename);
02645        if(!file.open(QIODevice::WriteOnly)){
02646               QMessageBox::critical(parent, tr("FET critical"),
02647                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02648               return;
02649               assert(0);
02650        }
02651        QTextStream tos(&file);
02652        tos.setCodec("UTF-8");
02653        tos.setGenerateByteOrderMark(true);
02654 
02655        tos<<writeHead(true, placedActivities, true);
02656        tos<<writeTOCDays(true);
02657 
02658        bool PRINT_DETAILED=true;
02659        do{
02660               for(int day=0; day<gt.rules.nDaysPerWeek; day++){
02661                      QSet<int> tmp;
02662                      tos<<singleYearsTimetableTimeVerticalDailyHtml(TIMETABLE_HTML_LEVEL, day, gt.rules.augmentedYearsList.size(), tmp, saveTime, true, PRINT_DETAILED);
02663 
02664                      tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
02665               }
02666               if(PRINT_DETAILED) PRINT_DETAILED=false;
02667               else PRINT_DETAILED=true;
02668        } while(!PRINT_DETAILED);
02669        tos << "  </body>\n</html>\n";
02670 
02671        if(file.error()>0){
02672               QMessageBox::critical(parent, tr("FET critical"),
02673                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02674        }
02675        file.close();
02676 }
02677 
02678 //XHTML generation code by Volker Dirr (http://timetabling.de/)
02679 void TimetableExport::writeYearsTimetableTimeHorizontalDailyHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02680        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02681        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02682 
02683        //Now we print the results to an HTML file
02684        QFile file(htmlfilename);
02685        if(!file.open(QIODevice::WriteOnly)){
02686               QMessageBox::critical(parent, tr("FET critical"),
02687                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02688               return;
02689               assert(0);
02690        }
02691        QTextStream tos(&file);
02692        tos.setCodec("UTF-8");
02693        tos.setGenerateByteOrderMark(true);
02694 
02695        tos<<writeHead(true, placedActivities, true);
02696        tos<<writeTOCDays(true);
02697        
02698        bool PRINT_DETAILED=true;
02699        do{
02700               for(int day=0; day<gt.rules.nDaysPerWeek; day++){
02701                      QSet<int> tmp;
02702                      tos<<singleYearsTimetableTimeHorizontalDailyHtml(TIMETABLE_HTML_LEVEL, day, gt.rules.augmentedYearsList.size(), tmp, saveTime, true, PRINT_DETAILED);
02703 
02704                      tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
02705               }
02706               if(PRINT_DETAILED) PRINT_DETAILED=false;
02707               else PRINT_DETAILED=true;
02708        } while(!PRINT_DETAILED);
02709        tos << "  </body>\n</html>\n";
02710 
02711        if(file.error()>0){
02712               QMessageBox::critical(parent, tr("FET critical"),
02713                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02714        }
02715        file.close();
02716 }
02717 
02718 //Print all activities
02719 
02720 //XHTML generation code by Volker Dirr (http://timetabling.de/)
02721 void TimetableExport::writeAllActivitiesTimetableDaysHorizontalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02722        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02723        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02724 
02725        //Now we print the results to an HTML file
02726        QFile file(htmlfilename);
02727        if(!file.open(QIODevice::WriteOnly)){
02728               QMessageBox::critical(parent, tr("FET critical"),
02729                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02730               return;
02731               assert(0);
02732        }
02733        QTextStream tos(&file);
02734        tos.setCodec("UTF-8");
02735        tos.setGenerateByteOrderMark(true);
02736 
02737        tos<<writeHead(true, placedActivities, true);
02738        tos<<singleAllActivitiesTimetableDaysHorizontalHtml(TIMETABLE_HTML_LEVEL, saveTime, true);
02739        tos<<"  </body>\n</html>\n";
02740 
02741        if(file.error()>0){
02742               QMessageBox::critical(parent, tr("FET critical"),
02743                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02744        }
02745        file.close();
02746 }
02747 
02748 //XHTML generation code by Volker Dirr (http://timetabling.de/)
02749 void TimetableExport::writeAllActivitiesTimetableDaysVerticalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02750        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02751        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02752 
02753        //Now we print the results to an HTML file
02754        QFile file(htmlfilename);
02755        if(!file.open(QIODevice::WriteOnly)){
02756               QMessageBox::critical(parent, tr("FET critical"),
02757                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02758               return;
02759               assert(0);
02760        }
02761        QTextStream tos(&file);
02762        tos.setCodec("UTF-8");
02763        tos.setGenerateByteOrderMark(true);
02764 
02765        tos<<writeHead(true, placedActivities, true);
02766        tos<<singleAllActivitiesTimetableDaysVerticalHtml(TIMETABLE_HTML_LEVEL, saveTime, true);
02767        tos<<"  </body>\n</html>\n";
02768 
02769        if(file.error()>0){
02770               QMessageBox::critical(parent, tr("FET critical"),
02771                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02772        }
02773        file.close();
02774 }
02775 
02776 //XHTML generation code by Volker Dirr (http://timetabling.de/)
02777 void TimetableExport::writeAllActivitiesTimetableTimeVerticalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02778        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02779        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02780 
02781        //Now we print the results to an HTML file
02782        QFile file(htmlfilename);
02783        if(!file.open(QIODevice::WriteOnly)){
02784               QMessageBox::critical(parent, tr("FET critical"),
02785                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02786               return;
02787               assert(0);
02788        }
02789        QTextStream tos(&file);
02790        tos.setCodec("UTF-8");
02791        tos.setGenerateByteOrderMark(true);
02792 
02793        tos<<writeHead(true, placedActivities, false);
02794 
02795 tos<<singleAllActivitiesTimetableTimeVerticalHtml(TIMETABLE_HTML_LEVEL, saveTime, true);
02796 
02797        tos<<"  </body>\n</html>\n";
02798 
02799        if(file.error()>0){
02800               QMessageBox::critical(parent, tr("FET critical"),
02801                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02802        }
02803        file.close();
02804 }
02805 
02806 //XHTML generation code by Volker Dirr (http://timetabling.de/)
02807 void TimetableExport::writeAllActivitiesTimetableTimeHorizontalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02808        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02809        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02810 
02811        //Now we print the results to an HTML file
02812        QFile file(htmlfilename);
02813        if(!file.open(QIODevice::WriteOnly)){
02814               QMessageBox::critical(parent, tr("FET critical"),
02815                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02816               return;
02817               assert(0);
02818        }
02819        QTextStream tos(&file);
02820        tos.setCodec("UTF-8");
02821        tos.setGenerateByteOrderMark(true);
02822 
02823        tos<<writeHead(true, placedActivities, false);
02824 
02825        tos<<singleAllActivitiesTimetableTimeHorizontalHtml(TIMETABLE_HTML_LEVEL, saveTime, true);
02826 
02827        tos<<"  </body>\n</html>\n";
02828 
02829        if(file.error()>0){
02830               QMessageBox::critical(parent, tr("FET critical"),
02831                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02832        }
02833        file.close();
02834 }
02835 
02836 //XHTML generation code by Volker Dirr (http://timetabling.de/)
02837 void TimetableExport::writeAllActivitiesTimetableTimeVerticalDailyHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02838        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02839        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02840 
02841        //Now we print the results to an HTML file
02842        QFile file(htmlfilename);
02843        if(!file.open(QIODevice::WriteOnly)){
02844               QMessageBox::critical(parent, tr("FET critical"),
02845                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02846               return;
02847               assert(0);
02848        }
02849        QTextStream tos(&file);
02850        tos.setCodec("UTF-8");
02851        tos.setGenerateByteOrderMark(true);
02852 
02853        tos<<writeHead(true, placedActivities, true);
02854        tos<<writeTOCDays(false);
02855 
02856        for(int day=0; day<gt.rules.nDaysPerWeek; day++){
02857               tos<<singleAllActivitiesTimetableTimeVerticalDailyHtml(TIMETABLE_HTML_LEVEL, day, saveTime, true);
02858               tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
02859        }
02860        tos<<"  </body>\n</html>\n";
02861 
02862        if(file.error()>0){
02863               QMessageBox::critical(parent, tr("FET critical"),
02864                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02865        }
02866        file.close();
02867 }
02868 
02869 //XHTML generation code by Volker Dirr (http://timetabling.de/)
02870 void TimetableExport::writeAllActivitiesTimetableTimeHorizontalDailyHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02871        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02872        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02873 
02874        //Now we print the results to an HTML file
02875        QFile file(htmlfilename);
02876        if(!file.open(QIODevice::WriteOnly)){
02877               QMessageBox::critical(parent, tr("FET critical"),
02878                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02879               return;
02880               assert(0);
02881        }
02882        QTextStream tos(&file);
02883        tos.setCodec("UTF-8");
02884        tos.setGenerateByteOrderMark(true);
02885 
02886        tos<<writeHead(true, placedActivities, true);
02887        tos<<writeTOCDays(false);
02888 
02889        for(int day=0; day<gt.rules.nDaysPerWeek; day++){
02890               tos<<singleAllActivitiesTimetableTimeHorizontalDailyHtml(TIMETABLE_HTML_LEVEL, day, saveTime, true);
02891 
02892               tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
02893        }
02894 
02895        tos<<"  </body>\n</html>\n";
02896 
02897        if(file.error()>0){
02898               QMessageBox::critical(parent, tr("FET critical"),
02899                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02900        }
02901        file.close();
02902 }
02903 
02904 //Print the teachers
02905 
02906 //XHTML generation code modified by Volker Dirr (timetabling.de) from old html generation code
02907 void TimetableExport::writeTeachersTimetableDaysHorizontalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02908        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02909        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02910 
02911        //Now we print the results to an HTML file
02912        QFile file(htmlfilename);
02913        if(!file.open(QIODevice::WriteOnly)){
02914               QMessageBox::critical(parent, tr("FET critical"),
02915                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02916               return;
02917               assert(0);
02918        }
02919        QTextStream tos(&file);
02920        tos.setCodec("UTF-8");
02921        tos.setGenerateByteOrderMark(true);
02922        
02923        tos<<writeHead(true, placedActivities, true);
02924               
02925        tos<<"    <p><strong>"<<TimetableExport::tr("Table of contents")<<"</strong></p>\n";
02926        tos<<"    <ul>\n";
02927        for(int teacher=0; teacher<gt.rules.nInternalTeachers; teacher++){
02928               QString teacher_name = gt.rules.internalTeachersList[teacher]->name;
02929               tos<<"      <li><a href=\""<<"#table_"<<hashTeacherIDsTimetable.value(teacher_name)<<"\">"<<protect2(teacher_name)<<"</a></li>\n";
02930        }
02931        tos<<"    </ul>\n    <p>&nbsp;</p>\n\n";
02932 
02933        for(int teacher=0; teacher<gt.rules.nInternalTeachers; teacher++){
02934               tos<<singleTeachersTimetableDaysHorizontalHtml(TIMETABLE_HTML_LEVEL, teacher, saveTime, true);
02935 
02936               tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
02937        }
02938        tos<<"  </body>\n</html>\n";
02939 
02940        if(file.error()>0){
02941               QMessageBox::critical(parent, tr("FET critical"),
02942                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02943        }
02944        file.close();
02945 }
02946 
02947 //XHTML generation code modified by Volker Dirr (timetabling.de) from old html generation code
02948 void TimetableExport::writeTeachersTimetableDaysVerticalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02949        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02950        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02951 
02952        //Now we print the results to an HTML file
02953        QFile file(htmlfilename);
02954        if(!file.open(QIODevice::WriteOnly)){
02955               QMessageBox::critical(parent, tr("FET critical"),
02956                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02957               return;
02958               assert(0);
02959        }
02960        QTextStream tos(&file);
02961        tos.setCodec("UTF-8");
02962        tos.setGenerateByteOrderMark(true);
02963 
02964        tos<<writeHead(true, placedActivities, true); 
02965               
02966        tos<<"    <p><strong>"<<TimetableExport::tr("Table of contents")<<"</strong></p>\n";
02967        tos<<"    <ul>\n";
02968        for(int teacher=0; teacher<gt.rules.nInternalTeachers; teacher++){
02969               QString teacher_name = gt.rules.internalTeachersList[teacher]->name;
02970               tos<<"      <li><a href=\""<<"#table_"<<hashTeacherIDsTimetable.value(teacher_name)<<"\">"<<protect2(teacher_name)<<"</a></li>\n";
02971        }
02972        tos<<"    </ul>\n    <p>&nbsp;</p>\n\n";
02973 
02974        for(int teacher=0; teacher<gt.rules.nInternalTeachers; teacher++){
02975               tos<<singleTeachersTimetableDaysVerticalHtml(TIMETABLE_HTML_LEVEL, teacher, saveTime, true);
02976               tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
02977        }
02978        tos<<"  </body>\n</html>\n";
02979 
02980        if(file.error()>0){
02981               QMessageBox::critical(parent, tr("FET critical"),
02982                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
02983        }
02984        file.close();
02985 }
02986 
02987 //XHTML generation code by Volker Dirr (http://timetabling.de/)
02988 void TimetableExport::writeTeachersTimetableTimeVerticalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
02989        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
02990        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
02991 
02992        //Now we print the results to an HTML file
02993        QFile file(htmlfilename);
02994        if(!file.open(QIODevice::WriteOnly)){
02995               QMessageBox::critical(parent, tr("FET critical"),
02996                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
02997               return;
02998               assert(0);
02999        }
03000        QTextStream tos(&file);
03001        tos.setCodec("UTF-8");
03002        tos.setGenerateByteOrderMark(true);
03003 
03004        tos<<writeHead(true, placedActivities, false);
03005        QSet<int> tmp;
03006        tos<<singleTeachersTimetableTimeVerticalHtml(TIMETABLE_HTML_LEVEL, gt.rules.nInternalTeachers, tmp, saveTime, true);
03007        tos << "  </body>\n</html>\n";
03008 
03009        if(file.error()>0){
03010               QMessageBox::critical(parent, tr("FET critical"),
03011                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
03012        }
03013        file.close();
03014 }
03015 
03016 //XHTML generation code modified by Volker Dirr (timetabling.de) from old html generation code
03017 void TimetableExport::writeTeachersTimetableTimeHorizontalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
03018        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
03019        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
03020 
03021        //Now we print the results to an HTML file
03022        QFile file(htmlfilename);
03023        if(!file.open(QIODevice::WriteOnly)){
03024               QMessageBox::critical(parent, tr("FET critical"),
03025                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
03026               return;
03027               assert(0);
03028        }
03029        QTextStream tos(&file);
03030        tos.setCodec("UTF-8");
03031        tos.setGenerateByteOrderMark(true);
03032 
03033        tos<<writeHead(true, placedActivities, false);
03034        QSet<int> tmp;
03035        tos<<singleTeachersTimetableTimeHorizontalHtml(TIMETABLE_HTML_LEVEL, gt.rules.nInternalTeachers, tmp, saveTime, true);
03036        tos << "  </body>\n</html>\n";
03037 
03038        if(file.error()>0){
03039               QMessageBox::critical(parent, tr("FET critical"),
03040                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
03041        }
03042        file.close();
03043 }
03044 
03045 //by Volker Dirr
03046 void TimetableExport::writeTeachersTimetableTimeVerticalDailyHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
03047        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
03048        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
03049 
03050        //Now we print the results to an HTML file
03051        QFile file(htmlfilename);
03052        if(!file.open(QIODevice::WriteOnly)){
03053               QMessageBox::critical(parent, tr("FET critical"),
03054                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
03055               return;
03056               assert(0);
03057        }
03058        QTextStream tos(&file);
03059        tos.setCodec("UTF-8");
03060        tos.setGenerateByteOrderMark(true);
03061 
03062        tos<<writeHead(true, placedActivities, true);
03063        tos<<writeTOCDays(false);
03064 
03065        for(int day=0; day<gt.rules.nDaysPerWeek; day++){
03066               QSet<int> tmp;
03067               tos<<singleTeachersTimetableTimeVerticalDailyHtml(TIMETABLE_HTML_LEVEL, day, gt.rules.nInternalTeachers, tmp, saveTime, true);
03068               tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
03069        }
03070        tos << "  </body>\n</html>\n";
03071 
03072        if(file.error()>0){
03073               QMessageBox::critical(parent, tr("FET critical"),
03074                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
03075        }
03076        file.close();
03077 }
03078 
03079 //by Volker Dirr
03080 void TimetableExport::writeTeachersTimetableTimeHorizontalDailyHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
03081        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
03082        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
03083 
03084        //Now we print the results to an HTML file
03085        QFile file(htmlfilename);
03086        if(!file.open(QIODevice::WriteOnly)){
03087               QMessageBox::critical(parent, tr("FET critical"),
03088                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
03089               return;
03090               assert(0);
03091        }
03092        QTextStream tos(&file);
03093        tos.setCodec("UTF-8");
03094        tos.setGenerateByteOrderMark(true);
03095 
03096        tos<<writeHead(true, placedActivities, true);
03097        tos<<writeTOCDays(false);
03098 
03099        for(int day=0; day<gt.rules.nDaysPerWeek; day++){
03100               QSet<int> tmp;
03101               tos<<singleTeachersTimetableTimeHorizontalDailyHtml(TIMETABLE_HTML_LEVEL, day, gt.rules.nInternalTeachers, tmp, saveTime, true);
03102               tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
03103        }
03104 
03105        tos << "  </body>\n</html>\n";
03106 
03107        if(file.error()>0){
03108               QMessageBox::critical(parent, tr("FET critical"),
03109                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
03110        }
03111        file.close();
03112 }
03113 
03114 //writing the rooms' timetable html format to a file by Volker Dirr
03115 void TimetableExport::writeRoomsTimetableDaysHorizontalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
03116        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
03117        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
03118 
03119        //Now we print the results to an HTML file
03120        QFile file(htmlfilename);
03121        if(!file.open(QIODevice::WriteOnly)){
03122               QMessageBox::critical(parent, tr("FET critical"),
03123                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
03124               return;
03125               assert(0);
03126        }
03127        QTextStream tos(&file);
03128        tos.setCodec("UTF-8");
03129        tos.setGenerateByteOrderMark(true);
03130 
03131        tos<<writeHead(true, placedActivities, true);    
03132        
03133        if(gt.rules.nInternalRooms==0)
03134               tos<<"    <h1>"<<TimetableExport::tr("No rooms recorded in FET for %1.", "%1 is the institution name").arg(protect2(gt.rules.institutionName))<<"</h1>\n";
03135        else {
03136               tos<<"    <p><strong>"<<TimetableExport::tr("Table of contents")<<"</strong></p>\n";
03137               tos<<"    <ul>\n";
03138               for(int room=0; room<gt.rules.nInternalRooms; room++){
03139                      QString room_name = gt.rules.internalRoomsList[room]->name;
03140                      tos<<"      <li><a href=\""<<"#table_"<<hashRoomIDsTimetable.value(room_name)<<"\">"<<protect2(room_name)<<"</a></li>\n";
03141               }
03142               tos<<"    </ul>\n    <p>&nbsp;</p>\n\n";
03143 
03144               for(int room=0; room<gt.rules.nInternalRooms; room++){
03145                      tos<<singleRoomsTimetableDaysHorizontalHtml(TIMETABLE_HTML_LEVEL, room, saveTime, true);
03146                      tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
03147               }
03148        }
03149        tos<<"  </body>\n</html>\n";
03150 
03151        if(file.error()>0){
03152               QMessageBox::critical(parent, tr("FET critical"),
03153                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
03154        }
03155        file.close();
03156 }
03157 
03158 //writing the rooms' timetable html format to a file by Volker Dirr
03159 void TimetableExport::writeRoomsTimetableDaysVerticalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
03160        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
03161        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
03162 
03163        //Now we print the results to an HTML file
03164        QFile file(htmlfilename);
03165        if(!file.open(QIODevice::WriteOnly)){
03166               QMessageBox::critical(parent, tr("FET critical"),
03167                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
03168               return;
03169 
03170               assert(0);
03171        }
03172        QTextStream tos(&file);
03173        tos.setCodec("UTF-8");
03174        tos.setGenerateByteOrderMark(true);
03175 
03176        tos<<writeHead(true, placedActivities, true);
03177               
03178        if(gt.rules.nInternalRooms==0)
03179               tos<<"    <h1>"<<TimetableExport::tr("No rooms recorded in FET for %1.", "%1 is the institution name").arg(protect2(gt.rules.institutionName))<<"</h1>\n";
03180        else {
03181               tos<<"    <p><strong>"<<TimetableExport::tr("Table of contents")<<"</strong></p>\n";
03182               tos<<"    <ul>\n";
03183               for(int room=0; room<gt.rules.nInternalRooms; room++){
03184                      QString room_name = gt.rules.internalRoomsList[room]->name;
03185                      tos<<"      <li><a href=\""<<"#table_"<<hashRoomIDsTimetable.value(room_name)<<"\">"<<protect2(room_name)<<"</a></li>\n";
03186               }
03187               tos<<"    </ul>\n    <p>&nbsp;</p>\n\n";
03188 
03189               for(int room=0; room<gt.rules.nInternalRooms; room++){
03190                      tos<<singleRoomsTimetableDaysVerticalHtml(TIMETABLE_HTML_LEVEL, room, saveTime, true);
03191                      tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
03192               }
03193        }
03194        tos<<"  </body>\n</html>\n";
03195 
03196        if(file.error()>0){
03197               QMessageBox::critical(parent, tr("FET critical"),
03198                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
03199        }
03200        file.close();
03201 }
03202 
03203 //writing the rooms' timetable html format to a file by Volker Dirr
03204 void TimetableExport::writeRoomsTimetableTimeVerticalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
03205        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
03206        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
03207 
03208        //Now we print the results to an HTML file
03209        QFile file(htmlfilename);
03210        if(!file.open(QIODevice::WriteOnly)){
03211               QMessageBox::critical(parent, tr("FET critical"),
03212                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
03213               return;
03214               assert(0);
03215        }
03216        QTextStream tos(&file);
03217        tos.setCodec("UTF-8");
03218        tos.setGenerateByteOrderMark(true);
03219 
03220        tos<<writeHead(true, placedActivities, false);
03221        
03222        if(gt.rules.nInternalRooms==0)
03223               tos<<"    <h1>"<<TimetableExport::tr("No rooms recorded in FET for %1.", "%1 is the institution name").arg(protect2(gt.rules.institutionName))<<"</h1>\n";
03224        else {
03225               QSet<int> tmp;
03226               tos<<singleRoomsTimetableTimeVerticalHtml(TIMETABLE_HTML_LEVEL, gt.rules.nInternalRooms, tmp, saveTime, true);
03227        }
03228        tos << "  </body>\n</html>\n";
03229 
03230        if(file.error()>0){
03231               QMessageBox::critical(parent, tr("FET critical"),
03232                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
03233        }
03234        file.close();
03235 }
03236 
03237 // writing the rooms' timetable html format to a file by Volker Dirr
03238 void TimetableExport::writeRoomsTimetableTimeHorizontalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
03239        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
03240        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
03241 
03242        //Now we print the results to an HTML file
03243        QFile file(htmlfilename);
03244        if(!file.open(QIODevice::WriteOnly)){
03245               QMessageBox::critical(parent, tr("FET critical"),
03246                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
03247               return;
03248               assert(0);
03249        }
03250        QTextStream tos(&file);
03251        tos.setCodec("UTF-8");
03252        tos.setGenerateByteOrderMark(true);
03253 
03254        tos<<writeHead(true, placedActivities, false);
03255        
03256        if(gt.rules.nInternalRooms==0)
03257               tos<<"    <h1>"<<TimetableExport::tr("No rooms recorded in FET for %1.", "%1 is the institution name").arg(protect2(gt.rules.institutionName))<<"</h1>\n";
03258        else {
03259               QSet<int> tmp;
03260               tos<<singleRoomsTimetableTimeHorizontalHtml(TIMETABLE_HTML_LEVEL, gt.rules.nInternalRooms, tmp, saveTime, true);
03261 
03262        }
03263        tos << "  </body>\n</html>\n";
03264 
03265        if(file.error()>0){
03266               QMessageBox::critical(parent, tr("FET critical"),
03267                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
03268        }
03269        file.close();
03270 }
03271 
03272 //by Volker Dirr
03273 void TimetableExport::writeRoomsTimetableTimeVerticalDailyHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
03274        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
03275        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
03276 
03277        //Now we print the results to an HTML file
03278        QFile file(htmlfilename);
03279        if(!file.open(QIODevice::WriteOnly)){
03280               QMessageBox::critical(parent, tr("FET critical"),
03281                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
03282               return;
03283               assert(0);
03284        }
03285        QTextStream tos(&file);
03286        tos.setCodec("UTF-8");
03287        tos.setGenerateByteOrderMark(true);
03288 
03289        tos<<writeHead(true, placedActivities, true);
03290        tos<<writeTOCDays(false);
03291        
03292        if(gt.rules.nInternalRooms==0)
03293               tos<<"    <h1>"<<TimetableExport::tr("No rooms recorded in FET for %1.", "%1 is the institution name").arg(protect2(gt.rules.institutionName))<<"</h1>\n";
03294        else {
03295               for(int day=0; day<gt.rules.nDaysPerWeek; day++){
03296                      QSet<int> tmp;
03297                      tos<<singleRoomsTimetableTimeVerticalDailyHtml(TIMETABLE_HTML_LEVEL, day, gt.rules.nInternalRooms, tmp, saveTime, true);
03298 
03299                      tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
03300               }
03301        }
03302        tos << "  </body>\n</html>\n";
03303 
03304        if(file.error()>0){
03305               QMessageBox::critical(parent, tr("FET critical"),
03306                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
03307        }
03308        file.close();
03309 }
03310 
03311 //by Volker Dirr
03312 void TimetableExport::writeRoomsTimetableTimeHorizontalDailyHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
03313        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
03314        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
03315 
03316        //Now we print the results to an HTML file
03317        QFile file(htmlfilename);
03318        if(!file.open(QIODevice::WriteOnly)){
03319               QMessageBox::critical(parent, tr("FET critical"),
03320                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
03321               return;
03322               assert(0);
03323        }
03324        QTextStream tos(&file);
03325        tos.setCodec("UTF-8");
03326        tos.setGenerateByteOrderMark(true);
03327 
03328        tos<<writeHead(true, placedActivities, true);
03329        tos<<writeTOCDays(false);
03330        
03331        if(gt.rules.nInternalRooms==0)
03332               tos<<"    <h1>"<<TimetableExport::tr("No rooms recorded in FET for %1.", "%1 is the institution name").arg(protect2(gt.rules.institutionName))<<"</h1>\n";
03333        else {
03334               for(int day=0; day<gt.rules.nDaysPerWeek; day++){
03335                      QSet<int> tmp;
03336                      tos<<singleRoomsTimetableTimeHorizontalDailyHtml(TIMETABLE_HTML_LEVEL, day, gt.rules.nInternalRooms, tmp, saveTime, true);
03337 
03338                      tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
03339               }
03340 
03341        }
03342        tos << "  </body>\n</html>\n";
03343 
03344        if(file.error()>0){
03345               QMessageBox::critical(parent, tr("FET critical"),
03346                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
03347        }
03348        file.close();
03349 }
03350 
03351 //Print the subjects
03352 
03353 //XHTML generation code by Volker Dirr (http://timetabling.de/)
03354 void TimetableExport::writeSubjectsTimetableDaysHorizontalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
03355        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
03356        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
03357 
03358        //Now we print the results to an HTML file
03359        QFile file(htmlfilename);
03360        if(!file.open(QIODevice::WriteOnly)){
03361               QMessageBox::critical(parent, tr("FET critical"),
03362                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
03363               return;
03364               assert(0);
03365        }
03366        QTextStream tos(&file);
03367        tos.setCodec("UTF-8");
03368        tos.setGenerateByteOrderMark(true);
03369 
03370        tos<<writeHead(true, placedActivities, true);
03371 
03372        tos<<"    <p><strong>"<<TimetableExport::tr("Table of contents")<<"</strong></p>\n";
03373        tos<<"    <ul>\n";
03374        for(int i=0; i<gt.rules.nInternalSubjects; i++){
03375               tos<<"      <li>\n        "<<TimetableExport::tr("Subject");
03376               tos<<" <a href=\""<<"#table_"<<hashSubjectIDsTimetable.value(gt.rules.internalSubjectsList[i]->name)<<"\">"<<gt.rules.internalSubjectsList[i]->name<<"</a>\n";
03377               tos<<"      </li>\n";
03378        }
03379        tos<<"    </ul>\n    <p>&nbsp;</p>\n\n";
03380 
03381 
03382        for(int subject=0; subject<gt.rules.nInternalSubjects; subject++){
03383               tos<<singleSubjectsTimetableDaysHorizontalHtml(TIMETABLE_HTML_LEVEL, subject, saveTime, true);
03384               tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
03385        }
03386        tos<<"  </body>\n</html>\n";
03387 
03388        if(file.error()>0){
03389               QMessageBox::critical(parent, tr("FET critical"),
03390                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
03391        }
03392        file.close();
03393 }
03394 
03395 //XHTML generation code by Volker Dirr (http://timetabling.de/)
03396 void TimetableExport::writeSubjectsTimetableDaysVerticalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
03397        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
03398        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
03399 
03400        //Now we print the results to an HTML file
03401        QFile file(htmlfilename);
03402        if(!file.open(QIODevice::WriteOnly)){
03403               QMessageBox::critical(parent, tr("FET critical"),
03404                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
03405               return;
03406               assert(0);
03407        }
03408        QTextStream tos(&file);
03409        tos.setCodec("UTF-8");
03410        tos.setGenerateByteOrderMark(true);
03411 
03412        tos<<writeHead(true, placedActivities, true);
03413 
03414        tos<<"    <p><strong>"<<TimetableExport::tr("Table of contents")<<"</strong></p>\n";
03415        tos<<"    <ul>\n";
03416        for(int i=0; i<gt.rules.nInternalSubjects; i++){
03417               tos<<"      <li>\n        "<<TimetableExport::tr("Subject");
03418               tos<<" <a href=\""<<"#table_"<<hashSubjectIDsTimetable.value(gt.rules.internalSubjectsList[i]->name)<<"\">"<<gt.rules.internalSubjectsList[i]->name<<"</a>\n";
03419               tos<<"      </li>\n";
03420        }
03421        tos<<"    </ul>\n    <p>&nbsp;</p>\n\n";
03422 
03423        for(int subject=0; subject<gt.rules.nInternalSubjects; subject++){
03424               tos<<singleSubjectsTimetableDaysVerticalHtml(TIMETABLE_HTML_LEVEL, subject, saveTime, true);
03425               tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
03426        }
03427        tos << "  </body>\n</html>\n";
03428 
03429        if(file.error()>0){
03430               QMessageBox::critical(parent, tr("FET critical"),
03431                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
03432        }
03433        file.close();
03434 }
03435 
03436 //XHTML generation code by Volker Dirr (http://timetabling.de/)
03437 void TimetableExport::writeSubjectsTimetableTimeVerticalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
03438        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
03439        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
03440 
03441        //Now we print the results to an HTML file
03442        QFile file(htmlfilename);
03443        if(!file.open(QIODevice::WriteOnly)){
03444               QMessageBox::critical(parent, tr("FET critical"),
03445                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
03446               return;
03447               assert(0);
03448        }
03449        QTextStream tos(&file);
03450        tos.setCodec("UTF-8");
03451        tos.setGenerateByteOrderMark(true);
03452 
03453        tos<<writeHead(true, placedActivities, false);
03454 
03455        QSet<int> tmp;
03456        tos<<singleSubjectsTimetableTimeVerticalHtml(TIMETABLE_HTML_LEVEL, gt.rules.nInternalSubjects, tmp, saveTime, true);
03457        tos << "  </body>\n</html>\n";
03458 
03459        if(file.error()>0){
03460               QMessageBox::critical(parent, tr("FET critical"),
03461                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
03462        }
03463        file.close();
03464 }
03465 
03466 //XHTML generation code by Volker Dirr (http://timetabling.de/)
03467 void TimetableExport::writeSubjectsTimetableTimeHorizontalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
03468        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
03469        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
03470 
03471        //Now we print the results to an HTML file
03472        QFile file(htmlfilename);
03473        if(!file.open(QIODevice::WriteOnly)){
03474               QMessageBox::critical(parent, tr("FET critical"),
03475                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
03476               return;
03477               assert(0);
03478        }
03479        QTextStream tos(&file);
03480        tos.setCodec("UTF-8");
03481        tos.setGenerateByteOrderMark(true);
03482 
03483        tos<<writeHead(true, placedActivities, false);
03484 
03485        QSet<int> tmp;
03486        tos<<singleSubjectsTimetableTimeHorizontalHtml(TIMETABLE_HTML_LEVEL, gt.rules.nInternalSubjects, tmp, saveTime, true);
03487 
03488        tos << "  </body>\n</html>\n";
03489 
03490        if(file.error()>0){
03491               QMessageBox::critical(parent, tr("FET critical"),
03492                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
03493        }
03494        file.close();
03495 }
03496 
03497 //XHTML generation code by Volker Dirr (http://timetabling.de/)
03498 void TimetableExport::writeSubjectsTimetableTimeVerticalDailyHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
03499        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
03500        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
03501 
03502        //Now we print the results to an HTML file
03503        QFile file(htmlfilename);
03504        if(!file.open(QIODevice::WriteOnly)){
03505               QMessageBox::critical(parent, tr("FET critical"),
03506                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
03507               return;
03508               assert(0);
03509        }
03510        QTextStream tos(&file);
03511        tos.setCodec("UTF-8");
03512        tos.setGenerateByteOrderMark(true);
03513 
03514        tos<<writeHead(true, placedActivities, true);
03515        tos<<writeTOCDays(false);
03516 
03517        for(int day=0; day<gt.rules.nDaysPerWeek; day++){
03518               QSet<int> tmp;
03519               tos<<singleSubjectsTimetableTimeVerticalDailyHtml(TIMETABLE_HTML_LEVEL, day, gt.rules.nInternalSubjects, tmp, saveTime, true);
03520 
03521               tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
03522        }
03523 
03524        tos << "  </body>\n</html>\n";
03525 
03526        if(file.error()>0){
03527               QMessageBox::critical(parent, tr("FET critical"),
03528                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
03529        }
03530        file.close();
03531 }
03532 
03533 //XHTML generation code by Volker Dirr (http://timetabling.de/)
03534 void TimetableExport::writeSubjectsTimetableTimeHorizontalDailyHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
03535        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
03536        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
03537 
03538        //Now we print the results to an HTML file
03539        QFile file(htmlfilename);
03540        if(!file.open(QIODevice::WriteOnly)){
03541               QMessageBox::critical(parent, tr("FET critical"),
03542                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
03543               return;
03544               assert(0);
03545        }
03546        QTextStream tos(&file);
03547        tos.setCodec("UTF-8");
03548        tos.setGenerateByteOrderMark(true);
03549 
03550        tos<<writeHead(true, placedActivities, true);
03551        tos<<writeTOCDays(false);
03552 
03553        for(int day=0; day<gt.rules.nDaysPerWeek; day++){
03554               QSet<int> tmp;
03555               tos<<singleSubjectsTimetableTimeHorizontalDailyHtml(TIMETABLE_HTML_LEVEL, day, gt.rules.nInternalSubjects, tmp, saveTime, true);
03556 
03557               tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
03558        }
03559        tos << "  </body>\n</html>\n";
03560 
03561        if(file.error()>0){
03562               QMessageBox::critical(parent, tr("FET critical"),
03563                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
03564        }
03565        file.close();
03566 }
03567 
03568 //Print the teachers free periods. Code by Volker Dirr (http://timetabling.de/)
03569 void TimetableExport::writeTeachersFreePeriodsTimetableDaysHorizontalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
03570        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
03571        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
03572 
03573        //Now we print the results to an HTML file
03574        QFile file(htmlfilename);
03575        if(!file.open(QIODevice::WriteOnly)){
03576               QMessageBox::critical(parent, tr("FET critical"),
03577                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
03578               return;
03579               assert(0);
03580        }
03581        QTextStream tos(&file);
03582        tos.setCodec("UTF-8");
03583        tos.setGenerateByteOrderMark(true);
03584 
03585        tos<<writeHead(true, placedActivities, true);
03586 
03587        tos<<"    <ul>\n";
03588        tos<<"      <li><a href=\""<<"#table_DETAILED\">"<<TimetableExport::tr("Teachers' Free Periods")<<" ("<<tr("Detailed")<<")</a></li>\n";
03589        tos<<"      <li><a href=\""<<"#table_LESS_DETAILED\">"<<TimetableExport::tr("Teachers' Free Periods")<<" ("<<tr("Less detailed")<<")</a></li>\n";
03590        tos<<"    </ul>\n    <p>&nbsp;</p>\n\n";
03591 
03592        tos<<"    <div class=\"TEACHER_HAS_SINGLE_GAP\">"<<TimetableExport::tr("Teacher has a single gap")<<"</div>\n";
03593        tos<<"    <div class=\"TEACHER_HAS_BORDER_GAP\">"<<TimetableExport::tr("Teacher has a border gap")<<"</div>\n";
03594        tos<<"    <div class=\"TEACHER_HAS_BIG_GAP\">"<<TimetableExport::tr("Teacher has a big gap")<<"</div>\n";
03595        tos<<"    <div class=\"TEACHER_MUST_COME_EARLIER\">"<<TimetableExport::tr("Teacher must come earlier")<<"</div>\n";
03596        tos<<"    <div class=\"TEACHER_MUST_COME_MUCH_EARLIER\">"<<TimetableExport::tr("Teacher must come much earlier")<<"</div>\n";
03597        tos<<"    <div class=\"TEACHER_MUST_STAY_LONGER\">"<<TimetableExport::tr("Teacher must stay longer")<<"</div>\n";
03598        tos<<"    <div class=\"TEACHER_MUST_STAY_MUCH_LONGER\">"<<TimetableExport::tr("Teacher must stay much longer")<<"</div>\n";
03599        tos<<"    <div class=\"TEACHER_HAS_A_FREE_DAY\">"<<TimetableExport::tr("Teacher has a free day")<<"</div>\n";
03600        tos<<"    <div class=\"TEACHER_IS_NOT_AVAILABLE\">"<<TimetableExport::tr("Teacher is not available")<<"</div>\n";
03601 
03602        tos<<"    <p>&nbsp;</p>\n\n";
03603        
03604        bool PRINT_DETAILED=true;
03605        do{
03606               tos<<singleTeachersFreePeriodsTimetableDaysHorizontalHtml(TIMETABLE_HTML_LEVEL, saveTime, PRINT_DETAILED);
03607               tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
03608               if(PRINT_DETAILED) PRINT_DETAILED=false;
03609               else PRINT_DETAILED=true;
03610        } while(!PRINT_DETAILED);
03611        tos<<"  </body>\n</html>\n";
03612 
03613        if(file.error()>0){
03614               QMessageBox::critical(parent, tr("FET critical"),
03615                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
03616        }
03617        file.close();
03618 }
03619 
03620 //XHTML generation code by Volker Dirr (http://timetabling.de/)
03621 void TimetableExport::writeTeachersFreePeriodsTimetableDaysVerticalHtml(QWidget* parent, const QString& htmlfilename, const QString& saveTime, int placedActivities){
03622        assert(gt.rules.initialized && gt.rules.internalStructureComputed);
03623        assert(students_schedule_ready && teachers_schedule_ready && rooms_schedule_ready);
03624 
03625        //Now we print the results to an HTML file
03626        QFile file(htmlfilename);
03627        if(!file.open(QIODevice::WriteOnly)){
03628               QMessageBox::critical(parent, tr("FET critical"),
03629                TimetableExport::tr("Cannot open file %1 for writing. Please check your disk's free space. Saving of %1 aborted.").arg(htmlfilename));
03630               return;
03631               assert(0);
03632        }
03633        QTextStream tos(&file);
03634        tos.setCodec("UTF-8");
03635        tos.setGenerateByteOrderMark(true);
03636 
03637        tos<<writeHead(true, placedActivities, true);
03638 
03639        tos<<"    <ul>\n";
03640        tos<<"      <li><a href=\""<<"#table_DETAILED\">"<<TimetableExport::tr("Teachers' Free Periods")<<" ("<<tr("Detailed")<<")</a></li>\n";
03641        tos<<"      <li><a href=\""<<"#table_LESS_DETAILED\">"<<TimetableExport::tr("Teachers' Free Periods")<<" ("<<tr("Less detailed")<<")</a></li>\n";
03642        tos<<"    </ul>\n    <p>&nbsp;</p>\n\n";
03643 
03644        tos<<"    <div class=\"TEACHER_HAS_SINGLE_GAP\">"<<TimetableExport::tr("Teacher has a single gap")<<"</div>\n";
03645        tos<<"    <div class=\"TEACHER_HAS_BORDER_GAP\">"<<TimetableExport::tr("Teacher has a border gap")<<"</div>\n";
03646        tos<<"    <div class=\"TEACHER_HAS_BIG_GAP\">"<<TimetableExport::tr("Teacher has a big gap")<<"</div>\n";
03647        tos<<"    <div class=\"TEACHER_MUST_COME_EARLIER\">"<<TimetableExport::tr("Teacher must come earlier")<<"</div>\n";
03648        tos<<"    <div class=\"TEACHER_MUST_COME_MUCH_EARLIER\">"<<TimetableExport::tr("Teacher must come much earlier")<<"</div>\n";
03649        tos<<"    <div class=\"TEACHER_MUST_STAY_LONGER\">"<<TimetableExport::tr("Teacher must stay longer")<<"</div>\n";
03650        tos<<"    <div class=\"TEACHER_MUST_STAY_MUCH_LONGER\">"<<TimetableExport::tr("Teacher must stay much longer")<<"</div>\n";
03651        tos<<"    <div class=\"TEACHER_HAS_A_FREE_DAY\">"<<TimetableExport::tr("Teacher has a free day")<<"</div>\n";
03652        tos<<"    <div class=\"TEACHER_IS_NOT_AVAILABLE\">"<<TimetableExport::tr("Teacher is not available")<<"</div>\n";
03653 
03654        tos<<"    <p>&nbsp;</p>\n\n";
03655 
03656        bool PRINT_DETAILED=true;
03657        do{
03658               tos<<singleTeachersFreePeriodsTimetableDaysVerticalHtml(TIMETABLE_HTML_LEVEL, saveTime, PRINT_DETAILED);
03659 
03660               tos<<"    <p class=\"back\"><a href=\""<<"#top\">"<<TimetableExport::tr("back to the top")<<"</a></p>\n\n";
03661               if(PRINT_DETAILED) PRINT_DETAILED=false;
03662               else PRINT_DETAILED=true;
03663        } while(!PRINT_DETAILED);
03664        tos<<"  </body>\n</html>\n";
03665 
03666        if(file.error()>0){
03667               QMessageBox::critical(parent, tr("FET critical"),
03668                TimetableExport::tr("Writing %1 gave error code %2, which means saving is compromised. Please check your disk's free space.").arg(htmlfilename).arg(file.error()));
03669        }
03670        file.close();
03671 }
03672 
03673 //------------------------------------------------------------------
03674 //------------------------------------------------------------------
03675 
03676 void TimetableExport::computeHashForIDsTimetable(){
03677 // by Volker Dirr
03678 
03679 //TODO if an use a relational data base this is unneded, because we can use the primary key id of the database 
03680 //This is very similar to statistics compute hash. so always check it if you change something here!
03681 
03682 /*     QSet<QString> usedStudents;
03683        for(int i=0; i<gt.rules.nInternalActivities; i++){
03684               foreach(QString st, gt.rules.internalActivitiesList[i].studentsNames){
03685                      if(!usedStudents.contains(st))
03686                             usedStudents<<st;
03687               }
03688        }*/
03689        hashStudentIDsTimetable.clear();
03690        int cnt=1;
03691        for(int i=0; i<gt.rules.augmentedYearsList.size(); i++){
03692               StudentsYear* sty=gt.rules.augmentedYearsList[i];
03693               //if(usedStudents.contains(sty->name)){
03694               if(!hashStudentIDsTimetable.contains(sty->name)){
03695                      hashStudentIDsTimetable.insert(sty->name, CustomFETString::number(cnt));
03696                      cnt++;
03697               }
03698               //}
03699               for(int j=0; j<sty->groupsList.size(); j++){
03700                      StudentsGroup* stg=sty->groupsList[j];
03701               //     if(usedStudents.contains(stg->name)){
03702                      if(!hashStudentIDsTimetable.contains(stg->name)){
03703                             hashStudentIDsTimetable.insert(stg->name, CustomFETString::number(cnt));
03704                             cnt++;
03705                      }
03706               //     }
03707                      for(int k=0; k<stg->subgroupsList.size(); k++){
03708                             StudentsSubgroup* sts=stg->subgroupsList[k];
03709               //            if(usedStudents.contains(sts->name)){
03710                             if(!hashStudentIDsTimetable.contains(sts->name)){
03711                                    hashStudentIDsTimetable.insert(sts->name, CustomFETString::number(cnt));
03712                                    cnt++;
03713                             }
03714               //            }
03715                      }
03716               }
03717        }
03718 
03719        hashSubjectIDsTimetable.clear();
03720        for(int i=0; i<gt.rules.nInternalSubjects; i++){
03721               hashSubjectIDsTimetable.insert(gt.rules.internalSubjectsList[i]->name, CustomFETString::number(i+1));
03722        }
03723        hashActivityTagIDsTimetable.clear();
03724        for(int i=0; i<gt.rules.nInternalActivityTags; i++){
03725               hashActivityTagIDsTimetable.insert(gt.rules.internalActivityTagsList[i]->name, CustomFETString::number(i+1));
03726        }
03727        hashTeacherIDsTimetable.clear();
03728        for(int i=0; i<gt.rules.nInternalTeachers; i++){
03729               hashTeacherIDsTimetable.insert(gt.rules.internalTeachersList[i]->name, CustomFETString::number(i+1));
03730        }
03731        hashRoomIDsTimetable.clear();
03732        for(int room=0; room<gt.rules.nInternalRooms; room++){
03733               hashRoomIDsTimetable.insert(gt.rules.internalRoomsList[room]->name, CustomFETString::number(room+1));
03734        }
03735        hashDayIDsTimetable.clear();
03736        for(int day=0; day<gt.rules.nDaysPerWeek; day++){
03737               hashDayIDsTimetable.insert(gt.rules.daysOfTheWeek[day], CustomFETString::number(day+1));
03738        }
03739 }
03740 
03741 void TimetableExport::computeActivitiesAtTime(){        // by Liviu Lalescu
03742        for(int day=0; day<gt.rules.nDaysPerWeek; day++)
03743               for(int hour=0; hour<gt.rules.nHoursPerDay; hour++)
03744                      activitiesAtTime[day][hour].clear();
03745        for(int i=0; i<gt.rules.nInternalActivities; i++) {            //maybe TODO: maybe it is better to do this sorted by students or teachers?
03746               Activity* act=&gt.rules.internalActivitiesList[i];
03747               if(best_solution.times[i]!=UNALLOCATED_TIME) {
03748                      int hour=best_solution.times[i]/gt.rules.nDaysPerWeek;
03749                      int day=best_solution.times[i]%gt.rules.nDaysPerWeek;
03750                      for(int dd=0; dd < act->duration && hour+dd < gt.rules.nHoursPerDay; dd++)
03751                             activitiesAtTime[day][hour+dd].append(i);
03752               }
03753        }
03754 }
03755 
03756 
03757 void TimetableExport::computeActivitiesWithSameStartingTime(){
03758 // by Volker Dirr
03759        activitiesWithSameStartingTime.clear();
03760 
03761        if(PRINT_ACTIVITIES_WITH_SAME_STARTING_TIME){
03762               for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
03763                      TimeConstraint* tc=gt.rules.internalTimeConstraintsList[i];
03764                      if(tc->type==CONSTRAINT_ACTIVITIES_SAME_STARTING_TIME){ //not needed anymore:  && tc->weightPercentage==100
03765                             ConstraintActivitiesSameStartingTime* c=(ConstraintActivitiesSameStartingTime*) tc;
03766                             for(int a=0; a<c->_n_activities; a++){
03767                                    //speed improvement
03768                                    QList<int> & tmpList=activitiesWithSameStartingTime[c->_activities[a]];
03769                                    for(int b=0; b<c->_n_activities; b++){
03770                                           if(a!=b){
03771                                                  if(best_solution.times[c->_activities[a]]==best_solution.times[c->_activities[b]]){        //because constraint is maybe not with 100% weight and failed
03772                                                         if(!tmpList.contains(c->_activities[b])){
03773                                                                tmpList<<c->_activities[b];
03774                                                         }
03775                                                  }
03776                                           }
03777                                    }
03778                                    /*
03779                                    QList<int> tmpList;
03780                                    if(activitiesWithSameStartingTime.contains(c->_activities[a]))
03781                                           tmpList=activitiesWithSameStartingTime.value(c->_activities[a]);
03782                                    for(int b=0; b<c->_n_activities; b++){
03783                                           if(a!=b){
03784                                                  if(best_solution.times[c->_activities[a]]==best_solution.times[c->_activities[b]]){        //because constraint is maybe not with 100% weight and failed
03785                                                         if(!tmpList.contains(c->_activities[b])){
03786                                                                tmpList<<c->_activities[b];
03787                                                         }
03788                                                  }
03789                                           }
03790                                    }
03791                                    activitiesWithSameStartingTime.insert(c->_activities[a], tmpList);
03792                                    */
03793                             }
03794                      }
03795               }
03796        }
03797 }
03798 
03799 bool TimetableExport::addActivitiesWithSameStartingTime(QList<int>& allActivities, int hour){
03800 // by Volker Dirr
03801        if(PRINT_ACTIVITIES_WITH_SAME_STARTING_TIME){
03802               bool activitiesWithSameStartingtime=false;
03803               QList<int> allActivitiesNew;
03804               foreach(int tmpAct, allActivities){
03805                      allActivitiesNew<<tmpAct;
03806                      if(activitiesWithSameStartingTime.contains(tmpAct)){
03807                             QList<int> sameTimeList=activitiesWithSameStartingTime.value(tmpAct);
03808                             foreach(int sameTimeAct, sameTimeList){
03809                                    if(!allActivitiesNew.contains(sameTimeAct) && !allActivities.contains(sameTimeAct)){
03810                                           if(best_solution.times[sameTimeAct]!=UNALLOCATED_TIME){
03811                                                  Activity* act=&gt.rules.internalActivitiesList[sameTimeAct];
03812                                                  assert(best_solution.times[tmpAct]==best_solution.times[sameTimeAct]);//{
03813                                                         if((best_solution.times[sameTimeAct]/gt.rules.nDaysPerWeek+(act->duration-1))>=hour){
03814                                                                allActivitiesNew<<sameTimeAct;
03815                                                         }
03816                                                         activitiesWithSameStartingtime=true; //don't add this line in previous if command because of activities with different duration!
03817                                                  //}
03818                                           }
03819                                    }
03820                             }
03821                      }
03822               }
03823               //allActivities.clear();
03824               allActivities=allActivitiesNew;
03825               //allActivitiesNew.clear();
03826               return activitiesWithSameStartingtime;
03827        }
03828        else
03829               return false;
03830 }
03831 
03832 // by Volker Dirr
03833 QString TimetableExport::writeHead(bool java, int placedActivities, bool printInstitution){
03834        QString tmp;
03835        tmp+="<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n";
03836        tmp+="  \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n\n";
03837 
03838        if(!LANGUAGE_STYLE_RIGHT_TO_LEFT)
03839               tmp+="<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\""+LANGUAGE_FOR_HTML+"\" xml:lang=\""+LANGUAGE_FOR_HTML+"\">\n";
03840        else
03841               tmp+="<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\""+LANGUAGE_FOR_HTML+"\" xml:lang=\""+LANGUAGE_FOR_HTML+"\" dir=\"rtl\">\n";
03842        tmp+="  <head>\n";
03843        tmp+="    <title>"+protect2(gt.rules.institutionName)+"</title>\n";
03844        tmp+="    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n";
03845        if(TIMETABLE_HTML_LEVEL>=1){
03846               QString cssfilename=INPUT_FILENAME_XML.right(INPUT_FILENAME_XML.length()-INPUT_FILENAME_XML.lastIndexOf(FILE_SEP)-1);
03847               
03848               if(cssfilename.right(4)==".fet")
03849                      cssfilename=cssfilename.left(cssfilename.length()-4);
03850               //else if(INPUT_FILENAME_XML!="")
03851               //     cout<<"Minor problem - input file does not end in .fet extension - might be a problem when saving the timetables"<<" (file:"<<__FILE__<<", line:"<<__LINE__<<")"<<endl;
03852               
03853               cssfilename+="_"+STYLESHEET_CSS;
03854               if(INPUT_FILENAME_XML=="")
03855                      cssfilename=STYLESHEET_CSS;
03856               tmp+="    <link rel=\"stylesheet\" media=\"all\" href=\""+cssfilename+"\" type=\"text/css\" />\n";
03857        }
03858        if(java){
03859               if(TIMETABLE_HTML_LEVEL>=5){  // the following JavaScript code is pretty similar to an example of Les Richardson
03860                      tmp+="    <meta http-equiv=\"Content-Script-Type\" content=\"text/javascript\" />\n";
03861                      tmp+="    <script type=\"text/javascript\">\n";
03862                      tmp+="      function highlight(classval) {\n";
03863                      tmp+="        var spans = document.getElementsByTagName('span');\n";
03864                      tmp+="        for(var i=0; spans.length>i; i++) {\n";
03865                      tmp+="          if (spans[i].className == classval) {\n";
03866                      tmp+="            spans[i].style.backgroundColor = 'lime';\n";
03867                      tmp+="          } else {\n";
03868                      tmp+="            spans[i].style.backgroundColor = 'white';\n";
03869                      tmp+="          }\n";
03870                      tmp+="        }\n";
03871                      tmp+="      }\n";
03872                      tmp+="    </script>\n";
03873               }
03874        }
03875        tmp+="  </head>\n\n";
03876        tmp+="  <body id=\"top\">\n";
03877        if(placedActivities!=gt.rules.nInternalActivities)
03878               tmp+="    <h1>"+TimetableExport::tr("Warning! Only %1 out of %2 activities placed!").arg(placedActivities).arg(gt.rules.nInternalActivities)+"</h1>\n";
03879        if(printInstitution){
03880               tmp+="    <table>\n      <tr align=\"left\" valign=\"top\">\n        <th>"+TimetableExport::tr("Institution name")+":</th>\n        <td>"+protect2(gt.rules.institutionName)+"</td>\n      </tr>\n    </table>\n";
03881               tmp+="    <table>\n      <tr align=\"left\" valign=\"top\">\n        <th>"+TimetableExport::tr("Comments")+":</th>\n        <td>"+protect2(gt.rules.comments).replace(QString("\n"), QString("<br />\n"))+"</td>\n      </tr>\n    </table>\n";
03882        }
03883        return tmp;
03884 }
03885 
03886 // by Volker Dirr
03887 QString TimetableExport::writeTOCDays(bool detailed){
03888        QString tmp;
03889        tmp+="    <p><strong>"+TimetableExport::tr("Table of contents")+"</strong></p>\n";
03890        tmp+="    <ul>\n";
03891        for(int day=0; day<gt.rules.nDaysPerWeek; day++){
03892               tmp+="      <li>\n        ";
03893               if(detailed){
03894                      tmp+=" <a href=\"";
03895                      tmp+="#table_"+hashDayIDsTimetable.value(gt.rules.daysOfTheWeek[day])+"_DETAILED\">"+protect2(gt.rules.daysOfTheWeek[day])+" ("+tr("Detailed")+")</a> /";
03896                      tmp+=" <a href=\"";
03897                      tmp+="#table_"+hashDayIDsTimetable.value(gt.rules.daysOfTheWeek[day])+"\">"+protect2(gt.rules.daysOfTheWeek[day])+" ("+tr("Less detailed")+")</a>\n";
03898               } else{
03899                      tmp+=" <a href=\"";
03900                      tmp+="#table_"+hashDayIDsTimetable.value(gt.rules.daysOfTheWeek[day])+"\">"+protect2(gt.rules.daysOfTheWeek[day])+"</a>\n";
03901               }
03902               tmp+="          </li>\n";
03903        }
03904        tmp+="    </ul>\n    <p>&nbsp;</p>\n";
03905        return tmp;
03906 }
03907 
03908 // by Volker Dirr
03909 QString TimetableExport::writeStartTagTDofActivities(int htmlLevel, const Activity* act, bool detailed, bool colspan, bool rowspan){
03910        QString tmp;
03911        assert(!(colspan && rowspan));
03912        if(detailed)
03913               assert(!colspan && !rowspan);
03914        else
03915               tmp+="          ";
03916        tmp+="<td";
03917        if(rowspan && act->duration>1)
03918               tmp+=" rowspan=\""+CustomFETString::number(act->duration)+"\"";
03919        if(colspan && act->duration>1)
03920               tmp+=" colspan=\""+CustomFETString::number(act->duration)+"\"";
03921        if(htmlLevel==6){
03922               tmp+=" class=\"";
03923               if(act->subjectName.size()>0){
03924                      tmp+="s_"+hashSubjectIDsTimetable.value(act->subjectName);
03925               }
03926               if(act->activityTagsNames.size()>0){
03927                      foreach(QString atn, act->activityTagsNames)
03928                              tmp+=" at_"+hashActivityTagIDsTimetable.value(atn);
03929               }
03930               if(act->studentsNames.size()>0){
03931                      foreach(QString st, act->studentsNames)
03932                             tmp+=" ss_"+hashStudentIDsTimetable.value(st);
03933               }
03934               if(act->teachersNames.size()>0){
03935                      foreach(QString t, act->teachersNames)
03936                             tmp+=" t_"+hashTeacherIDsTimetable.value(t);
03937               }
03938               //i need ai for this!!! so i need a parameter ai?! //TODO
03939               /*int r=best_solution.rooms[ai];
03940               if(r!=UNALLOCATED_SPACE && r!=UNSPECIFIED_ROOM){
03941                      tmp+=" room_"+protect2id(gt.rules.internalRoomsList[r]->name);
03942               }*/
03943               if(detailed)
03944                      tmp+=" detailed";
03945               tmp+="\"";
03946        }
03947        if(detailed && htmlLevel>=1 && htmlLevel<=5)
03948               tmp+=" class=\"detailed\"";
03949        tmp+=">";
03950        return tmp;
03951 }
03952 
03953 // by Volker Dirr
03954 QString TimetableExport::writeSubjectAndActivityTags(int htmlLevel, const Activity* act, const QString& startTag, const QString& startTagAttribute, bool activityTagsOnly, bool printActivityTags){
03955        QString tmp;
03956        if(act->subjectName.size()>0||act->activityTagsNames.size()>0){
03957               if(startTag=="div" && htmlLevel>=3)
03958                      tmp+="<"+startTag+startTagAttribute+">";
03959               if(act->subjectName.size()>0 && !activityTagsOnly){
03960                      switch(htmlLevel){
03961                             case 3 : tmp+="<span class=\"subject\">"+protect2(act->subjectName)+"</span>"; break;
03962                             case 4 : tmp+="<span class=\"subject\"><span class=\"s_"+hashSubjectIDsTimetable.value(act->subjectName)+"\">"+protect2(act->subjectName)+"</span></span>"; break;
03963                             case 5 : ;
03964                             case 6 : tmp+="<span class=\"subject\"><span class=\"s_"+hashSubjectIDsTimetable.value(act->subjectName)+"\" onmouseover=\"highlight('s_"+hashSubjectIDsTimetable.value(act->subjectName)+"')\">"+protect2(act->subjectName)+"</span></span>"; break;
03965                             default: tmp+=protect2(act->subjectName); break;
03966                      }
03967                      if(act->activityTagsNames.size()>0 && printActivityTags){
03968                             tmp+=" ";
03969                      }
03970               }
03971               if(act->activityTagsNames.size()>0 && printActivityTags){
03972                      if(!activityTagsOnly){
03973                             if(htmlLevel>=3){
03974                                    tmp+="<span class=\"activitytag\">";
03975                             }
03976                      }
03977                      foreach(QString atn, act->activityTagsNames){
03978                             switch(htmlLevel){
03979                                    case 3 : tmp+=protect2(atn); break;
03980                                    case 4 : tmp+="<span class=\"at_"+hashActivityTagIDsTimetable.value(atn)+"\">"+protect2(atn)+"</span>"; break;
03981                                    case 5 : ;
03982                                    case 6 : tmp+="<span class=\"at_"+hashActivityTagIDsTimetable.value(atn)+"\" onmouseover=\"highlight('at_"+hashActivityTagIDsTimetable.value(atn)+"')\">"+protect2(atn)+"</span>"; break;
03983                                    default: tmp+=protect2(atn); break;
03984                             }
03985                             tmp+=", ";
03986                      }
03987                      tmp.remove(tmp.size()-2, 2);
03988                      if(!activityTagsOnly){
03989                             if(htmlLevel>=3){
03990                                    tmp+="</span>";
03991                             }
03992                      }
03993               }
03994               if(startTag=="div"){
03995                      if(htmlLevel>=3)
03996                             tmp+="</div>";
03997                      else tmp+="<br />";
03998               }
03999        }
04000        return tmp;
04001 }
04002 
04003 // by Volker Dirr
04004 QString TimetableExport::writeStudents(int htmlLevel, const Activity* act, const QString& startTag, const QString& startTagAttribute){
04005        QString tmp;
04006        if(act->studentsNames.size()>0){
04007               if(startTag=="div" && htmlLevel>=3)
04008                      tmp+="<"+startTag+startTagAttribute+">";
04009               foreach(QString st, act->studentsNames){
04010                      switch(htmlLevel){
04011                             case 4 : tmp+="<span class=\"ss_"+hashStudentIDsTimetable.value(st)+"\">"+protect2(st)+"</span>"; break;
04012                             case 5 : ;
04013                             case 6 : tmp+="<span class=\"ss_"+hashStudentIDsTimetable.value(st)+"\" onmouseover=\"highlight('ss_"+hashStudentIDsTimetable.value(st)+"')\">"+protect2(st)+"</span>"; break;
04014                             default: tmp+=protect2(st); break;
04015                      }
04016                      tmp+=", ";
04017               }
04018               tmp.remove(tmp.size()-2, 2);
04019               if(startTag=="div"){
04020                      if(htmlLevel>=3)
04021                             tmp+="</div>";
04022                      else tmp+="<br />";
04023               }
04024        }
04025        return tmp;
04026 }
04027 
04028 // by Volker Dirr
04029 QString TimetableExport::writeTeachers(int htmlLevel, const Activity* act, const QString& startTag, const QString& startTagAttribute){
04030        QString tmp;
04031        if(act->teachersNames.size()>0){
04032               if(startTag=="div" && htmlLevel>=3)
04033                      tmp+="<"+startTag+startTagAttribute+">";
04034               foreach(QString t, act->teachersNames){
04035                      switch(htmlLevel){
04036                             case 4 : tmp+="<span class=\"t_"+hashTeacherIDsTimetable.value(t)+"\">"+protect2(t)+"</span>"; break;
04037                             case 5 : ;
04038                             case 6 : tmp+="<span class=\"t_"+hashTeacherIDsTimetable.value(t)+"\" onmouseover=\"highlight('t_"+hashTeacherIDsTimetable.value(t)+"')\">"+protect2(t)+"</span>"; break;
04039                             default: tmp+=protect2(t); break;
04040                      }
04041                      tmp+=", ";
04042               }
04043               tmp.remove(tmp.size()-2, 2);
04044               if(startTag=="div"){
04045                      if(htmlLevel>=3)
04046                             tmp+="</div>";
04047                      else tmp+="<br />";
04048               }
04049        }
04050        return tmp;
04051 }
04052 
04053 // by Volker Dirr
04054 QString TimetableExport::writeRoom(int htmlLevel, int ai, const QString& startTag, const QString& startTagAttribute){
04055        QString tmp;
04056        int r=best_solution.rooms[ai];
04057        if(r!=UNALLOCATED_SPACE && r!=UNSPECIFIED_ROOM){
04058               if(startTag=="div" && htmlLevel>=3)
04059                      tmp+="<"+startTag+startTagAttribute+">";
04060               switch(htmlLevel){
04061                      case 4 : tmp+="<span class=\"r_"+hashRoomIDsTimetable.value(gt.rules.internalRoomsList[r]->name)+"\">"+protect2(gt.rules.internalRoomsList[r]->name)+"</span>"; break;
04062                      case 5 : ;
04063                      case 6 : tmp+="<span class=\"r_"+hashRoomIDsTimetable.value(gt.rules.internalRoomsList[r]->name)+"\" onmouseover=\"highlight('r_"+hashRoomIDsTimetable.value(gt.rules.internalRoomsList[r]->name)+"')\">"+protect2(gt.rules.internalRoomsList[r]->name)+"</span>"; break;
04064                      default: tmp+=protect2(gt.rules.internalRoomsList[r]->name); break;
04065               }
04066               if(startTag=="div"){
04067                      if(htmlLevel>=3)
04068                             tmp+="</div>";
04069                      else tmp+="<br />";
04070               }
04071        }
04072        return tmp;
04073 }
04074 
04075 // by Volker Dirr
04076 QString TimetableExport::writeNotAvailableSlot(int htmlLevel, const QString& weight){
04077        QString tmp;
04078        //weight=" "+weight;
04079        switch(htmlLevel){
04080               case 3 : ;
04081               case 4 : tmp="          <td class=\"notAvailable\"><span class=\"notAvailable\">"+protect2(STRING_NOT_AVAILABLE_TIME_SLOT)+weight+"</span></td>\n"; break;
04082               case 5 : ;
04083               case 6 : tmp="          <td class=\"notAvailable\"><span class=\"notAvailable\" onmouseover=\"highlight('notAvailable')\">"+protect2(STRING_NOT_AVAILABLE_TIME_SLOT)+weight+"</span></td>\n"; break;
04084               default: tmp="          <td>"+protect2(STRING_NOT_AVAILABLE_TIME_SLOT)+weight+"</td>\n";
04085        }
04086        return tmp;
04087 }
04088 
04089 // by Volker Dirr
04090 QString TimetableExport::writeBreakSlot(int htmlLevel, const QString& weight){
04091        QString tmp;
04092        //weight=" "+weight;
04093        switch(htmlLevel){
04094               case 3 : ;
04095               case 4 : tmp="          <td class=\"break\"><span class=\"break\">"+protect2(STRING_BREAK_SLOT)+weight+"</span></td>\n"; break;
04096               case 5 : ;
04097               case 6 : tmp="          <td class=\"break\"><span class=\"break\" onmouseover=\"highlight('break')\">"+protect2(STRING_BREAK_SLOT)+weight+"</span></td>\n"; break;
04098               default: tmp="          <td>"+protect2(STRING_BREAK_SLOT)+weight+"</td>\n";
04099        }
04100        return tmp;
04101 }
04102 
04103 // by Volker Dirr
04104 QString TimetableExport::writeEmpty(int htmlLevel){
04105        QString tmp;
04106        switch(htmlLevel){
04107               case 3 : ;
04108               case 4 : tmp="          <td class=\"empty\"><span class=\"empty\">"+protect2(STRING_EMPTY_SLOT)+"</span></td>\n"; break;
04109               case 5 : ;
04110               case 6 : tmp="          <td class=\"empty\"><span class=\"empty\" onmouseover=\"highlight('empty')\">"+protect2(STRING_EMPTY_SLOT)+"</span></td>\n"; break;
04111               default: tmp="          <td>"+protect2(STRING_EMPTY_SLOT)+"</td>\n";
04112        }
04113        return tmp;
04114 }
04115 
04116 //by Volker Dirr
04117 QString TimetableExport::writeActivityStudents(int htmlLevel, int ai, int day, int hour, bool notAvailable, bool colspan, bool rowspan, bool printActivityTags){
04118        QString tmp;
04119        int currentTime=day+gt.rules.nDaysPerWeek*hour;
04120        if(ai!=UNALLOCATED_ACTIVITY){
04121               if(best_solution.times[ai]==currentTime){
04122                      Activity* act=&gt.rules.internalActivitiesList[ai];
04123                      tmp+=writeStartTagTDofActivities(htmlLevel, act, false, colspan, rowspan);
04124                      tmp+=writeSubjectAndActivityTags(htmlLevel, act, "div", " class=\"line1\"", false, printActivityTags);
04125                      tmp+=writeTeachers(htmlLevel, act, "div", " class=\"teacher line2\"");
04126                      tmp+=writeRoom(htmlLevel, ai, "div", " class=\"room line3\"");
04127                      tmp+="</td>\n";
04128               } else
04129                      tmp+="          <!-- span -->\n";
04130        } else {
04131               if(notAvailable && PRINT_NOT_AVAILABLE_TIME_SLOTS){
04132                      tmp+=writeNotAvailableSlot(htmlLevel, "");
04133               }
04134               else if(breakDayHour[day][hour] && PRINT_BREAK_TIME_SLOTS){
04135                      tmp+=writeBreakSlot(htmlLevel, "");
04136               }
04137               else{
04138                      tmp+=writeEmpty(htmlLevel);
04139               }
04140        }
04141        return tmp;
04142 }
04143 
04144 //by Volker Dirr
04145 QString TimetableExport::writeActivitiesStudents(int htmlLevel, const QList<int>& allActivities, bool printActivityTags){
04146        QString tmp;
04147        if(htmlLevel>=1)
04148               tmp+="          <td><table class=\"detailed\">";
04149        else
04150               tmp+="          <td><table>";
04151        if(htmlLevel>=3)
04152               tmp+="<tr class=\"student line0\">";
04153        else   tmp+="<tr>";
04154        for(int a=0; a<allActivities.size(); a++){
04155               int ai=allActivities[a];
04156               if(ai!=UNALLOCATED_ACTIVITY){
04157                      Activity* act=&gt.rules.internalActivitiesList[ai];
04158                      tmp+=writeStartTagTDofActivities(htmlLevel, act, true, false, false)+writeStudents(htmlLevel, act, "", "")+"</td>";
04159               }
04160        }
04161        tmp+="</tr>";
04162        if(htmlLevel>=3)
04163               tmp+="<tr class=\"line1\">";
04164        else   tmp+="<tr>";
04165        for(int a=0; a<allActivities.size(); a++){
04166               int ai=allActivities[a];
04167               if(ai!=UNALLOCATED_ACTIVITY){
04168                      Activity* act=&gt.rules.internalActivitiesList[ai];
04169                      tmp+=writeStartTagTDofActivities(htmlLevel, act, true, false, false)+writeSubjectAndActivityTags(htmlLevel, act, "", "", false, printActivityTags)+"</td>";
04170               }
04171        }
04172        tmp+="</tr>";
04173        if(htmlLevel>=3)
04174               tmp+="<tr class=\"teacher line2\">";
04175        else   tmp+="<tr>";
04176        for(int a=0; a<allActivities.size(); a++){
04177               int ai=allActivities[a];
04178               if(ai!=UNALLOCATED_ACTIVITY){
04179                      Activity* act=&gt.rules.internalActivitiesList[ai];
04180                      tmp+=writeStartTagTDofActivities(htmlLevel, act, true, false, false)+writeTeachers(htmlLevel, act, "", "")+"</td>";
04181               }
04182        }
04183        tmp+="</tr>";
04184        if(htmlLevel>=3)
04185               tmp+="<tr class=\"room line3\">";
04186        else   tmp+="<tr>";
04187        for(int a=0; a<allActivities.size(); a++){
04188               int ai=allActivities[a];
04189               if(ai!=UNALLOCATED_ACTIVITY){
04190                      Activity* act=&gt.rules.internalActivitiesList[ai];
04191                      tmp+=writeStartTagTDofActivities(htmlLevel, act, true, false, false)+writeRoom(htmlLevel, ai, "", "")+"</td>";
04192               }
04193        }
04194        tmp+="</tr>";
04195        tmp+="</table></td>\n";
04196        return tmp;
04197 }
04198 
04199 //by Volker Dirr
04200 QString TimetableExport::writeActivityTeacher(int htmlLevel, int teacher, int day, int hour, bool colspan, bool rowspan, bool printActivityTags){
04201        QString tmp;
04202        int ai=teachers_timetable_weekly[teacher][day][hour];
04203        int currentTime=day+gt.rules.nDaysPerWeek*hour;
04204        if(ai!=UNALLOCATED_ACTIVITY){
04205               if(best_solution.times[ai]==currentTime){
04206                      Activity* act=&gt.rules.internalActivitiesList[ai];
04207                      tmp+=writeStartTagTDofActivities(htmlLevel, act, false, colspan, rowspan);
04208                      tmp+=writeStudents(htmlLevel, act, "div", " class=\"student line1\"");
04209                      tmp+=writeSubjectAndActivityTags(htmlLevel, act, "div", " class=\"line2\"", false, printActivityTags);
04210                      tmp+=writeRoom(htmlLevel, ai, "div", " class=\"room line3\"");
04211                      tmp+="</td>\n";
04212               } else
04213                      tmp+="          <!-- span -->\n";
04214        } else {
04215               if(teacherNotAvailableDayHour[teacher][day][hour] && PRINT_NOT_AVAILABLE_TIME_SLOTS){
04216                      tmp+=writeNotAvailableSlot(htmlLevel, "");
04217               }
04218               else if(breakDayHour[day][hour] && PRINT_BREAK_TIME_SLOTS){
04219                      tmp+=writeBreakSlot(htmlLevel, "");
04220               }
04221               else{
04222                      tmp+=writeEmpty(htmlLevel);
04223               }
04224        }
04225        return tmp;
04226 }
04227 
04228 //by Volker Dirr
04229 QString TimetableExport::writeActivitiesTeachers(int htmlLevel, const QList<int>& allActivities, bool printActivityTags){
04230        QString tmp;
04231        if(htmlLevel>=1)
04232               tmp+="          <td><table class=\"detailed\">";
04233        else
04234               tmp+="          <td><table>";
04235        if(htmlLevel>=3)
04236               tmp+="<tr class=\"teacher line0\">";
04237        else   tmp+="<tr>";
04238        for(int a=0; a<allActivities.size(); a++){
04239               int ai=allActivities[a];
04240               if(ai!=UNALLOCATED_ACTIVITY){
04241                      Activity* act=&gt.rules.internalActivitiesList[ai];
04242                      tmp+=writeStartTagTDofActivities(htmlLevel, act, true, false, false)+writeTeachers(htmlLevel, act, "", "")+"</td>";
04243               }
04244        }
04245        tmp+="</tr>";
04246        if(htmlLevel>=3)
04247               tmp+="<tr class=\"student line1\">";
04248        else   tmp+="<tr>";
04249        for(int a=0; a<allActivities.size(); a++){
04250               int ai=allActivities[a];
04251               if(ai!=UNALLOCATED_ACTIVITY){
04252                      Activity* act=&gt.rules.internalActivitiesList[ai];
04253                      tmp+=writeStartTagTDofActivities(htmlLevel, act, true, false, false)+writeStudents(htmlLevel, act, "", "")+"</td>";
04254               }
04255        }
04256        tmp+="</tr>";
04257        if(htmlLevel>=3)
04258               tmp+="<tr class=\"line2\">";
04259        else   tmp+="<tr>";
04260        for(int a=0; a<allActivities.size(); a++){
04261               int ai=allActivities[a];
04262               if(ai!=UNALLOCATED_ACTIVITY){
04263                      Activity* act=&gt.rules.internalActivitiesList[ai];
04264                      tmp+=writeStartTagTDofActivities(htmlLevel, act, true, false, false)+writeSubjectAndActivityTags(htmlLevel, act, "", "", false, printActivityTags)+"</td>";
04265               }
04266        }
04267        tmp+="</tr>";
04268 
04269        if(htmlLevel>=3)
04270               tmp+="<tr class=\"room line3\">";
04271        else   tmp+="<tr>";
04272        for(int a=0; a<allActivities.size(); a++){
04273               int ai=allActivities[a];
04274               if(ai!=UNALLOCATED_ACTIVITY){
04275                      Activity* act=&gt.rules.internalActivitiesList[ai];
04276                      tmp+=writeStartTagTDofActivities(htmlLevel, act, true, false, false)+writeRoom(htmlLevel, ai, "", "")+"</td>";
04277               }
04278        }
04279        tmp+="</tr>";
04280        tmp+="</table></td>\n";
04281        return tmp;
04282 }
04283 
04284 //by Volker Dirr
04285 QString TimetableExport::writeActivityRoom(int htmlLevel, int room, int day, int hour, bool colspan, bool rowspan, bool printActivityTags){
04286        QString tmp;
04287        int ai=rooms_timetable_weekly[room][day][hour];
04288        int currentTime=day+gt.rules.nDaysPerWeek*hour;
04289        if(ai!=UNALLOCATED_ACTIVITY){
04290               if(best_solution.times[ai]==currentTime){
04291                      Activity* act=&gt.rules.internalActivitiesList[ai];
04292                      tmp+=writeStartTagTDofActivities(htmlLevel, act, false, colspan, rowspan);
04293                      tmp+=writeStudents(htmlLevel, act, "div", " class=\"student line1\"");
04294                      tmp+=writeTeachers(htmlLevel, act, "div", " class=\"teacher line2\"");
04295                      tmp+=writeSubjectAndActivityTags(htmlLevel, act, "div", " class=\"line3\"", false, printActivityTags);
04296                      tmp+="</td>\n";
04297               } else
04298                      tmp+="          <!-- span -->\n";
04299        } else {
04300               if(notAllowedRoomTimePercentages[room][day+hour*gt.rules.nDaysPerWeek]>=0 && PRINT_NOT_AVAILABLE_TIME_SLOTS){
04301                      tmp+=writeNotAvailableSlot(htmlLevel, "");
04302               }
04303               else if(breakDayHour[day][hour] && PRINT_BREAK_TIME_SLOTS){
04304                      tmp+=writeBreakSlot(htmlLevel, "");
04305               }
04306               else{
04307                      tmp+=writeEmpty(htmlLevel);
04308               }
04309        }
04310        return tmp;
04311 }
04312 
04313 //by Volker Dirr
04314 QString TimetableExport::writeActivitiesRooms(int htmlLevel, const QList<int>& allActivities, bool printActivityTags){
04315        QString tmp;
04316        if(htmlLevel>=1)
04317               tmp+="          <td><table class=\"detailed\">";
04318        else
04319               tmp+="          <td><table>";
04320        if(htmlLevel>=3)
04321               tmp+="<tr class=\"room line0\">";
04322        else   tmp+="<tr>";
04323        for(int a=0; a<allActivities.size(); a++){
04324               int ai=allActivities[a];
04325               if(ai!=UNALLOCATED_ACTIVITY){
04326                      Activity* act=&gt.rules.internalActivitiesList[ai];
04327                      tmp+=writeStartTagTDofActivities(htmlLevel, act, true, false, false)+writeRoom(htmlLevel, ai, "", "")+"</td>";
04328               }
04329        }
04330        tmp+="</tr>";
04331        if(htmlLevel>=3)
04332               tmp+="<tr class=\"student line1\">";
04333        else   tmp+="<tr>";
04334        for(int a=0; a<allActivities.size(); a++){
04335               int ai=allActivities[a];
04336               if(ai!=UNALLOCATED_ACTIVITY){
04337                      Activity* act=&gt.rules.internalActivitiesList[ai];
04338                      tmp+=writeStartTagTDofActivities(htmlLevel, act, true, false, false)+writeStudents(htmlLevel, act, "", "")+"</td>";
04339               }
04340        }
04341        tmp+="</tr>";
04342        if(htmlLevel>=3)
04343               tmp+="<tr class=\"teacher line2\">";
04344        else   tmp+="<tr>";
04345        for(int a=0; a<allActivities.size(); a++){
04346               int ai=allActivities[a];
04347               if(ai!=UNALLOCATED_ACTIVITY){
04348                      Activity* act=&gt.rules.internalActivitiesList[ai];
04349                      tmp+=writeStartTagTDofActivities(htmlLevel, act, true, false, false)+writeTeachers(htmlLevel, act, "", "")+"</td>";
04350               }
04351        }
04352        tmp+="</tr>";
04353        if(htmlLevel>=3)
04354               tmp+="<tr class=\"line3\">";
04355        else   tmp+="<tr>";
04356        for(int a=0; a<allActivities.size(); a++){
04357               int ai=allActivities[a];
04358               if(ai!=UNALLOCATED_ACTIVITY){
04359                      Activity* act=&gt.rules.internalActivitiesList[ai];
04360                      tmp+=writeStartTagTDofActivities(htmlLevel, act, true, false, false)+writeSubjectAndActivityTags(htmlLevel, act, "", "", false, printActivityTags)+"</td>";
04361               }
04362        }
04363        tmp+="</tr>";
04364 
04365        tmp+="</table></td>\n";
04366        return tmp;
04367 }
04368 
04369 //by Volker Dirr
04370 QString TimetableExport::writeActivitiesSubjects(int htmlLevel, const QList<int>& allActivities, bool printActivityTags){
04371        QString tmp;
04372        if(allActivities.isEmpty()){
04373               tmp+=writeEmpty(htmlLevel);
04374        } else {
04375               if(htmlLevel>=1)
04376                      tmp+="          <td><table class=\"detailed\">";
04377               else
04378                                           tmp+="          <td><table>";
04379               if(printActivityTags){
04380                      if(htmlLevel>=3)
04381                             tmp+="<tr class=\"line0 activitytag\">";
04382                      else   tmp+="<tr>";
04383                      for(int a=0; a<allActivities.size(); a++){
04384                             Activity* act=&gt.rules.internalActivitiesList[allActivities[a]];
04385                             tmp+=writeStartTagTDofActivities(htmlLevel, act, true, false, false)+writeSubjectAndActivityTags(htmlLevel, act, "", "", true, printActivityTags)+"</td>";
04386                      }
04387                      tmp+="</tr>";
04388               }
04389               if(htmlLevel>=3)
04390                      tmp+="<tr class=\"student line1\">";
04391               else   tmp+="<tr>";
04392               for(int a=0; a<allActivities.size(); a++){
04393                      Activity* act=&gt.rules.internalActivitiesList[allActivities[a]];
04394                      tmp+=writeStartTagTDofActivities(htmlLevel, act, true, false, false)+writeStudents(htmlLevel, act, "", "")+"</td>";    
04395               }
04396               tmp+="</tr>";
04397               if(htmlLevel>=3)
04398                      tmp+="<tr class=\"teacher line2\">";
04399               else   tmp+="<tr>";
04400               for(int a=0; a<allActivities.size(); a++){
04401                      Activity* act=&gt.rules.internalActivitiesList[allActivities[a]];
04402                      tmp+=writeStartTagTDofActivities(htmlLevel, act, true, false, false)+writeTeachers(htmlLevel, act, "", "")+"</td>";
04403               }
04404               tmp+="</tr>";
04405               if(htmlLevel>=3)
04406                      tmp+="<tr class=\"room line3\">";
04407               else   tmp+="<tr>";
04408               for(int a=0; a<allActivities.size(); a++){
04409                      int ai=allActivities[a];
04410                      Activity* act=&gt.rules.internalActivitiesList[ai];
04411                      tmp+=writeStartTagTDofActivities(htmlLevel, act, true, false, false)+writeRoom(htmlLevel, ai, "", "")+"</td>";
04412               }
04413               tmp+="</tr>";
04414               tmp+="</table></td>\n";
04415        }
04416        return tmp;
04417 }
04418 
04419 //the following functions return a single html table (needed for html file export and printing)
04420 
04421 //by Volker Dirr
04422 QString TimetableExport::singleSubgroupsTimetableDaysHorizontalHtml(int htmlLevel, int subgroup, const QString& saveTime, bool printActivityTags){
04423        assert(subgroup>=0);
04424        assert(subgroup<gt.rules.nInternalSubgroups);
04425        QString tmpString;
04426        QString subgroup_name = gt.rules.internalSubgroupsList[subgroup]->name;
04427        tmpString+="    <table id=\"table_"+hashStudentIDsTimetable.value(subgroup_name)+"\" border=\"1\"";
04428        if(subgroup%2==0) tmpString+=" class=\"odd_table\"";
04429        else tmpString+=" class=\"even_table\"";
04430        tmpString+=">\n";
04431               
04432        tmpString+="      <caption>"+protect2(gt.rules.institutionName)+"</caption>\n";
04433        tmpString+="      <thead>\n        <tr><td rowspan=\"2\"></td><th colspan=\""+QString::number(gt.rules.nDaysPerWeek)+"\">"+protect2(subgroup_name)+"</th></tr>\n";
04434        tmpString+="        <tr>\n          <!-- span -->\n";
04435        for(int day=0; day<gt.rules.nDaysPerWeek; day++){
04436               if(htmlLevel>=2)
04437                      tmpString+="          <th class=\"xAxis\">";
04438               else
04439                      tmpString+="          <th>";
04440               tmpString+=protect2(gt.rules.daysOfTheWeek[day])+"</th>\n";
04441        }
04442        tmpString+="        </tr>\n";
04443        tmpString+="      </thead>\n";
04444        /*workaround
04445        tmpString+="      <tfoot><tr><td></td><td colspan=\""+gt.rules.nDaysPerWeek+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr></tfoot>\n";
04446        */
04447        tmpString+="      <tbody>\n";
04448        for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
04449        tmpString+="        <tr>\n";
04450        if(htmlLevel>=2)
04451                      tmpString+="          <th class=\"yAxis\">";
04452               else
04453                      tmpString+="          <th>";
04454               tmpString+=protect2(gt.rules.hoursOfTheDay[hour])+"</th>\n";
04455               for(int day=0; day<gt.rules.nDaysPerWeek; day++){
04456                      QList<int> allActivities;
04457                      allActivities.clear();
04458                      allActivities<<students_timetable_weekly[subgroup][day][hour];
04459                      bool activitiesWithSameStartingtime=addActivitiesWithSameStartingTime(allActivities, hour);
04460                      if(allActivities.size()==1 && !activitiesWithSameStartingtime){  // because i am using colspan or rowspan!!!
04461                             tmpString+=writeActivityStudents(htmlLevel, students_timetable_weekly[subgroup][day][hour], day, hour, subgroupNotAvailableDayHour[subgroup][day][hour], false, true, printActivityTags);
04462                      } else{
04463                             tmpString+=writeActivitiesStudents(htmlLevel, allActivities, printActivityTags);
04464                      }
04465               }
04466               tmpString+="        </tr>\n";
04467        }
04468        //workaround begin.
04469        tmpString+="        <tr class=\"foot\"><td></td><td colspan=\""+QString::number(gt.rules.nDaysPerWeek)+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr>\n";
04470        //workaround end.
04471        tmpString+="      </tbody>\n";
04472        tmpString+="    </table>\n\n";
04473        return tmpString;
04474 }
04475        
04476 //by Volker Dirr
04477 QString TimetableExport::singleSubgroupsTimetableDaysVerticalHtml(int htmlLevel, int subgroup, const QString& saveTime, bool printActivityTags){
04478        assert(subgroup>=0);
04479        assert(subgroup<gt.rules.nInternalSubgroups);
04480        QString tmpString;
04481        QString subgroup_name = gt.rules.internalSubgroupsList[subgroup]->name;
04482        tmpString+="    <table id=\"table_"+hashStudentIDsTimetable.value(subgroup_name)+"\" border=\"1\"";
04483        if(subgroup%2==0) tmpString+=" class=\"odd_table\"";
04484        else tmpString+=" class=\"even_table\"";
04485        tmpString+=">\n";
04486        
04487        tmpString+="      <caption>"+protect2(gt.rules.institutionName)+"</caption>\n";
04488               tmpString+="      <thead>\n        <tr><td rowspan=\"2\"></td><th colspan=\""+QString::number(gt.rules.nHoursPerDay)+"\">"+protect2(subgroup_name)+"</th></tr>\n";
04489        tmpString+="        <tr>\n          <!-- span -->\n";
04490        for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
04491               if(htmlLevel>=2)
04492                      tmpString+="          <th class=\"xAxis\">";
04493               else
04494                      tmpString+="          <th>";
04495               tmpString+=protect2(gt.rules.hoursOfTheDay[hour])+"</th>\n";
04496        }
04497        tmpString+="        </tr>\n";
04498        tmpString+="      </thead>\n";
04499        /*workaround
04500        tmpString+="      <tfoot><tr><td></td><td colspan=\""+gt.rules.nHoursPerDay+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr></tfoot>\n";
04501        */
04502        tmpString+="      <tbody>\n";
04503        for(int day=0; day<gt.rules.nDaysPerWeek; day++){
04504               tmpString+="        <tr>\n";
04505               if(htmlLevel>=2)
04506                      tmpString+="          <th class=\"yAxis\">";
04507               else
04508                      tmpString+="          <th>";
04509               tmpString+=protect2(gt.rules.daysOfTheWeek[day])+"</th>\n";
04510                      for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
04511                      QList<int> allActivities;
04512                      allActivities.clear();
04513                      allActivities<<students_timetable_weekly[subgroup][day][hour];
04514                      bool activitiesWithSameStartingtime=addActivitiesWithSameStartingTime(allActivities, hour);
04515                      if(allActivities.size()==1 && !activitiesWithSameStartingtime){  // because i am using colspan or rowspan!!!
04516                             tmpString+=writeActivityStudents(htmlLevel, students_timetable_weekly[subgroup][day][hour], day, hour, subgroupNotAvailableDayHour[subgroup][day][hour], true, false, printActivityTags);
04517                      } else{
04518                             tmpString+=writeActivitiesStudents(htmlLevel, allActivities, printActivityTags);
04519                      }
04520               }
04521               tmpString+="        </tr>\n";
04522        }
04523        //workaround begin.
04524        tmpString+="        <tr class=\"foot\"><td></td><td colspan=\""+QString::number(gt.rules.nHoursPerDay)+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr>\n";
04525        //workaround end.
04526        tmpString+="      </tbody>\n";
04527        tmpString+="    </table>\n\n";
04528        return tmpString;
04529 }
04530        
04531 //by Volker Dirr
04532 QString TimetableExport::singleSubgroupsTimetableTimeVerticalHtml(int htmlLevel, int maxSubgroups, QSet<int>& excludedNames, const QString& saveTime, bool printActivityTags){
04533        QString tmpString;
04534        tmpString+="    <table border=\"1\">\n";
04535        tmpString+="      <caption>"+protect2(gt.rules.institutionName)+"</caption>\n";
04536 
04537        tmpString+="      <thead>\n        <tr><td colspan=\"2\"></td>";
04538        
04539        int currentCount=0;
04540        for(int subgroup=0; subgroup<gt.rules.nInternalSubgroups && currentCount<maxSubgroups; subgroup++){
04541               if(!excludedNames.contains(subgroup)){
04542                      currentCount++;
04543                      if(htmlLevel>=2)
04544                             tmpString+="          <th class=\"xAxis\">";
04545                      else
04546                             tmpString+="          <th>";
04547                      tmpString+=gt.rules.internalSubgroupsList[subgroup]->name+"</th>";
04548               }
04549        }
04550        tmpString+="</tr>\n      </thead>\n";
04551        /*workaround
04552        tmpString+="      <tfoot><tr><td colspan=\"2\"></td><td colspan=\""+QString::number(currentCount)+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr></tfoot>\n";
04553        */
04554        tmpString+="      <tbody>\n";
04555        for(int day=0; day<gt.rules.nDaysPerWeek; day++){
04556               for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
04557                      tmpString+="        <tr>\n";
04558                      if(hour==0)
04559                             tmpString+="        <th rowspan=\"" +QString::number(gt.rules.nHoursPerDay)+"\">"+protect2vert(gt.rules.daysOfTheWeek[day])+"</th>\n";
04560                      else tmpString+="          <!-- span -->\n";
04561 
04562                      if(htmlLevel>=2)
04563                             tmpString+="          <th class=\"yAxis\">";
04564                      else
04565                             tmpString+="          <th>";
04566                      tmpString+=protect2(gt.rules.hoursOfTheDay[hour])+"</th>\n";
04567                      currentCount=0;
04568                      for(int subgroup=0; subgroup<gt.rules.nInternalSubgroups && currentCount<maxSubgroups; subgroup++){
04569                             if(!excludedNames.contains(subgroup)){
04570                                    currentCount++;
04571                                    if(day+1==gt.rules.nDaysPerWeek && hour+1==gt.rules.nHoursPerDay)
04572                                           excludedNames<<subgroup;
04573                                    QList<int> allActivities;
04574                                    allActivities.clear();
04575                                    allActivities<<students_timetable_weekly[subgroup][day][hour];
04576                                    bool activitiesWithSameStartingtime=addActivitiesWithSameStartingTime(allActivities, hour);
04577                                    if(allActivities.size()==1 && !activitiesWithSameStartingtime){  // because i am using colspan or rowspan!!!
04578                                           tmpString+=writeActivityStudents(htmlLevel, students_timetable_weekly[subgroup][day][hour], day, hour, subgroupNotAvailableDayHour[subgroup][day][hour], false, true, printActivityTags);
04579                                    } else{
04580                                           tmpString+=writeActivitiesStudents(htmlLevel, allActivities, printActivityTags);
04581                                    }
04582                             }
04583                      }
04584                      tmpString+="        </tr>\n";
04585               }
04586        }
04587        //workaround begin.
04588        tmpString+="      <tr class=\"foot\"><td colspan=\"2\"></td><td colspan=\""+QString::number(currentCount)+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr>\n";
04589        //workaround end.
04590        tmpString+="      </tbody>\n    </table>\n";
04591        return tmpString;
04592 }
04593 
04594 //by Volker Dirr
04595 QString TimetableExport::singleSubgroupsTimetableTimeHorizontalHtml(int htmlLevel, int maxSubgroups, QSet<int>& excludedNames, const QString& saveTime, bool printActivityTags){
04596        QString tmpString;
04597        tmpString+="    <table border=\"1\">\n";
04598        tmpString+="      <caption>"+protect2(gt.rules.institutionName)+"</caption>\n";
04599 
04600        tmpString+="      <thead>\n        <tr><td rowspan=\"2\"></td>";
04601        for(int day=0; day<gt.rules.nDaysPerWeek; day++)
04602               tmpString+="<th colspan=\"" +QString::number(gt.rules.nHoursPerDay)+"\">"+protect2(gt.rules.daysOfTheWeek[day])+"</th>";
04603        tmpString+="        </tr>\n";
04604        tmpString+="        <tr>\n          <!-- span -->\n";
04605        for(int day=0; day<gt.rules.nDaysPerWeek; day++)
04606               for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
04607                      if(htmlLevel>=2)
04608                             tmpString+="          <th class=\"xAxis\">";
04609                      else
04610                             tmpString+="          <th>";
04611                      tmpString+=protect2(gt.rules.hoursOfTheDay[hour])+"</th>\n";
04612               }
04613        tmpString+="        </tr>\n";
04614        tmpString+="      </thead>\n";
04615        /*workaround
04616        tmpString+="      <tfoot><tr><td></td><td colspan=\""+gt.rules.nHoursPerDay*gt.rules.nDaysPerWeek+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr></tfoot>\n";
04617        */
04618        tmpString+="      <tbody>\n";
04619        
04620        int currentCount=0;
04621        for(int subgroup=0; subgroup<gt.rules.nInternalSubgroups && currentCount<maxSubgroups; subgroup++){
04622               if(!excludedNames.contains(subgroup)){
04623                      currentCount++;
04624                      excludedNames<<subgroup;
04625                      tmpString+="        <tr>\n";
04626                      if(htmlLevel>=2)
04627                             tmpString+="          <th class=\"yAxis\">";
04628                      else
04629                             tmpString+="          <th>";
04630                      tmpString+=gt.rules.internalSubgroupsList[subgroup]->name+"</th>\n";
04631                      for(int day=0; day<gt.rules.nDaysPerWeek; day++){
04632                             for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
04633                                    QList<int> allActivities;
04634                                    allActivities.clear();
04635                                    allActivities<<students_timetable_weekly[subgroup][day][hour];
04636                                    bool activitiesWithSameStartingtime=addActivitiesWithSameStartingTime(allActivities, hour);
04637                                    if(allActivities.size()==1 && !activitiesWithSameStartingtime){  // because i am using colspan or rowspan!!!
04638                                           tmpString+=writeActivityStudents(htmlLevel, students_timetable_weekly[subgroup][day][hour], day, hour, subgroupNotAvailableDayHour[subgroup][day][hour], true, false, printActivityTags);
04639                                    } else{
04640                                           tmpString+=writeActivitiesStudents(htmlLevel, allActivities, printActivityTags);
04641                                    }
04642                             }
04643                      }
04644                      tmpString+="        </tr>\n";
04645               }
04646        }
04647        //workaround begin.
04648        tmpString+="      <tr class=\"foot\"><td></td><td colspan=\""+QString::number(gt.rules.nHoursPerDay*gt.rules.nDaysPerWeek)+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr>\n";
04649        //workaround end.
04650        tmpString+="      </tbody>\n    </table>\n";
04651        return tmpString;
04652 }
04653 
04654 //by Volker Dirr
04655 QString TimetableExport::singleSubgroupsTimetableTimeVerticalDailyHtml(int htmlLevel, int day, int maxSubgroups, QSet<int>& excludedNames, const QString& saveTime, bool printActivityTags){
04656        assert(day>=0);
04657        assert(day<gt.rules.nDaysPerWeek);
04658        
04659        QString tmpString;
04660        tmpString+="    <table id=\"table_"+hashDayIDsTimetable.value(gt.rules.daysOfTheWeek[day])+"\" border=\"1\">\n";
04661        tmpString+="      <caption>"+protect2(gt.rules.institutionName)+"</caption>\n";
04662        
04663        tmpString+="      <thead>\n        <tr><td colspan=\"2\"></td>";
04664        int currentCount=0;
04665        for(int subgroup=0; subgroup<gt.rules.nInternalSubgroups && currentCount<maxSubgroups; subgroup++){
04666               if(!excludedNames.contains(subgroup)){
04667                      currentCount++;
04668                      if(htmlLevel>=2)
04669                             tmpString+="          <th class=\"xAxis\">";
04670                      else
04671                             tmpString+="          <th>";
04672                      tmpString+=gt.rules.internalSubgroupsList[subgroup]->name+"</th>";
04673               }
04674        }
04675        tmpString+="</tr>\n      </thead>\n";
04676        /*workaround
04677        tmpString+="      <tfoot><tr><td colspan=\"2\"></td><td colspan=\""+QString::number(currentCount)+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr></tfoot>\n";
04678        */
04679        tmpString+="      <tbody>\n";
04680        for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
04681               tmpString+="        <tr>\n";
04682               if(hour==0)
04683                      tmpString+="        <th rowspan=\""+QString::number(gt.rules.nHoursPerDay)+"\">"+protect2vert(gt.rules.daysOfTheWeek[day])+"</th>\n";
04684               else tmpString+="          <!-- span -->\n";
04685                      if(htmlLevel>=2)
04686                      tmpString+="          <th class=\"yAxis\">";
04687               else
04688                      tmpString+="          <th>";
04689               tmpString+=protect2(gt.rules.hoursOfTheDay[hour])+"</th>\n";
04690               currentCount=0;
04691               for(int subgroup=0; subgroup<gt.rules.nInternalSubgroups && currentCount<maxSubgroups; subgroup++){
04692                      if(!excludedNames.contains(subgroup)){
04693                             currentCount++;
04694                             if(hour+1==gt.rules.nHoursPerDay)
04695                                    excludedNames<<subgroup;
04696                             QList<int> allActivities;
04697                             allActivities.clear();
04698                             allActivities<<students_timetable_weekly[subgroup][day][hour];
04699                             bool activitiesWithSameStartingtime=addActivitiesWithSameStartingTime(allActivities, hour);
04700                             if(allActivities.size()==1 && !activitiesWithSameStartingtime){  // because i am using colspan or rowspan!!!
04701                                    tmpString+=writeActivityStudents(htmlLevel, students_timetable_weekly[subgroup][day][hour], day, hour, subgroupNotAvailableDayHour[subgroup][day][hour], false, true, printActivityTags);
04702                             } else{
04703                                    tmpString+=writeActivitiesStudents(htmlLevel, allActivities, printActivityTags);
04704                             }
04705                      }
04706               }
04707               tmpString+="        </tr>\n";
04708        }
04709        //workaround begin.
04710        tmpString+="        <tr class=\"foot\"><td colspan=\"2\"></td><td colspan=\""+QString::number(currentCount)+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr>\n";
04711        //workaround end.
04712        tmpString+="      </tbody>\n";
04713        tmpString+="    </table>\n\n";
04714        return tmpString;
04715 }
04716 
04717 //by Volker Dirr
04718 QString TimetableExport::singleSubgroupsTimetableTimeHorizontalDailyHtml(int htmlLevel, int day, int maxSubgroups, QSet<int>& excludedNames, const QString& saveTime, bool printActivityTags){
04719        assert(day>=0);
04720        assert(day<gt.rules.nDaysPerWeek);
04721        QString tmpString;
04722        tmpString+="    <table id=\"table_"+hashDayIDsTimetable.value(gt.rules.daysOfTheWeek[day])+"\" border=\"1\">\n";
04723        tmpString+="      <caption>"+protect2(gt.rules.institutionName)+"</caption>\n";
04724        
04725        tmpString+="      <thead>\n        <tr><td rowspan=\"2\"></td>";
04726        tmpString+="<th colspan=\""+QString::number(gt.rules.nHoursPerDay)+"\">"+protect2(gt.rules.daysOfTheWeek[day])+"</th>";
04727        tmpString+="        </tr>\n";
04728        tmpString+="        <tr>\n          <!-- span -->\n";
04729        for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
04730               if(htmlLevel>=2)
04731                      tmpString+="          <th class=\"xAxis\">";
04732               else
04733                      tmpString+="          <th>";
04734               tmpString+=protect2(gt.rules.hoursOfTheDay[hour])+"</th>\n";
04735               }
04736        tmpString+="        </tr>\n";
04737        tmpString+="      </thead>\n";
04738        /*workaround
04739        tmpString+="      <tfoot><tr><td></td><td colspan=\""+gt.rules.nHoursPerDay+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr></tfoot>\n";
04740        */
04741        tmpString+="      <tbody>\n";
04742        int currentCount=0;
04743        for(int subgroup=0; subgroup<gt.rules.nInternalSubgroups && currentCount<maxSubgroups; subgroup++){
04744               if(!excludedNames.contains(subgroup)){
04745                      currentCount++;
04746                      excludedNames<<subgroup;
04747 
04748                      tmpString+="        <tr>\n";
04749                      if(htmlLevel>=2)
04750                             tmpString+="          <th class=\"yAxis\">";
04751                      else
04752                             tmpString+="          <th>";
04753                      tmpString+=gt.rules.internalSubgroupsList[subgroup]->name+"</th>\n";
04754                      for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
04755                             QList<int> allActivities;
04756                             allActivities.clear();
04757                             allActivities<<students_timetable_weekly[subgroup][day][hour];
04758                             bool activitiesWithSameStartingtime=addActivitiesWithSameStartingTime(allActivities, hour);
04759                             if(allActivities.size()==1 && !activitiesWithSameStartingtime){  // because i am using colspan or rowspan!!!
04760                                    tmpString+=writeActivityStudents(htmlLevel, students_timetable_weekly[subgroup][day][hour], day, hour, subgroupNotAvailableDayHour[subgroup][day][hour], true, false, printActivityTags);
04761                             } else{
04762                                    tmpString+=writeActivitiesStudents(htmlLevel, allActivities, printActivityTags);
04763                             }
04764                      }
04765                      tmpString+="        </tr>\n";
04766               }
04767        }
04768        //workaround begin.
04769        tmpString+="        <tr class=\"foot\"><td></td><td colspan=\""+QString::number(gt.rules.nHoursPerDay)+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr>\n";
04770        //workaround end.
04771        tmpString+="      </tbody>\n";
04772        tmpString+="    </table>\n\n";
04773        return tmpString;
04774 }
04775        
04776 //by Volker Dirr
04777 QString TimetableExport::singleGroupsTimetableDaysHorizontalHtml(int htmlLevel, int group, const QString& saveTime, bool printActivityTags, bool detailed){
04778        assert(group>=0);
04779        assert(group<gt.rules.internalGroupsList.size());
04780        QString tmpString;
04781        tmpString+="    <table id=\"table_"+hashStudentIDsTimetable.value(gt.rules.internalGroupsList[group]->name);
04782        if(detailed) tmpString+="_DETAILED";
04783        tmpString+="\" border=\"1\"";
04784        if(group%2) tmpString+=" class=\"even_table\"";
04785        else tmpString+=" class=\"odd_table\"";
04786        tmpString+=">\n";
04787                      
04788        tmpString+="      <caption>"+protect2(gt.rules.institutionName)+"</caption>\n";
04789        tmpString+="      <thead>\n        <tr><td rowspan=\"2\"></td><th colspan=\""+QString::number(gt.rules.nDaysPerWeek)+"\">"+protect2(gt.rules.internalGroupsList[group]->name)+"</th></tr>\n";
04790        tmpString+="        <tr>\n          <!-- span -->\n";
04791        for(int day=0; day<gt.rules.nDaysPerWeek; day++){
04792               if(htmlLevel>=2)
04793                      tmpString+="          <th class=\"xAxis\">";
04794               else
04795                      tmpString+="          <th>";
04796               tmpString+=protect2(gt.rules.daysOfTheWeek[day])+"</th>\n";
04797        }
04798        tmpString+="        </tr>\n";
04799        tmpString+="      </thead>\n";
04800        /*workaround
04801        tmpString+="      <tfoot><tr><td></td><td colspan=\""+gt.rules.nDaysPerWeek+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr></tfoot>\n";
04802        */
04803        tmpString+="      <tbody>\n";
04804        for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
04805               tmpString+="        <tr>\n";
04806               if(htmlLevel>=2)
04807                      tmpString+="          <th class=\"yAxis\">";
04808               else
04809                      tmpString+="          <th>";
04810               tmpString+=protect2(gt.rules.hoursOfTheDay[hour])+"</th>\n";
04811               for(int day=0; day<gt.rules.nDaysPerWeek; day++){
04812                      QList<int> allActivities;
04813                      allActivities.clear();
04814                      bool isNotAvailable=true;
04815                      for(int sg=0; sg<gt.rules.internalGroupsList[group]->subgroupsList.size(); sg++){
04816                             StudentsSubgroup* sts=gt.rules.internalGroupsList[group]->subgroupsList[sg];
04817                             int subgroup=sts->indexInInternalSubgroupsList;
04818                             if(!(allActivities.contains(students_timetable_weekly[subgroup][day][hour])))
04819                                    allActivities<<students_timetable_weekly[subgroup][day][hour];
04820                             if(!subgroupNotAvailableDayHour[subgroup][day][hour])
04821                                    isNotAvailable=false;
04822                             }
04823                      assert(!allActivities.isEmpty());
04824                      bool activitiesWithSameStartingtime=addActivitiesWithSameStartingTime(allActivities, hour);
04825                      if(allActivities.size()==1 && !activitiesWithSameStartingtime){  // because i am using colspan or rowspan!!!
04826                             tmpString+=writeActivityStudents(htmlLevel, allActivities[0], day, hour, isNotAvailable, false, true, printActivityTags);
04827                      } else{
04828                             if(!detailed) tmpString+="          <td>"+protect2(STRING_SEVERAL_ACTIVITIES_IN_LESS_DETAILED_TABLES)+"</td>\n";
04829                             else{
04830                                    tmpString+=writeActivitiesStudents(htmlLevel, allActivities, printActivityTags);
04831                             }
04832                      }
04833               }
04834               tmpString+="        </tr>\n";
04835        }
04836        //workaround begin.
04837        tmpString+="        <tr class=\"foot\"><td></td><td colspan=\""+QString::number(gt.rules.nDaysPerWeek)+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr>\n";
04838        //workaround end.
04839        tmpString+="      </tbody>\n";
04840        tmpString+="    </table>\n\n";
04841        return tmpString;
04842 }
04843        
04844 //by Volker Dirr
04845 QString TimetableExport::singleGroupsTimetableDaysVerticalHtml(int htmlLevel, int group, const QString& saveTime, bool printActivityTags, bool detailed){
04846        assert(group>=0);
04847        assert(group<gt.rules.internalGroupsList.size());
04848        QString tmpString;
04849        tmpString+="    <table id=\"table_"+hashStudentIDsTimetable.value(gt.rules.internalGroupsList.at(group)->name);
04850        if(detailed) tmpString+="_DETAILED";
04851        tmpString+="\" border=\"1\"";
04852        if(group%2) tmpString+=" class=\"even_table\"";
04853        else tmpString+=" class=\"odd_table\"";
04854        tmpString+=">\n";
04855                      
04856        tmpString+="      <caption>"+protect2(gt.rules.institutionName)+"</caption>\n";
04857        tmpString+="      <thead>\n        <tr><td rowspan=\"2\"></td><th colspan=\""+QString::number(gt.rules.nHoursPerDay)+"\">"+protect2(gt.rules.internalGroupsList.at(group)->name)+"</th></tr>\n";
04858        tmpString+="        <tr>\n          <!-- span -->\n";
04859        for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
04860               if(htmlLevel>=2)
04861                      tmpString+="          <th class=\"xAxis\">";
04862               else
04863                      tmpString+="          <th>";
04864               tmpString+=protect2(gt.rules.hoursOfTheDay[hour])+"</th>\n";
04865        }
04866        tmpString+="        </tr>\n";
04867        tmpString+="      </thead>\n";
04868        /*workaround
04869        tmpString+="      <tfoot><tr><td></td><td colspan=\""+gt.rules.nHoursPerDay+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr></tfoot>\n";
04870        */
04871        tmpString+="      <tbody>\n";
04872        for(int day=0; day<gt.rules.nDaysPerWeek; day++){
04873               tmpString+="        <tr>\n";
04874               if(htmlLevel>=2)
04875                      tmpString+="          <th class=\"yAxis\">";
04876               else
04877                      tmpString+="          <th>";
04878               tmpString+=protect2(gt.rules.daysOfTheWeek[day])+"</th>\n";
04879               for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
04880                      QList<int> allActivities;
04881                      allActivities.clear();
04882                      bool isNotAvailable=true;
04883                      for(int sg=0; sg<gt.rules.internalGroupsList.at(group)->subgroupsList.size(); sg++){
04884                             StudentsSubgroup* sts=gt.rules.internalGroupsList.at(group)->subgroupsList[sg];
04885                             int subgroup=sts->indexInInternalSubgroupsList;
04886                             if(!(allActivities.contains(students_timetable_weekly[subgroup][day][hour])))
04887                                    allActivities<<students_timetable_weekly[subgroup][day][hour];
04888                             if(!subgroupNotAvailableDayHour[subgroup][day][hour])
04889                                    isNotAvailable=false;
04890                      }
04891                      assert(!allActivities.isEmpty());
04892                      bool activitiesWithSameStartingtime=addActivitiesWithSameStartingTime(allActivities, hour);
04893                      if(allActivities.size()==1 && !activitiesWithSameStartingtime){  // because i am using colspan or rowspan!!!
04894                             tmpString+=writeActivityStudents(htmlLevel, allActivities[0], day, hour, isNotAvailable, true, false, printActivityTags);
04895                      } else{
04896                             if(!detailed) tmpString+="          <td>"+protect2(STRING_SEVERAL_ACTIVITIES_IN_LESS_DETAILED_TABLES)+"</td>\n";
04897                             else{
04898                                    tmpString+=writeActivitiesStudents(htmlLevel, allActivities, printActivityTags);
04899                             }
04900                      }
04901               }
04902               tmpString+="        </tr>\n";
04903        }
04904        //workaround begin.
04905        tmpString+="        <tr class=\"foot\"><td></td><td colspan=\""+QString::number(gt.rules.nHoursPerDay)+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr>\n";
04906        //workaround end.
04907        tmpString+="      </tbody>\n";
04908        tmpString+="    </table>\n\n";
04909        return tmpString;
04910 }
04911        
04912 //by Volker Dirr
04913 QString TimetableExport::singleGroupsTimetableTimeVerticalHtml(int htmlLevel, int maxGroups, QSet<int>& excludedNames, const QString& saveTime, bool printActivityTags, bool detailed){
04914        QString tmpString;
04915        tmpString+="    <table id=\"table";
04916        if(!detailed)
04917               tmpString+="_LESS";
04918        tmpString+="_DETAILED";
04919        tmpString+="\" border=\"1\">\n";
04920               tmpString+="      <caption>"+protect2(gt.rules.institutionName)+"</caption>\n";
04921               tmpString+="      <thead>\n        <tr><td colspan=\"2\"></td>";
04922        int currentCount=0;
04923        for(int group=0; group<gt.rules.internalGroupsList.size() && currentCount<maxGroups; group++){
04924               if(!excludedNames.contains(group)){
04925                      currentCount++;
04926                      if(htmlLevel>=2)
04927                             tmpString+="          <th class=\"xAxis\">";
04928                      else
04929                             tmpString+="          <th>";
04930                      tmpString+=protect2(gt.rules.internalGroupsList.at(group)->name)+"</th>";
04931               }
04932        }
04933        
04934        tmpString+="</tr>\n      </thead>\n";
04935        /*workaround
04936        tmpString+="      <tfoot><tr><td colspan=\"2\"></td><td colspan=\""+QString::number(currentCount)+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr></tfoot>\n";
04937        */
04938        tmpString+="      <tbody>\n";
04939        for(int day=0; day<gt.rules.nDaysPerWeek; day++){
04940               for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
04941                      currentCount=0;
04942                      tmpString+="        <tr>\n";
04943                      if(hour==0)
04944                             tmpString+="        <th rowspan=\""+QString::number(gt.rules.nHoursPerDay)+"\">"+protect2vert(gt.rules.daysOfTheWeek[day])+"</th>\n";
04945                      else tmpString+="          <!-- span -->\n";
04946                      if(htmlLevel>=2)
04947                             tmpString+="          <th class=\"yAxis\">";
04948                      else
04949                             tmpString+="          <th>";
04950                      tmpString+=protect2(gt.rules.hoursOfTheDay[hour])+"</th>\n";
04951                      for(int group=0; group<gt.rules.internalGroupsList.size() && currentCount<maxGroups; group++){
04952                             if(!excludedNames.contains(group)){
04953                                    currentCount++;
04954                                    if(day+1==gt.rules.nDaysPerWeek && hour+1==gt.rules.nHoursPerDay)
04955                                           excludedNames<<group;
04956                                    QList<int> allActivities;
04957                                    allActivities.clear();
04958                                    bool isNotAvailable=true;
04959                                    for(int sg=0; sg<gt.rules.internalGroupsList.at(group)->subgroupsList.size(); sg++){
04960                                           StudentsSubgroup* sts=gt.rules.internalGroupsList.at(group)->subgroupsList[sg];
04961                                           int subgroup=sts->indexInInternalSubgroupsList;
04962                                           if(!(allActivities.contains(students_timetable_weekly[subgroup][day][hour])))
04963                                                  allActivities<<students_timetable_weekly[subgroup][day][hour];
04964                                           if(!subgroupNotAvailableDayHour[subgroup][day][hour])
04965                                                  isNotAvailable=false;
04966                                    }
04967                                    assert(!allActivities.isEmpty());
04968                                    bool activitiesWithSameStartingtime=addActivitiesWithSameStartingTime(allActivities, hour);
04969                                    if(allActivities.size()==1 && !activitiesWithSameStartingtime){  // because i am using colspan or rowspan!!!
04970                                           tmpString+=writeActivityStudents(htmlLevel, allActivities[0], day, hour, isNotAvailable, false, true, printActivityTags);
04971                                    } else{
04972                                           if(!detailed) tmpString+="          <td>"+protect2(STRING_SEVERAL_ACTIVITIES_IN_LESS_DETAILED_TABLES)+"</td>\n";
04973                                           else{
04974                                                  tmpString+=writeActivitiesStudents(htmlLevel, allActivities, printActivityTags);
04975                                           }
04976                                    }
04977                             }
04978                      }
04979                      tmpString+="        </tr>\n";
04980               }
04981        }
04982        //workaround begin.
04983        tmpString+="        <tr class=\"foot\"><td colspan=\"2\"></td><td colspan=\""+QString::number(currentCount)+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr>\n";
04984        //workaround end.
04985        tmpString+="      </tbody>\n";
04986        tmpString+="    </table>\n\n";
04987        return tmpString;
04988 }
04989 
04990 //by Volker Dirr
04991 QString TimetableExport::singleGroupsTimetableTimeHorizontalHtml(int htmlLevel, int maxGroups, QSet<int>& excludedNames, const QString& saveTime, bool printActivityTags, bool detailed){
04992        QString tmpString;
04993        tmpString+="    <table id=\"table";
04994        if(!detailed)
04995               tmpString+="_LESS";
04996        tmpString+="_DETAILED";
04997        tmpString+="\" border=\"1\">\n";
04998        tmpString+="      <caption>"+protect2(gt.rules.institutionName)+"</caption>\n";
04999        tmpString+="      <thead>\n        <tr><td rowspan=\"2\"></td>";
05000        for(int day=0; day<gt.rules.nDaysPerWeek; day++)
05001               tmpString+="<th colspan=\""+QString::number(gt.rules.nHoursPerDay)+"\">"+protect2(gt.rules.daysOfTheWeek[day])+"</th>";
05002        tmpString+="</tr>\n";
05003        tmpString+="        <tr>\n          <!-- span -->\n";
05004        for(int day=0; day<gt.rules.nDaysPerWeek; day++)
05005               for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
05006                      if(htmlLevel>=2)
05007                             tmpString+="          <th class=\"xAxis\">";
05008                      else
05009                             tmpString+="          <th>";
05010                      tmpString+=protect2(gt.rules.hoursOfTheDay[hour])+"</th>\n";
05011               }
05012        tmpString+="        </tr>\n";
05013        tmpString+="      </thead>\n";
05014        /*workaround
05015        tmpString+="      <tfoot><tr><td></td><td colspan=\""+gt.rules.nDaysPerWeek*gt.rules.nHoursPerDay+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr></tfoot>\n";
05016        */
05017        tmpString+="      <tbody>\n";
05018        
05019        int currentCount=0;
05020        for(int group=0; group<gt.rules.internalGroupsList.size() && currentCount<maxGroups; group++){
05021               if(!excludedNames.contains(group)){
05022                      currentCount++;
05023                      excludedNames<<group;
05024 
05025                      tmpString+="        <tr>\n";
05026                      if(htmlLevel>=2)
05027                             tmpString+="          <th class=\"yAxis\">";
05028                      else
05029                             tmpString+="          <th>";
05030                      tmpString+=protect2(gt.rules.internalGroupsList.at(group)->name)+"</th>\n";
05031                      for(int day=0; day<gt.rules.nDaysPerWeek; day++){
05032                             for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
05033                                    QList<int> allActivities;
05034                                    allActivities.clear();
05035                                    bool isNotAvailable=true;
05036                                    for(int sg=0; sg<gt.rules.internalGroupsList.at(group)->subgroupsList.size(); sg++){
05037                                           StudentsSubgroup* sts=gt.rules.internalGroupsList.at(group)->subgroupsList[sg];
05038                                           int subgroup=sts->indexInInternalSubgroupsList;
05039                                           if(!(allActivities.contains(students_timetable_weekly[subgroup][day][hour])))
05040                                                  allActivities<<students_timetable_weekly[subgroup][day][hour];
05041                                           if(!subgroupNotAvailableDayHour[subgroup][day][hour])
05042                                                  isNotAvailable=false;
05043                                    }
05044                                    assert(!allActivities.isEmpty());
05045                                    bool activitiesWithSameStartingtime=addActivitiesWithSameStartingTime(allActivities, hour);
05046                                    if(allActivities.size()==1 && !activitiesWithSameStartingtime){  // because i am using colspan or rowspan!!!
05047                                           tmpString+=writeActivityStudents(htmlLevel, allActivities[0], day, hour, isNotAvailable, true, false, printActivityTags);
05048                                    } else{
05049                                           if(!detailed) tmpString+="          <td>"+protect2(STRING_SEVERAL_ACTIVITIES_IN_LESS_DETAILED_TABLES)+"</td>\n";
05050                                           else{
05051                                                  tmpString+=writeActivitiesStudents(htmlLevel, allActivities, printActivityTags);
05052                                           }
05053                                    }
05054                             }
05055                      }
05056               }
05057               tmpString+="        </tr>\n";
05058        }
05059        //workaround begin.
05060        tmpString+="        <tr class=\"foot\"><td></td><td colspan=\""+QString::number(gt.rules.nDaysPerWeek*gt.rules.nHoursPerDay)+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr>\n";
05061        //workaround end.
05062        tmpString+="      </tbody>\n";
05063        tmpString+="    </table>\n\n";
05064        return tmpString;
05065 }
05066 
05067 //by Volker Dirr
05068 QString TimetableExport::singleGroupsTimetableTimeVerticalDailyHtml(int htmlLevel, int day, int maxGroups, QSet<int>& excludedNames, const QString& saveTime, bool printActivityTags, bool detailed){
05069        assert(day>=0);
05070        assert(day<gt.rules.nDaysPerWeek);
05071        QString tmpString;
05072        tmpString+="    <table id=\"table_"+hashDayIDsTimetable.value(gt.rules.daysOfTheWeek[day]);
05073        if(detailed) tmpString+="_DETAILED";
05074        tmpString+="\" border=\"1\">\n";
05075        tmpString+="      <caption>"+protect2(gt.rules.institutionName)+"</caption>\n";
05076        tmpString+="      <thead>\n        <tr><td colspan=\"2\"></td>";
05077        int currentCount=0;
05078        for(int group=0; group<gt.rules.internalGroupsList.size() && currentCount<maxGroups; group++){
05079               if(!excludedNames.contains(group)){
05080                      currentCount++;
05081                      if(htmlLevel>=2)
05082                             tmpString+="          <th class=\"xAxis\">";
05083                      else
05084                             tmpString+="          <th>";
05085                      tmpString+=gt.rules.internalGroupsList.at(group)->name+"</th>";
05086               }
05087        }
05088        
05089        tmpString+="</tr>\n      </thead>\n";
05090        /*workaround
05091        tmpString+="      <tfoot><tr><td colspan=\"2\"></td><td colspan=\""+QString::number(currentCount)+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr></tfoot>\n";
05092        */
05093        tmpString+="      <tbody>\n";
05094        for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
05095               currentCount=0;
05096               tmpString+="        <tr>\n";
05097               if(hour==0)
05098                      tmpString+="        <th rowspan=\""+QString::number(gt.rules.nHoursPerDay)+"\">" + protect2vert(gt.rules.daysOfTheWeek[day])+"</th>\n";
05099               else tmpString+="          <!-- span -->\n";
05100               if(htmlLevel>=2)
05101                      tmpString+="          <th class=\"yAxis\">";
05102               else
05103                      tmpString+="          <th>";
05104               tmpString+=protect2(gt.rules.hoursOfTheDay[hour])+"</th>\n";
05105               for(int group=0; group<gt.rules.internalGroupsList.size() && currentCount<maxGroups; group++){
05106                      if(!excludedNames.contains(group)){
05107                             currentCount++;
05108                             if(hour+1==gt.rules.nHoursPerDay)
05109                                    excludedNames<<group;
05110                             QList<int> allActivities;
05111                             allActivities.clear();
05112                             bool isNotAvailable=true;
05113                             for(int sg=0; sg<gt.rules.internalGroupsList.at(group)->subgroupsList.size(); sg++){
05114                                    StudentsSubgroup* sts=gt.rules.internalGroupsList.at(group)->subgroupsList[sg];
05115                                    int subgroup=sts->indexInInternalSubgroupsList;
05116                                    if(!(allActivities.contains(students_timetable_weekly[subgroup][day][hour])))
05117                                           allActivities<<students_timetable_weekly[subgroup][day][hour];
05118                                    if(!subgroupNotAvailableDayHour[subgroup][day][hour])
05119                                           isNotAvailable=false;
05120                             }
05121                             assert(!allActivities.isEmpty());
05122                             bool activitiesWithSameStartingtime=addActivitiesWithSameStartingTime(allActivities, hour);
05123                             if(allActivities.size()==1 && !activitiesWithSameStartingtime){  // because i am using colspan or rowspan!!!
05124                                    tmpString+=writeActivityStudents(htmlLevel, allActivities[0], day, hour, isNotAvailable, false, true, printActivityTags);
05125                             } else{
05126                                    if(!detailed) tmpString+="          <td>"+protect2(STRING_SEVERAL_ACTIVITIES_IN_LESS_DETAILED_TABLES)+"</td>\n";
05127                                    else{
05128                                           tmpString+=writeActivitiesStudents(htmlLevel, allActivities, printActivityTags);
05129                                    }
05130                             }
05131                      }
05132               }
05133               tmpString+="        </tr>\n";
05134        }
05135        //workaround begin.
05136        tmpString+="        <tr class=\"foot\"><td colspan=\"2\"></td><td colspan=\""+QString::number(currentCount)+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr>\n";
05137        //workaround end.
05138        tmpString+="      </tbody>\n";
05139        tmpString+="    </table>\n\n";
05140        return tmpString;
05141 }
05142 
05143 //by Volker Dirr
05144 QString TimetableExport::singleGroupsTimetableTimeHorizontalDailyHtml(int htmlLevel, int day, int maxGroups, QSet<int>& excludedNames, const QString& saveTime, bool printActivityTags, bool detailed){
05145        assert(day>=0);
05146        assert(day<gt.rules.nDaysPerWeek);
05147        QString tmpString;
05148        tmpString+="    <table id=\"table_"+hashDayIDsTimetable.value(gt.rules.daysOfTheWeek[day]);
05149        if(detailed) tmpString+="_DETAILED";
05150        tmpString+="\" border=\"1\">\n";
05151        tmpString+="      <caption>"+protect2(gt.rules.institutionName)+"</caption>\n";
05152        tmpString+="      <thead>\n        <tr><td rowspan=\"2\"></td>";
05153        tmpString+="<th colspan=\""+QString::number(gt.rules.nHoursPerDay)+"\">"+protect2(gt.rules.daysOfTheWeek[day])+"</th>";
05154        tmpString+="</tr>\n";
05155        tmpString+="        <tr>\n          <!-- span -->\n";
05156        for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
05157               if(htmlLevel>=2)
05158                      tmpString+="          <th class=\"xAxis\">";
05159               else
05160                      tmpString+="          <th>";
05161               tmpString+=protect2(gt.rules.hoursOfTheDay[hour])+"</th>\n";
05162        }
05163        tmpString+="        </tr>\n";
05164        tmpString+="      </thead>\n";
05165        /*workaround
05166        tmpString+="      <tfoot><tr><td></td><td colspan=\""+gt.rules.nHoursPerDay+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr></tfoot>\n";
05167        */
05168        tmpString+="      <tbody>\n";
05169        
05170        int currentCount=0;
05171        for(int group=0; group<gt.rules.internalGroupsList.size() && currentCount<maxGroups; group++){
05172               if(!excludedNames.contains(group)){
05173                      currentCount++;
05174                      excludedNames<<group;
05175 
05176                      tmpString+="        <tr>\n";
05177                      if(htmlLevel>=2)
05178                             tmpString+="          <th class=\"yAxis\">";
05179                      else
05180                             tmpString+="          <th>";
05181                      tmpString+=protect2(gt.rules.internalGroupsList.at(group)->name)+"</th>\n";
05182                      for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
05183                             QList<int> allActivities;
05184                             allActivities.clear();
05185                             bool isNotAvailable=true;
05186                             for(int sg=0; sg<gt.rules.internalGroupsList.at(group)->subgroupsList.size(); sg++){
05187                                    StudentsSubgroup* sts=gt.rules.internalGroupsList.at(group)->subgroupsList[sg];
05188                                    int subgroup=sts->indexInInternalSubgroupsList;
05189                                    if(!(allActivities.contains(students_timetable_weekly[subgroup][day][hour])))
05190                                           allActivities<<students_timetable_weekly[subgroup][day][hour];
05191                                    if(!subgroupNotAvailableDayHour[subgroup][day][hour])
05192                                           isNotAvailable=false;
05193                             }
05194                             assert(!allActivities.isEmpty());
05195                             bool activitiesWithSameStartingtime=addActivitiesWithSameStartingTime(allActivities, hour);
05196                             if(allActivities.size()==1 && !activitiesWithSameStartingtime){  // because i am using colspan or rowspan!!!
05197                                    tmpString+=writeActivityStudents(htmlLevel, allActivities[0], day, hour, isNotAvailable, true, false, printActivityTags);
05198                             } else{
05199                                    if(!detailed) tmpString+="          <td>"+protect2(STRING_SEVERAL_ACTIVITIES_IN_LESS_DETAILED_TABLES)+"</td>\n";
05200                                    else{
05201                                           tmpString+=writeActivitiesStudents(htmlLevel, allActivities, printActivityTags);
05202                                    }
05203                             }
05204                      }
05205                      tmpString+="        </tr>\n";
05206               }
05207        }
05208        //workaround begin.
05209        tmpString+="        <tr class=\"foot\"><td></td><td colspan=\""+QString::number(gt.rules.nHoursPerDay)+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr>\n";
05210        //workaround end.
05211        tmpString+="      </tbody>\n";
05212        tmpString+="    </table>\n\n";
05213        return tmpString;
05214 }
05215        
05216 //by Volker Dirr
05217 QString TimetableExport::singleYearsTimetableDaysHorizontalHtml(int htmlLevel, int year, const QString& saveTime, bool printActivityTags, bool detailed){
05218        assert(year>=0);
05219        assert(year<gt.rules.augmentedYearsList.size());
05220        QString tmpString;
05221        tmpString+="    <table id=\"table_"+hashStudentIDsTimetable.value(gt.rules.augmentedYearsList.at(year)->name);
05222        if(detailed) tmpString+="_DETAILED";
05223        tmpString+="\" border=\"1\"";
05224        if(year%2)  tmpString+=" class=\"even_table\"";
05225        else tmpString+=" class=\"odd_table\"";
05226        tmpString+=">\n";
05227                             
05228        tmpString+="      <caption>"+protect2(gt.rules.institutionName)+"</caption>\n";
05229        tmpString+="      <thead>\n        <tr><td rowspan=\"2\"></td><th colspan=\""+QString::number(gt.rules.nDaysPerWeek)+"\">"+protect2(gt.rules.augmentedYearsList.at(year)->name)+"</th></tr>\n";
05230        tmpString+="        <tr>\n          <!-- span -->\n";
05231        for(int day=0; day<gt.rules.nDaysPerWeek; day++){
05232               if(htmlLevel>=2)
05233                      tmpString+="          <th class=\"xAxis\">";
05234               else
05235                      tmpString+="          <th>";
05236               tmpString+=protect2(gt.rules.daysOfTheWeek[day])+"</th>\n";
05237        }
05238        tmpString+="        </tr>\n";
05239        tmpString+="      </thead>\n";
05240        /*workaround
05241        tmpString+="      <tfoot><tr><td></td><td colspan=\""+gt.rules.nDaysPerWeek+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr></tfoot>\n";
05242        */
05243        tmpString+="      <tbody>\n";
05244        for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
05245               tmpString+="        <tr>\n";
05246               if(htmlLevel>=2)
05247                      tmpString+="          <th class=\"yAxis\">";
05248               else
05249                      tmpString+="          <th>";
05250               tmpString+=protect2(gt.rules.hoursOfTheDay[hour])+"</th>\n";
05251               for(int day=0; day<gt.rules.nDaysPerWeek; day++){
05252                      QList<int> allActivities;
05253                      allActivities.clear();
05254                      bool isNotAvailable=true;
05255                      for(int g=0; g<gt.rules.augmentedYearsList.at(year)->groupsList.size(); g++){
05256                             StudentsGroup* stg=gt.rules.augmentedYearsList.at(year)->groupsList[g];
05257                             for(int sg=0; sg<stg->subgroupsList.size(); sg++){
05258                                    StudentsSubgroup* sts=stg->subgroupsList[sg];
05259                                    int subgroup=sts->indexInInternalSubgroupsList;
05260                                    if(!(allActivities.contains(students_timetable_weekly[subgroup][day][hour])))
05261                                           allActivities<<students_timetable_weekly[subgroup][day][hour];
05262                                    if(!subgroupNotAvailableDayHour[subgroup][day][hour])
05263                                           isNotAvailable=false;
05264                             }
05265                      }
05266                      assert(!allActivities.isEmpty());
05267                      bool activitiesWithSameStartingtime=addActivitiesWithSameStartingTime(allActivities, hour);
05268                      if(allActivities.size()==1 && !activitiesWithSameStartingtime){  // because i am using colspan or rowspan!!!
05269                             tmpString+=writeActivityStudents(htmlLevel, allActivities[0], day, hour, isNotAvailable, false, true, printActivityTags);
05270                      } else{
05271                             if(!detailed) tmpString+="          <td>"+protect2(STRING_SEVERAL_ACTIVITIES_IN_LESS_DETAILED_TABLES)+"</td>\n";
05272                             else{
05273                                    tmpString+=writeActivitiesStudents(htmlLevel, allActivities, printActivityTags);
05274                             }
05275                      }
05276               }
05277               tmpString+="        </tr>\n";
05278        }
05279        //workaround begin.
05280        tmpString+="        <tr class=\"foot\"><td></td><td colspan=\""+QString::number(gt.rules.nDaysPerWeek)+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr>\n";
05281        //workaround end.
05282        tmpString+="      </tbody>\n";
05283        tmpString+="    </table>\n\n";
05284        return tmpString;
05285 }
05286        
05287 //by Volker Dirr
05288 QString TimetableExport::singleYearsTimetableDaysVerticalHtml(int htmlLevel, int year, const QString& saveTime, bool printActivityTags, bool detailed){
05289        assert(year>=0);
05290        assert(year<gt.rules.augmentedYearsList.size());
05291        QString tmpString;
05292        tmpString+="    <table id=\"table_"+hashStudentIDsTimetable.value(gt.rules.augmentedYearsList.at(year)->name);
05293        if(detailed) tmpString+="_DETAILED";
05294        tmpString+="\" border=\"1\"";
05295        if(year%2)  tmpString+=" class=\"even_table\"";
05296        else tmpString+=" class=\"odd_table\"";
05297        tmpString+=">\n";
05298                      
05299        tmpString+="      <caption>"+protect2(gt.rules.institutionName)+"</caption>\n";
05300 
05301        tmpString+="      <thead>\n        <tr><td rowspan=\"2\"></td><th colspan=\""+QString::number(gt.rules.nHoursPerDay)+"\">"+protect2(gt.rules.augmentedYearsList.at(year)->name)+"</th></tr>\n";
05302        tmpString+="        <tr>\n          <!-- span -->\n";
05303        for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
05304               if(htmlLevel>=2)
05305                      tmpString+="          <th class=\"xAxis\">";
05306               else
05307                      tmpString+="          <th>";
05308               tmpString+=protect2(gt.rules.hoursOfTheDay[hour])+"</th>\n";
05309        }
05310        tmpString+="        </tr>\n";
05311        tmpString+="      </thead>\n";
05312        /*workaround
05313        tmpString+="      <tfoot><tr><td></td><td colspan=\""+gt.rules.nHoursPerDay+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr></tfoot>\n";
05314        */
05315        tmpString+="      <tbody>\n";
05316        for(int day=0; day<gt.rules.nDaysPerWeek; day++){
05317               tmpString+="        <tr>\n";
05318               if(htmlLevel>=2)
05319                      tmpString+="          <th class=\"yAxis\">";
05320               else
05321                      tmpString+="          <th>";
05322               tmpString+=protect2(gt.rules.daysOfTheWeek[day])+"</th>\n";
05323 
05324               for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
05325                      QList<int> allActivities;
05326                      allActivities.clear();
05327                      bool isNotAvailable=true;
05328                      for(int g=0; g<gt.rules.augmentedYearsList.at(year)->groupsList.size(); g++){
05329                             StudentsGroup* stg=gt.rules.augmentedYearsList.at(year)->groupsList[g];
05330                             for(int sg=0; sg<stg->subgroupsList.size(); sg++){
05331                                    StudentsSubgroup* sts=stg->subgroupsList[sg];
05332                                    int subgroup=sts->indexInInternalSubgroupsList;
05333                                    if(!(allActivities.contains(students_timetable_weekly[subgroup][day][hour])))
05334                                           allActivities<<students_timetable_weekly[subgroup][day][hour];
05335                                    if(!subgroupNotAvailableDayHour[subgroup][day][hour])
05336                                           isNotAvailable=false;
05337                             }
05338                      }
05339                      assert(!allActivities.isEmpty());
05340                      bool activitiesWithSameStartingtime=addActivitiesWithSameStartingTime(allActivities, hour);
05341                      if(allActivities.size()==1 && !activitiesWithSameStartingtime){  // because i am using colspan or rowspan!!!
05342                             tmpString+=writeActivityStudents(htmlLevel, allActivities[0], day, hour, isNotAvailable, true, false, printActivityTags);
05343                      } else{
05344                             if(!detailed) tmpString+="          <td>"+protect2(STRING_SEVERAL_ACTIVITIES_IN_LESS_DETAILED_TABLES)+"</td>\n";
05345                             else{
05346                                    tmpString+=writeActivitiesStudents(htmlLevel, allActivities, printActivityTags);
05347                             }
05348                      }
05349               }
05350               tmpString+="        </tr>\n";
05351        }
05352        //workaround begin.
05353        tmpString+="        <tr class=\"foot\"><td></td><td colspan=\""+QString::number(gt.rules.nHoursPerDay)+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr>\n";
05354        //workaround end.
05355        tmpString+="      </tbody>\n";
05356        tmpString+="    </table>\n\n";
05357        return tmpString;
05358 }
05359        
05360 //by Volker Dirr
05361 QString TimetableExport::singleYearsTimetableTimeVerticalHtml(int htmlLevel, int maxYears, QSet<int>& excludedNames, const QString& saveTime, bool printActivityTags, bool detailed){
05362        QString tmpString;
05363        tmpString+="    <table id=\"table";
05364        if(!detailed)
05365               tmpString+="_LESS";
05366        tmpString+="_DETAILED";
05367        tmpString+="\" border=\"1\">\n";
05368 
05369        tmpString+="      <caption>"+protect2(gt.rules.institutionName)+"</caption>\n";
05370 
05371        tmpString+="      <thead>\n        <tr><td colspan=\"2\"></td>";
05372        int currentCount=0;
05373        for(int year=0; year<gt.rules.augmentedYearsList.size() && currentCount<maxYears; year++){
05374               if(!excludedNames.contains(year)){
05375                      currentCount++;
05376                      if(htmlLevel>=2)
05377                             tmpString+="          <th class=\"xAxis\">";
05378                      else
05379                             tmpString+="          <th>";
05380                      tmpString+=protect2(gt.rules.augmentedYearsList.at(year)->name)+"</th>";
05381               }
05382        }
05383        
05384        tmpString+="</tr>\n      </thead>\n";
05385        /*workaround
05386        tmpString+="      <tfoot><tr><td colspan=\"2\"></td><td colspan=\""+QString::number(currentCount)+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr></tfoot>\n";
05387        */
05388        tmpString+="      <tbody>\n";
05389        for(int day=0; day<gt.rules.nDaysPerWeek; day++){
05390               for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
05391                      tmpString+="        <tr>\n";
05392                      if(hour==0)
05393                             tmpString+="        <th rowspan=\""+QString::number(gt.rules.nHoursPerDay)+"\">"+protect2vert(gt.rules.daysOfTheWeek[day])+"</th>\n";
05394                      else tmpString+="          <!-- span -->\n";
05395                      if(htmlLevel>=2)
05396                             tmpString+="          <th class=\"yAxis\">";
05397                      else
05398                             tmpString+="          <th>";
05399                      tmpString+=protect2(gt.rules.hoursOfTheDay[hour]) + "</th>\n";
05400                      currentCount=0;
05401                      for(int year=0; year<gt.rules.augmentedYearsList.size() && currentCount<maxYears; year++){
05402                             if(!excludedNames.contains(year)){
05403                                    currentCount++;
05404                                    if(day+1==gt.rules.nDaysPerWeek && hour+1==gt.rules.nHoursPerDay)
05405                                           excludedNames<<year;
05406                                    QList<int> allActivities;
05407                                    allActivities.clear();
05408                                    bool isNotAvailable=true;
05409                                    StudentsYear* sty=gt.rules.augmentedYearsList[year];
05410                                    for(int g=0; g<sty->groupsList.size(); g++){
05411                                           StudentsGroup* stg=sty->groupsList[g];
05412                                           for(int sg=0; sg<stg->subgroupsList.size(); sg++){
05413                                                  StudentsSubgroup* sts=stg->subgroupsList[sg];
05414                                                  int subgroup=sts->indexInInternalSubgroupsList;
05415                                                  if(!(allActivities.contains(students_timetable_weekly[subgroup][day][hour])))
05416                                                         allActivities<<students_timetable_weekly[subgroup][day][hour];
05417                                                  if(!subgroupNotAvailableDayHour[subgroup][day][hour])
05418                                                         isNotAvailable=false;
05419                                           }
05420                                    }
05421                                    assert(!allActivities.isEmpty());
05422                                    bool activitiesWithSameStartingtime=addActivitiesWithSameStartingTime(allActivities, hour);
05423                                    if(allActivities.size()==1 && !activitiesWithSameStartingtime){  // because i am using colspan or rowspan!!!
05424                                           tmpString+=writeActivityStudents(htmlLevel, allActivities[0], day, hour, isNotAvailable, false, true, printActivityTags);
05425                                    } else{
05426                                           if(!detailed) tmpString+="          <td>"+protect2(STRING_SEVERAL_ACTIVITIES_IN_LESS_DETAILED_TABLES)+"</td>\n";
05427                                           else{
05428                                                  tmpString+=writeActivitiesStudents(htmlLevel, allActivities, printActivityTags);
05429                                           }
05430                                    }
05431                             }
05432                      }
05433                      tmpString+="        </tr>\n";
05434               }
05435        }
05436        //workaround begin.
05437        tmpString+="        <tr class=\"foot\"><td colspan=\"2\"></td><td colspan=\""+QString::number(currentCount)+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr>\n";
05438        //workaround end.
05439        tmpString+="      </tbody>\n";
05440        tmpString+="    </table>\n\n";
05441        return tmpString;
05442 }
05443 
05444 //by Volker Dirr
05445 QString TimetableExport::singleYearsTimetableTimeHorizontalHtml(int htmlLevel, int maxYears, QSet<int>& excludedNames, const QString& saveTime, bool printActivityTags, bool detailed){
05446        QString tmpString;
05447        tmpString+="    <table id=\"table";
05448        if(!detailed)
05449               tmpString+="_LESS";
05450        tmpString+="_DETAILED";
05451        tmpString+="\" border=\"1\">\n";
05452 
05453        tmpString+="      <caption>"+protect2(gt.rules.institutionName)+"</caption>\n";
05454 
05455        tmpString+="      <thead>\n        <tr><td rowspan=\"2\"></td>";
05456        for(int day=0; day<gt.rules.nDaysPerWeek; day++)
05457               tmpString+="<th colspan=\""+QString::number(gt.rules.nHoursPerDay)+"\">"+protect2(gt.rules.daysOfTheWeek[day])+"</th>";
05458        tmpString+="</tr>\n";
05459        tmpString+="        <tr>\n          <!-- span -->\n";
05460        for(int day=0; day<gt.rules.nDaysPerWeek; day++)
05461               for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
05462                      if(htmlLevel>=2)
05463                             tmpString+="          <th class=\"xAxis\">";
05464                      else
05465                             tmpString+="          <th>";
05466                      tmpString+=protect2(gt.rules.hoursOfTheDay[hour])+"</th>\n";
05467               }
05468        tmpString+="        </tr>\n";
05469        tmpString+="      </thead>\n";
05470        /*workaround
05471        tmpString+="      <tfoot><tr><td></td><td colspan=\""+gt.rules.nHoursPerDay*gt.rules.nDaysPerWeek+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr></tfoot>\n";
05472        */
05473        tmpString+="      <tbody>\n";
05474        
05475        int currentCount=0;
05476        for(int year=0; year<gt.rules.augmentedYearsList.size() && currentCount<maxYears; year++){
05477               StudentsYear* sty=gt.rules.augmentedYearsList[year];
05478               if(!excludedNames.contains(year)){
05479                      currentCount++;
05480                      excludedNames<<year;
05481                      tmpString+="        <tr>\n";
05482                      if(htmlLevel>=2)
05483                             tmpString+="          <th class=\"yAxis\">";
05484                      else
05485                             tmpString+="          <th>";
05486                      tmpString+=protect2(sty->name)+"</th>\n";
05487                      for(int day=0; day<gt.rules.nDaysPerWeek; day++){
05488                             for(int hour=0; hour<gt.rules.nHoursPerDay; hour++){
05489                                    QList<int> allActivities;
05490                                    allActivities.clear();
05491                                    bool isNotAvailable=true;
05492                                    for(int g=0; g<sty->groupsList.size(); g++){
05493                                           StudentsGroup* stg=sty->groupsList[g];
05494                                           for(int sg=0; sg<stg->subgroupsList.size(); sg++){
05495                                                  StudentsSubgroup* sts=stg->subgroupsList[sg];
05496                                                  int subgroup=sts->indexInInternalSubgroupsList;
05497                                                  if(!(allActivities.contains(students_timetable_weekly[subgroup][day][hour])))
05498                                                         allActivities<<students_timetable_weekly[subgroup][day][hour];
05499                                                  if(!subgroupNotAvailableDayHour[subgroup][day][hour])
05500                                                         isNotAvailable=false;
05501                                           }
05502                                    }
05503                                    assert(!allActivities.isEmpty());
05504                                    bool activitiesWithSameStartingtime=addActivitiesWithSameStartingTime(allActivities, hour);
05505                                    if(allActivities.size()==1 && !activitiesWithSameStartingtime){  // because i am using colspan or rowspan!!!
05506                                           tmpString+=writeActivityStudents(htmlLevel, allActivities[0], day, hour, isNotAvailable, true, false, printActivityTags);
05507                                    } else{
05508                                           if(!detailed) tmpString+="          <td>"+protect2(STRING_SEVERAL_ACTIVITIES_IN_LESS_DETAILED_TABLES)+"</td>\n";
05509                                           else{
05510                                                  tmpString+=writeActivitiesStudents(htmlLevel, allActivities, printActivityTags);
05511                                           }
05512                                    }
05513                             }
05514                      }
05515                      tmpString+="        </tr>\n";
05516               }
05517        }
05518        //workaround begin.
05519        tmpString+="        <tr class=\"foot\"><td></td><td colspan=\""+QString::number(gt.rules.nHoursPerDay*gt.rules.nDaysPerWeek)+"\">"+TimetableExport::tr("Timetable generated with FET %1 on %2", "%1 is FET version, %2 is the date and time of generation").arg(FET_VERSION).arg(saveTime)+"</td></tr>\n";
05520        //workaround end.
05521        tmpString+="      </tbody>\n";
05522        tmpString+="    </table>\n\n";
05523        return tmpString;
05524 }
05525        
05526 //by Volker Dirr
05527 QString TimetableExport::singleYearsTimetableTimeVerticalDailyHtml(int htmlLevel, int day, int maxYears, QSet<int>& excludedNames, const QString& saveTime, bool printActivityTags, bool detailed){
05528        assert(day>=0);
05529        assert(day<gt.rules.nDaysPerWeek);
05530        QString tmpString;
05531        tmpString+="    <table id=\"table_"+hashDayIDsTimetable.value(gt.rules.daysOfTheWeek[day]);
05532        if(detailed) tmpString+="_DETAILED";
05533        tmpString+="\" border=\"1\">\n";
05534 
05535        tmpString+="      <caption>"+protect2(gt.rules.institutionName)+"</caption>\n";
05536 
05537        tmpString+="      <thead>\n        <tr><td colspan=\"2\"></td>";
05538        int currentCount=0;
05539        for(int year=0; year<gt.rules.