// swad_report.c: report on my use of the platform
/*
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-2017 Antonio Caņas Vargas
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General 3 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 .
*/
/*****************************************************************************/
/*********************************** Headers *********************************/
/*****************************************************************************/
#include // For mkdir
#include // For mkdir
#include "swad_database.h"
#include "swad_global.h"
#include "swad_ID.h"
#include "swad_profile.h"
#include "swad_tab.h"
/*****************************************************************************/
/****************************** Public constants *****************************/
/*****************************************************************************/
/*****************************************************************************/
/***************************** Private constants *****************************/
/*****************************************************************************/
#define Rep_FILENAME_ROOT "report"
#define Rep_MIN_CLICKS_CRS 100 // Minimum number of clicks to show a course in historic log
#define Rep_MAX_ACTIONS 50 // Maximum number of actions in list of frequent actions
#define Rep_MAX_BAR_WIDTH 50 // Maximum width of graphic bar
// #define Rep_BLOCK "═" // HTML code for a block in graphic bar
// #define Rep_BLOCK "▒" // HTML code for a block in graphic bar
// #define Rep_BLOCK "█" // HTML code for a block in graphic bar
// #define Rep_BLOCK "≡" // HTML code for a block in graphic bar
// #define Rep_BLOCK "•" // HTML code for a block in graphic bar
// #define Rep_BLOCK "▪" // HTML code for a block in graphic bar
#define Rep_BLOCK "-"
/*****************************************************************************/
/****************************** Internal types *******************************/
/*****************************************************************************/
struct Rep_CurrentTimeUTC
{
char StrDate[10 + 1]; // Example: 2016-10-02
// 1234567890
char StrTime[8 + 1]; // Example: 19:03:49
// 12345678
unsigned Date; // Example: 20161002
unsigned Time; // Example: 190349
};
struct Rep_Hits
{
unsigned long Num;
unsigned long Max;
};
struct Rep_Report
{
struct UsrFigures UsrFigures;
struct tm tm_FirstClickTime;
struct tm tm_CurrentTime;
struct Rep_CurrentTimeUTC CurrentTimeUTC;
struct Rep_Hits Hits;
unsigned long MaxHitsPerYear;
char FilenameReport[NAME_MAX + 1];
char Permalink[PATH_MAX + 1];
};
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
extern struct Globals Gbl;
/*****************************************************************************/
/************************* Internal global variables *************************/
/*****************************************************************************/
/*****************************************************************************/
/***************************** Private prototypes ****************************/
/*****************************************************************************/
static void Rep_CreateMyUsageReport (struct Rep_Report *Report);
static void Rep_PutLinkToMyUsageReport (struct Rep_Report *Report);
static void Req_TitleReport (struct Rep_CurrentTimeUTC *CurrentTimeUTC);
static void Rep_GetCurrentDateTimeUTC (struct Rep_Report *Report);
static void Rep_CreateNewReportFile (struct Rep_Report *Report);
static void Rep_CreateNewReportEntryIntoDB (const struct Rep_Report *Report);
static void Rep_WriteHeader (const struct Rep_Report *Report);
static void Rep_WriteSectionPlatform (void);
static void Rep_WriteSectionUsrInfo (void);
static void Rep_WriteSectionUsrFigures (const struct Rep_Report *Report);
static void Rep_WriteSectionHitsPerAction (struct Rep_Report *Report);
static void Rep_WriteSectionGlobalHits (struct Rep_Report *Report);
static void Rep_WriteSectionCurrentCourses (struct Rep_Report *Report);
static void Rep_WriteSectionHistoricCourses (struct Rep_Report *Report);
static void Rep_GetMaxHitsPerYear (struct Rep_Report *Report);
static void Rep_GetAndWriteMyCurrentCrss (Rol_Role_t Role,
struct Rep_Report *Report);
static void Rep_GetAndWriteMyHistoricClicsWithoutCrs (struct Rep_Report *Report);
static void Rep_GetAndWriteMyHistoricCrss (Rol_Role_t Role,
struct Rep_Report *Report);
static void Rep_WriteRowCrsData (long CrsCod,Rol_Role_t Role,
struct Rep_Report *Report,
bool WriteNumUsrs);
static void Rep_ShowMyHitsPerYear (bool AnyCourse,long CrsCod,Rol_Role_t Role,
struct Rep_Report *Report);
static void Rep_ComputeMaxAndTotalHits (struct Rep_Hits *Hits,
unsigned long NumRows,
MYSQL_RES *mysql_res,unsigned Field);
static void Rep_DrawBarNumHits (unsigned long HitsNum,unsigned long HitsMax,
unsigned MaxBarWidth);
static void Rep_RemoveUsrReportsFiles (long UsrCod);
static void Rep_RemoveUsrReportsFromDB (long UsrCod);
/*****************************************************************************/
/******* Request my usage report (report on my use of the platform) **********/
/*****************************************************************************/
void Rep_ReqMyUsageReport (void)
{
extern const char *Hlp_STATS_Report;
extern const char *Txt_Report_of_use_of_PLATFORM;
extern const char *Txt_Generate_report;
/***** Form to show my usage report *****/
Act_FormStart (ActSeeMyUsgRep);
/***** Start frame *****/
sprintf (Gbl.Title,Txt_Report_of_use_of_PLATFORM,Cfg_PLATFORM_SHORT_NAME);
Lay_StartRoundFrame (NULL,Gbl.Title,NULL,Hlp_STATS_Report);
/***** Header *****/
Req_TitleReport (NULL); // NULL means do not write date
/***** Send button and end frame *****/
Lay_EndRoundFrameWithButton (Lay_CONFIRM_BUTTON,Txt_Generate_report);
/***** End of form *****/
Act_FormEnd ();
}
/*****************************************************************************/
/********* Show my usage report (report on my use of the platform) ***********/
/*****************************************************************************/
void Rep_ShowMyUsageReport (void)
{
struct Rep_Report Report;
/***** Create my usage report *****/
Rep_CreateMyUsageReport (&Report);
/***** Put link to my usage report *****/
Rep_PutLinkToMyUsageReport (&Report);
}
/*****************************************************************************/
/******** Create my usage report (report on my use of the platform) **********/
/*****************************************************************************/
static void Rep_CreateMyUsageReport (struct Rep_Report *Report)
{
bool GetUsrFiguresAgain;
/***** Get current date-time *****/
Rep_GetCurrentDateTimeUTC (Report);
/***** Create a new report file *****/
Rep_CreateNewReportFile (Report);
/***** Store report entry into database *****/
Rep_CreateNewReportEntryIntoDB (Report);
/***** Start file *****/
Lay_StartHTMLFile (Gbl.F.Rep,Report->FilenameReport);
fprintf (Gbl.F.Rep,"\n");
/***** Header *****/
Rep_WriteHeader (Report);
/***** Platform *****/
Rep_WriteSectionPlatform ();
/***** Personal information *****/
Rep_WriteSectionUsrInfo ();
/***** Figures *****/
Prf_GetUsrFigures (Gbl.Usrs.Me.UsrDat.UsrCod,&Report->UsrFigures);
GetUsrFiguresAgain = Prf_GetAndStoreAllUsrFigures (Gbl.Usrs.Me.UsrDat.UsrCod,
&Report->UsrFigures);
if (GetUsrFiguresAgain)
Prf_GetUsrFigures (Gbl.Usrs.Me.UsrDat.UsrCod,&Report->UsrFigures);
if (Report->UsrFigures.FirstClickTimeUTC)
gmtime_r (&Report->UsrFigures.FirstClickTimeUTC,
&Report->tm_FirstClickTime);
Rep_WriteSectionUsrFigures (Report);
/***** Global count of hits *****/
Rep_WriteSectionGlobalHits (Report);
/***** Global hits distributed by action *****/
Rep_WriteSectionHitsPerAction (Report);
/***** Current courses *****/
Rep_GetMaxHitsPerYear (Report);
Rep_WriteSectionCurrentCourses (Report);
/***** Historic courses *****/
Rep_WriteSectionHistoricCourses (Report);
/***** End file *****/
fprintf (Gbl.F.Rep,"\n"
"