Back to index

fet  5.18.0
generate_pre.cpp
Go to the documentation of this file.
00001 /*File generate_pre.cpp
00002 */
00003 
00004 /*
00005 Copyright 2007 Lalescu Liviu.
00006 
00007 This file is part of FET.
00008 
00009 FET is free software; you can redistribute it and/or modify
00010 it under the terms of the GNU General Public License as published by
00011 the Free Software Foundation; either version 2 of the License, or
00012 (at your option) any later version.
00013 
00014 FET is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with FET; if not, write to the Free Software
00021 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 */
00023 
00024 #include "timetable_defs.h"
00025 #include "rules.h"
00026 #include "timetable.h"
00027 
00028 #include "generate_pre.h"
00029 
00030 #include "matrix.h"
00031 
00032 #include <iostream>
00033 #include <fstream>
00034 using namespace std;
00035 #include <algorithm>
00036 
00037 #include <QMessageBox>
00038 
00039 #include "longtextmessagebox.h"
00040 
00041 #include <QtAlgorithms>
00042 
00043 #include <QPair>
00044 #include <QSet>
00045 #include <QHash>
00046 #include <QQueue>
00047 
00048 extern Timetable gt;
00049 
00050 #include <QApplication>
00051 #include <QProgressDialog>
00052 
00053 extern QApplication* pqapplication;
00054 
00055 
00056 int permutation[MAX_ACTIVITIES]; //the permutation matrix to obtain activities in
00057 //decreasing difficulty order
00058 
00059 
00060 /*qint16 teachersTimetable[MAX_TEACHERS][MAX_DAYS_PER_WEEK][MAX_HOURS_PER_DAY];
00061 qint16 subgroupsTimetable[MAX_TOTAL_SUBGROUPS][MAX_DAYS_PER_WEEK][MAX_HOURS_PER_DAY];
00062 qint16 roomsTimetable[MAX_ROOMS][MAX_DAYS_PER_WEEK][MAX_HOURS_PER_DAY];*/
00063 
00064 
00065 //BASIC TIME
00066 //qint8 activitiesConflictingPercentage[MAX_ACTIVITIES][MAX_ACTIVITIES];
00067 Matrix2D<qint8> activitiesConflictingPercentage;
00068 
00069 //MIN DAYS BETWEEN ACTIVITIES
00070 Matrix1D<QList<int> > minDaysListOfActivities;
00071 Matrix1D<QList<int> > minDaysListOfMinDays;
00072 Matrix1D<QList<double> > minDaysListOfWeightPercentages;
00073 Matrix1D<QList<bool> > minDaysListOfConsecutiveIfSameDay;
00074 
00075 //MAX DAYS BETWEEN ACTIVITIES
00076 Matrix1D<QList<int> > maxDaysListOfActivities;
00077 Matrix1D<QList<int> > maxDaysListOfMaxDays;
00078 Matrix1D<QList<double> > maxDaysListOfWeightPercentages;
00079 
00080 //MIN GAPS BETWEEN ACTIVITIES
00081 Matrix1D<QList<int> > minGapsBetweenActivitiesListOfActivities;
00082 Matrix1D<QList<int> > minGapsBetweenActivitiesListOfMinGaps;
00083 Matrix1D<QList<double> > minGapsBetweenActivitiesListOfWeightPercentages;
00084 
00085 //TCH & ST NOT AVAIL, BREAK, ACT(S) PREFERRED TIME(S)
00086 //double notAllowedTimesPercentages[MAX_ACTIVITIES][MAX_HOURS_PER_WEEK];
00087 Matrix2D<double> notAllowedTimesPercentages;
00088 
00089 //breaks are no gaps - I keep track of this
00090 //bool breakTime[MAX_HOURS_PER_WEEK];
00091 //bool breakDayHour[MAX_DAYS_PER_WEEK][MAX_HOURS_PER_DAY];
00092 Matrix2D<bool> breakDayHour;
00093 
00094 //bool subgroupNotAvailableDayHour[MAX_TOTAL_SUBGROUPS][MAX_DAYS_PER_WEEK][MAX_HOURS_PER_DAY];
00095 Matrix3D<bool> subgroupNotAvailableDayHour;
00096 
00097 //bool teacherNotAvailableDayHour[MAX_TEACHERS][MAX_DAYS_PER_WEEK][MAX_HOURS_PER_DAY];
00098 Matrix3D<bool> teacherNotAvailableDayHour;
00099 
00100 //STUDENTS NO GAPS & EARLY
00101 int nHoursPerSubgroup[MAX_TOTAL_SUBGROUPS];
00102 double subgroupsEarlyMaxBeginningsAtSecondHourPercentage[MAX_TOTAL_SUBGROUPS];
00103 int subgroupsEarlyMaxBeginningsAtSecondHourMaxBeginnings[MAX_TOTAL_SUBGROUPS];
00104 double subgroupsMaxGapsPerWeekPercentage[MAX_TOTAL_SUBGROUPS];
00105 int subgroupsMaxGapsPerWeekMaxGaps[MAX_TOTAL_SUBGROUPS];
00106 
00107 double subgroupsMaxGapsPerDayPercentage[MAX_TOTAL_SUBGROUPS];
00108 int subgroupsMaxGapsPerDayMaxGaps[MAX_TOTAL_SUBGROUPS];
00109 bool haveStudentsMaxGapsPerDay;
00110 
00111 //TEACHERS MAX DAYS PER WEEK
00112 int teachersMaxDaysPerWeekMaxDays[MAX_TEACHERS];
00113 double teachersMaxDaysPerWeekWeightPercentages[MAX_TEACHERS];
00114 Matrix1D<QList<int> > teachersWithMaxDaysPerWeekForActivities;
00115 
00117 int nHoursPerTeacher[MAX_TEACHERS];
00118 double teachersMaxGapsPerWeekPercentage[MAX_TEACHERS];
00119 int teachersMaxGapsPerWeekMaxGaps[MAX_TEACHERS];
00120 
00121 double teachersMaxGapsPerDayPercentage[MAX_TEACHERS];
00122 int teachersMaxGapsPerDayMaxGaps[MAX_TEACHERS];
00123 
00124 //activities same starting time
00125 Matrix1D<QList<int> > activitiesSameStartingTimeActivities;
00126 Matrix1D<QList<double> > activitiesSameStartingTimePercentages;
00127 
00128 //activities same starting hour
00129 Matrix1D<QList<int> > activitiesSameStartingHourActivities;
00130 Matrix1D<QList<double> > activitiesSameStartingHourPercentages;
00131 
00132 //activities same starting day
00133 Matrix1D<QList<int> > activitiesSameStartingDayActivities;
00134 Matrix1D<QList<double> > activitiesSameStartingDayPercentages;
00135 
00136 //activities not overlapping
00137 Matrix1D<QList<int> > activitiesNotOverlappingActivities;
00138 Matrix1D<QList<double> > activitiesNotOverlappingPercentages;
00139 
00140 //teacher(s) max hours daily
00141 //int teachersGapsPerDay[MAX_TEACHERS][MAX_DAYS_PER_WEEK];
00142 //int teachersNHoursPerDay[MAX_TEACHERS][MAX_DAYS_PER_WEEK];
00143 
00144 double teachersMaxHoursDailyPercentages1[MAX_TEACHERS];
00145 int teachersMaxHoursDailyMaxHours1[MAX_TEACHERS];
00146 //int teachersRealGapsPerDay1[MAX_TEACHERS][MAX_DAYS_PER_WEEK];
00147 
00148 double teachersMaxHoursDailyPercentages2[MAX_TEACHERS];
00149 int teachersMaxHoursDailyMaxHours2[MAX_TEACHERS];
00150 //int teachersRealGapsPerDay2[MAX_TEACHERS][MAX_DAYS_PER_WEEK];
00151 
00152 //teacher(s) max hours continuously
00153 double teachersMaxHoursContinuouslyPercentages1[MAX_TEACHERS];
00154 int teachersMaxHoursContinuouslyMaxHours1[MAX_TEACHERS];
00155 
00156 double teachersMaxHoursContinuouslyPercentages2[MAX_TEACHERS];
00157 int teachersMaxHoursContinuouslyMaxHours2[MAX_TEACHERS];
00158 
00159 //teacher(s) activity tag max hours daily
00160 bool haveTeachersActivityTagMaxHoursDaily;
00161 
00162 Matrix1D<QList<int> > teachersActivityTagMaxHoursDailyMaxHours;
00163 Matrix1D<QList<int> > teachersActivityTagMaxHoursDailyActivityTag;
00164 Matrix1D<QList<double> > teachersActivityTagMaxHoursDailyPercentage;
00165 //(formerly arrays of size MAX_TEACHERS)
00166 
00167 //teacher(s) activity tag max hours continuously
00168 bool haveTeachersActivityTagMaxHoursContinuously;
00169 
00170 Matrix1D<QList<int> > teachersActivityTagMaxHoursContinuouslyMaxHours;
00171 Matrix1D<QList<int> > teachersActivityTagMaxHoursContinuouslyActivityTag;
00172 Matrix1D<QList<double> > teachersActivityTagMaxHoursContinuouslyPercentage;
00173 //(formerly arrays of size MAX_TEACHERS)
00174 
00175 //teacher(s) min hours daily
00176 double teachersMinHoursDailyPercentages[MAX_TEACHERS];
00177 int teachersMinHoursDailyMinHours[MAX_TEACHERS];
00178 
00179 //teacher(s) min days per week
00180 double teachersMinDaysPerWeekPercentages[MAX_TEACHERS];
00181 int teachersMinDaysPerWeekMinDays[MAX_TEACHERS];
00182 
00183 //students (set) max hours continuously
00184 double subgroupsMaxHoursContinuouslyPercentages1[MAX_TOTAL_SUBGROUPS];
00185 int subgroupsMaxHoursContinuouslyMaxHours1[MAX_TOTAL_SUBGROUPS];
00186 
00187 double subgroupsMaxHoursContinuouslyPercentages2[MAX_TOTAL_SUBGROUPS];
00188 int subgroupsMaxHoursContinuouslyMaxHours2[MAX_TOTAL_SUBGROUPS];
00189 
00190 //students (set) activity tag max hours daily
00191 bool haveStudentsActivityTagMaxHoursDaily;
00192 
00193 Matrix1D<QList<int> > subgroupsActivityTagMaxHoursDailyMaxHours;
00194 Matrix1D<QList<int> > subgroupsActivityTagMaxHoursDailyActivityTag;
00195 Matrix1D<QList<double> > subgroupsActivityTagMaxHoursDailyPercentage;
00196 //(formerly arrays of size MAX_TOTAL_SUBGROUPS)
00197 
00198 //students (set) activity tag max hours continuously
00199 bool haveStudentsActivityTagMaxHoursContinuously;
00200 
00201 Matrix1D<QList<int> > subgroupsActivityTagMaxHoursContinuouslyMaxHours;
00202 Matrix1D<QList<int> > subgroupsActivityTagMaxHoursContinuouslyActivityTag;
00203 Matrix1D<QList<double> > subgroupsActivityTagMaxHoursContinuouslyPercentage;
00204 //(formerly arrays of size MAX_TOTAL_SUBGROUPS)
00205 
00206 //students (set) max hours daily
00207 double subgroupsMaxHoursDailyPercentages1[MAX_TOTAL_SUBGROUPS];
00208 int subgroupsMaxHoursDailyMaxHours1[MAX_TOTAL_SUBGROUPS];
00209 
00210 double subgroupsMaxHoursDailyPercentages2[MAX_TOTAL_SUBGROUPS];
00211 int subgroupsMaxHoursDailyMaxHours2[MAX_TOTAL_SUBGROUPS];
00212 
00213 //students (set) min hours daily
00214 double subgroupsMinHoursDailyPercentages[MAX_TOTAL_SUBGROUPS];
00215 int subgroupsMinHoursDailyMinHours[MAX_TOTAL_SUBGROUPS];
00216 bool subgroupsMinHoursDailyAllowEmptyDays[MAX_TOTAL_SUBGROUPS];
00217 bool haveStudentsMinHoursDailyAllowEmptyDays;
00218 
00219 // 2 activities consecutive
00220 //index represents the first activity, value in array represents the second activity
00221 Matrix1D<QList<double> > constrTwoActivitiesConsecutivePercentages;
00222 Matrix1D<QList<int> > constrTwoActivitiesConsecutiveActivities;
00223 
00224 //index represents the second activity, value in array represents the first activity
00225 Matrix1D<QList<double> > inverseConstrTwoActivitiesConsecutivePercentages;
00226 Matrix1D<QList<int> > inverseConstrTwoActivitiesConsecutiveActivities;
00227 // 2 activities consecutive
00228 
00229 // 2 activities grouped
00230 //index represents the first activity, value in array represents the second activity
00231 Matrix1D<QList<double> > constrTwoActivitiesGroupedPercentages;
00232 Matrix1D<QList<int> > constrTwoActivitiesGroupedActivities;
00233 
00234 // 3 activities grouped
00235 //index represents the first activity, value in array represents the second activity
00236 Matrix1D<QList<double> > constrThreeActivitiesGroupedPercentages;
00237 Matrix1D<QList<QPair<int, int> > > constrThreeActivitiesGroupedActivities;
00238 
00239 // 2 activities ordered
00240 //index represents the first activity, value in array represents the second activity
00241 Matrix1D<QList<double> > constrTwoActivitiesOrderedPercentages;
00242 Matrix1D<QList<int> > constrTwoActivitiesOrderedActivities;
00243 
00244 //index represents the second activity, value in array represents the first activity
00245 Matrix1D<QList<double> > inverseConstrTwoActivitiesOrderedPercentages;
00246 Matrix1D<QList<int> > inverseConstrTwoActivitiesOrderedActivities;
00247 // 2 activities consecutive
00248 
00249 double activityEndsStudentsDayPercentages[MAX_ACTIVITIES];
00250 bool haveActivityEndsStudentsDay;
00251 
00252 
00254 double teachersIntervalMaxDaysPerWeekPercentages1[MAX_TEACHERS];
00255 int teachersIntervalMaxDaysPerWeekMaxDays1[MAX_TEACHERS];
00256 int teachersIntervalMaxDaysPerWeekIntervalStart1[MAX_TEACHERS];
00257 int teachersIntervalMaxDaysPerWeekIntervalEnd1[MAX_TEACHERS];
00258 
00259 double teachersIntervalMaxDaysPerWeekPercentages2[MAX_TEACHERS];
00260 int teachersIntervalMaxDaysPerWeekMaxDays2[MAX_TEACHERS];
00261 int teachersIntervalMaxDaysPerWeekIntervalStart2[MAX_TEACHERS];
00262 int teachersIntervalMaxDaysPerWeekIntervalEnd2[MAX_TEACHERS];
00263 
00264 double teachersIntervalMaxDaysPerWeekPercentages3[MAX_TEACHERS];
00265 int teachersIntervalMaxDaysPerWeekMaxDays3[MAX_TEACHERS];
00266 int teachersIntervalMaxDaysPerWeekIntervalStart3[MAX_TEACHERS];
00267 int teachersIntervalMaxDaysPerWeekIntervalEnd3[MAX_TEACHERS];
00268 
00269 //bool computeTeachersIntervalMaxDaysPerWeek();
00271 
00272 
00274 double subgroupsIntervalMaxDaysPerWeekPercentages1[MAX_TOTAL_SUBGROUPS];
00275 int subgroupsIntervalMaxDaysPerWeekMaxDays1[MAX_TOTAL_SUBGROUPS];
00276 int subgroupsIntervalMaxDaysPerWeekIntervalStart1[MAX_TOTAL_SUBGROUPS];
00277 int subgroupsIntervalMaxDaysPerWeekIntervalEnd1[MAX_TOTAL_SUBGROUPS];
00278 
00279 double subgroupsIntervalMaxDaysPerWeekPercentages2[MAX_TOTAL_SUBGROUPS];
00280 int subgroupsIntervalMaxDaysPerWeekMaxDays2[MAX_TOTAL_SUBGROUPS];
00281 int subgroupsIntervalMaxDaysPerWeekIntervalStart2[MAX_TOTAL_SUBGROUPS];
00282 int subgroupsIntervalMaxDaysPerWeekIntervalEnd2[MAX_TOTAL_SUBGROUPS];
00283 
00284 double subgroupsIntervalMaxDaysPerWeekPercentages3[MAX_TOTAL_SUBGROUPS];
00285 int subgroupsIntervalMaxDaysPerWeekMaxDays3[MAX_TOTAL_SUBGROUPS];
00286 int subgroupsIntervalMaxDaysPerWeekIntervalStart3[MAX_TOTAL_SUBGROUPS];
00287 int subgroupsIntervalMaxDaysPerWeekIntervalEnd3[MAX_TOTAL_SUBGROUPS];
00288 
00289 //bool computeSubgroupsIntervalMaxDaysPerWeek();
00291 
00292 
00294 //double notAllowedRoomTimePercentages[MAX_ROOMS][MAX_HOURS_PER_WEEK]; //-1 for available
00295 Matrix2D<double> notAllowedRoomTimePercentages; //-1 for available
00296 
00297 Matrix1D<QList<PreferredRoomsItem> > activitiesPreferredRoomsList;
00298 bool unspecifiedPreferredRoom[MAX_ACTIVITIES];
00299 
00300 Matrix1D<QList<int> > activitiesHomeRoomsHomeRooms;
00301 double activitiesHomeRoomsPercentage[MAX_ACTIVITIES];
00302 bool unspecifiedHomeRoom[MAX_ACTIVITIES];
00304 
00305 
00307 double maxBuildingChangesPerDayForStudentsPercentages[MAX_TOTAL_SUBGROUPS];
00308 int maxBuildingChangesPerDayForStudentsMaxChanges[MAX_TOTAL_SUBGROUPS];
00309 //bool computeMaxBuildingChangesPerDayForStudents();
00310 
00311 double minGapsBetweenBuildingChangesForStudentsPercentages[MAX_TOTAL_SUBGROUPS];
00312 int minGapsBetweenBuildingChangesForStudentsMinGaps[MAX_TOTAL_SUBGROUPS];
00313 //bool computeMinGapsBetweenBuildingChangesForStudents();
00314 
00315 double maxBuildingChangesPerDayForTeachersPercentages[MAX_TEACHERS];
00316 int maxBuildingChangesPerDayForTeachersMaxChanges[MAX_TEACHERS];
00317 //bool computeMaxBuildingChangesPerDayForTeachers();
00318 
00319 double minGapsBetweenBuildingChangesForTeachersPercentages[MAX_TEACHERS];
00320 int minGapsBetweenBuildingChangesForTeachersMinGaps[MAX_TEACHERS];
00321 //bool computeMinGapsBetweenBuildingChangesForTeachers();
00322 
00323 double maxBuildingChangesPerWeekForStudentsPercentages[MAX_TOTAL_SUBGROUPS];
00324 int maxBuildingChangesPerWeekForStudentsMaxChanges[MAX_TOTAL_SUBGROUPS];
00325 //bool computeMaxBuildingChangesPerWeekForStudents();
00326 
00327 double maxBuildingChangesPerWeekForTeachersPercentages[MAX_TEACHERS];
00328 int maxBuildingChangesPerWeekForTeachersMaxChanges[MAX_TEACHERS];
00329 //bool computeMaxBuildingChangesPerWeekForTeachers();
00331 
00332 
00333 Matrix1D<QList<int> > mustComputeTimetableSubgroups;
00334 Matrix1D<QList<int> > mustComputeTimetableTeachers;
00335 bool mustComputeTimetableSubgroup[MAX_TOTAL_SUBGROUPS];
00336 bool mustComputeTimetableTeacher[MAX_TEACHERS];
00337 //void computeMustComputeTimetableSubgroups();
00338 //void computeMustComputeTimetableTeachers();
00339 
00340 
00341 //2011-09-25 - Constraint activities occupy max time slots from selection
00342 QList<ActivitiesOccupyMaxTimeSlotsFromSelection_item> aomtsList;
00343 Matrix1D<QList<ActivitiesOccupyMaxTimeSlotsFromSelection_item*> > aomtsListForActivity;
00344 //bool computeActivitiesOccupyMaxTimeSlotsFromSelection(QWidget* parent);
00345 
00346 //2011-09-30 - Constraint activities max simultaneous in selected time slots
00347 QList<ActivitiesMaxSimultaneousInSelectedTimeSlots_item> amsistsList;
00348 Matrix1D<QList<ActivitiesMaxSimultaneousInSelectedTimeSlots_item*> > amsistsListForActivity;
00349 //bool computeActivitiesMaxSimultaneousInSelectedTimeSlots(QWidget* parent);
00350 
00351 bool haveActivitiesOccupyOrSimultaneousConstraints;
00352 
00353 //2011-09-25 - Constraint activities occupy max different rooms
00354 QList<ActivitiesOccupyMaxDifferentRooms_item> aomdrList;
00355 Matrix1D<QList<ActivitiesOccupyMaxDifferentRooms_item*> > aomdrListForActivity;
00356 //bool computeActivitiesOccupyMaxDifferentRooms(QWidget* parent);
00357 
00358 
00359 extern QString initialOrderOfActivities;
00360 
00361 extern int initialOrderOfActivitiesIndices[MAX_ACTIVITIES];
00362 
00363 
00364 bool fixedTimeActivity[MAX_ACTIVITIES];
00365 bool fixedSpaceActivity[MAX_ACTIVITIES];
00366 
00367 
00368 static int daysTeacherIsAvailable[MAX_TEACHERS];
00369 static int daysSubgroupIsAvailable[MAX_TOTAL_SUBGROUPS];
00370 static int requestedDaysForTeachers[MAX_TEACHERS];
00371 static int requestedDaysForSubgroups[MAX_TOTAL_SUBGROUPS];
00372 static int nReqForTeacher[MAX_TEACHERS];
00373 static int nReqForSubgroup[MAX_TOTAL_SUBGROUPS];
00374 
00375 
00376 //used only in homeRoomsAreOk
00377 static int nHoursRequiredForRoom[MAX_ROOMS];
00378 static int nHoursAvailableForRoom[MAX_ROOMS];
00380 
00382 static int nIncompatible[MAX_ACTIVITIES];
00383 static double nMinDaysConstraintsBroken[MAX_ACTIVITIES];
00384 static int nRoomsIncompat[MAX_ROOMS];
00385 static double nHoursForRoom[MAX_ROOMS];
00386 static Matrix1D<PreferredRoomsItem> maxPercentagePrefRooms;
00387 static qint8 crth[MAX_ACTIVITIES];
00388 static qint8 crtv[MAX_ACTIVITIES];
00389 static int reprNInc[MAX_ACTIVITIES];
00391 
00392 
00393 inline bool compareFunctionGeneratePre(int i, int j)
00394 {
00395        if(nIncompatible[i]>nIncompatible[j] ||
00396         (nIncompatible[i]==nIncompatible[j] &&
00397         nMinDaysConstraintsBroken[i]>nMinDaysConstraintsBroken[j]))
00398               return true;
00399        
00400        return false;
00401 }
00402 
00403 
00404 bool processTimeSpaceConstraints(QWidget* parent, QTextStream* initialOrderStream)
00405 {
00406        assert(gt.rules.internalStructureComputed);
00407 
00409 
00410        //MIN DAYS BETWEEN ACTIVITIES
00411        minDaysListOfActivities.resize(gt.rules.nInternalActivities);
00412        minDaysListOfMinDays.resize(gt.rules.nInternalActivities);
00413        minDaysListOfWeightPercentages.resize(gt.rules.nInternalActivities);
00414        minDaysListOfConsecutiveIfSameDay.resize(gt.rules.nInternalActivities);
00415 
00416        //MAX DAYS BETWEEN ACTIVITIES
00417        maxDaysListOfActivities.resize(gt.rules.nInternalActivities);
00418        maxDaysListOfMaxDays.resize(gt.rules.nInternalActivities);
00419        maxDaysListOfWeightPercentages.resize(gt.rules.nInternalActivities);
00420 
00421        //MIN GAPS BETWEEN ACTIVITIES
00422        minGapsBetweenActivitiesListOfActivities.resize(gt.rules.nInternalActivities);
00423        minGapsBetweenActivitiesListOfMinGaps.resize(gt.rules.nInternalActivities);
00424        minGapsBetweenActivitiesListOfWeightPercentages.resize(gt.rules.nInternalActivities);
00425 
00426        teachersWithMaxDaysPerWeekForActivities.resize(gt.rules.nInternalActivities);
00427 
00428        //activities same starting time
00429        activitiesSameStartingTimeActivities.resize(gt.rules.nInternalActivities);
00430        activitiesSameStartingTimePercentages.resize(gt.rules.nInternalActivities);
00431 
00432        //activities same starting hour
00433        activitiesSameStartingHourActivities.resize(gt.rules.nInternalActivities);
00434        activitiesSameStartingHourPercentages.resize(gt.rules.nInternalActivities);
00435 
00436        //activities same starting day
00437        activitiesSameStartingDayActivities.resize(gt.rules.nInternalActivities);
00438        activitiesSameStartingDayPercentages.resize(gt.rules.nInternalActivities);
00439 
00440        //activities not overlapping
00441        activitiesNotOverlappingActivities.resize(gt.rules.nInternalActivities);
00442        activitiesNotOverlappingPercentages.resize(gt.rules.nInternalActivities);
00443 
00444        // 2 activities consecutive
00445        //index represents the first activity, value in array represents the second activity
00446        constrTwoActivitiesConsecutivePercentages.resize(gt.rules.nInternalActivities);
00447        constrTwoActivitiesConsecutiveActivities.resize(gt.rules.nInternalActivities);
00448 
00449        //index represents the second activity, value in array represents the first activity
00450        inverseConstrTwoActivitiesConsecutivePercentages.resize(gt.rules.nInternalActivities);
00451        inverseConstrTwoActivitiesConsecutiveActivities.resize(gt.rules.nInternalActivities);
00452        // 2 activities consecutive
00453 
00454        // 2 activities grouped
00455        //index represents the first activity, value in array represents the second activity
00456        constrTwoActivitiesGroupedPercentages.resize(gt.rules.nInternalActivities);
00457        constrTwoActivitiesGroupedActivities.resize(gt.rules.nInternalActivities);
00458 
00459        // 3 activities grouped
00460        //index represents the first activity, value in array represents the second activity
00461        constrThreeActivitiesGroupedPercentages.resize(gt.rules.nInternalActivities);
00462        constrThreeActivitiesGroupedActivities.resize(gt.rules.nInternalActivities);
00463 
00464        // 2 activities ordered
00465        //index represents the first activity, value in array represents the second activity
00466        constrTwoActivitiesOrderedPercentages.resize(gt.rules.nInternalActivities);
00467        constrTwoActivitiesOrderedActivities.resize(gt.rules.nInternalActivities);
00468 
00469        //index represents the second activity, value in array represents the first activity
00470        inverseConstrTwoActivitiesOrderedPercentages.resize(gt.rules.nInternalActivities);
00471        inverseConstrTwoActivitiesOrderedActivities.resize(gt.rules.nInternalActivities);
00472        // 2 activities consecutive
00473 
00474        //rooms
00475        activitiesPreferredRoomsList.resize(gt.rules.nInternalActivities);
00476 
00477        activitiesHomeRoomsHomeRooms.resize(gt.rules.nInternalActivities);
00479 
00480        mustComputeTimetableSubgroups.resize(gt.rules.nInternalActivities);
00481        mustComputeTimetableTeachers.resize(gt.rules.nInternalActivities);
00482 
00484        teachersActivityTagMaxHoursDailyMaxHours.resize(gt.rules.nInternalTeachers);
00485        teachersActivityTagMaxHoursDailyActivityTag.resize(gt.rules.nInternalTeachers);
00486        teachersActivityTagMaxHoursDailyPercentage.resize(gt.rules.nInternalTeachers);
00487 
00488        teachersActivityTagMaxHoursContinuouslyMaxHours.resize(gt.rules.nInternalTeachers);
00489        teachersActivityTagMaxHoursContinuouslyActivityTag.resize(gt.rules.nInternalTeachers);
00490        teachersActivityTagMaxHoursContinuouslyPercentage.resize(gt.rules.nInternalTeachers);
00491 
00492        subgroupsActivityTagMaxHoursDailyMaxHours.resize(gt.rules.nInternalSubgroups);
00493        subgroupsActivityTagMaxHoursDailyActivityTag.resize(gt.rules.nInternalSubgroups);
00494        subgroupsActivityTagMaxHoursDailyPercentage.resize(gt.rules.nInternalSubgroups);
00495 
00496        subgroupsActivityTagMaxHoursContinuouslyMaxHours.resize(gt.rules.nInternalSubgroups);
00497        subgroupsActivityTagMaxHoursContinuouslyActivityTag.resize(gt.rules.nInternalSubgroups);
00498        subgroupsActivityTagMaxHoursContinuouslyPercentage.resize(gt.rules.nInternalSubgroups);
00499        
00500        //2011-09-25
00501        aomtsListForActivity.resize(gt.rules.nInternalActivities);
00502        //2011-09-30
00503        amsistsListForActivity.resize(gt.rules.nInternalActivities);
00504 
00505        //2011-09-25
00506        aomdrListForActivity.resize(gt.rules.nInternalActivities);
00507 
00509        
00510        QHash<int, int> reprSameStartingTime;
00511        QHash<int, QSet<int> > reprSameActivitiesSet;
00512 
00514        bool t=computeActivitiesConflictingPercentage(parent);
00515        if(!t)
00516               return false;
00518        
00520        t=computeMinDays(parent);
00521        if(!t)
00522               return false;
00524        
00526        t=computeMaxDays(parent);
00527        if(!t)
00528               return false;
00530        
00532        t=computeMinGapsBetweenActivities(parent);
00533        if(!t)
00534               return false;
00536        
00539        t=computeNotAllowedTimesPercentages(parent);
00540        if(!t)
00541               return false;
00543        
00545        t=computeNHoursPerSubgroup(parent);
00546        if(!t)
00547               return false;
00548        t=computeSubgroupsEarlyAndMaxGapsPercentages(parent);
00549        if(!t)
00550               return false;
00551        t=computeSubgroupsMaxGapsPerDayPercentages(parent); 
00552        if(!t)
00553               return false;
00554               
00556        
00558        t=computeMaxDaysPerWeekForTeachers(parent);
00559        if(!t)
00560               return false;
00562        
00563        
00565        t=computeNHoursPerTeacher(parent);
00566        if(!t)
00567               return false;
00568        t=computeTeachersMaxGapsPerWeekPercentage(parent);
00569        if(!t)
00570               return false;
00571        t=computeTeachersMaxGapsPerDayPercentage(parent);
00572        if(!t)
00573               return false;
00575        
00576        //must be AFTER basic time constraints (computeActivitiesConflictingPercentage)
00577        t=computeActivitiesSameStartingTime(parent, reprSameStartingTime, reprSameActivitiesSet);
00578        if(!t)
00579               return false;
00580 
00581        computeActivitiesSameStartingHour();
00582        
00583        computeActivitiesSameStartingDay();
00584        
00585        computeActivitiesNotOverlapping();
00586 
00587        //must be after allowed times, after n hours per teacher and after max days per week
00588        t=computeTeachersMaxHoursDaily(parent);
00589        if(!t)
00590               return false;
00591 
00592        t=computeTeachersMaxHoursContinuously(parent);
00593        if(!t)
00594               return false;
00595 
00596        t=computeTeachersActivityTagMaxHoursDaily(parent);
00597        if(!t)
00598               return false;
00599 
00600        t=computeTeachersActivityTagMaxHoursContinuously(parent);
00601        if(!t)
00602               return false;
00603 
00604        //must be after n hours per teacher
00605        t=computeTeachersMinHoursDaily(parent);
00606        if(!t)
00607               return false;
00608        
00609        //must be after teachers min hours daily
00610        t=computeTeachersMinDaysPerWeek(parent);
00611        if(!t)
00612               return false;
00613        
00614        //must be after allowed times and after n hours per subgroup
00615        t=computeSubgroupsMaxHoursDaily(parent);
00616        if(!t)
00617               return false;
00618        
00619        t=computeStudentsMaxHoursContinuously(parent);
00620        if(!t)
00621               return false;
00622 
00623        t=computeStudentsActivityTagMaxHoursDaily(parent);
00624        if(!t)
00625               return false;
00626 
00627        t=computeStudentsActivityTagMaxHoursContinuously(parent);
00628        if(!t)
00629               return false;
00630 
00631        t=computeSubgroupsMinHoursDaily(parent);
00632        if(!t)
00633               return false;
00634               
00635        computeConstrTwoActivitiesConsecutive();
00636        
00637        computeConstrTwoActivitiesGrouped();
00638        
00639        computeConstrThreeActivitiesGrouped();
00640        
00641        computeConstrTwoActivitiesOrdered();
00642        
00643        t=computeActivityEndsStudentsDayPercentages(parent);
00644        if(!t)
00645               return false;
00646               
00647        //check for impossible min days
00648        t=checkMinDays100Percent(parent);
00649        if(!t)
00650               return false;
00651        t=checkMinDaysConsecutiveIfSameDay(parent);
00652        if(!t)
00653               return false;
00654        
00655        //check teachers interval max days per week
00656        t=computeTeachersIntervalMaxDaysPerWeek(parent);
00657        if(!t)
00658               return false;
00659        
00660        //check subgroups interval max days per week
00661        t=computeSubgroupsIntervalMaxDaysPerWeek(parent);
00662        if(!t)
00663               return false;
00664               
00666        haveActivitiesOccupyOrSimultaneousConstraints=false;
00667 
00668        //2011-09-25
00669        t=computeActivitiesOccupyMaxTimeSlotsFromSelection(parent);
00670        if(!t)
00671               return false;
00672        
00673        //2011-09-30
00674        t=computeActivitiesMaxSimultaneousInSelectedTimeSlots(parent);
00675        if(!t)
00676               return false;
00678 
00679        //2011-09-25
00680        t=computeActivitiesOccupyMaxDifferentRooms(parent);
00681        if(!t)
00682               return false;
00683        
00685        
00687        t=computeBasicSpace(parent);
00688        if(!t)
00689               return false;
00690        t=computeNotAllowedRoomTimePercentages();
00691        if(!t)
00692               return false;
00693        t=computeActivitiesRoomsPreferences(parent);
00694        if(!t)
00695               return false;
00697        
00699        t=computeMaxBuildingChangesPerDayForStudents(parent);
00700        if(!t)
00701               return false;
00702        t=computeMaxBuildingChangesPerWeekForStudents(parent);
00703        if(!t)
00704               return false;
00705        t=computeMinGapsBetweenBuildingChangesForStudents(parent);
00706        if(!t)
00707               return false;
00708 
00709        t=computeMaxBuildingChangesPerDayForTeachers(parent);
00710        if(!t)
00711               return false;
00712        t=computeMaxBuildingChangesPerWeekForTeachers(parent);
00713        if(!t)
00714               return false;
00715        t=computeMinGapsBetweenBuildingChangesForTeachers(parent);
00716        if(!t)
00717               return false;
00719        
00720        t=homeRoomsAreOk(parent);
00721        if(!t)
00722               return false;
00723        
00724        computeMustComputeTimetableSubgroups();
00725        computeMustComputeTimetableTeachers();
00726        
00727        t=computeFixedActivities(parent);
00728        if(!t)
00729               return false;
00730        
00731        //must have here repr computed correctly
00732        sortActivities(reprSameStartingTime, reprSameActivitiesSet, initialOrderStream);
00733        
00734        if(SHOW_WARNING_FOR_NOT_PERFECT_CONSTRAINTS){
00735               if(haveStudentsMaxGapsPerDay || haveTeachersActivityTagMaxHoursDaily || haveStudentsActivityTagMaxHoursDaily){
00736                      QString s=GeneratePreTranslate::tr("Your data contains constraints students max gaps per day and/or activity tag max hours daily.");
00737                      s+="\n\n";
00738                      s+=GeneratePreTranslate::tr("These constraints are good, but they are not perfectly optimized for speed. You may obtain a long generation time or even impossible timetables.");
00739                      s+=" ";
00740                      s+=GeneratePreTranslate::tr("It is recommended to use such constraints with caution.");
00741                      s+="\n\n";
00742                      s+=GeneratePreTranslate::tr("Are you sure you want to continue?");
00743        
00744                      QMessageBox::StandardButton b=QMessageBox::warning(parent, GeneratePreTranslate::tr("FET warning"), s, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
00745                      if(b!=QMessageBox::Yes)
00746                             return false;
00747               }
00748        }
00749        
00750        if(SHOW_WARNING_FOR_STUDENTS_MIN_HOURS_DAILY_WITH_ALLOW_EMPTY_DAYS){
00751               if(haveStudentsMinHoursDailyAllowEmptyDays){
00752                      QString s=GeneratePreTranslate::tr("Your data contains constraints students min hours daily which allow empty days.");
00753                      s+="\n\n";
00754                      s+=GeneratePreTranslate::tr("These constraints are nonstandard. They are recommended only if the students can have free days and a solution with free days for students exists."
00755                             " Otherwise the solution might be impossible for FET to find.");
00756                      s+=" ";
00757                      s+=GeneratePreTranslate::tr("It is recommended to use such constraints with caution.");
00758                      s+="\n\n";
00759                      s+=GeneratePreTranslate::tr("Are you sure you want to continue?");
00760        
00761                      QMessageBox::StandardButton b=QMessageBox::warning(parent, GeneratePreTranslate::tr("FET warning"), s, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
00762                      if(b!=QMessageBox::Yes)
00763                             return false;
00764               }
00765        }
00766        
00767        bool ok=true;
00768        
00769        return ok;
00770 }
00771 
00772 //must be after allowed times and after n hours per subgroup
00773 bool computeSubgroupsMaxHoursDaily(QWidget* parent)
00774 {
00775        bool ok=true;
00776        
00777        for(int i=0; i<gt.rules.nInternalSubgroups; i++){
00778               subgroupsMaxHoursDailyMaxHours1[i]=-1;
00779               subgroupsMaxHoursDailyPercentages1[i]=-1;
00780 
00781               subgroupsMaxHoursDailyMaxHours2[i]=-1;
00782               subgroupsMaxHoursDailyPercentages2[i]=-1;
00783        }
00784        
00785        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
00786               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_STUDENTS_MAX_HOURS_DAILY){
00787                      ConstraintStudentsMaxHoursDaily* smd=(ConstraintStudentsMaxHoursDaily*)gt.rules.internalTimeConstraintsList[i];
00788 
00789                      for(int sb=0; sb<gt.rules.nInternalSubgroups; sb++){
00790                             if(subgroupsMaxHoursDailyMaxHours1[sb]==-1 ||
00791                              (subgroupsMaxHoursDailyMaxHours1[sb] >= smd->maxHoursDaily &&
00792                              subgroupsMaxHoursDailyPercentages1[sb] <= smd->weightPercentage)){
00793                                    subgroupsMaxHoursDailyMaxHours1[sb] = smd->maxHoursDaily;
00794                                    subgroupsMaxHoursDailyPercentages1[sb] = smd->weightPercentage;
00795                                    }
00796                             else if(subgroupsMaxHoursDailyMaxHours1[sb] <= smd->maxHoursDaily &&
00797                              subgroupsMaxHoursDailyPercentages1[sb] >= smd->weightPercentage){
00798                                    //nothing
00799                             }
00800                             else{
00801                                    if(subgroupsMaxHoursDailyMaxHours2[sb]==-1 ||
00802                                     (subgroupsMaxHoursDailyMaxHours2[sb] >= smd->maxHoursDaily &&
00803                                     subgroupsMaxHoursDailyPercentages2[sb] <= smd->weightPercentage)){
00804                                           subgroupsMaxHoursDailyMaxHours2[sb] = smd->maxHoursDaily;
00805                                           subgroupsMaxHoursDailyPercentages2[sb] = smd->weightPercentage;
00806                                           }
00807                                    else if(subgroupsMaxHoursDailyMaxHours2[sb] <= smd->maxHoursDaily &&
00808                                     subgroupsMaxHoursDailyPercentages2[sb] >= smd->weightPercentage){
00809                                           //nothing
00810                                    }
00811                                    else{                       
00812                                            //cannot proceed
00813                                           ok=false;
00814               
00815                                           int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
00816                                            GeneratePreTranslate::tr("Cannot optimize for subgroup %1, because there are too many constraints"
00817                                            " of type max hours daily relating to him, which cannot be compressed in 2 constraints of this type."
00818                                            " Two constraints max hours can be compressed into a single one if the max hours are lower"
00819                                            " in the first one and the weight percentage is higher on the first one."
00820                                            " It is possible to use any number of such constraints for a subgroup, but their resultant must"
00821                                            " be maximum 2 constraints of type max hours daily.\n\n"
00822                                            " Example: you are allowed to use 3 constraints: 6 hours 95%, 7 hours 100% and 8 hours 100%,"
00823                                            " which can be compressed into 2 constraints: 6 hours 95%, 7 hours 100%\n\n"
00824                                            " Please modify your data accordingly and try again.")
00825                                            .arg(gt.rules.internalSubgroupsList[sb]->name),
00826                                            GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
00827                                            1, 0 );
00828                                    
00829                                           if(t==0)
00830                                                  return false;
00831                                    }
00832                             }
00833                      }
00834               }
00835               else if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_DAILY){
00836                      ConstraintStudentsSetMaxHoursDaily* smd=(ConstraintStudentsSetMaxHoursDaily*)gt.rules.internalTimeConstraintsList[i];
00837 
00838                      for(int q=0; q<smd->iSubgroupsList.count(); q++){
00839                             int sb=smd->iSubgroupsList.at(q);
00840                      //for(int sb=0; sb<gt.rules.nInternalSubgroups; sb++){
00841                             if(subgroupsMaxHoursDailyMaxHours1[sb]==-1 ||
00842                              (subgroupsMaxHoursDailyMaxHours1[sb] >= smd->maxHoursDaily &&
00843                              subgroupsMaxHoursDailyPercentages1[sb] <= smd->weightPercentage)){
00844                                    subgroupsMaxHoursDailyMaxHours1[sb] = smd->maxHoursDaily;
00845                                    subgroupsMaxHoursDailyPercentages1[sb] = smd->weightPercentage;
00846                                    }
00847                             else if(subgroupsMaxHoursDailyMaxHours1[sb] <= smd->maxHoursDaily &&
00848                              subgroupsMaxHoursDailyPercentages1[sb] >= smd->weightPercentage){
00849                                    //nothing
00850                             }
00851                             else{
00852                                    if(subgroupsMaxHoursDailyMaxHours2[sb]==-1 ||
00853                                     (subgroupsMaxHoursDailyMaxHours2[sb] >= smd->maxHoursDaily &&
00854                                     subgroupsMaxHoursDailyPercentages2[sb] <= smd->weightPercentage)){
00855                                           subgroupsMaxHoursDailyMaxHours2[sb] = smd->maxHoursDaily;
00856                                           subgroupsMaxHoursDailyPercentages2[sb] = smd->weightPercentage;
00857                                           }
00858                                    else if(subgroupsMaxHoursDailyMaxHours2[sb] <= smd->maxHoursDaily &&
00859                                     subgroupsMaxHoursDailyPercentages2[sb] >= smd->weightPercentage){
00860                                           //nothing
00861                                    }
00862                                    else{
00863                                           //cannot proceed
00864                                           ok=false;
00865        
00866                                           int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
00867                                            GeneratePreTranslate::tr("Cannot optimize for subgroup %1, because there are too many constraints"
00868                                            " of type max hours daily relating to him, which cannot be compressed in 2 constraints of this type."
00869                                            " Two constraints max hours can be compressed into a single one if the max hours are lower"
00870                                            " in the first one and the weight percentage is higher on the first one."
00871                                            " It is possible to use any number of such constraints for a subgroup, but their resultant must"
00872                                            " be maximum 2 constraints of type max hours daily.\n\n"
00873                                            " Example: you are allowed to use 3 constraints: 6 hours 95%, 7 hours 100% and 8 hours 100%,"
00874                                            " which can be compressed into 2 constraints: 6 hours 95%, 7 hours 100%\n\n"
00875                                            " Please modify your data accordingly and try again.")
00876                                            .arg(gt.rules.internalSubgroupsList[sb]->name),
00877                                            GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
00878                                            1, 0 );
00879 
00880                                           if(t==0)
00881                                                  return false;
00882                                    }
00883                             }
00884                      }
00885               }
00886        }
00887        
00888        for(int sb=0; sb<gt.rules.nInternalSubgroups; sb++){
00889               if(subgroupsMaxHoursDailyPercentages1[sb]==100){
00890                      int nAllowedSlotsPerDay[MAX_DAYS_PER_WEEK];
00891                      for(int d=0; d<gt.rules.nDaysPerWeek; d++){
00892                             nAllowedSlotsPerDay[d]=0;
00893                             for(int h=0; h<gt.rules.nHoursPerDay; h++)
00894                                    if(!breakDayHour[d][h] && !subgroupNotAvailableDayHour[sb][d][h])
00895                                           nAllowedSlotsPerDay[d]++;
00896                             nAllowedSlotsPerDay[d]=min(nAllowedSlotsPerDay[d],subgroupsMaxHoursDailyMaxHours1[sb]);
00897                      }
00898                      int total=0;
00899                      for(int d=0; d<gt.rules.nDaysPerWeek; d++)
00900                             total+=nAllowedSlotsPerDay[d];
00901                      if(total<nHoursPerSubgroup[sb]){
00902                             ok=false;
00903                             
00904                             QString s;
00905                             s=GeneratePreTranslate::tr("Cannot optimize for subgroup %1, because there is a constraint of type"
00906                              " max %2 hours daily with 100% weight which cannot be respected because of number of days per week,"
00907                              " number of hours per day, students set not available and/or breaks. The number of total hours for this subgroup is"
00908                              " %3 and the number of available slots is, considering max hours daily and all other constraints, %4.")
00909                              .arg(gt.rules.internalSubgroupsList[sb]->name)
00910                              .arg(subgroupsMaxHoursDailyMaxHours1[sb])
00911                              .arg(nHoursPerSubgroup[sb])
00912                              .arg(total);
00913                             s+="\n\n";
00914                             s+=GeneratePreTranslate::tr("Please modify your data accordingly and try again");
00915        
00916                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"), s,
00917                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
00918                              1, 0 );
00919                                    
00920                             if(t==0)
00921                                    return false;
00922                      }
00923               }
00924        }
00925 
00926        for(int sb=0; sb<gt.rules.nInternalSubgroups; sb++){
00927               if(subgroupsMaxHoursDailyPercentages2[sb]==100){
00928                      int nAllowedSlotsPerDay[MAX_DAYS_PER_WEEK];
00929                      for(int d=0; d<gt.rules.nDaysPerWeek; d++){
00930                             nAllowedSlotsPerDay[d]=0;
00931                             for(int h=0; h<gt.rules.nHoursPerDay; h++)
00932                                    if(!breakDayHour[d][h] && !subgroupNotAvailableDayHour[sb][d][h])
00933                                           nAllowedSlotsPerDay[d]++;
00934                             nAllowedSlotsPerDay[d]=min(nAllowedSlotsPerDay[d],subgroupsMaxHoursDailyMaxHours2[sb]);
00935                      }
00936                      int total=0;
00937                      for(int d=0; d<gt.rules.nDaysPerWeek; d++)
00938                             total+=nAllowedSlotsPerDay[d];
00939                      if(total<nHoursPerSubgroup[sb]){
00940                             ok=false;
00941                             
00942                             QString s;
00943                             s=GeneratePreTranslate::tr("Cannot optimize for subgroup %1, because there is a constraint of type"
00944                              " max %2 hours daily with 100% weight which cannot be respected because of number of days per week,"
00945                              " number of hours per day, students set not available and/or breaks. The number of total hours for this subgroup is"
00946                              " %3 and the number of available slots is, considering max hours daily and all other constraints, %4.")
00947                              .arg(gt.rules.internalSubgroupsList[sb]->name)
00948                              .arg(subgroupsMaxHoursDailyMaxHours2[sb])
00949                              .arg(nHoursPerSubgroup[sb])
00950                              .arg(total);
00951                             s+="\n\n";
00952                             s+=GeneratePreTranslate::tr("Please modify your data accordingly and try again");
00953        
00954                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"), s,
00955                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
00956                              1, 0 );
00957                                    
00958                             if(t==0)
00959                                    return false;
00960                      }
00961               }
00962        }
00963        
00964        return ok;
00965 }
00966        
00967 bool computeStudentsMaxHoursContinuously(QWidget* parent)
00968 {
00969        bool ok=true;
00970        
00971        for(int i=0; i<gt.rules.nInternalSubgroups; i++){
00972               subgroupsMaxHoursContinuouslyMaxHours1[i]=-1;
00973               subgroupsMaxHoursContinuouslyPercentages1[i]=-1;
00974 
00975               subgroupsMaxHoursContinuouslyMaxHours2[i]=-1;
00976               subgroupsMaxHoursContinuouslyPercentages2[i]=-1;
00977        }
00978 
00979        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
00980               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_STUDENTS_MAX_HOURS_CONTINUOUSLY){
00981                      ConstraintStudentsMaxHoursContinuously* smd=(ConstraintStudentsMaxHoursContinuously*)gt.rules.internalTimeConstraintsList[i];
00982 
00983                      for(int sb=0; sb<gt.rules.nInternalSubgroups; sb++){
00984                             if(subgroupsMaxHoursContinuouslyMaxHours1[sb]==-1 ||
00985                              (subgroupsMaxHoursContinuouslyMaxHours1[sb] >= smd->maxHoursContinuously &&
00986                              subgroupsMaxHoursContinuouslyPercentages1[sb] <= smd->weightPercentage)){
00987                                    subgroupsMaxHoursContinuouslyMaxHours1[sb] = smd->maxHoursContinuously;
00988                                    subgroupsMaxHoursContinuouslyPercentages1[sb] = smd->weightPercentage;
00989                                    }
00990                             else if(subgroupsMaxHoursContinuouslyMaxHours1[sb] <= smd->maxHoursContinuously &&
00991                              subgroupsMaxHoursContinuouslyPercentages1[sb] >= smd->weightPercentage){
00992                                    //nothing
00993                             }
00994                             else{
00995                                    if(subgroupsMaxHoursContinuouslyMaxHours2[sb]==-1 ||
00996                                     (subgroupsMaxHoursContinuouslyMaxHours2[sb] >= smd->maxHoursContinuously &&
00997                                     subgroupsMaxHoursContinuouslyPercentages2[sb] <= smd->weightPercentage)){
00998                                           subgroupsMaxHoursContinuouslyMaxHours2[sb] = smd->maxHoursContinuously;
00999                                           subgroupsMaxHoursContinuouslyPercentages2[sb] = smd->weightPercentage;
01000                                           }
01001                                    else if(subgroupsMaxHoursContinuouslyMaxHours2[sb] <= smd->maxHoursContinuously &&
01002                                     subgroupsMaxHoursContinuouslyPercentages2[sb] >= smd->weightPercentage){
01003                                           //nothing
01004                                    }
01005                                    else{                       
01006                                            //cannot proceed
01007                                           ok=false;
01008               
01009                                           int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
01010                                            GeneratePreTranslate::tr("Cannot optimize for subgroup %1, because there are too many constraints"
01011                                            " of type max hours continuously relating to him, which cannot be compressed in 2 constraints of this type."
01012                                            " Two constraints max hours can be compressed into a single one if the max hours are lower"
01013                                            " in the first one and the weight percentage is higher on the first one."
01014                                            " It is possible to use any number of such constraints for a subgroup, but their resultant must"
01015                                            " be maximum 2 constraints of type max hours continuously.\n\n"
01016                                            " Example: you are allowed to use 3 constraints: 6 hours 95%, 7 hours 100% and 8 hours 100%,"
01017                                            " which can be compressed into 2 constraints: 6 hours 95%, 7 hours 100%\n\n"
01018                                            " Please modify your data accordingly and try again.")
01019                                            .arg(gt.rules.internalSubgroupsList[sb]->name),
01020                                            GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
01021                                            1, 0 );
01022                                    
01023                                           if(t==0)
01024                                                  return false;
01025                                    }
01026                             }
01027                      }
01028               }
01029               else if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_STUDENTS_SET_MAX_HOURS_CONTINUOUSLY){
01030                      ConstraintStudentsSetMaxHoursContinuously* smd=(ConstraintStudentsSetMaxHoursContinuously*)gt.rules.internalTimeConstraintsList[i];
01031 
01032                      for(int q=0; q<smd->iSubgroupsList.count(); q++){
01033                             int sb=smd->iSubgroupsList.at(q);
01034                      //for(int sb=0; sb<gt.rules.nInternalSubgroups; sb++){
01035                             if(subgroupsMaxHoursContinuouslyMaxHours1[sb]==-1 ||
01036                              (subgroupsMaxHoursContinuouslyMaxHours1[sb] >= smd->maxHoursContinuously &&
01037                              subgroupsMaxHoursContinuouslyPercentages1[sb] <= smd->weightPercentage)){
01038                                    subgroupsMaxHoursContinuouslyMaxHours1[sb] = smd->maxHoursContinuously;
01039                                    subgroupsMaxHoursContinuouslyPercentages1[sb] = smd->weightPercentage;
01040                                    }
01041                             else if(subgroupsMaxHoursContinuouslyMaxHours1[sb] <= smd->maxHoursContinuously &&
01042                              subgroupsMaxHoursContinuouslyPercentages1[sb] >= smd->weightPercentage){
01043                                    //nothing
01044                             }
01045                             else{
01046                                    if(subgroupsMaxHoursContinuouslyMaxHours2[sb]==-1 ||
01047                                     (subgroupsMaxHoursContinuouslyMaxHours2[sb] >= smd->maxHoursContinuously &&
01048                                     subgroupsMaxHoursContinuouslyPercentages2[sb] <= smd->weightPercentage)){
01049                                           subgroupsMaxHoursContinuouslyMaxHours2[sb] = smd->maxHoursContinuously;
01050                                           subgroupsMaxHoursContinuouslyPercentages2[sb] = smd->weightPercentage;
01051                                           }
01052                                    else if(subgroupsMaxHoursContinuouslyMaxHours2[sb] <= smd->maxHoursContinuously &&
01053                                     subgroupsMaxHoursContinuouslyPercentages2[sb] >= smd->weightPercentage){
01054                                           //nothing
01055                                    }
01056                                    else{
01057                                           //cannot proceed
01058                                           ok=false;
01059        
01060                                           int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
01061                                            GeneratePreTranslate::tr("Cannot optimize for subgroup %1, because there are too many constraints"
01062                                            " of type max hours continuously relating to him, which cannot be compressed in 2 constraints of this type."
01063                                            " Two constraints max hours can be compressed into a single one if the max hours are lower"
01064                                            " in the first one and the weight percentage is higher on the first one."
01065                                            " It is possible to use any number of such constraints for a subgroup, but their resultant must"
01066                                            " be maximum 2 constraints of type max hours continuously.\n\n"
01067                                            " Example: you are allowed to use 3 constraints: 6 hours 95%, 7 hours 100% and 8 hours 100%,"
01068                                            " which can be compressed into 2 constraints: 6 hours 95%, 7 hours 100%\n\n"
01069                                            " Please modify your data accordingly and try again.")
01070                                            .arg(gt.rules.internalSubgroupsList[sb]->name),
01071                                            GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
01072                                            1, 0 );
01073 
01074                                           if(t==0)
01075                                                  return false;
01076                                    }
01077                             }
01078                      }
01079               }
01080        }
01081        
01082 
01083 
01084 
01085 
01086        for(int ai=0; ai<gt.rules.nInternalActivities; ai++){
01087               foreach(int sbg, gt.rules.internalActivitiesList[ai].iSubgroupsList){
01088                      if(subgroupsMaxHoursContinuouslyPercentages1[sbg]>=0 && gt.rules.internalActivitiesList[ai].duration > subgroupsMaxHoursContinuouslyMaxHours1[sbg]){
01089                             QString s;
01090                             s=GeneratePreTranslate::tr("Cannot optimize for subgroup %1, because there is a constraint of type"
01091                              " max %2 hours continuously which cannot be respected because of activity with id %3 (which has duration %4).")
01092                              .arg(gt.rules.internalSubgroupsList[sbg]->name)
01093                              .arg(subgroupsMaxHoursContinuouslyMaxHours1[sbg])
01094                              .arg(gt.rules.internalActivitiesList[ai].id)
01095                              .arg(gt.rules.internalActivitiesList[ai].duration);
01096                             s+="\n\n";
01097                             s+=GeneratePreTranslate::tr("Please modify your data accordingly and try again");
01098        
01099                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"), s,
01100                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
01101                              1, 0 );
01102                                    
01103                             if(t==0)
01104                                    return false;
01105                      }
01106                      if(subgroupsMaxHoursContinuouslyPercentages2[sbg]>=0 && gt.rules.internalActivitiesList[ai].duration > subgroupsMaxHoursContinuouslyMaxHours2[sbg]){
01107                             QString s;
01108                             s=GeneratePreTranslate::tr("Cannot optimize for subgroup %1, because there is a constraint of type"
01109                              " max %2 hours continuously which cannot be respected because of activity with id %3 (which has duration %4).")
01110                              .arg(gt.rules.internalSubgroupsList[sbg]->name)
01111                              .arg(subgroupsMaxHoursContinuouslyMaxHours2[sbg])
01112                              .arg(gt.rules.internalActivitiesList[ai].id)
01113                              .arg(gt.rules.internalActivitiesList[ai].duration);
01114                             s+="\n\n";
01115                             s+=GeneratePreTranslate::tr("Please modify your data accordingly and try again");
01116        
01117                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"), s,
01118                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
01119                              1, 0 );
01120                                    
01121                             if(t==0)
01122                                    return false;
01123                      }
01124               }
01125        }
01126        
01127        return ok;
01128 }
01129 
01130 bool computeStudentsActivityTagMaxHoursDaily(QWidget* parent)
01131 {
01132        haveStudentsActivityTagMaxHoursDaily=false;
01133        
01134        bool ok=true;
01135        
01136        for(int i=0; i<gt.rules.nInternalSubgroups; i++){
01137               subgroupsActivityTagMaxHoursDailyMaxHours[i].clear();
01138               subgroupsActivityTagMaxHoursDailyPercentage[i].clear();
01139               subgroupsActivityTagMaxHoursDailyActivityTag[i].clear();
01140        }
01141 
01142        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
01143               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_STUDENTS_ACTIVITY_TAG_MAX_HOURS_DAILY){
01144                      haveStudentsActivityTagMaxHoursDaily=true;
01145 
01146                      ConstraintStudentsActivityTagMaxHoursDaily* samc=(ConstraintStudentsActivityTagMaxHoursDaily*)gt.rules.internalTimeConstraintsList[i];
01147                      
01148                      foreach(int sb, samc->canonicalSubgroupsList){
01149                             int pos1=-1, pos2=-1;
01150                             
01151                             for(int j=0; j<subgroupsActivityTagMaxHoursDailyMaxHours[sb].count(); j++){
01152                                    if(subgroupsActivityTagMaxHoursDailyActivityTag[sb].at(j)==samc->activityTagIndex){
01153                                           if(pos1==-1){
01154                                                  pos1=j;
01155                                           }
01156                                           else{
01157                                                  assert(pos2==-1);
01158                                                  pos2=j;
01159                                           }
01160                                    }
01161                             }
01162                             
01163                             if(pos1==-1){
01164                                    subgroupsActivityTagMaxHoursDailyActivityTag[sb].append(samc->activityTagIndex);
01165                                    subgroupsActivityTagMaxHoursDailyMaxHours[sb].append(samc->maxHoursDaily);
01166                                    subgroupsActivityTagMaxHoursDailyPercentage[sb].append(samc->weightPercentage);
01167                             }
01168                             else{
01169                                    if(subgroupsActivityTagMaxHoursDailyMaxHours[sb].at(pos1) <= samc->maxHoursDaily
01170                                     && subgroupsActivityTagMaxHoursDailyPercentage[sb].at(pos1) >= samc->weightPercentage){
01171                                           //do nothing
01172                                    }
01173                                    else if(subgroupsActivityTagMaxHoursDailyMaxHours[sb].at(pos1) >= samc->maxHoursDaily
01174                                     && subgroupsActivityTagMaxHoursDailyPercentage[sb].at(pos1) <= samc->weightPercentage){
01175                                    
01176                                           subgroupsActivityTagMaxHoursDailyActivityTag[sb][pos1]=samc->activityTagIndex;
01177                                           subgroupsActivityTagMaxHoursDailyMaxHours[sb][pos1]=samc->maxHoursDaily;
01178                                           subgroupsActivityTagMaxHoursDailyPercentage[sb][pos1]=samc->weightPercentage;
01179                                    }
01180                                    else{
01181                                           if(pos2==-1){
01182                                                  subgroupsActivityTagMaxHoursDailyActivityTag[sb].append(samc->activityTagIndex);
01183                                                  subgroupsActivityTagMaxHoursDailyMaxHours[sb].append(samc->maxHoursDaily);
01184                                                  subgroupsActivityTagMaxHoursDailyPercentage[sb].append(samc->weightPercentage);
01185                                           }
01186                                           else{
01187 
01188                                                  if(subgroupsActivityTagMaxHoursDailyMaxHours[sb].at(pos2) <= samc->maxHoursDaily
01189                                                   && subgroupsActivityTagMaxHoursDailyPercentage[sb].at(pos2) >= samc->weightPercentage){
01190                                                         //do nothing
01191                                                  }
01192                                                  else if(subgroupsActivityTagMaxHoursDailyMaxHours[sb].at(pos2) >= samc->maxHoursDaily
01193                                                   && subgroupsActivityTagMaxHoursDailyPercentage[sb].at(pos2) <= samc->weightPercentage){
01194                                                  
01195                                                         subgroupsActivityTagMaxHoursDailyActivityTag[sb][pos2]=samc->activityTagIndex;
01196                                                         subgroupsActivityTagMaxHoursDailyMaxHours[sb][pos2]=samc->maxHoursDaily;
01197                                                         subgroupsActivityTagMaxHoursDailyPercentage[sb][pos2]=samc->weightPercentage;
01198                                                  }
01199                                                  else{
01200                                                         ok=false;
01201        
01202                                                         int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
01203                                                          GeneratePreTranslate::tr("Cannot optimize for subgroup %1, because there are too many constraints"
01204                                                          " of type activity tag max hours daily relating to him, which cannot be compressed in 2 constraints of this type."
01205                                                          " Two constraints max hours can be compressed into a single one if the max hours are lower"
01206                                                          " in the first one and the weight percentage is higher on the first one."
01207                                                          " It is possible to use any number of such constraints for a subgroup, but their resultant must"
01208                                                          " be maximum 2 constraints of type activity tag max hours daily.\n\n"
01209                                                          " Example: you are allowed to use 3 constraints: 6 hours 95%, 7 hours 100% and 8 hours 100%,"
01210                                                          " which can be compressed into 2 constraints: 6 hours 95%, 7 hours 100%\n\n"
01211                                                          " Please modify your data accordingly and try again.")
01212                                                          .arg(gt.rules.internalSubgroupsList[sb]->name),
01213                                                          GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
01214                                                          1, 0 );
01215 
01216                                                         if(t==0)
01217                                                                return false;
01218                                                  }
01219                                           }
01220                                    }
01221                             }
01222                      }
01223               }
01224               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_DAILY){
01225                      haveStudentsActivityTagMaxHoursDaily=true;
01226 
01227                      ConstraintStudentsSetActivityTagMaxHoursDaily* samc=(ConstraintStudentsSetActivityTagMaxHoursDaily*)gt.rules.internalTimeConstraintsList[i];
01228                      
01229                      foreach(int sb, samc->canonicalSubgroupsList){
01230                             int pos1=-1, pos2=-1;
01231                             
01232                             for(int j=0; j<subgroupsActivityTagMaxHoursDailyMaxHours[sb].count(); j++){
01233                                    if(subgroupsActivityTagMaxHoursDailyActivityTag[sb].at(j)==samc->activityTagIndex){
01234                                           if(pos1==-1){
01235                                                  pos1=j;
01236                                           }
01237                                           else{
01238                                                  assert(pos2==-1);
01239                                                  pos2=j;
01240                                           }
01241                                    }
01242                             }
01243                             
01244                             if(pos1==-1){
01245                                    subgroupsActivityTagMaxHoursDailyActivityTag[sb].append(samc->activityTagIndex);
01246                                    subgroupsActivityTagMaxHoursDailyMaxHours[sb].append(samc->maxHoursDaily);
01247                                    subgroupsActivityTagMaxHoursDailyPercentage[sb].append(samc->weightPercentage);
01248                             }
01249                             else{
01250                                    if(subgroupsActivityTagMaxHoursDailyMaxHours[sb].at(pos1) <= samc->maxHoursDaily
01251                                     && subgroupsActivityTagMaxHoursDailyPercentage[sb].at(pos1) >= samc->weightPercentage){
01252                                           //do nothing
01253                                    }
01254                                    else if(subgroupsActivityTagMaxHoursDailyMaxHours[sb].at(pos1) >= samc->maxHoursDaily
01255                                     && subgroupsActivityTagMaxHoursDailyPercentage[sb].at(pos1) <= samc->weightPercentage){
01256                                    
01257                                           subgroupsActivityTagMaxHoursDailyActivityTag[sb][pos1]=samc->activityTagIndex;
01258                                           subgroupsActivityTagMaxHoursDailyMaxHours[sb][pos1]=samc->maxHoursDaily;
01259                                           subgroupsActivityTagMaxHoursDailyPercentage[sb][pos1]=samc->weightPercentage;
01260                                    }
01261                                    else{
01262                                           if(pos2==-1){
01263                                                  subgroupsActivityTagMaxHoursDailyActivityTag[sb].append(samc->activityTagIndex);
01264                                                  subgroupsActivityTagMaxHoursDailyMaxHours[sb].append(samc->maxHoursDaily);
01265                                                  subgroupsActivityTagMaxHoursDailyPercentage[sb].append(samc->weightPercentage);
01266                                           }
01267                                           else{
01268 
01269                                                  if(subgroupsActivityTagMaxHoursDailyMaxHours[sb].at(pos2) <= samc->maxHoursDaily
01270                                                   && subgroupsActivityTagMaxHoursDailyPercentage[sb].at(pos2) >= samc->weightPercentage){
01271                                                         //do nothing
01272                                                  }
01273                                                  else if(subgroupsActivityTagMaxHoursDailyMaxHours[sb].at(pos2) >= samc->maxHoursDaily
01274                                                   && subgroupsActivityTagMaxHoursDailyPercentage[sb].at(pos2) <= samc->weightPercentage){
01275                                                  
01276                                                         subgroupsActivityTagMaxHoursDailyActivityTag[sb][pos2]=samc->activityTagIndex;
01277                                                         subgroupsActivityTagMaxHoursDailyMaxHours[sb][pos2]=samc->maxHoursDaily;
01278                                                         subgroupsActivityTagMaxHoursDailyPercentage[sb][pos2]=samc->weightPercentage;
01279                                                  }
01280                                                  else{
01281                                                         ok=false;
01282        
01283                                                         int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
01284                                                          GeneratePreTranslate::tr("Cannot optimize for subgroup %1, because there are too many constraints"
01285                                                          " of type activity tag max hours daily relating to him, which cannot be compressed in 2 constraints of this type."
01286                                                          " Two constraints max hours can be compressed into a single one if the max hours are lower"
01287                                                          " in the first one and the weight percentage is higher on the first one."
01288                                                          " It is possible to use any number of such constraints for a subgroup, but their resultant must"
01289                                                          " be maximum 2 constraints of type activity tag max hours daily.\n\n"
01290                                                          " Example: you are allowed to use 3 constraints: 6 hours 95%, 7 hours 100% and 8 hours 100%,"
01291                                                          " which can be compressed into 2 constraints: 6 hours 95%, 7 hours 100%\n\n"
01292                                                          " Please modify your data accordingly and try again.")
01293                                                          .arg(gt.rules.internalSubgroupsList[sb]->name),
01294                                                          GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
01295                                                          1, 0 );
01296 
01297                                                         if(t==0)
01298                                                                return false;
01299                                                  }
01300                                           }
01301                                    }
01302                             }
01303                      }
01304               }
01305        }
01306 
01307        int navd[MAX_DAYS_PER_WEEK];
01308        
01309        for(int i=0; i<gt.rules.nInternalSubgroups; i++){
01310               for(int d=0; d<gt.rules.nDaysPerWeek; d++){
01311                      navd[d]=0;
01312                      for(int h=0; h<gt.rules.nHoursPerDay; h++){
01313                             if(!breakDayHour[d][h] && !subgroupNotAvailableDayHour[i][d][h])
01314                                    navd[d]++;
01315                      }
01316               }
01317        
01318               for(int j=0; j<subgroupsActivityTagMaxHoursDailyMaxHours[i].count(); j++){
01319                      int mh=subgroupsActivityTagMaxHoursDailyMaxHours[i].at(j);
01320                      double perc=subgroupsActivityTagMaxHoursDailyPercentage[i].at(j);
01321                      int at=subgroupsActivityTagMaxHoursDailyActivityTag[i].at(j);
01322                      if(perc==100.0){
01323                             int totalAt=0;
01324                             foreach(int ai, gt.rules.internalSubgroupsList[i]->activitiesForSubgroup)
01325                                    if(gt.rules.internalActivitiesList[ai].iActivityTagsSet.contains(at))
01326                                           totalAt+=gt.rules.internalActivitiesList[ai].duration;
01327                                           
01328                             int ava=0;
01329                             for(int d=0; d<gt.rules.nDaysPerWeek; d++)
01330                                    ava+=min(navd[d], mh);
01331                                    
01332                             if(ava<totalAt){
01333                                    ok=false;
01334                                    
01335                                    int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
01336                                     GeneratePreTranslate::tr("Cannot optimize for subgroup %1, because there is a constraint activity tag %2 max %3 hours daily for it with weight 100\%"
01337                                     " which cannot be satisfied, considering the number of available slots (%4) and total duration of activities with this activity tag (%5)"
01338                                     ". Please correct and try again.", "%2 is the activity tag for this constraint, %3 is the max number of hours daily for this constraint")
01339                                     .arg(gt.rules.internalSubgroupsList[i]->name).arg(gt.rules.activityTagsList.at(at)->name).arg(mh).arg(ava).arg(totalAt),
01340                                     GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
01341                                     1, 0 );
01342 
01343                                    if(t==0)
01344                                           return false;
01345                             }
01346                      }
01347               }
01348        }
01349        
01350        return ok;
01351 }
01352 
01353 bool computeStudentsActivityTagMaxHoursContinuously(QWidget* parent)
01354 {
01355        haveStudentsActivityTagMaxHoursContinuously=false;
01356        
01357        bool ok=true;
01358        
01359        for(int i=0; i<gt.rules.nInternalSubgroups; i++){
01360               subgroupsActivityTagMaxHoursContinuouslyMaxHours[i].clear();
01361               subgroupsActivityTagMaxHoursContinuouslyPercentage[i].clear();
01362               subgroupsActivityTagMaxHoursContinuouslyActivityTag[i].clear();
01363        }
01364 
01365        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
01366               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_STUDENTS_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
01367                      haveStudentsActivityTagMaxHoursContinuously=true;
01368 
01369                      ConstraintStudentsActivityTagMaxHoursContinuously* samc=(ConstraintStudentsActivityTagMaxHoursContinuously*)gt.rules.internalTimeConstraintsList[i];
01370                      
01371                      foreach(int sb, samc->canonicalSubgroupsList){
01372                             int pos1=-1, pos2=-1;
01373                             
01374                             for(int j=0; j<subgroupsActivityTagMaxHoursContinuouslyMaxHours[sb].count(); j++){
01375                                    if(subgroupsActivityTagMaxHoursContinuouslyActivityTag[sb].at(j)==samc->activityTagIndex){
01376                                           if(pos1==-1){
01377                                                  pos1=j;
01378                                           }
01379                                           else{
01380                                                  assert(pos2==-1);
01381                                                  pos2=j;
01382                                           }
01383                                    }
01384                             }
01385                             
01386                             if(pos1==-1){
01387                                    subgroupsActivityTagMaxHoursContinuouslyActivityTag[sb].append(samc->activityTagIndex);
01388                                    subgroupsActivityTagMaxHoursContinuouslyMaxHours[sb].append(samc->maxHoursContinuously);
01389                                    subgroupsActivityTagMaxHoursContinuouslyPercentage[sb].append(samc->weightPercentage);
01390                             }
01391                             else{
01392                                    if(subgroupsActivityTagMaxHoursContinuouslyMaxHours[sb].at(pos1) <= samc->maxHoursContinuously
01393                                     && subgroupsActivityTagMaxHoursContinuouslyPercentage[sb].at(pos1) >= samc->weightPercentage){
01394                                           //do nothing
01395                                    }
01396                                    else if(subgroupsActivityTagMaxHoursContinuouslyMaxHours[sb].at(pos1) >= samc->maxHoursContinuously
01397                                     && subgroupsActivityTagMaxHoursContinuouslyPercentage[sb].at(pos1) <= samc->weightPercentage){
01398                                    
01399                                           subgroupsActivityTagMaxHoursContinuouslyActivityTag[sb][pos1]=samc->activityTagIndex;
01400                                           subgroupsActivityTagMaxHoursContinuouslyMaxHours[sb][pos1]=samc->maxHoursContinuously;
01401                                           subgroupsActivityTagMaxHoursContinuouslyPercentage[sb][pos1]=samc->weightPercentage;
01402                                    }
01403                                    else{
01404                                           if(pos2==-1){
01405                                                  subgroupsActivityTagMaxHoursContinuouslyActivityTag[sb].append(samc->activityTagIndex);
01406                                                  subgroupsActivityTagMaxHoursContinuouslyMaxHours[sb].append(samc->maxHoursContinuously);
01407                                                  subgroupsActivityTagMaxHoursContinuouslyPercentage[sb].append(samc->weightPercentage);
01408                                           }
01409                                           else{
01410 
01411                                                  if(subgroupsActivityTagMaxHoursContinuouslyMaxHours[sb].at(pos2) <= samc->maxHoursContinuously
01412                                                   && subgroupsActivityTagMaxHoursContinuouslyPercentage[sb].at(pos2) >= samc->weightPercentage){
01413                                                         //do nothing
01414                                                  }
01415                                                  else if(subgroupsActivityTagMaxHoursContinuouslyMaxHours[sb].at(pos2) >= samc->maxHoursContinuously
01416                                                   && subgroupsActivityTagMaxHoursContinuouslyPercentage[sb].at(pos2) <= samc->weightPercentage){
01417                                                  
01418                                                         subgroupsActivityTagMaxHoursContinuouslyActivityTag[sb][pos2]=samc->activityTagIndex;
01419                                                         subgroupsActivityTagMaxHoursContinuouslyMaxHours[sb][pos2]=samc->maxHoursContinuously;
01420                                                         subgroupsActivityTagMaxHoursContinuouslyPercentage[sb][pos2]=samc->weightPercentage;
01421                                                  }
01422                                                  else{
01423                                                         ok=false;
01424        
01425                                                         int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
01426                                                          GeneratePreTranslate::tr("Cannot optimize for subgroup %1, because there are too many constraints"
01427                                                          " of type activity tag max hours continuously relating to him, which cannot be compressed in 2 constraints of this type."
01428                                                          " Two constraints max hours can be compressed into a single one if the max hours are lower"
01429                                                          " in the first one and the weight percentage is higher on the first one."
01430                                                          " It is possible to use any number of such constraints for a subgroup, but their resultant must"
01431                                                          " be maximum 2 constraints of type activity tag max hours continuously.\n\n"
01432                                                          " Example: you are allowed to use 3 constraints: 6 hours 95%, 7 hours 100% and 8 hours 100%,"
01433                                                          " which can be compressed into 2 constraints: 6 hours 95%, 7 hours 100%\n\n"
01434                                                          " Please modify your data accordingly and try again.")
01435                                                          .arg(gt.rules.internalSubgroupsList[sb]->name),
01436                                                          GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
01437                                                          1, 0 );
01438 
01439                                                         if(t==0)
01440                                                                return false;
01441                                                  }
01442                                           }
01443                                    }
01444                             }
01445                      }
01446               }
01447               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_STUDENTS_SET_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
01448                      haveStudentsActivityTagMaxHoursContinuously=true;
01449 
01450                      ConstraintStudentsSetActivityTagMaxHoursContinuously* samc=(ConstraintStudentsSetActivityTagMaxHoursContinuously*)gt.rules.internalTimeConstraintsList[i];
01451                      
01452                      foreach(int sb, samc->canonicalSubgroupsList){
01453                             int pos1=-1, pos2=-1;
01454                             
01455                             for(int j=0; j<subgroupsActivityTagMaxHoursContinuouslyMaxHours[sb].count(); j++){
01456                                    if(subgroupsActivityTagMaxHoursContinuouslyActivityTag[sb].at(j)==samc->activityTagIndex){
01457                                           if(pos1==-1){
01458                                                  pos1=j;
01459                                           }
01460                                           else{
01461                                                  assert(pos2==-1);
01462                                                  pos2=j;
01463                                           }
01464                                    }
01465                             }
01466                             
01467                             if(pos1==-1){
01468                                    subgroupsActivityTagMaxHoursContinuouslyActivityTag[sb].append(samc->activityTagIndex);
01469                                    subgroupsActivityTagMaxHoursContinuouslyMaxHours[sb].append(samc->maxHoursContinuously);
01470                                    subgroupsActivityTagMaxHoursContinuouslyPercentage[sb].append(samc->weightPercentage);
01471                             }
01472                             else{
01473                                    if(subgroupsActivityTagMaxHoursContinuouslyMaxHours[sb].at(pos1) <= samc->maxHoursContinuously
01474                                     && subgroupsActivityTagMaxHoursContinuouslyPercentage[sb].at(pos1) >= samc->weightPercentage){
01475                                           //do nothing
01476                                    }
01477                                    else if(subgroupsActivityTagMaxHoursContinuouslyMaxHours[sb].at(pos1) >= samc->maxHoursContinuously
01478                                     && subgroupsActivityTagMaxHoursContinuouslyPercentage[sb].at(pos1) <= samc->weightPercentage){
01479                                    
01480                                           subgroupsActivityTagMaxHoursContinuouslyActivityTag[sb][pos1]=samc->activityTagIndex;
01481                                           subgroupsActivityTagMaxHoursContinuouslyMaxHours[sb][pos1]=samc->maxHoursContinuously;
01482                                           subgroupsActivityTagMaxHoursContinuouslyPercentage[sb][pos1]=samc->weightPercentage;
01483                                    }
01484                                    else{
01485                                           if(pos2==-1){
01486                                                  subgroupsActivityTagMaxHoursContinuouslyActivityTag[sb].append(samc->activityTagIndex);
01487                                                  subgroupsActivityTagMaxHoursContinuouslyMaxHours[sb].append(samc->maxHoursContinuously);
01488                                                  subgroupsActivityTagMaxHoursContinuouslyPercentage[sb].append(samc->weightPercentage);
01489                                           }
01490                                           else{
01491 
01492                                                  if(subgroupsActivityTagMaxHoursContinuouslyMaxHours[sb].at(pos2) <= samc->maxHoursContinuously
01493                                                   && subgroupsActivityTagMaxHoursContinuouslyPercentage[sb].at(pos2) >= samc->weightPercentage){
01494                                                         //do nothing
01495                                                  }
01496                                                  else if(subgroupsActivityTagMaxHoursContinuouslyMaxHours[sb].at(pos2) >= samc->maxHoursContinuously
01497                                                   && subgroupsActivityTagMaxHoursContinuouslyPercentage[sb].at(pos2) <= samc->weightPercentage){
01498                                                  
01499                                                         subgroupsActivityTagMaxHoursContinuouslyActivityTag[sb][pos2]=samc->activityTagIndex;
01500                                                         subgroupsActivityTagMaxHoursContinuouslyMaxHours[sb][pos2]=samc->maxHoursContinuously;
01501                                                         subgroupsActivityTagMaxHoursContinuouslyPercentage[sb][pos2]=samc->weightPercentage;
01502                                                  }
01503                                                  else{
01504                                                         ok=false;
01505        
01506                                                         int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
01507                                                          GeneratePreTranslate::tr("Cannot optimize for subgroup %1, because there are too many constraints"
01508                                                          " of type activity tag max hours continuously relating to him, which cannot be compressed in 2 constraints of this type."
01509                                                          " Two constraints max hours can be compressed into a single one if the max hours are lower"
01510                                                          " in the first one and the weight percentage is higher on the first one."
01511                                                          " It is possible to use any number of such constraints for a subgroup, but their resultant must"
01512                                                          " be maximum 2 constraints of type activity tag max hours continuously.\n\n"
01513                                                          " Example: you are allowed to use 3 constraints: 6 hours 95%, 7 hours 100% and 8 hours 100%,"
01514                                                          " which can be compressed into 2 constraints: 6 hours 95%, 7 hours 100%\n\n"
01515                                                          " Please modify your data accordingly and try again.")
01516                                                          .arg(gt.rules.internalSubgroupsList[sb]->name),
01517                                                          GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
01518                                                          1, 0 );
01519 
01520                                                         if(t==0)
01521                                                                return false;
01522                                                  }
01523                                           }
01524                                    }
01525                             }
01526                      }
01527               }
01528        }
01529        
01530        return ok;
01531 }
01532 
01533 bool computeSubgroupsMinHoursDaily(QWidget* parent)
01534 {
01535        bool ok=true;
01536        
01537        for(int i=0; i<gt.rules.nInternalSubgroups; i++){
01538               subgroupsMinHoursDailyMinHours[i]=-1;
01539               subgroupsMinHoursDailyPercentages[i]=-1;
01540               subgroupsMinHoursDailyAllowEmptyDays[i]=true;
01541        }
01542        
01543        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
01544               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_STUDENTS_MIN_HOURS_DAILY){
01545                      ConstraintStudentsMinHoursDaily* smd=(ConstraintStudentsMinHoursDaily*)gt.rules.internalTimeConstraintsList[i];
01546                      
01547                      if(smd->weightPercentage!=100){
01548                             ok=false;
01549        
01550                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
01551                              GeneratePreTranslate::tr("Cannot optimize for students, because the constraint of type min hours daily relating to students"
01552                              " has no 100% weight"
01553                              ". Please modify your data accordingly and try again"),
01554                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
01555                              1, 0 );
01556                                    
01557                             if(t==0)
01558                                    return false;
01559                      }
01560                      
01562                      if(smd->minHoursDaily>gt.rules.nHoursPerDay){
01563                             ok=false;
01564 
01565                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
01566                              GeneratePreTranslate::tr("Cannot optimize, because you have constraint students min hours daily with"
01567                              " %1 min hours daily, and the number of working hours per day is only %2. Please correct and try again")
01568                              .arg(smd->minHoursDaily)
01569                              .arg(gt.rules.nHoursPerDay),
01570                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
01571                              1, 0 );
01572                             
01573                             if(t==0)
01574                                    return false;
01575                      }
01577               }
01578               else if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_STUDENTS_SET_MIN_HOURS_DAILY){
01579                      ConstraintStudentsSetMinHoursDaily* smd=(ConstraintStudentsSetMinHoursDaily*)gt.rules.internalTimeConstraintsList[i];
01580                      
01581                      if(smd->weightPercentage!=100){
01582                             ok=false;
01583        
01584                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
01585                              GeneratePreTranslate::tr("Cannot optimize for students set %1, because the constraint of type min hours daily relating to him"
01586                              " has no 100% weight"
01587                              ". Please modify your data accordingly and try again")
01588                              .arg(smd->students),
01589                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
01590                              1, 0 );
01591                                    
01592                             if(t==0)
01593                                    return false;
01594                      }
01595 
01597                      if(smd->minHoursDaily>gt.rules.nHoursPerDay){
01598                             ok=false;
01599 
01600                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
01601                              GeneratePreTranslate::tr("Cannot optimize, because you have constraint students set min hours daily for students set %1 with"
01602                              " %2 min hours daily, and the number of working hours per day is only %3. Please correct and try again")
01603                              .arg(smd->students)
01604                              .arg(smd->minHoursDaily)
01605                              .arg(gt.rules.nHoursPerDay),
01606                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
01607                              1, 0 );
01608                             
01609                             if(t==0)
01610                                    return false;
01611                      }
01613               }
01614        }
01615 
01616        if(!ok)
01617               return ok;
01618 
01619        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
01620               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_STUDENTS_MIN_HOURS_DAILY){
01621                      ConstraintStudentsMinHoursDaily* smd=(ConstraintStudentsMinHoursDaily*)gt.rules.internalTimeConstraintsList[i];
01622 
01623                      for(int sb=0; sb<gt.rules.nInternalSubgroups; sb++){
01624                             if(subgroupsMinHoursDailyMinHours[sb]==-1 ||
01625                              (subgroupsMinHoursDailyMinHours[sb] <= smd->minHoursDaily &&
01626                              subgroupsMinHoursDailyPercentages[sb] <= smd->weightPercentage)){
01627                                    subgroupsMinHoursDailyMinHours[sb] = smd->minHoursDaily;
01628                                    subgroupsMinHoursDailyPercentages[sb] = smd->weightPercentage;
01629                                    }
01630                             else if(subgroupsMinHoursDailyMinHours[sb] >= smd->minHoursDaily &&
01631                              subgroupsMinHoursDailyPercentages[sb] >= smd->weightPercentage){
01632                                    //nothing
01633                             }
01634                             else{ //cannot proceed
01635                                    ok=false;
01636        
01637                                    int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
01638                                     GeneratePreTranslate::tr("Cannot optimize for subgroup %1, because there are two constraints"
01639                                     " of type min hours daily relating to him, and the weight percentage is higher on the constraint"
01640                                     " with less minimum hours. You are allowed only to have for each subgroup"
01641                                     " the most important constraint with maximum weight percentage and largest minimum hours daily allowed"
01642                                     ". Please modify your data accordingly and try again")
01643                                     .arg(gt.rules.internalSubgroupsList[sb]->name),
01644                                     GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
01645                                     1, 0 );
01646                                    
01647                                    if(t==0)
01648                                           return false;
01649                             }
01650                             
01651                             if(smd->allowEmptyDays==false)
01652                                    subgroupsMinHoursDailyAllowEmptyDays[sb]=false;
01653                      }
01654               }
01655               else if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_STUDENTS_SET_MIN_HOURS_DAILY){
01656                      ConstraintStudentsSetMinHoursDaily* smd=(ConstraintStudentsSetMinHoursDaily*)gt.rules.internalTimeConstraintsList[i];
01657 
01658                      for(int q=0; q<smd->iSubgroupsList.count(); q++){
01659                             int sb=smd->iSubgroupsList.at(q);
01660                             if(subgroupsMinHoursDailyMinHours[sb]==-1 ||
01661                              (subgroupsMinHoursDailyMinHours[sb] <= smd->minHoursDaily &&
01662                              subgroupsMinHoursDailyPercentages[sb] <= smd->weightPercentage)){
01663                                    subgroupsMinHoursDailyMinHours[sb] = smd->minHoursDaily;
01664                                    subgroupsMinHoursDailyPercentages[sb] = smd->weightPercentage;
01665                                    }
01666                             else if(subgroupsMinHoursDailyMinHours[sb] >= smd->minHoursDaily &&
01667                              subgroupsMinHoursDailyPercentages[sb] >= smd->weightPercentage){
01668                                    //nothing
01669                             }
01670                             else{ //cannot proceed
01671                                    ok=false;
01672        
01673                                    int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
01674                                     GeneratePreTranslate::tr("Cannot optimize for subgroup %1, because there are two constraints"
01675                                     " of type min hours daily relating to him, and the weight percentage is higher on the constraint"
01676                                     " with less minimum hours. You are allowed only to have for each subgroup"
01677                                     " the most important constraint with maximum weight percentage and largest minimum hours daily allowed"
01678                                     ". Please modify your data accordingly and try again")
01679                                     .arg(gt.rules.internalSubgroupsList[sb]->name),
01680                                     GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
01681                                     1, 0 );
01682                                    
01683                                    if(t==0)
01684                                           return false;
01685                             }
01686                             if(smd->allowEmptyDays==false)
01687                                    subgroupsMinHoursDailyAllowEmptyDays[sb]=false;
01688                      }
01689               }
01690        }
01691        
01692        haveStudentsMinHoursDailyAllowEmptyDays=false;
01693 
01694        for(int i=0; i<gt.rules.nInternalSubgroups; i++){
01695               if(subgroupsMinHoursDailyMinHours[i]>=0 && subgroupsMinHoursDailyAllowEmptyDays[i]==true && !haveStudentsMinHoursDailyAllowEmptyDays)
01696                      haveStudentsMinHoursDailyAllowEmptyDays=true;
01697        
01698               if(subgroupsMinHoursDailyMinHours[i]>=0 && subgroupsMinHoursDailyAllowEmptyDays[i]==false){
01699                      if(gt.rules.nDaysPerWeek*subgroupsMinHoursDailyMinHours[i] > nHoursPerSubgroup[i]){
01700                             ok=false;
01701                      
01702                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
01703                              GeneratePreTranslate::tr("For subgroup %1 you have too little activities to respect the constraint(s)"
01704                              " of type min hours daily (the constraint(s) do not allow empty days). Please modify your data accordingly and try again.")
01705                              .arg(gt.rules.internalSubgroupsList[i]->name),
01706                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
01707                              1, 0 );
01708                                    
01709                             if(t==0)
01710                                    return false;
01711                      }
01712 
01713                      for(int j=0; j<gt.rules.nDaysPerWeek; j++){
01714                             int freeSlots=0;
01715                             for(int k=0; k<gt.rules.nHoursPerDay; k++)
01716                                    if(!subgroupNotAvailableDayHour[i][j][k] && !breakDayHour[j][k])
01717                                           freeSlots++;
01718                             if(subgroupsMinHoursDailyMinHours[i]>freeSlots){
01719                                    ok=false;
01720                      
01721                                    int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
01722                                     GeneratePreTranslate::tr("For subgroup %1 cannot respect the constraint(s)"
01723                                     " of type min hours daily (the constraint(s) do not allow empty days) on day %2, because of students set not available and/or break."
01724                                     " Please modify your data accordingly and try again")
01725                                     .arg(gt.rules.internalSubgroupsList[i]->name)
01726                                     .arg(gt.rules.daysOfTheWeek[j]),
01727                                     GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
01728                                     1, 0 );
01729                                    
01730                                    if(t==0)
01731                                           return false;
01732                             }
01733                      }
01734               }
01735               else if(subgroupsMinHoursDailyMinHours[i]>=0 && subgroupsMinHoursDailyAllowEmptyDays[i]==true){
01736 
01737                      if(nHoursPerSubgroup[i]>0 && subgroupsMinHoursDailyMinHours[i]>nHoursPerSubgroup[i]){
01738                             ok=false;
01739 
01740                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
01741                              GeneratePreTranslate::tr("Cannot optimize, because you have constraint students min %1 hours daily for subgroup"
01742                              " %2 (the constraint allows empty days). This subgroup has in total only %3 hours per week, so impossible constraint."
01743                              " Please correct and try again")
01744                              .arg(subgroupsMinHoursDailyMinHours[i])
01745                              .arg(gt.rules.internalSubgroupsList[i]->name)
01746                              .arg(nHoursPerSubgroup[i])
01747                              ,
01748                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
01749                              1, 0 );
01750                             
01751                             if(t==0)
01752                                    return false;
01753                      }
01754 
01755                      if(subgroupsMinHoursDailyMinHours[i]<2){
01756                             ok=false;
01757 
01758                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
01759                              GeneratePreTranslate::tr("Cannot optimize, because you have constraint students min %1 hours daily for subgroup"
01760                              " %2 and the constraint allows empty days. The number of min hours daily should be at least 2, to make a non-trivial constraint. Please correct and try again")
01761                              .arg(subgroupsMinHoursDailyMinHours[i])
01762                              .arg(gt.rules.internalSubgroupsList[i]->name)
01763                              ,
01764                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
01765                              1, 0 );
01766                             
01767                             if(t==0)
01768                                    return false;
01769                      }
01770               }
01771        }
01772        
01773        return ok;
01774 }
01775        
01776 //must be after allowed times, after n hours per teacher and after max days per week
01777 bool computeTeachersMaxHoursDaily(QWidget* parent)
01778 {
01779        bool ok=true;
01780        
01781        for(int i=0; i<gt.rules.nInternalTeachers; i++){
01782               teachersMaxHoursDailyMaxHours1[i]=-1;
01783               teachersMaxHoursDailyPercentages1[i]=-1;
01784 
01785               teachersMaxHoursDailyMaxHours2[i]=-1;
01786               teachersMaxHoursDailyPercentages2[i]=-1;
01787        }
01788        
01789        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
01790               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TEACHER_MAX_HOURS_DAILY){
01791                      ConstraintTeacherMaxHoursDaily* tmd=(ConstraintTeacherMaxHoursDaily*)gt.rules.internalTimeConstraintsList[i];
01792 
01794                      /*if(tmd->weightPercentage!=100){
01795                             ok=false;
01796 
01797                             int t=QMessageBox::warning(parent, GeneratePreTranslate::tr("FET warning"),
01798                              GeneratePreTranslate::tr("Cannot optimize, because you have constraint teacher max hours daily for teacher %1 with"
01799                              " weight (percentage) below 100. Starting with FET version 5.3.0 it is only possible"
01800                              " to use 100% weight for such constraints. Please make weight 100% and try again")
01801                              .arg(tmd->teacherName),
01802                              GeneratePreTranslate::tr("Skip rest of max hours problems"), GeneratePreTranslate::tr("See next incompatibility max hours"), QString(),
01803                              1, 0 );
01804                             
01805                             if(t==0)
01806                                    return false;
01807                      }*/
01809 
01810                      if(teachersMaxHoursDailyMaxHours1[tmd->teacher_ID]==-1 ||
01811                       (teachersMaxHoursDailyMaxHours1[tmd->teacher_ID] >= tmd->maxHoursDaily &&
01812                       teachersMaxHoursDailyPercentages1[tmd->teacher_ID] <= tmd->weightPercentage)){
01813                             teachersMaxHoursDailyMaxHours1[tmd->teacher_ID] = tmd->maxHoursDaily;
01814                             teachersMaxHoursDailyPercentages1[tmd->teacher_ID] = tmd->weightPercentage;
01815                      }
01816                      else if(teachersMaxHoursDailyMaxHours1[tmd->teacher_ID] <= tmd->maxHoursDaily &&
01817                       teachersMaxHoursDailyPercentages1[tmd->teacher_ID] >= tmd->weightPercentage){
01818                             //nothing
01819                      }
01820                      else{
01821                             if(teachersMaxHoursDailyMaxHours2[tmd->teacher_ID]==-1 ||
01822                              (teachersMaxHoursDailyMaxHours2[tmd->teacher_ID] >= tmd->maxHoursDaily &&
01823                              teachersMaxHoursDailyPercentages2[tmd->teacher_ID] <= tmd->weightPercentage)){
01824                                    teachersMaxHoursDailyMaxHours2[tmd->teacher_ID] = tmd->maxHoursDaily;
01825                                    teachersMaxHoursDailyPercentages2[tmd->teacher_ID] = tmd->weightPercentage;
01826                             }
01827                             else if(teachersMaxHoursDailyMaxHours2[tmd->teacher_ID] <= tmd->maxHoursDaily &&
01828                              teachersMaxHoursDailyPercentages2[tmd->teacher_ID] >= tmd->weightPercentage){
01829                                    //nothing
01830                             }
01831                             else{ //cannot proceed
01832                                    ok=false;
01833 
01834                                    int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
01835                                     GeneratePreTranslate::tr("Cannot optimize for teacher %1, because there are too many constraints"
01836                                     " of type max hours daily relating to him, which cannot be compressed in 2 constraints of this type."
01837                                     " Two constraints max hours can be compressed into a single one if the max hours are lower"
01838                                     " in the first one and the weight percentage is higher on the first one."
01839                                     " It is possible to use any number of such constraints for a teacher, but their resultant must"
01840                                     " be maximum 2 constraints of type max hours daily.\n\n"
01841                                     " Example: you are allowed to use 3 constraints: 6 hours 95%, 7 hours 100% and 8 hours 100%,"
01842                                     " which can be compressed into 2 constraints: 6 hours 95%, 7 hours 100%\n\n"
01843                                     " Please modify your data accordingly and try again.")
01844                                     .arg(gt.rules.internalTeachersList[tmd->teacher_ID]->name),
01845                                     GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
01846                                     1, 0 );
01847                                    
01848                                    if(t==0)
01849                                           return false;
01850                             }
01851                      }
01852               }
01853               else if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TEACHERS_MAX_HOURS_DAILY){
01854                      ConstraintTeachersMaxHoursDaily* tmd=(ConstraintTeachersMaxHoursDaily*)gt.rules.internalTimeConstraintsList[i];
01855 
01857                      /*if(tmd->weightPercentage!=100){
01858                             ok=false;
01859 
01860                             int t=QMessageBox::warning(parent, GeneratePreTranslate::tr("FET warning"),
01861                              GeneratePreTranslate::tr("Cannot optimize, because you have constraint teachers max hours daily with"
01862                              " weight (percentage) below 100. Starting with FET version 5.3.0 it is only possible"
01863                              " to use 100% weight for such constraints. Please make weight 100% and try again"),
01864                              GeneratePreTranslate::tr("Skip rest of max hours problems"), GeneratePreTranslate::tr("See next incompatibility max hours"), QString(),
01865                              1, 0 );
01866                             
01867                             if(t==0)
01868                                    return false;
01869                      }*/
01871 
01872                      for(int tch=0; tch<gt.rules.nInternalTeachers; tch++){
01873                             if(teachersMaxHoursDailyMaxHours1[tch]==-1 ||
01874                              (teachersMaxHoursDailyMaxHours1[tch] >= tmd->maxHoursDaily &&
01875                              teachersMaxHoursDailyPercentages1[tch] <= tmd->weightPercentage)){
01876                                    teachersMaxHoursDailyMaxHours1[tch] = tmd->maxHoursDaily;
01877                                    teachersMaxHoursDailyPercentages1[tch] = tmd->weightPercentage;
01878                                    }
01879                             else if(teachersMaxHoursDailyMaxHours1[tch] <= tmd->maxHoursDaily &&
01880                              teachersMaxHoursDailyPercentages1[tch] >= tmd->weightPercentage){
01881                                    //nothing
01882                             }
01883                             else{
01884                                    if(teachersMaxHoursDailyMaxHours2[tch]==-1 ||
01885                                     (teachersMaxHoursDailyMaxHours2[tch] >= tmd->maxHoursDaily &&
01886                                     teachersMaxHoursDailyPercentages2[tch] <= tmd->weightPercentage)){
01887                                           teachersMaxHoursDailyMaxHours2[tch] = tmd->maxHoursDaily;
01888                                           teachersMaxHoursDailyPercentages2[tch] = tmd->weightPercentage;
01889                                           }
01890                                    else if(teachersMaxHoursDailyMaxHours2[tch] <= tmd->maxHoursDaily &&
01891                                     teachersMaxHoursDailyPercentages2[tch] >= tmd->weightPercentage){
01892                                    //nothing
01893                                    }
01894                                    else{ //cannot proceed
01895                                           ok=false;
01896 
01897                                           int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
01898                                            GeneratePreTranslate::tr("Cannot optimize for teacher %1, because there are too many constraints"
01899                                            " of type max hours daily relating to him, which cannot be compressed in 2 constraints of this type."
01900                                            " Two constraints max hours can be compressed into a single one if the max hours are lower"
01901                                            " in the first one and the weight percentage is higher on the first one."
01902                                            " It is possible to use any number of such constraints for a teacher, but their resultant must"
01903                                            " be maximum 2 constraints of type max hours daily.\n\n"
01904                                            " Example: you are allowed to use 3 constraints: 6 hours 95%, 7 hours 100% and 8 hours 100%,"
01905                                            " which can be compressed into 2 constraints: 6 hours 95%, 7 hours 100%\n\n"
01906                                            " Please modify your data accordingly and try again.")
01907                                            .arg(gt.rules.internalTeachersList[tch]->name),
01908                                            GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
01909                                            1, 0 );
01910 
01911                                           if(t==0)
01912                                                  return false;
01913                                    }
01914                             }
01915                      }
01916               }
01917        }
01918        
01919        for(int tc=0; tc<gt.rules.nInternalTeachers; tc++){
01920               if(teachersMaxHoursDailyPercentages1[tc]==100){
01921                      int nAllowedSlotsPerDay[MAX_DAYS_PER_WEEK];
01922                      for(int d=0; d<gt.rules.nDaysPerWeek; d++){
01923                             nAllowedSlotsPerDay[d]=0;
01924                             for(int h=0; h<gt.rules.nHoursPerDay; h++)
01925                                    if(!breakDayHour[d][h] && !teacherNotAvailableDayHour[tc][d][h])
01926                                           nAllowedSlotsPerDay[d]++;
01927                             nAllowedSlotsPerDay[d]=min(nAllowedSlotsPerDay[d],teachersMaxHoursDailyMaxHours1[tc]);
01928                      }
01929                      
01930                      int dayAvailable[MAX_DAYS_PER_WEEK];
01931                      for(int d=0; d<gt.rules.nDaysPerWeek; d++)
01932                             dayAvailable[d]=1;
01933                      if(teachersMaxDaysPerWeekMaxDays[tc]>=0){
01934                             //n days per week has 100% weight
01935                             for(int d=0; d<gt.rules.nDaysPerWeek; d++)
01936                                    dayAvailable[d]=0;
01937                             assert(teachersMaxDaysPerWeekMaxDays[tc]<=gt.rules.nDaysPerWeek);
01938                             for(int k=0; k<teachersMaxDaysPerWeekMaxDays[tc]; k++){
01939                                    int maxPos=-1, maxVal=-1;
01940                                    for(int d=0; d<gt.rules.nDaysPerWeek; d++)
01941                                           if(dayAvailable[d]==0)
01942                                                  if(maxVal<nAllowedSlotsPerDay[d]){
01943                                                         maxVal=nAllowedSlotsPerDay[d];
01944                                                         maxPos=d;
01945                                                  }
01946                                    assert(maxPos>=0);
01947                                    assert(dayAvailable[maxPos]==0);
01948                                    dayAvailable[maxPos]=1;
01949                             }
01950                      }
01951                      
01952                      int total=0;
01953                      for(int d=0; d<gt.rules.nDaysPerWeek; d++)
01954                             if(dayAvailable[d]==1)
01955                                    total+=nAllowedSlotsPerDay[d];
01956                      if(total<nHoursPerTeacher[tc]){
01957                             ok=false;
01958                             
01959                             QString s;
01960                             s=GeneratePreTranslate::tr("Cannot optimize for teacher %1, because there is a constraint of type"
01961                              " max %2 hours daily with 100% weight which cannot be respected because of number of days per week,"
01962                              " number of hours per day, teacher max days per week, teacher not available and/or breaks."
01963                              " The number of total hours for this teacher is"
01964                              " %3 and the number of available slots is, considering max hours daily and all other constraints, %4.")
01965                              .arg(gt.rules.internalTeachersList[tc]->name)
01966                              .arg(teachersMaxHoursDailyMaxHours1[tc])
01967                              .arg(nHoursPerTeacher[tc])
01968                              .arg(total);
01969                             s+="\n\n";
01970                             s+=GeneratePreTranslate::tr("Please modify your data accordingly and try again");
01971        
01972                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"), s,
01973                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
01974                              1, 0 );
01975                                    
01976                             if(t==0)
01977                                    return false;
01978                      }
01979               }
01980        }
01981 
01982        for(int tc=0; tc<gt.rules.nInternalTeachers; tc++){
01983               if(teachersMaxHoursDailyPercentages2[tc]==100){
01984                      int nAllowedSlotsPerDay[MAX_DAYS_PER_WEEK];
01985                      for(int d=0; d<gt.rules.nDaysPerWeek; d++){
01986                             nAllowedSlotsPerDay[d]=0;
01987                             for(int h=0; h<gt.rules.nHoursPerDay; h++)
01988                                    if(!breakDayHour[d][h] && !teacherNotAvailableDayHour[tc][d][h])
01989                                           nAllowedSlotsPerDay[d]++;
01990                             nAllowedSlotsPerDay[d]=min(nAllowedSlotsPerDay[d],teachersMaxHoursDailyMaxHours2[tc]);
01991                      }
01992                      
01993                      int dayAvailable[MAX_DAYS_PER_WEEK];
01994                      for(int d=0; d<gt.rules.nDaysPerWeek; d++)
01995                             dayAvailable[d]=1;
01996                      if(teachersMaxDaysPerWeekMaxDays[tc]>=0){
01997                             //n days per week has 100% weight
01998                             for(int d=0; d<gt.rules.nDaysPerWeek; d++)
01999                                    dayAvailable[d]=0;
02000                             assert(teachersMaxDaysPerWeekMaxDays[tc]<=gt.rules.nDaysPerWeek);
02001                             for(int k=0; k<teachersMaxDaysPerWeekMaxDays[tc]; k++){
02002                                    int maxPos=-1, maxVal=-1;
02003                                    for(int d=0; d<gt.rules.nDaysPerWeek; d++)
02004                                           if(dayAvailable[d]==0)
02005                                                  if(maxVal<nAllowedSlotsPerDay[d]){
02006                                                         maxVal=nAllowedSlotsPerDay[d];
02007                                                         maxPos=d;
02008                                                  }
02009                                    assert(maxPos>=0);
02010                                    assert(dayAvailable[maxPos]==0);
02011                                    dayAvailable[maxPos]=1;
02012                             }
02013                      }
02014                      
02015                      int total=0;
02016                      for(int d=0; d<gt.rules.nDaysPerWeek; d++)
02017                             if(dayAvailable[d]==1)
02018                                    total+=nAllowedSlotsPerDay[d];
02019                      if(total<nHoursPerTeacher[tc]){
02020                             ok=false;
02021                             
02022                             QString s;
02023                             s=GeneratePreTranslate::tr("Cannot optimize for teacher %1, because there is a constraint of type"
02024                              " max %2 hours daily with 100% weight which cannot be respected because of number of days per week,"
02025                              " number of hours per day, teacher max days per week, teacher not available and/or breaks."
02026                              " The number of total hours for this teacher is"
02027                              " %3 and the number of available slots is, considering max hours daily and all other constraints, %4.")
02028                              .arg(gt.rules.internalTeachersList[tc]->name)
02029                              .arg(teachersMaxHoursDailyMaxHours2[tc])
02030                              .arg(nHoursPerTeacher[tc])
02031                              .arg(total);
02032                             s+="\n\n";
02033                             s+=GeneratePreTranslate::tr("Please modify your data accordingly and try again");
02034        
02035                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"), s,
02036                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
02037                              1, 0 );
02038                                    
02039                             if(t==0)
02040                                    return false;
02041                      }
02042               }
02043        }
02044 
02045        return ok;
02046 }
02047 
02048 bool computeTeachersMaxHoursContinuously(QWidget* parent)
02049 {
02050        bool ok=true;
02051        
02052        for(int i=0; i<gt.rules.nInternalTeachers; i++){
02053               teachersMaxHoursContinuouslyMaxHours1[i]=-1;
02054               teachersMaxHoursContinuouslyPercentages1[i]=-1;
02055 
02056               teachersMaxHoursContinuouslyMaxHours2[i]=-1;
02057               teachersMaxHoursContinuouslyPercentages2[i]=-1;
02058        }
02059 
02060        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
02061               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TEACHER_MAX_HOURS_CONTINUOUSLY){
02062                      ConstraintTeacherMaxHoursContinuously* tmd=(ConstraintTeacherMaxHoursContinuously*)gt.rules.internalTimeConstraintsList[i];
02063 
02064                      if(teachersMaxHoursContinuouslyMaxHours1[tmd->teacher_ID]==-1 ||
02065                       (teachersMaxHoursContinuouslyMaxHours1[tmd->teacher_ID] >= tmd->maxHoursContinuously &&
02066                       teachersMaxHoursContinuouslyPercentages1[tmd->teacher_ID] <= tmd->weightPercentage)){
02067                             teachersMaxHoursContinuouslyMaxHours1[tmd->teacher_ID] = tmd->maxHoursContinuously;
02068                             teachersMaxHoursContinuouslyPercentages1[tmd->teacher_ID] = tmd->weightPercentage;
02069                      }
02070                      else if(teachersMaxHoursContinuouslyMaxHours1[tmd->teacher_ID] <= tmd->maxHoursContinuously &&
02071                       teachersMaxHoursContinuouslyPercentages1[tmd->teacher_ID] >= tmd->weightPercentage){
02072                             //nothing
02073                      }
02074                      else{
02075                             if(teachersMaxHoursContinuouslyMaxHours2[tmd->teacher_ID]==-1 ||
02076                              (teachersMaxHoursContinuouslyMaxHours2[tmd->teacher_ID] >= tmd->maxHoursContinuously &&
02077                              teachersMaxHoursContinuouslyPercentages2[tmd->teacher_ID] <= tmd->weightPercentage)){
02078                                    teachersMaxHoursContinuouslyMaxHours2[tmd->teacher_ID] = tmd->maxHoursContinuously;
02079                                    teachersMaxHoursContinuouslyPercentages2[tmd->teacher_ID] = tmd->weightPercentage;
02080                             }
02081                             else if(teachersMaxHoursContinuouslyMaxHours2[tmd->teacher_ID] <= tmd->maxHoursContinuously &&
02082                              teachersMaxHoursContinuouslyPercentages2[tmd->teacher_ID] >= tmd->weightPercentage){
02083                                    //nothing
02084                             }
02085                             else{ //cannot proceed
02086                                    ok=false;
02087 
02088                                    int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
02089                                     GeneratePreTranslate::tr("Cannot optimize for teacher %1, because there are too many constraints"
02090                                     " of type max hours continuously relating to him, which cannot be compressed in 2 constraints of this type."
02091                                     " Two constraints max hours can be compressed into a single one if the max hours are lower"
02092                                     " in the first one and the weight percentage is higher on the first one."
02093                                     " It is possible to use any number of such constraints for a teacher, but their resultant must"
02094                                     " be maximum 2 constraints of type max hours continuously.\n\n"
02095                                     " Example: you are allowed to use 3 constraints: 6 hours 95%, 7 hours 100% and 8 hours 100%,"
02096                                     " which can be compressed into 2 constraints: 6 hours 95%, 7 hours 100%\n\n"
02097                                     " Please modify your data accordingly and try again.")
02098                                     .arg(gt.rules.internalTeachersList[tmd->teacher_ID]->name),
02099                                     GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
02100                                     1, 0 );
02101                                    
02102                                    if(t==0)
02103                                           return false;
02104                             }
02105                      }
02106               }
02107               else if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TEACHERS_MAX_HOURS_CONTINUOUSLY){
02108                      ConstraintTeachersMaxHoursContinuously* tmd=(ConstraintTeachersMaxHoursContinuously*)gt.rules.internalTimeConstraintsList[i];
02109 
02110                      for(int tch=0; tch<gt.rules.nInternalTeachers; tch++){
02111                             if(teachersMaxHoursContinuouslyMaxHours1[tch]==-1 ||
02112                              (teachersMaxHoursContinuouslyMaxHours1[tch] >= tmd->maxHoursContinuously &&
02113                              teachersMaxHoursContinuouslyPercentages1[tch] <= tmd->weightPercentage)){
02114                                    teachersMaxHoursContinuouslyMaxHours1[tch] = tmd->maxHoursContinuously;
02115                                    teachersMaxHoursContinuouslyPercentages1[tch] = tmd->weightPercentage;
02116                                    }
02117                             else if(teachersMaxHoursContinuouslyMaxHours1[tch] <= tmd->maxHoursContinuously &&
02118                              teachersMaxHoursContinuouslyPercentages1[tch] >= tmd->weightPercentage){
02119                                    //nothing
02120                             }
02121                             else{
02122                                    if(teachersMaxHoursContinuouslyMaxHours2[tch]==-1 ||
02123                                     (teachersMaxHoursContinuouslyMaxHours2[tch] >= tmd->maxHoursContinuously &&
02124                                     teachersMaxHoursContinuouslyPercentages2[tch] <= tmd->weightPercentage)){
02125                                           teachersMaxHoursContinuouslyMaxHours2[tch] = tmd->maxHoursContinuously;
02126                                           teachersMaxHoursContinuouslyPercentages2[tch] = tmd->weightPercentage;
02127                                           }
02128                                    else if(teachersMaxHoursContinuouslyMaxHours2[tch] <= tmd->maxHoursContinuously &&
02129                                     teachersMaxHoursContinuouslyPercentages2[tch] >= tmd->weightPercentage){
02130                                    //nothing
02131                                    }
02132                                    else{ //cannot proceed
02133                                           ok=false;
02134 
02135                                           int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
02136                                            GeneratePreTranslate::tr("Cannot optimize for teacher %1, because there are too many constraints"
02137                                            " of type max hours continuously relating to him, which cannot be compressed in 2 constraints of this type."
02138                                            " Two constraints max hours can be compressed into a single one if the max hours are lower"
02139                                            " in the first one and the weight percentage is higher on the first one."
02140                                            " It is possible to use any number of such constraints for a teacher, but their resultant must"
02141                                            " be maximum 2 constraints of type max hours continuously.\n\n"
02142                                            " Example: you are allowed to use 3 constraints: 6 hours 95%, 7 hours 100% and 8 hours 100%,"
02143                                            " which can be compressed into 2 constraints: 6 hours 95%, 7 hours 100%\n\n"
02144                                            " Please modify your data accordingly and try again.")
02145                                            .arg(gt.rules.internalTeachersList[tch]->name),
02146                                            GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
02147                                            1, 0 );
02148 
02149                                           if(t==0)
02150                                                  return false;
02151                                    }
02152                             }
02153                      }
02154               }
02155        }
02156        
02157        for(int ai=0; ai<gt.rules.nInternalActivities; ai++){
02158               foreach(int tch, gt.rules.internalActivitiesList[ai].iTeachersList){
02159                      if(teachersMaxHoursContinuouslyPercentages1[tch]>=0 && gt.rules.internalActivitiesList[ai].duration > teachersMaxHoursContinuouslyMaxHours1[tch]){
02160                             QString s;
02161                             s=GeneratePreTranslate::tr("Cannot optimize for teacher %1, because there is a constraint of type"
02162                              " max %2 hours continuously which cannot be respected because of activity with id %3 (which has duration %4).")
02163                              .arg(gt.rules.internalTeachersList[tch]->name)
02164                              .arg(teachersMaxHoursContinuouslyMaxHours1[tch])
02165                              .arg(gt.rules.internalActivitiesList[ai].id)
02166                              .arg(gt.rules.internalActivitiesList[ai].duration);
02167                             s+="\n\n";
02168                             s+=GeneratePreTranslate::tr("Please modify your data accordingly and try again");
02169        
02170                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"), s,
02171                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
02172                              1, 0 );
02173                                    
02174                             if(t==0)
02175                                    return false;
02176                      }
02177                      if(teachersMaxHoursContinuouslyPercentages2[tch]>=0 && gt.rules.internalActivitiesList[ai].duration > teachersMaxHoursContinuouslyMaxHours2[tch]){
02178                             QString s;
02179                             s=GeneratePreTranslate::tr("Cannot optimize for teacher %1, because there is a constraint of type"
02180                              " max %2 hours continuously which cannot be respected because of activity with id %3 (which has duration %4).")
02181                              .arg(gt.rules.internalTeachersList[tch]->name)
02182                              .arg(teachersMaxHoursContinuouslyMaxHours2[tch])
02183                              .arg(gt.rules.internalActivitiesList[ai].id)
02184                              .arg(gt.rules.internalActivitiesList[ai].duration);
02185                             s+="\n\n";
02186                             s+=GeneratePreTranslate::tr("Please modify your data accordingly and try again");
02187        
02188                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"), s,
02189                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
02190                              1, 0 );
02191                                    
02192                             if(t==0)
02193                                    return false;
02194                      }
02195               }
02196        }
02197        
02198        return ok;
02199 }
02200 
02201 bool computeTeachersActivityTagMaxHoursDaily(QWidget* parent)
02202 {
02203        haveTeachersActivityTagMaxHoursDaily=false;
02204        
02205        bool ok=true;
02206        
02207        for(int i=0; i<gt.rules.nInternalTeachers; i++){
02208               teachersActivityTagMaxHoursDailyMaxHours[i].clear();
02209               teachersActivityTagMaxHoursDailyPercentage[i].clear();
02210               teachersActivityTagMaxHoursDailyActivityTag[i].clear();
02211        }
02212 
02213        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
02214               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TEACHERS_ACTIVITY_TAG_MAX_HOURS_DAILY){
02215                      haveTeachersActivityTagMaxHoursDaily=true;
02216 
02217                      ConstraintTeachersActivityTagMaxHoursDaily* samc=(ConstraintTeachersActivityTagMaxHoursDaily*)gt.rules.internalTimeConstraintsList[i];
02218                      
02219                      foreach(int tc, samc->canonicalTeachersList){
02220                             int pos1=-1, pos2=-1;
02221                             
02222                             for(int j=0; j<teachersActivityTagMaxHoursDailyMaxHours[tc].count(); j++){
02223                                    if(teachersActivityTagMaxHoursDailyActivityTag[tc].at(j)==samc->activityTagIndex){
02224                                           if(pos1==-1){
02225                                                  pos1=j;
02226                                           }
02227                                           else{
02228                                                  assert(pos2==-1);
02229                                                  pos2=j;
02230                                           }
02231                                    }
02232                             }
02233                             
02234                             if(pos1==-1){
02235                                    teachersActivityTagMaxHoursDailyActivityTag[tc].append(samc->activityTagIndex);
02236                                    teachersActivityTagMaxHoursDailyMaxHours[tc].append(samc->maxHoursDaily);
02237                                    teachersActivityTagMaxHoursDailyPercentage[tc].append(samc->weightPercentage);
02238                             }
02239                             else{
02240                                    if(teachersActivityTagMaxHoursDailyMaxHours[tc].at(pos1) <= samc->maxHoursDaily
02241                                     && teachersActivityTagMaxHoursDailyPercentage[tc].at(pos1) >= samc->weightPercentage){
02242                                           //do nothing
02243                                    }
02244                                    else if(teachersActivityTagMaxHoursDailyMaxHours[tc].at(pos1) >= samc->maxHoursDaily
02245                                     && teachersActivityTagMaxHoursDailyPercentage[tc].at(pos1) <= samc->weightPercentage){
02246                                    
02247                                           teachersActivityTagMaxHoursDailyActivityTag[tc][pos1]=samc->activityTagIndex;
02248                                           teachersActivityTagMaxHoursDailyMaxHours[tc][pos1]=samc->maxHoursDaily;
02249                                           teachersActivityTagMaxHoursDailyPercentage[tc][pos1]=samc->weightPercentage;
02250                                    }
02251                                    else{
02252                                           if(pos2==-1){
02253                                                  teachersActivityTagMaxHoursDailyActivityTag[tc].append(samc->activityTagIndex);
02254                                                  teachersActivityTagMaxHoursDailyMaxHours[tc].append(samc->maxHoursDaily);
02255                                                  teachersActivityTagMaxHoursDailyPercentage[tc].append(samc->weightPercentage);
02256                                           }
02257                                           else{
02258 
02259                                                  if(teachersActivityTagMaxHoursDailyMaxHours[tc].at(pos2) <= samc->maxHoursDaily
02260                                                   && teachersActivityTagMaxHoursDailyPercentage[tc].at(pos2) >= samc->weightPercentage){
02261                                                         //do nothing
02262                                                  }
02263                                                  else if(teachersActivityTagMaxHoursDailyMaxHours[tc].at(pos2) >= samc->maxHoursDaily
02264                                                   && teachersActivityTagMaxHoursDailyPercentage[tc].at(pos2) <= samc->weightPercentage){
02265                                                  
02266                                                         teachersActivityTagMaxHoursDailyActivityTag[tc][pos2]=samc->activityTagIndex;
02267                                                         teachersActivityTagMaxHoursDailyMaxHours[tc][pos2]=samc->maxHoursDaily;
02268                                                         teachersActivityTagMaxHoursDailyPercentage[tc][pos2]=samc->weightPercentage;
02269                                                  }
02270                                                  else{
02271                                                         ok=false;
02272        
02273                                                         int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
02274                                                          GeneratePreTranslate::tr("Cannot optimize for teacher %1, because there are too many constraints"
02275                                                          " of type activity tag max hours daily relating to him, which cannot be compressed in 2 constraints of this type."
02276                                                          " Two constraints max hours can be compressed into a single one if the max hours are lower"
02277                                                          " in the first one and the weight percentage is higher on the first one."
02278                                                          " It is possible to use any number of such constraints for a teacher, but their resultant must"
02279                                                          " be maximum 2 constraints of type activity tag max hours daily.\n\n"
02280                                                          " Example: you are allowed to use 3 constraints: 6 hours 95%, 7 hours 100% and 8 hours 100%,"
02281                                                          " which can be compressed into 2 constraints: 6 hours 95%, 7 hours 100%\n\n"
02282                                                          " Please modify your data accordingly and try again.")
02283                                                          .arg(gt.rules.internalTeachersList[tc]->name),
02284                                                          GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
02285                                                          1, 0 );
02286 
02287                                                         if(t==0)
02288                                                                return false;
02289                                                  }
02290                                           }
02291                                    }
02292                             }
02293                      }
02294               }
02295               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TEACHER_ACTIVITY_TAG_MAX_HOURS_DAILY){
02296                      haveTeachersActivityTagMaxHoursDaily=true;
02297 
02298                      ConstraintTeacherActivityTagMaxHoursDaily* samc=(ConstraintTeacherActivityTagMaxHoursDaily*)gt.rules.internalTimeConstraintsList[i];
02299                      
02300                      foreach(int tc, samc->canonicalTeachersList){
02301                             int pos1=-1, pos2=-1;
02302                             
02303                             for(int j=0; j<teachersActivityTagMaxHoursDailyMaxHours[tc].count(); j++){
02304                                    if(teachersActivityTagMaxHoursDailyActivityTag[tc].at(j)==samc->activityTagIndex){
02305                                           if(pos1==-1){
02306                                                  pos1=j;
02307                                           }
02308                                           else{
02309                                                  assert(pos2==-1);
02310                                                  pos2=j;
02311                                           }
02312                                    }
02313                             }
02314                             
02315                             if(pos1==-1){
02316                                    teachersActivityTagMaxHoursDailyActivityTag[tc].append(samc->activityTagIndex);
02317                                    teachersActivityTagMaxHoursDailyMaxHours[tc].append(samc->maxHoursDaily);
02318                                    teachersActivityTagMaxHoursDailyPercentage[tc].append(samc->weightPercentage);
02319                             }
02320                             else{
02321                                    if(teachersActivityTagMaxHoursDailyMaxHours[tc].at(pos1) <= samc->maxHoursDaily
02322                                     && teachersActivityTagMaxHoursDailyPercentage[tc].at(pos1) >= samc->weightPercentage){
02323                                           //do nothing
02324                                    }
02325                                    else if(teachersActivityTagMaxHoursDailyMaxHours[tc].at(pos1) >= samc->maxHoursDaily
02326                                     && teachersActivityTagMaxHoursDailyPercentage[tc].at(pos1) <= samc->weightPercentage){
02327                                    
02328                                           teachersActivityTagMaxHoursDailyActivityTag[tc][pos1]=samc->activityTagIndex;
02329                                           teachersActivityTagMaxHoursDailyMaxHours[tc][pos1]=samc->maxHoursDaily;
02330                                           teachersActivityTagMaxHoursDailyPercentage[tc][pos1]=samc->weightPercentage;
02331                                    }
02332                                    else{
02333                                           if(pos2==-1){
02334                                                  teachersActivityTagMaxHoursDailyActivityTag[tc].append(samc->activityTagIndex);
02335                                                  teachersActivityTagMaxHoursDailyMaxHours[tc].append(samc->maxHoursDaily);
02336                                                  teachersActivityTagMaxHoursDailyPercentage[tc].append(samc->weightPercentage);
02337                                           }
02338                                           else{
02339 
02340                                                  if(teachersActivityTagMaxHoursDailyMaxHours[tc].at(pos2) <= samc->maxHoursDaily
02341                                                   && teachersActivityTagMaxHoursDailyPercentage[tc].at(pos2) >= samc->weightPercentage){
02342                                                         //do nothing
02343                                                  }
02344                                                  else if(teachersActivityTagMaxHoursDailyMaxHours[tc].at(pos2) >= samc->maxHoursDaily
02345                                                   && teachersActivityTagMaxHoursDailyPercentage[tc].at(pos2) <= samc->weightPercentage){
02346                                                  
02347                                                         teachersActivityTagMaxHoursDailyActivityTag[tc][pos2]=samc->activityTagIndex;
02348                                                         teachersActivityTagMaxHoursDailyMaxHours[tc][pos2]=samc->maxHoursDaily;
02349                                                         teachersActivityTagMaxHoursDailyPercentage[tc][pos2]=samc->weightPercentage;
02350                                                  }
02351                                                  else{
02352                                                         ok=false;
02353        
02354                                                         int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
02355                                                          GeneratePreTranslate::tr("Cannot optimize for teacher %1, because there are too many constraints"
02356                                                          " of type activity tag max hours daily relating to him, which cannot be compressed in 2 constraints of this type."
02357                                                          " Two constraints max hours can be compressed into a single one if the max hours are lower"
02358                                                          " in the first one and the weight percentage is higher on the first one."
02359                                                          " It is possible to use any number of such constraints for a teacher, but their resultant must"
02360                                                          " be maximum 2 constraints of type activity tag max hours daily.\n\n"
02361                                                          " Example: you are allowed to use 3 constraints: 6 hours 95%, 7 hours 100% and 8 hours 100%,"
02362                                                          " which can be compressed into 2 constraints: 6 hours 95%, 7 hours 100%\n\n"
02363                                                          " Please modify your data accordingly and try again.")
02364                                                          .arg(gt.rules.internalTeachersList[tc]->name),
02365                                                          GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
02366                                                          1, 0 );
02367 
02368                                                         if(t==0)
02369                                                                return false;
02370                                                  }
02371                                           }
02372                                    }
02373                             }
02374                      }
02375               }
02376        }
02377 
02378        int navd[MAX_DAYS_PER_WEEK];
02379        
02380        for(int i=0; i<gt.rules.nInternalTeachers; i++){
02381               for(int d=0; d<gt.rules.nDaysPerWeek; d++){
02382                      navd[d]=0;
02383                      for(int h=0; h<gt.rules.nHoursPerDay; h++){
02384                             if(!breakDayHour[d][h] && !teacherNotAvailableDayHour[i][d][h])
02385                                    navd[d]++;
02386                      }
02387               }
02388        
02389               for(int j=0; j<teachersActivityTagMaxHoursDailyMaxHours[i].count(); j++){
02390                      int mh=teachersActivityTagMaxHoursDailyMaxHours[i].at(j);
02391                      double perc=teachersActivityTagMaxHoursDailyPercentage[i].at(j);
02392                      int at=teachersActivityTagMaxHoursDailyActivityTag[i].at(j);
02393                      if(perc==100.0){
02394                             int totalAt=0;
02395                             foreach(int ai, gt.rules.internalTeachersList[i]->activitiesForTeacher)
02396                                    if(gt.rules.internalActivitiesList[ai].iActivityTagsSet.contains(at))
02397                                           totalAt+=gt.rules.internalActivitiesList[ai].duration;
02398                                           
02399                             int ava=0;
02400                             for(int d=0; d<gt.rules.nDaysPerWeek; d++)
02401                                    ava+=min(navd[d], mh);
02402                                    
02403                             if(ava<totalAt){
02404                                    ok=false;
02405                                    
02406                                    int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
02407                                     GeneratePreTranslate::tr("Cannot optimize for teacher %1, because there is a constraint activity tag %2 max %3 hours daily for it with weight 100\%"
02408                                     " which cannot be satisfied, considering the number of available slots (%4) and total duration of activities with this activity tag (%5)"
02409                                     ". Please correct and try again.", "%2 is the activity tag for this constraint, %3 is the max number of hours daily for this constraint")
02410                                     .arg(gt.rules.internalTeachersList[i]->name).arg(gt.rules.activityTagsList.at(at)->name).arg(mh).arg(ava).arg(totalAt),
02411                                     GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
02412                                     1, 0 );
02413 
02414                                    if(t==0)
02415                                           return false;
02416                             }
02417                      }
02418               }
02419        }
02420        
02421        return ok;
02422 }
02423 
02424 bool computeTeachersActivityTagMaxHoursContinuously(QWidget* parent)
02425 {
02426        haveTeachersActivityTagMaxHoursContinuously=false;
02427        
02428        bool ok=true;
02429        
02430        for(int i=0; i<gt.rules.nInternalTeachers; i++){
02431               teachersActivityTagMaxHoursContinuouslyMaxHours[i].clear();
02432               teachersActivityTagMaxHoursContinuouslyPercentage[i].clear();
02433               teachersActivityTagMaxHoursContinuouslyActivityTag[i].clear();
02434        }
02435 
02436        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
02437               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TEACHERS_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
02438                      haveTeachersActivityTagMaxHoursContinuously=true;
02439 
02440                      ConstraintTeachersActivityTagMaxHoursContinuously* samc=(ConstraintTeachersActivityTagMaxHoursContinuously*)gt.rules.internalTimeConstraintsList[i];
02441                      
02442                      foreach(int tc, samc->canonicalTeachersList){
02443                             int pos1=-1, pos2=-1;
02444                             
02445                             for(int j=0; j<teachersActivityTagMaxHoursContinuouslyMaxHours[tc].count(); j++){
02446                                    if(teachersActivityTagMaxHoursContinuouslyActivityTag[tc].at(j)==samc->activityTagIndex){
02447                                           if(pos1==-1){
02448                                                  pos1=j;
02449                                           }
02450                                           else{
02451                                                  assert(pos2==-1);
02452                                                  pos2=j;
02453                                           }
02454                                    }
02455                             }
02456                             
02457                             if(pos1==-1){
02458                                    teachersActivityTagMaxHoursContinuouslyActivityTag[tc].append(samc->activityTagIndex);
02459                                    teachersActivityTagMaxHoursContinuouslyMaxHours[tc].append(samc->maxHoursContinuously);
02460                                    teachersActivityTagMaxHoursContinuouslyPercentage[tc].append(samc->weightPercentage);
02461                             }
02462                             else{
02463                                    if(teachersActivityTagMaxHoursContinuouslyMaxHours[tc].at(pos1) <= samc->maxHoursContinuously
02464                                     && teachersActivityTagMaxHoursContinuouslyPercentage[tc].at(pos1) >= samc->weightPercentage){
02465                                           //do nothing
02466                                    }
02467                                    else if(teachersActivityTagMaxHoursContinuouslyMaxHours[tc].at(pos1) >= samc->maxHoursContinuously
02468                                     && teachersActivityTagMaxHoursContinuouslyPercentage[tc].at(pos1) <= samc->weightPercentage){
02469                                    
02470                                           teachersActivityTagMaxHoursContinuouslyActivityTag[tc][pos1]=samc->activityTagIndex;
02471                                           teachersActivityTagMaxHoursContinuouslyMaxHours[tc][pos1]=samc->maxHoursContinuously;
02472                                           teachersActivityTagMaxHoursContinuouslyPercentage[tc][pos1]=samc->weightPercentage;
02473                                    }
02474                                    else{
02475                                           if(pos2==-1){
02476                                                  teachersActivityTagMaxHoursContinuouslyActivityTag[tc].append(samc->activityTagIndex);
02477                                                  teachersActivityTagMaxHoursContinuouslyMaxHours[tc].append(samc->maxHoursContinuously);
02478                                                  teachersActivityTagMaxHoursContinuouslyPercentage[tc].append(samc->weightPercentage);
02479                                           }
02480                                           else{
02481 
02482                                                  if(teachersActivityTagMaxHoursContinuouslyMaxHours[tc].at(pos2) <= samc->maxHoursContinuously
02483                                                   && teachersActivityTagMaxHoursContinuouslyPercentage[tc].at(pos2) >= samc->weightPercentage){
02484                                                         //do nothing
02485                                                  }
02486                                                  else if(teachersActivityTagMaxHoursContinuouslyMaxHours[tc].at(pos2) >= samc->maxHoursContinuously
02487                                                   && teachersActivityTagMaxHoursContinuouslyPercentage[tc].at(pos2) <= samc->weightPercentage){
02488                                                  
02489                                                         teachersActivityTagMaxHoursContinuouslyActivityTag[tc][pos2]=samc->activityTagIndex;
02490                                                         teachersActivityTagMaxHoursContinuouslyMaxHours[tc][pos2]=samc->maxHoursContinuously;
02491                                                         teachersActivityTagMaxHoursContinuouslyPercentage[tc][pos2]=samc->weightPercentage;
02492                                                  }
02493                                                  else{
02494                                                         ok=false;
02495        
02496                                                         int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
02497                                                          GeneratePreTranslate::tr("Cannot optimize for teacher %1, because there are too many constraints"
02498                                                          " of type activity tag max hours continuously relating to him, which cannot be compressed in 2 constraints of this type."
02499                                                          " Two constraints max hours can be compressed into a single one if the max hours are lower"
02500                                                          " in the first one and the weight percentage is higher on the first one."
02501                                                          " It is possible to use any number of such constraints for a teacher, but their resultant must"
02502                                                          " be maximum 2 constraints of type activity tag max hours continuously.\n\n"
02503                                                          " Example: you are allowed to use 3 constraints: 6 hours 95%, 7 hours 100% and 8 hours 100%,"
02504                                                          " which can be compressed into 2 constraints: 6 hours 95%, 7 hours 100%\n\n"
02505                                                          " Please modify your data accordingly and try again.")
02506                                                          .arg(gt.rules.internalTeachersList[tc]->name),
02507                                                          GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
02508                                                          1, 0 );
02509 
02510                                                         if(t==0)
02511                                                                return false;
02512                                                  }
02513                                           }
02514                                    }
02515                             }
02516                      }
02517               }
02518               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TEACHER_ACTIVITY_TAG_MAX_HOURS_CONTINUOUSLY){
02519                      haveTeachersActivityTagMaxHoursContinuously=true;
02520 
02521                      ConstraintTeacherActivityTagMaxHoursContinuously* samc=(ConstraintTeacherActivityTagMaxHoursContinuously*)gt.rules.internalTimeConstraintsList[i];
02522                      
02523                      foreach(int tc, samc->canonicalTeachersList){
02524                             int pos1=-1, pos2=-1;
02525                             
02526                             for(int j=0; j<teachersActivityTagMaxHoursContinuouslyMaxHours[tc].count(); j++){
02527                                    if(teachersActivityTagMaxHoursContinuouslyActivityTag[tc].at(j)==samc->activityTagIndex){
02528                                           if(pos1==-1){
02529                                                  pos1=j;
02530                                           }
02531                                           else{
02532                                                  assert(pos2==-1);
02533                                                  pos2=j;
02534                                           }
02535                                    }
02536                             }
02537                             
02538                             if(pos1==-1){
02539                                    teachersActivityTagMaxHoursContinuouslyActivityTag[tc].append(samc->activityTagIndex);
02540                                    teachersActivityTagMaxHoursContinuouslyMaxHours[tc].append(samc->maxHoursContinuously);
02541                                    teachersActivityTagMaxHoursContinuouslyPercentage[tc].append(samc->weightPercentage);
02542                             }
02543                             else{
02544                                    if(teachersActivityTagMaxHoursContinuouslyMaxHours[tc].at(pos1) <= samc->maxHoursContinuously
02545                                     && teachersActivityTagMaxHoursContinuouslyPercentage[tc].at(pos1) >= samc->weightPercentage){
02546                                           //do nothing
02547                                    }
02548                                    else if(teachersActivityTagMaxHoursContinuouslyMaxHours[tc].at(pos1) >= samc->maxHoursContinuously
02549                                     && teachersActivityTagMaxHoursContinuouslyPercentage[tc].at(pos1) <= samc->weightPercentage){
02550                                    
02551                                           teachersActivityTagMaxHoursContinuouslyActivityTag[tc][pos1]=samc->activityTagIndex;
02552                                           teachersActivityTagMaxHoursContinuouslyMaxHours[tc][pos1]=samc->maxHoursContinuously;
02553                                           teachersActivityTagMaxHoursContinuouslyPercentage[tc][pos1]=samc->weightPercentage;
02554                                    }
02555                                    else{
02556                                           if(pos2==-1){
02557                                                  teachersActivityTagMaxHoursContinuouslyActivityTag[tc].append(samc->activityTagIndex);
02558                                                  teachersActivityTagMaxHoursContinuouslyMaxHours[tc].append(samc->maxHoursContinuously);
02559                                                  teachersActivityTagMaxHoursContinuouslyPercentage[tc].append(samc->weightPercentage);
02560                                           }
02561                                           else{
02562 
02563                                                  if(teachersActivityTagMaxHoursContinuouslyMaxHours[tc].at(pos2) <= samc->maxHoursContinuously
02564                                                   && teachersActivityTagMaxHoursContinuouslyPercentage[tc].at(pos2) >= samc->weightPercentage){
02565                                                         //do nothing
02566                                                  }
02567                                                  else if(teachersActivityTagMaxHoursContinuouslyMaxHours[tc].at(pos2) >= samc->maxHoursContinuously
02568                                                   && teachersActivityTagMaxHoursContinuouslyPercentage[tc].at(pos2) <= samc->weightPercentage){
02569                                                  
02570                                                         teachersActivityTagMaxHoursContinuouslyActivityTag[tc][pos2]=samc->activityTagIndex;
02571                                                         teachersActivityTagMaxHoursContinuouslyMaxHours[tc][pos2]=samc->maxHoursContinuously;
02572                                                         teachersActivityTagMaxHoursContinuouslyPercentage[tc][pos2]=samc->weightPercentage;
02573                                                  }
02574                                                  else{
02575                                                         ok=false;
02576        
02577                                                         int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
02578                                                          GeneratePreTranslate::tr("Cannot optimize for teacher %1, because there are too many constraints"
02579                                                          " of type activity tag max hours continuously relating to him, which cannot be compressed in 2 constraints of this type."
02580                                                          " Two constraints max hours can be compressed into a single one if the max hours are lower"
02581                                                          " in the first one and the weight percentage is higher on the first one."
02582                                                          " It is possible to use any number of such constraints for a teacher, but their resultant must"
02583                                                          " be maximum 2 constraints of type activity tag max hours continuously.\n\n"
02584                                                          " Example: you are allowed to use 3 constraints: 6 hours 95%, 7 hours 100% and 8 hours 100%,"
02585                                                          " which can be compressed into 2 constraints: 6 hours 95%, 7 hours 100%\n\n"
02586                                                          " Please modify your data accordingly and try again.")
02587                                                          .arg(gt.rules.internalTeachersList[tc]->name),
02588                                                          GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
02589                                                          1, 0 );
02590 
02591                                                         if(t==0)
02592                                                                return false;
02593                                                  }
02594                                           }
02595                                    }
02596                             }
02597                      }
02598               }
02599        }
02600        
02601        return ok;
02602 }
02603 
02604 //must be after n hours per teacher
02605 bool computeTeachersMinHoursDaily(QWidget* parent)
02606 {
02607        bool ok=true;
02608        
02609        for(int i=0; i<gt.rules.nInternalTeachers; i++){
02610               teachersMinHoursDailyMinHours[i]=-1;
02611               teachersMinHoursDailyPercentages[i]=-1;
02612        }
02613        
02614        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
02615               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TEACHER_MIN_HOURS_DAILY){
02616                      ConstraintTeacherMinHoursDaily* tmd=(ConstraintTeacherMinHoursDaily*)gt.rules.internalTimeConstraintsList[i];
02617 
02619                      if(tmd->weightPercentage!=100){
02620                             ok=false;
02621 
02622                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
02623                              GeneratePreTranslate::tr("Cannot optimize, because you have constraint teacher min hours daily for teacher %1 with"
02624                              " weight (percentage) below 100. Starting with FET version 5.4.0 it is only possible"
02625                              " to use 100% weight for such constraints. Please make weight 100% and try again")
02626                              .arg(tmd->teacherName),
02627                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
02628                              1, 0 );
02629                             
02630                             if(t==0)
02631                                    return false;
02632                      }
02634 
02636                      if(tmd->minHoursDaily>gt.rules.nHoursPerDay){
02637                             ok=false;
02638 
02639                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
02640                              GeneratePreTranslate::tr("Cannot optimize, because you have constraint teacher min hours daily for teacher %1 with"
02641                              " %2 min hours daily, and the number of working hours per day is only %3. Please correct and try again")
02642                              .arg(tmd->teacherName)
02643                              .arg(tmd->minHoursDaily)
02644                              .arg(gt.rules.nHoursPerDay),
02645                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
02646                              1, 0 );
02647                             
02648                             if(t==0)
02649                                    return false;
02650                      }
02652 
02653                      if(teachersMinHoursDailyMinHours[tmd->teacher_ID]==-1 || teachersMinHoursDailyMinHours[tmd->teacher_ID]<tmd->minHoursDaily){
02654                             teachersMinHoursDailyMinHours[tmd->teacher_ID]=tmd->minHoursDaily;
02655                             teachersMinHoursDailyPercentages[tmd->teacher_ID]=100;
02656                      }
02657               }
02658               else if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TEACHERS_MIN_HOURS_DAILY){
02659                      ConstraintTeachersMinHoursDaily* tmd=(ConstraintTeachersMinHoursDaily*)gt.rules.internalTimeConstraintsList[i];
02660 
02662                      if(tmd->weightPercentage!=100){
02663                             ok=false;
02664 
02665                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
02666                              GeneratePreTranslate::tr("Cannot optimize, because you have constraint teachers min hours daily with"
02667                              " weight (percentage) below 100. Starting with FET version 5.4.0 it is only possible"
02668                              " to use 100% weight for such constraints. Please make weight 100% and try again"),
02669                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
02670                              1, 0 );
02671                             
02672                             if(t==0)
02673                                    return false;
02674                      }
02676 
02678                      if(tmd->minHoursDaily>gt.rules.nHoursPerDay){
02679                             ok=false;
02680 
02681                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
02682                              GeneratePreTranslate::tr("Cannot optimize, because you have constraint teachers min hours daily with"
02683                              " %1 min hours daily, and the number of working hours per day is only %2. Please correct and try again")
02684                              .arg(tmd->minHoursDaily)
02685                              .arg(gt.rules.nHoursPerDay),
02686                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
02687                              1, 0 );
02688                             
02689                             if(t==0)
02690                                    return false;
02691                      }
02693                      for(int tch=0; tch<gt.rules.nInternalTeachers; tch++){
02694                             if(teachersMinHoursDailyMinHours[tch]==-1 || teachersMinHoursDailyMinHours[tch]<tmd->minHoursDaily)
02695                                    teachersMinHoursDailyMinHours[tch]=tmd->minHoursDaily;
02696                                    teachersMinHoursDailyPercentages[tch]=100;
02697                      }
02698               }
02699        }
02700        
02701        for(int tc=0; tc<gt.rules.nInternalTeachers; tc++){
02702               if(teachersMinHoursDailyPercentages[tc]==100){
02703                      assert(teachersMinHoursDailyMinHours[tc]>=0);
02704                      if(nHoursPerTeacher[tc]>0 && teachersMinHoursDailyMinHours[tc]>nHoursPerTeacher[tc]){
02705                             ok=false;
02706 
02707                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
02708                              GeneratePreTranslate::tr("Cannot optimize, because you have constraint teacher min %1 hours daily for teacher"
02709                              " %2 (the constraint allows empty days). This teacher has in total only %3 hours per week, so impossible constraint."
02710                              " Please correct and try again")
02711                              .arg(teachersMinHoursDailyMinHours[tc])
02712                              .arg(gt.rules.internalTeachersList[tc]->name)
02713                              .arg(nHoursPerTeacher[tc])
02714                              ,
02715                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
02716                              1, 0 );
02717                             
02718                             if(t==0)
02719                                    return false;
02720                      }
02721 
02722                      if(teachersMinHoursDailyMinHours[tc]<2){
02723                             ok=false;
02724 
02725                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
02726                              GeneratePreTranslate::tr("Cannot optimize, because you have constraint teacher min %1 hours daily for teacher"
02727                              " %2 (the constraint allows empty days). The number of min hours daily should be at least 2, to make a non-trivial constraint. Please correct and try again")
02728                              .arg(teachersMinHoursDailyMinHours[tc])
02729                              .arg(gt.rules.internalTeachersList[tc]->name)
02730                              ,
02731                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
02732                              1, 0 );
02733                             
02734                             if(t==0)
02735                                    return false;
02736                      }
02737               }
02738        }
02739 
02740        return ok;
02741 }
02742 
02743 //must be after min hours for teachers
02744 bool computeTeachersMinDaysPerWeek(QWidget* parent)
02745 {
02746        bool ok=true;
02747        
02748        for(int i=0; i<gt.rules.nInternalTeachers; i++){
02749               teachersMinDaysPerWeekMinDays[i]=-1;
02750               teachersMinDaysPerWeekPercentages[i]=-1;
02751        }
02752        
02753        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
02754               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TEACHER_MIN_DAYS_PER_WEEK){
02755                      ConstraintTeacherMinDaysPerWeek* tmd=(ConstraintTeacherMinDaysPerWeek*)gt.rules.internalTimeConstraintsList[i];
02756 
02758                      if(tmd->weightPercentage!=100){
02759                             ok=false;
02760 
02761                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
02762                              GeneratePreTranslate::tr("Cannot optimize, because you have constraint teacher min days per week for teacher %1 with"
02763                              " weight (percentage) below 100. Please make weight 100% and try again")
02764                              .arg(tmd->teacherName),
02765                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
02766                              1, 0 );
02767                             
02768                             if(t==0)
02769                                    return false;
02770                      }
02772 
02774                      if(tmd->minDaysPerWeek>gt.rules.nDaysPerWeek){
02775                             ok=false;
02776 
02777                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
02778                              GeneratePreTranslate::tr("Cannot optimize, because you have constraint teacher min days per week for teacher %1 with"
02779                              " %2 min days per week, and the number of working days per week is only %3. Please correct and try again")
02780                              .arg(tmd->teacherName)
02781                              .arg(tmd->minDaysPerWeek)
02782                              .arg(gt.rules.nDaysPerWeek),
02783                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
02784                              1, 0 );
02785                             
02786                             if(t==0)
02787                                    return false;
02788                      }
02790 
02791                      if(teachersMinDaysPerWeekMinDays[tmd->teacher_ID]==-1 || teachersMinDaysPerWeekMinDays[tmd->teacher_ID]<tmd->minDaysPerWeek){
02792                             teachersMinDaysPerWeekMinDays[tmd->teacher_ID]=tmd->minDaysPerWeek;
02793                             teachersMinDaysPerWeekPercentages[tmd->teacher_ID]=100;
02794                      }
02795               }
02796               else if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TEACHERS_MIN_DAYS_PER_WEEK){
02797                      ConstraintTeachersMinDaysPerWeek* tmd=(ConstraintTeachersMinDaysPerWeek*)gt.rules.internalTimeConstraintsList[i];
02798 
02800                      if(tmd->weightPercentage!=100){
02801                             ok=false;
02802 
02803                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
02804                              GeneratePreTranslate::tr("Cannot optimize, because you have constraint teachers min days per week with weight"
02805                              " (percentage) below 100. Please make weight 100% and try again"),
02806                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
02807                              1, 0 );
02808                             
02809                             if(t==0)
02810                                    return false;
02811                      }
02813 
02815                      if(tmd->minDaysPerWeek>gt.rules.nDaysPerWeek){
02816                             ok=false;
02817 
02818                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
02819                              GeneratePreTranslate::tr("Cannot optimize, because you have constraint teachers min days per week with"
02820                              " %1 min days per week, and the number of working days per week is only %2. Please correct and try again")
02821                              .arg(tmd->minDaysPerWeek)
02822                              .arg(gt.rules.nDaysPerWeek),
02823                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
02824                              1, 0 );
02825                             
02826                             if(t==0)
02827                                    return false;
02828                      }
02830                      for(int tch=0; tch<gt.rules.nInternalTeachers; tch++){
02831                             if(teachersMinDaysPerWeekMinDays[tch]==-1 || teachersMinDaysPerWeekMinDays[tch]<tmd->minDaysPerWeek)
02832                                    teachersMinDaysPerWeekMinDays[tch]=tmd->minDaysPerWeek;
02833                                    teachersMinDaysPerWeekPercentages[tch]=100;
02834                      }
02835               }
02836        }
02837        
02838        for(int tc=0; tc<gt.rules.nInternalTeachers; tc++){
02839               if(teachersMinDaysPerWeekMinDays[tc]>=0){
02840                      int md=teachersMinDaysPerWeekMinDays[tc];
02841                      if(md>gt.rules.internalTeachersList[tc]->activitiesForTeacher.count()){
02842                             ok=false;
02843 
02844                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
02845                              GeneratePreTranslate::tr("Cannot optimize because for teacher %1 you have min days per week %2 and he has only %3 activities - impossible."
02846                              " Please correct and try again.")
02847                              .arg(gt.rules.internalTeachersList[tc]->name)
02848                              .arg(md)
02849                              .arg(gt.rules.internalTeachersList[tc]->activitiesForTeacher.count())
02850                              ,
02851                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
02852                              1, 0 );
02853                             
02854                             if(t==0)
02855                                    return false;
02856                      }
02857                      
02858                      if(teachersMinHoursDailyMinHours[tc]>=0){
02859                             int mh=teachersMinHoursDailyMinHours[tc];
02860                             
02861                             if(md*mh>nHoursPerTeacher[tc]){
02862                                    ok=false;
02863 
02864                                    int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
02865                                     GeneratePreTranslate::tr("Cannot optimize because for teacher %1 you have min days per week %2 and min hours daily %3"
02866                                     " and he has only %4 working hours - impossible. Please correct and try again.")
02867                                     .arg(gt.rules.internalTeachersList[tc]->name)
02868                                     .arg(md)
02869                                     .arg(mh)
02870                                     .arg(nHoursPerTeacher[tc])
02871                                     ,
02872                                     GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
02873                                     1, 0 );
02874                             
02875                                    if(t==0)
02876                                           return false;
02877                             }
02878                      }
02879               }
02880        }
02881 
02882 
02883        for(int tc=0; tc<gt.rules.nInternalTeachers; tc++){
02884               if(teachersMinDaysPerWeekMinDays[tc]>=0){
02885                      if(teachersMaxDaysPerWeekMaxDays[tc]>=0){
02886                             if(teachersMaxDaysPerWeekMaxDays[tc]<teachersMinDaysPerWeekMinDays[tc]){
02887                                    ok=false;
02888 
02889                                    int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
02890                                     GeneratePreTranslate::tr("Cannot optimize because for teacher %1 you have min days per week %2 > max days per week %3"
02891                                     " - impossible (min days must be <= max days). Please correct and try again.")
02892                                     .arg(gt.rules.internalTeachersList[tc]->name)
02893                                     .arg(teachersMinDaysPerWeekMinDays[tc])
02894                                     .arg(teachersMaxDaysPerWeekMaxDays[tc])
02895                                     ,
02896                                     GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
02897                                     1, 0 );
02898                             
02899                                    if(t==0)
02900                                           return false;
02901                             }
02902                      }
02903               
02904                      int med=1; //minimum each day = 1 hour
02905                      if(teachersMinHoursDailyMinHours[tc]>=0)
02906                             med=teachersMinHoursDailyMinHours[tc];
02907                             
02908                      int navdays=0;
02909                      
02910                      for(int d=0; d<gt.rules.nDaysPerWeek; d++){
02911                             int navhours=0;
02912                             for(int h=0; h<gt.rules.nHoursPerDay; h++)
02913                                    if(!breakDayHour[d][h] && !teacherNotAvailableDayHour[tc][d][h])
02914                                           navhours++;
02915                             if(navhours>=med)
02916                                    navdays++;
02917                      }
02918                      
02919                      if(navdays<teachersMinDaysPerWeekMinDays[tc]){
02920                             ok=false;
02921                             
02922                             QString s;
02923                             
02924                             if(teachersMinHoursDailyMinHours[tc]>=0){
02925                                    s=GeneratePreTranslate::tr("Cannot optimize because for teacher %1 you have min days per week %2 and only %3"
02926                                     " available days considering breaks and not available and min hours daily for this teacher. Please correct and try again.")
02927                                     .arg(gt.rules.internalTeachersList[tc]->name)
02928                                     .arg(teachersMinDaysPerWeekMinDays[tc])
02929                                     .arg(navdays);
02930                             }
02931                             else{
02932                                    s=GeneratePreTranslate::tr("Cannot optimize because for teacher %1 you have min days per week %2 and only %3"
02933                                     " available days considering breaks and not available for this teacher. Please correct and try again.")
02934                                     .arg(gt.rules.internalTeachersList[tc]->name)
02935                                     .arg(teachersMinDaysPerWeekMinDays[tc])
02936                                     .arg(navdays);
02937                             }
02938 
02939                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"), s ,
02940                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
02941                              1, 0 );
02942                      
02943                             if(t==0)
02944                                    return false;
02945                      }
02946               }
02947        }
02948 
02949        
02950        return ok;
02951 }
02952 
02953 void computeActivitiesNotOverlapping()
02954 {
02955        for(int i=0; i<gt.rules.nInternalActivities; i++){
02956               activitiesNotOverlappingActivities[i].clear();
02957               activitiesNotOverlappingPercentages[i].clear();
02958        }
02959 
02960        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++)
02961               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_ACTIVITIES_NOT_OVERLAPPING){
02962                      ConstraintActivitiesNotOverlapping* no=(ConstraintActivitiesNotOverlapping*)gt.rules.internalTimeConstraintsList[i];
02963 
02964                      for(int j=0; j<no->_n_activities; j++){
02965                             int ai1=no->_activities[j];
02966                             for(int k=0; k<no->_n_activities; k++){
02967                                    int ai2=no->_activities[k];
02968                                    if(ai1!=ai2){
02969                                           int t=activitiesNotOverlappingActivities[ai1].indexOf(ai2);
02970                                           if(t>=0){
02971                                                  if(activitiesNotOverlappingPercentages[ai1].at(t) < no->weightPercentage){
02972                                                         activitiesNotOverlappingPercentages[ai1][t]=no->weightPercentage;
02973                                                  }
02974                                           }
02975                                           else{
02976                                                  activitiesNotOverlappingPercentages[ai1].append(no->weightPercentage);
02977                                                  activitiesNotOverlappingActivities[ai1].append(ai2);
02978                                           }
02979                                    }
02980                             }
02981                      }
02982               }
02983 }
02984 
02985 bool computeActivitiesSameStartingTime(QWidget* parent, QHash<int, int> & reprSameStartingTime, QHash<int, QSet<int> > & reprSameActivitiesSet)
02986 {
02987        bool reportunder100=true;
02988        bool report100=true;
02989        
02990        bool oktocontinue=true;
02991 
02992        for(int i=0; i<gt.rules.nInternalActivities; i++){
02993               activitiesSameStartingTimeActivities[i].clear();
02994               activitiesSameStartingTimePercentages[i].clear();
02995        }
02996 
02997        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++)
02998               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_ACTIVITIES_SAME_STARTING_TIME){
02999                      ConstraintActivitiesSameStartingTime* sst=(ConstraintActivitiesSameStartingTime*)gt.rules.internalTimeConstraintsList[i];
03000 
03001                      for(int j=0; j<sst->_n_activities; j++){
03002                             int ai1=sst->_activities[j];
03003                             for(int k=j+1; k<sst->_n_activities; k++){
03004                                    int ai2=sst->_activities[k];
03005                                    
03006                                    if(sst->weightPercentage==100.0 && activitiesConflictingPercentage[ai1][ai2]==100)
03007                                           oktocontinue=false;
03008                                    
03009                                    if(sst->weightPercentage<100.0 && reportunder100 && activitiesConflictingPercentage[ai1][ai2]==100){
03010                                           QString s;
03011                                           
03012                                           s+=sst->getDetailedDescription(gt.rules);
03013                                           s+="\n";
03014                                           s+=GeneratePreTranslate::tr("The constraint is impossible to respect, because there are the activities with id-s %1 and %2 which "
03015                                            "conflict one with another, because they have common students sets or teachers or must be not overlapping. FET will allow you to continue, "
03016                                            "because the weight of this constraint is below 100.0%, "
03017                                            "but anyway most probably you have made a mistake in this constraint, "
03018                                            "so it is recommended to modify it.")
03019                                            .arg(gt.rules.internalActivitiesList[ai1].id)
03020                                            .arg(gt.rules.internalActivitiesList[ai2].id);
03021                                    
03022                                           int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
03023                                            s, GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
03024                                            1, 0 );
03025                                    
03026                                           if(t==0)
03027                                                  reportunder100=false;
03028                                    }
03029                                    else if(sst->weightPercentage==100.0 && report100 && activitiesConflictingPercentage[ai1][ai2]==100){
03030                                           QString s;
03031                                           
03032                                           s+=sst->getDetailedDescription(gt.rules);
03033                                           s+="\n";
03034                                           s+=GeneratePreTranslate::tr("The constraint is impossible to respect, because there are the activities with id-s %1 and %2 which "
03035                                            "conflict one with another, because they have common students sets or teachers or must be not overlapping. The weight of this constraint is 100.0%, "
03036                                            "so your timetable is impossible. Please correct this constraint.")
03037                                            .arg(gt.rules.internalActivitiesList[ai1].id)
03038                                            .arg(gt.rules.internalActivitiesList[ai2].id);
03039                                    
03040                                           int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
03041                                            s, GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
03042                                            1, 0 );
03043                                    
03044                                           if(t==0)
03045                                                  report100=false;
03046                                    }
03047                             }
03048                      }
03049                      
03050                      for(int j=0; j<sst->_n_activities; j++){
03051                             int ai1=sst->_activities[j];
03052                             for(int k=0; k<sst->_n_activities; k++){
03053                                    int ai2=sst->_activities[k];
03054                                    if(ai1!=ai2){
03055                                           int t=activitiesSameStartingTimeActivities[ai1].indexOf(ai2);
03056                                           double perc=-1;
03057                                           if(t!=-1){
03058                                                  perc=activitiesSameStartingTimePercentages[ai1].at(t);
03059                                                  assert(perc>=0 && perc<=100);
03060                                           }
03061                                           
03062                                           if(t==-1 /*|| perc<sst->weightPercentage*/){
03063                                                  activitiesSameStartingTimeActivities[ai1].append(ai2);
03064                                                  activitiesSameStartingTimePercentages[ai1].append(sst->weightPercentage);
03065                                                  assert(activitiesSameStartingTimeActivities[ai1].count()==activitiesSameStartingTimePercentages[ai1].count());
03066                                           }
03067                                           else if(t>=0 && perc<sst->weightPercentage){
03068                                                  activitiesSameStartingTimePercentages[ai1][t]=sst->weightPercentage;
03069                                           }
03070                                    }
03071                             }
03072                      }
03073               }
03074               
03075               
03076        //added June 2009, FET-5.10.0
03077        bool reportIndirect=true;
03078        
03079        QMultiHash<int, int> adjMatrix;
03080        
03081        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
03082               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_ACTIVITIES_SAME_STARTING_TIME
03083                &&gt.rules.internalTimeConstraintsList[i]->weightPercentage==100.0){
03084                      ConstraintActivitiesSameStartingTime* sst=(ConstraintActivitiesSameStartingTime*)gt.rules.internalTimeConstraintsList[i];
03085                      
03086                      for(int i=1; i<sst->_n_activities; i++){
03087                             adjMatrix.insert(sst->_activities[0], sst->_activities[i]);
03088                             adjMatrix.insert(sst->_activities[i], sst->_activities[0]);
03089                      }
03090               }
03091        }
03092               
03093        QHash<int, int> repr;
03094        //repr.clear();
03095        
03096        QQueue<int> queue;
03097        
03098        for(int i=0; i<gt.rules.nInternalActivities; i++){
03099               int start=i;
03100               
03101               if(repr.value(start, -1)==-1){ //not visited
03102                      repr.insert(start, start);
03103                      queue.enqueue(start);
03104                      while(!queue.isEmpty()){
03105                             int crtHead=queue.dequeue();
03106                             assert(repr.value(crtHead, -1)==start);
03107                             QList<int> neighList=adjMatrix.values(crtHead);
03108                             foreach(int neigh, neighList){
03109                                    if(repr.value(neigh, -1)==-1){
03110                                           queue.enqueue(neigh);
03111                                           repr.insert(neigh, start);
03112                                    }
03113                                    else{
03114                                           assert(repr.value(neigh, -1)==start);
03115                                    }
03116                             }
03117                      }
03118               }
03119        }
03120 
03121        for(int i=0; i<gt.rules.nInternalActivities; i++)
03122               for(int j=i+1; j<gt.rules.nInternalActivities; j++)
03123                      if(repr.value(i) == repr.value(j)){
03124                             if(activitiesConflictingPercentage[i][j]==100){
03125                                    oktocontinue=false;
03126                                    
03127                                    if(reportIndirect){
03128                                           QString s=GeneratePreTranslate::tr("You have a set of impossible constraints activities same starting time, considering all the indirect links between"
03129                                            " activities same starting time constraints");
03130                                           s+="\n\n";
03131                                           s+=GeneratePreTranslate::tr("The activities with ids %1 and %2 must be simultaneous (request determined indirectly), but they have common teachers and/or students sets or must be not overlapping")
03132                                            .arg(gt.rules.internalActivitiesList[i].id).arg(gt.rules.internalActivitiesList[j].id);
03133                                    
03134                                           int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
03135                                            s, GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
03136                                            1, 0 );
03137                                    
03138                                           if(t==0)
03139                                                  reportIndirect=false;
03140                                    }
03141                             }
03142                      }
03144        
03145        QHash<int, QSet<int> > hashSet;
03146        
03147        for(int i=0; i<gt.rules.nInternalActivities; i++){
03148               assert(repr.contains(i));
03149               int r=repr.value(i);
03150               hashSet[r].insert(i); //faster
03151               /*QSet<int> s;
03152               if(hashSet.contains(r))
03153                      s=hashSet.value(r);
03154               s.insert(i);
03155               hashSet.insert(r, s);*/
03156        }
03157        
03158        reprSameStartingTime=repr;
03159        reprSameActivitiesSet=hashSet;
03160 
03161        return oktocontinue;
03162 }
03163 
03164 void computeActivitiesSameStartingHour()
03165 {
03166        for(int i=0; i<gt.rules.nInternalActivities; i++){
03167               activitiesSameStartingHourActivities[i].clear();
03168               activitiesSameStartingHourPercentages[i].clear();
03169        }
03170 
03171        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++)
03172               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_ACTIVITIES_SAME_STARTING_HOUR){
03173                      ConstraintActivitiesSameStartingHour* sst=(ConstraintActivitiesSameStartingHour*)gt.rules.internalTimeConstraintsList[i];
03174                      
03175                      for(int j=0; j<sst->_n_activities; j++){
03176                             int ai1=sst->_activities[j];
03177                             for(int k=0; k<sst->_n_activities; k++){
03178                                    int ai2=sst->_activities[k];
03179                                    if(ai1!=ai2){
03180                                           int t=activitiesSameStartingHourActivities[ai1].indexOf(ai2);
03181                                           double perc=-1;
03182                                           if(t!=-1){
03183                                                  perc=activitiesSameStartingHourPercentages[ai1].at(t);
03184                                                  assert(perc>=0 && perc<=100);
03185                                           }
03186                                           
03187                                           if(t==-1 /*|| perc<sst->weightPercentage*/){
03188                                                  activitiesSameStartingHourActivities[ai1].append(ai2);
03189                                                  activitiesSameStartingHourPercentages[ai1].append(sst->weightPercentage);
03190                                                  assert(activitiesSameStartingHourActivities[ai1].count()==activitiesSameStartingHourPercentages[ai1].count());
03191                                           }
03192                                           else if(t>=0 && perc<sst->weightPercentage){
03193                                                  activitiesSameStartingHourPercentages[ai1][t]=sst->weightPercentage;
03194                                           }
03195                                    }
03196                             }
03197                      }
03198               }
03199 }
03200 
03201 void computeActivitiesSameStartingDay()
03202 {
03203        for(int i=0; i<gt.rules.nInternalActivities; i++){
03204               activitiesSameStartingDayActivities[i].clear();
03205               activitiesSameStartingDayPercentages[i].clear();
03206        }
03207 
03208        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++)
03209               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_ACTIVITIES_SAME_STARTING_DAY){
03210                      ConstraintActivitiesSameStartingDay* sst=(ConstraintActivitiesSameStartingDay*)gt.rules.internalTimeConstraintsList[i];
03211                      
03212                      for(int j=0; j<sst->_n_activities; j++){
03213                             int ai1=sst->_activities[j];
03214                             for(int k=0; k<sst->_n_activities; k++){
03215                                    int ai2=sst->_activities[k];
03216                                    if(ai1!=ai2){
03217                                           int t=activitiesSameStartingDayActivities[ai1].indexOf(ai2);
03218                                           double perc=-1;
03219                                           if(t!=-1){
03220                                                  perc=activitiesSameStartingDayPercentages[ai1].at(t);
03221                                                  assert(perc>=0 && perc<=100);
03222                                           }
03223                                           
03224                                           if(t==-1 /*|| perc<sst->weightPercentage*/){
03225                                                  activitiesSameStartingDayActivities[ai1].append(ai2);
03226                                                  activitiesSameStartingDayPercentages[ai1].append(sst->weightPercentage);
03227                                                  assert(activitiesSameStartingDayActivities[ai1].count()==activitiesSameStartingDayPercentages[ai1].count());
03228                                           }
03229                                           else if(t>=0 && perc<sst->weightPercentage){
03230                                                  activitiesSameStartingDayPercentages[ai1][t]=sst->weightPercentage;
03231                                           }
03232                                    }
03233                             }
03234                      }
03235               }
03236 }
03237 
03239 //important also for other purposes
03240 bool computeNHoursPerTeacher(QWidget* parent)
03241 {
03242        for(int i=0; i<gt.rules.nInternalTeachers; i++)
03243               nHoursPerTeacher[i]=0;
03244        for(int i=0; i<gt.rules.nInternalActivities; i++){
03245               Activity* act=&gt.rules.internalActivitiesList[i];
03246               for(int j=0; j<act->iTeachersList.count(); j++){
03247                      int tc=act->iTeachersList.at(j);
03248                      nHoursPerTeacher[tc]+=act->duration;
03249               }
03250        }
03251        
03252        bool ok=true;
03253        
03254        for(int i=0; i<gt.rules.nInternalTeachers; i++)
03255               if(nHoursPerTeacher[i]>gt.rules.nHoursPerWeek){
03256                      ok=false;
03257 
03258                      int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
03259                       GeneratePreTranslate::tr("Cannot optimize for teacher %1, because the number of hours for teacher is %2"
03260                        " and you have only %3 days x %4 hours in a week.")
03261                       .arg(gt.rules.internalTeachersList[i]->name)
03262                       .arg(nHoursPerTeacher[i])
03263                       .arg(gt.rules.nDaysPerWeek)
03264                       .arg(gt.rules.nHoursPerDay),
03265                       GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
03266                       1, 0 );
03267                      
03268                      if(t==0)
03269                             return ok;
03270               }
03271        
03272        for(int i=0; i<gt.rules.nInternalTeachers; i++){
03273               int freeSlots=0;
03274               for(int j=0; j<gt.rules.nDaysPerWeek; j++)
03275                      for(int k=0; k<gt.rules.nHoursPerDay; k++)
03276                             if(!teacherNotAvailableDayHour[i][j][k] && !breakDayHour[j][k])
03277                                    freeSlots++;
03278               if(nHoursPerTeacher[i]>freeSlots){
03279                      ok=false;
03280 
03281                      int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
03282                       GeneratePreTranslate::tr("Cannot optimize for teacher %1, because the number of hours for teacher is %2"
03283                        " and you have only %3 free slots from constraints teacher not available and/or break. Maybe you inputted wrong constraints teacher"
03284                        " not available or break or the number of hours per week is less because of a misunderstanding")
03285                       .arg(gt.rules.internalTeachersList[i]->name)
03286                       .arg(nHoursPerTeacher[i])
03287                       .arg(freeSlots),
03288                       GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
03289                       1, 0 );
03290                      
03291                      if(t==0)
03292                             return ok;
03293               }
03294        }
03295        
03296        //n days per week has 100% weight
03297        for(int i=0; i<gt.rules.nInternalTeachers; i++)
03298               if(teachersMaxDaysPerWeekMaxDays[i]>=0){
03299                      int nd=teachersMaxDaysPerWeekMaxDays[i];
03300                      if(nHoursPerTeacher[i] > nd*gt.rules.nHoursPerDay){
03301                             ok=false;
03302 
03303                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
03304                              GeneratePreTranslate::tr("Cannot optimize for teacher %1, because the number of hours for teacher is %2"
03305                               " and you have only %3 allowed days from constraint teacher max days per week x %4 hours in a day."
03306                               " Probably there is an error in your data")
03307                              .arg(gt.rules.internalTeachersList[i]->name)
03308                              .arg(nHoursPerTeacher[i])
03309                              .arg(nd)
03310                              .arg(gt.rules.nHoursPerDay),
03311                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
03312                              1, 0 );
03313                      
03314                             if(t==0)
03315                                    return ok;
03316                      }
03317               }
03318               
03319        //n days per week has 100% weight
03320        //check n days per week together with not available and breaks
03321        for(int tc=0; tc<gt.rules.nInternalTeachers; tc++){
03322               int nAllowedSlotsPerDay[MAX_DAYS_PER_WEEK];
03323               for(int d=0; d<gt.rules.nDaysPerWeek; d++){
03324                      nAllowedSlotsPerDay[d]=0;
03325                      for(int h=0; h<gt.rules.nHoursPerDay; h++)
03326                             if(!breakDayHour[d][h] && !teacherNotAvailableDayHour[tc][d][h])
03327                                    nAllowedSlotsPerDay[d]++;
03328               }
03329 
03330               int dayAvailable[MAX_DAYS_PER_WEEK];
03331               for(int d=0; d<gt.rules.nDaysPerWeek; d++)
03332                      dayAvailable[d]=1;
03333               if(teachersMaxDaysPerWeekMaxDays[tc]>=0){
03334                      for(int d=0; d<gt.rules.nDaysPerWeek; d++)
03335                             dayAvailable[d]=0;
03336               
03337                      assert(teachersMaxDaysPerWeekMaxDays[tc]<=gt.rules.nDaysPerWeek);
03338                      for(int k=0; k<teachersMaxDaysPerWeekMaxDays[tc]; k++){
03339                             int maxPos=-1, maxVal=-1;
03340                             for(int d=0; d<gt.rules.nDaysPerWeek; d++)
03341                                    if(dayAvailable[d]==0)
03342                                           if(maxVal<nAllowedSlotsPerDay[d]){
03343                                                  maxVal=nAllowedSlotsPerDay[d];
03344                                                  maxPos=d;
03345                                           }
03346                             assert(maxPos>=0);
03347                             assert(dayAvailable[maxPos]==0);
03348                             dayAvailable[maxPos]=1;
03349                      }
03350               }
03351                      
03352               int total=0;
03353               for(int d=0; d<gt.rules.nDaysPerWeek; d++)
03354                      if(dayAvailable[d]==1)
03355                             total+=nAllowedSlotsPerDay[d];
03356               if(total<nHoursPerTeacher[tc]){
03357                      ok=false;
03358                             
03359                      QString s;
03360                      s=GeneratePreTranslate::tr("Cannot optimize for teacher %1, because of too constrained"
03361                       " teacher max days per week, teacher not available and/or breaks."
03362                       " The number of total hours for this teacher is"
03363                       " %2 and the number of available slots is, considering max days per week and all other constraints, %3.")
03364                       .arg(gt.rules.internalTeachersList[tc]->name)
03365                       .arg(nHoursPerTeacher[tc])
03366                       .arg(total);
03367                      s+="\n\n";
03368                      s+=GeneratePreTranslate::tr("Please modify your data accordingly and try again");
03369        
03370                      int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"), s,
03371                       GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
03372                       1, 0 );
03373                                    
03374                      if(t==0)
03375                             return false;
03376               }
03377        }
03378        
03379        return ok;
03380 }
03381 
03382 bool computeTeachersMaxGapsPerWeekPercentage(QWidget* parent)
03383 {
03384        for(int j=0; j<gt.rules.nInternalTeachers; j++){
03385               teachersMaxGapsPerWeekMaxGaps[j]=-1;
03386               teachersMaxGapsPerWeekPercentage[j]=-1;
03387        }
03388        
03389        bool ok=true;
03390 
03391        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
03392               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TEACHERS_MAX_GAPS_PER_WEEK){
03393                      ConstraintTeachersMaxGapsPerWeek* tg=(ConstraintTeachersMaxGapsPerWeek*)gt.rules.internalTimeConstraintsList[i];
03394 
03395                      if(tg->weightPercentage!=100){
03396                             ok=false;
03397 
03398                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
03399                              GeneratePreTranslate::tr("Cannot optimize, because you have constraint teachers max gaps per week with"
03400                              " weight (percentage) below 100. Please make weight 100% and try again"),
03401                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
03402                              1, 0 );
03403                             
03404                             if(t==0)
03405                                    return false;
03406                      }
03407               }
03408 
03409               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TEACHER_MAX_GAPS_PER_WEEK){
03410                      ConstraintTeacherMaxGapsPerWeek* tg=(ConstraintTeacherMaxGapsPerWeek*)gt.rules.internalTimeConstraintsList[i];
03411 
03412                      if(tg->weightPercentage!=100){
03413                             ok=false;
03414 
03415                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
03416                              GeneratePreTranslate::tr("Cannot optimize, because you have constraint teacher max gaps per week with"
03417                              " weight (percentage) below 100 for teacher %1. Please make weight 100% and try again")
03418                              .arg(tg->teacherName),
03419                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
03420                              1, 0 );
03421                             
03422                             if(t==0)
03423                                    return false;
03424                      }
03425               }
03426        }
03427        
03428        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
03429               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TEACHERS_MAX_GAPS_PER_WEEK){
03430                      ConstraintTeachersMaxGapsPerWeek* tg=(ConstraintTeachersMaxGapsPerWeek*)gt.rules.internalTimeConstraintsList[i];
03431                      
03432                      for(int j=0; j<gt.rules.nInternalTeachers; j++){
03433                             if(teachersMaxGapsPerWeekMaxGaps[j]==-1 
03434                              ||(teachersMaxGapsPerWeekMaxGaps[j]>=0 && teachersMaxGapsPerWeekMaxGaps[j]>=tg->maxGaps && teachersMaxGapsPerWeekPercentage[j]<=tg->weightPercentage)){
03435                                    teachersMaxGapsPerWeekMaxGaps[j]=tg->maxGaps;
03436                                    teachersMaxGapsPerWeekPercentage[j]=tg->weightPercentage;
03437                             }
03438                             else if(teachersMaxGapsPerWeekMaxGaps[j]>=0 && teachersMaxGapsPerWeekMaxGaps[j]<=tg->maxGaps && teachersMaxGapsPerWeekPercentage[j]>=tg->weightPercentage){
03439                                    //do nothing
03440                             }
03441                             else{
03442                                    ok=false;
03443 
03444                                    int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
03445                                     GeneratePreTranslate::tr("Cannot optimize for teacher %1, because there are two constraints"
03446                                     " of type max gaps per week relating to him, and the weight percentage is higher on the constraint"
03447                                     " with more gaps allowed. You are allowed only to have for each teacher"
03448                                     " the most important constraint with maximum weight percentage and minimum gaps allowed"
03449                                     ". Please modify your data accordingly and try again")
03450                                     .arg(gt.rules.internalTeachersList[j]->name),
03451                                     GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
03452                                     1, 0 );
03453                             
03454                                    if(t==0)
03455                                           return false;
03456                             }
03457                      }
03458               }
03459               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TEACHER_MAX_GAPS_PER_WEEK){
03460                      ConstraintTeacherMaxGapsPerWeek* tg=(ConstraintTeacherMaxGapsPerWeek*)gt.rules.internalTimeConstraintsList[i];
03461               
03462                      int j=tg->teacherIndex;
03463                      if(teachersMaxGapsPerWeekMaxGaps[j]==-1 
03464                       ||(teachersMaxGapsPerWeekMaxGaps[j]>=0 && teachersMaxGapsPerWeekMaxGaps[j]>=tg->maxGaps && teachersMaxGapsPerWeekPercentage[j]<=tg->weightPercentage)){
03465                             teachersMaxGapsPerWeekMaxGaps[j]=tg->maxGaps;
03466                             teachersMaxGapsPerWeekPercentage[j]=tg->weightPercentage;
03467                      }
03468                      else if(teachersMaxGapsPerWeekMaxGaps[j]>=0 && teachersMaxGapsPerWeekMaxGaps[j]<=tg->maxGaps && teachersMaxGapsPerWeekPercentage[j]>=tg->weightPercentage){
03469                             //do nothing
03470                      }
03471                      else{
03472                             ok=false;
03473 
03474                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
03475                              GeneratePreTranslate::tr("Cannot optimize for teacher %1, because there are two constraints"
03476                              " of type max gaps per week relating to him, and the weight percentage is higher on the constraint"
03477                              " with more gaps allowed. You are allowed only to have for each teacher"
03478                              " the most important constraint with maximum weight percentage and minimum gaps allowed"
03479                              ". Please modify your data accordingly and try again")
03480                              .arg(gt.rules.internalTeachersList[j]->name),
03481                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
03482                              1, 0 );
03483                      
03484                             if(t==0)
03485                                    return false;
03486                      }
03487               }
03488        }
03489        
03490        return ok;
03491 }
03492 
03493 bool computeTeachersMaxGapsPerDayPercentage(QWidget* parent)
03494 {
03495        for(int j=0; j<gt.rules.nInternalTeachers; j++){
03496               teachersMaxGapsPerDayMaxGaps[j]=-1;
03497               teachersMaxGapsPerDayPercentage[j]=-1;
03498        }
03499        
03500        bool ok=true;
03501 
03502        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
03503               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TEACHERS_MAX_GAPS_PER_DAY){
03504                      ConstraintTeachersMaxGapsPerDay* tg=(ConstraintTeachersMaxGapsPerDay*)gt.rules.internalTimeConstraintsList[i];
03505 
03506                      if(tg->weightPercentage!=100){
03507                             ok=false;
03508 
03509                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
03510                              GeneratePreTranslate::tr("Cannot optimize, because you have constraint teachers max gaps per day with"
03511                              " weight (percentage) below 100. Please make weight 100% and try again"),
03512                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
03513                              1, 0 );
03514                             
03515                             if(t==0)
03516                                    return false;
03517                      }
03518               }
03519 
03520               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TEACHER_MAX_GAPS_PER_DAY){
03521                      ConstraintTeacherMaxGapsPerDay* tg=(ConstraintTeacherMaxGapsPerDay*)gt.rules.internalTimeConstraintsList[i];
03522 
03523                      if(tg->weightPercentage!=100){
03524                             ok=false;
03525 
03526                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
03527                              GeneratePreTranslate::tr("Cannot optimize, because you have constraint teacher max gaps per day with"
03528                              " weight (percentage) below 100 for teacher %1. Please make weight 100% and try again")
03529                              .arg(tg->teacherName),
03530                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
03531                              1, 0 );
03532                             
03533                             if(t==0)
03534                                    return false;
03535                      }
03536               }
03537        }
03538        
03539        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
03540               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TEACHERS_MAX_GAPS_PER_DAY){
03541                      ConstraintTeachersMaxGapsPerDay* tg=(ConstraintTeachersMaxGapsPerDay*)gt.rules.internalTimeConstraintsList[i];
03542                      
03543                      for(int j=0; j<gt.rules.nInternalTeachers; j++){
03544                             if(teachersMaxGapsPerDayMaxGaps[j]==-1 
03545                              ||(teachersMaxGapsPerDayMaxGaps[j]>=0 && teachersMaxGapsPerDayMaxGaps[j]>=tg->maxGaps && teachersMaxGapsPerDayPercentage[j]<=tg->weightPercentage)){
03546                                    teachersMaxGapsPerDayMaxGaps[j]=tg->maxGaps;
03547                                    teachersMaxGapsPerDayPercentage[j]=tg->weightPercentage;
03548                             }
03549                             else if(teachersMaxGapsPerDayMaxGaps[j]>=0 && teachersMaxGapsPerDayMaxGaps[j]<=tg->maxGaps && teachersMaxGapsPerDayPercentage[j]>=tg->weightPercentage){
03550                                    //do nothing
03551                             }
03552                             else{
03553                                    ok=false;
03554 
03555                                    int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
03556                                     GeneratePreTranslate::tr("Cannot optimize for teacher %1, because there are two constraints"
03557                                     " of type max gaps per day relating to him, and the weight percentage is higher on the constraint"
03558                                     " with more gaps allowed. You are allowed only to have for each teacher"
03559                                     " the most important constraint with maximum weight percentage and minimum gaps allowed"
03560                                     ". Please modify your data accordingly and try again")
03561                                     .arg(gt.rules.internalTeachersList[j]->name),
03562                                     GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
03563                                     1, 0 );
03564                             
03565                                    if(t==0)
03566                                           return false;
03567                             }
03568                      }
03569               }
03570               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TEACHER_MAX_GAPS_PER_DAY){
03571                      ConstraintTeacherMaxGapsPerDay* tg=(ConstraintTeacherMaxGapsPerDay*)gt.rules.internalTimeConstraintsList[i];
03572               
03573                      int j=tg->teacherIndex;
03574                      if(teachersMaxGapsPerDayMaxGaps[j]==-1 
03575                       ||(teachersMaxGapsPerDayMaxGaps[j]>=0 && teachersMaxGapsPerDayMaxGaps[j]>=tg->maxGaps && teachersMaxGapsPerDayPercentage[j]<=tg->weightPercentage)){
03576                             teachersMaxGapsPerDayMaxGaps[j]=tg->maxGaps;
03577                             teachersMaxGapsPerDayPercentage[j]=tg->weightPercentage;
03578                      }
03579                      else if(teachersMaxGapsPerDayMaxGaps[j]>=0 && teachersMaxGapsPerDayMaxGaps[j]<=tg->maxGaps && teachersMaxGapsPerDayPercentage[j]>=tg->weightPercentage){
03580                             //do nothing
03581                      }
03582                      else{
03583                             ok=false;
03584 
03585                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
03586                              GeneratePreTranslate::tr("Cannot optimize for teacher %1, because there are two constraints"
03587                              " of type max gaps per day relating to him, and the weight percentage is higher on the constraint"
03588                              " with more gaps allowed. You are allowed only to have for each teacher"
03589                              " the most important constraint with maximum weight percentage and minimum gaps allowed"
03590                              ". Please modify your data accordingly and try again")
03591                              .arg(gt.rules.internalTeachersList[j]->name),
03592                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
03593                              1, 0 );
03594                      
03595                             if(t==0)
03596                                    return false;
03597                      }
03598               }
03599        }
03600        
03601        return ok;
03602 }
03604 
03605 
03607 //important also for other purposes
03608 bool computeNHoursPerSubgroup(QWidget* parent)
03609 {
03610        for(int i=0; i<gt.rules.nInternalSubgroups; i++)
03611               nHoursPerSubgroup[i]=0;
03612        for(int i=0; i<gt.rules.nInternalActivities; i++){
03613               Activity* act=&gt.rules.internalActivitiesList[i];
03614               for(int j=0; j<act->iSubgroupsList.count(); j++){
03615                      int isg=act->iSubgroupsList.at(j);
03616                      nHoursPerSubgroup[isg]+=act->duration;
03617               }
03618        }
03619        
03620        bool ok=true;
03621        for(int i=0; i<gt.rules.nInternalSubgroups; i++)
03622               if(nHoursPerSubgroup[i]>gt.rules.nHoursPerWeek){
03623                      ok=false;
03624 
03625                      int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
03626                       GeneratePreTranslate::tr("Cannot optimize for subgroup %1, because the number of hours for subgroup is %2"
03627                        " and you have only %3 days x %4 hours in a week.")
03628                       .arg(gt.rules.internalSubgroupsList[i]->name)
03629                       .arg(nHoursPerSubgroup[i])
03630                       .arg(gt.rules.nDaysPerWeek)
03631                       .arg(gt.rules.nHoursPerDay),
03632                       GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
03633                       1, 0 );
03634                      
03635                      if(t==0)
03636                             return ok;
03637               }
03638               
03639        for(int i=0; i<gt.rules.nInternalSubgroups; i++){
03640               int freeSlots=0;
03641               for(int j=0; j<gt.rules.nDaysPerWeek; j++)
03642                      for(int k=0; k<gt.rules.nHoursPerDay; k++)
03643                             if(!subgroupNotAvailableDayHour[i][j][k] && !breakDayHour[j][k])
03644                                    freeSlots++;
03645               if(nHoursPerSubgroup[i]>freeSlots){
03646                      ok=false;
03647 
03648                      int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
03649                       GeneratePreTranslate::tr("Cannot optimize for subgroup %1, because the number of hours for subgroup is %2"
03650                        " and you have only %3 free slots from constraints students set not available and/or break. Maybe you inputted wrong constraints students set"
03651                        " not available or break or the number of hours per week is less because of a misunderstanding")
03652                       .arg(gt.rules.internalSubgroupsList[i]->name)
03653                       .arg(nHoursPerSubgroup[i])
03654                       .arg(freeSlots),
03655                       GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
03656                       1, 0 );
03657                      
03658                      if(t==0)
03659                             return ok;
03660               }
03661        }
03662               
03663        return ok;
03664 }
03665 
03666 
03667 bool computeMaxDaysPerWeekForTeachers(QWidget* parent)
03668 {
03669        for(int j=0; j<gt.rules.nInternalTeachers; j++){
03670               teachersMaxDaysPerWeekMaxDays[j]=-1;
03671               teachersMaxDaysPerWeekWeightPercentages[j]=-1;
03672        }
03673 
03674        bool ok=true;
03675        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
03676               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TEACHER_MAX_DAYS_PER_WEEK){
03677                      ConstraintTeacherMaxDaysPerWeek* tn=(ConstraintTeacherMaxDaysPerWeek*)gt.rules.internalTimeConstraintsList[i];
03678 
03679                      if(tn->weightPercentage!=100){
03680                             ok=false;
03681 
03682                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
03683                              GeneratePreTranslate::tr("Cannot optimize, because you have constraint teacher max days per week with"
03684                              " weight (percentage) below 100 for teacher %1. Starting with FET version 5.2.17 it is only possible"
03685                              " to use 100% weight for such constraints. Please make weight 100% and try again")
03686                              .arg(tn->teacherName),
03687                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
03688                              1, 0 );
03689                             
03690                             if(t==0)
03691                                    return false;
03692                      }
03693 
03694                      if(teachersMaxDaysPerWeekMaxDays[tn->teacher_ID]==-1 ||
03695                       (teachersMaxDaysPerWeekMaxDays[tn->teacher_ID]>=0 && teachersMaxDaysPerWeekMaxDays[tn->teacher_ID] > tn->maxDaysPerWeek)){
03696                             teachersMaxDaysPerWeekMaxDays[tn->teacher_ID]=tn->maxDaysPerWeek;
03697                             teachersMaxDaysPerWeekWeightPercentages[tn->teacher_ID]=tn->weightPercentage;
03698                      }
03699                      /*else{
03700                             ok=false;
03701                             
03702                             int t=QMessageBox::warning(parent, GeneratePreTranslate::tr("FET warning"),
03703                              GeneratePreTranslate::tr("Cannot optimize for teacher %1, because it has at least two constraints max days per week"
03704                              ". Please modify your data correspondingly (leave maximum one constraint of type"
03705                              " constraint teacher max days per week for each teacher) and try again")
03706                              .arg(gt.rules.internalTeachersList[tn->teacher_ID]->name),
03707                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
03708                              1, 0 );
03709                       
03710                             if(t==0)
03711                                    break;
03712                      }*/
03713               }
03714               else if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TEACHERS_MAX_DAYS_PER_WEEK){
03715                      ConstraintTeachersMaxDaysPerWeek* tn=(ConstraintTeachersMaxDaysPerWeek*)gt.rules.internalTimeConstraintsList[i];
03716 
03717                      if(tn->weightPercentage!=100){
03718                             ok=false;
03719 
03720                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
03721                              GeneratePreTranslate::tr("Cannot optimize, because you have constraint teachers max days per week with"
03722                              " weight (percentage) below 100. Please make weight 100% and try again"),
03723                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
03724                              1, 0 );
03725                             
03726                             if(t==0)
03727                                    return false;
03728                      }
03729                      
03730                      for(int t=0; t<gt.rules.nInternalTeachers; t++){
03731                             if(teachersMaxDaysPerWeekMaxDays[t]==-1 ||
03732                              (teachersMaxDaysPerWeekMaxDays[t]>=0 && teachersMaxDaysPerWeekMaxDays[t] > tn->maxDaysPerWeek)){
03733                                    teachersMaxDaysPerWeekMaxDays[t]=tn->maxDaysPerWeek;
03734                                    teachersMaxDaysPerWeekWeightPercentages[t]=tn->weightPercentage;
03735                             }
03736                      }
03737                      /*else{
03738                             ok=false;
03739                             
03740                             int t=QMessageBox::warning(parent, GeneratePreTranslate::tr("FET warning"),
03741                              GeneratePreTranslate::tr("Cannot optimize for teacher %1, because it has at least two constraints max days per week"
03742                              ". Please modify your data correspondingly (leave maximum one constraint of type"
03743                              " constraint teacher max days per week for each teacher) and try again")
03744                              .arg(gt.rules.internalTeachersList[tn->teacher_ID]->name),
03745                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
03746                              1, 0 );
03747                       
03748                             if(t==0)
03749                                    break;
03750                      }*/
03751               }
03752        }
03753        
03754        if(ok){
03755               for(int i=0; i<gt.rules.nInternalActivities; i++){
03756                      teachersWithMaxDaysPerWeekForActivities[i].clear();
03757               
03758                      Activity* act=&gt.rules.internalActivitiesList[i];
03759                      for(int j=0; j<act->iTeachersList.count(); j++){
03760                             int tch=act->iTeachersList.at(j);
03761                             
03762                             if(teachersMaxDaysPerWeekMaxDays[tch]>=0){
03763                                    assert(teachersWithMaxDaysPerWeekForActivities[i].indexOf(tch)==-1);
03764                                    teachersWithMaxDaysPerWeekForActivities[i].append(tch);
03765                             }
03766                      }
03767               }
03768        }
03769        
03770        return ok;
03771 }
03772 
03773 bool computeSubgroupsEarlyAndMaxGapsPercentages(QWidget* parent) //st no gaps & early - part 2
03774 {
03775        for(int i=0; i<gt.rules.nInternalSubgroups; i++){
03776               subgroupsEarlyMaxBeginningsAtSecondHourPercentage[i]=-1;
03777               subgroupsEarlyMaxBeginningsAtSecondHourMaxBeginnings[i]=-1;
03778               subgroupsMaxGapsPerWeekPercentage[i]=-1;
03779               subgroupsMaxGapsPerWeekMaxGaps[i]=-1;
03780        }
03781 
03782        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
03783               //students early
03784               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_STUDENTS_EARLY_MAX_BEGINNINGS_AT_SECOND_HOUR){
03785                      ConstraintStudentsEarlyMaxBeginningsAtSecondHour* se=(ConstraintStudentsEarlyMaxBeginningsAtSecondHour*) gt.rules.internalTimeConstraintsList[i];
03786                      for(int j=0; j<gt.rules.nInternalSubgroups; j++){
03787                             if(subgroupsEarlyMaxBeginningsAtSecondHourPercentage[j] < se->weightPercentage)
03788                                    subgroupsEarlyMaxBeginningsAtSecondHourPercentage[j] = se->weightPercentage;
03789                             if(subgroupsEarlyMaxBeginningsAtSecondHourMaxBeginnings[j]==-1 || subgroupsEarlyMaxBeginningsAtSecondHourMaxBeginnings[j] > se->maxBeginningsAtSecondHour)
03790                                    subgroupsEarlyMaxBeginningsAtSecondHourMaxBeginnings[j] = se->maxBeginningsAtSecondHour;
03791                      }
03792               }
03793 
03794               //students set early
03795               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_STUDENTS_SET_EARLY_MAX_BEGINNINGS_AT_SECOND_HOUR){
03796                      ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour* se=(ConstraintStudentsSetEarlyMaxBeginningsAtSecondHour*) gt.rules.internalTimeConstraintsList[i];
03797                      for(int q=0; q<se->iSubgroupsList.count(); q++){
03798                             int j=se->iSubgroupsList.at(q);
03799                             if(subgroupsEarlyMaxBeginningsAtSecondHourPercentage[j] < se->weightPercentage)
03800                                    subgroupsEarlyMaxBeginningsAtSecondHourPercentage[j] = se->weightPercentage;
03801                             if(subgroupsEarlyMaxBeginningsAtSecondHourMaxBeginnings[j]==-1 || subgroupsEarlyMaxBeginningsAtSecondHourMaxBeginnings[j] > se->maxBeginningsAtSecondHour)
03802                                    subgroupsEarlyMaxBeginningsAtSecondHourMaxBeginnings[j] = se->maxBeginningsAtSecondHour;
03803                      }
03804               }
03805 
03806               //students no gaps
03807               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_STUDENTS_MAX_GAPS_PER_WEEK){
03808                      ConstraintStudentsMaxGapsPerWeek* sg=(ConstraintStudentsMaxGapsPerWeek*) gt.rules.internalTimeConstraintsList[i];
03809                      for(int j=0; j<gt.rules.nInternalSubgroups; j++){ //weight is 100% for all of them
03810                             if(subgroupsMaxGapsPerWeekPercentage[j] < sg->weightPercentage)
03811                                    subgroupsMaxGapsPerWeekPercentage[j] = sg->weightPercentage;
03812                             if(subgroupsMaxGapsPerWeekMaxGaps[j]==-1 || subgroupsMaxGapsPerWeekMaxGaps[j] > sg->maxGaps){
03813                                    subgroupsMaxGapsPerWeekMaxGaps[j] = sg->maxGaps;
03814                             }
03815                      }
03816               }
03817 
03818               //students set no gaps
03819               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_WEEK){
03820                      ConstraintStudentsSetMaxGapsPerWeek* sg=(ConstraintStudentsSetMaxGapsPerWeek*) gt.rules.internalTimeConstraintsList[i];
03821                      for(int j=0; j<sg->iSubgroupsList.count(); j++){
03822                             int s=sg->iSubgroupsList.at(j);
03823                             
03824                             if(subgroupsMaxGapsPerWeekPercentage[s] < sg->weightPercentage)
03825                                    subgroupsMaxGapsPerWeekPercentage[s] = sg->weightPercentage;
03826                             if(subgroupsMaxGapsPerWeekMaxGaps[s]==-1 || subgroupsMaxGapsPerWeekMaxGaps[s] > sg->maxGaps){
03827                                    subgroupsMaxGapsPerWeekMaxGaps[s] = sg->maxGaps;
03828                             }
03829                      }
03830               }
03831        }
03832        
03833        bool ok=true;
03834        for(int i=0; i<gt.rules.nInternalSubgroups; i++){
03835               assert((subgroupsEarlyMaxBeginningsAtSecondHourPercentage[i]==-1 &&
03836                subgroupsEarlyMaxBeginningsAtSecondHourMaxBeginnings[i]==-1) ||
03837                (subgroupsEarlyMaxBeginningsAtSecondHourPercentage[i]>=0 &&
03838                subgroupsEarlyMaxBeginningsAtSecondHourMaxBeginnings[i]>=0));
03839 
03840               assert((subgroupsMaxGapsPerWeekPercentage[i]==-1 &&
03841                subgroupsMaxGapsPerWeekMaxGaps[i]==-1) ||
03842                (subgroupsMaxGapsPerWeekPercentage[i]>=0 &&
03843                subgroupsMaxGapsPerWeekMaxGaps[i]>=0));
03844        
03845               bool oksubgroup=true;
03846               /*if(subgroupsNoGapsPercentage[i]== -1 && subgroupsEarlyMaxBeginningsAtSecondHourPercentage[i]==-1 ||
03847                      subgroupsNoGapsPercentage[i]>=0 && subgroupsEarlyMaxBeginningsAtSecondHourPercentage[i]==-1 ||
03848                      subgroupsNoGapsPercentage[i]>=0 && subgroupsEarlyMaxBeginningsAtSecondHourPercentage[i]>=0
03849                      && subgroupsNoGapsPercentage[i]==subgroupsEarlyMaxBeginningsAtSecondHourPercentage[i])
03850                             oksubgroup=true;
03851               else
03852                      oksubgroup=false;*/
03853                      
03854               if(subgroupsMaxGapsPerWeekPercentage[i]>=0 && subgroupsMaxGapsPerWeekPercentage[i]!=100){
03855                      oksubgroup=false;
03856                      ok=false;
03857 
03858                      int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
03859                       GeneratePreTranslate::tr("Cannot optimize for subgroup %1, because you have a max gaps constraint"
03860                       " with weight percentage less than 100%. Currently, the algorithm can only"
03861                       " optimize with not existing constraint max gaps or existing with 100% weight for it"
03862                       ". Please modify your data correspondingly and try again")
03863                       .arg(gt.rules.internalSubgroupsList[i]->name),
03864                       GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
03865                       1, 0 );
03866                       
03867                      if(t==0)
03868                             break;
03869               }
03870               if(subgroupsEarlyMaxBeginningsAtSecondHourPercentage[i]>=0 && subgroupsEarlyMaxBeginningsAtSecondHourPercentage[i]!=100){
03871                      oksubgroup=false;
03872                      ok=false;
03873 
03874                      int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
03875                       GeneratePreTranslate::tr("Cannot optimize for subgroup %1, because you have an early max beginnings at second hour constraint"
03876                       " with weight percentage less than 100%. Currently, the algorithm can only"
03877                       " optimize with not existing constraint early m.b.a.s.h. or existing with 100% weight for it"
03878                       ". Please modify your data correspondingly and try again")
03879                       .arg(gt.rules.internalSubgroupsList[i]->name),
03880                       GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
03881                       1, 0 );
03882                       
03883                      if(t==0)
03884                             break;
03885               }
03886               /*if(subgroupsNoGapsPercentage[i]== -1 && subgroupsEarlyMaxBeginningsAtSecondHourPercentage[i]>=0){
03887                      oksubgroup=false;
03888                      ok=false;
03889 
03890                      int t=QMessageBox::warning(parent, GeneratePreTranslate::tr("FET warning"),
03891                       GeneratePreTranslate::tr("Cannot optimize for subgroup %1, because a students early max beginnings at second hour constraint"
03892                       " exists for this subgroup, and you have not 'no gaps' requirements for this subgroup. "
03893                       "The algorithm can 1. optimize with 'early' and 'no gaps'"
03894                       " having the same weight percentage or 2. only 'no gaps' optimization"
03895                       " without 'early'. Please modify your data correspondingly and try again")
03896                       .arg(gt.rules.internalSubgroupsList[i]->name),
03897                       GeneratePreTranslate::tr("Skip rest of early - no gaps problems"), GeneratePreTranslate::tr("See next incompatibility no gaps - early"), QString(),
03898                       1, 0 );
03899                       
03900                      if(t==0)
03901                             break;
03902               }
03903               if(subgroupsNoGapsPercentage[i]>=0 && subgroupsEarlyMaxBeginningsAtSecondHourPercentage[i]>=0 
03904                && subgroupsNoGapsPercentage[i]!=subgroupsEarlyMaxBeginningsAtSecondHourPercentage[i]){
03905                      oksubgroup=false;
03906                      ok=false;
03907 
03908                      int t=QMessageBox::warning(parent, GeneratePreTranslate::tr("FET warning"),
03909                       GeneratePreTranslate::tr("Cannot optimize for subgroup %1, because early max beginnings at second hour constraint"
03910                       " has weight percentage %2, and 'no gaps' constraint has weight percentage %3."
03911                       ". The algorithm can:"
03912                       "\n1: Optimize with 'early' and 'no gaps' having the same weight percentage or"
03913                       "\n2. Only 'no gaps' optimization without 'early'."
03914                       "\nPlease modify your data correspondingly and try again")
03915                       .arg(gt.rules.internalSubgroupsList[i]->name)
03916                       .arg(subgroupsEarlyMaxBeginningsAtSecondHourPercentage[i]).
03917                       arg(subgroupsNoGapsPercentage[i]),
03918                       GeneratePreTranslate::tr("Skip rest of early - no gaps problems"), GeneratePreTranslate::tr("See next incompatibility no gaps - early"), QString(),
03919                       1, 0 );
03920                       
03921                      if(t==0)
03922                             break;
03923               }*/
03924 
03925               if(subgroupsEarlyMaxBeginningsAtSecondHourMaxBeginnings[i]>=0 
03926                && subgroupsEarlyMaxBeginningsAtSecondHourMaxBeginnings[i]>gt.rules.nDaysPerWeek){
03927                      oksubgroup=false;
03928                      ok=false;
03929 
03930                      int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
03931                       GeneratePreTranslate::tr("Cannot optimize for subgroup %1, because early max beginnings at second hour constraint"
03932                       " has max beginnings at second hour %2, and the number of days per week is %3 which is less. It must be that the number of"
03933                       " days per week must be greater or equal with the max beginnings at second hour\n"
03934                       "Please modify your data correspondingly and try again")
03935                       .arg(gt.rules.internalSubgroupsList[i]->name)
03936                       .arg(subgroupsEarlyMaxBeginningsAtSecondHourMaxBeginnings[i]).
03937                       arg(gt.rules.nDaysPerWeek),
03938                       GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
03939                       1, 0 );
03940                       
03941                      if(t==0)
03942                             break;
03943               }
03944               
03945               if(!oksubgroup)
03946                      ok=false;
03947        }
03948        
03949        return ok;
03950 }
03951 
03952 bool computeSubgroupsMaxGapsPerDayPercentages(QWidget* parent)
03953 {
03954        haveStudentsMaxGapsPerDay=false;
03955 
03956        for(int i=0; i<gt.rules.nInternalSubgroups; i++){
03957               subgroupsMaxGapsPerDayPercentage[i]=-1;
03958               subgroupsMaxGapsPerDayMaxGaps[i]=-1;
03959        }
03960 
03961        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
03962               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_STUDENTS_MAX_GAPS_PER_DAY){
03963                      haveStudentsMaxGapsPerDay=true;
03964                      ConstraintStudentsMaxGapsPerDay* sg=(ConstraintStudentsMaxGapsPerDay*) gt.rules.internalTimeConstraintsList[i];
03965                      for(int j=0; j<gt.rules.nInternalSubgroups; j++){ //weight is 100% for all of them
03966                             if(subgroupsMaxGapsPerDayPercentage[j] < sg->weightPercentage)
03967                                    subgroupsMaxGapsPerDayPercentage[j] = sg->weightPercentage;
03968                             if(subgroupsMaxGapsPerDayMaxGaps[j]==-1 || subgroupsMaxGapsPerDayMaxGaps[j] > sg->maxGaps){
03969                                    subgroupsMaxGapsPerDayMaxGaps[j] = sg->maxGaps;
03970                             }
03971                      }
03972               }
03973 
03974               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_STUDENTS_SET_MAX_GAPS_PER_DAY){
03975                      haveStudentsMaxGapsPerDay=true;
03976                      ConstraintStudentsSetMaxGapsPerDay* sg=(ConstraintStudentsSetMaxGapsPerDay*) gt.rules.internalTimeConstraintsList[i];
03977                      for(int j=0; j<sg->iSubgroupsList.count(); j++){
03978                             int s=sg->iSubgroupsList.at(j);
03979                             
03980                             if(subgroupsMaxGapsPerDayPercentage[s] < sg->weightPercentage)
03981                                    subgroupsMaxGapsPerDayPercentage[s] = sg->weightPercentage;
03982                             if(subgroupsMaxGapsPerDayMaxGaps[s]==-1 || subgroupsMaxGapsPerDayMaxGaps[s] > sg->maxGaps){
03983                                    subgroupsMaxGapsPerDayMaxGaps[s] = sg->maxGaps;
03984                             }
03985                      }
03986               }
03987        }
03988        
03989        bool ok=true;
03990        for(int i=0; i<gt.rules.nInternalSubgroups; i++){
03991               assert((subgroupsMaxGapsPerDayPercentage[i]==-1 &&
03992                subgroupsMaxGapsPerDayMaxGaps[i]==-1) ||
03993                (subgroupsMaxGapsPerDayPercentage[i]>=0 &&
03994                subgroupsMaxGapsPerDayMaxGaps[i]>=0));
03995        
03996               bool oksubgroup=true;
03997 
03998               if(subgroupsMaxGapsPerDayPercentage[i]>=0 && subgroupsMaxGapsPerDayPercentage[i]!=100){
03999                      oksubgroup=false;
04000                      ok=false;
04001 
04002                      int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
04003                       GeneratePreTranslate::tr("Cannot optimize for subgroup %1, because you have a max gaps constraint"
04004                       " with weight percentage less than 100%. Currently, the algorithm can only"
04005                       " optimize with not existing constraint max gaps or existing with 100% weight for it"
04006                       ". Please modify your data correspondingly and try again")
04007                       .arg(gt.rules.internalSubgroupsList[i]->name),
04008                       GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
04009                       1, 0 );
04010                       
04011                      if(t==0)
04012                             break;
04013               }
04014 
04015               if(!oksubgroup)
04016                      ok=false;
04017        }
04018 
04019        for(int i=0; i<gt.rules.nInternalSubgroups; i++){
04020               if(subgroupsMaxGapsPerDayMaxGaps[i]>=0){
04021                      int mgw=gt.rules.nDaysPerWeek*subgroupsMaxGapsPerDayMaxGaps[i];
04022                      assert(mgw>=0);
04023                      if(subgroupsMaxGapsPerWeekMaxGaps[i]==-1 || (subgroupsMaxGapsPerWeekMaxGaps[i]>=0 && subgroupsMaxGapsPerWeekMaxGaps[i]>mgw)){
04024                             subgroupsMaxGapsPerWeekMaxGaps[i]=mgw;
04025                             subgroupsMaxGapsPerWeekPercentage[i]=100.0;
04026                      }
04027               }
04028        }
04029        
04030        return ok;
04031 }
04032 
04033 bool computeNotAllowedTimesPercentages(QWidget* parent)
04034 {
04035        Matrix1D<bool> allowed;
04036        allowed.resize(gt.rules.nHoursPerWeek);
04037 
04038        bool ok=true;
04039 
04040        assert(gt.rules.internalStructureComputed);
04041 
04042        breakDayHour.resize(gt.rules.nDaysPerWeek, gt.rules.nHoursPerDay);
04043        //BREAK
04044        for(int j=0; j<gt.rules.nDaysPerWeek; j++)
04045               for(int k=0; k<gt.rules.nHoursPerDay; k++)
04046                      breakDayHour[j][k]=false;
04047                      
04048        subgroupNotAvailableDayHour.resize(gt.rules.nInternalSubgroups, gt.rules.nDaysPerWeek, gt.rules.nHoursPerDay);
04049        //STUDENTS SET NOT AVAILABLE
04050        for(int i=0; i<gt.rules.nInternalSubgroups; i++)
04051               for(int j=0; j<gt.rules.nDaysPerWeek; j++)
04052                      for(int k=0; k<gt.rules.nHoursPerDay; k++)
04053                             subgroupNotAvailableDayHour[i][j][k]=false;      
04054        
04055        teacherNotAvailableDayHour.resize(gt.rules.nInternalTeachers, gt.rules.nDaysPerWeek, gt.rules.nHoursPerDay);
04056        //TEACHER NOT AVAILABLE
04057        for(int i=0; i<gt.rules.nInternalTeachers; i++)
04058               for(int j=0; j<gt.rules.nDaysPerWeek; j++)
04059                      for(int k=0; k<gt.rules.nHoursPerDay; k++)
04060                             teacherNotAvailableDayHour[i][j][k]=false;
04061        
04062        notAllowedTimesPercentages.resize(gt.rules.nInternalActivities, gt.rules.nHoursPerWeek);
04063        //improvement by Volker Dirr (late activities):
04064        for(int i=0; i<gt.rules.nInternalActivities; i++){
04065               Activity* act=&gt.rules.internalActivitiesList[i];
04066               for(int j=0; j<gt.rules.nHoursPerWeek; j++){
04067                      int h=j/gt.rules.nDaysPerWeek;
04068                      if(h+act->duration <= gt.rules.nHoursPerDay)
04069                             notAllowedTimesPercentages[i][j]=-1;
04070                      else
04071                             notAllowedTimesPercentages[i][j]=100;
04072               }
04073        }
04074 
04075        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
04076                      //TEACHER not available
04077                      if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TEACHER_NOT_AVAILABLE_TIMES){
04078                             ConstraintTeacherNotAvailableTimes* tn=(ConstraintTeacherNotAvailableTimes*)gt.rules.internalTimeConstraintsList[i];
04079                             for(int ai=0; ai<gt.rules.nInternalActivities; ai++){
04080                                    Activity* act=&gt.rules.internalActivitiesList[ai];
04081                                    for(int ti=0; ti<act->iTeachersList.count(); ti++)
04082                                           if(act->iTeachersList.at(ti)==tn->teacher_ID){
04083                                                  assert(tn->days.count()==tn->hours.count());
04084                                                  for(int kk=0; kk<tn->days.count(); kk++){
04085                                                         int d=tn->days.at(kk);
04086                                                         int h=tn->hours.at(kk);
04087                                                         
04088                                                         for(int hh=max(0, h-act->duration+1); hh<=h; hh++)
04089                                                                if(notAllowedTimesPercentages[ai][d+hh*gt.rules.nDaysPerWeek]<tn->weightPercentage)
04090                                                                       notAllowedTimesPercentages[ai][d+hh*gt.rules.nDaysPerWeek]=tn->weightPercentage;
04091                                                  }
04092                                                  //break; //search no more for teacher -- careful with that
04093                                           }
04094                             }
04095 
04096                             if(tn->weightPercentage!=100){
04097                                    ok=false;
04098 
04099                                    LongTextMessageBox::mediumInformation(parent, GeneratePreTranslate::tr("FET warning"),
04100                                     GeneratePreTranslate::tr("Cannot optimize, because you have constraints of type "
04101                                     "teacher not available with weight percentage less than 100\% for teacher %1. Currently, FET can only optimize with "
04102                                     "constraints teacher not available with 100\% weight (or no constraint). Please "
04103                                     "modify your data accordingly and try again.").arg(tn->teacher));
04104                      
04105                                    return ok;
04106                             }
04107                             else{                       
04108                                    assert(tn->weightPercentage==100);
04109                                    assert(tn->days.count()==tn->hours.count());
04110                                    for(int kk=0; kk<tn->days.count(); kk++){
04111                                           int d=tn->days.at(kk);
04112                                           int h=tn->hours.at(kk);
04113 
04114                                           teacherNotAvailableDayHour[tn->teacher_ID][d][h]=true;
04115                                    }
04116                             }
04117                      }
04118 
04119                      //STUDENTS SET not available              
04120                      if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_STUDENTS_SET_NOT_AVAILABLE_TIMES){
04121                             ConstraintStudentsSetNotAvailableTimes* sn=(ConstraintStudentsSetNotAvailableTimes*)gt.rules.internalTimeConstraintsList[i];
04122                             for(int ai=0; ai<gt.rules.nInternalActivities; ai++){
04123                                    Activity* act=&gt.rules.internalActivitiesList[ai];
04124                                    for(int sg=0; sg<act->iSubgroupsList.count(); sg++)
04125                                           for(int j=0; j<sn->iSubgroupsList.count(); j++){
04126                                                  if(act->iSubgroupsList.at(sg)==sn->iSubgroupsList.at(j)){
04127                                                         assert(sn->days.count()==sn->hours.count());
04128                                                         for(int kk=0; kk<sn->days.count(); kk++){
04129                                                                int d=sn->days.at(kk);
04130                                                                int h=sn->hours.at(kk);
04131 
04132                                                                for(int hh=max(0, h-act->duration+1); hh<=h; hh++)
04133                                                                       if(notAllowedTimesPercentages[ai][d+hh*gt.rules.nDaysPerWeek]<sn->weightPercentage)
04134                                                                              notAllowedTimesPercentages[ai][d+hh*gt.rules.nDaysPerWeek]=sn->weightPercentage;
04135                                                         }
04136                                                         //break; //search no more for subgroup - this can bring an improvement in precalculation
04137                                                         //but needs attention
04138                                                  }
04139                                           }
04140                             }
04141 
04142                             if(sn->weightPercentage!=100){
04143                                    ok=false;
04144 
04145                                    LongTextMessageBox::mediumInformation(parent, GeneratePreTranslate::tr("FET warning"),
04146                                     GeneratePreTranslate::tr("Cannot optimize, because you have constraints of type "
04147                                     "students set not available with weight percentage less than 100\% for students set %1. Currently, FET can only optimize with "
04148                                     "constraints students set not available with 100\% weight (or no constraint). Please "
04149                                     "modify your data accordingly and try again.").arg(sn->students));
04150                      
04151                                    return ok;
04152                             }
04153                             else{                       
04154                                    assert(sn->weightPercentage==100);
04155                                    for(int q=0; q<sn->iSubgroupsList.count(); q++){
04156                                           int ss=sn->iSubgroupsList.at(q);
04157                                           assert(sn->days.count()==sn->hours.count());
04158                                           for(int kk=0; kk<sn->days.count(); kk++){
04159                                                  int d=sn->days.at(kk);
04160                                                  int h=sn->hours.at(kk);
04161 
04162                                                  subgroupNotAvailableDayHour[ss][d][h]=true;
04163                                           }
04164                                    }
04165                             }
04166                      }
04167                      
04168                      //BREAK
04169                      if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_BREAK_TIMES){
04170                             ConstraintBreakTimes* br=(ConstraintBreakTimes*)gt.rules.internalTimeConstraintsList[i];
04171                             for(int ai=0; ai<gt.rules.nInternalActivities; ai++){
04172                                    Activity* act=&gt.rules.internalActivitiesList[ai];
04173 
04174                                    assert(br->days.count()==br->hours.count());
04175                                    for(int kk=0; kk<br->days.count(); kk++){
04176                                           int d=br->days.at(kk);
04177                                           int h=br->hours.at(kk);
04178 
04179                                           for(int hh=max(0, h-act->duration+1); hh<=h; hh++)
04180                                                  if(notAllowedTimesPercentages[ai][d+hh*gt.rules.nDaysPerWeek]<br->weightPercentage)
04181                                                         notAllowedTimesPercentages[ai][d+hh*gt.rules.nDaysPerWeek]=br->weightPercentage;
04182                                    }
04183                             }
04184 
04185                             if(br->weightPercentage!=100){
04186                                    ok=false;
04187 
04188                                    LongTextMessageBox::mediumInformation(parent, GeneratePreTranslate::tr("FET warning"),
04189                                     GeneratePreTranslate::tr("Cannot optimize, because you have constraints of type "
04190                                     "break with weight percentage less than 100\%. Currently, FET can only optimize with "
04191                                     "constraints break with 100\% weight (or no constraint). Please "
04192                                     "modify your data accordingly and try again."));
04193                      
04194                                    return ok;
04195                             }
04196                             else{                       
04197                                    assert(br->weightPercentage==100);
04198        
04199                                    assert(br->days.count()==br->hours.count());
04200                                    for(int kk=0; kk<br->days.count(); kk++){
04201                                           int d=br->days.at(kk);
04202                                           int h=br->hours.at(kk);
04203 
04204                                           breakDayHour[d][h]=true;
04205                                    }
04206                             }
04207                      }
04208 
04209                      //ACTIVITY preferred starting time
04210                      if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_ACTIVITY_PREFERRED_STARTING_TIME){
04211                             ConstraintActivityPreferredStartingTime* ap=(ConstraintActivityPreferredStartingTime*)gt.rules.internalTimeConstraintsList[i];
04212                             
04213                             if(ap->day>=0 && ap->hour>=0){
04214                                    for(int d=0; d<gt.rules.nDaysPerWeek; d++)
04215                                           for(int h=0; h<gt.rules.nHoursPerDay; h++)
04216                                                  if(d!=ap->day || h!=ap->hour)
04217                                                         if(notAllowedTimesPercentages[ap->activityIndex][d+h*gt.rules.nDaysPerWeek]<ap->weightPercentage)
04218                                                                notAllowedTimesPercentages[ap->activityIndex][d+h*gt.rules.nDaysPerWeek]=ap->weightPercentage;
04219                             }
04220                             else if(ap->day>=0){
04221                                    for(int d=0; d<gt.rules.nDaysPerWeek; d++)
04222                                           for(int h=0; h<gt.rules.nHoursPerDay; h++)
04223                                                  if(d!=ap->day)
04224                                                         if(notAllowedTimesPercentages[ap->activityIndex][d+h*gt.rules.nDaysPerWeek]<ap->weightPercentage)
04225                                                                notAllowedTimesPercentages[ap->activityIndex][d+h*gt.rules.nDaysPerWeek]=ap->weightPercentage;
04226                             }
04227                             else if(ap->hour>=0){
04228                                    for(int d=0; d<gt.rules.nDaysPerWeek; d++)
04229                                           for(int h=0; h<gt.rules.nHoursPerDay; h++)
04230                                                  if(h!=ap->hour)
04231                                                         if(notAllowedTimesPercentages[ap->activityIndex][d+h*gt.rules.nDaysPerWeek]<ap->weightPercentage)
04232                                                                notAllowedTimesPercentages[ap->activityIndex][d+h*gt.rules.nDaysPerWeek]=ap->weightPercentage;
04233                             }
04234                             else{
04235                                    ok=false;
04236 
04237                                    int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
04238                                     GeneratePreTranslate::tr("Cannot optimize, because you have constraints of type "
04239                                     "activity preferred starting time with no day nor hour selected (for activity with id==%1). "
04240                                     "Please modify your data accordingly (remove or edit constraint) and try again.")
04241                                     .arg(gt.rules.internalActivitiesList[ap->activityIndex].id),
04242                                     GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
04243                                    1, 0 );
04244 
04245                                    if(t==0)
04246                                           break;
04247                                    //assert(0);
04248                             }
04249                      }      
04250 
04251                      //ACTIVITY preferred starting times
04252                      if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_ACTIVITY_PREFERRED_STARTING_TIMES){
04253                             ConstraintActivityPreferredStartingTimes* ap=(ConstraintActivityPreferredStartingTimes*)gt.rules.internalTimeConstraintsList[i];
04254                             
04255                             int ai=ap->activityIndex;
04256                             
04257                             //Matrix1D<bool> allowed;
04258                             //allowed.resize(gt.rules.nHoursPerWeek);
04259                             //bool allowed[MAX_HOURS_PER_WEEK];
04260                             for(int k=0; k<gt.rules.nHoursPerWeek; k++)
04261                                    allowed[k]=false;
04262                                           
04263                             for(int m=0; m<ap->nPreferredStartingTimes_L; m++){
04264                                    int d=ap->days_L[m];
04265                                    int h=ap->hours_L[m];
04266                                    
04267                                    if(d>=0 && h>=0){
04268                                           assert(d>=0 && h>=0);
04269                                           allowed[d+h*gt.rules.nDaysPerWeek]=true;
04270                                    }
04271                                    else if(d>=0){
04272                                           for(int hh=0; hh<gt.rules.nHoursPerDay; hh++)
04273                                                  allowed[d+hh*gt.rules.nDaysPerWeek]=true;
04274                                    }
04275                                    else if(h>=0){
04276                                           for(int dd=0; dd<gt.rules.nDaysPerWeek; dd++)
04277                                                  allowed[dd+h*gt.rules.nDaysPerWeek]=true;
04278                                    }
04279                             }
04280                             
04281                             for(int k=0; k<gt.rules.nHoursPerWeek; k++)
04282                                    if(!allowed[k])
04283                                           if(notAllowedTimesPercentages[ai][k] < ap->weightPercentage)
04284                                                  notAllowedTimesPercentages[ai][k] = ap->weightPercentage;
04285                      }
04286                      
04287                      //ACTIVITIES preferred starting times
04288                      if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_ACTIVITIES_PREFERRED_STARTING_TIMES){
04289                             ConstraintActivitiesPreferredStartingTimes* ap=(ConstraintActivitiesPreferredStartingTimes*)gt.rules.internalTimeConstraintsList[i];
04290                             
04291                             for(int j=0; j<ap->nActivities; j++){
04292                                    int ai=ap->activitiesIndices[j];
04293                                    
04294                                    //Matrix1D<bool> allowed;
04295                                    //allowed.resize(gt.rules.nHoursPerWeek);
04296                                    //bool allowed[MAX_HOURS_PER_WEEK];
04297                                    for(int k=0; k<gt.rules.nHoursPerWeek; k++)
04298                                           allowed[k]=false;
04299                                           
04300                                    for(int m=0; m<ap->nPreferredStartingTimes_L; m++){
04301                                           int d=ap->days_L[m];
04302                                           int h=ap->hours_L[m];
04303                                           assert(d>=0 && h>=0);
04304                                           allowed[d+h*gt.rules.nDaysPerWeek]=true;
04305                                    }
04306                                    
04307                                    for(int k=0; k<gt.rules.nHoursPerWeek; k++)
04308                                           if(!allowed[k])
04309                                                  if(notAllowedTimesPercentages[ai][k] < ap->weightPercentage)
04310                                                         notAllowedTimesPercentages[ai][k] = ap->weightPercentage;
04311                             }
04312                      }
04313                      //subactivities preferred starting times
04314                      if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_STARTING_TIMES){
04315                             ConstraintSubactivitiesPreferredStartingTimes* ap=(ConstraintSubactivitiesPreferredStartingTimes*)gt.rules.internalTimeConstraintsList[i];
04316                             
04317                             for(int j=0; j<ap->nActivities; j++){
04318                                    int ai=ap->activitiesIndices[j];
04319                                    
04320                                    //Matrix1D<bool> allowed;
04321                                    //allowed.resize(gt.rules.nHoursPerWeek);
04322                                    //bool allowed[MAX_HOURS_PER_WEEK];
04323                                    for(int k=0; k<gt.rules.nHoursPerWeek; k++)
04324                                           allowed[k]=false;
04325                                           
04326                                    for(int m=0; m<ap->nPreferredStartingTimes_L; m++){
04327                                           int d=ap->days_L[m];
04328                                           int h=ap->hours_L[m];
04329                                           assert(d>=0 && h>=0);
04330                                           allowed[d+h*gt.rules.nDaysPerWeek]=true;
04331                                    }
04332                                    
04333                                    for(int k=0; k<gt.rules.nHoursPerWeek; k++)
04334                                           if(!allowed[k])
04335                                                  if(notAllowedTimesPercentages[ai][k] < ap->weightPercentage)
04336                                                         notAllowedTimesPercentages[ai][k] = ap->weightPercentage;
04337                             }
04338                      }
04339                      //ACTIVITY preferred time slots
04340                      if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_ACTIVITY_PREFERRED_TIME_SLOTS){
04341                             ConstraintActivityPreferredTimeSlots* ap=(ConstraintActivityPreferredTimeSlots*)gt.rules.internalTimeConstraintsList[i];
04342                             
04343                             int ai=ap->p_activityIndex;
04344                             
04345                             //Matrix1D<bool> allowed;
04346                             //allowed.resize(gt.rules.nHoursPerWeek);
04347                             //bool allowed[MAX_HOURS_PER_WEEK];
04348                             for(int k=0; k<gt.rules.nHoursPerWeek; k++)
04349                                    allowed[k]=false;
04350                                           
04351                             for(int m=0; m<ap->p_nPreferredTimeSlots_L; m++){
04352                                    int d=ap->p_days_L[m];
04353                                    int h=ap->p_hours_L[m];
04354                                    
04355                                    if(d>=0 && h>=0){
04356                                           assert(d>=0 && h>=0);
04357                                           allowed[d+h*gt.rules.nDaysPerWeek]=true;
04358                                    }
04359                                    else if(d>=0){
04360                                           for(int hh=0; hh<gt.rules.nHoursPerDay; hh++)
04361                                                  allowed[d+hh*gt.rules.nDaysPerWeek]=true;
04362                                    }
04363                                    else if(h>=0){
04364                                           for(int dd=0; dd<gt.rules.nDaysPerWeek; dd++)
04365                                                  allowed[dd+h*gt.rules.nDaysPerWeek]=true;
04366                                    }
04367                             }
04368                             
04369                             for(int k=0; k<gt.rules.nHoursPerWeek; k++){
04370                                    int d=k%gt.rules.nDaysPerWeek;
04371                                    int h=k/gt.rules.nDaysPerWeek;
04372                                    
04373                                    bool ok=true;
04374                                    
04375                                    for(int dur=0; dur<gt.rules.internalActivitiesList[ai].duration && h+dur<gt.rules.nHoursPerDay; dur++){
04376                                           assert(d+(h+dur)*gt.rules.nDaysPerWeek<gt.rules.nDaysPerWeek*gt.rules.nHoursPerDay);
04377                                           if(!allowed[d+(h+dur)*gt.rules.nDaysPerWeek]){
04378                                                  ok=false;
04379                                                  break;
04380                                           }
04381                                    }
04382                             
04383                                    if(!ok)
04384                                           if(notAllowedTimesPercentages[ai][k] < ap->weightPercentage)
04385                                                  notAllowedTimesPercentages[ai][k] = ap->weightPercentage;
04386                             }
04387                      }
04388                      
04389                      //ACTIVITIES preferred time slots
04390                      if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_ACTIVITIES_PREFERRED_TIME_SLOTS){
04391                             ConstraintActivitiesPreferredTimeSlots* ap=(ConstraintActivitiesPreferredTimeSlots*)gt.rules.internalTimeConstraintsList[i];
04392                             
04393                             for(int j=0; j<ap->p_nActivities; j++){
04394                                    int ai=ap->p_activitiesIndices[j];
04395                                    
04396                                    //Matrix1D<bool> allowed;
04397                                    //allowed.resize(gt.rules.nHoursPerWeek);
04398                                    //bool allowed[MAX_HOURS_PER_WEEK];
04399                                    for(int k=0; k<gt.rules.nHoursPerWeek; k++)
04400                                           allowed[k]=false;
04401                                           
04402                                    for(int m=0; m<ap->p_nPreferredTimeSlots_L; m++){
04403                                           int d=ap->p_days_L[m];
04404                                           int h=ap->p_hours_L[m];
04405                                           assert(d>=0 && h>=0);
04406                                           allowed[d+h*gt.rules.nDaysPerWeek]=true;
04407                                    }
04408                                    
04409                                    for(int k=0; k<gt.rules.nHoursPerWeek; k++){
04410                                           int d=k%gt.rules.nDaysPerWeek;
04411                                           int h=k/gt.rules.nDaysPerWeek;
04412                                           
04413                                           bool ok=true;
04414                                           
04415                                           for(int dur=0; dur<gt.rules.internalActivitiesList[ai].duration && h+dur<gt.rules.nHoursPerDay; dur++){
04416                                                  assert(d+(h+dur)*gt.rules.nDaysPerWeek<gt.rules.nDaysPerWeek*gt.rules.nHoursPerDay);
04417                                                  if(!allowed[d+(h+dur)*gt.rules.nDaysPerWeek]){
04418                                                         ok=false;
04419                                                         break;
04420                                                  }
04421                                           }
04422                             
04423                                           if(!ok)
04424                                                  if(notAllowedTimesPercentages[ai][k] < ap->weightPercentage)
04425                                                         notAllowedTimesPercentages[ai][k] = ap->weightPercentage;
04426                                    }
04427                             }
04428                      }
04429                      //subactivities preferred time slots 
04430                      if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_SUBACTIVITIES_PREFERRED_TIME_SLOTS){
04431                             ConstraintSubactivitiesPreferredTimeSlots* ap=(ConstraintSubactivitiesPreferredTimeSlots*)gt.rules.internalTimeConstraintsList[i];
04432                             
04433                             for(int j=0; j<ap->p_nActivities; j++){
04434                                    int ai=ap->p_activitiesIndices[j];
04435                                    
04436                                    //Matrix1D<bool> allowed;
04437                                    //allowed.resize(gt.rules.nHoursPerWeek);
04438                                    //bool allowed[MAX_HOURS_PER_WEEK];
04439                                    for(int k=0; k<gt.rules.nHoursPerWeek; k++)
04440                                           allowed[k]=false;
04441                                           
04442                                    for(int m=0; m<ap->p_nPreferredTimeSlots_L; m++){
04443                                           int d=ap->p_days_L[m];
04444                                           int h=ap->p_hours_L[m];
04445                                           assert(d>=0 && h>=0);
04446                                           allowed[d+h*gt.rules.nDaysPerWeek]=true;
04447                                    }
04448                                    
04449                                    for(int k=0; k<gt.rules.nHoursPerWeek; k++){
04450                                           int d=k%gt.rules.nDaysPerWeek;
04451                                           int h=k/gt.rules.nDaysPerWeek;
04452                                           
04453                                           bool ok=true;
04454                                           
04455                                           for(int dur=0; dur<gt.rules.internalActivitiesList[ai].duration && h+dur<gt.rules.nHoursPerDay; dur++){
04456                                                  assert(d+(h+dur)*gt.rules.nDaysPerWeek<gt.rules.nDaysPerWeek*gt.rules.nHoursPerDay);
04457                                                  if(!allowed[d+(h+dur)*gt.rules.nDaysPerWeek]){
04458                                                         ok=false;
04459                                                         break;
04460                                                  }
04461                                           }
04462                             
04463                                           if(!ok)
04464                                                  if(notAllowedTimesPercentages[ai][k] < ap->weightPercentage)
04465                                                         notAllowedTimesPercentages[ai][k] = ap->weightPercentage;
04466                                    }
04467                             }
04468                      }
04469        }
04470        
04471        return ok;
04472 }
04473 
04474 bool computeMinDays(QWidget* parent)
04475 {
04476        QSet<ConstraintMinDaysBetweenActivities*> mdset;
04477 
04478        bool ok=true;
04479 
04480        for(int j=0; j<gt.rules.nInternalActivities; j++){
04481               minDaysListOfActivities[j].clear();
04482               minDaysListOfMinDays[j].clear();
04483               minDaysListOfConsecutiveIfSameDay[j].clear();
04484               minDaysListOfWeightPercentages[j].clear();
04485                             
04486               //for(int k=0; k<gt.rules.nInternalActivities; k++)
04487               //     minDays[j][k]=0;
04488        }
04489 
04490        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++)
04491               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_MIN_DAYS_BETWEEN_ACTIVITIES
04492                /*&&gt.rules.internalTimeConstraintsList[i]->compulsory==true*/){
04493                      ConstraintMinDaysBetweenActivities* md=
04494                       (ConstraintMinDaysBetweenActivities*)gt.rules.internalTimeConstraintsList[i];
04495                      
04496                      for(int j=0; j<md->_n_activities; j++){
04497                             int ai1=md->_activities[j];
04498                             for(int k=0; k<md->_n_activities; k++)
04499                                    if(j!=k){
04500                                           int ai2=md->_activities[k];
04501                                           if(ai1==ai2){                                    
04502                                                  ok=false;
04503                                                  
04504                                                  if(!mdset.contains(md)){
04505                                                         mdset.insert(md);
04506                                           
04507                                                         int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
04508                                                          GeneratePreTranslate::tr("Cannot optimize, because you have a constraint min days with duplicate activities. The constraint "
04509                                                          "is: %1. Please correct that.").arg(md->getDetailedDescription(gt.rules)),
04510                                                          GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
04511                                                          1, 0 );
04512                                    
04513                                                         if(t==0)
04514                                                                return ok;
04515                                                  }
04516                                           }
04517                                           int m=md->minDays;
04518                                           /*if(m>minDays[ai1][ai2])
04519                                                  minDays[ai1][ai2]=minDays[ai2][ai1]=m;*/
04520                                           
04521                                           minDaysListOfActivities[ai1].append(ai2);
04522                                           minDaysListOfMinDays[ai1].append(m);
04523                                           assert(md->weightPercentage >=0 && md->weightPercentage<=100);
04524                                           minDaysListOfWeightPercentages[ai1].append(md->weightPercentage);
04525                                           minDaysListOfConsecutiveIfSameDay[ai1].append(md->consecutiveIfSameDay);
04526                                    }
04527                      }
04528               }
04529 
04530        /*for(int j=0; j<gt.rules.nInternalActivities; j++)
04531               for(int k=0; k<gt.rules.nInternalActivities; k++)
04532                      if(minDays[j][k]>0){
04533                             assert(j!=k);
04534                             minDaysListOfActivities[j].append(k);
04535                             minDaysListOfMinDays[j].append(minDays[j][k]);
04536                      }*/
04537                      
04538        return ok;
04539 }
04540 
04541 bool computeMaxDays(QWidget* parent)
04542 {
04543        QSet<ConstraintMaxDaysBetweenActivities*> mdset;
04544 
04545        bool ok=true;
04546 
04547        for(int j=0; j<gt.rules.nInternalActivities; j++){
04548               maxDaysListOfActivities[j].clear();
04549               maxDaysListOfMaxDays[j].clear();
04550               maxDaysListOfWeightPercentages[j].clear();
04551        }
04552 
04553        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++)
04554               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_MAX_DAYS_BETWEEN_ACTIVITIES
04555                /*&&gt.rules.internalTimeConstraintsList[i]->compulsory==true*/){
04556                      ConstraintMaxDaysBetweenActivities* md=
04557                       (ConstraintMaxDaysBetweenActivities*)gt.rules.internalTimeConstraintsList[i];
04558                      
04559                      for(int j=0; j<md->_n_activities; j++){
04560                             int ai1=md->_activities[j];
04561                             for(int k=0; k<md->_n_activities; k++)
04562                                    if(j!=k){
04563                                           int ai2=md->_activities[k];
04564                                           if(ai1==ai2){                                    
04565                                                  ok=false;
04566                                                  
04567                                                  if(!mdset.contains(md)){
04568                                                         mdset.insert(md);
04569                                           
04570                                                         int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
04571                                                          GeneratePreTranslate::tr("Cannot optimize, because you have a constraint max days between activities with duplicate activities. The constraint "
04572                                                          "is: %1. Please correct that.").arg(md->getDetailedDescription(gt.rules)),
04573                                                          GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
04574                                                          1, 0 );
04575                                    
04576                                                         if(t==0)
04577                                                                return ok;
04578                                                  }
04579                                           }
04580                                           int m=md->maxDays;
04581                                           /*if(m>minDays[ai1][ai2])
04582                                                  minDays[ai1][ai2]=minDays[ai2][ai1]=m;*/
04583                                           
04584                                           maxDaysListOfActivities[ai1].append(ai2);
04585                                           maxDaysListOfMaxDays[ai1].append(m);
04586                                           assert(md->weightPercentage >=0 && md->weightPercentage<=100);
04587                                           maxDaysListOfWeightPercentages[ai1].append(md->weightPercentage);
04588                                           //maxDaysListOfConsecutiveIfSameDay[ai1].append(md->consecutiveIfSameDay);
04589                                    }
04590                      }
04591               }
04592 
04593        /*for(int j=0; j<gt.rules.nInternalActivities; j++)
04594               for(int k=0; k<gt.rules.nInternalActivities; k++)
04595                      if(minDays[j][k]>0){
04596                             assert(j!=k);
04597                             minDaysListOfActivities[j].append(k);
04598                             minDaysListOfMinDays[j].append(minDays[j][k]);
04599                      }*/
04600                      
04601        return ok;
04602 }
04603 
04604 bool computeMinGapsBetweenActivities(QWidget* parent)
04605 {
04606        QSet<ConstraintMinGapsBetweenActivities*> mgset;
04607 
04608        bool ok=true;
04609 
04610        for(int j=0; j<gt.rules.nInternalActivities; j++){
04611               minGapsBetweenActivitiesListOfActivities[j].clear();
04612               minGapsBetweenActivitiesListOfMinGaps[j].clear();
04613               minGapsBetweenActivitiesListOfWeightPercentages[j].clear();
04614                             
04615               //for(int k=0; k<gt.rules.nInternalActivities; k++)
04616               //     minDays[j][k]=0;
04617        }
04618 
04619        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++)
04620               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_MIN_GAPS_BETWEEN_ACTIVITIES
04621                /*&&gt.rules.internalTimeConstraintsList[i]->compulsory==true*/){
04622                      ConstraintMinGapsBetweenActivities* mg=
04623                       (ConstraintMinGapsBetweenActivities*)gt.rules.internalTimeConstraintsList[i];
04624                       
04625                      assert(mg->_n_activities==mg->_activities.count());
04626                      
04627                      for(int j=0; j<mg->_n_activities; j++){
04628                             int ai1=mg->_activities[j];
04629                             for(int k=0; k<mg->_n_activities; k++)
04630                                    if(j!=k){
04631                                           int ai2=mg->_activities[k];
04632                                           if(ai1==ai2){                                    
04633                                                  ok=false;
04634                                                  
04635                                                  if(!mgset.contains(mg)){
04636                                                         mgset.insert(mg);
04637                                           
04638                                                         int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
04639                                                          GeneratePreTranslate::tr("Cannot optimize, because you have a constraint min gaps between activities with duplicate activities. The constraint "
04640                                                          "is: %1. Please correct that.").arg(mg->getDetailedDescription(gt.rules)),
04641                                                          GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
04642                                                          1, 0 );
04643                                    
04644                                                         if(t==0)
04645                                                                return ok;
04646                                                  }
04647                                           }
04648                                           int m=mg->minGaps;
04649                                           
04650                                           minGapsBetweenActivitiesListOfActivities[ai1].append(ai2);
04651                                           minGapsBetweenActivitiesListOfMinGaps[ai1].append(m);
04652                                           assert(mg->weightPercentage >=0 && mg->weightPercentage<=100);
04653                                           minGapsBetweenActivitiesListOfWeightPercentages[ai1].append(mg->weightPercentage);
04654                                    }
04655                      }
04656               }
04657 
04658        return ok;
04659 }
04660 
04661 bool computeActivitiesConflictingPercentage(QWidget* parent)
04662 {
04663        //get maximum weight percent of a basic time constraint
04664        double m=-1;
04665        
04666        bool ok=false;
04667        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++)
04668               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_BASIC_COMPULSORY_TIME){
04669                      ok=true;
04670                      if(gt.rules.internalTimeConstraintsList[i]->weightPercentage>m)
04671                             m=gt.rules.internalTimeConstraintsList[i]->weightPercentage;
04672               }
04673               
04674        if(m<100)
04675               ok=false;
04676               
04677        if(!ok || m<100){
04678               LongTextMessageBox::mediumInformation(parent, GeneratePreTranslate::tr("FET warning"),
04679                GeneratePreTranslate::tr("Cannot generate, because you do not have a constraint of type basic compulsory time or its weight is lower than 100.0%.")
04680                +" "+
04681                GeneratePreTranslate::tr("Please add a constraint of this type with weight 100%.")
04682                +" "+
04683                GeneratePreTranslate::tr("You can add this constraint from the menu Data -> Time constraints -> Miscellaneous -> Basic compulsory time constraints.")
04684                +"\n\n"+
04685                GeneratePreTranslate::tr("Explanation:")
04686                +" "+
04687                GeneratePreTranslate::tr("Each time you create a new file, it contains an automatically added constraint of this type.")
04688                +" "+
04689                GeneratePreTranslate::tr("For complete flexibility, you are allowed to remove it (even if this is a wrong idea).")
04690                +" "+
04691                GeneratePreTranslate::tr("Maybe you removed it by mistake from your file.")
04692                +" "+
04693                GeneratePreTranslate::tr("By adding it again, everything should be all right.")
04694                );
04695               return false;
04696        }
04697        
04698        assert(m>=0 && m<=100);
04699        assert(m==100);
04700 
04701        //compute conflicting
04702        activitiesConflictingPercentage.resize(gt.rules.nInternalActivities, gt.rules.nInternalActivities);
04703        for(int i=0; i<gt.rules.nInternalActivities; i++)
04704               for(int j=0; j<gt.rules.nInternalActivities; j++)
04705                      activitiesConflictingPercentage[i][j]=-1;
04706               
04707        for(int i=0; i<gt.rules.nInternalActivities; i++)
04708               activitiesConflictingPercentage[i][i]=100;
04709 
04710        QProgressDialog progress(parent);
04711        progress.setWindowTitle(GeneratePreTranslate::tr("Precomputing", "Title of a progress dialog"));
04712        progress.setLabelText(GeneratePreTranslate::tr("Precomputing ... please wait"));
04713        progress.setRange(0, gt.rules.nInternalTeachers+gt.rules.nInternalSubgroups);
04714        progress.setModal(true);
04715        
04716        int ttt=0;
04717        
04718        for(int t=0; t<gt.rules.nInternalTeachers; t++){
04719               progress.setValue(ttt);
04720               //pqapplication->processEvents();
04721               if(progress.wasCanceled()){
04722                      QMessageBox::information(parent, GeneratePreTranslate::tr("FET information"), GeneratePreTranslate::tr("Canceled"));
04723                      return false;
04724               }
04725               
04726               ttt++;
04727               
04728               foreach(int i, gt.rules.internalTeachersList[t]->activitiesForTeacher)
04729                      foreach(int j, gt.rules.internalTeachersList[t]->activitiesForTeacher)
04730                             activitiesConflictingPercentage[i][j]=100;
04731        }
04732        
04733        for(int s=0; s<gt.rules.nInternalSubgroups; s++){
04734               progress.setValue(ttt);
04735               //pqapplication->processEvents();
04736               if(progress.wasCanceled()){
04737                      QMessageBox::information(parent, GeneratePreTranslate::tr("FET information"), GeneratePreTranslate::tr("Canceled"));
04738                      return false;
04739               }
04740               
04741               ttt++;
04742               
04743               foreach(int i, gt.rules.internalSubgroupsList[s]->activitiesForSubgroup)
04744                      foreach(int j, gt.rules.internalSubgroupsList[s]->activitiesForSubgroup)
04745                             activitiesConflictingPercentage[i][j]=100;
04746        }
04747 
04748        progress.setValue(gt.rules.nInternalTeachers+gt.rules.nInternalSubgroups);
04749        
04750        //new volker (start)
04751        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
04752               TimeConstraint* tc=gt.rules.internalTimeConstraintsList[i];
04753               if(tc->type==CONSTRAINT_ACTIVITIES_NOT_OVERLAPPING){
04754                      if(tc->weightPercentage==100.0){
04755                             ConstraintActivitiesNotOverlapping* cno=(ConstraintActivitiesNotOverlapping*) tc;
04756                             
04757                             for(int a=0; a<cno->_n_activities; a++){
04758                                    for(int b=0; b<cno->_n_activities; b++){
04759                                           if(cno->_activities[a]!=cno->_activities[b]){
04760                                                  activitiesConflictingPercentage[cno->_activities[a]][cno->_activities[b]]=100;
04761                                           }
04762                                    }
04763                             }
04764                      }
04765                      else{
04766                             ConstraintActivitiesNotOverlapping* cno=(ConstraintActivitiesNotOverlapping*) tc;
04767                             
04768                             int ww=int(cno->weightPercentage);
04769                             if(ww>100)
04770                                    ww=100;
04771                      
04772                             for(int a=0; a<cno->_n_activities; a++){
04773                                    for(int b=0; b<cno->_n_activities; b++){
04774                                           if(cno->_activities[a]!=cno->_activities[b]){
04775                                                  if(activitiesConflictingPercentage[cno->_activities[a]][cno->_activities[b]] < ww)
04776                                                         activitiesConflictingPercentage[cno->_activities[a]][cno->_activities[b]]=ww;
04777                                           }
04778                                    }
04779                             }
04780                      }
04781               }
04782        }
04783        //new volker (end)
04784 
04785        return true;
04786 }
04787 
04788 //old
04789 /*
04790 #if 0
04791 bool computeActivitiesConflictingPercentage()
04792 {
04793        //get maximum weight percent of a basic time constraint
04794        double m=-1;
04795        
04796        bool ok=false;
04797        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++)
04798               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_BASIC_COMPULSORY_TIME){
04799                      ok=true;
04800                      if(gt.rules.internalTimeConstraintsList[i]->weightPercentage>m)
04801                             m=gt.rules.internalTimeConstraintsList[i]->weightPercentage;
04802               }
04803               
04804        if(m<100)
04805               ok=false;
04806               
04807        if(!ok || m<100){
04808               QMessageBox::warning(parent, GeneratePreTranslate::tr("FET warning"),
04809                GeneratePreTranslate::tr("Cannot optimize, because you have no basic time constraints or its weight is lower than 100.0%. "
04810                "Please add a basic time constraint (100% weight)"));
04811               return false;
04812        }
04813        
04814        assert(m>=0 && m<=100);
04815        assert(m==100);
04816 
04817        //compute conflictig
04818        for(int i=0; i<gt.rules.nInternalActivities; i++)
04819               activitiesConflictingPercentage[i][i]=100;
04820               
04821        QProgressDialog progress(parent);
04822        progress.setLabelText(GeneratePreTranslate::tr("Precomputing ... please wait"));
04823        progress.setRange(0, gt.rules.nInternalActivities*(gt.rules.nInternalActivities-1)/2);
04824        progress.setModal(true);
04825        
04826        int ttt=0;
04827               
04828        for(int i=0; i<gt.rules.nInternalActivities; i++){
04829               progress.setValue(ttt);
04830               pqapplication->processEvents();
04831               if(progress.wasCanceled()){
04832                      QMessageBox::information(parent, GeneratePreTranslate::tr("FET information"), GeneratePreTranslate::tr("Canceled"));
04833                      return false;
04834               }
04835                      
04836               for(int j=i+1; j<gt.rules.nInternalActivities; j++){
04837                      ttt++;
04838               
04839                      //see if they share a teacher
04840                      bool shareTeacher=false;
04841                      foreach(QString tni, gt.rules.internalActivitiesList[i].teachersNames){
04842                             foreach(QString tnj, gt.rules.internalActivitiesList[j].teachersNames){
04843                                    if(tni==tnj){
04844                                           shareTeacher=true;
04845                                           break;
04846                                    }
04847                             }
04848                             if(shareTeacher)
04849                                    break;
04850                      }
04851                      
04852                      bool shareStudentsSet=false;
04853                      foreach(QString ssi, gt.rules.internalActivitiesList[i].studentsNames){
04854                             foreach(QString ssj, gt.rules.internalActivitiesList[j].studentsNames){
04855                                    if(gt.rules.studentsSetsRelated(ssi, ssj)){
04856                                           shareStudentsSet=true;
04857                                           break;
04858                                    }
04859                             }
04860                             if(shareStudentsSet)
04861                                    break;
04862                      }
04863                      
04864                      if(shareTeacher||shareStudentsSet)
04865                             activitiesConflictingPercentage[i][j]=activitiesConflictingPercentage[j][i]=100;
04866                      else
04867                             activitiesConflictingPercentage[i][j]=activitiesConflictingPercentage[j][i]=-1;
04868               }
04869        }
04870 
04871        progress.setValue(gt.rules.nInternalActivities*(gt.rules.nInternalActivities-1)/2);
04872               
04873        return true;
04874 }
04875 #endif
04876 //endif 0
04877 */
04878 
04879 void computeConstrTwoActivitiesConsecutive()
04880 {
04881        for(int i=0; i<gt.rules.nInternalActivities; i++){
04882               constrTwoActivitiesConsecutivePercentages[i].clear();
04883               constrTwoActivitiesConsecutiveActivities[i].clear();
04884 
04885               inverseConstrTwoActivitiesConsecutivePercentages[i].clear();
04886               inverseConstrTwoActivitiesConsecutiveActivities[i].clear();
04887        }
04888 
04889        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++)
04890               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TWO_ACTIVITIES_CONSECUTIVE){
04891                      ConstraintTwoActivitiesConsecutive* c2=(ConstraintTwoActivitiesConsecutive*)gt.rules.internalTimeConstraintsList[i];
04892                      
04893                      int fai=c2->firstActivityIndex;
04894                      int sai=c2->secondActivityIndex;
04895                      
04896                      //direct
04897                      int j=constrTwoActivitiesConsecutiveActivities[fai].indexOf(sai); 
04898                      if(j==-1){
04899                             constrTwoActivitiesConsecutiveActivities[fai].append(sai);
04900                             constrTwoActivitiesConsecutivePercentages[fai].append(c2->weightPercentage);
04901                      }
04902                      else if(j>=0 && constrTwoActivitiesConsecutivePercentages[fai].at(j)<c2->weightPercentage){
04903                             constrTwoActivitiesConsecutivePercentages[fai][j]=c2->weightPercentage;
04904                      }
04905 
04906                      //inverse
04907                      j=inverseConstrTwoActivitiesConsecutiveActivities[sai].indexOf(fai); 
04908                      if(j==-1){
04909                             inverseConstrTwoActivitiesConsecutiveActivities[sai].append(fai);
04910                             inverseConstrTwoActivitiesConsecutivePercentages[sai].append(c2->weightPercentage);
04911                      }
04912                      else if(j>=0 && inverseConstrTwoActivitiesConsecutivePercentages[sai].at(j)<c2->weightPercentage){
04913                             inverseConstrTwoActivitiesConsecutivePercentages[sai][j]=c2->weightPercentage;
04914                      }
04915               }
04916 }
04917 
04918 void computeConstrTwoActivitiesGrouped()
04919 {
04920        for(int i=0; i<gt.rules.nInternalActivities; i++){
04921               constrTwoActivitiesGroupedPercentages[i].clear();
04922               constrTwoActivitiesGroupedActivities[i].clear();
04923        }
04924 
04925        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++)
04926               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TWO_ACTIVITIES_GROUPED){
04927                      ConstraintTwoActivitiesGrouped* c2=(ConstraintTwoActivitiesGrouped*)gt.rules.internalTimeConstraintsList[i];
04928                      
04929                      int fai=c2->firstActivityIndex;
04930                      int sai=c2->secondActivityIndex;
04931                      
04932                      //direct
04933                      int j=constrTwoActivitiesGroupedActivities[fai].indexOf(sai); 
04934                      if(j==-1){
04935                             constrTwoActivitiesGroupedActivities[fai].append(sai);
04936                             constrTwoActivitiesGroupedPercentages[fai].append(c2->weightPercentage);
04937                      }
04938                      else if(j>=0 && constrTwoActivitiesGroupedPercentages[fai].at(j)<c2->weightPercentage){
04939                             constrTwoActivitiesGroupedPercentages[fai][j]=c2->weightPercentage;
04940                      }
04941 
04942                      //inverse
04943                      j=constrTwoActivitiesGroupedActivities[sai].indexOf(fai); 
04944                      if(j==-1){
04945                             constrTwoActivitiesGroupedActivities[sai].append(fai);
04946                             constrTwoActivitiesGroupedPercentages[sai].append(c2->weightPercentage);
04947                      }
04948                      else if(j>=0 && constrTwoActivitiesGroupedPercentages[sai].at(j)<c2->weightPercentage){
04949                             constrTwoActivitiesGroupedPercentages[sai][j]=c2->weightPercentage;
04950                      }
04951               }
04952 }
04953 
04954 void computeConstrThreeActivitiesGrouped()
04955 {
04956        for(int i=0; i<gt.rules.nInternalActivities; i++){
04957               constrThreeActivitiesGroupedPercentages[i].clear();
04958               constrThreeActivitiesGroupedActivities[i].clear();
04959        }
04960 
04961        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++)
04962               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_THREE_ACTIVITIES_GROUPED){
04963                      ConstraintThreeActivitiesGrouped* c3=(ConstraintThreeActivitiesGrouped*)gt.rules.internalTimeConstraintsList[i];
04964                      
04965                      int fai=c3->firstActivityIndex;
04966                      int sai=c3->secondActivityIndex;
04967                      int tai=c3->thirdActivityIndex;
04968 
04969                      QPair<int, int> p23(sai, tai);
04970                      int j=constrThreeActivitiesGroupedActivities[fai].indexOf(p23);
04971                      if(j==-1){
04972                             constrThreeActivitiesGroupedActivities[fai].append(p23);
04973                             constrThreeActivitiesGroupedPercentages[fai].append(c3->weightPercentage);
04974                      }
04975                      else if(j>=0 && constrThreeActivitiesGroupedPercentages[fai].at(j)<c3->weightPercentage){
04976                             constrThreeActivitiesGroupedPercentages[fai][j]=c3->weightPercentage;
04977                      }
04978 
04979                      QPair<int, int> p13(fai, tai);
04980                      j=constrThreeActivitiesGroupedActivities[sai].indexOf(p13);
04981                      if(j==-1){
04982                             constrThreeActivitiesGroupedActivities[sai].append(p13);
04983                             constrThreeActivitiesGroupedPercentages[sai].append(c3->weightPercentage);
04984                      }
04985                      else if(j>=0 && constrThreeActivitiesGroupedPercentages[sai].at(j)<c3->weightPercentage){
04986                             constrThreeActivitiesGroupedPercentages[sai][j]=c3->weightPercentage;
04987                      }
04988 
04989                      QPair<int, int> p12(fai, sai);
04990                      j=constrThreeActivitiesGroupedActivities[tai].indexOf(p12);
04991                      if(j==-1){
04992                             constrThreeActivitiesGroupedActivities[tai].append(p12);
04993                             constrThreeActivitiesGroupedPercentages[tai].append(c3->weightPercentage);
04994                      }
04995                      else if(j>=0 && constrThreeActivitiesGroupedPercentages[tai].at(j)<c3->weightPercentage){
04996                             constrThreeActivitiesGroupedPercentages[tai][j]=c3->weightPercentage;
04997                      }
04998               }
04999 }
05000 
05001 void computeConstrTwoActivitiesOrdered()
05002 {
05003        for(int i=0; i<gt.rules.nInternalActivities; i++){
05004               constrTwoActivitiesOrderedPercentages[i].clear();
05005               constrTwoActivitiesOrderedActivities[i].clear();
05006 
05007               inverseConstrTwoActivitiesOrderedPercentages[i].clear();
05008               inverseConstrTwoActivitiesOrderedActivities[i].clear();
05009        }
05010 
05011        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++)
05012               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_TWO_ACTIVITIES_ORDERED){
05013                      ConstraintTwoActivitiesOrdered* c2=(ConstraintTwoActivitiesOrdered*)gt.rules.internalTimeConstraintsList[i];
05014                      
05015                      int fai=c2->firstActivityIndex;
05016                      int sai=c2->secondActivityIndex;
05017                      
05018                      //direct
05019                      int j=constrTwoActivitiesOrderedActivities[fai].indexOf(sai); 
05020                      if(j==-1){
05021                             constrTwoActivitiesOrderedActivities[fai].append(sai);
05022                             constrTwoActivitiesOrderedPercentages[fai].append(c2->weightPercentage);
05023                      }
05024                      else if(j>=0 && constrTwoActivitiesOrderedPercentages[fai].at(j)<c2->weightPercentage){
05025                             constrTwoActivitiesOrderedPercentages[fai][j]=c2->weightPercentage;
05026                      }
05027 
05028                      //inverse
05029                      j=inverseConstrTwoActivitiesOrderedActivities[sai].indexOf(fai); 
05030                      if(j==-1){
05031                             inverseConstrTwoActivitiesOrderedActivities[sai].append(fai);
05032                             inverseConstrTwoActivitiesOrderedPercentages[sai].append(c2->weightPercentage);
05033                      }
05034                      else if(j>=0 && inverseConstrTwoActivitiesOrderedPercentages[sai].at(j)<c2->weightPercentage){
05035                             inverseConstrTwoActivitiesOrderedPercentages[sai][j]=c2->weightPercentage;
05036                      }
05037               }
05038 }
05039 
05040 bool computeActivityEndsStudentsDayPercentages(QWidget* parent)
05041 {
05042        bool ok=true;
05043 
05044        for(int ai=0; ai<gt.rules.nInternalActivities; ai++)
05045               activityEndsStudentsDayPercentages[ai]=-1;
05046               
05047        haveActivityEndsStudentsDay=false;
05048               
05049        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
05050               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_ACTIVITY_ENDS_STUDENTS_DAY){
05051                      haveActivityEndsStudentsDay=true;
05052               
05053                      ConstraintActivityEndsStudentsDay* cae=(ConstraintActivityEndsStudentsDay*)gt.rules.internalTimeConstraintsList[i];
05054                      
05055                      if(cae->weightPercentage!=100){
05056                             ok=false;
05057 
05058                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
05059                              GeneratePreTranslate::tr("Cannot optimize, because you have constraints of type "
05060                              "activity activity ends students day for activity with id==%1 with weight percentage under 100%. "
05061                              "Constraint activity ends students day can only have weight percentage 100%. "
05062                              "Please modify your data accordingly (remove or edit constraint) and try again.")
05063                              .arg(gt.rules.internalActivitiesList[cae->activityIndex].id),
05064                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
05065                             1, 0 );
05066                             
05067                             if(t==0)
05068                                    break;
05069                      }
05070                      
05071                      int ai=cae->activityIndex;
05072                      if(activityEndsStudentsDayPercentages[ai] < cae->weightPercentage)
05073                             activityEndsStudentsDayPercentages[ai] = cae->weightPercentage;
05074               }
05075               else if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_ACTIVITIES_END_STUDENTS_DAY){
05076                      haveActivityEndsStudentsDay=true;
05077               
05078                      ConstraintActivitiesEndStudentsDay* cae=(ConstraintActivitiesEndStudentsDay*)gt.rules.internalTimeConstraintsList[i];
05079                      
05080                      if(cae->weightPercentage!=100){
05081                             ok=false;
05082 
05083                             int t=LongTextMessageBox::mediumConfirmation(parent, GeneratePreTranslate::tr("FET warning"),
05084                              GeneratePreTranslate::tr("Cannot optimize, because you have constraints of type "
05085                              "activity activities end students day with weight percentage under 100%. "
05086                              "Constraint activities end students day can only have weight percentage 100%. "
05087                              "Please modify your data accordingly (remove or edit constraint) and try again."),
05088                              GeneratePreTranslate::tr("Skip rest"), GeneratePreTranslate::tr("See next"), QString(),
05089                             1, 0 );
05090                             
05091                             if(t==0)
05092                                    break;
05093                      }
05094                      
05095                      for(int i=0; i<cae->nActivities; i++){
05096                             int ai=cae->activitiesIndices[i];
05097                             if(activityEndsStudentsDayPercentages[ai] < cae->weightPercentage)
05098                                    activityEndsStudentsDayPercentages[ai] = cae->weightPercentage;
05099                      }
05100               }
05101        }
05102               
05103        return ok;
05104 }
05105 
05106 bool checkMinDays100Percent(QWidget* parent)
05107 {
05108        bool ok=true;
05109        
05110        //int daysTeacherIsAvailable[MAX_TEACHERS];
05111 
05112        for(int tc=0; tc<gt.rules.nInternalTeachers; tc++){
05113               daysTeacherIsAvailable[tc]=0;
05114 
05115               for(int d=0; d<gt.rules.nDaysPerWeek; d++){
05116                      bool dayAvailable=false;
05117                      for(int h=0; h<gt.rules.nHoursPerDay; h++)
05118                             if(!breakDayHour[d][h] && !teacherNotAvailableDayHour[tc][d][h]){
05119                                    dayAvailable=true;
05120                                    break;
05121                             }
05122                             
05123                      if(dayAvailable)
05124                             daysTeacherIsAvailable[tc]++;
05125               }
05126                      
05127               if(teachersMaxDaysPerWeekMaxDays[tc]>=0){ //it has compulsory 100% weight
05128                      assert(teachersMaxDaysPerWeekWeightPercentages[tc]==100);
05129                      daysTeacherIsAvailable[tc]=min(daysTeacherIsAvailable[tc], teachersMaxDaysPerWeekMaxDays[tc]);
05130               }
05131        }
05132 
05133        //int daysSubgroupIsAvailable[MAX_TOTAL_SUBGROUPS];
05134 
05135        for(int sb=0; sb<gt.rules.nInternalSubgroups; sb++){
05136               daysSubgroupIsAvailable[sb]=0;
05137 
05138               for(int d=0; d<gt.rules.nDaysPerWeek; d++){
05139                      bool dayAvailable=false;
05140                      for(int h=0; h<gt.rules.nHoursPerDay; h++)
05141                             if(!breakDayHour[d][h] && !subgroupNotAvailableDayHour[sb][d][h]){
05142                                    dayAvailable=true;
05143                                    break;
05144                             }
05145                             
05146                      if(dayAvailable)
05147                             daysSubgroupIsAvailable[sb]++;
05148               }
05149        }
05150        
05151        for(int i=0; i<gt.rules.nInternalTimeConstraints; i++){
05152               if(gt.rules.internalTimeConstraintsList[i]->type==CONSTRAINT_MIN_DAYS_BETWEEN_ACTIVITIES
05153                &&gt.rules.internalTimeConstraintsList[i]->weightPercentage==100.0){
05154                      ConstraintMinDaysBetweenActivities* md=(ConstraintMinDaysBetweenActivities*)gt.rules.internalTimeConstraintsList[i];                 
05155                      
05156                      if(md->minDays>=1){
05157                             int na=md->_n_activities;
05158                             int nd=md->minDays;
05159                             if((na-1)*nd+1 > gt.rules.nDaysPerWeek){
05160                                    ok=false;
05161                                           
05162                                    QString s=GeneratePreTranslate::tr("%1 cannot be respected because it contains %2 activities,"
05163                                     " has weight 100% and has min number of days between activities=%3. The minimum required number of days per week for"
05164                                     " that would be (nactivities-1)*mindays+1=%4, and you have only %5 days per week - impossible. Please correct this constraint.", "%1 is the detailed description of a constraint"
05165                                    )
05166                                     .arg(md->getDetailedDescription(gt.rules))
05167                                     .arg(na)
05168                                     .arg(nd)
05169                                     .arg((na-1)*nd+1)
05170                                     .arg(gt.rules.nDaysPerWeek)
05171                                     ;
05172 
05173                                    int t=