Version 16.190

This commit is contained in:
Antonio Cañas Vargas 2017-04-25 11:57:36 +02:00
parent 0cd2ceb4c5
commit e1a44ef85b
4 changed files with 178 additions and 85 deletions

View File

@ -219,13 +219,14 @@
/****************************** Public constants *****************************/ /****************************** Public constants *****************************/
/*****************************************************************************/ /*****************************************************************************/
#define Log_PLATFORM_VERSION "SWAD 16.189 (2017-04-25)" #define Log_PLATFORM_VERSION "SWAD 16.190 (2017-04-25)"
#define CSS_FILE "swad16.189.css" #define CSS_FILE "swad16.189.css"
#define JS_FILE "swad16.181.js" #define JS_FILE "swad16.181.js"
// Number of lines (includes comments but not blank lines) has been got with the following command: // Number of lines (includes comments but not blank lines) has been got with the following command:
// nl swad*.c swad*.h css/swad*.css py/swad*.py js/swad*.js soap/swad*?.h sql/swad*.sql | tail -1 // nl swad*.c swad*.h css/swad*.css py/swad*.py js/swad*.js soap/swad*?.h sql/swad*.sql | tail -1
/* /*
Version 16.190: Apr 25, 2017 Code refactoring in timetable. (218106 lines)
Version 16.189: Apr 25, 2017 Changes in timetable. (218027 lines) Version 16.189: Apr 25, 2017 Changes in timetable. (218027 lines)
7 changes necessary in database. 7 changes necessary in database.
ALTER TABLE timetable_crs DROP COLUMN DayOld; ALTER TABLE timetable_crs DROP COLUMN DayOld;

View File

@ -622,6 +622,17 @@ struct Globals
} Msg; } Msg;
struct struct
{ {
struct
{
unsigned StartHour; // Day starts at this hour
unsigned EndHour; // Day ends at this hour
unsigned MinutesPerInterval; // Number of minutes per interval
unsigned HoursPerDay; // From start hour to end hour
unsigned SecondsPerInterval;
unsigned IntervalsPerHour;
unsigned IntervalsPerDay;
unsigned IntervalsBeforeStartHour;
} Config;
TT_TimeTableType_t Type; TT_TimeTableType_t Type;
unsigned Weekday; unsigned Weekday;
unsigned Interval; unsigned Interval;

View File

@ -15565,23 +15565,23 @@ const char *Txt_In_the_year_X_of_the_degree_Y_already_existed_a_course_with_the_
const char *Txt_Incomplete_timetable_for_lack_of_space = const char *Txt_Incomplete_timetable_for_lack_of_space =
#if L==1 #if L==1
"Horari incomplet per falta d'espai"; "Horari incomplet per falta d'espai.";
#elif L==2 #elif L==2
"Unvollständige Studenplan für Platzmangel"; "Unvollständige Studenplan für Platzmangel.";
#elif L==3 #elif L==3
"Incomplete timetable for lack of space"; "Incomplete timetable for lack of space.";
#elif L==4 #elif L==4
"Horario incompleto por falta de espacio"; "Horario incompleto por falta de espacio.";
#elif L==5 #elif L==5
"Horaire incomplète par manque de place"; "Horaire incomplète par manque de place.";
#elif L==6 #elif L==6
"Horario incompleto por falta de espacio"; // Okoteve traducción "Horario incompleto por falta de espacio."; // Okoteve traducción
#elif L==7 #elif L==7
"Orario incompleto per mancanza di spazio"; "Orario incompleto per mancanza di spazio.";
#elif L==8 #elif L==8
"Niekompletne harmonogram brak miejsca"; "Niekompletne harmonogram brak miejsca.";
#elif L==9 #elif L==9
"Horário incompleto por falta de espaço"; "Horário incompleto por falta de espaço.";
#endif #endif
const char *Txt_Increase_level_of_X = // Warning: it is very important to include %s in the following sentences const char *Txt_Increase_level_of_X = // Warning: it is very important to include %s in the following sentences

View File

@ -54,18 +54,14 @@ extern struct Globals Gbl;
#define TT_MINUTES_PER_HOUR 60 // Number of minutes in 1 hour #define TT_MINUTES_PER_HOUR 60 // Number of minutes in 1 hour
#define TT_SECONDS_PER_MINUTE 60 // Number of seconds in 1 minute #define TT_SECONDS_PER_MINUTE 60 // Number of seconds in 1 minute
/*
#define TT_START_HOUR 6 // Day starts at 6:00 #define TT_MIN_START_HOUR 0 // Day starts at this hour
#define TT_END_HOUR 24 // Day ends at 24:00 #define TT_MAX_END_HOUR 24 // Day ends at this hour
#define TT_HOURS_PER_DAY (TT_END_HOUR - TT_START_HOUR) // From 6:00 to 24:00 #define TT_MIN_MINUTES_PER_INTERVAL 5
#define TT_MAX_HOURS_PER_DAY (TT_MAX_END_HOUR - TT_MIN_START_HOUR)
#define TT_MINUTES_PER_INTERVAL 5 #define TT_MAX_INTERVALS_PER_HOUR (TT_MINUTES_PER_HOUR / TT_MIN_MINUTES_PER_INTERVAL)
#define TT_SECONDS_PER_INTERVAL (TT_MINUTES_PER_INTERVAL * TT_SECONDS_PER_MINUTE) #define TT_MAX_INTERVALS_PER_DAY (TT_MAX_INTERVALS_PER_HOUR * TT_MAX_HOURS_PER_DAY)
*/
#define TT_INTERVALS_PER_HOUR (TT_MINUTES_PER_HOUR / TT_MINUTES_PER_INTERVAL)
#define TT_INTERVALS_PER_DAY (TT_INTERVALS_PER_HOUR * TT_HOURS_PER_DAY)
#define TT_INTERVALS_BEFORE_START_HOUR (TT_INTERVALS_PER_HOUR * TT_START_HOUR)
#define TT_MAX_COLUMNS_PER_CELL 3 // Maximum number of items (i.e. classes) in a timetable cell (1, 2, 3 or 4) #define TT_MAX_COLUMNS_PER_CELL 3 // Maximum number of items (i.e. classes) in a timetable cell (1, 2, 3 or 4)
#define TT_NUM_MINICOLUMNS_PER_DAY 6 // Least common multiple of 1,2,3,...,TT_MAX_COLUMNS_PER_CELL #define TT_NUM_MINICOLUMNS_PER_DAY 6 // Least common multiple of 1,2,3,...,TT_MAX_COLUMNS_PER_CELL
@ -105,18 +101,21 @@ struct TimeTableColumn
char Group[Grp_MAX_BYTES_GROUP_NAME + 1]; char Group[Grp_MAX_BYTES_GROUP_NAME + 1];
}; };
struct struct TimeTableCell
{ {
unsigned NumColumns; unsigned NumColumns;
struct TimeTableColumn Columns[TT_MAX_COLUMNS_PER_CELL]; struct TimeTableColumn Columns[TT_MAX_COLUMNS_PER_CELL];
} TT_TimeTable[TT_DAYS_PER_WEEK][TT_INTERVALS_PER_DAY]; };
bool TimeTableHoursChecked[TT_INTERVALS_PER_DAY]; struct TimeTableCell *TT_TimeTable[TT_DAYS_PER_WEEK];
/*****************************************************************************/ /*****************************************************************************/
/***************************** Internal prototypes **************************/ /***************************** Internal prototypes **************************/
/*****************************************************************************/ /*****************************************************************************/
static void TT_TimeTableConstructor (void);
static void TT_TimeTableDestructor (void);
static void TT_ShowTimeTableGrpsSelected (void); static void TT_ShowTimeTableGrpsSelected (void);
static void TT_GetParamsTimeTable (void); static void TT_GetParamsTimeTable (void);
static void TT_PutContextualIcons (void); static void TT_PutContextualIcons (void);
@ -127,18 +126,69 @@ static void TT_PutIconToViewMyTT (void);
static void TT_WriteCrsTimeTableIntoDB (long CrsCod); static void TT_WriteCrsTimeTableIntoDB (long CrsCod);
static void TT_WriteTutTimeTableIntoDB (long UsrCod); static void TT_WriteTutTimeTableIntoDB (long UsrCod);
static void TT_CreatTimeTableFromDB (long UsrCod); static void TT_FillTimeTableFromDB (long UsrCod);
static void TT_ModifTimeTable (void); static void TT_ModifTimeTable (void);
static void TT_DrawTimeTable (void); static void TT_DrawTimeTable (void);
static void TT_TimeTableDrawAdjustRow (void); static void TT_TimeTableDrawAdjustRow (void);
static void TT_TimeTableDrawDaysCells (void); static void TT_TimeTableDrawDaysCells (void);
static void TT_TimeTableDrawHourCell (unsigned Hour,unsigned Min,const char *Align); static void TT_TimeTableDrawHourCell (unsigned Hour,unsigned Min,const char *Align);
static unsigned TT_TimeTableCalculateColsToDraw (unsigned Weekday,unsigned Interval); static unsigned TT_CalculateColsToDrawInCell (bool TopCall,
unsigned Weekday,unsigned Interval);
static void TT_DrawCellAlignTimeTable (void); static void TT_DrawCellAlignTimeTable (void);
static void TT_TimeTableDrawCell (unsigned Weekday,unsigned Interval,unsigned Column,unsigned ColSpan, static void TT_TimeTableDrawCell (unsigned Weekday,unsigned Interval,unsigned Column,unsigned ColSpan,
long CrsCod,TT_IntervalType_t IntervalType,TT_ClassType_t ClassType, long CrsCod,TT_IntervalType_t IntervalType,TT_ClassType_t ClassType,
unsigned DurationNumIntervals,char *Group,long GrpCod,char *Place); unsigned DurationNumIntervals,char *Group,long GrpCod,char *Place);
/*****************************************************************************/
/******************** Create internal timetable in memory ********************/
/*****************************************************************************/
static void TT_TimeTableConstructor (void)
{
unsigned Weekday;
/***** Configure timetable *****/
Gbl.TimeTable.Config.StartHour = 6; // Day starts at this hour
Gbl.TimeTable.Config.EndHour = 24; // Day ends at this hour
Gbl.TimeTable.Config.MinutesPerInterval = 15; // Number of minutes per interval
Gbl.TimeTable.Config.HoursPerDay = Gbl.TimeTable.Config.EndHour -
Gbl.TimeTable.Config.StartHour; // From start hour to end hour
Gbl.TimeTable.Config.SecondsPerInterval = Gbl.TimeTable.Config.MinutesPerInterval *
TT_SECONDS_PER_MINUTE;
Gbl.TimeTable.Config.IntervalsPerHour = TT_MINUTES_PER_HOUR /
Gbl.TimeTable.Config.MinutesPerInterval;
Gbl.TimeTable.Config.IntervalsPerDay = Gbl.TimeTable.Config.IntervalsPerHour *
Gbl.TimeTable.Config.HoursPerDay;
Gbl.TimeTable.Config.IntervalsBeforeStartHour = Gbl.TimeTable.Config.IntervalsPerHour *
Gbl.TimeTable.Config.StartHour;
/***** Allocate memory for timetable *****/
for (Weekday = 0;
Weekday < TT_DAYS_PER_WEEK;
Weekday++)
if ((TT_TimeTable[Weekday] = (struct TimeTableCell *)
malloc (Gbl.TimeTable.Config.IntervalsPerDay *
sizeof (struct TimeTableCell))) == NULL)
Lay_ShowErrorAndExit ("Error allocating memory for timetable.");
}
/*****************************************************************************/
/******************** Destroy internal timetable in memory *******************/
/*****************************************************************************/
static void TT_TimeTableDestructor (void)
{
unsigned Weekday;
/***** Free memory for timetable *****/
for (Weekday = 0;
Weekday < TT_DAYS_PER_WEEK;
Weekday++)
free ((void *) TT_TimeTable[Weekday]);
}
/*****************************************************************************/ /*****************************************************************************/
/*********** Show whether only my groups or all groups are shown *************/ /*********** Show whether only my groups or all groups are shown *************/
/*****************************************************************************/ /*****************************************************************************/
@ -182,10 +232,10 @@ static void TT_GetParamsTimeTable (void)
/***** Get hour *****/ /***** Get hour *****/
Gbl.TimeTable.Interval = (unsigned) Gbl.TimeTable.Interval = (unsigned)
Par_GetParToUnsignedLong ("ModTTHour", Par_GetParToUnsignedLong ("ModTTHour",
0, 0,
TT_INTERVALS_PER_DAY - 1, Gbl.TimeTable.Config.IntervalsPerDay - 1,
0); 0);
/***** Get number of column *****/ /***** Get number of column *****/
Gbl.TimeTable.Column = (unsigned) Gbl.TimeTable.Column = (unsigned)
@ -208,8 +258,8 @@ static void TT_GetParamsTimeTable (void)
Par_GetParToText ("ModTTDur",StrDuration,TT_MAX_BYTES_STR_DURATION); Par_GetParToText ("ModTTDur",StrDuration,TT_MAX_BYTES_STR_DURATION);
if (sscanf (StrDuration,"%u:%u",&Hours,&Minutes) != 2) if (sscanf (StrDuration,"%u:%u",&Hours,&Minutes) != 2)
Lay_ShowErrorAndExit ("Duration is missing."); Lay_ShowErrorAndExit ("Duration is missing.");
Gbl.TimeTable.DurationNumIntervals = Hours * TT_INTERVALS_PER_HOUR + Gbl.TimeTable.DurationNumIntervals = Hours * Gbl.TimeTable.Config.IntervalsPerHour +
Minutes / TT_MINUTES_PER_INTERVAL; Minutes / Gbl.TimeTable.Config.MinutesPerInterval;
/***** Get group code *****/ /***** Get group code *****/
Gbl.TimeTable.GrpCod = Par_GetParToLong ("ModTTGrpCod"); Gbl.TimeTable.GrpCod = Par_GetParToLong ("ModTTGrpCod");
@ -424,8 +474,11 @@ static void TT_PutIconToViewMyTT (void)
void TT_ShowTimeTable (long UsrCod) void TT_ShowTimeTable (long UsrCod)
{ {
/***** Create an internal table with the timetable from database *****/ /***** Create internal timetable in memory *****/
TT_CreatTimeTableFromDB (UsrCod); TT_TimeTableConstructor ();
/***** Fill internal timetable with the timetable from database *****/
TT_FillTimeTableFromDB (UsrCod);
/***** If timetable must be modified... *****/ /***** If timetable must be modified... *****/
if (Gbl.Action.Act == ActChgCrsTT || if (Gbl.Action.Act == ActChgCrsTT ||
@ -451,11 +504,14 @@ void TT_ShowTimeTable (long UsrCod)
} }
/* Get a new table from database */ /* Get a new table from database */
TT_CreatTimeTableFromDB (UsrCod); TT_FillTimeTableFromDB (UsrCod);
} }
/***** Draw timetable *****/ /***** Draw timetable *****/
TT_DrawTimeTable (); TT_DrawTimeTable ();
/***** Free internal timetable in memory *****/
TT_TimeTableDestructor ();
} }
/*****************************************************************************/ /*****************************************************************************/
@ -482,11 +538,11 @@ static void TT_WriteCrsTimeTableIntoDB (long CrsCod)
for (Weekday = 0; for (Weekday = 0;
Weekday < TT_DAYS_PER_WEEK; Weekday < TT_DAYS_PER_WEEK;
Weekday++) Weekday++)
for (Interval = 0, Hour = TT_START_HOUR, Min = 0; for (Interval = 0, Hour = Gbl.TimeTable.Config.StartHour, Min = 0;
Interval < TT_INTERVALS_PER_DAY; Interval < Gbl.TimeTable.Config.IntervalsPerDay;
Interval++, Interval++,
Hour += (Min + TT_MINUTES_PER_INTERVAL) / TT_SECONDS_PER_MINUTE, Hour += (Min + Gbl.TimeTable.Config.MinutesPerInterval) / TT_SECONDS_PER_MINUTE,
Min = (Min + TT_MINUTES_PER_INTERVAL) % TT_SECONDS_PER_MINUTE) Min = (Min + Gbl.TimeTable.Config.MinutesPerInterval) % TT_SECONDS_PER_MINUTE)
for (Column = 0; for (Column = 0;
Column < TT_MAX_COLUMNS_PER_CELL; Column < TT_MAX_COLUMNS_PER_CELL;
Column++) Column++)
@ -503,7 +559,8 @@ static void TT_WriteCrsTimeTableIntoDB (long CrsCod)
TT_TimeTable[Weekday][Interval].Columns[Column].GrpCod, TT_TimeTable[Weekday][Interval].Columns[Column].GrpCod,
Weekday, Weekday,
Hour,Min, Hour,Min,
TT_TimeTable[Weekday][Interval].Columns[Column].DurationNumIntervals * TT_SECONDS_PER_INTERVAL, TT_TimeTable[Weekday][Interval].Columns[Column].DurationNumIntervals *
Gbl.TimeTable.Config.SecondsPerInterval,
TimeTableStrsClassTypeDB[TT_TimeTable[Weekday][Interval].Columns[Column].ClassType], TimeTableStrsClassTypeDB[TT_TimeTable[Weekday][Interval].Columns[Column].ClassType],
TT_TimeTable[Weekday][Interval].Columns[Column].Place, TT_TimeTable[Weekday][Interval].Columns[Column].Place,
TT_TimeTable[Weekday][Interval].Columns[Column].Group); TT_TimeTable[Weekday][Interval].Columns[Column].Group);
@ -534,11 +591,11 @@ static void TT_WriteTutTimeTableIntoDB (long UsrCod)
for (Weekday = 0; for (Weekday = 0;
Weekday < TT_DAYS_PER_WEEK; Weekday < TT_DAYS_PER_WEEK;
Weekday++) Weekday++)
for (Interval = 0, Hour = TT_START_HOUR, Min = 0; for (Interval = 0, Hour = Gbl.TimeTable.Config.StartHour, Min = 0;
Interval < TT_INTERVALS_PER_DAY; Interval < Gbl.TimeTable.Config.IntervalsPerDay;
Interval++, Interval++,
Hour += (Min + TT_MINUTES_PER_INTERVAL) / TT_SECONDS_PER_MINUTE, Hour += (Min + Gbl.TimeTable.Config.MinutesPerInterval) / TT_SECONDS_PER_MINUTE,
Min = (Min + TT_MINUTES_PER_INTERVAL) % TT_SECONDS_PER_MINUTE) Min = (Min + Gbl.TimeTable.Config.MinutesPerInterval) % TT_SECONDS_PER_MINUTE)
for (Column = 0; for (Column = 0;
Column < TT_MAX_COLUMNS_PER_CELL; Column < TT_MAX_COLUMNS_PER_CELL;
Column++) Column++)
@ -552,7 +609,8 @@ static void TT_WriteTutTimeTableIntoDB (long UsrCod)
UsrCod, UsrCod,
Weekday, Weekday,
Hour,Min, Hour,Min,
TT_TimeTable[Weekday][Interval].Columns[Column].DurationNumIntervals * TT_SECONDS_PER_INTERVAL, TT_TimeTable[Weekday][Interval].Columns[Column].DurationNumIntervals *
Gbl.TimeTable.Config.SecondsPerInterval,
TT_TimeTable[Weekday][Interval].Columns[Column].Place); TT_TimeTable[Weekday][Interval].Columns[Column].Place);
DB_QueryINSERT (Query,"can not create office timetable"); DB_QueryINSERT (Query,"can not create office timetable");
} }
@ -562,7 +620,7 @@ static void TT_WriteTutTimeTableIntoDB (long UsrCod)
/********** Create an internal table with timetable from database ************/ /********** Create an internal table with timetable from database ************/
/*****************************************************************************/ /*****************************************************************************/
static void TT_CreatTimeTableFromDB (long UsrCod) static void TT_FillTimeTableFromDB (long UsrCod)
{ {
extern const char *Txt_Incomplete_timetable_for_lack_of_space; extern const char *Txt_Incomplete_timetable_for_lack_of_space;
char Query[4096]; char Query[4096];
@ -588,7 +646,7 @@ static void TT_CreatTimeTableFromDB (long UsrCod)
Weekday < TT_DAYS_PER_WEEK; Weekday < TT_DAYS_PER_WEEK;
Weekday++) Weekday++)
for (Interval = 0; for (Interval = 0;
Interval < TT_INTERVALS_PER_DAY; Interval < Gbl.TimeTable.Config.IntervalsPerDay;
Interval++) Interval++)
{ {
TT_TimeTable[Weekday][Interval].NumColumns = 0; TT_TimeTable[Weekday][Interval].NumColumns = 0;
@ -770,16 +828,16 @@ static void TT_CreatTimeTableFromDB (long UsrCod)
--> StartTime in number of intervals */ --> StartTime in number of intervals */
if (sscanf (row[1],"%u",&Seconds) != 1) if (sscanf (row[1],"%u",&Seconds) != 1)
Lay_ShowErrorAndExit ("Wrong start time in timetable."); Lay_ShowErrorAndExit ("Wrong start time in timetable.");
Interval = Seconds / TT_SECONDS_PER_INTERVAL; Interval = Seconds / Gbl.TimeTable.Config.SecondsPerInterval;
if (Interval < TT_INTERVALS_BEFORE_START_HOUR) if (Interval < Gbl.TimeTable.Config.IntervalsBeforeStartHour)
Lay_ShowErrorAndExit ("Wrong start time in timetable."); Lay_ShowErrorAndExit ("Wrong start time in timetable.");
Interval -= TT_INTERVALS_BEFORE_START_HOUR; Interval -= Gbl.TimeTable.Config.IntervalsBeforeStartHour;
/* Duration formatted as seconds (row[2]) /* Duration formatted as seconds (row[2])
--> Duration in number of intervals */ --> Duration in number of intervals */
if (sscanf (row[2],"%u",&Seconds) != 1) if (sscanf (row[2],"%u",&Seconds) != 1)
Lay_ShowErrorAndExit ("Wrong duration in timetable."); Lay_ShowErrorAndExit ("Wrong duration in timetable.");
DurationNumIntervals = Seconds / TT_SECONDS_PER_INTERVAL; DurationNumIntervals = Seconds / Gbl.TimeTable.Config.SecondsPerInterval;
/* Type of class (row[4]) */ /* Type of class (row[4]) */
switch (Gbl.TimeTable.Type) switch (Gbl.TimeTable.Type)
@ -824,7 +882,7 @@ static void TT_CreatTimeTableFromDB (long UsrCod)
TimeTableHasSpaceForThisClass = true; TimeTableHasSpaceForThisClass = true;
for (I = Interval + 1; for (I = Interval + 1;
I < Interval + DurationNumIntervals && I < Interval + DurationNumIntervals &&
I < TT_INTERVALS_PER_DAY; I < Gbl.TimeTable.Config.IntervalsPerDay;
I++) I++)
if (TT_TimeTable[Weekday][I].Columns[FirstFreeColumn].IntervalType != TT_FREE_INTERVAL) if (TT_TimeTable[Weekday][I].Columns[FirstFreeColumn].IntervalType != TT_FREE_INTERVAL)
{ {
@ -839,7 +897,7 @@ static void TT_CreatTimeTableFromDB (long UsrCod)
TT_TimeTable[Weekday][Interval].Columns[FirstFreeColumn].IntervalType = TT_FIRST_INTERVAL; TT_TimeTable[Weekday][Interval].Columns[FirstFreeColumn].IntervalType = TT_FIRST_INTERVAL;
for (I = Interval + 1; for (I = Interval + 1;
I < Interval + DurationNumIntervals && I < Interval + DurationNumIntervals &&
I < TT_INTERVALS_PER_DAY; I < Gbl.TimeTable.Config.IntervalsPerDay;
I++) I++)
{ {
TT_TimeTable[Weekday][I].Columns[FirstFreeColumn].IntervalType = TT_NEXT_INTERVAL; TT_TimeTable[Weekday][I].Columns[FirstFreeColumn].IntervalType = TT_NEXT_INTERVAL;
@ -932,7 +990,6 @@ static void TT_DrawTimeTable (void)
unsigned Weekday; // Day of week unsigned Weekday; // Day of week
unsigned Interval; unsigned Interval;
unsigned Min; unsigned Min;
unsigned I;
unsigned Column; unsigned Column;
unsigned ColumnsToDraw; unsigned ColumnsToDraw;
unsigned ColumnsToDrawIncludingExtraColumn; unsigned ColumnsToDrawIncludingExtraColumn;
@ -964,7 +1021,8 @@ static void TT_DrawTimeTable (void)
" style=\"width:%u%%;\">" " style=\"width:%u%%;\">"
"%02u" "%02u"
"</td>", "</td>",
TT_PERCENT_WIDTH_OF_AN_HOUR_COLUMN,TT_START_HOUR); TT_PERCENT_WIDTH_OF_AN_HOUR_COLUMN,
Gbl.TimeTable.Config.StartHour);
TT_DrawCellAlignTimeTable (); TT_DrawCellAlignTimeTable ();
TT_TimeTableDrawDaysCells (); TT_TimeTableDrawDaysCells ();
TT_DrawCellAlignTimeTable (); TT_DrawCellAlignTimeTable ();
@ -974,7 +1032,7 @@ static void TT_DrawTimeTable (void)
"</td>" "</td>"
"</tr>", "</tr>",
TT_PERCENT_WIDTH_OF_AN_HOUR_COLUMN, TT_PERCENT_WIDTH_OF_AN_HOUR_COLUMN,
TT_START_HOUR); Gbl.TimeTable.Config.StartHour);
/***** Get list of groups types and groups in this course *****/ /***** Get list of groups types and groups in this course *****/
if (Gbl.Action.Act == ActEdiCrsTT || if (Gbl.Action.Act == ActEdiCrsTT ||
@ -982,15 +1040,18 @@ static void TT_DrawTimeTable (void)
Grp_GetListGrpTypesAndGrpsInThisCrs (Grp_ONLY_GROUP_TYPES_WITH_GROUPS); Grp_GetListGrpTypesAndGrpsInThisCrs (Grp_ONLY_GROUP_TYPES_WITH_GROUPS);
/***** Write the table row by row *****/ /***** Write the table row by row *****/
for (Interval = 0, Min = TT_MINUTES_PER_INTERVAL; for (Interval = 0, Min = Gbl.TimeTable.Config.MinutesPerInterval;
Interval < TT_INTERVALS_PER_DAY; Interval < Gbl.TimeTable.Config.IntervalsPerDay;
Interval++, Min = (Min + TT_MINUTES_PER_INTERVAL) % TT_SECONDS_PER_MINUTE) Interval++,
Min = (Min + Gbl.TimeTable.Config.MinutesPerInterval) %
TT_SECONDS_PER_MINUTE)
{ {
fprintf (Gbl.F.Out,"<tr>"); fprintf (Gbl.F.Out,"<tr>");
/* Left hour:minutes cell */ /* Left hour:minutes cell */
if (Interval % 2) if (Interval % 2)
TT_TimeTableDrawHourCell (TT_START_HOUR + (Interval + 2) / TT_INTERVALS_PER_HOUR, TT_TimeTableDrawHourCell (Gbl.TimeTable.Config.StartHour +
(Interval + 2) / Gbl.TimeTable.Config.IntervalsPerHour,
Min, Min,
"RIGHT_MIDDLE"); "RIGHT_MIDDLE");
@ -1010,11 +1071,8 @@ static void TT_DrawTimeTable (void)
/* Check how many colums are needed. /* Check how many colums are needed.
For each item (class) in this hour from left to right, For each item (class) in this hour from left to right,
we must check the maximum of columns */ we must check the maximum of columns */
for (I = 0; ColumnsToDraw = TT_CalculateColsToDrawInCell (true, // Top call, non recursive
I < TT_INTERVALS_PER_DAY; Weekday,Interval);
I++)
TimeTableHoursChecked[I] = false;
ColumnsToDraw = TT_TimeTableCalculateColsToDraw (Weekday,Interval);
if (!Editing && ColumnsToDraw == 0) if (!Editing && ColumnsToDraw == 0)
ColumnsToDraw = 1; ColumnsToDraw = 1;
ColumnsToDrawIncludingExtraColumn = ColumnsToDraw; ColumnsToDrawIncludingExtraColumn = ColumnsToDraw;
@ -1057,7 +1115,8 @@ static void TT_DrawTimeTable (void)
/* Right hour:minutes cell */ /* Right hour:minutes cell */
if (Interval % 2) if (Interval % 2)
TT_TimeTableDrawHourCell (TT_START_HOUR + (Interval + 2) / TT_INTERVALS_PER_HOUR, TT_TimeTableDrawHourCell (Gbl.TimeTable.Config.StartHour +
(Interval + 2) / Gbl.TimeTable.Config.IntervalsPerHour,
Min, Min,
"LEFT_MIDDLE"); "LEFT_MIDDLE");
@ -1168,19 +1227,30 @@ static void TT_TimeTableDrawHourCell (unsigned Hour,unsigned Min,const char *Ali
/**** Calculate recursively number of columns to draw for a day and hour *****/ /**** Calculate recursively number of columns to draw for a day and hour *****/
/*****************************************************************************/ /*****************************************************************************/
static unsigned TT_TimeTableCalculateColsToDraw (unsigned Weekday,unsigned Interval) static unsigned TT_CalculateColsToDrawInCell (bool TopCall,
unsigned Weekday,unsigned Interval)
{ {
unsigned ColumnsToDraw; unsigned ColumnsToDraw;
unsigned Column; unsigned Column;
unsigned I; unsigned I;
unsigned FirstHour; unsigned FirstHour;
unsigned Cols; unsigned Cols;
static bool *TT_IntervalsChecked;
if (TopCall) // Top call, non recursive call
{
/****** Allocate space to store list of intervals already checked
and initialize to false by using calloc *****/
if ((TT_IntervalsChecked = (bool *) calloc (Gbl.TimeTable.Config.IntervalsPerDay,
sizeof (bool))) == NULL)
Lay_ShowErrorAndExit ("Error allocating memory for timetable.");
}
ColumnsToDraw = TT_TimeTable[Weekday][Interval].NumColumns; ColumnsToDraw = TT_TimeTable[Weekday][Interval].NumColumns;
if (!TimeTableHoursChecked[Interval]) if (!TT_IntervalsChecked[Interval])
{ {
TimeTableHoursChecked[Interval] = true; TT_IntervalsChecked[Interval] = true;
for (Column = 0; for (Column = 0;
Column < TT_MAX_COLUMNS_PER_CELL; Column < TT_MAX_COLUMNS_PER_CELL;
Column++) Column++)
@ -1194,9 +1264,10 @@ static unsigned TT_TimeTableCalculateColsToDraw (unsigned Weekday,unsigned Inter
for (I = Interval + 1; for (I = Interval + 1;
I < Interval + TT_TimeTable[Weekday][Interval].Columns[Column].DurationNumIntervals; I < Interval + TT_TimeTable[Weekday][Interval].Columns[Column].DurationNumIntervals;
I++) I++)
if (!TimeTableHoursChecked[I]) if (!TT_IntervalsChecked[I])
{ {
Cols = TT_TimeTableCalculateColsToDraw (Weekday,I); Cols = TT_CalculateColsToDrawInCell (false, // Recursive call
Weekday,I);
if (Cols > ColumnsToDraw) if (Cols > ColumnsToDraw)
ColumnsToDraw = Cols; ColumnsToDraw = Cols;
} }
@ -1206,13 +1277,15 @@ static unsigned TT_TimeTableCalculateColsToDraw (unsigned Weekday,unsigned Inter
for (FirstHour = Interval; for (FirstHour = Interval;
TT_TimeTable[Weekday][FirstHour].Columns[Column].IntervalType == TT_NEXT_INTERVAL; TT_TimeTable[Weekday][FirstHour].Columns[Column].IntervalType == TT_NEXT_INTERVAL;
FirstHour--); FirstHour--);
/* Check from first hour to last hour searching maximum number of columns */
/* Check from first hour to last hour searching maximum number of columns */
for (I = FirstHour; for (I = FirstHour;
I < FirstHour + TT_TimeTable[Weekday][FirstHour].Columns[Column].DurationNumIntervals; I < FirstHour + TT_TimeTable[Weekday][FirstHour].Columns[Column].DurationNumIntervals;
I++) I++)
if (!TimeTableHoursChecked[I]) if (!TT_IntervalsChecked[I])
{ {
Cols = TT_TimeTableCalculateColsToDraw (Weekday,I); Cols = TT_CalculateColsToDrawInCell (false, // Recursive call
Weekday,I);
if (Cols > ColumnsToDraw) if (Cols > ColumnsToDraw)
ColumnsToDraw = Cols; ColumnsToDraw = Cols;
} }
@ -1220,6 +1293,11 @@ static unsigned TT_TimeTableCalculateColsToDraw (unsigned Weekday,unsigned Inter
} }
} }
} }
if (TopCall) // Top call, non recursive call
/****** Free space used by list of intervals already checked *****/
free ((void *) TT_IntervalsChecked);
return ColumnsToDraw; return ColumnsToDraw;
} }
@ -1357,8 +1435,9 @@ static void TT_TimeTableDrawCell (unsigned Weekday,unsigned Interval,unsigned Co
/***** Type of class and duration *****/ /***** Type of class and duration *****/
fprintf (Gbl.F.Out,"%s (%u:%02u h)", fprintf (Gbl.F.Out,"%s (%u:%02u h)",
Txt_TIMETABLE_CLASS_TYPES[ClassType], Txt_TIMETABLE_CLASS_TYPES[ClassType],
(DurationNumIntervals / TT_INTERVALS_PER_HOUR), // Hours (DurationNumIntervals / Gbl.TimeTable.Config.IntervalsPerHour), // Hours
(DurationNumIntervals % TT_INTERVALS_PER_HOUR) * TT_MINUTES_PER_INTERVAL); // Minutes (DurationNumIntervals % Gbl.TimeTable.Config.IntervalsPerHour) *
Gbl.TimeTable.Config.MinutesPerInterval); // Minutes
/***** Group *****/ /***** Group *****/
if (TimeTableView == TT_CRS_SHOW) if (TimeTableView == TT_CRS_SHOW)
@ -1411,16 +1490,17 @@ static void TT_TimeTableDrawCell (unsigned Weekday,unsigned Interval,unsigned Co
{ {
fprintf (Gbl.F.Out,"<input type=\"hidden\" name=\"ModTTDur\" value=\""); fprintf (Gbl.F.Out,"<input type=\"hidden\" name=\"ModTTDur\" value=\"");
for (I = Interval + 1; for (I = Interval + 1;
I < TT_INTERVALS_PER_DAY; I < Gbl.TimeTable.Config.IntervalsPerDay;
I++) I++)
if (TT_TimeTable[Weekday][I].NumColumns == TT_MAX_COLUMNS_PER_CELL) if (TT_TimeTable[Weekday][I].NumColumns == TT_MAX_COLUMNS_PER_CELL)
break; break;
MaxDuration = I - Interval; MaxDuration = I - Interval;
Dur = (MaxDuration >= TT_INTERVALS_PER_HOUR) ? TT_INTERVALS_PER_HOUR : // MaxDuration >= 1h ==> Dur = 1h Dur = (MaxDuration >= Gbl.TimeTable.Config.IntervalsPerHour) ? Gbl.TimeTable.Config.IntervalsPerHour : // MaxDuration >= 1h ==> Dur = 1h
MaxDuration; // MaxDuration < 1h ==> Dur = MaxDuration MaxDuration; // MaxDuration < 1h ==> Dur = MaxDuration
fprintf (Gbl.F.Out,"%u:%02u h\" />", fprintf (Gbl.F.Out,"%u:%02u h\" />",
(Dur / TT_INTERVALS_PER_HOUR), // Hours (Dur / Gbl.TimeTable.Config.IntervalsPerHour), // Hours
(Dur % TT_INTERVALS_PER_HOUR) * TT_MINUTES_PER_INTERVAL); // Minutes (Dur % Gbl.TimeTable.Config.IntervalsPerHour) *
Gbl.TimeTable.Config.MinutesPerInterval); // Minutes
} }
else else
{ {
@ -1429,7 +1509,7 @@ static void TT_TimeTableDrawCell (unsigned Weekday,unsigned Interval,unsigned Co
" onchange=\"document.getElementById('%s').submit();\">", " onchange=\"document.getElementById('%s').submit();\">",
Gbl.Form.Id); Gbl.Form.Id);
for (I = Interval + TT_TimeTable[Weekday][Interval].Columns[Column].DurationNumIntervals; for (I = Interval + TT_TimeTable[Weekday][Interval].Columns[Column].DurationNumIntervals;
I < TT_INTERVALS_PER_DAY; I < Gbl.TimeTable.Config.IntervalsPerDay;
I++) I++)
if (TT_TimeTable[Weekday][I].NumColumns == TT_MAX_COLUMNS_PER_CELL) if (TT_TimeTable[Weekday][I].NumColumns == TT_MAX_COLUMNS_PER_CELL)
break; break;
@ -1444,8 +1524,9 @@ static void TT_TimeTableDrawCell (unsigned Weekday,unsigned Interval,unsigned Co
if (Dur == DurationNumIntervals) if (Dur == DurationNumIntervals)
fprintf (Gbl.F.Out," selected=\"selected\""); fprintf (Gbl.F.Out," selected=\"selected\"");
fprintf (Gbl.F.Out,">%u:%02u h</option>", fprintf (Gbl.F.Out,">%u:%02u h</option>",
(Dur / TT_INTERVALS_PER_HOUR), // Hours (Dur / Gbl.TimeTable.Config.IntervalsPerHour), // Hours
(Dur % TT_INTERVALS_PER_HOUR) * TT_MINUTES_PER_INTERVAL); // Minutes (Dur % Gbl.TimeTable.Config.IntervalsPerHour) *
Gbl.TimeTable.Config.MinutesPerInterval); // Minutes
} }
fprintf (Gbl.F.Out,"</select>"); fprintf (Gbl.F.Out,"</select>");