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_report_database.o swad_role.o swad_role_database.o swad_room.o \
|
||||||
swad_room_database.o swad_RSS.o \
|
swad_room_database.o swad_RSS.o \
|
||||||
swad_scope.o swad_search.o swad_session.o swad_session_database.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_setting.o swad_setting_database.o swad_statistic.o \
|
||||||
swad_survey.o swad_syllabus.o swad_system_config.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_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_test_import.o swad_test_print.o swad_test_visibility.o \
|
||||||
swad_theme.o \
|
swad_theme.o \
|
||||||
|
|
|
@ -131,8 +131,8 @@ static void Att_PutLinkAttEvent (struct Att_Event *AttEvent,
|
||||||
const char *Class);
|
const char *Class);
|
||||||
static void Att_PutParamsCodGrps (long AttCod);
|
static void Att_PutParamsCodGrps (long AttCod);
|
||||||
static unsigned Att_GetNumUsrsFromAListWhoAreInAttEvent (long AttCod,
|
static unsigned Att_GetNumUsrsFromAListWhoAreInAttEvent (long AttCod,
|
||||||
long LstSelectedUsrCods[],
|
long LstSelectedUsrCods[],
|
||||||
unsigned NumUsrsInList);
|
unsigned NumUsrsInList);
|
||||||
static bool Att_CheckIfUsrIsPresentInAttEvent (long AttCod,long UsrCod);
|
static bool Att_CheckIfUsrIsPresentInAttEvent (long AttCod,long UsrCod);
|
||||||
static bool Att_CheckIfUsrIsPresentInAttEventAndGetComments (long AttCod,long UsrCod,
|
static bool Att_CheckIfUsrIsPresentInAttEventAndGetComments (long AttCod,long UsrCod,
|
||||||
char CommentStd[Cns_MAX_BYTES_TEXT + 1],
|
char CommentStd[Cns_MAX_BYTES_TEXT + 1],
|
||||||
|
@ -2085,8 +2085,8 @@ void Att_RegisterStudentsInAttEvent (void)
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static unsigned Att_GetNumUsrsFromAListWhoAreInAttEvent (long AttCod,
|
static unsigned Att_GetNumUsrsFromAListWhoAreInAttEvent (long AttCod,
|
||||||
long LstSelectedUsrCods[],
|
long LstSelectedUsrCods[],
|
||||||
unsigned NumUsrsInList)
|
unsigned NumUsrsInList)
|
||||||
{
|
{
|
||||||
char *SubQueryUsrs;
|
char *SubQueryUsrs;
|
||||||
unsigned NumUsrsInAttEvent;
|
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.
|
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 CSS_FILE "swad20.45.css"
|
||||||
#define JS_FILE "swad20.69.1.js"
|
#define JS_FILE "swad20.69.1.js"
|
||||||
/*
|
/*
|
||||||
TODO: Rename CENTRE to CENTER in help wiki.
|
TODO: Rename CENTRE to CENTER in help wiki.
|
||||||
TODO: Rename ASSESSMENT.Announcements to ASSESSMENT.Calls_for_exams
|
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.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.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)
|
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);
|
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 ***********/
|
/************ 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,
|
unsigned Log_DB_GetMyHitsPerYear (MYSQL_RES **mysql_res,
|
||||||
bool AnyCourse,long CrsCod,Rol_Role_t Role,
|
bool AnyCourse,long CrsCod,Rol_Role_t Role,
|
||||||
time_t FirstClickTimeUTC);
|
time_t FirstClickTimeUTC);
|
||||||
|
void Log_DB_GetLogComments (long LogCod,char Comments[Cns_MAX_BYTES_TEXT + 1]);
|
||||||
|
|
||||||
void Log_DB_RemoveOldEntriesRecentLog (void);
|
void Log_DB_RemoveOldEntriesRecentLog (void);
|
||||||
|
|
||||||
|
|
620
swad_statistic.c
620
swad_statistic.c
|
@ -42,9 +42,11 @@
|
||||||
#include "swad_HTML.h"
|
#include "swad_HTML.h"
|
||||||
#include "swad_ID.h"
|
#include "swad_ID.h"
|
||||||
#include "swad_log.h"
|
#include "swad_log.h"
|
||||||
|
#include "swad_log_database.h"
|
||||||
#include "swad_profile.h"
|
#include "swad_profile.h"
|
||||||
#include "swad_role.h"
|
#include "swad_role.h"
|
||||||
#include "swad_statistic.h"
|
#include "swad_statistic.h"
|
||||||
|
#include "swad_statistic_database.h"
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/************** External global variables from others modules ****************/
|
/************** External global variables from others modules ****************/
|
||||||
|
@ -94,12 +96,6 @@ static const unsigned Sta_CellPadding[Sta_NUM_CLICKS_GROUPED_BY] =
|
||||||
/******************************* Private types *******************************/
|
/******************************* Private types *******************************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
Sta_SHOW_GLOBAL_ACCESSES,
|
|
||||||
Sta_SHOW_COURSE_ACCESSES,
|
|
||||||
} Sta_GlobalOrCourseAccesses_t;
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/***************************** Private prototypes ****************************/
|
/***************************** Private prototypes ****************************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@ -262,8 +258,8 @@ static void Sta_PutFormCrsHits (struct Sta_Stats *Stats)
|
||||||
|
|
||||||
/***** Contextual menu *****/
|
/***** Contextual menu *****/
|
||||||
Mnu_ContextMenuBegin ();
|
Mnu_ContextMenuBegin ();
|
||||||
Sta_PutLinkToGlobalHits (); // Global hits
|
Sta_PutLinkToGlobalHits (); // Global hits
|
||||||
Log_PutLinkToLastClicks (); // Last clicks in real time
|
Log_PutLinkToLastClicks (); // Last clicks in real time
|
||||||
Mnu_ContextMenuEnd ();
|
Mnu_ContextMenuEnd ();
|
||||||
|
|
||||||
/***** Get and update type of list,
|
/***** Get and update type of list,
|
||||||
|
@ -743,10 +739,6 @@ void Sta_SeeCrsAccesses (void)
|
||||||
/******************** Compute and show access statistics ********************/
|
/******************** 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)
|
static void Sta_ShowHits (Sta_GlobalOrCourseAccesses_t GlobalOrCourse)
|
||||||
{
|
{
|
||||||
extern const char *Txt_You_must_select_one_ore_more_users;
|
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_STAT_TYPE_COUNT_CAPS[Sta_NUM_COUNT_TYPES];
|
||||||
extern const char *Txt_Time_zone_used_in_the_calculation_of_these_statistics;
|
extern const char *Txt_Time_zone_used_in_the_calculation_of_these_statistics;
|
||||||
struct Sta_Stats Stats;
|
struct Sta_Stats Stats;
|
||||||
char *Query = NULL;
|
|
||||||
char QueryAux[512];
|
|
||||||
long LengthQuery;
|
|
||||||
MYSQL_RES *mysql_res;
|
MYSQL_RES *mysql_res;
|
||||||
unsigned NumHits;
|
unsigned NumHits;
|
||||||
const char *LogTable;
|
const char *LogTable;
|
||||||
Sta_ClicksDetailedOrGrouped_t DetailedOrGrouped = Sta_CLICKS_GROUPED;
|
Sta_ClicksDetailedOrGrouped_t DetailedOrGrouped = Sta_CLICKS_GROUPED;
|
||||||
struct UsrData UsrDat;
|
|
||||||
char BrowserTimeZone[Dat_MAX_BYTES_TIME_ZONE + 1];
|
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;
|
unsigned NumDays;
|
||||||
bool ICanQueryWholeRange;
|
bool ICanQueryWholeRange;
|
||||||
|
unsigned NumUsrsInList = 0;
|
||||||
|
long *LstSelectedUsrCods = NULL;
|
||||||
|
|
||||||
/***** Reset stats context *****/
|
/***** Reset stats context *****/
|
||||||
Sta_ResetStats (&Stats);
|
Sta_ResetStats (&Stats);
|
||||||
|
Stats.GlobalOrCourse = GlobalOrCourse;
|
||||||
|
|
||||||
/***** Get initial and ending dates *****/
|
/***** Get initial and ending dates *****/
|
||||||
Dat_GetIniEndDatesFromForm ();
|
Dat_GetIniEndDatesFromForm ();
|
||||||
|
@ -820,7 +807,7 @@ static void Sta_ShowHits (Sta_GlobalOrCourseAccesses_t GlobalOrCourse)
|
||||||
Act_NUM_ACTIONS - 1,
|
Act_NUM_ACTIONS - 1,
|
||||||
(unsigned long) Sta_NUM_ACTION_DEFAULT);
|
(unsigned long) Sta_NUM_ACTION_DEFAULT);
|
||||||
|
|
||||||
switch (GlobalOrCourse)
|
switch (Stats.GlobalOrCourse)
|
||||||
{
|
{
|
||||||
case Sta_SHOW_GLOBAL_ACCESSES:
|
case Sta_SHOW_GLOBAL_ACCESSES:
|
||||||
/***** Get the type of user of clicks *****/
|
/***** Get the type of user of clicks *****/
|
||||||
|
@ -883,14 +870,20 @@ static void Sta_ShowHits (Sta_GlobalOrCourseAccesses_t GlobalOrCourse)
|
||||||
/****** Get lists of selected users ******/
|
/****** Get lists of selected users ******/
|
||||||
Usr_GetListsSelectedEncryptedUsrsCods (&Gbl.Usrs.Selected);
|
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 *****/
|
/***** Show the form again *****/
|
||||||
Sta_PutFormCrsHits (&Stats);
|
Sta_PutFormCrsHits (&Stats);
|
||||||
|
|
||||||
/***** Begin results section *****/
|
/***** Begin results section *****/
|
||||||
HTM_SECTION_Begin (Sta_STAT_RESULTS_SECTION_ID);
|
HTM_SECTION_Begin (Sta_STAT_RESULTS_SECTION_ID);
|
||||||
|
|
||||||
/***** Check selection *****/
|
/***** Check users' selection *****/
|
||||||
if (!Usr_CheckIfThereAreUsrsInListOfSelectedEncryptedUsrCods (&Gbl.Usrs.Selected)) // Error: there are no users selected
|
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 */
|
/* Write warning message, clean and abort */
|
||||||
Ale_ShowAlert (Ale_WARNING,Txt_You_must_select_one_ore_more_users);
|
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 *****/
|
/***** Check if range of dates is forbidden for me *****/
|
||||||
NumDays = Dat_GetNumDaysBetweenDates (&Gbl.DateRange.DateIni.Date,&Gbl.DateRange.DateEnd.Date);
|
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_TCH && Gbl.Scope.Current == HieLvl_CRS) ||
|
||||||
(Gbl.Usrs.Me.Role.Logged == Rol_DEG_ADM && (Gbl.Scope.Current == HieLvl_DEG ||
|
(Gbl.Usrs.Me.Role.Logged == Rol_DEG_ADM && (Gbl.Scope.Current == HieLvl_DEG ||
|
||||||
Gbl.Scope.Current == HieLvl_CRS)) ||
|
Gbl.Scope.Current == HieLvl_CRS)) ||
|
||||||
|
@ -922,516 +915,9 @@ static void Sta_ShowHits (Sta_GlobalOrCourseAccesses_t GlobalOrCourse)
|
||||||
return;
|
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 *****/
|
/***** Make the query *****/
|
||||||
NumHits = (unsigned)
|
if ((NumHits = Sta_DB_GetHits (&mysql_res,&Stats,LogTable,BrowserTimeZone,
|
||||||
DB_QuerySELECT (&mysql_res,"can not get clicks",
|
NumUsrsInList,LstSelectedUsrCods)))
|
||||||
"%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
|
|
||||||
{
|
{
|
||||||
/***** Put the table with the clicks *****/
|
/***** Put the table with the clicks *****/
|
||||||
if (Stats.ClicksGroupedBy == Sta_CLICKS_CRS_DETAILED_LIST)
|
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);
|
Sta_ShowNumHitsPerCourse (Stats.CountType,NumHits,mysql_res);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
HTM_TABLE_End ();
|
HTM_TABLE_End ();
|
||||||
|
|
||||||
/* End box and section */
|
/* End box and section */
|
||||||
Box_BoxEnd ();
|
Box_BoxEnd ();
|
||||||
HTM_SECTION_End ();
|
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 *****/
|
/***** Free structure that stores the query result *****/
|
||||||
DB_FreeMySQLResult (&mysql_res);
|
DB_FreeMySQLResult (&mysql_res);
|
||||||
|
|
||||||
/***** Free memory used by list of selected users' codes *****/
|
/***** 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);
|
Usr_FreeListsSelectedEncryptedUsrsCods (&Gbl.Usrs.Selected);
|
||||||
|
}
|
||||||
|
|
||||||
/***** Write time zone used in the calculation of these statistics *****/
|
/***** Write time zone used in the calculation of these statistics *****/
|
||||||
switch (Stats.ClicksGroupedBy)
|
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)
|
static void Sta_WriteLogComments (long LogCod)
|
||||||
|
@ -1795,12 +1288,7 @@ static void Sta_WriteLogComments (long LogCod)
|
||||||
char Comments[Cns_MAX_BYTES_TEXT + 1];
|
char Comments[Cns_MAX_BYTES_TEXT + 1];
|
||||||
|
|
||||||
/***** Get log comments from database *****/
|
/***** Get log comments from database *****/
|
||||||
DB_QuerySELECTString (Comments,sizeof (Comments) - 1,
|
Log_DB_GetLogComments (LogCod,Comments);
|
||||||
"can not get log comments",
|
|
||||||
"SELECT Comments"
|
|
||||||
" FROM log_comments"
|
|
||||||
" WHERE LogCod=%ld",
|
|
||||||
LogCod);
|
|
||||||
|
|
||||||
/***** Write comments *****/
|
/***** Write comments *****/
|
||||||
if (Comments[0])
|
if (Comments[0])
|
||||||
|
@ -2351,7 +1839,7 @@ static void Sta_DrawBarColors (Sta_ColorType_t ColorType,double HitsMax)
|
||||||
HTM_Unsigned (0);
|
HTM_Unsigned (0);
|
||||||
HTM_TD_End ();
|
HTM_TD_End ();
|
||||||
|
|
||||||
for (Interval = 1;
|
for (Interval = 1;
|
||||||
Interval <= 4;
|
Interval <= 4;
|
||||||
Interval++)
|
Interval++)
|
||||||
{
|
{
|
||||||
|
@ -2985,34 +2473,34 @@ static void Sta_ShowAverageAccessesPerMinute (unsigned NumHits,MYSQL_RES *mysql_
|
||||||
/***** X axis *****/
|
/***** X axis *****/
|
||||||
HTM_TR_Begin (NULL);
|
HTM_TR_Begin (NULL);
|
||||||
|
|
||||||
/* First division (left) */
|
/* 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++)
|
|
||||||
{
|
|
||||||
HTM_TD_Begin ("class=\"LM\" style=\"width:%upx;\"",
|
HTM_TD_Begin ("class=\"LM\" style=\"width:%upx;\"",
|
||||||
Sta_WIDTH_SEMIDIVISION_GRAPHIC);
|
Sta_WIDTH_SEMIDIVISION_GRAPHIC);
|
||||||
HTM_IMG (Cfg_URL_ICON_PUBLIC,"ejex24x1.gif",NULL,
|
HTM_IMG (Cfg_URL_ICON_PUBLIC,"ejexizq24x1.gif",NULL,
|
||||||
"style=\"display:block;width:%upx;height:1px;\"",
|
"style=\"display:block;width:%upx;height:1px;\"",
|
||||||
Sta_WIDTH_SEMIDIVISION_GRAPHIC);
|
Sta_WIDTH_SEMIDIVISION_GRAPHIC);
|
||||||
HTM_TD_End ();
|
HTM_TD_End ();
|
||||||
}
|
|
||||||
|
|
||||||
/* Last division (right) */
|
/* All the intermediate divisions */
|
||||||
HTM_TD_Begin ("class=\"LM\" style=\"width:%upx;\"",
|
for (i = 0;
|
||||||
Sta_WIDTH_SEMIDIVISION_GRAPHIC);
|
i < Sta_NUM_DIVISIONS_X * 2;
|
||||||
HTM_IMG (Cfg_URL_ICON_PUBLIC,"tr24x1.gif",NULL,
|
i++)
|
||||||
"style=\"display:block;width:%upx;height:1px;\"",
|
{
|
||||||
Sta_WIDTH_SEMIDIVISION_GRAPHIC);
|
HTM_TD_Begin ("class=\"LM\" style=\"width:%upx;\"",
|
||||||
HTM_TD_End ();
|
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 ();
|
HTM_TR_End ();
|
||||||
|
|
||||||
|
|
|
@ -128,8 +128,15 @@ struct Sta_Hits
|
||||||
double Total;
|
double Total;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
Sta_SHOW_GLOBAL_ACCESSES,
|
||||||
|
Sta_SHOW_COURSE_ACCESSES,
|
||||||
|
} Sta_GlobalOrCourseAccesses_t;
|
||||||
|
|
||||||
struct Sta_Stats
|
struct Sta_Stats
|
||||||
{
|
{
|
||||||
|
Sta_GlobalOrCourseAccesses_t GlobalOrCourse;
|
||||||
Sta_ClicksGroupedBy_t ClicksGroupedBy;
|
Sta_ClicksGroupedBy_t ClicksGroupedBy;
|
||||||
Sta_Role_t Role;
|
Sta_Role_t Role;
|
||||||
Sta_CountType_t CountType;
|
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;
|
size_t MaxLength;
|
||||||
|
|
||||||
/***** Allocate space for subquery *****/
|
/***** 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)
|
if ((*UsrsSubQuery = malloc (MaxLength + 1)) == NULL)
|
||||||
Err_NotEnoughMemoryExit ();
|
Err_NotEnoughMemoryExit ();
|
||||||
(*UsrsSubQuery)[0] = '\0';
|
(*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 *****/
|
/***** Allocate memory for the string with the list of group names where student belongs to *****/
|
||||||
if (Gbl.Scope.Current == HieLvl_CRS)
|
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)
|
if ((GroupNames = malloc (Length + 1)) == NULL)
|
||||||
Err_NotEnoughMemoryExit ();
|
Err_NotEnoughMemoryExit ();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue