2014-12-01 23:55:08 +01:00
|
|
|
|
// swad_timetable.c: timetables
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
SWAD (Shared Workspace At a Distance),
|
|
|
|
|
is a web platform developed at the University of Granada (Spain),
|
|
|
|
|
and used to support university teaching.
|
|
|
|
|
|
|
|
|
|
This file is part of SWAD core.
|
2018-04-24 13:21:53 +02:00
|
|
|
|
Copyright (C) 1999-2018 Antonio Ca<EFBFBD>as Vargas
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU Affero General Public License as
|
|
|
|
|
published by the Free Software Foundation, either version 3 of the
|
|
|
|
|
License, or (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU Affero General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/*********************************** Headers *********************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include <linux/stddef.h> // For NULL
|
|
|
|
|
#include <stdio.h> // For fprintf, etc.
|
2017-04-27 10:15:07 +02:00
|
|
|
|
#include <stdlib.h> // For malloc, calloc, free
|
2014-12-01 23:55:08 +01:00
|
|
|
|
#include <string.h> // For string functions
|
|
|
|
|
|
2017-06-10 21:38:10 +02:00
|
|
|
|
#include "swad_box.h"
|
2015-12-01 00:38:22 +01:00
|
|
|
|
#include "swad_calendar.h"
|
2014-12-01 23:55:08 +01:00
|
|
|
|
#include "swad_database.h"
|
|
|
|
|
#include "swad_global.h"
|
|
|
|
|
#include "swad_parameter.h"
|
|
|
|
|
#include "swad_text.h"
|
|
|
|
|
#include "swad_timetable.h"
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/*************************** External constants ******************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/************** External global variables from others modules ****************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
extern struct Globals Gbl;
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
2017-04-25 14:48:47 +02:00
|
|
|
|
/************************ Internal constants and types ***********************/
|
2014-12-01 23:55:08 +01:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-04-24 21:12:53 +02:00
|
|
|
|
#define TT_DAYS_PER_WEEK 7 // Seven days per week
|
|
|
|
|
|
|
|
|
|
#define TT_MINUTES_PER_HOUR 60 // Number of minutes in 1 hour
|
|
|
|
|
#define TT_SECONDS_PER_MINUTE 60 // Number of seconds in 1 minute
|
2017-04-25 21:20:19 +02:00
|
|
|
|
#define TT_SECONDS_PER_HOUR (TT_SECONDS_PER_MINUTE * TT_MINUTES_PER_HOUR) // Number of seconds in 1 hour
|
2017-04-25 14:48:47 +02:00
|
|
|
|
|
|
|
|
|
#define TT_START_HOUR 6 // Day starts at this hour
|
|
|
|
|
#define TT_END_HOUR 24 // Day ends at this hour
|
|
|
|
|
|
|
|
|
|
#define TT_MIN_MINUTES_PER_INTERVAL 5
|
|
|
|
|
#define TT_MAX_MINUTES_PER_INTERVAL 30
|
|
|
|
|
|
2014-12-01 23:55:08 +01:00
|
|
|
|
#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
|
2017-04-24 21:12:53 +02:00
|
|
|
|
|
2014-12-01 23:55:08 +01:00
|
|
|
|
#define TT_PERCENT_WIDTH_OF_A_MINICOLUMN 2 // Width (%) of each minicolumn
|
2017-01-29 21:41:08 +01:00
|
|
|
|
#define TT_PERCENT_WIDTH_OF_A_DAY (TT_PERCENT_WIDTH_OF_A_MINICOLUMN * TT_NUM_MINICOLUMNS_PER_DAY) // Width (%) of each day
|
2017-04-24 21:12:53 +02:00
|
|
|
|
#define TT_PERCENT_WIDTH_OF_ALL_DAYS (TT_PERCENT_WIDTH_OF_A_DAY * TT_DAYS_PER_WEEK) // Width (%) of all days
|
2017-06-12 14:16:33 +02:00
|
|
|
|
#define TT_PERCENT_WIDTH_OF_A_SEPARATION_COLUMN 1 // Width (%) of left and right columns
|
2017-01-28 15:58:46 +01:00
|
|
|
|
#define TT_PERCENT_WIDTH_OF_AN_HOUR_COLUMN ((100 - TT_PERCENT_WIDTH_OF_ALL_DAYS - TT_PERCENT_WIDTH_OF_A_SEPARATION_COLUMN * 2) / 2) // Width (%) of the separation columns
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
|
|
|
|
#define TT_MAX_BYTES_STR_CLASS_TYPE 256
|
2017-03-08 03:48:23 +01:00
|
|
|
|
#define TT_MAX_BYTES_STR_DURATION 32 // "hh:mm h"
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
2017-04-25 14:48:47 +02:00
|
|
|
|
struct TT_Column
|
|
|
|
|
{
|
|
|
|
|
long CrsCod; // Course code (-1 if no course selected)
|
|
|
|
|
long GrpCod; // Group code (-1 if no group selected)
|
|
|
|
|
TT_IntervalType_t IntervalType;
|
|
|
|
|
TT_ClassType_t ClassType;
|
2017-04-25 21:20:19 +02:00
|
|
|
|
unsigned DurationIntervals;
|
2017-04-25 14:48:47 +02:00
|
|
|
|
char Place[TT_MAX_BYTES_PLACE + 1];
|
|
|
|
|
char Group[Grp_MAX_BYTES_GROUP_NAME + 1];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct TT_Cell
|
|
|
|
|
{
|
|
|
|
|
unsigned NumColumns;
|
|
|
|
|
struct TT_Column Columns[TT_MAX_COLUMNS_PER_CELL];
|
|
|
|
|
};
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/************************* Internal global variables *************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-04-25 14:48:47 +02:00
|
|
|
|
char *TT_ClassTypeDB[TT_NUM_CLASS_TYPES] =
|
2017-04-24 13:00:59 +02:00
|
|
|
|
{
|
|
|
|
|
"free",
|
|
|
|
|
"lecture",
|
|
|
|
|
"practical",
|
|
|
|
|
"tutoring",
|
|
|
|
|
};
|
2017-04-24 13:39:55 +02:00
|
|
|
|
|
2017-04-25 14:48:47 +02:00
|
|
|
|
struct TT_Cell *TT_TimeTable[TT_DAYS_PER_WEEK];
|
2017-04-24 13:39:55 +02:00
|
|
|
|
|
2017-04-25 14:48:47 +02:00
|
|
|
|
/* Possible resolutions of the timetable in minutes */
|
|
|
|
|
#define TT_NUM_RESOLUTIONS 3
|
2017-04-25 21:20:19 +02:00
|
|
|
|
unsigned TT_MinutesPerInterval[TT_NUM_RESOLUTIONS] =
|
2017-04-24 13:39:55 +02:00
|
|
|
|
{
|
2017-04-25 14:48:47 +02:00
|
|
|
|
5, // 5 minutes
|
|
|
|
|
15, // 15 minutes // Use 10 or 15 minutes (15 looks better), never both together
|
|
|
|
|
30, // 30 minutes
|
2017-04-25 11:57:36 +02:00
|
|
|
|
};
|
2017-04-24 13:39:55 +02:00
|
|
|
|
|
2014-12-01 23:55:08 +01:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/***************************** Internal prototypes **************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-04-25 14:48:47 +02:00
|
|
|
|
static void TT_TimeTableConfigureIntervalsAndAllocateTimeTable (void);
|
2017-04-25 21:20:19 +02:00
|
|
|
|
static void TT_FreeTimeTable (void);
|
2017-04-25 11:57:36 +02:00
|
|
|
|
|
2014-12-01 23:55:08 +01:00
|
|
|
|
static void TT_ShowTimeTableGrpsSelected (void);
|
|
|
|
|
static void TT_GetParamsTimeTable (void);
|
2016-03-18 14:07:21 +01:00
|
|
|
|
static void TT_PutContextualIcons (void);
|
2016-11-26 22:07:52 +01:00
|
|
|
|
static void TT_PutFormToSelectWhichGroupsToShow (void);
|
2015-12-01 00:38:22 +01:00
|
|
|
|
|
2016-03-18 14:17:19 +01:00
|
|
|
|
static void TT_PutIconToViewCrsTT (void);
|
|
|
|
|
static void TT_PutIconToViewMyTT (void);
|
|
|
|
|
|
2014-12-01 23:55:08 +01:00
|
|
|
|
static void TT_WriteCrsTimeTableIntoDB (long CrsCod);
|
|
|
|
|
static void TT_WriteTutTimeTableIntoDB (long UsrCod);
|
2017-04-25 11:57:36 +02:00
|
|
|
|
static void TT_FillTimeTableFromDB (long UsrCod);
|
2017-04-25 21:20:19 +02:00
|
|
|
|
static void TT_CalculateRangeCell (unsigned StartTimeSeconds,
|
|
|
|
|
unsigned EndTimeSeconds,
|
|
|
|
|
struct TT_Range *Range);
|
|
|
|
|
static unsigned TT_CalculateMinutesPerInterval (unsigned Seconds);
|
2017-04-25 14:48:47 +02:00
|
|
|
|
|
2014-12-01 23:55:08 +01:00
|
|
|
|
static void TT_ModifTimeTable (void);
|
2016-03-18 14:07:21 +01:00
|
|
|
|
static void TT_DrawTimeTable (void);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
static void TT_TimeTableDrawAdjustRow (void);
|
|
|
|
|
static void TT_TimeTableDrawDaysCells (void);
|
2017-04-24 21:12:53 +02:00
|
|
|
|
static void TT_TimeTableDrawHourCell (unsigned Hour,unsigned Min,const char *Align);
|
2017-04-25 11:57:36 +02:00
|
|
|
|
static unsigned TT_CalculateColsToDrawInCell (bool TopCall,
|
|
|
|
|
unsigned Weekday,unsigned Interval);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
static void TT_DrawCellAlignTimeTable (void);
|
2017-04-24 21:12:53 +02:00
|
|
|
|
static void TT_TimeTableDrawCell (unsigned Weekday,unsigned Interval,unsigned Column,unsigned ColSpan,
|
|
|
|
|
long CrsCod,TT_IntervalType_t IntervalType,TT_ClassType_t ClassType,
|
|
|
|
|
unsigned DurationNumIntervals,char *Group,long GrpCod,char *Place);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
2017-04-25 11:57:36 +02:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/******************** Create internal timetable in memory ********************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-04-25 21:20:19 +02:00
|
|
|
|
static void TT_TimeTableConfigureIntervalsAndAllocateTimeTable (void)
|
2017-04-25 11:57:36 +02:00
|
|
|
|
{
|
2017-04-25 21:20:19 +02:00
|
|
|
|
unsigned Weekday;
|
2017-04-25 14:48:47 +02:00
|
|
|
|
|
2017-04-25 21:20:19 +02:00
|
|
|
|
if (Gbl.TimeTable.Config.Range.Hours.End >
|
|
|
|
|
Gbl.TimeTable.Config.Range.Hours.Start)
|
2017-04-25 14:48:47 +02:00
|
|
|
|
{
|
2017-04-25 21:20:19 +02:00
|
|
|
|
/***** Configuration of timetable depending on hours and resolution *****/
|
|
|
|
|
Gbl.TimeTable.Config.HoursPerDay = Gbl.TimeTable.Config.Range.Hours.End -
|
|
|
|
|
Gbl.TimeTable.Config.Range.Hours.Start; // From start hour to end hour
|
|
|
|
|
Gbl.TimeTable.Config.SecondsPerInterval = Gbl.TimeTable.Config.Range.MinutesPerInterval *
|
|
|
|
|
TT_SECONDS_PER_MINUTE;
|
|
|
|
|
Gbl.TimeTable.Config.IntervalsPerHour = TT_MINUTES_PER_HOUR /
|
|
|
|
|
Gbl.TimeTable.Config.Range.MinutesPerInterval;
|
|
|
|
|
Gbl.TimeTable.Config.IntervalsPerDay = Gbl.TimeTable.Config.IntervalsPerHour *
|
|
|
|
|
Gbl.TimeTable.Config.HoursPerDay;
|
|
|
|
|
Gbl.TimeTable.Config.IntervalsBeforeStartHour = Gbl.TimeTable.Config.IntervalsPerHour *
|
|
|
|
|
Gbl.TimeTable.Config.Range.Hours.Start;
|
|
|
|
|
|
|
|
|
|
/***** Allocate memory for timetable *****/
|
|
|
|
|
for (Weekday = 0;
|
|
|
|
|
Weekday < TT_DAYS_PER_WEEK;
|
|
|
|
|
Weekday++)
|
|
|
|
|
if ((TT_TimeTable[Weekday] = (struct TT_Cell *)
|
|
|
|
|
malloc (Gbl.TimeTable.Config.IntervalsPerDay *
|
|
|
|
|
sizeof (struct TT_Cell))) == NULL)
|
|
|
|
|
Lay_ShowErrorAndExit ("Error allocating memory for timetable.");
|
2017-04-25 14:48:47 +02:00
|
|
|
|
}
|
2017-04-25 21:20:19 +02:00
|
|
|
|
else
|
2017-04-25 14:48:47 +02:00
|
|
|
|
{
|
2017-04-25 21:20:19 +02:00
|
|
|
|
/***** Table is empty *****/
|
|
|
|
|
Gbl.TimeTable.Config.HoursPerDay = 0;
|
|
|
|
|
Gbl.TimeTable.Config.SecondsPerInterval = 0;
|
|
|
|
|
Gbl.TimeTable.Config.IntervalsPerHour = 0;
|
|
|
|
|
Gbl.TimeTable.Config.IntervalsPerDay = 0;
|
|
|
|
|
Gbl.TimeTable.Config.IntervalsBeforeStartHour = 0;
|
|
|
|
|
|
|
|
|
|
/***** Clear timetable in order to not try to free it *****/
|
|
|
|
|
for (Weekday = 0;
|
|
|
|
|
Weekday < TT_DAYS_PER_WEEK;
|
|
|
|
|
Weekday++)
|
|
|
|
|
TT_TimeTable[Weekday] = NULL;
|
2017-04-25 14:48:47 +02:00
|
|
|
|
}
|
2017-04-25 11:57:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/******************** Destroy internal timetable in memory *******************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-04-25 21:20:19 +02:00
|
|
|
|
static void TT_FreeTimeTable (void)
|
2017-04-25 11:57:36 +02:00
|
|
|
|
{
|
|
|
|
|
unsigned Weekday;
|
|
|
|
|
|
|
|
|
|
/***** Free memory for timetable *****/
|
|
|
|
|
for (Weekday = 0;
|
|
|
|
|
Weekday < TT_DAYS_PER_WEEK;
|
|
|
|
|
Weekday++)
|
2017-04-25 21:20:19 +02:00
|
|
|
|
if (TT_TimeTable[Weekday])
|
|
|
|
|
{
|
|
|
|
|
free ((void *) TT_TimeTable[Weekday]);
|
|
|
|
|
TT_TimeTable[Weekday] = NULL;
|
|
|
|
|
}
|
2017-04-25 11:57:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
2014-12-01 23:55:08 +01:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/*********** Show whether only my groups or all groups are shown *************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void TT_ShowTimeTableGrpsSelected (void)
|
|
|
|
|
{
|
|
|
|
|
extern const char *Txt_Groups_OF_A_USER;
|
|
|
|
|
extern const char *Txt_All_groups;
|
|
|
|
|
|
2017-03-03 21:06:34 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"<div class=\"CLASSPHOTO_TITLE CENTER_MIDDLE\">");
|
2014-12-01 23:55:08 +01:00
|
|
|
|
switch (Gbl.CurrentCrs.Grps.WhichGrps)
|
|
|
|
|
{
|
|
|
|
|
case Grp_ONLY_MY_GROUPS:
|
|
|
|
|
fprintf (Gbl.F.Out,Txt_Groups_OF_A_USER,
|
|
|
|
|
Gbl.Usrs.Me.UsrDat.FullName);
|
|
|
|
|
break;
|
|
|
|
|
case Grp_ALL_GROUPS:
|
|
|
|
|
fprintf (Gbl.F.Out,"%s",Txt_All_groups);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2016-03-18 22:17:35 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"</div>");
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/******************** Get paramaters for timetable editing *******************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void TT_GetParamsTimeTable (void)
|
|
|
|
|
{
|
2017-04-24 18:53:25 +02:00
|
|
|
|
char StrClassType[TT_MAX_BYTES_STR_CLASS_TYPE + 1];
|
2017-01-28 15:58:46 +01:00
|
|
|
|
char StrDuration[TT_MAX_BYTES_STR_DURATION + 1];
|
2017-01-29 21:41:08 +01:00
|
|
|
|
unsigned Hours;
|
|
|
|
|
unsigned Minutes;
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
2017-01-29 21:41:08 +01:00
|
|
|
|
/***** Get day (0: monday, 1: tuesday,..., 6: sunday *****/
|
2017-04-24 21:12:53 +02:00
|
|
|
|
Gbl.TimeTable.Weekday = (unsigned)
|
2017-04-25 21:20:19 +02:00
|
|
|
|
Par_GetParToUnsignedLong ("TTDay",
|
2017-04-24 21:12:53 +02:00
|
|
|
|
0,
|
|
|
|
|
TT_DAYS_PER_WEEK - 1,
|
|
|
|
|
0);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
|
|
|
|
/***** Get hour *****/
|
2017-04-24 21:12:53 +02:00
|
|
|
|
Gbl.TimeTable.Interval = (unsigned)
|
2017-04-25 21:20:19 +02:00
|
|
|
|
Par_GetParToUnsignedLong ("TTInt",
|
2017-04-25 11:57:36 +02:00
|
|
|
|
0,
|
|
|
|
|
Gbl.TimeTable.Config.IntervalsPerDay - 1,
|
|
|
|
|
0);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
|
|
|
|
/***** Get number of column *****/
|
2017-01-29 21:41:08 +01:00
|
|
|
|
Gbl.TimeTable.Column = (unsigned)
|
2017-04-25 21:20:19 +02:00
|
|
|
|
Par_GetParToUnsignedLong ("TTCol",
|
2017-01-29 21:41:08 +01:00
|
|
|
|
0,
|
|
|
|
|
TT_MAX_COLUMNS_PER_CELL - 1,
|
|
|
|
|
0);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
|
|
|
|
/***** Get class type *****/
|
2017-04-25 21:20:19 +02:00
|
|
|
|
Par_GetParToText ("TTTyp",StrClassType,TT_MAX_BYTES_STR_CLASS_TYPE);
|
2017-04-24 13:39:55 +02:00
|
|
|
|
for (Gbl.TimeTable.ClassType = (TT_ClassType_t) 0;
|
|
|
|
|
Gbl.TimeTable.ClassType < (TT_ClassType_t) TT_NUM_CLASS_TYPES;
|
|
|
|
|
Gbl.TimeTable.ClassType++)
|
2017-04-25 14:48:47 +02:00
|
|
|
|
if (!strcmp (StrClassType,TT_ClassTypeDB[Gbl.TimeTable.ClassType]))
|
2014-12-01 23:55:08 +01:00
|
|
|
|
break;
|
2017-04-24 13:39:55 +02:00
|
|
|
|
if (Gbl.TimeTable.ClassType == (TT_ClassType_t) TT_NUM_CLASS_TYPES)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
Lay_ShowErrorAndExit ("Type of timetable cell is missing.");
|
|
|
|
|
|
|
|
|
|
/***** Get class duration *****/
|
2017-04-25 21:20:19 +02:00
|
|
|
|
Par_GetParToText ("TTDur",StrDuration,TT_MAX_BYTES_STR_DURATION);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
if (sscanf (StrDuration,"%u:%u",&Hours,&Minutes) != 2)
|
|
|
|
|
Lay_ShowErrorAndExit ("Duration is missing.");
|
2017-04-25 21:20:19 +02:00
|
|
|
|
Gbl.TimeTable.DurationIntervals = Hours * Gbl.TimeTable.Config.IntervalsPerHour +
|
|
|
|
|
Minutes / Gbl.TimeTable.Config.Range.MinutesPerInterval;
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
|
|
|
|
/***** Get group code *****/
|
2017-04-25 21:20:19 +02:00
|
|
|
|
Gbl.TimeTable.GrpCod = Par_GetParToLong ("TTGrp");
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
|
|
|
|
/***** Get place *****/
|
2017-04-25 21:20:19 +02:00
|
|
|
|
Par_GetParToText ("TTPlc",Gbl.TimeTable.Place,TT_MAX_BYTES_PLACE);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/**************************** Show class timetable ***************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
void TT_ShowClassTimeTable (void)
|
|
|
|
|
{
|
2016-11-26 21:12:23 +01:00
|
|
|
|
extern const char *Hlp_COURSE_Timetable;
|
2016-11-26 20:58:12 +01:00
|
|
|
|
extern const char *Hlp_PROFILE_Timetable;
|
2015-01-02 12:57:26 +01:00
|
|
|
|
extern const char *Txt_TIMETABLE_TYPES[TT_NUM_TIMETABLE_TYPES];
|
2016-11-26 20:58:12 +01:00
|
|
|
|
const char *Help[TT_NUM_TIMETABLE_TYPES] =
|
|
|
|
|
{
|
2016-11-26 21:12:23 +01:00
|
|
|
|
Hlp_COURSE_Timetable, // TT_COURSE_TIMETABLE
|
2016-11-26 20:58:12 +01:00
|
|
|
|
Hlp_PROFILE_Timetable, // TT_MY_TIMETABLE
|
2017-04-24 13:00:59 +02:00
|
|
|
|
NULL, // TT_TUTORING_TIMETABLE
|
2016-11-26 20:58:12 +01:00
|
|
|
|
};
|
2016-11-26 22:02:42 +01:00
|
|
|
|
Act_Action_t ActChgTT1stDay[TT_NUM_TIMETABLE_TYPES] =
|
|
|
|
|
{
|
|
|
|
|
ActChgCrsTT1stDay,// TT_COURSE_TIMETABLE
|
|
|
|
|
ActChgMyTT1stDay, // TT_MY_TIMETABLE
|
2017-04-24 13:00:59 +02:00
|
|
|
|
ActUnk, // TT_TUTORING_TIMETABLE
|
2016-11-26 22:02:42 +01:00
|
|
|
|
};
|
2016-03-18 14:07:21 +01:00
|
|
|
|
bool PrintView = (Gbl.Action.Act == ActPrnCrsTT ||
|
|
|
|
|
Gbl.Action.Act == ActPrnMyTT);;
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
2015-12-01 00:38:22 +01:00
|
|
|
|
/***** Initializations *****/
|
2016-01-17 15:10:54 +01:00
|
|
|
|
switch (Gbl.Action.Act)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
2015-12-01 00:38:22 +01:00
|
|
|
|
case ActSeeCrsTT:
|
|
|
|
|
case ActPrnCrsTT:
|
|
|
|
|
case ActChgCrsTT1stDay:
|
2016-03-18 14:07:21 +01:00
|
|
|
|
Gbl.TimeTable.Type = TT_COURSE_TIMETABLE;
|
2014-12-01 23:55:08 +01:00
|
|
|
|
break;
|
2015-12-01 00:38:22 +01:00
|
|
|
|
case ActSeeMyTT:
|
|
|
|
|
case ActPrnMyTT:
|
|
|
|
|
case ActChgMyTT1stDay:
|
2016-03-18 14:07:21 +01:00
|
|
|
|
Gbl.TimeTable.Type = TT_MY_TIMETABLE;
|
2014-12-01 23:55:08 +01:00
|
|
|
|
break;
|
2015-12-01 00:38:22 +01:00
|
|
|
|
default:
|
|
|
|
|
Lay_ShowErrorAndExit ("Wrong action.");
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
2016-12-04 20:12:56 +01:00
|
|
|
|
|
2016-03-18 14:07:21 +01:00
|
|
|
|
Gbl.TimeTable.ContextualIcons.PutIconEditCrsTT = (Gbl.TimeTable.Type == TT_COURSE_TIMETABLE &&
|
|
|
|
|
!PrintView &&
|
2017-06-04 18:18:54 +02:00
|
|
|
|
Gbl.Usrs.Me.Role.Logged >= Rol_TCH);
|
2016-03-18 14:07:21 +01:00
|
|
|
|
Gbl.TimeTable.ContextualIcons.PutIconEditOfficeHours = (Gbl.TimeTable.Type == TT_MY_TIMETABLE &&
|
|
|
|
|
!PrintView &&
|
2017-06-04 18:18:54 +02:00
|
|
|
|
(Gbl.Usrs.Me.Role.Available & (1 << Rol_TCH)));
|
2016-12-04 20:12:56 +01:00
|
|
|
|
Gbl.TimeTable.ContextualIcons.PutIconPrint = !PrintView;
|
2015-12-01 00:38:22 +01:00
|
|
|
|
|
|
|
|
|
/***** Get whether to show only my groups or all groups *****/
|
|
|
|
|
Grp_GetParamWhichGrps ();
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
2017-06-12 14:16:33 +02:00
|
|
|
|
/***** Start box *****/
|
2017-06-10 21:38:10 +02:00
|
|
|
|
Box_StartBox ("100%",Txt_TIMETABLE_TYPES[Gbl.TimeTable.Type],
|
2017-06-11 22:26:40 +02:00
|
|
|
|
(Gbl.TimeTable.ContextualIcons.PutIconEditCrsTT ||
|
|
|
|
|
Gbl.TimeTable.ContextualIcons.PutIconEditOfficeHours ||
|
|
|
|
|
Gbl.TimeTable.ContextualIcons.PutIconPrint) ? TT_PutContextualIcons :
|
|
|
|
|
NULL,
|
2017-06-12 15:03:29 +02:00
|
|
|
|
Help[Gbl.TimeTable.Type],Box_NOT_CLOSABLE);
|
2014-12-08 17:35:48 +01:00
|
|
|
|
|
|
|
|
|
/***** Start time table drawing *****/
|
2016-03-18 14:07:21 +01:00
|
|
|
|
if (Gbl.TimeTable.Type == TT_COURSE_TIMETABLE)
|
2016-03-18 22:17:35 +01:00
|
|
|
|
Lay_WriteHeaderClassPhoto (PrintView,false,
|
2014-12-08 17:35:48 +01:00
|
|
|
|
Gbl.CurrentIns.Ins.InsCod,Gbl.CurrentDeg.Deg.DegCod,Gbl.CurrentCrs.Crs.CrsCod);
|
|
|
|
|
|
|
|
|
|
if (PrintView)
|
2015-01-02 12:57:26 +01:00
|
|
|
|
/***** Show whether only my groups or all groups are selected *****/
|
|
|
|
|
TT_ShowTimeTableGrpsSelected ();
|
|
|
|
|
else
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
2015-12-01 00:38:22 +01:00
|
|
|
|
/***** Select whether show only my groups or all groups *****/
|
2016-12-04 12:42:45 +01:00
|
|
|
|
if ( Gbl.TimeTable.Type == TT_MY_TIMETABLE ||
|
|
|
|
|
(Gbl.TimeTable.Type == TT_COURSE_TIMETABLE &&
|
|
|
|
|
Gbl.CurrentCrs.Grps.NumGrps))
|
2016-11-26 22:07:52 +01:00
|
|
|
|
TT_PutFormToSelectWhichGroupsToShow ();
|
2015-12-01 00:38:22 +01:00
|
|
|
|
|
|
|
|
|
/***** Show form to change first day of week *****/
|
2016-11-26 22:02:42 +01:00
|
|
|
|
Cal_ShowFormToSelFirstDayOfWeek (ActChgTT1stDay[Gbl.TimeTable.Type],
|
2016-12-04 12:42:45 +01:00
|
|
|
|
Grp_PutParamWhichGrps,
|
2016-11-14 10:05:41 +01:00
|
|
|
|
"ICO25x25");
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***** Show the time table *****/
|
2016-03-18 14:07:21 +01:00
|
|
|
|
TT_ShowTimeTable (Gbl.Usrs.Me.UsrDat.UsrCod);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
2017-06-12 14:16:33 +02:00
|
|
|
|
/***** End box *****/
|
2017-06-10 21:38:10 +02:00
|
|
|
|
Box_EndBox ();
|
2016-03-18 14:07:21 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/***************** Put contextual icons above the time table *****************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void TT_PutContextualIcons (void)
|
|
|
|
|
{
|
|
|
|
|
if (Gbl.TimeTable.ContextualIcons.PutIconEditCrsTT)
|
2017-06-11 19:13:28 +02:00
|
|
|
|
Ico_PutContextualIconToEdit (ActEdiCrsTT,Grp_PutParamWhichGrps);
|
2016-03-18 14:07:21 +01:00
|
|
|
|
|
|
|
|
|
if (Gbl.TimeTable.ContextualIcons.PutIconEditOfficeHours)
|
2017-06-11 19:13:28 +02:00
|
|
|
|
Ico_PutContextualIconToEdit (ActEdiTut,NULL);
|
2016-03-18 14:07:21 +01:00
|
|
|
|
|
|
|
|
|
if (Gbl.TimeTable.ContextualIcons.PutIconPrint)
|
2017-06-11 19:13:28 +02:00
|
|
|
|
Ico_PutContextualIconToPrint (Gbl.TimeTable.Type == TT_COURSE_TIMETABLE ? ActPrnCrsTT :
|
2017-04-30 19:44:18 +02:00
|
|
|
|
ActPrnMyTT,
|
|
|
|
|
Grp_PutParamWhichGrps);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
|
|
|
|
|
2016-11-26 22:07:52 +01:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/***************** Put form to select which groups to show *******************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void TT_PutFormToSelectWhichGroupsToShow (void)
|
|
|
|
|
{
|
|
|
|
|
Act_Action_t ActSeeTT[TT_NUM_TIMETABLE_TYPES] =
|
|
|
|
|
{
|
|
|
|
|
ActSeeCrsTT, // TT_COURSE_TIMETABLE
|
|
|
|
|
ActSeeMyTT, // TT_MY_TIMETABLE
|
2017-04-24 13:00:59 +02:00
|
|
|
|
ActUnk, // TT_TUTORING_TIMETABLE
|
2016-11-26 22:07:52 +01:00
|
|
|
|
};
|
|
|
|
|
|
2016-12-04 23:09:28 +01:00
|
|
|
|
Grp_ShowFormToSelWhichGrps (ActSeeTT[Gbl.TimeTable.Type],NULL);
|
2016-11-26 22:07:52 +01:00
|
|
|
|
}
|
|
|
|
|
|
2014-12-01 23:55:08 +01:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/********************** Show course timetable for edition ********************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
void TT_EditCrsTimeTable (void)
|
|
|
|
|
{
|
2016-11-26 21:12:23 +01:00
|
|
|
|
extern const char *Hlp_COURSE_Timetable;
|
2015-04-12 01:40:51 +02:00
|
|
|
|
extern const char *Txt_TIMETABLE_TYPES[TT_NUM_TIMETABLE_TYPES];
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
|
|
|
|
/***** Editable time table *****/
|
2016-03-18 14:07:21 +01:00
|
|
|
|
Gbl.TimeTable.Type = TT_COURSE_TIMETABLE;
|
2017-06-11 22:26:40 +02:00
|
|
|
|
Box_StartBox ("100%",Txt_TIMETABLE_TYPES[Gbl.TimeTable.Type],TT_PutIconToViewCrsTT,
|
2017-06-12 15:03:29 +02:00
|
|
|
|
Hlp_COURSE_Timetable,Box_NOT_CLOSABLE);
|
2016-03-18 14:07:21 +01:00
|
|
|
|
TT_ShowTimeTable (Gbl.Usrs.Me.UsrDat.UsrCod);
|
2017-06-10 21:38:10 +02:00
|
|
|
|
Box_EndBox ();
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/********************* Show tutor timetable for edition **********************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2016-11-26 20:58:12 +01:00
|
|
|
|
void TT_EditMyTutTimeTable (void)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
2016-11-26 20:58:12 +01:00
|
|
|
|
extern const char *Hlp_PROFILE_Timetable;
|
2015-01-02 12:57:26 +01:00
|
|
|
|
extern const char *Txt_TIMETABLE_TYPES[TT_NUM_TIMETABLE_TYPES];
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
|
|
|
|
/***** Time table *****/
|
2017-04-24 13:00:59 +02:00
|
|
|
|
Gbl.TimeTable.Type = TT_TUTORING_TIMETABLE;
|
2017-06-11 22:26:40 +02:00
|
|
|
|
Box_StartBox ("100%",Txt_TIMETABLE_TYPES[Gbl.TimeTable.Type],TT_PutIconToViewMyTT,
|
2017-06-12 15:03:29 +02:00
|
|
|
|
Hlp_PROFILE_Timetable,Box_NOT_CLOSABLE);
|
2016-03-18 14:07:21 +01:00
|
|
|
|
TT_ShowTimeTable (Gbl.Usrs.Me.UsrDat.UsrCod);
|
2017-06-10 21:38:10 +02:00
|
|
|
|
Box_EndBox ();
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
|
|
|
|
|
2016-03-18 14:17:19 +01:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/********************** Put icon to view course timetable ********************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void TT_PutIconToViewCrsTT (void)
|
|
|
|
|
{
|
2017-06-11 19:13:28 +02:00
|
|
|
|
Ico_PutContextualIconToView (ActSeeCrsTT,NULL);
|
2016-03-18 14:17:19 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/************************ Put icon to view my timetable **********************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void TT_PutIconToViewMyTT (void)
|
|
|
|
|
{
|
2017-06-11 19:13:28 +02:00
|
|
|
|
Ico_PutContextualIconToView (ActSeeMyTT,NULL);
|
2016-03-18 14:17:19 +01:00
|
|
|
|
}
|
|
|
|
|
|
2014-12-01 23:55:08 +01:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/*********** Show course timetable or tutor timetable of a teacher ***********/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2016-03-18 14:07:21 +01:00
|
|
|
|
void TT_ShowTimeTable (long UsrCod)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
2017-04-25 21:20:19 +02:00
|
|
|
|
extern const char *Txt_The_timetable_is_empty;
|
|
|
|
|
|
2017-04-25 21:42:29 +02:00
|
|
|
|
/***** Set type of view depending on current action *****/
|
|
|
|
|
Gbl.TimeTable.View = TT_CRS_VIEW;
|
2017-04-25 21:20:19 +02:00
|
|
|
|
switch (Gbl.Action.Act)
|
|
|
|
|
{
|
|
|
|
|
case ActSeeCrsTT: case ActPrnCrsTT: case ActChgCrsTT1stDay:
|
|
|
|
|
case ActSeeMyTT: case ActPrnMyTT: case ActChgMyTT1stDay:
|
2017-04-25 21:42:29 +02:00
|
|
|
|
Gbl.TimeTable.View = TT_CRS_VIEW;
|
|
|
|
|
break;
|
2017-04-25 21:20:19 +02:00
|
|
|
|
case ActSeeRecOneTch: case ActSeeRecSevTch:
|
2017-04-25 21:42:29 +02:00
|
|
|
|
Gbl.TimeTable.View = TT_TUT_VIEW;
|
|
|
|
|
break;
|
2017-04-25 21:20:19 +02:00
|
|
|
|
case ActEdiCrsTT: case ActChgCrsTT:
|
2017-04-25 21:42:29 +02:00
|
|
|
|
Gbl.TimeTable.View = TT_CRS_EDIT;
|
|
|
|
|
break;
|
2017-04-25 21:20:19 +02:00
|
|
|
|
case ActEdiTut: case ActChgTut:
|
2017-04-25 21:42:29 +02:00
|
|
|
|
Gbl.TimeTable.View = TT_TUT_EDIT;
|
|
|
|
|
break;
|
2017-04-25 21:20:19 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***** If editing ==> configure and allocate timetable *****/
|
2017-04-25 21:42:29 +02:00
|
|
|
|
if (Gbl.TimeTable.View == TT_CRS_EDIT ||
|
|
|
|
|
Gbl.TimeTable.View == TT_TUT_EDIT)
|
2017-04-25 21:20:19 +02:00
|
|
|
|
{
|
|
|
|
|
Gbl.TimeTable.Config.Range.Hours.Start = TT_START_HOUR; // Day starts at this hour
|
|
|
|
|
Gbl.TimeTable.Config.Range.Hours.End = TT_END_HOUR; // Day ends at this hour
|
|
|
|
|
Gbl.TimeTable.Config.Range.MinutesPerInterval = TT_MinutesPerInterval[0]; // The smallest interval
|
|
|
|
|
TT_TimeTableConfigureIntervalsAndAllocateTimeTable ();
|
|
|
|
|
}
|
|
|
|
|
/* If viewing (not editing) ==>
|
|
|
|
|
configure and allocate memory when table is read from database */
|
2017-04-25 11:57:36 +02:00
|
|
|
|
|
|
|
|
|
/***** Fill internal timetable with the timetable from database *****/
|
|
|
|
|
TT_FillTimeTableFromDB (UsrCod);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
|
|
|
|
/***** If timetable must be modified... *****/
|
2016-01-17 15:10:54 +01:00
|
|
|
|
if (Gbl.Action.Act == ActChgCrsTT ||
|
|
|
|
|
Gbl.Action.Act == ActChgTut)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
|
|
|
|
/* Get parameters for time table editing */
|
|
|
|
|
TT_GetParamsTimeTable ();
|
|
|
|
|
|
|
|
|
|
/* Modify timetable in memory */
|
|
|
|
|
TT_ModifTimeTable ();
|
|
|
|
|
|
|
|
|
|
/* Write a new timetable in database */
|
2016-03-18 14:07:21 +01:00
|
|
|
|
switch (Gbl.TimeTable.Type)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
|
|
|
|
case TT_COURSE_TIMETABLE:
|
|
|
|
|
TT_WriteCrsTimeTableIntoDB (Gbl.CurrentCrs.Crs.CrsCod);
|
|
|
|
|
break;
|
2017-04-24 13:00:59 +02:00
|
|
|
|
case TT_TUTORING_TIMETABLE:
|
2014-12-01 23:55:08 +01:00
|
|
|
|
TT_WriteTutTimeTableIntoDB (UsrCod);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get a new table from database */
|
2017-04-25 11:57:36 +02:00
|
|
|
|
TT_FillTimeTableFromDB (UsrCod);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***** Draw timetable *****/
|
2017-04-25 21:20:19 +02:00
|
|
|
|
if (Gbl.TimeTable.Config.HoursPerDay)
|
|
|
|
|
TT_DrawTimeTable ();
|
|
|
|
|
else
|
2017-05-11 23:45:46 +02:00
|
|
|
|
Ale_ShowAlert (Ale_INFO,Txt_The_timetable_is_empty);
|
2017-04-25 11:57:36 +02:00
|
|
|
|
|
|
|
|
|
/***** Free internal timetable in memory *****/
|
2017-04-25 21:20:19 +02:00
|
|
|
|
TT_FreeTimeTable ();
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/******************* Write course timetable into database ********************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void TT_WriteCrsTimeTableIntoDB (long CrsCod)
|
|
|
|
|
{
|
2017-03-13 14:57:35 +01:00
|
|
|
|
char Query[512 +
|
|
|
|
|
TT_MAX_BYTES_PLACE +
|
|
|
|
|
Grp_MAX_BYTES_GROUP_NAME];
|
2017-04-24 13:50:03 +02:00
|
|
|
|
unsigned Weekday;
|
2017-04-24 21:12:53 +02:00
|
|
|
|
unsigned Interval;
|
2017-04-24 13:39:55 +02:00
|
|
|
|
unsigned Hour;
|
|
|
|
|
unsigned Min;
|
2017-03-13 14:57:35 +01:00
|
|
|
|
unsigned Column;
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
|
|
|
|
/***** Remove former timetable *****/
|
2017-03-24 01:09:27 +01:00
|
|
|
|
sprintf (Query,"DELETE FROM timetable_crs WHERE CrsCod=%ld",
|
2017-03-13 14:57:35 +01:00
|
|
|
|
CrsCod);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
DB_QueryDELETE (Query,"can not remove former timetable");
|
|
|
|
|
|
|
|
|
|
/***** Go across the timetable inserting classes into database *****/
|
2017-04-24 13:50:03 +02:00
|
|
|
|
for (Weekday = 0;
|
2017-04-24 21:12:53 +02:00
|
|
|
|
Weekday < TT_DAYS_PER_WEEK;
|
2017-04-24 13:50:03 +02:00
|
|
|
|
Weekday++)
|
2017-04-25 21:20:19 +02:00
|
|
|
|
for (Interval = 0, Hour = Gbl.TimeTable.Config.Range.Hours.Start, Min = 0;
|
2017-04-25 11:57:36 +02:00
|
|
|
|
Interval < Gbl.TimeTable.Config.IntervalsPerDay;
|
2017-04-24 21:12:53 +02:00
|
|
|
|
Interval++,
|
2017-04-25 21:20:19 +02:00
|
|
|
|
Hour += (Min + Gbl.TimeTable.Config.Range.MinutesPerInterval) / TT_SECONDS_PER_MINUTE,
|
|
|
|
|
Min = (Min + Gbl.TimeTable.Config.Range.MinutesPerInterval) % TT_SECONDS_PER_MINUTE)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
for (Column = 0;
|
|
|
|
|
Column < TT_MAX_COLUMNS_PER_CELL;
|
|
|
|
|
Column++)
|
2017-04-24 21:12:53 +02:00
|
|
|
|
if (TT_TimeTable[Weekday][Interval].Columns[Column].IntervalType == TT_FIRST_INTERVAL &&
|
2017-04-25 21:20:19 +02:00
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[Column].DurationIntervals)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
2017-03-13 13:17:53 +01:00
|
|
|
|
sprintf (Query,"INSERT INTO timetable_crs"
|
2017-04-24 13:39:55 +02:00
|
|
|
|
" (CrsCod,GrpCod,Weekday,StartTime,Duration,"
|
|
|
|
|
"ClassType,Place,GroupName)"
|
2017-03-13 13:17:53 +01:00
|
|
|
|
" VALUES"
|
2017-04-24 13:39:55 +02:00
|
|
|
|
" (%ld,%ld,%u,'%02u:%02u:00',SEC_TO_TIME(%u),"
|
|
|
|
|
"'%s','%s','%s')",
|
2014-12-01 23:55:08 +01:00
|
|
|
|
CrsCod,
|
2017-04-24 21:12:53 +02:00
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[Column].GrpCod,
|
2017-04-24 13:50:03 +02:00
|
|
|
|
Weekday,
|
2017-04-24 13:39:55 +02:00
|
|
|
|
Hour,Min,
|
2017-04-25 21:20:19 +02:00
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[Column].DurationIntervals *
|
2017-04-25 11:57:36 +02:00
|
|
|
|
Gbl.TimeTable.Config.SecondsPerInterval,
|
2017-04-25 14:48:47 +02:00
|
|
|
|
TT_ClassTypeDB[TT_TimeTable[Weekday][Interval].Columns[Column].ClassType],
|
2017-04-24 21:12:53 +02:00
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[Column].Place,
|
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[Column].Group);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
DB_QueryINSERT (Query,"can not create course timetable");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/********************* Write tutor timetable into database *******************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void TT_WriteTutTimeTableIntoDB (long UsrCod)
|
|
|
|
|
{
|
2017-03-13 14:57:35 +01:00
|
|
|
|
char Query[512 +
|
|
|
|
|
TT_MAX_BYTES_PLACE];
|
2017-04-24 13:50:03 +02:00
|
|
|
|
unsigned Weekday;
|
2017-04-24 21:12:53 +02:00
|
|
|
|
unsigned Interval;
|
2017-04-24 13:50:03 +02:00
|
|
|
|
unsigned Hour;
|
|
|
|
|
unsigned Min;
|
2017-04-24 13:00:59 +02:00
|
|
|
|
unsigned Column;
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
|
|
|
|
/***** Remove former timetable *****/
|
2017-03-24 01:09:27 +01:00
|
|
|
|
sprintf (Query,"DELETE FROM timetable_tut WHERE UsrCod=%ld",
|
2017-03-13 14:57:35 +01:00
|
|
|
|
UsrCod);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
DB_QueryDELETE (Query,"can not remove former timetable");
|
|
|
|
|
|
|
|
|
|
/***** Loop over timetable *****/
|
2017-04-24 13:50:03 +02:00
|
|
|
|
for (Weekday = 0;
|
2017-04-24 21:12:53 +02:00
|
|
|
|
Weekday < TT_DAYS_PER_WEEK;
|
2017-04-24 13:50:03 +02:00
|
|
|
|
Weekday++)
|
2017-04-25 21:20:19 +02:00
|
|
|
|
for (Interval = 0, Hour = Gbl.TimeTable.Config.Range.Hours.Start, Min = 0;
|
2017-04-25 11:57:36 +02:00
|
|
|
|
Interval < Gbl.TimeTable.Config.IntervalsPerDay;
|
2017-04-24 21:12:53 +02:00
|
|
|
|
Interval++,
|
2017-04-25 21:20:19 +02:00
|
|
|
|
Hour += (Min + Gbl.TimeTable.Config.Range.MinutesPerInterval) / TT_SECONDS_PER_MINUTE,
|
|
|
|
|
Min = (Min + Gbl.TimeTable.Config.Range.MinutesPerInterval) % TT_SECONDS_PER_MINUTE)
|
2017-04-24 18:53:25 +02:00
|
|
|
|
for (Column = 0;
|
2014-12-01 23:55:08 +01:00
|
|
|
|
Column < TT_MAX_COLUMNS_PER_CELL;
|
|
|
|
|
Column++)
|
2017-04-24 21:12:53 +02:00
|
|
|
|
if (TT_TimeTable[Weekday][Interval].Columns[Column].IntervalType == TT_FIRST_INTERVAL &&
|
2017-04-25 21:20:19 +02:00
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[Column].DurationIntervals)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
2017-03-13 13:17:53 +01:00
|
|
|
|
sprintf (Query,"INSERT INTO timetable_tut"
|
2017-04-24 13:50:03 +02:00
|
|
|
|
" (UsrCod,Weekday,StartTime,Duration,Place)"
|
2017-03-13 13:17:53 +01:00
|
|
|
|
" VALUES"
|
2017-04-24 13:50:03 +02:00
|
|
|
|
" (%ld,%u,'%02u:%02u:00',SEC_TO_TIME(%u),'%s')",
|
|
|
|
|
UsrCod,
|
|
|
|
|
Weekday,
|
|
|
|
|
Hour,Min,
|
2017-04-25 21:20:19 +02:00
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[Column].DurationIntervals *
|
2017-04-25 11:57:36 +02:00
|
|
|
|
Gbl.TimeTable.Config.SecondsPerInterval,
|
2017-04-24 21:12:53 +02:00
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[Column].Place);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
DB_QueryINSERT (Query,"can not create office timetable");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/********** Create an internal table with timetable from database ************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-04-25 11:57:36 +02:00
|
|
|
|
static void TT_FillTimeTableFromDB (long UsrCod)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
|
|
|
|
extern const char *Txt_Incomplete_timetable_for_lack_of_space;
|
|
|
|
|
char Query[4096];
|
|
|
|
|
MYSQL_RES *mysql_res;
|
|
|
|
|
MYSQL_ROW row;
|
2017-04-24 13:00:59 +02:00
|
|
|
|
unsigned long NumRow;
|
|
|
|
|
unsigned long NumRows;
|
2017-04-24 18:53:25 +02:00
|
|
|
|
unsigned Weekday;
|
2017-04-24 21:12:53 +02:00
|
|
|
|
unsigned Interval;
|
2017-04-25 21:20:19 +02:00
|
|
|
|
unsigned i; // To iterate through intervals
|
2017-04-24 21:12:53 +02:00
|
|
|
|
unsigned DurationNumIntervals;
|
2017-04-24 13:00:59 +02:00
|
|
|
|
unsigned Column;
|
2017-04-25 14:48:47 +02:00
|
|
|
|
unsigned StartTimeSeconds;
|
|
|
|
|
unsigned DurationSeconds;
|
|
|
|
|
unsigned EndTimeSeconds;
|
2017-04-25 21:20:19 +02:00
|
|
|
|
struct TT_Range RangeCell;
|
2017-04-24 13:00:59 +02:00
|
|
|
|
unsigned FirstFreeColumn;
|
2014-12-01 23:55:08 +01:00
|
|
|
|
long GrpCod;
|
2017-04-24 13:39:55 +02:00
|
|
|
|
TT_ClassType_t ClassType = TT_FREE; // Initialized to avoid warning
|
2014-12-01 23:55:08 +01:00
|
|
|
|
bool TimeTableIsIncomplete = false;
|
|
|
|
|
bool TimeTableHasSpaceForThisClass;
|
|
|
|
|
bool Found;
|
|
|
|
|
|
|
|
|
|
/***** Get timetable from database *****/
|
2016-03-18 14:07:21 +01:00
|
|
|
|
switch (Gbl.TimeTable.Type)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
|
|
|
|
case TT_MY_TIMETABLE:
|
|
|
|
|
switch (Gbl.CurrentCrs.Grps.WhichGrps)
|
|
|
|
|
{
|
|
|
|
|
case Grp_ONLY_MY_GROUPS:
|
2017-04-24 18:53:25 +02:00
|
|
|
|
sprintf (Query,"SELECT "
|
|
|
|
|
"timetable_crs.Weekday,"
|
2017-04-25 02:07:32 +02:00
|
|
|
|
"TIME_TO_SEC(timetable_crs.StartTime) AS S,"
|
2017-04-24 18:53:25 +02:00
|
|
|
|
"TIME_TO_SEC(timetable_crs.Duration) AS D,"
|
|
|
|
|
"timetable_crs.Place,"
|
|
|
|
|
"timetable_crs.ClassType,"
|
|
|
|
|
"timetable_crs.GroupName,"
|
|
|
|
|
"timetable_crs.GrpCod,"
|
|
|
|
|
"timetable_crs.CrsCod"
|
2014-12-01 23:55:08 +01:00
|
|
|
|
" FROM timetable_crs,crs_usr"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE crs_usr.UsrCod=%ld"
|
|
|
|
|
" AND timetable_crs.GrpCod=-1"
|
|
|
|
|
" AND timetable_crs.CrsCod=crs_usr.CrsCod"
|
2014-12-01 23:55:08 +01:00
|
|
|
|
" UNION DISTINCT "
|
2017-04-24 18:53:25 +02:00
|
|
|
|
"SELECT "
|
|
|
|
|
"timetable_crs.Weekday,"
|
2017-04-25 02:07:32 +02:00
|
|
|
|
"TIME_TO_SEC(timetable_crs.StartTime) AS S,"
|
2017-04-24 18:53:25 +02:00
|
|
|
|
"TIME_TO_SEC(timetable_crs.Duration) AS D,"
|
|
|
|
|
"timetable_crs.Place,"
|
|
|
|
|
"timetable_crs.ClassType,"
|
|
|
|
|
"timetable_crs.GroupName,"
|
|
|
|
|
"timetable_crs.GrpCod,"
|
|
|
|
|
"timetable_crs.CrsCod"
|
2014-12-01 23:55:08 +01:00
|
|
|
|
" FROM timetable_crs,crs_grp_usr"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE crs_grp_usr.UsrCod=%ld"
|
|
|
|
|
" AND timetable_crs.GrpCod=crs_grp_usr.GrpCod"
|
2014-12-01 23:55:08 +01:00
|
|
|
|
" UNION "
|
2017-04-24 18:53:25 +02:00
|
|
|
|
"SELECT "
|
|
|
|
|
"Weekday,"
|
2017-04-25 02:07:32 +02:00
|
|
|
|
"TIME_TO_SEC(StartTime) AS S,"
|
2017-04-24 18:53:25 +02:00
|
|
|
|
"TIME_TO_SEC(Duration) AS D,"
|
|
|
|
|
"Place,"
|
|
|
|
|
"'tutoring' AS ClassType,"
|
|
|
|
|
"'' AS GroupName,"
|
|
|
|
|
"-1 AS GrpCod,"
|
|
|
|
|
"-1 AS CrsCod"
|
2014-12-01 23:55:08 +01:00
|
|
|
|
" FROM timetable_tut"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE UsrCod=%ld"
|
2017-04-25 02:07:32 +02:00
|
|
|
|
" ORDER BY Weekday,S,ClassType,"
|
2017-04-24 18:53:25 +02:00
|
|
|
|
"GroupName,GrpCod,Place,D DESC,CrsCod",
|
2014-12-01 23:55:08 +01:00
|
|
|
|
UsrCod,UsrCod,UsrCod);
|
|
|
|
|
break;
|
|
|
|
|
case Grp_ALL_GROUPS:
|
2017-04-24 18:53:25 +02:00
|
|
|
|
sprintf (Query,"SELECT "
|
|
|
|
|
"timetable_crs.Weekday,"
|
2017-04-25 02:07:32 +02:00
|
|
|
|
"TIME_TO_SEC(timetable_crs.StartTime) AS S,"
|
2017-04-24 18:53:25 +02:00
|
|
|
|
"TIME_TO_SEC(timetable_crs.Duration) AS D,"
|
|
|
|
|
"timetable_crs.Place,"
|
|
|
|
|
"timetable_crs.ClassType,"
|
|
|
|
|
"timetable_crs.GroupName,"
|
|
|
|
|
"timetable_crs.GrpCod,"
|
|
|
|
|
"timetable_crs.CrsCod"
|
2014-12-01 23:55:08 +01:00
|
|
|
|
" FROM timetable_crs,crs_usr"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE crs_usr.UsrCod=%ld"
|
|
|
|
|
" AND timetable_crs.CrsCod=crs_usr.CrsCod"
|
2014-12-01 23:55:08 +01:00
|
|
|
|
" UNION "
|
2017-04-24 18:53:25 +02:00
|
|
|
|
"SELECT "
|
|
|
|
|
"Weekday,"
|
2017-04-25 02:07:32 +02:00
|
|
|
|
"TIME_TO_SEC(StartTime) AS S,"
|
2017-04-24 18:53:25 +02:00
|
|
|
|
"TIME_TO_SEC(Duration) AS D,"
|
|
|
|
|
"Place,"
|
|
|
|
|
"'tutoring' AS ClassType,"
|
|
|
|
|
"'' AS GroupName,"
|
|
|
|
|
"-1 AS GrpCod,"
|
|
|
|
|
"-1 AS CrsCod"
|
2014-12-01 23:55:08 +01:00
|
|
|
|
" FROM timetable_tut"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE UsrCod=%ld"
|
2017-04-25 02:07:32 +02:00
|
|
|
|
" ORDER BY Weekday,S,ClassType,"
|
2017-04-24 18:53:25 +02:00
|
|
|
|
"GroupName,GrpCod,Place,D DESC,CrsCod",
|
2014-12-01 23:55:08 +01:00
|
|
|
|
UsrCod,UsrCod);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case TT_COURSE_TIMETABLE:
|
|
|
|
|
if (Gbl.CurrentCrs.Grps.WhichGrps == Grp_ALL_GROUPS ||
|
2016-01-17 15:10:54 +01:00
|
|
|
|
Gbl.Action.Act == ActEdiCrsTT ||
|
|
|
|
|
Gbl.Action.Act == ActChgCrsTT) // If we are editing, all groups are shown
|
2017-04-24 18:53:25 +02:00
|
|
|
|
sprintf (Query,"SELECT "
|
|
|
|
|
"Weekday,"
|
2017-04-25 02:07:32 +02:00
|
|
|
|
"TIME_TO_SEC(StartTime) AS S,"
|
2017-04-24 18:53:25 +02:00
|
|
|
|
"TIME_TO_SEC(Duration) AS D,"
|
|
|
|
|
"Place,"
|
|
|
|
|
"ClassType,"
|
|
|
|
|
"GroupName,"
|
|
|
|
|
"GrpCod"
|
2014-12-01 23:55:08 +01:00
|
|
|
|
" FROM timetable_crs"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE CrsCod=%ld"
|
2017-04-25 02:07:32 +02:00
|
|
|
|
" ORDER BY Weekday,S,ClassType,"
|
2017-04-24 18:53:25 +02:00
|
|
|
|
"GroupName,GrpCod,Place,D DESC",
|
2014-12-01 23:55:08 +01:00
|
|
|
|
Gbl.CurrentCrs.Crs.CrsCod);
|
|
|
|
|
else
|
2017-04-24 18:53:25 +02:00
|
|
|
|
sprintf (Query,"SELECT "
|
|
|
|
|
"timetable_crs.Weekday,"
|
2017-04-25 02:07:32 +02:00
|
|
|
|
"TIME_TO_SEC(timetable_crs.StartTime) AS S,"
|
2017-04-24 18:53:25 +02:00
|
|
|
|
"TIME_TO_SEC(timetable_crs.Duration) AS D,"
|
|
|
|
|
"timetable_crs.Place,"
|
|
|
|
|
"timetable_crs.ClassType,"
|
|
|
|
|
"timetable_crs.GroupName,"
|
|
|
|
|
"timetable_crs.GrpCod"
|
2014-12-01 23:55:08 +01:00
|
|
|
|
" FROM timetable_crs,crs_usr"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE timetable_crs.CrsCod=%ld"
|
|
|
|
|
" AND timetable_crs.GrpCod=-1 AND crs_usr.UsrCod=%ld"
|
|
|
|
|
" AND timetable_crs.CrsCod=crs_usr.CrsCod"
|
2014-12-01 23:55:08 +01:00
|
|
|
|
" UNION DISTINCT "
|
2017-04-24 18:53:25 +02:00
|
|
|
|
"SELECT timetable_crs.Weekday,"
|
2017-04-25 02:07:32 +02:00
|
|
|
|
"TIME_TO_SEC(timetable_crs.StartTime) AS S,"
|
2017-04-24 18:53:25 +02:00
|
|
|
|
"TIME_TO_SEC(timetable_crs.Duration) AS D,"
|
|
|
|
|
"timetable_crs.Place,"
|
|
|
|
|
"timetable_crs.ClassType,"
|
|
|
|
|
"timetable_crs.GroupName,"
|
|
|
|
|
"timetable_crs.GrpCod"
|
2014-12-01 23:55:08 +01:00
|
|
|
|
" FROM timetable_crs,crs_grp_usr"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE timetable_crs.CrsCod=%ld"
|
|
|
|
|
" AND crs_grp_usr.UsrCod=%ld"
|
|
|
|
|
" AND timetable_crs.GrpCod=crs_grp_usr.GrpCod"
|
2017-04-25 02:07:32 +02:00
|
|
|
|
" ORDER BY Weekday,S,ClassType,"
|
2017-04-24 18:53:25 +02:00
|
|
|
|
"GroupName,GrpCod,Place,D DESC",
|
2014-12-01 23:55:08 +01:00
|
|
|
|
Gbl.CurrentCrs.Crs.CrsCod,UsrCod,
|
|
|
|
|
Gbl.CurrentCrs.Crs.CrsCod,UsrCod);
|
|
|
|
|
break;
|
2017-04-24 13:00:59 +02:00
|
|
|
|
case TT_TUTORING_TIMETABLE:
|
2017-04-24 18:53:25 +02:00
|
|
|
|
sprintf (Query,"SELECT "
|
|
|
|
|
"Weekday,"
|
2017-04-25 02:07:32 +02:00
|
|
|
|
"TIME_TO_SEC(StartTime) AS S,"
|
2017-04-24 18:53:25 +02:00
|
|
|
|
"TIME_TO_SEC(Duration) AS D,"
|
|
|
|
|
"Place"
|
2014-12-01 23:55:08 +01:00
|
|
|
|
" FROM timetable_tut"
|
2017-03-24 01:09:27 +01:00
|
|
|
|
" WHERE UsrCod=%ld"
|
2017-04-25 02:07:32 +02:00
|
|
|
|
" ORDER BY Weekday,S,Place,D DESC",
|
2014-12-01 23:55:08 +01:00
|
|
|
|
UsrCod);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get timetable");
|
|
|
|
|
|
2017-04-25 21:20:19 +02:00
|
|
|
|
/***** If viewing (not editing) ==>
|
|
|
|
|
calculate range of hours and resolution *****/
|
2017-04-25 21:42:29 +02:00
|
|
|
|
if (Gbl.TimeTable.View == TT_CRS_VIEW ||
|
|
|
|
|
Gbl.TimeTable.View == TT_TUT_VIEW)
|
2017-04-25 14:48:47 +02:00
|
|
|
|
{
|
2017-04-25 21:20:19 +02:00
|
|
|
|
/* Initialize hours and resolution for timetable */
|
|
|
|
|
Gbl.TimeTable.Config.Range.Hours.Start = TT_END_HOUR; // Initialized to maximum hour
|
|
|
|
|
Gbl.TimeTable.Config.Range.Hours.End = TT_START_HOUR; // Initialized to minimum hour
|
|
|
|
|
Gbl.TimeTable.Config.Range.MinutesPerInterval = TT_MinutesPerInterval[TT_NUM_RESOLUTIONS - 1]; // The longest interval
|
2017-04-25 14:48:47 +02:00
|
|
|
|
|
|
|
|
|
for (NumRow = 0;
|
|
|
|
|
NumRow < NumRows;
|
|
|
|
|
NumRow++)
|
|
|
|
|
{
|
|
|
|
|
row = mysql_fetch_row (mysql_res);
|
|
|
|
|
|
|
|
|
|
/* StartTime formatted as seconds (row[1]) */
|
|
|
|
|
if (sscanf (row[1],"%u",&StartTimeSeconds) != 1)
|
|
|
|
|
Lay_ShowErrorAndExit ("Wrong start time in timetable.");
|
|
|
|
|
|
|
|
|
|
/* Duration formatted as seconds (row[2]) */
|
|
|
|
|
if (sscanf (row[2],"%u",&DurationSeconds) != 1)
|
|
|
|
|
Lay_ShowErrorAndExit ("Wrong duration in timetable.");
|
|
|
|
|
EndTimeSeconds = StartTimeSeconds + DurationSeconds;
|
|
|
|
|
|
2017-04-25 21:20:19 +02:00
|
|
|
|
/* Compute hours and resolution */
|
|
|
|
|
TT_CalculateRangeCell (StartTimeSeconds,EndTimeSeconds,&RangeCell);
|
|
|
|
|
if (RangeCell.Hours.Start < Gbl.TimeTable.Config.Range.Hours.Start)
|
|
|
|
|
Gbl.TimeTable.Config.Range.Hours.Start = RangeCell.Hours.Start;
|
|
|
|
|
if (RangeCell.Hours.End > Gbl.TimeTable.Config.Range.Hours.End)
|
|
|
|
|
Gbl.TimeTable.Config.Range.Hours.End = RangeCell.Hours.End;
|
|
|
|
|
if (RangeCell.MinutesPerInterval < Gbl.TimeTable.Config.Range.MinutesPerInterval)
|
|
|
|
|
Gbl.TimeTable.Config.Range.MinutesPerInterval = RangeCell.MinutesPerInterval;
|
|
|
|
|
|
2017-04-25 14:48:47 +02:00
|
|
|
|
}
|
|
|
|
|
mysql_data_seek (mysql_res,0);
|
|
|
|
|
|
2017-04-25 21:20:19 +02:00
|
|
|
|
/***** Configure and allocate timetable *****/
|
2017-04-25 14:48:47 +02:00
|
|
|
|
TT_TimeTableConfigureIntervalsAndAllocateTimeTable ();
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-25 21:20:19 +02:00
|
|
|
|
/***** Build the table by filling it from database *****/
|
|
|
|
|
if (Gbl.TimeTable.Config.HoursPerDay)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
2017-04-25 21:20:19 +02:00
|
|
|
|
/***** Initialize timetable to all free *****/
|
|
|
|
|
for (Weekday = 0;
|
|
|
|
|
Weekday < TT_DAYS_PER_WEEK;
|
|
|
|
|
Weekday++)
|
|
|
|
|
for (Interval = 0;
|
|
|
|
|
Interval < Gbl.TimeTable.Config.IntervalsPerDay;
|
|
|
|
|
Interval++)
|
|
|
|
|
{
|
|
|
|
|
TT_TimeTable[Weekday][Interval].NumColumns = 0;
|
|
|
|
|
for (Column = 0;
|
|
|
|
|
Column < TT_MAX_COLUMNS_PER_CELL;
|
|
|
|
|
Column++)
|
|
|
|
|
{
|
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[Column].CrsCod = -1L;
|
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[Column].GrpCod = -1L;
|
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[Column].IntervalType = TT_FREE_INTERVAL;
|
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[Column].ClassType = TT_FREE;
|
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[Column].DurationIntervals = 0;
|
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[Column].Group[0] = '\0';
|
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[Column].Place[0] = '\0';
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
2017-04-25 21:20:19 +02:00
|
|
|
|
/***** Fill data from database *****/
|
|
|
|
|
for (NumRow = 0;
|
|
|
|
|
NumRow < NumRows;
|
|
|
|
|
NumRow++)
|
|
|
|
|
{
|
|
|
|
|
row = mysql_fetch_row (mysql_res);
|
2017-04-25 02:07:32 +02:00
|
|
|
|
|
2017-04-25 21:20:19 +02:00
|
|
|
|
if (Gbl.TimeTable.Type == TT_MY_TIMETABLE ||
|
|
|
|
|
Gbl.TimeTable.Type == TT_COURSE_TIMETABLE)
|
|
|
|
|
/* Group code */
|
|
|
|
|
if (sscanf (row[6],"%ld",&GrpCod) != 1)
|
|
|
|
|
GrpCod = -1;
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
2017-04-25 21:20:19 +02:00
|
|
|
|
/* Day of week (row[0]) */
|
|
|
|
|
if (sscanf (row[0],"%u",&Weekday) != 1)
|
|
|
|
|
Lay_ShowErrorAndExit ("Wrong day of week in timetable.");
|
|
|
|
|
if (Weekday >= TT_DAYS_PER_WEEK)
|
|
|
|
|
Lay_ShowErrorAndExit ("Wrong day of week in timetable.");
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
2017-04-25 21:20:19 +02:00
|
|
|
|
/* StartTime formatted as seconds (row[1])
|
|
|
|
|
--> StartTime in number of intervals */
|
|
|
|
|
if (sscanf (row[1],"%u",&StartTimeSeconds) != 1)
|
|
|
|
|
Lay_ShowErrorAndExit ("Wrong start time in timetable.");
|
|
|
|
|
Interval = StartTimeSeconds /
|
|
|
|
|
Gbl.TimeTable.Config.SecondsPerInterval;
|
|
|
|
|
if (Interval < Gbl.TimeTable.Config.IntervalsBeforeStartHour)
|
|
|
|
|
Lay_ShowErrorAndExit ("Wrong start time in timetable.");
|
|
|
|
|
Interval -= Gbl.TimeTable.Config.IntervalsBeforeStartHour;
|
|
|
|
|
|
|
|
|
|
/* Duration formatted as seconds (row[2])
|
|
|
|
|
--> Duration in number of intervals */
|
|
|
|
|
if (sscanf (row[2],"%u",&DurationSeconds) != 1)
|
|
|
|
|
Lay_ShowErrorAndExit ("Wrong duration in timetable.");
|
|
|
|
|
DurationNumIntervals = DurationSeconds /
|
|
|
|
|
Gbl.TimeTable.Config.SecondsPerInterval;
|
|
|
|
|
|
|
|
|
|
/* Type of class (row[4]) */
|
|
|
|
|
switch (Gbl.TimeTable.Type)
|
|
|
|
|
{
|
|
|
|
|
case TT_COURSE_TIMETABLE:
|
|
|
|
|
case TT_MY_TIMETABLE:
|
|
|
|
|
for (ClassType = TT_LECTURE, Found = false;
|
|
|
|
|
ClassType <= TT_TUTORING;
|
|
|
|
|
ClassType++)
|
|
|
|
|
if (!strcmp (row[4],TT_ClassTypeDB[ClassType]))
|
|
|
|
|
{
|
|
|
|
|
Found = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!Found)
|
|
|
|
|
Lay_ShowErrorAndExit ("Wrong type of class in timetable.");
|
|
|
|
|
break;
|
|
|
|
|
case TT_TUTORING_TIMETABLE:
|
|
|
|
|
ClassType = TT_TUTORING;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Cell has been read without errors */
|
|
|
|
|
if (TT_TimeTable[Weekday][Interval].NumColumns < TT_MAX_COLUMNS_PER_CELL)
|
|
|
|
|
// If there's place for another column in this cell...
|
|
|
|
|
{
|
|
|
|
|
/* Find the first free column for this day-hour */
|
|
|
|
|
FirstFreeColumn = TT_MAX_COLUMNS_PER_CELL;
|
|
|
|
|
for (Column = 0;
|
|
|
|
|
Column < TT_MAX_COLUMNS_PER_CELL;
|
|
|
|
|
Column++)
|
|
|
|
|
if (TT_TimeTable[Weekday][Interval].Columns[Column].IntervalType == TT_FREE_INTERVAL)
|
|
|
|
|
{
|
|
|
|
|
FirstFreeColumn = Column;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (FirstFreeColumn < TT_MAX_COLUMNS_PER_CELL)
|
|
|
|
|
// If there's place for another column in this cell
|
|
|
|
|
{
|
|
|
|
|
/* Check if there's place for all the rows of this class */
|
|
|
|
|
TimeTableHasSpaceForThisClass = true;
|
|
|
|
|
for (i = Interval + 1;
|
|
|
|
|
i < Interval + DurationNumIntervals &&
|
|
|
|
|
i < Gbl.TimeTable.Config.IntervalsPerDay;
|
|
|
|
|
i++)
|
|
|
|
|
if (TT_TimeTable[Weekday][i].Columns[FirstFreeColumn].IntervalType != TT_FREE_INTERVAL)
|
|
|
|
|
{
|
|
|
|
|
TimeTableIsIncomplete = true;
|
|
|
|
|
TimeTableHasSpaceForThisClass = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (TimeTableHasSpaceForThisClass)
|
|
|
|
|
{
|
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[FirstFreeColumn].ClassType = ClassType;
|
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[FirstFreeColumn].DurationIntervals = DurationNumIntervals;
|
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[FirstFreeColumn].IntervalType = TT_FIRST_INTERVAL;
|
|
|
|
|
for (i = Interval + 1;
|
|
|
|
|
i < Interval + DurationNumIntervals &&
|
|
|
|
|
i < Gbl.TimeTable.Config.IntervalsPerDay;
|
|
|
|
|
i++)
|
|
|
|
|
{
|
|
|
|
|
TT_TimeTable[Weekday][i].Columns[FirstFreeColumn].IntervalType = TT_NEXT_INTERVAL;
|
|
|
|
|
TT_TimeTable[Weekday][i].NumColumns++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Course (row[7]), group (row[5]) and place (row[3])*/
|
|
|
|
|
switch (Gbl.TimeTable.Type)
|
|
|
|
|
{
|
|
|
|
|
case TT_MY_TIMETABLE:
|
|
|
|
|
case TT_COURSE_TIMETABLE:
|
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[FirstFreeColumn].CrsCod =
|
|
|
|
|
(Gbl.TimeTable.Type == TT_MY_TIMETABLE ? Str_ConvertStrCodToLongCod (row[7]) :
|
|
|
|
|
Gbl.CurrentCrs.Crs.CrsCod);
|
|
|
|
|
Str_Copy (TT_TimeTable[Weekday][Interval].Columns[FirstFreeColumn].Group,
|
|
|
|
|
row[5],
|
|
|
|
|
Grp_MAX_BYTES_GROUP_NAME);
|
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[FirstFreeColumn].GrpCod = GrpCod;
|
2018-10-04 21:57:25 +02:00
|
|
|
|
/* falls through */
|
|
|
|
|
/* no break */
|
2017-04-25 21:20:19 +02:00
|
|
|
|
case TT_TUTORING_TIMETABLE:
|
|
|
|
|
Str_Copy (TT_TimeTable[Weekday][Interval].Columns[FirstFreeColumn].Place,
|
|
|
|
|
row[3],
|
|
|
|
|
TT_MAX_BYTES_PLACE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Increment number of items in this cell */
|
|
|
|
|
TT_TimeTable[Weekday][Interval].NumColumns++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
TimeTableIsIncomplete = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
TimeTableIsIncomplete = true;
|
|
|
|
|
}
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***** Free structure that stores the query result *****/
|
|
|
|
|
DB_FreeMySQLResult (&mysql_res);
|
|
|
|
|
|
|
|
|
|
if (TimeTableIsIncomplete)
|
2017-05-11 23:45:46 +02:00
|
|
|
|
Ale_ShowAlert (Ale_INFO,Txt_Incomplete_timetable_for_lack_of_space);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
|
|
|
|
|
2017-04-25 14:48:47 +02:00
|
|
|
|
/*****************************************************************************/
|
2017-04-27 10:15:07 +02:00
|
|
|
|
/** Calculate range of a cell (start hour, end hour, minutes per interval) ***/
|
2017-04-25 14:48:47 +02:00
|
|
|
|
/*****************************************************************************/
|
2017-04-25 21:20:19 +02:00
|
|
|
|
|
|
|
|
|
static void TT_CalculateRangeCell (unsigned StartTimeSeconds,
|
|
|
|
|
unsigned EndTimeSeconds,
|
|
|
|
|
struct TT_Range *Range)
|
|
|
|
|
{
|
|
|
|
|
unsigned TimeMinutes;
|
|
|
|
|
unsigned MinutesPerIntervalForEndTime;
|
|
|
|
|
|
|
|
|
|
/***** Compute minimum hour *****/
|
|
|
|
|
// Example: if Seconds == 42300 (time == 11:45:00) =>
|
|
|
|
|
// TimeMinutes = 42300/60 = 705 =>
|
|
|
|
|
// Hour = 705/60 = 11
|
|
|
|
|
TimeMinutes = StartTimeSeconds / TT_SECONDS_PER_MINUTE;
|
|
|
|
|
Range->Hours.Start = TimeMinutes / TT_MINUTES_PER_HOUR;
|
|
|
|
|
|
|
|
|
|
/***** Compute maximum hour *****/
|
|
|
|
|
// Example: if Seconds == 42300 (time == 11:45:00) =>
|
|
|
|
|
// TimeMinutes = 42300/60 = 705 =>
|
|
|
|
|
// Hour = 705/60 = 11
|
|
|
|
|
// 705 % 60 = 45 ==> Hour = Hour+1 = 12
|
|
|
|
|
TimeMinutes = EndTimeSeconds / TT_SECONDS_PER_MINUTE;
|
|
|
|
|
Range->Hours.End = TimeMinutes / TT_MINUTES_PER_HOUR;
|
|
|
|
|
if (TimeMinutes % TT_MINUTES_PER_HOUR)
|
|
|
|
|
Range->Hours.End++;
|
|
|
|
|
|
|
|
|
|
/***** Compute resolution (longest interval necessary for this cell) *****/
|
|
|
|
|
Range->MinutesPerInterval = TT_CalculateMinutesPerInterval (StartTimeSeconds);
|
|
|
|
|
if (Range->MinutesPerInterval > TT_MinutesPerInterval[0]) // If not already the shortest
|
|
|
|
|
{
|
|
|
|
|
MinutesPerIntervalForEndTime = TT_CalculateMinutesPerInterval (EndTimeSeconds);
|
|
|
|
|
if (MinutesPerIntervalForEndTime < Range->MinutesPerInterval)
|
|
|
|
|
Range->MinutesPerInterval = MinutesPerIntervalForEndTime;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-27 10:15:07 +02:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/*********************** Calculate minutes per interval **********************/
|
|
|
|
|
/*****************************************************************************/
|
2017-04-25 14:48:47 +02:00
|
|
|
|
// Example: if Seconds == 42300 (time == 11:45:00) => Minutes = 45 => Resolution = 15
|
|
|
|
|
|
2017-04-25 21:20:19 +02:00
|
|
|
|
static unsigned TT_CalculateMinutesPerInterval (unsigned Seconds)
|
2017-04-25 14:48:47 +02:00
|
|
|
|
{
|
|
|
|
|
unsigned Minutes;
|
2017-04-25 21:20:19 +02:00
|
|
|
|
unsigned MinutesPerInterval;
|
|
|
|
|
unsigned Resolution;
|
2017-04-25 14:48:47 +02:00
|
|
|
|
|
2017-04-25 21:20:19 +02:00
|
|
|
|
/***** Compute minutes part (45) of a time (11:45:00) from seconds (42300) *****/
|
2017-04-25 14:48:47 +02:00
|
|
|
|
Minutes = (Seconds / TT_SECONDS_PER_MINUTE) % TT_MINUTES_PER_HOUR;
|
|
|
|
|
|
2017-04-25 21:20:19 +02:00
|
|
|
|
/***** Compute minutes per interval *****/
|
|
|
|
|
MinutesPerInterval = TT_MinutesPerInterval[0]; // Default: the shortest interval
|
|
|
|
|
for (Resolution = TT_NUM_RESOLUTIONS - 1; // From the longest interval...
|
|
|
|
|
Resolution > 0;
|
|
|
|
|
Resolution--) // ...to shorter intervals
|
|
|
|
|
if (Minutes % TT_MinutesPerInterval[Resolution] == 0)
|
2017-04-25 14:48:47 +02:00
|
|
|
|
{
|
2017-04-25 21:20:19 +02:00
|
|
|
|
MinutesPerInterval = TT_MinutesPerInterval[Resolution];
|
2017-04-25 14:48:47 +02:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-25 21:20:19 +02:00
|
|
|
|
return MinutesPerInterval;
|
2017-04-25 14:48:47 +02:00
|
|
|
|
}
|
|
|
|
|
|
2014-12-01 23:55:08 +01:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/*********************** Modify a class in timetable *************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void TT_ModifTimeTable (void)
|
|
|
|
|
{
|
2017-04-24 21:12:53 +02:00
|
|
|
|
if (TT_TimeTable[Gbl.TimeTable.Weekday][Gbl.TimeTable.Interval].Columns[Gbl.TimeTable.Column].IntervalType == TT_FIRST_INTERVAL)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
|
|
|
|
/***** Free this cell *****/
|
2017-04-25 21:20:19 +02:00
|
|
|
|
TT_TimeTable[Gbl.TimeTable.Weekday][Gbl.TimeTable.Interval].Columns[Gbl.TimeTable.Column].GrpCod = -1L;
|
|
|
|
|
TT_TimeTable[Gbl.TimeTable.Weekday][Gbl.TimeTable.Interval].Columns[Gbl.TimeTable.Column].IntervalType = TT_FREE_INTERVAL;
|
|
|
|
|
TT_TimeTable[Gbl.TimeTable.Weekday][Gbl.TimeTable.Interval].Columns[Gbl.TimeTable.Column].ClassType = TT_FREE;
|
|
|
|
|
TT_TimeTable[Gbl.TimeTable.Weekday][Gbl.TimeTable.Interval].Columns[Gbl.TimeTable.Column].DurationIntervals = 0;
|
|
|
|
|
TT_TimeTable[Gbl.TimeTable.Weekday][Gbl.TimeTable.Interval].Columns[Gbl.TimeTable.Column].Group[0] = '\0';
|
|
|
|
|
TT_TimeTable[Gbl.TimeTable.Weekday][Gbl.TimeTable.Interval].Columns[Gbl.TimeTable.Column].Place[0] = '\0';
|
2017-04-24 21:12:53 +02:00
|
|
|
|
TT_TimeTable[Gbl.TimeTable.Weekday][Gbl.TimeTable.Interval].NumColumns--;
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
|
|
|
|
|
2017-04-24 21:12:53 +02:00
|
|
|
|
if (Gbl.TimeTable.ClassType != TT_FREE &&
|
2017-04-25 21:20:19 +02:00
|
|
|
|
Gbl.TimeTable.DurationIntervals > 0 &&
|
2017-04-24 21:12:53 +02:00
|
|
|
|
TT_TimeTable[Gbl.TimeTable.Weekday][Gbl.TimeTable.Interval].NumColumns < TT_MAX_COLUMNS_PER_CELL)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
|
|
|
|
/***** Change this cell *****/
|
2017-04-24 21:12:53 +02:00
|
|
|
|
TT_TimeTable[Gbl.TimeTable.Weekday][Gbl.TimeTable.Interval].NumColumns++;
|
2017-04-25 21:20:19 +02:00
|
|
|
|
TT_TimeTable[Gbl.TimeTable.Weekday][Gbl.TimeTable.Interval].Columns[Gbl.TimeTable.Column].GrpCod = Gbl.TimeTable.GrpCod;
|
|
|
|
|
TT_TimeTable[Gbl.TimeTable.Weekday][Gbl.TimeTable.Interval].Columns[Gbl.TimeTable.Column].IntervalType = TT_FIRST_INTERVAL;
|
|
|
|
|
TT_TimeTable[Gbl.TimeTable.Weekday][Gbl.TimeTable.Interval].Columns[Gbl.TimeTable.Column].ClassType = Gbl.TimeTable.ClassType;
|
|
|
|
|
TT_TimeTable[Gbl.TimeTable.Weekday][Gbl.TimeTable.Interval].Columns[Gbl.TimeTable.Column].DurationIntervals = Gbl.TimeTable.DurationIntervals;
|
2017-04-24 21:12:53 +02:00
|
|
|
|
Str_Copy (TT_TimeTable[Gbl.TimeTable.Weekday][Gbl.TimeTable.Interval].Columns[Gbl.TimeTable.Column].Group,
|
2017-01-17 03:10:43 +01:00
|
|
|
|
Gbl.TimeTable.Group,
|
2017-03-08 03:48:23 +01:00
|
|
|
|
Grp_MAX_BYTES_GROUP_NAME);
|
2017-04-24 21:12:53 +02:00
|
|
|
|
Str_Copy (TT_TimeTable[Gbl.TimeTable.Weekday][Gbl.TimeTable.Interval].Columns[Gbl.TimeTable.Column].Place,
|
2017-01-17 03:10:43 +01:00
|
|
|
|
Gbl.TimeTable.Place,
|
|
|
|
|
TT_MAX_BYTES_PLACE);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/********************* Draw timetable using internal table *******************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2016-03-18 14:07:21 +01:00
|
|
|
|
static void TT_DrawTimeTable (void)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
2015-11-30 21:23:14 +01:00
|
|
|
|
unsigned DayColumn; // Column from left (0) to right (6)
|
2017-04-24 21:12:53 +02:00
|
|
|
|
unsigned Weekday; // Day of week
|
|
|
|
|
unsigned Interval;
|
2017-04-24 01:56:57 +02:00
|
|
|
|
unsigned Min;
|
2015-11-30 21:23:14 +01:00
|
|
|
|
unsigned Column;
|
|
|
|
|
unsigned ColumnsToDraw;
|
|
|
|
|
unsigned ColumnsToDrawIncludingExtraColumn;
|
|
|
|
|
unsigned ContinuousFreeMinicolumns;
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
2017-06-12 14:16:33 +02:00
|
|
|
|
/***** Start table *****/
|
2015-11-30 20:47:37 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"<table id=\"timetable\">");
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
|
|
|
|
/***** Top row used for column adjustement *****/
|
|
|
|
|
TT_TimeTableDrawAdjustRow ();
|
|
|
|
|
|
|
|
|
|
/***** Row with day names *****/
|
|
|
|
|
fprintf (Gbl.F.Out,"<tr>"
|
2017-04-24 10:13:53 +02:00
|
|
|
|
"<td rowspan=\"2\" class=\"TT_HOUR_BIG RIGHT_MIDDLE\""
|
|
|
|
|
" style=\"width:%u%%;\">"
|
2017-04-25 14:48:47 +02:00
|
|
|
|
"%02u:00"
|
2014-12-26 16:55:46 +01:00
|
|
|
|
"</td>",
|
2017-04-25 11:57:36 +02:00
|
|
|
|
TT_PERCENT_WIDTH_OF_AN_HOUR_COLUMN,
|
2017-04-25 21:20:19 +02:00
|
|
|
|
Gbl.TimeTable.Config.Range.Hours.Start);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
TT_DrawCellAlignTimeTable ();
|
|
|
|
|
TT_TimeTableDrawDaysCells ();
|
|
|
|
|
TT_DrawCellAlignTimeTable ();
|
2017-04-24 10:13:53 +02:00
|
|
|
|
fprintf (Gbl.F.Out,"<td rowspan=\"2\" class=\"TT_HOUR_BIG LEFT_MIDDLE\""
|
|
|
|
|
" style=\"width:%u%%;\">"
|
2017-04-25 14:48:47 +02:00
|
|
|
|
"%02u:00"
|
2014-12-26 16:55:46 +01:00
|
|
|
|
"</td>"
|
2014-12-01 23:55:08 +01:00
|
|
|
|
"</tr>",
|
2017-04-24 01:56:57 +02:00
|
|
|
|
TT_PERCENT_WIDTH_OF_AN_HOUR_COLUMN,
|
2017-04-25 21:20:19 +02:00
|
|
|
|
Gbl.TimeTable.Config.Range.Hours.Start);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
|
|
|
|
/***** Get list of groups types and groups in this course *****/
|
2016-01-17 15:10:54 +01:00
|
|
|
|
if (Gbl.Action.Act == ActEdiCrsTT ||
|
|
|
|
|
Gbl.Action.Act == ActChgCrsTT)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
Grp_GetListGrpTypesAndGrpsInThisCrs (Grp_ONLY_GROUP_TYPES_WITH_GROUPS);
|
|
|
|
|
|
|
|
|
|
/***** Write the table row by row *****/
|
2017-04-25 21:20:19 +02:00
|
|
|
|
for (Interval = 0, Min = Gbl.TimeTable.Config.Range.MinutesPerInterval;
|
2017-04-25 11:57:36 +02:00
|
|
|
|
Interval < Gbl.TimeTable.Config.IntervalsPerDay;
|
|
|
|
|
Interval++,
|
2017-04-25 21:20:19 +02:00
|
|
|
|
Min = (Min + Gbl.TimeTable.Config.Range.MinutesPerInterval) %
|
2017-04-25 11:57:36 +02:00
|
|
|
|
TT_SECONDS_PER_MINUTE)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
|
|
|
|
fprintf (Gbl.F.Out,"<tr>");
|
|
|
|
|
|
2017-04-24 21:12:53 +02:00
|
|
|
|
/* Left hour:minutes cell */
|
|
|
|
|
if (Interval % 2)
|
2017-04-25 21:20:19 +02:00
|
|
|
|
TT_TimeTableDrawHourCell (Gbl.TimeTable.Config.Range.Hours.Start +
|
2017-04-25 11:57:36 +02:00
|
|
|
|
(Interval + 2) / Gbl.TimeTable.Config.IntervalsPerHour,
|
2017-04-24 21:12:53 +02:00
|
|
|
|
Min,
|
|
|
|
|
"RIGHT_MIDDLE");
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
|
|
|
|
/* Empty column used to adjust height */
|
|
|
|
|
TT_DrawCellAlignTimeTable ();
|
|
|
|
|
|
|
|
|
|
/* Row for this hour */
|
2015-11-30 21:23:14 +01:00
|
|
|
|
for (DayColumn = 0;
|
2017-04-24 21:12:53 +02:00
|
|
|
|
DayColumn < TT_DAYS_PER_WEEK;
|
2015-11-30 21:23:14 +01:00
|
|
|
|
DayColumn++)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
2017-04-24 21:12:53 +02:00
|
|
|
|
/* Weekday == 0 ==> monday,
|
2015-11-30 21:23:14 +01:00
|
|
|
|
...
|
2017-04-24 21:12:53 +02:00
|
|
|
|
Weekday == 6 ==> sunday */
|
|
|
|
|
Weekday = (DayColumn + Gbl.Prefs.FirstDayOfWeek) % 7;
|
2015-11-30 21:23:14 +01:00
|
|
|
|
|
2014-12-01 23:55:08 +01:00
|
|
|
|
/* Check how many colums are needed.
|
2017-04-25 02:07:32 +02:00
|
|
|
|
For each item (class) in this hour from left to right,
|
|
|
|
|
we must check the maximum of columns */
|
2017-04-25 11:57:36 +02:00
|
|
|
|
ColumnsToDraw = TT_CalculateColsToDrawInCell (true, // Top call, non recursive
|
|
|
|
|
Weekday,Interval);
|
2017-04-25 21:42:29 +02:00
|
|
|
|
if (ColumnsToDraw == 0 &&
|
|
|
|
|
(Gbl.TimeTable.View == TT_CRS_VIEW ||
|
|
|
|
|
Gbl.TimeTable.View == TT_TUT_VIEW))
|
2014-12-01 23:55:08 +01:00
|
|
|
|
ColumnsToDraw = 1;
|
2017-04-25 14:48:47 +02:00
|
|
|
|
// If editing and there's place for more columns,
|
|
|
|
|
// a potential new column is added at the end of each day
|
2014-12-01 23:55:08 +01:00
|
|
|
|
ColumnsToDrawIncludingExtraColumn = ColumnsToDraw;
|
2017-04-25 21:42:29 +02:00
|
|
|
|
if (ColumnsToDraw < TT_MAX_COLUMNS_PER_CELL &&
|
|
|
|
|
(Gbl.TimeTable.View == TT_CRS_EDIT ||
|
|
|
|
|
Gbl.TimeTable.View == TT_TUT_EDIT))
|
2014-12-01 23:55:08 +01:00
|
|
|
|
ColumnsToDrawIncludingExtraColumn++;
|
|
|
|
|
|
2017-04-24 01:56:57 +02:00
|
|
|
|
/* Draw cells */
|
2014-12-01 23:55:08 +01:00
|
|
|
|
for (Column = 0, ContinuousFreeMinicolumns = 0;
|
|
|
|
|
Column < ColumnsToDrawIncludingExtraColumn;
|
|
|
|
|
Column++)
|
2017-04-24 21:12:53 +02:00
|
|
|
|
if (TT_TimeTable[Weekday][Interval].Columns[Column].IntervalType == TT_FREE_INTERVAL)
|
|
|
|
|
ContinuousFreeMinicolumns += TT_NUM_MINICOLUMNS_PER_DAY /
|
|
|
|
|
ColumnsToDrawIncludingExtraColumn;
|
2014-12-01 23:55:08 +01:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (ContinuousFreeMinicolumns)
|
|
|
|
|
{
|
2017-04-24 21:12:53 +02:00
|
|
|
|
TT_TimeTableDrawCell (Weekday,Interval,Column - 1,ContinuousFreeMinicolumns,
|
|
|
|
|
-1L,TT_FREE_INTERVAL,TT_FREE,0,NULL,-1,NULL);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
ContinuousFreeMinicolumns = 0;
|
|
|
|
|
}
|
2017-04-24 21:12:53 +02:00
|
|
|
|
TT_TimeTableDrawCell (Weekday,Interval,Column,
|
|
|
|
|
TT_NUM_MINICOLUMNS_PER_DAY /
|
|
|
|
|
ColumnsToDrawIncludingExtraColumn,
|
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[Column].CrsCod,
|
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[Column].IntervalType,
|
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[Column].ClassType,
|
2017-04-25 21:20:19 +02:00
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[Column].DurationIntervals,
|
2017-04-24 21:12:53 +02:00
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[Column].Group,
|
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[Column].GrpCod,
|
|
|
|
|
TT_TimeTable[Weekday][Interval].Columns[Column].Place);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
|
|
|
|
if (ContinuousFreeMinicolumns)
|
2017-04-24 21:12:53 +02:00
|
|
|
|
TT_TimeTableDrawCell (Weekday,Interval,Column - 1,ContinuousFreeMinicolumns,
|
|
|
|
|
-1L,TT_FREE_INTERVAL,TT_FREE,0,NULL,-1L,NULL);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Empty column used to adjust height */
|
|
|
|
|
TT_DrawCellAlignTimeTable ();
|
|
|
|
|
|
2017-04-24 21:12:53 +02:00
|
|
|
|
/* Right hour:minutes cell */
|
|
|
|
|
if (Interval % 2)
|
2017-04-25 21:20:19 +02:00
|
|
|
|
TT_TimeTableDrawHourCell (Gbl.TimeTable.Config.Range.Hours.Start +
|
2017-04-25 11:57:36 +02:00
|
|
|
|
(Interval + 2) / Gbl.TimeTable.Config.IntervalsPerHour,
|
2017-04-24 21:12:53 +02:00
|
|
|
|
Min,
|
|
|
|
|
"LEFT_MIDDLE");
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
|
|
|
|
fprintf (Gbl.F.Out,"</tr>");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***** Free list of groups types and groups in this course *****/
|
2016-01-17 15:10:54 +01:00
|
|
|
|
if (Gbl.Action.Act == ActEdiCrsTT ||
|
|
|
|
|
Gbl.Action.Act == ActChgCrsTT)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
Grp_FreeListGrpTypesAndGrps ();
|
|
|
|
|
|
|
|
|
|
/***** Row with day names *****/
|
|
|
|
|
fprintf (Gbl.F.Out,"<tr>");
|
|
|
|
|
TT_DrawCellAlignTimeTable ();
|
|
|
|
|
TT_TimeTableDrawDaysCells ();
|
|
|
|
|
TT_DrawCellAlignTimeTable ();
|
|
|
|
|
fprintf (Gbl.F.Out,"</tr>");
|
|
|
|
|
|
|
|
|
|
/***** Bottom row used for column adjustement *****/
|
|
|
|
|
TT_TimeTableDrawAdjustRow ();
|
|
|
|
|
|
2017-06-12 14:16:33 +02:00
|
|
|
|
/***** End table *****/
|
2014-12-01 23:55:08 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"</table>");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/********** Draw a row used for column adjustement in a time table ***********/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void TT_TimeTableDrawAdjustRow (void)
|
|
|
|
|
{
|
2017-04-24 21:12:53 +02:00
|
|
|
|
unsigned Weekday;
|
2014-12-01 23:55:08 +01:00
|
|
|
|
unsigned Minicolumn;
|
|
|
|
|
|
|
|
|
|
fprintf (Gbl.F.Out,"<tr>"
|
2017-04-25 21:20:19 +02:00
|
|
|
|
"<td class=\"TT_HOURCOL\"></td>");
|
2017-04-24 10:13:53 +02:00
|
|
|
|
TT_DrawCellAlignTimeTable ();
|
2017-04-24 21:12:53 +02:00
|
|
|
|
for (Weekday = 0;
|
|
|
|
|
Weekday < TT_DAYS_PER_WEEK;
|
|
|
|
|
Weekday++)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
for (Minicolumn = 0;
|
|
|
|
|
Minicolumn < TT_NUM_MINICOLUMNS_PER_DAY;
|
|
|
|
|
Minicolumn++)
|
2017-04-25 21:20:19 +02:00
|
|
|
|
fprintf (Gbl.F.Out,"<td class=\"TT_MINICOL\"></td>");
|
2017-04-24 10:13:53 +02:00
|
|
|
|
TT_DrawCellAlignTimeTable ();
|
2017-04-25 21:20:19 +02:00
|
|
|
|
fprintf (Gbl.F.Out,"<td class=\"TT_HOURCOL\"></td>"
|
|
|
|
|
"</tr>");
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/****************** Draw cells with day names in a time table ****************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void TT_TimeTableDrawDaysCells (void)
|
|
|
|
|
{
|
|
|
|
|
extern const char *Txt_DAYS_CAPS[7];
|
2015-11-30 21:23:14 +01:00
|
|
|
|
unsigned DayColumn;
|
2017-04-24 21:12:53 +02:00
|
|
|
|
unsigned Weekday;
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
2015-11-30 21:23:14 +01:00
|
|
|
|
for (DayColumn = 0;
|
2017-04-24 21:12:53 +02:00
|
|
|
|
DayColumn < TT_DAYS_PER_WEEK;
|
2015-11-30 21:23:14 +01:00
|
|
|
|
DayColumn++)
|
|
|
|
|
{
|
2017-04-24 21:12:53 +02:00
|
|
|
|
Weekday = (DayColumn + Gbl.Prefs.FirstDayOfWeek) % 7;
|
2017-04-24 01:56:57 +02:00
|
|
|
|
fprintf (Gbl.F.Out,"<td colspan=\"%u\""
|
|
|
|
|
" class=\"%s CENTER_MIDDLE\""
|
2015-09-02 23:51:44 +02:00
|
|
|
|
" style=\"width:%u%%;\">"
|
2014-12-26 16:55:46 +01:00
|
|
|
|
"%s"
|
|
|
|
|
"</td>",
|
2015-11-30 21:23:14 +01:00
|
|
|
|
TT_NUM_MINICOLUMNS_PER_DAY,
|
2017-04-24 21:12:53 +02:00
|
|
|
|
Weekday == 6 ? "TT_SUNDAY" : // Sunday drawn in red
|
|
|
|
|
"TT_DAY", // Monday to Saturday
|
2015-11-30 21:23:14 +01:00
|
|
|
|
TT_PERCENT_WIDTH_OF_A_DAY,
|
2017-04-24 21:12:53 +02:00
|
|
|
|
Txt_DAYS_CAPS[Weekday]);
|
2015-11-30 21:23:14 +01:00
|
|
|
|
}
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
|
|
|
|
|
2017-04-24 10:13:53 +02:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/****************** Draw cells with day names in a time table ****************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-04-24 21:12:53 +02:00
|
|
|
|
static void TT_TimeTableDrawHourCell (unsigned Hour,unsigned Min,const char *Align)
|
2017-04-24 10:13:53 +02:00
|
|
|
|
{
|
2017-04-25 21:20:19 +02:00
|
|
|
|
fprintf (Gbl.F.Out,"<td rowspan=\"2\" class=\"TT_HOUR %s %s\">"
|
2017-04-25 14:48:47 +02:00
|
|
|
|
"%02u:%02u"
|
|
|
|
|
"</td>",
|
2017-04-24 10:13:53 +02:00
|
|
|
|
Min ? "TT_HOUR_SMALL" :
|
|
|
|
|
"TT_HOUR_BIG",
|
|
|
|
|
Align,
|
2017-04-25 14:48:47 +02:00
|
|
|
|
Hour,Min);
|
2017-04-24 10:13:53 +02:00
|
|
|
|
}
|
|
|
|
|
|
2014-12-01 23:55:08 +01:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/**** Calculate recursively number of columns to draw for a day and hour *****/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-04-25 11:57:36 +02:00
|
|
|
|
static unsigned TT_CalculateColsToDrawInCell (bool TopCall,
|
|
|
|
|
unsigned Weekday,unsigned Interval)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
2015-11-30 21:23:14 +01:00
|
|
|
|
unsigned ColumnsToDraw;
|
|
|
|
|
unsigned Column;
|
2017-04-25 21:20:19 +02:00
|
|
|
|
unsigned i;
|
2015-11-30 21:23:14 +01:00
|
|
|
|
unsigned FirstHour;
|
|
|
|
|
unsigned Cols;
|
2017-04-25 11:57:36 +02:00
|
|
|
|
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.");
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
2017-04-24 21:12:53 +02:00
|
|
|
|
ColumnsToDraw = TT_TimeTable[Weekday][Interval].NumColumns;
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
2017-04-25 11:57:36 +02:00
|
|
|
|
if (!TT_IntervalsChecked[Interval])
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
2017-04-25 11:57:36 +02:00
|
|
|
|
TT_IntervalsChecked[Interval] = true;
|
2014-12-01 23:55:08 +01:00
|
|
|
|
for (Column = 0;
|
|
|
|
|
Column < TT_MAX_COLUMNS_PER_CELL;
|
|
|
|
|
Column++)
|
2017-04-24 21:12:53 +02:00
|
|
|
|
switch (TT_TimeTable[Weekday][Interval].Columns[Column].IntervalType)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
2017-04-24 21:12:53 +02:00
|
|
|
|
case TT_FREE_INTERVAL:
|
2014-12-01 23:55:08 +01:00
|
|
|
|
break;
|
2017-04-24 21:12:53 +02:00
|
|
|
|
case TT_FIRST_INTERVAL:
|
2017-04-27 10:15:07 +02:00
|
|
|
|
/* Check from first hour (this one) to last hour
|
|
|
|
|
searching maximum number of columns */
|
2017-04-25 21:20:19 +02:00
|
|
|
|
for (i = Interval + 1;
|
|
|
|
|
i < Interval + TT_TimeTable[Weekday][Interval].Columns[Column].DurationIntervals;
|
|
|
|
|
i++)
|
|
|
|
|
if (!TT_IntervalsChecked[i])
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
2017-04-25 11:57:36 +02:00
|
|
|
|
Cols = TT_CalculateColsToDrawInCell (false, // Recursive call
|
2017-04-25 21:20:19 +02:00
|
|
|
|
Weekday,i);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
if (Cols > ColumnsToDraw)
|
|
|
|
|
ColumnsToDraw = Cols;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2017-04-24 21:12:53 +02:00
|
|
|
|
case TT_NEXT_INTERVAL:
|
2014-12-01 23:55:08 +01:00
|
|
|
|
/* Find first hour for this item (class) */
|
2017-04-24 21:12:53 +02:00
|
|
|
|
for (FirstHour = Interval;
|
|
|
|
|
TT_TimeTable[Weekday][FirstHour].Columns[Column].IntervalType == TT_NEXT_INTERVAL;
|
2014-12-01 23:55:08 +01:00
|
|
|
|
FirstHour--);
|
2017-04-25 11:57:36 +02:00
|
|
|
|
|
2017-04-27 10:15:07 +02:00
|
|
|
|
/* Check from first hour to last hour
|
|
|
|
|
searching maximum number of columns */
|
2017-04-25 21:20:19 +02:00
|
|
|
|
for (i = FirstHour;
|
|
|
|
|
i < FirstHour + TT_TimeTable[Weekday][FirstHour].Columns[Column].DurationIntervals;
|
|
|
|
|
i++)
|
|
|
|
|
if (!TT_IntervalsChecked[i])
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
2017-04-25 11:57:36 +02:00
|
|
|
|
Cols = TT_CalculateColsToDrawInCell (false, // Recursive call
|
2017-04-25 21:20:19 +02:00
|
|
|
|
Weekday,i);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
if (Cols > ColumnsToDraw)
|
|
|
|
|
ColumnsToDraw = Cols;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-04-25 11:57:36 +02:00
|
|
|
|
|
|
|
|
|
if (TopCall) // Top call, non recursive call
|
|
|
|
|
/****** Free space used by list of intervals already checked *****/
|
|
|
|
|
free ((void *) TT_IntervalsChecked);
|
|
|
|
|
|
2014-12-01 23:55:08 +01:00
|
|
|
|
return ColumnsToDraw;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/******************** Write empty cell for alignment *************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void TT_DrawCellAlignTimeTable (void)
|
|
|
|
|
{
|
2017-04-25 21:20:19 +02:00
|
|
|
|
fprintf (Gbl.F.Out,"<td class=\"TT_ALIGN\"></td>");
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/*************************** Write a timetable cell **************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-04-24 21:12:53 +02:00
|
|
|
|
static void TT_TimeTableDrawCell (unsigned Weekday,unsigned Interval,unsigned Column,unsigned ColSpan,
|
|
|
|
|
long CrsCod,TT_IntervalType_t IntervalType,TT_ClassType_t ClassType,
|
|
|
|
|
unsigned DurationNumIntervals,char *Group,long GrpCod,char *Place)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
2016-10-02 20:03:21 +02:00
|
|
|
|
extern const char *Txt_unknown_removed_course;
|
2015-01-02 12:57:26 +01:00
|
|
|
|
extern const char *Txt_TIMETABLE_CLASS_TYPES[TT_NUM_CLASS_TYPES];
|
2014-12-01 23:55:08 +01:00
|
|
|
|
extern const char *Txt_Group;
|
|
|
|
|
extern const char *Txt_All_groups;
|
|
|
|
|
extern const char *Txt_Classroom;
|
|
|
|
|
extern const char *Txt_Place;
|
|
|
|
|
static const char *TimeTableClasses[TT_NUM_CLASS_TYPES] =
|
|
|
|
|
{
|
2017-04-25 21:42:29 +02:00
|
|
|
|
"TT_FREE", // TT_FREE (free hour)
|
|
|
|
|
"TT_LECT", // TT_LECTURE (lecture class)
|
|
|
|
|
"TT_PRAC", // TT_PRACTICAL (practical class)
|
|
|
|
|
"TT_TUTO", // TT_TUTORING (tutoring/office hour)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
};
|
|
|
|
|
struct GroupData GrpDat;
|
|
|
|
|
unsigned NumGrpTyp;
|
|
|
|
|
unsigned NumGrp;
|
2017-04-25 21:20:19 +02:00
|
|
|
|
unsigned i;
|
2014-12-01 23:55:08 +01:00
|
|
|
|
unsigned Dur;
|
|
|
|
|
unsigned MaxDuration;
|
|
|
|
|
unsigned RowSpan = 0;
|
2017-04-24 13:39:55 +02:00
|
|
|
|
TT_ClassType_t CT;
|
2014-12-01 23:55:08 +01:00
|
|
|
|
struct Course Crs;
|
|
|
|
|
|
|
|
|
|
/***** Compute row span and background color depending on hour type *****/
|
2017-04-24 21:12:53 +02:00
|
|
|
|
switch (IntervalType)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
2017-04-24 21:12:53 +02:00
|
|
|
|
case TT_FREE_INTERVAL: // Free cell written
|
2015-11-30 20:47:37 +01:00
|
|
|
|
RowSpan = 1;
|
2014-12-01 23:55:08 +01:00
|
|
|
|
break;
|
2017-04-24 21:12:53 +02:00
|
|
|
|
case TT_FIRST_INTERVAL: // Normal cell written
|
|
|
|
|
RowSpan = DurationNumIntervals;
|
2014-12-01 23:55:08 +01:00
|
|
|
|
break;
|
2017-04-24 21:12:53 +02:00
|
|
|
|
case TT_NEXT_INTERVAL: // Nothing written
|
2014-12-01 23:55:08 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***** If there's nothing to do... *****/
|
|
|
|
|
if (RowSpan == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/***** If group code > 0, a group is selected ==> get group type and name *****/
|
2017-04-24 21:12:53 +02:00
|
|
|
|
if (IntervalType == TT_FIRST_INTERVAL &&
|
2017-04-25 21:42:29 +02:00
|
|
|
|
(Gbl.TimeTable.View == TT_CRS_VIEW ||
|
|
|
|
|
Gbl.TimeTable.View == TT_CRS_EDIT) &&
|
2014-12-01 23:55:08 +01:00
|
|
|
|
GrpCod > 0)
|
|
|
|
|
{
|
|
|
|
|
/* Get group type and name */
|
|
|
|
|
GrpDat.GrpCod = GrpCod;
|
|
|
|
|
Grp_GetDataOfGroupByCod (&GrpDat);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***** Cell start *****/
|
2017-04-25 21:20:19 +02:00
|
|
|
|
fprintf (Gbl.F.Out,"<td");
|
|
|
|
|
if (RowSpan > 1)
|
|
|
|
|
fprintf (Gbl.F.Out," rowspan=\"%u\"",RowSpan);
|
|
|
|
|
if (ColSpan > 1)
|
|
|
|
|
fprintf (Gbl.F.Out," colspan=\"%u\"",ColSpan);
|
|
|
|
|
fprintf (Gbl.F.Out," class=\"%s",TimeTableClasses[ClassType]);
|
2017-04-24 13:39:55 +02:00
|
|
|
|
if (ClassType == TT_FREE)
|
2017-04-24 21:12:53 +02:00
|
|
|
|
fprintf (Gbl.F.Out,"%u",Interval % 4);
|
2017-04-25 21:20:19 +02:00
|
|
|
|
else
|
|
|
|
|
fprintf (Gbl.F.Out," CENTER_MIDDLE DAT_SMALL");
|
|
|
|
|
fprintf (Gbl.F.Out,"\">");
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
|
|
|
|
/***** Form to modify this cell *****/
|
2017-04-25 21:42:29 +02:00
|
|
|
|
if (Gbl.TimeTable.View == TT_CRS_EDIT)
|
2018-10-15 14:07:12 +02:00
|
|
|
|
Act_StartForm (ActChgCrsTT);
|
2017-04-25 21:42:29 +02:00
|
|
|
|
else if (Gbl.TimeTable.View == TT_TUT_EDIT)
|
2018-10-15 14:07:12 +02:00
|
|
|
|
Act_StartForm (ActChgTut);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
|
|
|
|
/***** Draw cell depending on type of view *****/
|
2017-04-25 21:42:29 +02:00
|
|
|
|
switch (Gbl.TimeTable.View)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
2017-04-25 21:42:29 +02:00
|
|
|
|
case TT_CRS_VIEW: // View course timetable
|
|
|
|
|
case TT_TUT_VIEW: // View tutoring timetable
|
2017-04-24 21:12:53 +02:00
|
|
|
|
if (IntervalType != TT_FREE_INTERVAL) // If cell is not empty...
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
2017-04-25 02:07:32 +02:00
|
|
|
|
/***** Start cell *****/
|
2017-03-05 19:15:57 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"<div class=\"TT_CELL TT_TXT\">");
|
2017-04-25 02:07:32 +02:00
|
|
|
|
|
|
|
|
|
/***** Course name *****/
|
2016-03-18 14:07:21 +01:00
|
|
|
|
if (Gbl.TimeTable.Type == TT_MY_TIMETABLE)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
|
|
|
|
Crs.CrsCod = CrsCod;
|
|
|
|
|
Crs_GetDataOfCourseByCod (&Crs);
|
2017-04-24 13:39:55 +02:00
|
|
|
|
if (ClassType == TT_LECTURE ||
|
|
|
|
|
ClassType == TT_PRACTICAL)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"%s<br />",
|
2016-10-28 10:03:37 +02:00
|
|
|
|
Crs.ShrtName[0] ? Crs.ShrtName :
|
|
|
|
|
Txt_unknown_removed_course);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
2017-04-25 02:07:32 +02:00
|
|
|
|
|
|
|
|
|
/***** Type of class and duration *****/
|
2017-04-25 14:48:47 +02:00
|
|
|
|
fprintf (Gbl.F.Out,"%s (%u:%02u)",
|
2017-04-24 13:39:55 +02:00
|
|
|
|
Txt_TIMETABLE_CLASS_TYPES[ClassType],
|
2017-04-25 11:57:36 +02:00
|
|
|
|
(DurationNumIntervals / Gbl.TimeTable.Config.IntervalsPerHour), // Hours
|
|
|
|
|
(DurationNumIntervals % Gbl.TimeTable.Config.IntervalsPerHour) *
|
2017-04-25 21:20:19 +02:00
|
|
|
|
Gbl.TimeTable.Config.Range.MinutesPerInterval); // Minutes
|
2017-04-25 02:07:32 +02:00
|
|
|
|
|
|
|
|
|
/***** Group *****/
|
2017-04-25 21:42:29 +02:00
|
|
|
|
if (Gbl.TimeTable.View == TT_CRS_VIEW)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
2017-04-25 02:07:32 +02:00
|
|
|
|
if (GrpCod <= 0)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
|
|
|
|
if (Group[0])
|
|
|
|
|
fprintf (Gbl.F.Out,"<br />%s",Group);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
fprintf (Gbl.F.Out,"<br />%s %s",
|
|
|
|
|
GrpDat.GrpTypName,GrpDat.GrpName);
|
|
|
|
|
}
|
2017-04-25 02:07:32 +02:00
|
|
|
|
|
|
|
|
|
/***** Place *****/
|
|
|
|
|
if (Place[0])
|
|
|
|
|
fprintf (Gbl.F.Out,"<br />%s",Place);
|
|
|
|
|
|
|
|
|
|
/***** End cell *****/
|
2017-03-05 19:15:57 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"</div>");
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case TT_CRS_EDIT:
|
|
|
|
|
case TT_TUT_EDIT:
|
2017-04-25 21:20:19 +02:00
|
|
|
|
Par_PutHiddenParamUnsigned ("TTDay",Weekday);
|
|
|
|
|
Par_PutHiddenParamUnsigned ("TTInt",Interval);
|
|
|
|
|
Par_PutHiddenParamUnsigned ("TTCol",Column);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
|
|
|
|
/***** Class type *****/
|
2017-04-25 21:20:19 +02:00
|
|
|
|
fprintf (Gbl.F.Out,"<select name=\"TTTyp\" style=\"width:68px;\""
|
2015-10-22 14:49:48 +02:00
|
|
|
|
" onchange=\"document.getElementById('%s').submit();\">",
|
2016-01-14 10:31:09 +01:00
|
|
|
|
Gbl.Form.Id);
|
2017-04-24 13:39:55 +02:00
|
|
|
|
for (CT = (TT_ClassType_t) 0;
|
|
|
|
|
CT < (TT_ClassType_t) TT_NUM_CLASS_TYPES;
|
2014-12-01 23:55:08 +01:00
|
|
|
|
CT++)
|
2017-04-24 13:00:59 +02:00
|
|
|
|
if ((CT == TT_FREE) ||
|
2017-04-25 21:42:29 +02:00
|
|
|
|
((Gbl.TimeTable.View == TT_CRS_EDIT) && (CT == TT_LECTURE || CT == TT_PRACTICAL)) ||
|
|
|
|
|
((Gbl.TimeTable.View == TT_TUT_EDIT) && (CT == TT_TUTORING)))
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
|
|
|
|
fprintf (Gbl.F.Out,"<option");
|
2017-04-24 13:39:55 +02:00
|
|
|
|
if (CT == ClassType)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
fprintf (Gbl.F.Out," selected=\"selected\"");
|
|
|
|
|
fprintf (Gbl.F.Out," value=\"%s\">%s</option>",
|
2017-04-25 14:48:47 +02:00
|
|
|
|
TT_ClassTypeDB[CT],
|
2015-01-02 12:57:26 +01:00
|
|
|
|
Txt_TIMETABLE_CLASS_TYPES[CT]);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
|
|
|
|
fprintf (Gbl.F.Out,"</select>");
|
2017-04-25 02:07:32 +02:00
|
|
|
|
|
2017-04-24 21:12:53 +02:00
|
|
|
|
if (IntervalType == TT_FREE_INTERVAL)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
2017-04-25 21:20:19 +02:00
|
|
|
|
fprintf (Gbl.F.Out,"<input type=\"hidden\" name=\"TTDur\" value=\"");
|
|
|
|
|
for (i = Interval + 1;
|
|
|
|
|
i < Gbl.TimeTable.Config.IntervalsPerDay;
|
|
|
|
|
i++)
|
|
|
|
|
if (TT_TimeTable[Weekday][i].NumColumns == TT_MAX_COLUMNS_PER_CELL)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
break;
|
2017-04-25 21:20:19 +02:00
|
|
|
|
MaxDuration = i - Interval;
|
2017-04-25 11:57:36 +02:00
|
|
|
|
Dur = (MaxDuration >= Gbl.TimeTable.Config.IntervalsPerHour) ? Gbl.TimeTable.Config.IntervalsPerHour : // MaxDuration >= 1h ==> Dur = 1h
|
2017-04-25 21:20:19 +02:00
|
|
|
|
MaxDuration; // MaxDuration < 1h ==> Dur = MaxDuration
|
2017-04-25 14:48:47 +02:00
|
|
|
|
fprintf (Gbl.F.Out,"%u:%02u\" />",
|
2017-04-25 11:57:36 +02:00
|
|
|
|
(Dur / Gbl.TimeTable.Config.IntervalsPerHour), // Hours
|
|
|
|
|
(Dur % Gbl.TimeTable.Config.IntervalsPerHour) *
|
2017-04-25 21:20:19 +02:00
|
|
|
|
Gbl.TimeTable.Config.Range.MinutesPerInterval); // Minutes
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/***** Class duration *****/
|
2017-04-25 21:20:19 +02:00
|
|
|
|
fprintf (Gbl.F.Out,"<select name=\"TTDur\" style=\"width:57px;\""
|
2015-10-22 14:49:48 +02:00
|
|
|
|
" onchange=\"document.getElementById('%s').submit();\">",
|
2016-01-14 10:31:09 +01:00
|
|
|
|
Gbl.Form.Id);
|
2017-04-25 21:20:19 +02:00
|
|
|
|
for (i = Interval + TT_TimeTable[Weekday][Interval].Columns[Column].DurationIntervals;
|
|
|
|
|
i < Gbl.TimeTable.Config.IntervalsPerDay;
|
|
|
|
|
i++)
|
|
|
|
|
if (TT_TimeTable[Weekday][i].NumColumns == TT_MAX_COLUMNS_PER_CELL)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
break;
|
2017-04-25 21:20:19 +02:00
|
|
|
|
MaxDuration = i - Interval;
|
|
|
|
|
if (TT_TimeTable[Weekday][Interval].Columns[Column].DurationIntervals > MaxDuration)
|
|
|
|
|
MaxDuration = TT_TimeTable[Weekday][Interval].Columns[Column].DurationIntervals;
|
2014-12-01 23:55:08 +01:00
|
|
|
|
for (Dur = 0;
|
|
|
|
|
Dur <= MaxDuration;
|
|
|
|
|
Dur++)
|
|
|
|
|
{
|
|
|
|
|
fprintf (Gbl.F.Out,"<option");
|
2017-04-24 21:12:53 +02:00
|
|
|
|
if (Dur == DurationNumIntervals)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
fprintf (Gbl.F.Out," selected=\"selected\"");
|
2017-04-25 14:48:47 +02:00
|
|
|
|
fprintf (Gbl.F.Out,">%u:%02u</option>",
|
2017-04-25 11:57:36 +02:00
|
|
|
|
(Dur / Gbl.TimeTable.Config.IntervalsPerHour), // Hours
|
|
|
|
|
(Dur % Gbl.TimeTable.Config.IntervalsPerHour) *
|
2017-04-25 21:20:19 +02:00
|
|
|
|
Gbl.TimeTable.Config.Range.MinutesPerInterval); // Minutes
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
|
|
|
|
fprintf (Gbl.F.Out,"</select>");
|
|
|
|
|
|
2017-04-25 21:42:29 +02:00
|
|
|
|
if (Gbl.TimeTable.View == TT_CRS_EDIT)
|
2014-12-01 23:55:08 +01:00
|
|
|
|
{
|
|
|
|
|
/***** Group *****/
|
2016-12-26 16:35:01 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"<br />"
|
|
|
|
|
"<label>"
|
|
|
|
|
"%s"
|
2017-04-25 21:20:19 +02:00
|
|
|
|
"<select name=\"TTGrp\""
|
2015-09-28 18:28:29 +02:00
|
|
|
|
" style=\"width:110px;\""
|
2015-10-22 14:49:48 +02:00
|
|
|
|
" onchange=\"document.getElementById('%s').submit();\">",
|
2016-01-14 10:31:09 +01:00
|
|
|
|
Txt_Group,Gbl.Form.Id);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"<option value=\"-1\"");
|
|
|
|
|
if (GrpCod <= 0)
|
|
|
|
|
fprintf (Gbl.F.Out," selected=\"selected\"");
|
|
|
|
|
fprintf (Gbl.F.Out,">%s</option>",Txt_All_groups);
|
|
|
|
|
for (NumGrpTyp = 0;
|
|
|
|
|
NumGrpTyp < Gbl.CurrentCrs.Grps.GrpTypes.Num;
|
|
|
|
|
NumGrpTyp++)
|
|
|
|
|
for (NumGrp = 0;
|
|
|
|
|
NumGrp < Gbl.CurrentCrs.Grps.GrpTypes.LstGrpTypes[NumGrpTyp].NumGrps;
|
|
|
|
|
NumGrp++)
|
|
|
|
|
{
|
|
|
|
|
fprintf (Gbl.F.Out,"<option value=\"%ld\"",
|
|
|
|
|
Gbl.CurrentCrs.Grps.GrpTypes.LstGrpTypes[NumGrpTyp].LstGrps[NumGrp].GrpCod);
|
|
|
|
|
if (GrpCod == Gbl.CurrentCrs.Grps.GrpTypes.LstGrpTypes[NumGrpTyp].LstGrps[NumGrp].GrpCod)
|
|
|
|
|
fprintf (Gbl.F.Out," selected=\"selected\"");
|
|
|
|
|
fprintf (Gbl.F.Out,">%s %s</option>",
|
|
|
|
|
Gbl.CurrentCrs.Grps.GrpTypes.LstGrpTypes[NumGrpTyp].GrpTypName,
|
|
|
|
|
Gbl.CurrentCrs.Grps.GrpTypes.LstGrpTypes[NumGrpTyp].LstGrps[NumGrp].GrpName);
|
|
|
|
|
}
|
2016-12-26 16:35:01 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"</select>"
|
|
|
|
|
"</label>");
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
|
|
|
|
/***** Class room *****/
|
2016-12-26 16:35:01 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"<br />"
|
|
|
|
|
"<label>"
|
|
|
|
|
"%s"
|
2017-04-25 21:20:19 +02:00
|
|
|
|
"<input type=\"text\" name=\"TTPlc\""
|
2015-10-22 14:49:48 +02:00
|
|
|
|
" size=\"1\" maxlength=\"%u\" value=\"%s\""
|
2016-12-26 16:35:01 +01:00
|
|
|
|
" onchange=\"document.getElementById('%s').submit();\" />"
|
|
|
|
|
"</label>",
|
2017-03-08 03:48:23 +01:00
|
|
|
|
Txt_Classroom,TT_MAX_CHARS_PLACE,Place,Gbl.Form.Id);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
|
|
|
|
else // TimeTableView == TT_TUT_EDIT
|
|
|
|
|
{
|
|
|
|
|
/***** Place *****/
|
2016-12-26 16:35:01 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"<br />"
|
2016-12-27 16:45:37 +01:00
|
|
|
|
"<label class=\"DAT_SMALL\">"
|
2016-12-26 16:35:01 +01:00
|
|
|
|
"%s"
|
2017-04-25 21:20:19 +02:00
|
|
|
|
"<input type=\"text\" name=\"TTPlc\""
|
2015-10-22 14:49:48 +02:00
|
|
|
|
" size=\"12\" maxlength=\"%u\" value=\"%s\""
|
2016-12-26 16:35:01 +01:00
|
|
|
|
" onchange=\"document.getElementById('%s').submit();\" />"
|
|
|
|
|
"</label>",
|
2017-03-08 03:48:23 +01:00
|
|
|
|
Txt_Place,TT_MAX_CHARS_PLACE,Place,Gbl.Form.Id);
|
2014-12-01 23:55:08 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-12 14:16:33 +02:00
|
|
|
|
/***** End form *****/
|
2017-04-25 21:42:29 +02:00
|
|
|
|
if (Gbl.TimeTable.View == TT_CRS_EDIT ||
|
|
|
|
|
Gbl.TimeTable.View == TT_TUT_EDIT)
|
2018-10-15 14:07:12 +02:00
|
|
|
|
Act_EndForm ();
|
2014-12-01 23:55:08 +01:00
|
|
|
|
|
2017-06-12 14:16:33 +02:00
|
|
|
|
/***** End cell *****/
|
2014-12-01 23:55:08 +01:00
|
|
|
|
fprintf (Gbl.F.Out,"</td>");
|
|
|
|
|
}
|