swad-core/swad_calendar.c

487 lines
17 KiB
C
Raw Normal View History

2015-01-04 14:43:03 +01:00
// swad_calendar.c: Draw month and calendar
/*
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.
Copyright (C) 1999-2015 Antonio Ca<EFBFBD>as Vargas
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 <string.h> // For string functions
#include "swad_exam.h"
#include "swad_global.h"
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
extern struct Globals Gbl;
/*****************************************************************************/
/**************************** Private constants ******************************/
/*****************************************************************************/
/*****************************************************************************/
/***************************** Private prototypes ****************************/
/*****************************************************************************/
static void Cal_DrawMonth (unsigned RealYear,unsigned RealMonth,
2015-10-29 20:07:40 +01:00
bool DrawingCalendar,bool PrintView);
2015-01-04 14:43:03 +01:00
/*****************************************************************************/
/***************************** Draw current month ****************************/
/*****************************************************************************/
void Cal_DrawCurrentMonth (void)
{
2015-10-29 17:46:48 +01:00
extern const char *Txt_MONTHS_CAPS[12];
extern const char *Txt_DAYS_CAPS[7];
2015-10-30 01:39:00 +01:00
extern const char *Txt_Exam_of_X;
2015-10-29 22:59:40 +01:00
extern const char *Txt_STR_LANG_ID[Txt_NUM_LANGUAGES];
2015-10-29 17:46:48 +01:00
unsigned Month;
unsigned DayOfWeek; /* 0, 1, 2, 3, 4, 5, 6 */
2015-10-30 01:39:00 +01:00
unsigned NumHld;
2015-10-29 20:07:40 +01:00
unsigned NumExamAnnouncement; // Number of exam announcement
2015-10-29 22:59:40 +01:00
char Params[256+256+Ses_LENGTH_SESSION_ID+256];
2015-10-29 17:46:48 +01:00
2015-01-04 14:43:03 +01:00
/***** Get list of holidays *****/
if (!Gbl.Hlds.LstIsRead)
{
Gbl.Hlds.SelectedOrderType = Hld_ORDER_BY_START_DATE;
Hld_GetListHolidays ();
}
/***** Create list of dates of exam announcements *****/
Exa_CreateListOfExamAnnouncements ();
/***** Draw the month *****/
2015-10-30 01:39:00 +01:00
// Cal_DrawMonth (Gbl.Now.Date.Year,Gbl.Now.Date.Month,false,false);
2015-01-04 14:43:03 +01:00
2015-10-29 17:46:48 +01:00
/***** Draw the month in JavaScript *****/
/* JavaScript will write HTML here */
2015-10-29 14:56:01 +01:00
fprintf (Gbl.F.Out,"<div id=\"CurrentMonth\">"
2015-10-29 17:46:48 +01:00
"</div>");
/* Write script to draw the month */
fprintf (Gbl.F.Out,"<script type=\"text/javascript\">\n"
" var MONTHS_CAPS = [");
for (Month = 0;
Month < 12;
Month++)
{
if (Month)
fprintf (Gbl.F.Out,",");
fprintf (Gbl.F.Out,"'%s'",Txt_MONTHS_CAPS[Month]);
}
2015-10-29 20:07:40 +01:00
fprintf (Gbl.F.Out,"];\n");
fprintf (Gbl.F.Out," var DAYS_CAPS = [");
2015-10-29 17:46:48 +01:00
for (DayOfWeek = 0;
DayOfWeek < 7;
DayOfWeek++)
{
if (DayOfWeek)
fprintf (Gbl.F.Out,",");
fprintf (Gbl.F.Out,"'%c'",Txt_DAYS_CAPS[DayOfWeek][0]);
}
2015-10-29 20:07:40 +01:00
fprintf (Gbl.F.Out,"];\n");
2015-10-30 01:39:00 +01:00
fprintf (Gbl.F.Out," var STR_EXAM = '");
fprintf (Gbl.F.Out,Txt_Exam_of_X,Gbl.CurrentCrs.Crs.FullName);
fprintf (Gbl.F.Out,"';");
fprintf (Gbl.F.Out," var Hlds = [];\n");
for (NumHld = 0;
NumHld < Gbl.Hlds.Num;
NumHld++)
fprintf (Gbl.F.Out," Hlds.push({ PlcCod: %ld, HldTyp: %u, StartDate: %s, EndDate: %s, Name: '%s' });\n",
Gbl.Hlds.Lst[NumHld].PlcCod,
(unsigned) Gbl.Hlds.Lst[NumHld].HldTyp,
Gbl.Hlds.Lst[NumHld].StartDate.YYYYMMDD,
Gbl.Hlds.Lst[NumHld].EndDate.YYYYMMDD,
Gbl.Hlds.Lst[NumHld].Name);
2015-10-29 20:07:40 +01:00
fprintf (Gbl.F.Out," var LstExamAnnouncements = [];\n");
for (NumExamAnnouncement = 0;
NumExamAnnouncement < Gbl.LstExamAnnouncements.NumExamAnnounc;
NumExamAnnouncement++)
2015-10-30 01:39:00 +01:00
fprintf (Gbl.F.Out," LstExamAnnouncements.push({ Year: %u, Month: %u, Day: %u });\n",
2015-10-29 20:07:40 +01:00
Gbl.LstExamAnnouncements.Lst[NumExamAnnouncement].Year,
Gbl.LstExamAnnouncements.Lst[NumExamAnnouncement].Month,
Gbl.LstExamAnnouncements.Lst[NumExamAnnouncement].Day);
2015-10-29 22:59:40 +01:00
2015-10-30 01:39:00 +01:00
fprintf (Gbl.F.Out," DrawCurrentMonth ('CurrentMonth',%ld,'%s/%s',%ld,",
2015-10-29 22:59:40 +01:00
(long) Gbl.StartExecutionTimeUTC,
Cfg_HTTPS_URL_SWAD_CGI,Txt_STR_LANG_ID[Gbl.Prefs.Language],
2015-10-30 01:39:00 +01:00
Gbl.CurrentCtr.Ctr.PlcCod);
Act_SetParamsForm (Params,ActSeeCal,true);
fprintf (Gbl.F.Out,"'%s',",Params);
Act_SetParamsForm (Params,ActSeeExaAnn,true);
fprintf (Gbl.F.Out,"'%s');\n"
"</script>\n",Params);
2015-10-29 14:56:01 +01:00
2015-01-04 14:43:03 +01:00
/***** Free list of dates of exam announcements *****/
Exa_FreeListExamAnnouncements ();
}
/*****************************************************************************/
/************************ Draw an academic calendar **************************/
/*****************************************************************************/
/* Current Starting
month month
1 -> 9
2 -> 9
3 -> 9
4 -> 9
5 -> 1
6 -> 1
7 -> 1
8 -> 1
9 -> 5
10 -> 5
11 -> 5
12 -> 5
*/
void Cal_DrawCalendar (void)
{
2015-04-02 15:59:35 +02:00
extern const char *Txt_Print;
2015-01-04 14:43:03 +01:00
static unsigned StartingMonth[1+12] = // Calendar starts one row before current month
{
0, // Not used
9, // January --> September
9, // February --> September
9, // Mars --> September
9, // April --> September
1, // May --> January
1, // June --> January
1, // July --> January
1, // Agoust --> January
5, // September --> May
5, // October --> May
5, // November --> May
5, // December --> May
};
unsigned Row,Col;
unsigned Month = StartingMonth[Gbl.Now.Date.Month];
unsigned Year = (Month < Gbl.Now.Date.Month) ? Gbl.Now.Date.Year :
Gbl.Now.Date.Year - 1;
bool PrintView = (Gbl.CurrentAct == ActPrnCal);
/***** Get list of holidays *****/
if (!Gbl.Hlds.LstIsRead)
{
Gbl.Hlds.SelectedOrderType = Hld_ORDER_BY_START_DATE;
Hld_GetListHolidays ();
}
/***** Start of table and title *****/
if (!PrintView)
{
/* Link to print view */
2015-04-02 14:22:21 +02:00
fprintf (Gbl.F.Out,"<div class=\"CONTEXT_MENU\">");
2015-04-02 18:39:49 +02:00
Act_PutContextualLink (ActPrnCal,NULL,"print",Txt_Print);
2015-01-04 14:43:03 +01:00
fprintf (Gbl.F.Out,"</div>");
}
2015-04-12 18:01:06 +02:00
Lay_StartRoundFrameTable (NULL,0,NULL);
2015-01-04 14:43:03 +01:00
Lay_WriteHeaderClassPhoto (1,PrintView,false,
Gbl.CurrentIns.Ins.InsCod,
Gbl.CurrentDeg.Deg.DegCod,
Gbl.CurrentCrs.Crs.CrsCod);
/***** Create list of calls for examination *****/
Exa_CreateListOfExamAnnouncements ();
/***** Draw several months *****/
fprintf (Gbl.F.Out,"<tr>"
2015-07-28 10:15:44 +02:00
"<td class=\"CENTER_TOP\">"
2015-10-21 19:53:35 +02:00
"<table style=\"margin:0 auto; border-spacing:6px;\">");
2015-01-04 14:43:03 +01:00
for (Row = 0;
Row < 4;
Row++)
{
fprintf (Gbl.F.Out,"<tr>");
for (Col = 0;
Col < 4;
Col++)
{
2015-09-28 18:28:29 +02:00
fprintf (Gbl.F.Out,"<td class=\"CENTER_TOP\" style=\"width:150px;\">");
2015-10-29 20:07:40 +01:00
Cal_DrawMonth (Year,Month,true,(Gbl.CurrentAct == ActPrnCal));
2015-01-04 14:43:03 +01:00
fprintf (Gbl.F.Out,"</td>");
if (++Month == 13)
{
Month = 1;
Year++;
}
}
fprintf (Gbl.F.Out,"</tr>");
}
fprintf (Gbl.F.Out,"</table>"
"</td>"
"</tr>");
/***** Free list of dates of exam announcements *****/
Exa_FreeListExamAnnouncements ();
/***** End frame *****/
2015-04-12 18:01:06 +02:00
Lay_EndRoundFrameTable ();
2015-01-04 14:43:03 +01:00
}
/*****************************************************************************/
/******************************** Draw a month *******************************/
/*****************************************************************************/
static void Cal_DrawMonth (unsigned RealYear,unsigned RealMonth,
2015-10-29 20:07:40 +01:00
bool DrawingCalendar,bool PrintView)
2015-01-04 14:43:03 +01:00
{
extern const unsigned Dat_NumDaysMonth[1+12];
extern const char *Txt_Show_calendar;
extern const char *Txt_DAYS_CAPS[7];
extern const char *Txt_MONTHS_CAPS[12];
extern const char *Txt_Exam_of_X;
char StrExamOfX[512+Crs_MAX_LENGTH_COURSE_FULL_NAME];
unsigned Week;
2015-10-29 14:56:01 +01:00
unsigned DayOfWeek; /* 0, 1, 2, 3, 4, 5, 6 */
2015-01-04 14:43:03 +01:00
unsigned DayOfMonth;
unsigned NumDaysInMonth;
unsigned Year = RealYear;
unsigned Month = RealMonth;
char YYYYMMDD[4+2+2+1];
unsigned NumHld;
char *ClassForDay; // Class of day depending on type of day
char *TextForDay; // Text associated to a day, for example the name of the holiday
unsigned NumExamAnnouncement; // Number of exam announcement
int ResultOfCmpStartDate;
bool ContinueSearching;
bool PutLinkToCalendar = !DrawingCalendar && Gbl.CurrentCrs.Crs.CrsCod > 0;
bool ThisDayHasEvent = false;
bool IsToday;
/***** Compute number of day of month for the first box *****/
/* The initial day of month can be -5, -4, -3, -2, -1, 0, or 1
If it's -5 then write 6 boxes of the previous month.
If it's -4 then write 5 boxes of the previous month.
If it's -3 then write 4 boxes of the previous month.
If it's -2 then write 3 boxes of the previous month.
If it's -1 then write 2 boxes of the previous month.
If it's 0 then write 1 box of the previous month.
If it's 1 then write 0 boxes of the previous month. */
if ((DayOfWeek = Dat_GetDayOfWeek (Year,Month,1)) == 0)
DayOfMonth = 1;
else
{
if (Month <= 1)
{
Month = 12;
Year--;
}
else
Month--;
NumDaysInMonth = (Month == 2) ? Dat_GetNumDaysFebruary (Year) :
Dat_NumDaysMonth[Month];
DayOfMonth = NumDaysInMonth - DayOfWeek + 1;
}
/***** Start of month *****/
fprintf (Gbl.F.Out,"<div class=\"MONTH_CONTAINER\">");
/***** Month name *****/
fprintf (Gbl.F.Out,"<div class=\"MONTH\">");
if (PutLinkToCalendar)
{
Act_FormStart (ActSeeCal);
Act_LinkFormSubmit (Txt_Show_calendar,"MONTH");
}
fprintf (Gbl.F.Out,"%s %u",
Txt_MONTHS_CAPS[RealMonth-1],RealYear);
if (PutLinkToCalendar)
2015-03-13 00:16:02 +01:00
{
fprintf (Gbl.F.Out,"</a>");
Act_FormEnd ();
}
2015-01-04 14:43:03 +01:00
fprintf (Gbl.F.Out,"</div>");
/***** Month head: first letter for each day of week *****/
fprintf (Gbl.F.Out,"<table class=\"MONTH_TABLE_DAYS\">"
"<tr>");
for (DayOfWeek = 0;
DayOfWeek < 7;
DayOfWeek++)
2015-07-28 10:15:44 +02:00
fprintf (Gbl.F.Out,"<td class=\"%s\">"
2015-01-04 14:43:03 +01:00
"%c"
"</td>",
(DayOfWeek == 6) ? "DAY_NO_WRK_HEAD" :
"DAY_WRK_HEAD",
Txt_DAYS_CAPS[DayOfWeek][0]);
fprintf (Gbl.F.Out,"</tr>");
/***** Draw every week of the month *****/
for (Week = 0;
Week < 6;
Week++)
{
fprintf (Gbl.F.Out,"<tr>");
/***** Draw every day of the week *****/
for (DayOfWeek = 0;
DayOfWeek < 7;
DayOfWeek++)
{
/***** Set class for day being drawn *****/
ClassForDay = (Month == RealMonth) ? "DAY_WRK" :
"DAY_WRK_LIGHT";
TextForDay = NULL;
/* Check if day is a holiday or a school day */
sprintf (YYYYMMDD,"%04u%02u%02u",Year,Month,DayOfMonth);
for (NumHld = 0, ContinueSearching = true;
NumHld < Gbl.Hlds.Num && ContinueSearching;
NumHld++)
if (Gbl.Hlds.Lst[NumHld].PlcCod <= 0 ||
Gbl.Hlds.Lst[NumHld].PlcCod == Gbl.CurrentCtr.Ctr.PlcCod)
{
ResultOfCmpStartDate = strcmp (Gbl.Hlds.Lst[NumHld].StartDate.YYYYMMDD,YYYYMMDD);
if (ResultOfCmpStartDate > 0) // List is ordered by start date. If start date is greater than date being drawn, don't continue searching
ContinueSearching = false;
else // ResultOfCmpStartDate <= 0 <==> start date <= date being drawn
switch (Gbl.Hlds.Lst[NumHld].HldTyp)
{
case Hld_HOLIDAY:
if (ResultOfCmpStartDate == 0) // If start date == date being drawn
{
ClassForDay = (Month == RealMonth) ? "DAY_HLD" :
"DAY_HLD_LIGHT";
TextForDay = Gbl.Hlds.Lst[NumHld].Name;
ContinueSearching = false;
}
break;
case Hld_NON_SCHOOL_PERIOD:
if (strcmp (Gbl.Hlds.Lst[NumHld].EndDate.YYYYMMDD,YYYYMMDD) >= 0) // If start date <= date being drawn <= end date
{
ClassForDay = (Month == RealMonth) ? "DAY_NO_WORK" :
"DAY_NO_WORK_LIGHT";
TextForDay = Gbl.Hlds.Lst[NumHld].Name;
}
break;
}
}
/* Day being drawn is sunday? */
if (DayOfWeek == 6) // All the sundays are holidays
ClassForDay = (Month == RealMonth) ? "DAY_HLD" :
"DAY_HLD_LIGHT";
/* Date being drawn is today? */
2015-10-29 22:59:40 +01:00
IsToday = (Month == RealMonth &&
2015-01-04 14:43:03 +01:00
Year == Gbl.Now.Date.Year &&
Month == Gbl.Now.Date.Month &&
DayOfMonth == Gbl.Now.Date.Day);
/* Check if day has an exam announcement */
ThisDayHasEvent = false;
if (!DrawingCalendar || Month == RealMonth) // If drawing calendar and the month is not the real one, don't draw exam announcements
for (NumExamAnnouncement = 0;
NumExamAnnouncement < Gbl.LstExamAnnouncements.NumExamAnnounc;
NumExamAnnouncement++)
if (Year == Gbl.LstExamAnnouncements.Lst[NumExamAnnouncement].Year &&
Month == Gbl.LstExamAnnouncements.Lst[NumExamAnnouncement].Month &&
DayOfMonth == Gbl.LstExamAnnouncements.Lst[NumExamAnnouncement].Day)
{
ThisDayHasEvent = true;
2015-10-29 20:07:40 +01:00
if (!PrintView)
2015-01-04 14:43:03 +01:00
{
sprintf (StrExamOfX,Txt_Exam_of_X,Gbl.CurrentCrs.Crs.FullName);
sprintf (Gbl.Title,"%s: %02u/%02u/%04u",
StrExamOfX,
Gbl.LstExamAnnouncements.Lst[NumExamAnnouncement].Day,
Gbl.LstExamAnnouncements.Lst[NumExamAnnouncement].Month,
Gbl.LstExamAnnouncements.Lst[NumExamAnnouncement].Year);
}
break;
}
/***** Write the box with the day *****/
2015-07-28 10:15:44 +02:00
fprintf (Gbl.F.Out,"<td class=\"%s\">",
2015-10-29 22:59:40 +01:00
(IsToday && !PrintView) ? (ThisDayHasEvent ? "TODAY_EVENT" :
"TODAY") :
(ThisDayHasEvent ? "DAY_EVENT" :
"DAY" ));
2015-01-04 14:43:03 +01:00
/* If day has an exam announcement */
2015-10-29 20:07:40 +01:00
if (!PrintView && ThisDayHasEvent)
2015-01-04 14:43:03 +01:00
{
Act_FormStart (ActSeeExaAnn);
fprintf (Gbl.F.Out,"<table style=\"width:100%%;\">"
"<tr>"
2015-07-28 10:15:44 +02:00
"<td class=\"%s\">",
2015-01-04 14:43:03 +01:00
ClassForDay);
Act_LinkFormSubmit (Gbl.Title,ClassForDay);
}
else
{
fprintf (Gbl.F.Out,"<div class=\"%s\"",ClassForDay);
if (!PrintView && TextForDay)
fprintf (Gbl.F.Out," title=\"%s\"",TextForDay);
fprintf (Gbl.F.Out,">");
}
/* Write the day of month */
fprintf (Gbl.F.Out,"%u",DayOfMonth);
/* If day has an exam announcement */
2015-10-29 20:07:40 +01:00
if (!PrintView && ThisDayHasEvent)
2015-03-13 00:16:02 +01:00
{
2015-01-04 14:43:03 +01:00
fprintf (Gbl.F.Out,"</a>"
"</td>"
"</tr>"
2015-03-13 00:16:02 +01:00
"</table>");
Act_FormEnd ();
}
2015-01-04 14:43:03 +01:00
else
fprintf (Gbl.F.Out,"</div>");
fprintf (Gbl.F.Out,"</td>");
/***** Set the next day *****/
NumDaysInMonth = (Month == 2) ? Dat_GetNumDaysFebruary (Year) :
Dat_NumDaysMonth[Month];
if (++DayOfMonth > NumDaysInMonth)
{
if (++Month > 12)
{
Year++;
Month = 1;
}
DayOfMonth = 1;
}
}
fprintf (Gbl.F.Out,"</tr>");
}
/***** End of month *****/
fprintf (Gbl.F.Out,"</table>"
"</div>");
}