// 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-2021 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 free
#include // For mkdir
#include // For mkdir
#include "swad_box.h"
#include "swad_browser_database.h"
#include "swad_database.h"
#include "swad_error.h"
#include "swad_form.h"
#include "swad_global.h"
#include "swad_hierarchy_level.h"
#include "swad_HTML.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 "-"
/*****************************************************************************/
/****************************** Private types ********************************/
/*****************************************************************************/
struct Rep_CurrentTimeUTC
{
char StrDate[3 * (Cns_MAX_DECIMAL_DIGITS_INT + 1)]; // Example: 2016-10-02
char StrTime[3 * (Cns_MAX_DECIMAL_DIGITS_INT + 1)]; // Example: 19:03:49
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[Cns_MAX_BYTES_WWW + 1];
};
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
extern struct Globals Gbl;
/*****************************************************************************/
/************************* Private global variables **************************/
/*****************************************************************************/
/*****************************************************************************/
/***************************** Private prototypes ****************************/
/*****************************************************************************/
static void Rep_CreateMyUsageReport (struct Rep_Report *Report);
static void Rep_PutLinkToMyUsageReport (struct Rep_Report *Report);
static void Rep_TitleReport (struct Rep_CurrentTimeUTC *CurrentTimeUTC);
static void Rep_GetCurrentDateTimeUTC (struct Rep_Report *Report);
static void Rep_CreateNewReportFile (struct Rep_Report *Report);
static void Rep_DB_CreateNewReport (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 NumHits,
MYSQL_RES *mysql_res,unsigned Field);
static void Rep_DrawBarNumHits (unsigned long HitsNum,unsigned long HitsMax,
unsigned MaxBarWidth);
static void Rep_WriteDouble (double Num);
static void Rep_RemoveUsrReportsFiles (long UsrCod);
static void Rep_DB_RemoveUsrReports (long UsrCod);
/*****************************************************************************/
/******* Request my usage report (report on my use of the platform) **********/
/*****************************************************************************/
void Rep_ReqMyUsageReport (void)
{
extern const char *Hlp_ANALYTICS_Report;
extern const char *Txt_Report_of_use_of_PLATFORM;
extern const char *Txt_Generate_report;
/***** Form to show my usage report *****/
Frm_BeginForm (ActSeeMyUsgRep);
/***** Begin box *****/
Box_BoxBegin (NULL,Str_BuildStringStr (Txt_Report_of_use_of_PLATFORM,
Cfg_PLATFORM_SHORT_NAME),
NULL,NULL,
Hlp_ANALYTICS_Report,Box_NOT_CLOSABLE);
Str_FreeString ();
/***** Header *****/
Rep_TitleReport (NULL); // NULL means do not write date
/***** Send button and end box *****/
Box_BoxWithButtonEnd (Btn_CONFIRM_BUTTON,Txt_Generate_report);
/***** End form *****/
Frm_EndForm ();
}
/*****************************************************************************/
/********* 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_DB_CreateNewReport (Report);
/***** Begin file *****/
Lay_BeginHTMLFile (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"
"