mirror of https://github.com/acanas/swad-core.git
Version 21.37: Oct 19, 2021 New module swad_statistic_database for database queries related to statistics of accesses to platform.
This commit is contained in:
parent
42d013dcd3
commit
2e7d0b099b
5
Makefile
5
Makefile
|
@ -79,8 +79,9 @@ OBJS = swad_account.o swad_account_database.o swad_action.o swad_admin.o \
|
|||
swad_report_database.o swad_role.o swad_role_database.o swad_room.o \
|
||||
swad_room_database.o swad_RSS.o \
|
||||
swad_scope.o swad_search.o swad_session.o swad_session_database.o \
|
||||
swad_setting.o swad_setting_database.o swad_statistic.o swad_string.o \
|
||||
swad_survey.o swad_syllabus.o swad_system_config.o \
|
||||
swad_setting.o swad_setting_database.o swad_statistic.o \
|
||||
swad_statistic_database.o swad_string.o swad_survey.o swad_syllabus.o \
|
||||
swad_system_config.o \
|
||||
swad_tab.o swad_tag.o swad_test.o swad_test_config.o \
|
||||
swad_test_import.o swad_test_print.o swad_test_visibility.o \
|
||||
swad_theme.o \
|
||||
|
|
|
@ -131,8 +131,8 @@ static void Att_PutLinkAttEvent (struct Att_Event *AttEvent,
|
|||
const char *Class);
|
||||
static void Att_PutParamsCodGrps (long AttCod);
|
||||
static unsigned Att_GetNumUsrsFromAListWhoAreInAttEvent (long AttCod,
|
||||
long LstSelectedUsrCods[],
|
||||
unsigned NumUsrsInList);
|
||||
long LstSelectedUsrCods[],
|
||||
unsigned NumUsrsInList);
|
||||
static bool Att_CheckIfUsrIsPresentInAttEvent (long AttCod,long UsrCod);
|
||||
static bool Att_CheckIfUsrIsPresentInAttEventAndGetComments (long AttCod,long UsrCod,
|
||||
char CommentStd[Cns_MAX_BYTES_TEXT + 1],
|
||||
|
@ -2085,8 +2085,8 @@ void Att_RegisterStudentsInAttEvent (void)
|
|||
/*****************************************************************************/
|
||||
|
||||
static unsigned Att_GetNumUsrsFromAListWhoAreInAttEvent (long AttCod,
|
||||
long LstSelectedUsrCods[],
|
||||
unsigned NumUsrsInList)
|
||||
long LstSelectedUsrCods[],
|
||||
unsigned NumUsrsInList)
|
||||
{
|
||||
char *SubQueryUsrs;
|
||||
unsigned NumUsrsInAttEvent;
|
||||
|
|
|
@ -602,13 +602,14 @@ TODO: FIX BUG, URGENT! En las fechas como par
|
|||
|
||||
TODO: En las encuestas, que los estudiantes no puedan ver los resultados hasta que no finalice el plazo.
|
||||
*/
|
||||
#define Log_PLATFORM_VERSION "SWAD 21.36 (2021-10-18)"
|
||||
#define Log_PLATFORM_VERSION "SWAD 21.37 (2021-10-19)"
|
||||
#define CSS_FILE "swad20.45.css"
|
||||
#define JS_FILE "swad20.69.1.js"
|
||||
/*
|
||||
TODO: Rename CENTRE to CENTER in help wiki.
|
||||
TODO: Rename ASSESSMENT.Announcements to ASSESSMENT.Calls_for_exams
|
||||
|
||||
Version 21.37: Oct 19, 2021 New module swad_statistic_database for database queries related to statistics of accesses to platform. (320363 lines)
|
||||
Version 21.36: Oct 18, 2021 New module swad_setting_database for database queries related to user's settings / preferences. (320253 lines)
|
||||
Version 21.35.1: Oct 18, 2021 Queries moved to module swad_file_database. (320175 lines)
|
||||
Version 21.35: Oct 18, 2021 New module swad_file_database for database queries related to files. (320171 lines)
|
||||
|
|
|
@ -380,6 +380,20 @@ unsigned Log_DB_GetMyHitsPerYear (MYSQL_RES **mysql_res,
|
|||
SubQueryRol);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/********************* Get the comments of a hit from log ********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void Log_DB_GetLogComments (long LogCod,char Comments[Cns_MAX_BYTES_TEXT + 1])
|
||||
{
|
||||
DB_QuerySELECTString (Comments,Cns_MAX_BYTES_TEXT,
|
||||
"can not get log comments",
|
||||
"SELECT Comments"
|
||||
" FROM log_comments"
|
||||
" WHERE LogCod=%ld",
|
||||
LogCod);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/************ Sometimes, we delete old entries in recent log table ***********/
|
||||
/*****************************************************************************/
|
||||
|
|
|
@ -60,6 +60,7 @@ unsigned Log_DB_GetMyHistoricCrss (MYSQL_RES **mysql_res,
|
|||
unsigned Log_DB_GetMyHitsPerYear (MYSQL_RES **mysql_res,
|
||||
bool AnyCourse,long CrsCod,Rol_Role_t Role,
|
||||
time_t FirstClickTimeUTC);
|
||||
void Log_DB_GetLogComments (long LogCod,char Comments[Cns_MAX_BYTES_TEXT + 1]);
|
||||
|
||||
void Log_DB_RemoveOldEntriesRecentLog (void);
|
||||
|
||||
|
|
620
swad_statistic.c
620
swad_statistic.c
|
@ -42,9 +42,11 @@
|
|||
#include "swad_HTML.h"
|
||||
#include "swad_ID.h"
|
||||
#include "swad_log.h"
|
||||
#include "swad_log_database.h"
|
||||
#include "swad_profile.h"
|
||||
#include "swad_role.h"
|
||||
#include "swad_statistic.h"
|
||||
#include "swad_statistic_database.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/************** External global variables from others modules ****************/
|
||||
|
@ -94,12 +96,6 @@ static const unsigned Sta_CellPadding[Sta_NUM_CLICKS_GROUPED_BY] =
|
|||
/******************************* Private types *******************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
Sta_SHOW_GLOBAL_ACCESSES,
|
||||
Sta_SHOW_COURSE_ACCESSES,
|
||||
} Sta_GlobalOrCourseAccesses_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Private prototypes ****************************/
|
||||
/*****************************************************************************/
|
||||
|
@ -262,8 +258,8 @@ static void Sta_PutFormCrsHits (struct Sta_Stats *Stats)
|
|||
|
||||
/***** Contextual menu *****/
|
||||
Mnu_ContextMenuBegin ();
|
||||
Sta_PutLinkToGlobalHits (); // Global hits
|
||||
Log_PutLinkToLastClicks (); // Last clicks in real time
|
||||
Sta_PutLinkToGlobalHits (); // Global hits
|
||||
Log_PutLinkToLastClicks (); // Last clicks in real time
|
||||
Mnu_ContextMenuEnd ();
|
||||
|
||||
/***** Get and update type of list,
|
||||
|
@ -743,10 +739,6 @@ void Sta_SeeCrsAccesses (void)
|
|||
/******************** Compute and show access statistics ********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#define Sta_MAX_BYTES_QUERY_ACCESS (1024 + (10 + ID_MAX_BYTES_USR_ID) * 5000 - 1)
|
||||
|
||||
#define Sta_MAX_BYTES_COUNT_TYPE (256 - 1)
|
||||
|
||||
static void Sta_ShowHits (Sta_GlobalOrCourseAccesses_t GlobalOrCourse)
|
||||
{
|
||||
extern const char *Txt_You_must_select_one_ore_more_users;
|
||||
|
@ -757,24 +749,19 @@ static void Sta_ShowHits (Sta_GlobalOrCourseAccesses_t GlobalOrCourse)
|
|||
extern const char *Txt_STAT_TYPE_COUNT_CAPS[Sta_NUM_COUNT_TYPES];
|
||||
extern const char *Txt_Time_zone_used_in_the_calculation_of_these_statistics;
|
||||
struct Sta_Stats Stats;
|
||||
char *Query = NULL;
|
||||
char QueryAux[512];
|
||||
long LengthQuery;
|
||||
MYSQL_RES *mysql_res;
|
||||
unsigned NumHits;
|
||||
const char *LogTable;
|
||||
Sta_ClicksDetailedOrGrouped_t DetailedOrGrouped = Sta_CLICKS_GROUPED;
|
||||
struct UsrData UsrDat;
|
||||
char BrowserTimeZone[Dat_MAX_BYTES_TIME_ZONE + 1];
|
||||
unsigned NumUsr = 0;
|
||||
const char *Ptr;
|
||||
char StrRole[256];
|
||||
char StrQueryCountType[Sta_MAX_BYTES_COUNT_TYPE + 1];
|
||||
unsigned NumDays;
|
||||
bool ICanQueryWholeRange;
|
||||
unsigned NumUsrsInList = 0;
|
||||
long *LstSelectedUsrCods = NULL;
|
||||
|
||||
/***** Reset stats context *****/
|
||||
Sta_ResetStats (&Stats);
|
||||
Stats.GlobalOrCourse = GlobalOrCourse;
|
||||
|
||||
/***** Get initial and ending dates *****/
|
||||
Dat_GetIniEndDatesFromForm ();
|
||||
|
@ -820,7 +807,7 @@ static void Sta_ShowHits (Sta_GlobalOrCourseAccesses_t GlobalOrCourse)
|
|||
Act_NUM_ACTIONS - 1,
|
||||
(unsigned long) Sta_NUM_ACTION_DEFAULT);
|
||||
|
||||
switch (GlobalOrCourse)
|
||||
switch (Stats.GlobalOrCourse)
|
||||
{
|
||||
case Sta_SHOW_GLOBAL_ACCESSES:
|
||||
/***** Get the type of user of clicks *****/
|
||||
|
@ -883,14 +870,20 @@ static void Sta_ShowHits (Sta_GlobalOrCourseAccesses_t GlobalOrCourse)
|
|||
/****** Get lists of selected users ******/
|
||||
Usr_GetListsSelectedEncryptedUsrsCods (&Gbl.Usrs.Selected);
|
||||
|
||||
/***** Count number of valid users in list of encrypted user codes *****/
|
||||
NumUsrsInList = Usr_CountNumUsrsInListOfSelectedEncryptedUsrCods (&Gbl.Usrs.Selected);
|
||||
|
||||
/***** Show the form again *****/
|
||||
Sta_PutFormCrsHits (&Stats);
|
||||
|
||||
/***** Begin results section *****/
|
||||
HTM_SECTION_Begin (Sta_STAT_RESULTS_SECTION_ID);
|
||||
|
||||
/***** Check selection *****/
|
||||
if (!Usr_CheckIfThereAreUsrsInListOfSelectedEncryptedUsrCods (&Gbl.Usrs.Selected)) // Error: there are no users selected
|
||||
/***** Check users' selection *****/
|
||||
if (NumUsrsInList)
|
||||
/* Get list of user codes from encrypted user codes */
|
||||
Usr_GetListSelectedUsrCods (&Gbl.Usrs.Selected,NumUsrsInList,&LstSelectedUsrCods);
|
||||
else // There are no users selected
|
||||
{
|
||||
/* Write warning message, clean and abort */
|
||||
Ale_ShowAlert (Ale_WARNING,Txt_You_must_select_one_ore_more_users);
|
||||
|
@ -902,7 +895,7 @@ static void Sta_ShowHits (Sta_GlobalOrCourseAccesses_t GlobalOrCourse)
|
|||
|
||||
/***** Check if range of dates is forbidden for me *****/
|
||||
NumDays = Dat_GetNumDaysBetweenDates (&Gbl.DateRange.DateIni.Date,&Gbl.DateRange.DateEnd.Date);
|
||||
ICanQueryWholeRange = (Gbl.Usrs.Me.Role.Logged >= Rol_TCH && GlobalOrCourse == Sta_SHOW_COURSE_ACCESSES) ||
|
||||
ICanQueryWholeRange = (Gbl.Usrs.Me.Role.Logged >= Rol_TCH && Stats.GlobalOrCourse == Sta_SHOW_COURSE_ACCESSES) ||
|
||||
(Gbl.Usrs.Me.Role.Logged == Rol_TCH && Gbl.Scope.Current == HieLvl_CRS) ||
|
||||
(Gbl.Usrs.Me.Role.Logged == Rol_DEG_ADM && (Gbl.Scope.Current == HieLvl_DEG ||
|
||||
Gbl.Scope.Current == HieLvl_CRS)) ||
|
||||
|
@ -922,516 +915,9 @@ static void Sta_ShowHits (Sta_GlobalOrCourseAccesses_t GlobalOrCourse)
|
|||
return;
|
||||
}
|
||||
|
||||
/***** Query depending on the type of count *****/
|
||||
switch (Stats.CountType)
|
||||
{
|
||||
case Sta_TOTAL_CLICKS:
|
||||
Str_Copy (StrQueryCountType,"COUNT(*)",sizeof (StrQueryCountType) - 1);
|
||||
break;
|
||||
case Sta_DISTINCT_USRS:
|
||||
sprintf (StrQueryCountType,"COUNT(DISTINCT(%s.UsrCod))",LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_PER_USR:
|
||||
sprintf (StrQueryCountType,"COUNT(*)/GREATEST(COUNT(DISTINCT(%s.UsrCod)),1)+0.000000",LogTable);
|
||||
break;
|
||||
case Sta_GENERATION_TIME:
|
||||
sprintf (StrQueryCountType,"(AVG(%s.TimeToGenerate)/1E6)+0.000000",LogTable);
|
||||
break;
|
||||
case Sta_SEND_TIME:
|
||||
sprintf (StrQueryCountType,"(AVG(%s.TimeToSend)/1E6)+0.000000",LogTable);
|
||||
break;
|
||||
}
|
||||
|
||||
/***** Select clicks from the table of log *****/
|
||||
/* Allocate memory for the query */
|
||||
if ((Query = malloc (Sta_MAX_BYTES_QUERY_ACCESS + 1)) == NULL)
|
||||
Err_NotEnoughMemoryExit ();
|
||||
|
||||
/* Start the query */
|
||||
switch (Stats.ClicksGroupedBy)
|
||||
{
|
||||
case Sta_CLICKS_CRS_DETAILED_LIST:
|
||||
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
|
||||
"SELECT SQL_NO_CACHE LogCod,"
|
||||
"UsrCod,"
|
||||
"Role,"
|
||||
"UNIX_TIMESTAMP(ClickTime) AS F,"
|
||||
"ActCod"
|
||||
" FROM %s",
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_USR:
|
||||
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
|
||||
"SELECT SQL_NO_CACHE UsrCod,"
|
||||
"%s AS Num"
|
||||
" FROM %s",
|
||||
StrQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_DAY:
|
||||
case Sta_CLICKS_GBL_PER_DAY:
|
||||
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
|
||||
"SELECT SQL_NO_CACHE DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%Y%%m%%d') AS Day,"
|
||||
"%s"
|
||||
" FROM %s",
|
||||
BrowserTimeZone,
|
||||
StrQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_DAY_AND_HOUR:
|
||||
case Sta_CLICKS_GBL_PER_DAY_AND_HOUR:
|
||||
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
|
||||
"SELECT SQL_NO_CACHE DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%Y%%m%%d') AS Day,"
|
||||
"DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%H') AS Hour,"
|
||||
"%s"
|
||||
" FROM %s",
|
||||
BrowserTimeZone,
|
||||
BrowserTimeZone,
|
||||
StrQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_WEEK:
|
||||
case Sta_CLICKS_GBL_PER_WEEK:
|
||||
/* With %x%v the weeks are counted from monday to sunday.
|
||||
With %X%V the weeks are counted from sunday to saturday. */
|
||||
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
|
||||
(Gbl.Prefs.FirstDayOfWeek == 0) ?
|
||||
"SELECT SQL_NO_CACHE DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%x%%v') AS Week,"// Weeks start on monday
|
||||
"%s"
|
||||
" FROM %s" :
|
||||
"SELECT SQL_NO_CACHE DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%X%%V') AS Week,"// Weeks start on sunday
|
||||
"%s"
|
||||
" FROM %s",
|
||||
BrowserTimeZone,
|
||||
StrQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_MONTH:
|
||||
case Sta_CLICKS_GBL_PER_MONTH:
|
||||
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
|
||||
"SELECT SQL_NO_CACHE DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%Y%%m') AS Month,"
|
||||
"%s"
|
||||
" FROM %s",
|
||||
BrowserTimeZone,
|
||||
StrQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_YEAR:
|
||||
case Sta_CLICKS_GBL_PER_YEAR:
|
||||
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
|
||||
"SELECT SQL_NO_CACHE DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%Y') AS Year,"
|
||||
"%s"
|
||||
" FROM %s",
|
||||
BrowserTimeZone,
|
||||
StrQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_HOUR:
|
||||
case Sta_CLICKS_GBL_PER_HOUR:
|
||||
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
|
||||
"SELECT SQL_NO_CACHE DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%H') AS Hour,"
|
||||
"%s"
|
||||
" FROM %s",
|
||||
BrowserTimeZone,
|
||||
StrQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_MINUTE:
|
||||
case Sta_CLICKS_GBL_PER_MINUTE:
|
||||
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
|
||||
"SELECT SQL_NO_CACHE DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%H%%i') AS Minute,"
|
||||
"%s"
|
||||
" FROM %s",
|
||||
BrowserTimeZone,
|
||||
StrQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_ACTION:
|
||||
case Sta_CLICKS_GBL_PER_ACTION:
|
||||
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
|
||||
"SELECT SQL_NO_CACHE ActCod,"
|
||||
"%s AS Num"
|
||||
" FROM %s",
|
||||
StrQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_PLUGIN:
|
||||
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
|
||||
"SELECT SQL_NO_CACHE log_api.PlgCod,"
|
||||
"%s AS Num"
|
||||
" FROM %s,"
|
||||
"log_api",
|
||||
StrQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_API_FUNCTION:
|
||||
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
|
||||
"SELECT SQL_NO_CACHE log_api.FunCod,"
|
||||
"%s AS Num"
|
||||
" FROM %s,"
|
||||
"log_api",
|
||||
StrQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_BANNER:
|
||||
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
|
||||
"SELECT SQL_NO_CACHE log_banners.BanCod,"
|
||||
"%s AS Num"
|
||||
" FROM %s,"
|
||||
"log_banners",
|
||||
StrQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_COUNTRY:
|
||||
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
|
||||
"SELECT SQL_NO_CACHE CtyCod,"
|
||||
"%s AS Num"
|
||||
" FROM %s",
|
||||
StrQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_INSTITUTION:
|
||||
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
|
||||
"SELECT SQL_NO_CACHE InsCod,"
|
||||
"%s AS Num"
|
||||
" FROM %s",
|
||||
StrQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_CENTER:
|
||||
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
|
||||
"SELECT SQL_NO_CACHE CtrCod,"
|
||||
"%s AS Num"
|
||||
" FROM %s",
|
||||
StrQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_DEGREE:
|
||||
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
|
||||
"SELECT SQL_NO_CACHE DegCod,"
|
||||
"%s AS Num"
|
||||
" FROM %s",
|
||||
StrQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_COURSE:
|
||||
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
|
||||
"SELECT SQL_NO_CACHE CrsCod,"
|
||||
"%s AS Num"
|
||||
" FROM %s",
|
||||
StrQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
}
|
||||
sprintf (QueryAux," WHERE %s.ClickTime"
|
||||
" BETWEEN FROM_UNIXTIME(%ld)"
|
||||
" AND FROM_UNIXTIME(%ld)",
|
||||
LogTable,
|
||||
(long) Gbl.DateRange.TimeUTC[Dat_STR_TIME],
|
||||
(long) Gbl.DateRange.TimeUTC[Dat_END_TIME]);
|
||||
Str_Concat (Query,QueryAux,Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
|
||||
switch (GlobalOrCourse)
|
||||
{
|
||||
case Sta_SHOW_GLOBAL_ACCESSES:
|
||||
/* Scope */
|
||||
switch (Gbl.Scope.Current)
|
||||
{
|
||||
case HieLvl_UNK:
|
||||
case HieLvl_SYS:
|
||||
break;
|
||||
case HieLvl_CTY:
|
||||
if (Gbl.Hierarchy.Cty.CtyCod > 0)
|
||||
{
|
||||
sprintf (QueryAux," AND %s.CtyCod=%ld",
|
||||
LogTable,Gbl.Hierarchy.Cty.CtyCod);
|
||||
Str_Concat (Query,QueryAux,Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
}
|
||||
break;
|
||||
case HieLvl_INS:
|
||||
if (Gbl.Hierarchy.Ins.InsCod > 0)
|
||||
{
|
||||
sprintf (QueryAux," AND %s.InsCod=%ld",
|
||||
LogTable,Gbl.Hierarchy.Ins.InsCod);
|
||||
Str_Concat (Query,QueryAux,Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
}
|
||||
break;
|
||||
case HieLvl_CTR:
|
||||
if (Gbl.Hierarchy.Ctr.CtrCod > 0)
|
||||
{
|
||||
sprintf (QueryAux," AND %s.CtrCod=%ld",
|
||||
LogTable,Gbl.Hierarchy.Ctr.CtrCod);
|
||||
Str_Concat (Query,QueryAux,Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
}
|
||||
break;
|
||||
case HieLvl_DEG:
|
||||
if (Gbl.Hierarchy.Deg.DegCod > 0)
|
||||
{
|
||||
sprintf (QueryAux," AND %s.DegCod=%ld",
|
||||
LogTable,Gbl.Hierarchy.Deg.DegCod);
|
||||
Str_Concat (Query,QueryAux,Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
}
|
||||
break;
|
||||
case HieLvl_CRS:
|
||||
if (Gbl.Hierarchy.Level == HieLvl_CRS)
|
||||
{
|
||||
sprintf (QueryAux," AND %s.CrsCod=%ld",
|
||||
LogTable,Gbl.Hierarchy.Crs.CrsCod);
|
||||
Str_Concat (Query,QueryAux,Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Type of users */
|
||||
switch (Stats.Role)
|
||||
{
|
||||
case Sta_ROLE_IDENTIFIED_USRS:
|
||||
sprintf (StrRole," AND %s.Role<>%u",
|
||||
LogTable,(unsigned) Rol_UNK);
|
||||
break;
|
||||
case Sta_ROLE_ALL_USRS:
|
||||
switch (Stats.CountType)
|
||||
{
|
||||
case Sta_TOTAL_CLICKS:
|
||||
case Sta_GENERATION_TIME:
|
||||
case Sta_SEND_TIME:
|
||||
StrRole[0] = '\0';
|
||||
break;
|
||||
case Sta_DISTINCT_USRS:
|
||||
case Sta_CLICKS_PER_USR:
|
||||
sprintf (StrRole," AND %s.Role<>%u",
|
||||
LogTable,(unsigned) Rol_UNK);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Sta_ROLE_INS_ADMINS:
|
||||
sprintf (StrRole," AND %s.Role=%u",
|
||||
LogTable,(unsigned) Rol_INS_ADM);
|
||||
break;
|
||||
case Sta_ROLE_CTR_ADMINS:
|
||||
sprintf (StrRole," AND %s.Role=%u",
|
||||
LogTable,(unsigned) Rol_CTR_ADM);
|
||||
break;
|
||||
case Sta_ROLE_DEG_ADMINS:
|
||||
sprintf (StrRole," AND %s.Role=%u",
|
||||
LogTable,(unsigned) Rol_DEG_ADM);
|
||||
break;
|
||||
case Sta_ROLE_TEACHERS:
|
||||
sprintf (StrRole," AND %s.Role=%u",
|
||||
LogTable,(unsigned) Rol_TCH);
|
||||
break;
|
||||
case Sta_ROLE_NON_EDITING_TEACHERS:
|
||||
sprintf (StrRole," AND %s.Role=%u",
|
||||
LogTable,(unsigned) Rol_NET);
|
||||
break;
|
||||
case Sta_ROLE_STUDENTS:
|
||||
sprintf (StrRole," AND %s.Role=%u",
|
||||
LogTable,(unsigned) Rol_STD);
|
||||
break;
|
||||
case Sta_ROLE_USERS:
|
||||
sprintf (StrRole," AND %s.Role=%u",
|
||||
LogTable,(unsigned) Rol_USR);
|
||||
break;
|
||||
case Sta_ROLE_GUESTS:
|
||||
sprintf (StrRole," AND %s.Role=%u",
|
||||
LogTable,(unsigned) Rol_GST);
|
||||
break;
|
||||
case Sta_ROLE_UNKNOWN_USRS:
|
||||
sprintf (StrRole," AND %s.Role=%u",
|
||||
LogTable,(unsigned) Rol_UNK);
|
||||
break;
|
||||
case Sta_ROLE_ME:
|
||||
sprintf (StrRole," AND %s.UsrCod=%ld",
|
||||
LogTable,Gbl.Usrs.Me.UsrDat.UsrCod);
|
||||
break;
|
||||
}
|
||||
Str_Concat (Query,StrRole,Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
|
||||
switch (Stats.ClicksGroupedBy)
|
||||
{
|
||||
case Sta_CLICKS_GBL_PER_PLUGIN:
|
||||
case Sta_CLICKS_GBL_PER_API_FUNCTION:
|
||||
sprintf (QueryAux," AND %s.LogCod=log_api.LogCod",
|
||||
LogTable);
|
||||
Str_Concat (Query,QueryAux,Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_BANNER:
|
||||
sprintf (QueryAux," AND %s.LogCod=log_banners.LogCod",
|
||||
LogTable);
|
||||
Str_Concat (Query,QueryAux,Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Sta_SHOW_COURSE_ACCESSES:
|
||||
sprintf (QueryAux," AND %s.CrsCod=%ld",
|
||||
LogTable,Gbl.Hierarchy.Crs.CrsCod);
|
||||
Str_Concat (Query,QueryAux,Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
|
||||
/***** Initialize data structure of the user *****/
|
||||
Usr_UsrDataConstructor (&UsrDat);
|
||||
|
||||
LengthQuery = strlen (Query);
|
||||
NumUsr = 0;
|
||||
Ptr = Gbl.Usrs.Selected.List[Rol_UNK];
|
||||
while (*Ptr)
|
||||
{
|
||||
Par_GetNextStrUntilSeparParamMult (&Ptr,UsrDat.EnUsrCod,
|
||||
Cry_BYTES_ENCRYPTED_STR_SHA256_BASE64);
|
||||
Usr_GetUsrCodFromEncryptedUsrCod (&UsrDat);
|
||||
if (UsrDat.UsrCod > 0)
|
||||
{
|
||||
LengthQuery = LengthQuery + 25 + 10 + 1;
|
||||
if (LengthQuery > Sta_MAX_BYTES_QUERY_ACCESS - 128)
|
||||
Err_ShowErrorAndExit ("Query is too large.");
|
||||
sprintf (QueryAux,
|
||||
NumUsr ? " OR %s.UsrCod=%ld" :
|
||||
" AND (%s.UsrCod=%ld",
|
||||
LogTable,UsrDat.UsrCod);
|
||||
Str_Concat (Query,QueryAux,Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
NumUsr++;
|
||||
}
|
||||
}
|
||||
Str_Concat (Query,")",Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
|
||||
/***** Free memory used by the data of the user *****/
|
||||
Usr_UsrDataDestructor (&UsrDat);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Select action */
|
||||
if (Stats.NumAction != ActAll)
|
||||
{
|
||||
sprintf (QueryAux," AND %s.ActCod=%ld",
|
||||
LogTable,Act_GetActCod (Stats.NumAction));
|
||||
Str_Concat (Query,QueryAux,Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
}
|
||||
|
||||
/* End the query */
|
||||
switch (Stats.ClicksGroupedBy)
|
||||
{
|
||||
case Sta_CLICKS_CRS_DETAILED_LIST:
|
||||
Str_Concat (Query," ORDER BY F",
|
||||
Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_USR:
|
||||
sprintf (QueryAux," GROUP BY %s.UsrCod"
|
||||
" ORDER BY Num DESC",
|
||||
LogTable);
|
||||
Str_Concat (Query,QueryAux,Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_DAY:
|
||||
case Sta_CLICKS_GBL_PER_DAY:
|
||||
Str_Concat (Query," GROUP BY Day"
|
||||
" ORDER BY Day DESC",
|
||||
Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_DAY_AND_HOUR:
|
||||
case Sta_CLICKS_GBL_PER_DAY_AND_HOUR:
|
||||
Str_Concat (Query," GROUP BY Day,Hour"
|
||||
" ORDER BY Day DESC,Hour",
|
||||
Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_WEEK:
|
||||
case Sta_CLICKS_GBL_PER_WEEK:
|
||||
Str_Concat (Query," GROUP BY Week"
|
||||
" ORDER BY Week DESC",
|
||||
Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_MONTH:
|
||||
case Sta_CLICKS_GBL_PER_MONTH:
|
||||
Str_Concat (Query," GROUP BY Month"
|
||||
" ORDER BY Month DESC",
|
||||
Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_YEAR:
|
||||
case Sta_CLICKS_GBL_PER_YEAR:
|
||||
Str_Concat (Query," GROUP BY Year"
|
||||
" ORDER BY Year DESC",
|
||||
Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_HOUR:
|
||||
case Sta_CLICKS_GBL_PER_HOUR:
|
||||
Str_Concat (Query," GROUP BY Hour"
|
||||
" ORDER BY Hour",
|
||||
Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_MINUTE:
|
||||
case Sta_CLICKS_GBL_PER_MINUTE:
|
||||
Str_Concat (Query," GROUP BY Minute"
|
||||
" ORDER BY Minute",
|
||||
Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_ACTION:
|
||||
case Sta_CLICKS_GBL_PER_ACTION:
|
||||
sprintf (QueryAux," GROUP BY %s.ActCod"
|
||||
" ORDER BY Num DESC",
|
||||
LogTable);
|
||||
Str_Concat (Query,QueryAux,Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_PLUGIN:
|
||||
Str_Concat (Query," GROUP BY log_api.PlgCod"
|
||||
" ORDER BY Num DESC",
|
||||
Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_API_FUNCTION:
|
||||
Str_Concat (Query," GROUP BY log_api.FunCod"
|
||||
" ORDER BY Num DESC",
|
||||
Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_BANNER:
|
||||
Str_Concat (Query," GROUP BY log_banners.BanCod"
|
||||
" ORDER BY Num DESC",
|
||||
Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_COUNTRY:
|
||||
sprintf (QueryAux," GROUP BY %s.CtyCod"
|
||||
" ORDER BY Num DESC",
|
||||
LogTable);
|
||||
Str_Concat (Query,QueryAux,Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_INSTITUTION:
|
||||
sprintf (QueryAux," GROUP BY %s.InsCod"
|
||||
" ORDER BY Num DESC",
|
||||
LogTable);
|
||||
Str_Concat (Query,QueryAux,Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_CENTER:
|
||||
sprintf (QueryAux," GROUP BY %s.CtrCod"
|
||||
" ORDER BY Num DESC",
|
||||
LogTable);
|
||||
Str_Concat (Query,QueryAux,Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_DEGREE:
|
||||
sprintf (QueryAux," GROUP BY %s.DegCod"
|
||||
" ORDER BY Num DESC",
|
||||
LogTable);
|
||||
Str_Concat (Query,QueryAux,Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_COURSE:
|
||||
sprintf (QueryAux," GROUP BY %s.CrsCod"
|
||||
" ORDER BY Num DESC",
|
||||
LogTable);
|
||||
Str_Concat (Query,QueryAux,Sta_MAX_BYTES_QUERY_ACCESS);
|
||||
break;
|
||||
}
|
||||
/***** Write query for debug *****/
|
||||
/*
|
||||
if (Gbl.Usrs.Me.Role.Logged == Rol_SYS_ADM)
|
||||
Ale_ShowAlert (Ale_INFO,Query);
|
||||
*/
|
||||
|
||||
/***** Make the query *****/
|
||||
NumHits = (unsigned)
|
||||
DB_QuerySELECT (&mysql_res,"can not get clicks",
|
||||
"%s",
|
||||
Query);
|
||||
|
||||
/***** Count the number of rows in result *****/
|
||||
if (NumHits == 0)
|
||||
Ale_ShowAlert (Ale_INFO,Txt_There_are_no_accesses_with_the_selected_search_criteria);
|
||||
else
|
||||
if ((NumHits = Sta_DB_GetHits (&mysql_res,&Stats,LogTable,BrowserTimeZone,
|
||||
NumUsrsInList,LstSelectedUsrCods)))
|
||||
{
|
||||
/***** Put the table with the clicks *****/
|
||||
if (Stats.ClicksGroupedBy == Sta_CLICKS_CRS_DETAILED_LIST)
|
||||
|
@ -1509,19 +995,26 @@ static void Sta_ShowHits (Sta_GlobalOrCourseAccesses_t GlobalOrCourse)
|
|||
Sta_ShowNumHitsPerCourse (Stats.CountType,NumHits,mysql_res);
|
||||
break;
|
||||
}
|
||||
|
||||
HTM_TABLE_End ();
|
||||
|
||||
/* End box and section */
|
||||
Box_BoxEnd ();
|
||||
HTM_SECTION_End ();
|
||||
}
|
||||
else // No hits retrieved
|
||||
Ale_ShowAlert (Ale_INFO,Txt_There_are_no_accesses_with_the_selected_search_criteria);
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
|
||||
/***** Free memory used by list of selected users' codes *****/
|
||||
if (Gbl.Action.Act == ActSeeAccCrs)
|
||||
if (Stats.GlobalOrCourse == Sta_SHOW_COURSE_ACCESSES)
|
||||
{
|
||||
if (NumUsrsInList)
|
||||
Usr_FreeListSelectedUsrCods (LstSelectedUsrCods);
|
||||
Usr_FreeListsSelectedEncryptedUsrsCods (&Gbl.Usrs.Selected);
|
||||
}
|
||||
|
||||
/***** Write time zone used in the calculation of these statistics *****/
|
||||
switch (Stats.ClicksGroupedBy)
|
||||
|
@ -1787,7 +1280,7 @@ static void Sta_ShowDetailedAccessesList (const struct Sta_Stats *Stats,
|
|||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******** Show a listing of with the number of clicks of each user ***********/
|
||||
/*************** Get and write the comments of a hit from log ****************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Sta_WriteLogComments (long LogCod)
|
||||
|
@ -1795,12 +1288,7 @@ static void Sta_WriteLogComments (long LogCod)
|
|||
char Comments[Cns_MAX_BYTES_TEXT + 1];
|
||||
|
||||
/***** Get log comments from database *****/
|
||||
DB_QuerySELECTString (Comments,sizeof (Comments) - 1,
|
||||
"can not get log comments",
|
||||
"SELECT Comments"
|
||||
" FROM log_comments"
|
||||
" WHERE LogCod=%ld",
|
||||
LogCod);
|
||||
Log_DB_GetLogComments (LogCod,Comments);
|
||||
|
||||
/***** Write comments *****/
|
||||
if (Comments[0])
|
||||
|
@ -2351,7 +1839,7 @@ static void Sta_DrawBarColors (Sta_ColorType_t ColorType,double HitsMax)
|
|||
HTM_Unsigned (0);
|
||||
HTM_TD_End ();
|
||||
|
||||
for (Interval = 1;
|
||||
for (Interval = 1;
|
||||
Interval <= 4;
|
||||
Interval++)
|
||||
{
|
||||
|
@ -2985,34 +2473,34 @@ static void Sta_ShowAverageAccessesPerMinute (unsigned NumHits,MYSQL_RES *mysql_
|
|||
/***** X axis *****/
|
||||
HTM_TR_Begin (NULL);
|
||||
|
||||
/* First division (left) */
|
||||
HTM_TD_Begin ("class=\"LM\" style=\"width:%upx;\"",
|
||||
Sta_WIDTH_SEMIDIVISION_GRAPHIC);
|
||||
HTM_IMG (Cfg_URL_ICON_PUBLIC,"ejexizq24x1.gif",NULL,
|
||||
"style=\"display:block;width:%upx;height:1px;\"",
|
||||
Sta_WIDTH_SEMIDIVISION_GRAPHIC);
|
||||
HTM_TD_End ();
|
||||
|
||||
/* All the intermediate divisions */
|
||||
for (i = 0;
|
||||
i < Sta_NUM_DIVISIONS_X * 2;
|
||||
i++)
|
||||
{
|
||||
/* First division (left) */
|
||||
HTM_TD_Begin ("class=\"LM\" style=\"width:%upx;\"",
|
||||
Sta_WIDTH_SEMIDIVISION_GRAPHIC);
|
||||
HTM_IMG (Cfg_URL_ICON_PUBLIC,"ejex24x1.gif",NULL,
|
||||
"style=\"display:block;width:%upx;height:1px;\"",
|
||||
Sta_WIDTH_SEMIDIVISION_GRAPHIC);
|
||||
HTM_IMG (Cfg_URL_ICON_PUBLIC,"ejexizq24x1.gif",NULL,
|
||||
"style=\"display:block;width:%upx;height:1px;\"",
|
||||
Sta_WIDTH_SEMIDIVISION_GRAPHIC);
|
||||
HTM_TD_End ();
|
||||
}
|
||||
|
||||
/* Last division (right) */
|
||||
HTM_TD_Begin ("class=\"LM\" style=\"width:%upx;\"",
|
||||
Sta_WIDTH_SEMIDIVISION_GRAPHIC);
|
||||
HTM_IMG (Cfg_URL_ICON_PUBLIC,"tr24x1.gif",NULL,
|
||||
"style=\"display:block;width:%upx;height:1px;\"",
|
||||
Sta_WIDTH_SEMIDIVISION_GRAPHIC);
|
||||
HTM_TD_End ();
|
||||
/* All the intermediate divisions */
|
||||
for (i = 0;
|
||||
i < Sta_NUM_DIVISIONS_X * 2;
|
||||
i++)
|
||||
{
|
||||
HTM_TD_Begin ("class=\"LM\" style=\"width:%upx;\"",
|
||||
Sta_WIDTH_SEMIDIVISION_GRAPHIC);
|
||||
HTM_IMG (Cfg_URL_ICON_PUBLIC,"ejex24x1.gif",NULL,
|
||||
"style=\"display:block;width:%upx;height:1px;\"",
|
||||
Sta_WIDTH_SEMIDIVISION_GRAPHIC);
|
||||
HTM_TD_End ();
|
||||
}
|
||||
|
||||
/* Last division (right) */
|
||||
HTM_TD_Begin ("class=\"LM\" style=\"width:%upx;\"",
|
||||
Sta_WIDTH_SEMIDIVISION_GRAPHIC);
|
||||
HTM_IMG (Cfg_URL_ICON_PUBLIC,"tr24x1.gif",NULL,
|
||||
"style=\"display:block;width:%upx;height:1px;\"",
|
||||
Sta_WIDTH_SEMIDIVISION_GRAPHIC);
|
||||
HTM_TD_End ();
|
||||
|
||||
HTM_TR_End ();
|
||||
|
||||
|
|
|
@ -128,8 +128,15 @@ struct Sta_Hits
|
|||
double Total;
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
Sta_SHOW_GLOBAL_ACCESSES,
|
||||
Sta_SHOW_COURSE_ACCESSES,
|
||||
} Sta_GlobalOrCourseAccesses_t;
|
||||
|
||||
struct Sta_Stats
|
||||
{
|
||||
Sta_GlobalOrCourseAccesses_t GlobalOrCourse;
|
||||
Sta_ClicksGroupedBy_t ClicksGroupedBy;
|
||||
Sta_Role_t Role;
|
||||
Sta_CountType_t CountType;
|
||||
|
|
|
@ -0,0 +1,576 @@
|
|||
// swad_statistic_database.c: statistics, operations with database
|
||||
|
||||
/*
|
||||
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 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 <stddef.h> // For NULL
|
||||
#include <string.h> // For string functions
|
||||
|
||||
#include "swad_database.h"
|
||||
#include "swad_error.h"
|
||||
#include "swad_global.h"
|
||||
#include "swad_ID.h"
|
||||
#include "swad_statistic.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/************** External global variables from others modules ****************/
|
||||
/*****************************************************************************/
|
||||
|
||||
extern struct Globals Gbl;
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Private constants *****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************************* Private types *******************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Private prototypes ****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************** Compute and show access statistics ********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#define Sta_DB_MAX_BYTES_QUERY (1024 + (10 + ID_MAX_BYTES_USR_ID) * 5000 - 1)
|
||||
|
||||
unsigned Sta_DB_GetHits (MYSQL_RES **mysql_res,
|
||||
const struct Sta_Stats *Stats,
|
||||
const char *LogTable,
|
||||
const char BrowserTimeZone[Dat_MAX_BYTES_TIME_ZONE + 1],
|
||||
unsigned NumUsrsInList,
|
||||
const long LstSelectedUsrCods[])
|
||||
{
|
||||
char SubQueryCountType[256];
|
||||
char SubQueryRole[256];
|
||||
char SubQuery[512];
|
||||
char *Query = NULL;
|
||||
long LengthQuery;
|
||||
unsigned NumUsr;
|
||||
unsigned NumHits;
|
||||
|
||||
/***** Build subquery depending on the type of count *****/
|
||||
switch (Stats->CountType)
|
||||
{
|
||||
case Sta_TOTAL_CLICKS:
|
||||
Str_Copy (SubQueryCountType,"COUNT(*)",sizeof (SubQueryCountType) - 1);
|
||||
break;
|
||||
case Sta_DISTINCT_USRS:
|
||||
sprintf (SubQueryCountType,"COUNT(DISTINCT(%s.UsrCod))",LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_PER_USR:
|
||||
sprintf (SubQueryCountType,"COUNT(*)/GREATEST(COUNT(DISTINCT(%s.UsrCod)),1)+0.000000",LogTable);
|
||||
break;
|
||||
case Sta_GENERATION_TIME:
|
||||
sprintf (SubQueryCountType,"(AVG(%s.TimeToGenerate)/1E6)+0.000000",LogTable);
|
||||
break;
|
||||
case Sta_SEND_TIME:
|
||||
sprintf (SubQueryCountType,"(AVG(%s.TimeToSend)/1E6)+0.000000",LogTable);
|
||||
break;
|
||||
}
|
||||
|
||||
/***** Allocate memory for the query *****/
|
||||
if ((Query = malloc (Sta_DB_MAX_BYTES_QUERY + 1)) == NULL)
|
||||
Err_NotEnoughMemoryExit ();
|
||||
|
||||
/***** Begin building the query *****/
|
||||
switch (Stats->ClicksGroupedBy)
|
||||
{
|
||||
case Sta_CLICKS_CRS_DETAILED_LIST:
|
||||
snprintf (Query,Sta_DB_MAX_BYTES_QUERY + 1,
|
||||
"SELECT SQL_NO_CACHE LogCod,"
|
||||
"UsrCod,"
|
||||
"Role,"
|
||||
"UNIX_TIMESTAMP(ClickTime) AS F,"
|
||||
"ActCod"
|
||||
" FROM %s",
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_USR:
|
||||
snprintf (Query,Sta_DB_MAX_BYTES_QUERY + 1,
|
||||
"SELECT SQL_NO_CACHE UsrCod,"
|
||||
"%s AS Num"
|
||||
" FROM %s",
|
||||
SubQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_DAY:
|
||||
case Sta_CLICKS_GBL_PER_DAY:
|
||||
snprintf (Query,Sta_DB_MAX_BYTES_QUERY + 1,
|
||||
"SELECT SQL_NO_CACHE DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%Y%%m%%d') AS Day,"
|
||||
"%s"
|
||||
" FROM %s",
|
||||
BrowserTimeZone,
|
||||
SubQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_DAY_AND_HOUR:
|
||||
case Sta_CLICKS_GBL_PER_DAY_AND_HOUR:
|
||||
snprintf (Query,Sta_DB_MAX_BYTES_QUERY + 1,
|
||||
"SELECT SQL_NO_CACHE DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%Y%%m%%d') AS Day,"
|
||||
"DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%H') AS Hour,"
|
||||
"%s"
|
||||
" FROM %s",
|
||||
BrowserTimeZone,
|
||||
BrowserTimeZone,
|
||||
SubQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_WEEK:
|
||||
case Sta_CLICKS_GBL_PER_WEEK:
|
||||
/* With %x%v the weeks are counted from monday to sunday.
|
||||
With %X%V the weeks are counted from sunday to saturday. */
|
||||
snprintf (Query,Sta_DB_MAX_BYTES_QUERY + 1,
|
||||
(Gbl.Prefs.FirstDayOfWeek == 0) ?
|
||||
"SELECT SQL_NO_CACHE DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%x%%v') AS Week,"// Weeks start on monday
|
||||
"%s"
|
||||
" FROM %s" :
|
||||
"SELECT SQL_NO_CACHE DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%X%%V') AS Week,"// Weeks start on sunday
|
||||
"%s"
|
||||
" FROM %s",
|
||||
BrowserTimeZone,
|
||||
SubQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_MONTH:
|
||||
case Sta_CLICKS_GBL_PER_MONTH:
|
||||
snprintf (Query,Sta_DB_MAX_BYTES_QUERY + 1,
|
||||
"SELECT SQL_NO_CACHE DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%Y%%m') AS Month,"
|
||||
"%s"
|
||||
" FROM %s",
|
||||
BrowserTimeZone,
|
||||
SubQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_YEAR:
|
||||
case Sta_CLICKS_GBL_PER_YEAR:
|
||||
snprintf (Query,Sta_DB_MAX_BYTES_QUERY + 1,
|
||||
"SELECT SQL_NO_CACHE DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%Y') AS Year,"
|
||||
"%s"
|
||||
" FROM %s",
|
||||
BrowserTimeZone,
|
||||
SubQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_HOUR:
|
||||
case Sta_CLICKS_GBL_PER_HOUR:
|
||||
snprintf (Query,Sta_DB_MAX_BYTES_QUERY + 1,
|
||||
"SELECT SQL_NO_CACHE DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%H') AS Hour,"
|
||||
"%s"
|
||||
" FROM %s",
|
||||
BrowserTimeZone,
|
||||
SubQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_MINUTE:
|
||||
case Sta_CLICKS_GBL_PER_MINUTE:
|
||||
snprintf (Query,Sta_DB_MAX_BYTES_QUERY + 1,
|
||||
"SELECT SQL_NO_CACHE DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%H%%i') AS Minute,"
|
||||
"%s"
|
||||
" FROM %s",
|
||||
BrowserTimeZone,
|
||||
SubQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_ACTION:
|
||||
case Sta_CLICKS_GBL_PER_ACTION:
|
||||
snprintf (Query,Sta_DB_MAX_BYTES_QUERY + 1,
|
||||
"SELECT SQL_NO_CACHE ActCod,"
|
||||
"%s AS Num"
|
||||
" FROM %s",
|
||||
SubQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_PLUGIN:
|
||||
snprintf (Query,Sta_DB_MAX_BYTES_QUERY + 1,
|
||||
"SELECT SQL_NO_CACHE log_api.PlgCod,"
|
||||
"%s AS Num"
|
||||
" FROM %s,"
|
||||
"log_api",
|
||||
SubQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_API_FUNCTION:
|
||||
snprintf (Query,Sta_DB_MAX_BYTES_QUERY + 1,
|
||||
"SELECT SQL_NO_CACHE log_api.FunCod,"
|
||||
"%s AS Num"
|
||||
" FROM %s,"
|
||||
"log_api",
|
||||
SubQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_BANNER:
|
||||
snprintf (Query,Sta_DB_MAX_BYTES_QUERY + 1,
|
||||
"SELECT SQL_NO_CACHE log_banners.BanCod,"
|
||||
"%s AS Num"
|
||||
" FROM %s,"
|
||||
"log_banners",
|
||||
SubQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_COUNTRY:
|
||||
snprintf (Query,Sta_DB_MAX_BYTES_QUERY + 1,
|
||||
"SELECT SQL_NO_CACHE CtyCod,"
|
||||
"%s AS Num"
|
||||
" FROM %s",
|
||||
SubQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_INSTITUTION:
|
||||
snprintf (Query,Sta_DB_MAX_BYTES_QUERY + 1,
|
||||
"SELECT SQL_NO_CACHE InsCod,"
|
||||
"%s AS Num"
|
||||
" FROM %s",
|
||||
SubQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_CENTER:
|
||||
snprintf (Query,Sta_DB_MAX_BYTES_QUERY + 1,
|
||||
"SELECT SQL_NO_CACHE CtrCod,"
|
||||
"%s AS Num"
|
||||
" FROM %s",
|
||||
SubQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_DEGREE:
|
||||
snprintf (Query,Sta_DB_MAX_BYTES_QUERY + 1,
|
||||
"SELECT SQL_NO_CACHE DegCod,"
|
||||
"%s AS Num"
|
||||
" FROM %s",
|
||||
SubQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_COURSE:
|
||||
snprintf (Query,Sta_DB_MAX_BYTES_QUERY + 1,
|
||||
"SELECT SQL_NO_CACHE CrsCod,"
|
||||
"%s AS Num"
|
||||
" FROM %s",
|
||||
SubQueryCountType,
|
||||
LogTable);
|
||||
break;
|
||||
}
|
||||
sprintf (SubQuery," WHERE %s.ClickTime"
|
||||
" BETWEEN FROM_UNIXTIME(%ld)"
|
||||
" AND FROM_UNIXTIME(%ld)",
|
||||
LogTable,
|
||||
(long) Gbl.DateRange.TimeUTC[Dat_STR_TIME],
|
||||
(long) Gbl.DateRange.TimeUTC[Dat_END_TIME]);
|
||||
Str_Concat (Query,SubQuery,Sta_DB_MAX_BYTES_QUERY);
|
||||
|
||||
switch (Stats->GlobalOrCourse)
|
||||
{
|
||||
case Sta_SHOW_GLOBAL_ACCESSES:
|
||||
/* Scope */
|
||||
switch (Gbl.Scope.Current)
|
||||
{
|
||||
case HieLvl_UNK:
|
||||
case HieLvl_SYS:
|
||||
break;
|
||||
case HieLvl_CTY:
|
||||
if (Gbl.Hierarchy.Cty.CtyCod > 0)
|
||||
{
|
||||
sprintf (SubQuery," AND %s.CtyCod=%ld",
|
||||
LogTable,Gbl.Hierarchy.Cty.CtyCod);
|
||||
Str_Concat (Query,SubQuery,Sta_DB_MAX_BYTES_QUERY);
|
||||
}
|
||||
break;
|
||||
case HieLvl_INS:
|
||||
if (Gbl.Hierarchy.Ins.InsCod > 0)
|
||||
{
|
||||
sprintf (SubQuery," AND %s.InsCod=%ld",
|
||||
LogTable,Gbl.Hierarchy.Ins.InsCod);
|
||||
Str_Concat (Query,SubQuery,Sta_DB_MAX_BYTES_QUERY);
|
||||
}
|
||||
break;
|
||||
case HieLvl_CTR:
|
||||
if (Gbl.Hierarchy.Ctr.CtrCod > 0)
|
||||
{
|
||||
sprintf (SubQuery," AND %s.CtrCod=%ld",
|
||||
LogTable,Gbl.Hierarchy.Ctr.CtrCod);
|
||||
Str_Concat (Query,SubQuery,Sta_DB_MAX_BYTES_QUERY);
|
||||
}
|
||||
break;
|
||||
case HieLvl_DEG:
|
||||
if (Gbl.Hierarchy.Deg.DegCod > 0)
|
||||
{
|
||||
sprintf (SubQuery," AND %s.DegCod=%ld",
|
||||
LogTable,Gbl.Hierarchy.Deg.DegCod);
|
||||
Str_Concat (Query,SubQuery,Sta_DB_MAX_BYTES_QUERY);
|
||||
}
|
||||
break;
|
||||
case HieLvl_CRS:
|
||||
if (Gbl.Hierarchy.Level == HieLvl_CRS)
|
||||
{
|
||||
sprintf (SubQuery," AND %s.CrsCod=%ld",
|
||||
LogTable,Gbl.Hierarchy.Crs.CrsCod);
|
||||
Str_Concat (Query,SubQuery,Sta_DB_MAX_BYTES_QUERY);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Type of users */
|
||||
switch (Stats->Role)
|
||||
{
|
||||
case Sta_ROLE_IDENTIFIED_USRS:
|
||||
sprintf (SubQueryRole," AND %s.Role<>%u",
|
||||
LogTable,(unsigned) Rol_UNK);
|
||||
break;
|
||||
case Sta_ROLE_ALL_USRS:
|
||||
switch (Stats->CountType)
|
||||
{
|
||||
case Sta_TOTAL_CLICKS:
|
||||
case Sta_GENERATION_TIME:
|
||||
case Sta_SEND_TIME:
|
||||
SubQueryRole[0] = '\0';
|
||||
break;
|
||||
case Sta_DISTINCT_USRS:
|
||||
case Sta_CLICKS_PER_USR:
|
||||
sprintf (SubQueryRole," AND %s.Role<>%u",
|
||||
LogTable,(unsigned) Rol_UNK);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Sta_ROLE_INS_ADMINS:
|
||||
sprintf (SubQueryRole," AND %s.Role=%u",
|
||||
LogTable,(unsigned) Rol_INS_ADM);
|
||||
break;
|
||||
case Sta_ROLE_CTR_ADMINS:
|
||||
sprintf (SubQueryRole," AND %s.Role=%u",
|
||||
LogTable,(unsigned) Rol_CTR_ADM);
|
||||
break;
|
||||
case Sta_ROLE_DEG_ADMINS:
|
||||
sprintf (SubQueryRole," AND %s.Role=%u",
|
||||
LogTable,(unsigned) Rol_DEG_ADM);
|
||||
break;
|
||||
case Sta_ROLE_TEACHERS:
|
||||
sprintf (SubQueryRole," AND %s.Role=%u",
|
||||
LogTable,(unsigned) Rol_TCH);
|
||||
break;
|
||||
case Sta_ROLE_NON_EDITING_TEACHERS:
|
||||
sprintf (SubQueryRole," AND %s.Role=%u",
|
||||
LogTable,(unsigned) Rol_NET);
|
||||
break;
|
||||
case Sta_ROLE_STUDENTS:
|
||||
sprintf (SubQueryRole," AND %s.Role=%u",
|
||||
LogTable,(unsigned) Rol_STD);
|
||||
break;
|
||||
case Sta_ROLE_USERS:
|
||||
sprintf (SubQueryRole," AND %s.Role=%u",
|
||||
LogTable,(unsigned) Rol_USR);
|
||||
break;
|
||||
case Sta_ROLE_GUESTS:
|
||||
sprintf (SubQueryRole," AND %s.Role=%u",
|
||||
LogTable,(unsigned) Rol_GST);
|
||||
break;
|
||||
case Sta_ROLE_UNKNOWN_USRS:
|
||||
sprintf (SubQueryRole," AND %s.Role=%u",
|
||||
LogTable,(unsigned) Rol_UNK);
|
||||
break;
|
||||
case Sta_ROLE_ME:
|
||||
sprintf (SubQueryRole," AND %s.UsrCod=%ld",
|
||||
LogTable,Gbl.Usrs.Me.UsrDat.UsrCod);
|
||||
break;
|
||||
}
|
||||
Str_Concat (Query,SubQueryRole,Sta_DB_MAX_BYTES_QUERY);
|
||||
|
||||
switch (Stats->ClicksGroupedBy)
|
||||
{
|
||||
case Sta_CLICKS_GBL_PER_PLUGIN:
|
||||
case Sta_CLICKS_GBL_PER_API_FUNCTION:
|
||||
sprintf (SubQuery," AND %s.LogCod=log_api.LogCod",
|
||||
LogTable);
|
||||
Str_Concat (Query,SubQuery,Sta_DB_MAX_BYTES_QUERY);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_BANNER:
|
||||
sprintf (SubQuery," AND %s.LogCod=log_banners.LogCod",
|
||||
LogTable);
|
||||
Str_Concat (Query,SubQuery,Sta_DB_MAX_BYTES_QUERY);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Sta_SHOW_COURSE_ACCESSES:
|
||||
sprintf (SubQuery," AND %s.CrsCod=%ld",
|
||||
LogTable,Gbl.Hierarchy.Crs.CrsCod);
|
||||
Str_Concat (Query,SubQuery,Sta_DB_MAX_BYTES_QUERY);
|
||||
|
||||
if (NumUsrsInList)
|
||||
{
|
||||
LengthQuery = strlen (Query);
|
||||
|
||||
for (NumUsr = 0;
|
||||
NumUsr < NumUsrsInList;
|
||||
NumUsr++)
|
||||
{
|
||||
LengthQuery = LengthQuery + 25 + 10 + 1;
|
||||
if (LengthQuery > Sta_DB_MAX_BYTES_QUERY - 128)
|
||||
Err_ShowErrorAndExit ("Query is too large.");
|
||||
sprintf (SubQuery,
|
||||
NumUsr ? " OR %s.UsrCod=%ld" :
|
||||
" AND (%s.UsrCod=%ld",
|
||||
LogTable,LstSelectedUsrCods[NumUsr]);
|
||||
Str_Concat (Query,SubQuery,Sta_DB_MAX_BYTES_QUERY);
|
||||
}
|
||||
Str_Concat (Query,")",Sta_DB_MAX_BYTES_QUERY);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Select action */
|
||||
if (Stats->NumAction != ActAll)
|
||||
{
|
||||
sprintf (SubQuery," AND %s.ActCod=%ld",
|
||||
LogTable,Act_GetActCod (Stats->NumAction));
|
||||
Str_Concat (Query,SubQuery,Sta_DB_MAX_BYTES_QUERY);
|
||||
}
|
||||
|
||||
/* End the query */
|
||||
switch (Stats->ClicksGroupedBy)
|
||||
{
|
||||
case Sta_CLICKS_CRS_DETAILED_LIST:
|
||||
Str_Concat (Query," ORDER BY F",
|
||||
Sta_DB_MAX_BYTES_QUERY);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_USR:
|
||||
sprintf (SubQuery," GROUP BY %s.UsrCod"
|
||||
" ORDER BY Num DESC",
|
||||
LogTable);
|
||||
Str_Concat (Query,SubQuery,Sta_DB_MAX_BYTES_QUERY);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_DAY:
|
||||
case Sta_CLICKS_GBL_PER_DAY:
|
||||
Str_Concat (Query," GROUP BY Day"
|
||||
" ORDER BY Day DESC",
|
||||
Sta_DB_MAX_BYTES_QUERY);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_DAY_AND_HOUR:
|
||||
case Sta_CLICKS_GBL_PER_DAY_AND_HOUR:
|
||||
Str_Concat (Query," GROUP BY Day,Hour"
|
||||
" ORDER BY Day DESC,Hour",
|
||||
Sta_DB_MAX_BYTES_QUERY);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_WEEK:
|
||||
case Sta_CLICKS_GBL_PER_WEEK:
|
||||
Str_Concat (Query," GROUP BY Week"
|
||||
" ORDER BY Week DESC",
|
||||
Sta_DB_MAX_BYTES_QUERY);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_MONTH:
|
||||
case Sta_CLICKS_GBL_PER_MONTH:
|
||||
Str_Concat (Query," GROUP BY Month"
|
||||
" ORDER BY Month DESC",
|
||||
Sta_DB_MAX_BYTES_QUERY);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_YEAR:
|
||||
case Sta_CLICKS_GBL_PER_YEAR:
|
||||
Str_Concat (Query," GROUP BY Year"
|
||||
" ORDER BY Year DESC",
|
||||
Sta_DB_MAX_BYTES_QUERY);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_HOUR:
|
||||
case Sta_CLICKS_GBL_PER_HOUR:
|
||||
Str_Concat (Query," GROUP BY Hour"
|
||||
" ORDER BY Hour",
|
||||
Sta_DB_MAX_BYTES_QUERY);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_MINUTE:
|
||||
case Sta_CLICKS_GBL_PER_MINUTE:
|
||||
Str_Concat (Query," GROUP BY Minute"
|
||||
" ORDER BY Minute",
|
||||
Sta_DB_MAX_BYTES_QUERY);
|
||||
break;
|
||||
case Sta_CLICKS_CRS_PER_ACTION:
|
||||
case Sta_CLICKS_GBL_PER_ACTION:
|
||||
sprintf (SubQuery," GROUP BY %s.ActCod"
|
||||
" ORDER BY Num DESC",
|
||||
LogTable);
|
||||
Str_Concat (Query,SubQuery,Sta_DB_MAX_BYTES_QUERY);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_PLUGIN:
|
||||
Str_Concat (Query," GROUP BY log_api.PlgCod"
|
||||
" ORDER BY Num DESC",
|
||||
Sta_DB_MAX_BYTES_QUERY);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_API_FUNCTION:
|
||||
Str_Concat (Query," GROUP BY log_api.FunCod"
|
||||
" ORDER BY Num DESC",
|
||||
Sta_DB_MAX_BYTES_QUERY);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_BANNER:
|
||||
Str_Concat (Query," GROUP BY log_banners.BanCod"
|
||||
" ORDER BY Num DESC",
|
||||
Sta_DB_MAX_BYTES_QUERY);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_COUNTRY:
|
||||
sprintf (SubQuery," GROUP BY %s.CtyCod"
|
||||
" ORDER BY Num DESC",
|
||||
LogTable);
|
||||
Str_Concat (Query,SubQuery,Sta_DB_MAX_BYTES_QUERY);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_INSTITUTION:
|
||||
sprintf (SubQuery," GROUP BY %s.InsCod"
|
||||
" ORDER BY Num DESC",
|
||||
LogTable);
|
||||
Str_Concat (Query,SubQuery,Sta_DB_MAX_BYTES_QUERY);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_CENTER:
|
||||
sprintf (SubQuery," GROUP BY %s.CtrCod"
|
||||
" ORDER BY Num DESC",
|
||||
LogTable);
|
||||
Str_Concat (Query,SubQuery,Sta_DB_MAX_BYTES_QUERY);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_DEGREE:
|
||||
sprintf (SubQuery," GROUP BY %s.DegCod"
|
||||
" ORDER BY Num DESC",
|
||||
LogTable);
|
||||
Str_Concat (Query,SubQuery,Sta_DB_MAX_BYTES_QUERY);
|
||||
break;
|
||||
case Sta_CLICKS_GBL_PER_COURSE:
|
||||
sprintf (SubQuery," GROUP BY %s.CrsCod"
|
||||
" ORDER BY Num DESC",
|
||||
LogTable);
|
||||
Str_Concat (Query,SubQuery,Sta_DB_MAX_BYTES_QUERY);
|
||||
break;
|
||||
}
|
||||
/***** Write query for debug *****/
|
||||
/*
|
||||
if (Gbl.Usrs.Me.Role.Logged == Rol_SYS_ADM)
|
||||
Ale_ShowAlert (Ale_INFO,Query);
|
||||
*/
|
||||
|
||||
/***** Make the query *****/
|
||||
NumHits = (unsigned)
|
||||
DB_QuerySELECT (mysql_res,"can not get clicks",
|
||||
"%s",
|
||||
Query);
|
||||
|
||||
/* Free memory for the query */
|
||||
free (Query);
|
||||
|
||||
return NumHits;
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
// swad_statistic_database.h: statistics, operations with database
|
||||
|
||||
#ifndef _SWAD_STA_DB
|
||||
#define _SWAD_STA_DB
|
||||
/*
|
||||
SWAD (Shared Workspace At a Distance in Spanish),
|
||||
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 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 <mysql/mysql.h> // To access MySQL databases
|
||||
|
||||
// #include "swad_indicator.h"
|
||||
// #include "swad_photo.h"
|
||||
// #include "swad_user.h"
|
||||
#include "swad_statistic.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/************************** Public types and constants ***********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Public prototypes *****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
unsigned Sta_DB_GetHits (MYSQL_RES **mysql_res,
|
||||
const struct Sta_Stats *Stats,
|
||||
const char *LogTable,
|
||||
const char BrowserTimeZone[Dat_MAX_BYTES_TIME_ZONE + 1],
|
||||
unsigned NumUsrsInList,
|
||||
const long LstSelectedUsrCods[]);
|
||||
|
||||
#endif
|
|
@ -6343,7 +6343,7 @@ void Usr_CreateSubqueryUsrCods (long LstSelectedUsrCods[],
|
|||
size_t MaxLength;
|
||||
|
||||
/***** Allocate space for subquery *****/
|
||||
MaxLength = NumUsrsInList * (1 + Cns_MAX_DECIMAL_DIGITS_LONG);
|
||||
MaxLength = (size_t) NumUsrsInList * (size_t) (1 + Cns_MAX_DECIMAL_DIGITS_LONG);
|
||||
if ((*UsrsSubQuery = malloc (MaxLength + 1)) == NULL)
|
||||
Err_NotEnoughMemoryExit ();
|
||||
(*UsrsSubQuery)[0] = '\0';
|
||||
|
@ -7221,7 +7221,7 @@ void Usr_ListAllDataStds (void)
|
|||
/***** Allocate memory for the string with the list of group names where student belongs to *****/
|
||||
if (Gbl.Scope.Current == HieLvl_CRS)
|
||||
{
|
||||
Length = (Grp_MAX_BYTES_GROUP_NAME + 2) * Gbl.Crs.Grps.GrpTypes.NumGrpsTotal;
|
||||
Length = (size_t) (Grp_MAX_BYTES_GROUP_NAME + 2) * (size_t) Gbl.Crs.Grps.GrpTypes.NumGrpsTotal;
|
||||
if ((GroupNames = malloc (Length + 1)) == NULL)
|
||||
Err_NotEnoughMemoryExit ();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue