swad-core/swad_statistic.c

4251 lines
151 KiB
C
Raw Normal View History

2014-12-01 23:55:08 +01:00
// swad_statistic.c: statistics
/*
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.
2019-01-07 21:52:19 +01:00
Copyright (C) 1999-2019 Antonio Ca<EFBFBD>as Vargas
2014-12-01 23:55:08 +01:00
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 <math.h> // For log10, floor, ceil, modf, sqrt...
2019-02-13 13:32:11 +01:00
#include <stdlib.h> // For getenv, malloc
2014-12-01 23:55:08 +01:00
#include <string.h> // For string functions
2017-06-10 21:38:10 +02:00
#include "swad_box.h"
2014-12-01 23:55:08 +01:00
#include "swad_database.h"
2018-11-09 20:47:39 +01:00
#include "swad_form.h"
2014-12-01 23:55:08 +01:00
#include "swad_global.h"
#include "swad_ID.h"
2015-03-14 17:39:04 +01:00
#include "swad_profile.h"
2019-01-11 12:32:41 +01:00
#include "swad_role.h"
2014-12-01 23:55:08 +01:00
#include "swad_statistic.h"
2017-06-11 20:09:59 +02:00
#include "swad_table.h"
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
extern struct Globals Gbl;
/*****************************************************************************/
/***************************** Private constants *****************************/
/*****************************************************************************/
2017-01-28 15:58:46 +01:00
#define Sta_SECONDS_IN_RECENT_LOG ((time_t) (Cfg_DAYS_IN_RECENT_LOG * 24UL * 60UL * 60UL)) // Remove entries in recent log oldest than this time
2014-12-01 23:55:08 +01:00
2015-11-12 01:27:33 +01:00
const unsigned Sta_CellPadding[Sta_NUM_CLICKS_GROUPED_BY] =
{
2017-06-11 20:21:44 +02:00
2, // Sta_CLICKS_CRS_DETAILED_LIST
2015-11-12 01:27:33 +01:00
1, // Sta_CLICKS_CRS_PER_USR
2018-10-07 14:01:25 +02:00
1, // Sta_CLICKS_CRS_PER_DAY
0, // Sta_CLICKS_CRS_PER_DAY_AND_HOUR
1, // Sta_CLICKS_CRS_PER_WEEK
1, // Sta_CLICKS_CRS_PER_MONTH
1, // Sta_CLICKS_CRS_PER_YEAR
2015-11-12 01:27:33 +01:00
1, // Sta_CLICKS_CRS_PER_HOUR
0, // Sta_CLICKS_CRS_PER_MINUTE
1, // Sta_CLICKS_CRS_PER_ACTION
2018-10-07 14:01:25 +02:00
1, // Sta_CLICKS_GBL_PER_DAY
0, // Sta_CLICKS_GBL_PER_DAY_AND_HOUR
1, // Sta_CLICKS_GBL_PER_WEEK
1, // Sta_CLICKS_GBL_PER_MONTH
1, // Sta_CLICKS_GBL_PER_YEAR
2015-11-12 01:27:33 +01:00
1, // Sta_CLICKS_GBL_PER_HOUR
0, // Sta_CLICKS_GBL_PER_MINUTE
1, // Sta_CLICKS_GBL_PER_ACTION
1, // Sta_CLICKS_GBL_PER_PLUGIN
2018-10-07 14:01:25 +02:00
1, // Sta_CLICKS_GBL_PER_API_FUNCTION
2015-11-12 01:27:33 +01:00
1, // Sta_CLICKS_GBL_PER_BANNER
1, // Sta_CLICKS_GBL_PER_COUNTRY
1, // Sta_CLICKS_GBL_PER_INSTITUTION
1, // Sta_CLICKS_GBL_PER_CENTRE
1, // Sta_CLICKS_GBL_PER_DEGREE
1, // Sta_CLICKS_GBL_PER_COURSE
};
2017-05-25 13:43:54 +02:00
#define Sta_STAT_RESULTS_SECTION_ID "stat_results"
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/******************************* Private types *******************************/
/*****************************************************************************/
2015-09-30 23:26:48 +02:00
typedef enum
{
Sta_SHOW_GLOBAL_ACCESSES,
Sta_SHOW_COURSE_ACCESSES,
} Sta_GlobalOrCourseAccesses_t;
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/***************************** Internal prototypes ***************************/
/*****************************************************************************/
2019-01-11 12:32:41 +01:00
static void Sta_PutLinkToCourseHits (void);
static void Sta_PutLinkToGlobalHits (void);
2014-12-01 23:55:08 +01:00
static void Sta_WriteSelectorCountType (void);
static void Sta_WriteSelectorAction (void);
2015-10-11 17:40:07 +02:00
static void Sta_ShowHits (Sta_GlobalOrCourseAccesses_t GlobalOrCourse);
2014-12-01 23:55:08 +01:00
static void Sta_ShowDetailedAccessesList (unsigned long NumRows,MYSQL_RES *mysql_res);
static void Sta_WriteLogComments (long LogCod);
2017-05-22 20:37:46 +02:00
static void Sta_ShowNumHitsPerUsr (unsigned long NumRows,MYSQL_RES *mysql_res);
2018-10-07 14:01:25 +02:00
static void Sta_ShowNumHitsPerDay (unsigned long NumRows,MYSQL_RES *mysql_res);
static void Sta_ShowDistrAccessesPerDayAndHour (unsigned long NumRows,MYSQL_RES *mysql_res);
2019-02-12 14:46:14 +01:00
static void Sta_PutHiddenParamScopeSta (void);
2014-12-01 23:55:08 +01:00
static Sta_ColorType_t Sta_GetStatColorType (void);
2015-10-11 18:53:22 +02:00
static void Sta_DrawBarColors (Sta_ColorType_t ColorType,float HitsMax);
static void Sta_DrawAccessesPerHourForADay (Sta_ColorType_t ColorType,float HitsNum[24],float HitsMax);
static void Sta_SetColor (Sta_ColorType_t ColorType,float HitsNum,float HitsMax,
unsigned *R,unsigned *G,unsigned *B);
2018-10-07 14:01:25 +02:00
static void Sta_ShowNumHitsPerWeek (unsigned long NumRows,
2015-10-11 14:12:20 +02:00
MYSQL_RES *mysql_res);
2018-10-07 14:01:25 +02:00
static void Sta_ShowNumHitsPerMonth (unsigned long NumRows,
2015-10-11 14:12:20 +02:00
MYSQL_RES *mysql_res);
2018-10-07 14:01:25 +02:00
static void Sta_ShowNumHitsPerYear (unsigned long NumRows,
MYSQL_RES *mysql_res);
2015-10-11 14:12:20 +02:00
static void Sta_ShowNumHitsPerHour (unsigned long NumRows,
MYSQL_RES *mysql_res);
2015-10-11 18:53:22 +02:00
static void Sta_WriteAccessHour (unsigned Hour,struct Sta_Hits *Hits,unsigned ColumnWidth);
2014-12-01 23:55:08 +01:00
static void Sta_ShowAverageAccessesPerMinute (unsigned long NumRows,MYSQL_RES *mysql_res);
static void Sta_WriteLabelsXAxisAccMin (float IncX,const char *Format);
2015-10-11 18:53:22 +02:00
static void Sta_WriteAccessMinute (unsigned Minute,float HitsNum,float MaxX);
2015-10-11 14:12:20 +02:00
static void Sta_ShowNumHitsPerAction (unsigned long NumRows,
MYSQL_RES *mysql_res);
static void Sta_ShowNumHitsPerPlugin (unsigned long NumRows,
MYSQL_RES *mysql_res);
static void Sta_ShowNumHitsPerWSFunction (unsigned long NumRows,
MYSQL_RES *mysql_res);
static void Sta_ShowNumHitsPerBanner (unsigned long NumRows,
MYSQL_RES *mysql_res);
static void Sta_ShowNumHitsPerCountry (unsigned long NumRows,
MYSQL_RES *mysql_res);
static void Sta_WriteCountry (long CtyCod);
static void Sta_ShowNumHitsPerInstitution (unsigned long NumRows,
MYSQL_RES *mysql_res);
static void Sta_WriteInstitution (long InsCod);
static void Sta_ShowNumHitsPerCentre (unsigned long NumRows,
MYSQL_RES *mysql_res);
static void Sta_WriteCentre (long CtrCod);
static void Sta_ShowNumHitsPerDegree (unsigned long NumRows,
MYSQL_RES *mysql_res);
2014-12-01 23:55:08 +01:00
static void Sta_WriteDegree (long DegCod);
2015-10-11 14:12:20 +02:00
static void Sta_ShowNumHitsPerCourse (unsigned long NumRows,
MYSQL_RES *mysql_res);
2014-12-01 23:55:08 +01:00
2018-10-07 15:13:24 +02:00
static void Sta_DrawBarNumHits (char Color,
float HitsNum,float HitsMax,float HitsTotal,
unsigned MaxBarWidth);
2016-09-12 01:06:36 +02:00
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/*************** Read CGI environment variable REMOTE_ADDR *******************/
/*****************************************************************************/
/*
CGI Environment Variables:
REMOTE_ADDR
The IP address of the remote host making the request.
*/
void Sta_GetRemoteAddr (void)
{
if (getenv ("REMOTE_ADDR"))
2017-01-17 03:10:43 +01:00
Str_Copy (Gbl.IP,getenv ("REMOTE_ADDR"),
2017-03-07 11:03:05 +01:00
Cns_MAX_BYTES_IP);
2014-12-01 23:55:08 +01:00
else
Gbl.IP[0] = '\0';
}
/*****************************************************************************/
/**************************** Log access in database *************************/
/*****************************************************************************/
void Sta_LogAccess (const char *Comments)
{
long LogCod;
2018-04-24 13:21:53 +02:00
long ActCod = Act_GetActCod (Gbl.Action.Act);
2017-06-04 18:18:54 +02:00
Rol_Role_t RoleToStore = (Gbl.Action.Act == ActLogOut) ? Gbl.Usrs.Me.Role.LoggedBeforeCloseSession :
Gbl.Usrs.Me.Role.Logged;
2014-12-01 23:55:08 +01:00
/***** Insert access into database *****/
2015-10-16 02:24:29 +02:00
/* Log access in historical log (log_full) */
2018-11-03 01:45:36 +01:00
LogCod =
DB_QueryINSERTandReturnCode ("can not log access (full)",
"INSERT INTO log_full "
"(ActCod,CtyCod,InsCod,CtrCod,DegCod,CrsCod,UsrCod,"
"Role,ClickTime,TimeToGenerate,TimeToSend,IP)"
" VALUES "
"(%ld,%ld,%ld,%ld,%ld,%ld,%ld,"
"%u,NOW(),%ld,%ld,'%s')",
ActCod,
2019-04-03 20:57:04 +02:00
Gbl.Hierarchy.Cty.CtyCod,
Gbl.Hierarchy.Ins.InsCod,
Gbl.Hierarchy.Ctr.CtrCod,
Gbl.Hierarchy.Deg.DegCod,
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.CrsCod,
2018-11-03 01:45:36 +01:00
Gbl.Usrs.Me.UsrDat.UsrCod,
(unsigned) RoleToStore,
Gbl.TimeGenerationInMicroseconds,
Gbl.TimeSendInMicroseconds,
Gbl.IP);
2014-12-01 23:55:08 +01:00
2015-10-16 02:24:29 +02:00
/* Log access in recent log (log_recent) */
2018-11-02 19:37:11 +01:00
DB_QueryINSERT ("can not log access (recent)",
"INSERT INTO log_recent "
"(LogCod,ActCod,CtyCod,InsCod,CtrCod,DegCod,CrsCod,UsrCod,"
"Role,ClickTime,TimeToGenerate,TimeToSend,IP)"
" VALUES "
"(%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,"
"%u,NOW(),%ld,%ld,'%s')",
LogCod,ActCod,
2019-04-03 20:57:04 +02:00
Gbl.Hierarchy.Cty.CtyCod,
Gbl.Hierarchy.Ins.InsCod,
Gbl.Hierarchy.Ctr.CtrCod,
Gbl.Hierarchy.Deg.DegCod,
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.CrsCod,
2018-11-02 19:37:11 +01:00
Gbl.Usrs.Me.UsrDat.UsrCod,
(unsigned) RoleToStore,
Gbl.TimeGenerationInMicroseconds,
Gbl.TimeSendInMicroseconds,
Gbl.IP);
2014-12-01 23:55:08 +01:00
2018-11-04 20:51:38 +01:00
/* Log comments */
2014-12-01 23:55:08 +01:00
if (Comments)
2018-11-04 20:51:38 +01:00
DB_QueryINSERT ("can not log access (comments)",
"INSERT INTO log_comments"
" (LogCod,Comments)"
" VALUES"
" (%ld,'%s')",
2018-11-05 19:40:36 +01:00
LogCod,Comments);
2014-12-01 23:55:08 +01:00
2018-11-04 20:51:38 +01:00
/* Log search string */
2017-02-27 01:41:46 +01:00
if (Gbl.Search.LogSearch && Gbl.Search.Str[0])
2018-11-04 20:51:38 +01:00
DB_QueryINSERT ("can not log access (search)",
"INSERT INTO log_search"
" (LogCod,SearchStr)"
" VALUES"
" (%ld,'%s')",
2018-12-10 10:48:44 +01:00
LogCod,Gbl.Search.Str);
2017-02-27 01:41:46 +01:00
2014-12-01 23:55:08 +01:00
if (Gbl.WebService.IsWebService)
/* Log web service plugin and function */
2018-11-02 19:37:11 +01:00
DB_QueryINSERT ("can not log access (comments)",
"INSERT INTO log_ws"
" (LogCod,PlgCod,FunCod)"
" VALUES"
" (%ld,%ld,%u)",
LogCod,Gbl.WebService.PlgCod,
(unsigned) Gbl.WebService.Function);
2014-12-01 23:55:08 +01:00
else if (Gbl.Banners.BanCodClicked > 0)
/* Log banner clicked */
2018-11-02 19:37:11 +01:00
DB_QueryINSERT ("can not log banner clicked",
"INSERT INTO log_banners"
" (LogCod,BanCod)"
" VALUES"
" (%ld,%ld)",
LogCod,Gbl.Banners.BanCodClicked);
2015-03-10 01:47:25 +01:00
/***** Increment my number of clicks *****/
2018-10-10 23:56:42 +02:00
if (Gbl.Usrs.Me.Logged)
2015-03-14 17:39:04 +01:00
Prf_IncrementNumClicksUsr (Gbl.Usrs.Me.UsrDat.UsrCod);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************ Sometimes, we delete old entries in recent log table ***********/
/*****************************************************************************/
void Sta_RemoveOldEntriesRecentLog (void)
{
/***** Remove all expired clipboards *****/
2018-11-02 22:00:31 +01:00
DB_QueryDELETE ("can not remove old entries from recent log",
"DELETE LOW_PRIORITY FROM log_recent"
2019-02-13 13:32:11 +01:00
" WHERE ClickTime<FROM_UNIXTIME(UNIX_TIMESTAMP()-%lu)",
2018-11-02 22:00:31 +01:00
Sta_SECONDS_IN_RECENT_LOG);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************** Show a form to make a query of clicks ******************/
/*****************************************************************************/
2015-10-11 17:40:07 +02:00
void Sta_AskShowCrsHits (void)
2014-12-01 23:55:08 +01:00
{
2017-12-19 18:41:19 +01:00
extern const char *Hlp_ANALYTICS_Visits_visits_to_course;
2019-02-22 21:47:50 +01:00
extern const char *The_ClassFormInBox[The_NUM_THEMES];
2015-09-30 23:10:15 +02:00
extern const char *Txt_Statistics_of_visits_to_the_course_X;
2015-09-25 01:48:00 +02:00
extern const char *Txt_Users;
extern const char *Txt_Show;
2014-12-01 23:55:08 +01:00
extern const char *Txt_distributed_by;
2015-09-25 01:48:00 +02:00
extern const char *Txt_STAT_CLICKS_GROUPED_BY[Sta_NUM_CLICKS_GROUPED_BY];
2014-12-01 23:55:08 +01:00
extern const char *Txt_results_per_page;
2015-10-11 14:12:20 +02:00
extern const char *Txt_Show_hits;
2015-03-24 17:47:26 +01:00
extern const char *Txt_No_teachers_or_students_found;
2016-11-06 15:36:26 +01:00
static unsigned long RowsPerPage[] =
{
2017-01-29 21:41:08 +01:00
Sta_MIN_ROWS_PER_PAGE * 1,
Sta_MIN_ROWS_PER_PAGE * 2,
Sta_MIN_ROWS_PER_PAGE * 3,
Sta_MIN_ROWS_PER_PAGE * 4,
Sta_MIN_ROWS_PER_PAGE * 5,
Sta_MIN_ROWS_PER_PAGE * 10,
Sta_MIN_ROWS_PER_PAGE * 50,
Sta_MIN_ROWS_PER_PAGE * 100,
Sta_MIN_ROWS_PER_PAGE * 500,
Sta_MIN_ROWS_PER_PAGE * 1000,
Sta_MIN_ROWS_PER_PAGE * 5000,
Sta_MAX_ROWS_PER_PAGE,
2016-11-06 15:36:26 +01:00
};
2014-12-31 01:09:25 +01:00
#define NUM_OPTIONS_ROWS_PER_PAGE (sizeof (RowsPerPage) / sizeof (RowsPerPage[0]))
2016-06-23 13:51:37 +02:00
unsigned NumTotalUsrs;
2015-09-25 01:48:00 +02:00
Sta_ClicksGroupedBy_t ClicksGroupedBy;
2014-12-01 23:55:08 +01:00
unsigned long i;
2019-01-11 12:32:41 +01:00
/***** Contextual links *****/
fprintf (Gbl.F.Out,"<div class=\"CONTEXT_MENU\">");
/* Put form to go to test edition and configuration */
Sta_PutLinkToGlobalHits ();
/* Link to show last clicks in real time */
2019-02-12 14:46:14 +01:00
Sta_PutLinkToLastClicks ();
2019-01-11 12:32:41 +01:00
fprintf (Gbl.F.Out,"</div>");
2015-10-19 21:49:45 +02:00
/***** Get and update type of list,
number of columns in class photo
and preference about view photos *****/
2014-12-01 23:55:08 +01:00
Usr_GetAndUpdatePrefsAboutUsrList ();
2016-11-25 03:21:02 +01:00
/***** Get groups to show ******/
Grp_GetParCodsSeveralGrpsToShowUsrs ();
2014-12-01 23:55:08 +01:00
/***** Get and order the lists of users of this course *****/
2019-04-03 20:57:04 +02:00
Usr_GetListUsrs (Hie_CRS,Rol_STD);
Usr_GetListUsrs (Hie_CRS,Rol_NET);
Usr_GetListUsrs (Hie_CRS,Rol_TCH);
2017-05-22 20:37:46 +02:00
NumTotalUsrs = Gbl.Usrs.LstUsrs[Rol_STD].NumUsrs +
Gbl.Usrs.LstUsrs[Rol_NET].NumUsrs +
Gbl.Usrs.LstUsrs[Rol_TCH].NumUsrs;
2014-12-01 23:55:08 +01:00
2017-06-12 14:16:33 +02:00
/***** Start box *****/
2018-10-18 02:02:32 +02:00
snprintf (Gbl.Title,sizeof (Gbl.Title),
Txt_Statistics_of_visits_to_the_course_X,
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.ShrtName);
2017-06-10 21:38:10 +02:00
Box_StartBox (NULL,Gbl.Title,NULL,
2017-12-19 18:41:19 +01:00
Hlp_ANALYTICS_Visits_visits_to_course,Box_NOT_CLOSABLE);
2016-11-25 03:21:02 +01:00
/***** Show form to select the groups *****/
2017-07-02 18:53:35 +02:00
Grp_ShowFormToSelectSeveralGroups (ActReqAccCrs,Grp_ONLY_MY_GROUPS);
2017-05-25 11:04:38 +02:00
/***** Start section with user list *****/
2017-05-25 13:43:54 +02:00
Lay_StartSection (Usr_USER_LIST_SECTION_ID);
2016-11-25 03:21:02 +01:00
2016-06-23 13:51:37 +02:00
if (NumTotalUsrs)
2014-12-01 23:55:08 +01:00
{
2016-07-04 14:03:04 +02:00
if (Usr_GetIfShowBigList (NumTotalUsrs,NULL))
2014-12-01 23:55:08 +01:00
{
2015-10-02 01:04:28 +02:00
/***** Form to select type of list used for select several users *****/
Usr_ShowFormsToSelectUsrListType (ActReqAccCrs);
2017-05-29 21:34:43 +02:00
/***** Put link to register students *****/
Enr_CheckStdsAndPutButtonToRegisterStdsInCurrentCrs ();
2015-10-02 01:04:28 +02:00
/***** Start form *****/
2018-11-09 20:47:39 +01:00
Frm_StartFormAnchor (ActSeeAccCrs,Sta_STAT_RESULTS_SECTION_ID);
2015-10-11 14:12:20 +02:00
2014-12-01 23:55:08 +01:00
Grp_PutParamsCodGrps ();
Par_PutHiddenParamLong ("FirstRow",0);
Par_PutHiddenParamLong ("LastRow",0);
2015-09-25 01:48:00 +02:00
/***** Put list of users to select some of them *****/
2017-06-11 20:09:59 +02:00
Tbl_StartTableCenter (2);
2017-05-01 12:36:24 +02:00
fprintf (Gbl.F.Out,"<tr>"
2016-12-20 02:18:50 +01:00
"<td class=\"RIGHT_TOP %s\">%s:"
2015-09-25 01:48:00 +02:00
"</td>"
2015-10-02 12:28:52 +02:00
"<td colspan=\"2\" class=\"%s LEFT_TOP\">"
2015-09-25 01:48:00 +02:00
"<table>",
2019-02-22 21:47:50 +01:00
The_ClassFormInBox[Gbl.Prefs.Theme],Txt_Users,
The_ClassFormInBox[Gbl.Prefs.Theme]);
2017-05-18 19:13:41 +02:00
Usr_ListUsersToSelect (Rol_TCH);
2017-05-22 20:37:46 +02:00
Usr_ListUsersToSelect (Rol_NET);
2017-05-18 19:13:41 +02:00
Usr_ListUsersToSelect (Rol_STD);
2015-09-25 01:48:00 +02:00
fprintf (Gbl.F.Out,"</table>"
"</td>"
2014-12-01 23:55:08 +01:00
"</tr>");
/***** Initial and final dates of the search *****/
2017-02-26 20:09:21 +01:00
Dat_PutFormStartEndClientLocalDateTimesWithYesterdayToday (Gbl.Action.Act == ActReqAccCrs);
2014-12-01 23:55:08 +01:00
/***** Selection of action *****/
Sta_WriteSelectorAction ();
2015-09-25 01:48:00 +02:00
/***** Option a) Listing of clicks distributed by some metric *****/
fprintf (Gbl.F.Out,"<tr>"
2018-10-27 14:14:34 +02:00
"<td class=\"RIGHT_MIDDLE %s\">%s:</td>"
"<td colspan=\"2\" class=\"LEFT_MIDDLE\">",
2019-02-22 21:47:50 +01:00
The_ClassFormInBox[Gbl.Prefs.Theme],Txt_Show);
2015-09-25 01:48:00 +02:00
if ((Gbl.Stat.ClicksGroupedBy < Sta_CLICKS_CRS_PER_USR ||
Gbl.Stat.ClicksGroupedBy > Sta_CLICKS_CRS_PER_ACTION) &&
Gbl.Stat.ClicksGroupedBy != Sta_CLICKS_CRS_DETAILED_LIST)
2017-01-29 21:41:08 +01:00
Gbl.Stat.ClicksGroupedBy = Sta_CLICKS_GROUPED_BY_DEFAULT;
2015-09-25 01:48:00 +02:00
2016-12-25 21:43:59 +01:00
fprintf (Gbl.F.Out,"<input type=\"radio\""
" name=\"GroupedOrDetailed\" value=\"%u\"",
2015-09-25 01:48:00 +02:00
(unsigned) Sta_CLICKS_GROUPED);
if (Gbl.Stat.ClicksGroupedBy != Sta_CLICKS_CRS_DETAILED_LIST)
fprintf (Gbl.F.Out," checked=\"checked\"");
fprintf (Gbl.F.Out," onclick=\"disableDetailedClicks()\" />");
/* Selection of count type (number of pages generated, accesses per user, etc.) */
2014-12-01 23:55:08 +01:00
Sta_WriteSelectorCountType ();
2016-12-20 02:18:50 +01:00
fprintf (Gbl.F.Out,"<label class=\"%s\">&nbsp;%s&nbsp;"
2016-03-27 21:36:52 +02:00
"<select id=\"GroupedBy\" name=\"GroupedBy\">",
2019-02-22 21:47:50 +01:00
The_ClassFormInBox[Gbl.Prefs.Theme],Txt_distributed_by);
2015-09-25 01:48:00 +02:00
for (ClicksGroupedBy = Sta_CLICKS_CRS_PER_USR;
ClicksGroupedBy <= Sta_CLICKS_CRS_PER_ACTION;
ClicksGroupedBy++)
2014-12-01 23:55:08 +01:00
{
2015-09-25 01:48:00 +02:00
fprintf (Gbl.F.Out,"<option value=\"%u\"",
(unsigned) ClicksGroupedBy);
if (ClicksGroupedBy == Gbl.Stat.ClicksGroupedBy)
fprintf (Gbl.F.Out," selected=\"selected\"");
fprintf (Gbl.F.Out,">%s",Txt_STAT_CLICKS_GROUPED_BY[ClicksGroupedBy]);
2014-12-01 23:55:08 +01:00
}
2015-09-25 01:48:00 +02:00
fprintf (Gbl.F.Out,"</select>"
2016-12-20 02:18:50 +01:00
"</label><br />");
2014-12-01 23:55:08 +01:00
2015-09-25 01:48:00 +02:00
/***** Option b) Listing of detailed clicks to this course *****/
2016-12-25 21:43:59 +01:00
fprintf (Gbl.F.Out,"<label>"
"<input type=\"radio\""
" name=\"GroupedOrDetailed\" value=\"%u\"",
2015-09-25 01:48:00 +02:00
(unsigned) Sta_CLICKS_DETAILED);
if (Gbl.Stat.ClicksGroupedBy == Sta_CLICKS_CRS_DETAILED_LIST)
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out," checked=\"checked\"");
2016-12-25 21:43:59 +01:00
fprintf (Gbl.F.Out," onclick=\"enableDetailedClicks()\" />"
"%s"
"</label>",
2015-09-25 01:48:00 +02:00
Txt_STAT_CLICKS_GROUPED_BY[Sta_CLICKS_CRS_DETAILED_LIST]);
2014-12-01 23:55:08 +01:00
/* Number of rows per page */
// To use getElementById in Firefox, it's necessary to have the id attribute
2016-12-25 21:43:59 +01:00
fprintf (Gbl.F.Out," "
"<label>"
"(%s: <select id=\"RowsPage\" name=\"RowsPage\"",
2014-12-01 23:55:08 +01:00
Txt_results_per_page);
2015-09-25 01:48:00 +02:00
if (Gbl.Stat.ClicksGroupedBy != Sta_CLICKS_CRS_DETAILED_LIST)
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out," disabled=\"disabled\"");
fprintf (Gbl.F.Out,">");
for (i = 0;
2014-12-31 01:09:25 +01:00
i < NUM_OPTIONS_ROWS_PER_PAGE;
2014-12-01 23:55:08 +01:00
i++)
{
fprintf (Gbl.F.Out,"<option");
if (RowsPerPage[i] == Gbl.Stat.RowsPerPage)
fprintf (Gbl.F.Out," selected=\"selected\"");
fprintf (Gbl.F.Out,">%lu",RowsPerPage[i]);
}
fprintf (Gbl.F.Out,"</select>)"
2016-12-25 21:43:59 +01:00
"</label>"
2014-12-01 23:55:08 +01:00
"</td>"
2017-05-01 12:36:24 +02:00
"</tr>");
2017-06-11 20:09:59 +02:00
Tbl_EndTable ();
2014-12-01 23:55:08 +01:00
2015-10-27 22:59:49 +01:00
/***** Hidden param used to get client time zone *****/
2015-10-28 21:47:42 +01:00
Dat_PutHiddenParBrowserTZDiff ();
2015-10-26 23:16:21 +01:00
2015-10-02 01:04:28 +02:00
/***** Send button *****/
2017-06-11 19:02:40 +02:00
Btn_PutConfirmButton (Txt_Show_hits);
2014-12-01 23:55:08 +01:00
2015-04-11 17:33:14 +02:00
/***** End form *****/
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2014-12-01 23:55:08 +01:00
}
}
else // No teachers nor students found
2019-02-16 18:25:41 +01:00
Ale_ShowAlert (Ale_WARNING,Txt_No_teachers_or_students_found);
2014-12-01 23:55:08 +01:00
2017-05-25 11:04:38 +02:00
/***** End section with user list *****/
2017-05-25 13:43:54 +02:00
Lay_EndSection ();
2017-05-25 11:04:38 +02:00
2017-06-12 14:16:33 +02:00
/***** End box *****/
2017-06-10 21:38:10 +02:00
Box_EndBox ();
2016-11-24 21:02:04 +01:00
/***** Free memory used by the lists *****/
2017-05-18 19:13:41 +02:00
Usr_FreeUsrsList (Rol_TCH);
2017-05-22 20:37:46 +02:00
Usr_FreeUsrsList (Rol_NET);
2017-05-18 19:13:41 +02:00
Usr_FreeUsrsList (Rol_STD);
2014-12-01 23:55:08 +01:00
2016-11-24 21:02:04 +01:00
/***** Free memory for list of selected groups *****/
2014-12-01 23:55:08 +01:00
Grp_FreeListCodSelectedGrps ();
}
/*****************************************************************************/
/********** Show a form to select the type of global stat of clics ***********/
/*****************************************************************************/
2015-10-11 17:40:07 +02:00
void Sta_AskShowGblHits (void)
2014-12-01 23:55:08 +01:00
{
2017-12-19 18:41:19 +01:00
extern const char *Hlp_ANALYTICS_Visits_global_visits;
2019-02-22 21:47:50 +01:00
extern const char *The_ClassFormInBox[The_NUM_THEMES];
2015-09-30 23:10:15 +02:00
extern const char *Txt_Statistics_of_all_visits;
2014-12-01 23:55:08 +01:00
extern const char *Txt_Users;
extern const char *Txt_ROLE_STATS[Sta_NUM_ROLES_STAT];
extern const char *Txt_Scope;
2015-09-25 01:48:00 +02:00
extern const char *Txt_Show;
2014-12-01 23:55:08 +01:00
extern const char *Txt_distributed_by;
2015-09-25 01:48:00 +02:00
extern const char *Txt_STAT_CLICKS_GROUPED_BY[Sta_NUM_CLICKS_GROUPED_BY];
2015-10-11 14:12:20 +02:00
extern const char *Txt_Show_hits;
2014-12-01 23:55:08 +01:00
Sta_Role_t RoleStat;
2015-09-25 01:48:00 +02:00
Sta_ClicksGroupedBy_t ClicksGroupedBy;
2014-12-01 23:55:08 +01:00
2015-10-07 22:48:13 +02:00
/***** Contextual links *****/
2016-12-10 16:12:19 +01:00
fprintf (Gbl.F.Out,"<div class=\"CONTEXT_MENU\">");
2015-10-07 22:48:13 +02:00
/* Put form to go to test edition and configuration */
2019-01-11 12:32:41 +01:00
Sta_PutLinkToCourseHits ();
2015-10-07 22:48:13 +02:00
/* Link to show last clicks in real time */
2019-02-12 14:46:14 +01:00
Sta_PutLinkToLastClicks ();
2015-10-07 22:48:13 +02:00
fprintf (Gbl.F.Out,"</div>");
2014-12-31 00:48:40 +01:00
2014-12-01 23:55:08 +01:00
/***** Start form *****/
2018-11-09 20:47:39 +01:00
Frm_StartFormAnchor (ActSeeAccGbl,Sta_STAT_RESULTS_SECTION_ID);
2015-09-25 01:48:00 +02:00
2017-06-12 14:16:33 +02:00
/***** Start box and table *****/
2017-06-10 21:38:10 +02:00
Box_StartBoxTable (NULL,Txt_Statistics_of_all_visits,NULL,
2017-12-19 18:41:19 +01:00
Hlp_ANALYTICS_Visits_global_visits,Box_NOT_CLOSABLE,2);
2014-12-01 23:55:08 +01:00
/***** Start and end dates for the search *****/
2017-02-26 20:09:21 +01:00
Dat_PutFormStartEndClientLocalDateTimesWithYesterdayToday (Gbl.Action.Act == ActReqAccGbl);
2014-12-01 23:55:08 +01:00
/***** Users' roles whose accesses we want to see *****/
fprintf (Gbl.F.Out,"<tr>"
2016-03-27 21:36:52 +02:00
"<td class=\"RIGHT_MIDDLE\">"
2016-12-20 02:18:50 +01:00
"<label for=\"Role\" class=\"%s\">%s:</label>"
2014-12-25 12:54:21 +01:00
"</td>"
2015-10-02 12:28:52 +02:00
"<td colspan=\"2\" class=\"LEFT_MIDDLE\">"
2016-12-20 02:18:50 +01:00
"<select id=\"Role\" name=\"Role\">",
2019-02-22 21:47:50 +01:00
The_ClassFormInBox[Gbl.Prefs.Theme],Txt_Users);
2014-12-01 23:55:08 +01:00
for (RoleStat = (Sta_Role_t) 0;
RoleStat < Sta_NUM_ROLES_STAT;
RoleStat++)
{
fprintf (Gbl.F.Out,"<option value=\"%u\"",(unsigned) RoleStat);
if (RoleStat == Gbl.Stat.Role)
fprintf (Gbl.F.Out," selected=\"selected\"");
fprintf (Gbl.F.Out,">%s",Txt_ROLE_STATS[RoleStat]);
}
fprintf (Gbl.F.Out,"</select>"
"</td>"
"</tr>");
/***** Selection of action *****/
Sta_WriteSelectorAction ();
/***** Clicks made from anywhere, current centre, current degree or current course *****/
fprintf (Gbl.F.Out,"<tr>"
2016-03-27 21:36:52 +02:00
"<td class=\"RIGHT_MIDDLE\">"
2016-12-20 02:18:50 +01:00
"<label for=\"ScopeSta\" class=\"%s\">%s:</label>"
2014-12-25 12:54:21 +01:00
"</td>"
2015-10-02 12:28:52 +02:00
"<td colspan=\"2\" class=\"LEFT_MIDDLE\">",
2019-02-22 21:47:50 +01:00
The_ClassFormInBox[Gbl.Prefs.Theme],Txt_Scope);
2019-04-03 20:57:04 +02:00
Gbl.Scope.Allowed = 1 << Hie_SYS |
1 << Hie_CTY |
1 << Hie_INS |
1 << Hie_CTR |
1 << Hie_DEG |
1 << Hie_CRS;
Gbl.Scope.Default = Hie_SYS;
2016-06-24 20:34:58 +02:00
Sco_GetScope ("ScopeSta");
Sco_PutSelectorScope ("ScopeSta",false);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"</td>"
"</tr>");
/***** Count type for the statistic *****/
fprintf (Gbl.F.Out,"<tr>"
2018-10-27 14:14:34 +02:00
"<td class=\"RIGHT_MIDDLE\">"
2016-12-20 02:18:50 +01:00
"<label for=\"CountType\" class=\"%s\">%s:</label>"
2014-12-25 12:54:21 +01:00
"</td>"
2018-10-27 14:14:34 +02:00
"<td colspan=\"2\" class=\"LEFT_MIDDLE\">",
2019-02-22 21:47:50 +01:00
The_ClassFormInBox[Gbl.Prefs.Theme],Txt_Show);
2015-09-25 01:48:00 +02:00
Sta_WriteSelectorCountType ();
/***** Type of statistic *****/
2016-12-20 02:18:50 +01:00
fprintf (Gbl.F.Out,"<label class=\"%s\">&nbsp;%s&nbsp;",
2019-02-22 21:47:50 +01:00
The_ClassFormInBox[Gbl.Prefs.Theme],Txt_distributed_by);
2015-09-25 01:48:00 +02:00
2018-10-07 14:01:25 +02:00
if (Gbl.Stat.ClicksGroupedBy < Sta_CLICKS_GBL_PER_DAY ||
2015-09-25 01:48:00 +02:00
Gbl.Stat.ClicksGroupedBy > Sta_CLICKS_GBL_PER_COURSE)
2018-10-07 14:01:25 +02:00
Gbl.Stat.ClicksGroupedBy = Sta_CLICKS_GBL_PER_DAY;
2015-09-25 01:48:00 +02:00
fprintf (Gbl.F.Out,"<select name=\"GroupedBy\">");
2018-10-07 14:01:25 +02:00
for (ClicksGroupedBy = Sta_CLICKS_GBL_PER_DAY;
2015-09-25 01:48:00 +02:00
ClicksGroupedBy <= Sta_CLICKS_GBL_PER_COURSE;
ClicksGroupedBy++)
2014-12-01 23:55:08 +01:00
{
2015-09-25 01:48:00 +02:00
fprintf (Gbl.F.Out,"<option value=\"%u\"",
(unsigned) ClicksGroupedBy);
if (ClicksGroupedBy == Gbl.Stat.ClicksGroupedBy)
fprintf (Gbl.F.Out," selected=\"selected\"");
fprintf (Gbl.F.Out,">%s",Txt_STAT_CLICKS_GROUPED_BY[ClicksGroupedBy]);
2014-12-01 23:55:08 +01:00
}
2015-09-25 01:48:00 +02:00
fprintf (Gbl.F.Out,"</select>"
2016-12-20 02:18:50 +01:00
"</label>"
2015-09-25 01:48:00 +02:00
"</td>"
2017-06-12 14:16:33 +02:00
"</tr>");
/***** End table *****/
Tbl_EndTable ();
2015-10-26 23:16:21 +01:00
2015-10-27 22:59:49 +01:00
/***** Hidden param used to get client time zone *****/
2015-10-28 21:47:42 +01:00
Dat_PutHiddenParBrowserTZDiff ();
2015-10-26 23:16:21 +01:00
2017-06-12 14:16:33 +02:00
/***** Send button and end box *****/
2017-06-11 19:02:40 +02:00
Box_EndBoxWithButton (Btn_CONFIRM_BUTTON,Txt_Show_hits);
2014-12-01 23:55:08 +01:00
2015-04-11 17:33:14 +02:00
/***** End form *****/
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2014-12-01 23:55:08 +01:00
}
2019-01-11 12:32:41 +01:00
/*****************************************************************************/
/*************** Put a link to show visits to current course *****************/
/*****************************************************************************/
static void Sta_PutLinkToCourseHits (void)
{
extern const char *Txt_Visits_to_course;
2019-04-03 20:57:04 +02:00
if (Gbl.Hierarchy.Level == Hie_CRS) // Course selected
2019-01-11 12:32:41 +01:00
switch (Gbl.Usrs.Me.Role.Logged)
{
case Rol_NET:
case Rol_TCH:
case Rol_SYS_ADM:
2019-01-12 03:00:59 +01:00
Lay_PutContextualLinkIconText (ActReqAccCrs,NULL,NULL,
"chart-line.svg",
Txt_Visits_to_course);
2019-01-11 12:32:41 +01:00
break;
default:
break;
}
}
/*****************************************************************************/
/********************* Put a link to show global visits **********************/
/*****************************************************************************/
static void Sta_PutLinkToGlobalHits (void)
{
extern const char *Txt_Global_visits;
2019-01-12 03:00:59 +01:00
Lay_PutContextualLinkIconText (ActReqAccGbl,NULL,NULL,
"chart-line.svg",
Txt_Global_visits);
2019-01-11 12:32:41 +01:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/****** Put selectors for type of access count and for degree or course ******/
/*****************************************************************************/
static void Sta_WriteSelectorCountType (void)
{
2015-09-25 01:48:00 +02:00
extern const char *Txt_STAT_TYPE_COUNT_SMALL[Sta_NUM_COUNT_TYPES];
2014-12-01 23:55:08 +01:00
Sta_CountType_t StatCountType;
/**** Count type *****/
2015-09-25 01:48:00 +02:00
fprintf (Gbl.F.Out,"<select id=\"CountType\" name=\"CountType\">");
2014-12-01 23:55:08 +01:00
for (StatCountType = (Sta_CountType_t) 0;
2015-09-25 01:48:00 +02:00
StatCountType < Sta_NUM_COUNT_TYPES;
2014-12-01 23:55:08 +01:00
StatCountType++)
{
fprintf (Gbl.F.Out,"<option value=\"%u\"",(unsigned) StatCountType);
if (StatCountType == Gbl.Stat.CountType)
fprintf (Gbl.F.Out," selected=\"selected\"");
fprintf (Gbl.F.Out,">%s",Txt_STAT_TYPE_COUNT_SMALL[StatCountType]);
}
2015-09-25 01:48:00 +02:00
fprintf (Gbl.F.Out,"</select>");
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/****** Put selectors for type of access count and for degree or course ******/
/*****************************************************************************/
static void Sta_WriteSelectorAction (void)
{
2019-02-22 21:47:50 +01:00
extern const char *The_ClassFormInBox[The_NUM_THEMES];
2014-12-01 23:55:08 +01:00
extern const char *Txt_Action;
2016-12-28 17:22:25 +01:00
extern const char *Txt_TABS_TXT[Tab_NUM_TABS];
2016-10-20 22:58:11 +02:00
Act_Action_t Action;
Tab_Tab_t Tab;
2017-03-07 01:56:41 +01:00
char ActTxt[Act_MAX_BYTES_ACTION_TXT + 1];
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"<tr>"
2018-10-27 14:14:34 +02:00
"<td class=\"RIGHT_MIDDLE\">"
2016-12-20 02:18:50 +01:00
"<label for=\"StatAct\" class=\"%s\">%s:</label>"
2014-12-25 12:54:21 +01:00
"</td>"
2018-10-27 14:14:34 +02:00
"<td colspan=\"2\" class=\"LEFT_MIDDLE\">"
2016-12-20 02:18:50 +01:00
"<select id=\"StatAct\" name=\"StatAct\""
2015-09-28 18:28:29 +02:00
" style=\"width:375px;\">",
2019-02-22 21:47:50 +01:00
The_ClassFormInBox[Gbl.Prefs.Theme],Txt_Action);
2016-10-20 22:58:11 +02:00
for (Action = (Act_Action_t) 0;
Action < Act_NUM_ACTIONS;
Action++)
2014-12-01 23:55:08 +01:00
{
2016-10-20 22:58:11 +02:00
fprintf (Gbl.F.Out,"<option value=\"%u\"",(unsigned) Action);
if (Action == Gbl.Stat.NumAction)
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out," selected=\"selected\"");
fprintf (Gbl.F.Out,">");
2016-10-20 22:58:11 +02:00
if (Action)
fprintf (Gbl.F.Out,"%u: ",(unsigned) Action);
2018-04-24 13:21:53 +02:00
Tab = Act_GetTab (Act_GetSuperAction (Action));
2016-12-28 17:22:25 +01:00
if (Txt_TABS_TXT[Tab])
fprintf (Gbl.F.Out,"%s &gt; ",Txt_TABS_TXT[Tab]);
2016-04-23 23:39:07 +02:00
fprintf (Gbl.F.Out,"%s",
2018-04-24 13:21:53 +02:00
Act_GetActionTextFromDB (Act_GetActCod (Action),ActTxt));
2014-12-01 23:55:08 +01:00
}
fprintf (Gbl.F.Out,"</select>"
"</td>"
"</tr>");
}
/*****************************************************************************/
/************ Set end date to current date ************/
/************ and set initial date to end date minus several days ************/
/*****************************************************************************/
void Sta_SetIniEndDates (void)
{
2015-10-27 19:00:21 +01:00
Gbl.DateRange.TimeUTC[0] = Gbl.StartExecutionTimeUTC - ((Cfg_DAYS_IN_RECENT_LOG - 1) * 24 * 60 * 60);
Gbl.DateRange.TimeUTC[1] = Gbl.StartExecutionTimeUTC;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************** Compute and show access statistics *********************/
/*****************************************************************************/
2015-09-30 23:26:48 +02:00
void Sta_SeeGblAccesses (void)
2014-12-01 23:55:08 +01:00
{
2015-10-11 17:40:07 +02:00
Sta_ShowHits (Sta_SHOW_GLOBAL_ACCESSES);
2014-12-01 23:55:08 +01:00
}
2015-09-30 23:26:48 +02:00
void Sta_SeeCrsAccesses (void)
2014-12-01 23:55:08 +01:00
{
2015-10-11 17:40:07 +02:00
Sta_ShowHits (Sta_SHOW_COURSE_ACCESSES);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************** Compute and show access statistics ********************/
/*****************************************************************************/
2017-03-08 01:21:21 +01:00
#define Sta_MAX_BYTES_QUERY_ACCESS (1024 + (10 + ID_MAX_BYTES_USR_ID) * 5000 - 1)
2017-01-15 22:58:26 +01:00
2017-03-08 01:21:21 +01:00
#define Sta_MAX_BYTES_COUNT_TYPE (256 - 1)
2014-12-01 23:55:08 +01:00
2015-10-11 17:40:07 +02:00
static void Sta_ShowHits (Sta_GlobalOrCourseAccesses_t GlobalOrCourse)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_You_must_select_one_ore_more_users;
extern const char *Txt_There_is_no_knowing_how_many_users_not_logged_have_accessed;
extern const char *Txt_The_date_range_must_be_less_than_or_equal_to_X_days;
extern const char *Txt_There_are_no_accesses_with_the_selected_search_criteria;
2015-09-30 23:10:15 +02:00
extern const char *Txt_List_of_detailed_clicks;
extern const char *Txt_STAT_TYPE_COUNT_CAPS[Sta_NUM_COUNT_TYPES];
2015-10-28 21:47:42 +01:00
extern const char *Txt_Time_zone_used_in_the_calculation_of_these_statistics;
2018-10-30 03:29:40 +01:00
char *Query = NULL;
2014-12-01 23:55:08 +01:00
char QueryAux[512];
long LengthQuery;
MYSQL_RES *mysql_res;
unsigned long NumRows;
const char *LogTable;
2015-09-25 01:48:00 +02:00
Sta_ClicksDetailedOrGrouped_t DetailedOrGrouped = Sta_CLICKS_GROUPED;
2014-12-01 23:55:08 +01:00
struct UsrData UsrDat;
2017-01-28 15:58:46 +01:00
char BrowserTimeZone[Dat_MAX_BYTES_TIME_ZONE + 1];
2014-12-01 23:55:08 +01:00
unsigned NumUsr = 0;
const char *Ptr;
2015-03-24 17:47:26 +01:00
char StrRole[256];
2017-03-08 01:21:21 +01:00
char StrQueryCountType[Sta_MAX_BYTES_COUNT_TYPE + 1];
2014-12-01 23:55:08 +01:00
unsigned NumDays;
2015-11-14 16:54:43 +01:00
bool ICanQueryWholeRange;
2014-12-01 23:55:08 +01:00
/***** Get initial and ending dates *****/
Dat_GetIniEndDatesFromForm ();
2015-10-27 22:59:49 +01:00
/***** Get client time zone *****/
2015-10-28 21:47:42 +01:00
Dat_GetBrowserTimeZone (BrowserTimeZone);
2015-10-27 22:59:49 +01:00
2014-12-01 23:55:08 +01:00
/***** Set table where to find depending on initial date *****/
2017-02-25 13:49:03 +01:00
/* If initial day is older than current day minus Cfg_DAYS_IN_RECENT_LOG,
then use recent log table, else use historic log table */
2017-01-29 21:41:08 +01:00
LogTable = (Dat_GetNumDaysBetweenDates (&Gbl.DateRange.DateIni.Date,&Gbl.Now.Date)
<= Cfg_DAYS_IN_RECENT_LOG) ? "log_recent" :
"log_full";
2014-12-01 23:55:08 +01:00
/***** Get the type of stat of clicks ******/
2017-01-29 21:41:08 +01:00
DetailedOrGrouped = (Sta_ClicksDetailedOrGrouped_t)
Par_GetParToUnsignedLong ("GroupedOrDetailed",
0,
Sta_NUM_CLICKS_DETAILED_OR_GROUPED - 1,
(unsigned long) Sta_CLICKS_DETAILED_OR_GROUPED_DEFAULT);
2015-09-25 01:48:00 +02:00
if (DetailedOrGrouped == Sta_CLICKS_DETAILED)
Gbl.Stat.ClicksGroupedBy = Sta_CLICKS_CRS_DETAILED_LIST;
else // DetailedOrGrouped == Sta_CLICKS_GROUPED
2017-01-29 21:41:08 +01:00
Gbl.Stat.ClicksGroupedBy = (Sta_ClicksGroupedBy_t)
Par_GetParToUnsignedLong ("GroupedBy",
0,
Sta_NUM_CLICKS_GROUPED_BY - 1,
(unsigned long) Sta_CLICKS_GROUPED_BY_DEFAULT);
2014-12-01 23:55:08 +01:00
/***** Get the type of count of clicks *****/
2015-09-25 01:48:00 +02:00
if (Gbl.Stat.ClicksGroupedBy != Sta_CLICKS_CRS_DETAILED_LIST)
2017-01-29 21:41:08 +01:00
Gbl.Stat.CountType = (Sta_CountType_t)
Par_GetParToUnsignedLong ("CountType",
0,
Sta_NUM_COUNT_TYPES - 1,
(unsigned long) Sta_COUNT_TYPE_DEFAULT);
2014-12-01 23:55:08 +01:00
/***** Get action *****/
2017-01-29 21:41:08 +01:00
Gbl.Stat.NumAction = (Act_Action_t)
Par_GetParToUnsignedLong ("StatAct",
0,
Act_NUM_ACTIONS - 1,
(unsigned long) Sta_NUM_ACTION_DEFAULT);
2014-12-01 23:55:08 +01:00
2015-09-30 23:26:48 +02:00
switch (GlobalOrCourse)
2014-12-01 23:55:08 +01:00
{
2015-09-30 23:26:48 +02:00
case Sta_SHOW_GLOBAL_ACCESSES:
/***** Get the type of user of clicks *****/
2017-01-29 21:41:08 +01:00
Gbl.Stat.Role = (Sta_Role_t)
Par_GetParToUnsignedLong ("Role",
0,
Sta_NUM_ROLES_STAT - 1,
(unsigned long) Sta_ROLE_DEFAULT);
2015-09-30 23:26:48 +02:00
/***** Get users range for access statistics *****/
2019-04-03 20:57:04 +02:00
Gbl.Scope.Allowed = 1 << Hie_SYS |
1 << Hie_CTY |
1 << Hie_INS |
1 << Hie_CTR |
1 << Hie_DEG |
1 << Hie_CRS;
Gbl.Scope.Default = Hie_SYS;
2016-06-24 20:34:58 +02:00
Sco_GetScope ("ScopeSta");
2015-09-30 23:26:48 +02:00
/***** Show form again *****/
2015-10-11 17:40:07 +02:00
Sta_AskShowGblHits ();
2015-09-30 23:26:48 +02:00
2017-05-29 10:32:45 +02:00
/***** Start results section *****/
Lay_StartSection (Sta_STAT_RESULTS_SECTION_ID);
/***** Check selection *****/
2017-05-23 18:15:59 +02:00
if ((Gbl.Stat.Role == Sta_ROLE_ALL_USRS ||
Gbl.Stat.Role == Sta_ROLE_UNKNOWN_USRS) &&
2015-09-30 23:26:48 +02:00
(Gbl.Stat.CountType == Sta_DISTINCT_USRS ||
2017-05-29 10:32:45 +02:00
Gbl.Stat.CountType == Sta_CLICKS_PER_USR)) // These types of query will never give a valid result
2015-09-30 23:26:48 +02:00
{
2017-05-29 10:32:45 +02:00
/* Write warning message and abort */
2019-02-16 18:25:41 +01:00
Ale_ShowAlert (Ale_WARNING,Txt_There_is_no_knowing_how_many_users_not_logged_have_accessed);
2015-09-30 23:26:48 +02:00
return;
}
2014-12-01 23:55:08 +01:00
break;
2015-09-30 23:26:48 +02:00
case Sta_SHOW_COURSE_ACCESSES:
if (Gbl.Stat.ClicksGroupedBy == Sta_CLICKS_CRS_DETAILED_LIST)
{
/****** Get the number of the first row to show ******/
2017-01-29 21:41:08 +01:00
Gbl.Stat.FirstRow = Par_GetParToUnsignedLong ("FirstRow",
1,
ULONG_MAX,
0);
2015-09-30 23:26:48 +02:00
/****** Get the number of the last row to show ******/
2017-01-29 21:41:08 +01:00
Gbl.Stat.LastRow = Par_GetParToUnsignedLong ("LastRow",
1,
ULONG_MAX,
0);
2015-09-30 23:26:48 +02:00
/****** Get the number of rows per page ******/
2017-01-29 21:41:08 +01:00
Gbl.Stat.RowsPerPage = Par_GetParToUnsignedLong ("RowsPage",
Sta_MIN_ROWS_PER_PAGE,
Sta_MAX_ROWS_PER_PAGE,
Sta_DEF_ROWS_PER_PAGE);
2015-09-30 23:26:48 +02:00
}
2015-09-30 23:10:15 +02:00
2015-09-30 23:26:48 +02:00
/****** Get lists of selected users ******/
2016-07-04 14:03:04 +02:00
Usr_GetListsSelectedUsrsCods ();
2014-12-01 23:55:08 +01:00
2017-05-29 10:32:45 +02:00
/***** Show the form again *****/
Sta_AskShowCrsHits ();
/***** Start results section *****/
Lay_StartSection (Sta_STAT_RESULTS_SECTION_ID);
/***** Check selection *****/
if (!Usr_CountNumUsrsInListOfSelectedUsrs ()) // Error: there are no users selected
{
/* Write warning message, clean and abort */
2019-02-16 18:25:41 +01:00
Ale_ShowAlert (Ale_WARNING,Txt_You_must_select_one_ore_more_users);
2017-05-29 10:32:45 +02:00
Usr_FreeListsSelectedUsrsCods ();
2015-09-30 23:26:48 +02:00
return;
}
break;
2014-12-01 23:55:08 +01:00
}
/***** Check if range of dates is forbidden for me *****/
2015-10-27 19:00:21 +01:00
NumDays = Dat_GetNumDaysBetweenDates (&Gbl.DateRange.DateIni.Date,&Gbl.DateRange.DateEnd.Date);
2017-06-04 18:18:54 +02:00
ICanQueryWholeRange = (Gbl.Usrs.Me.Role.Logged >= Rol_TCH && GlobalOrCourse == Sta_SHOW_COURSE_ACCESSES) ||
2019-04-03 20:57:04 +02:00
(Gbl.Usrs.Me.Role.Logged == Rol_TCH && Gbl.Scope.Current == Hie_CRS) ||
(Gbl.Usrs.Me.Role.Logged == Rol_DEG_ADM && (Gbl.Scope.Current == Hie_DEG ||
Gbl.Scope.Current == Hie_CRS)) ||
(Gbl.Usrs.Me.Role.Logged == Rol_CTR_ADM && (Gbl.Scope.Current == Hie_CTR ||
Gbl.Scope.Current == Hie_DEG ||
Gbl.Scope.Current == Hie_CRS)) ||
(Gbl.Usrs.Me.Role.Logged == Rol_INS_ADM && (Gbl.Scope.Current == Hie_INS ||
Gbl.Scope.Current == Hie_CTR ||
Gbl.Scope.Current == Hie_DEG ||
Gbl.Scope.Current == Hie_CRS)) ||
2017-06-04 18:18:54 +02:00
Gbl.Usrs.Me.Role.Logged == Rol_SYS_ADM;
2015-11-14 16:54:43 +01:00
if (!ICanQueryWholeRange && NumDays > Cfg_DAYS_IN_RECENT_LOG)
{
2019-02-16 18:25:41 +01:00
/* ...write warning message and show the form again */
Ale_ShowAlert (Ale_WARNING,Txt_The_date_range_must_be_less_than_or_equal_to_X_days,
Cfg_DAYS_IN_RECENT_LOG);
2015-11-14 16:54:43 +01:00
return;
}
2014-12-01 23:55:08 +01:00
/***** Query depending on the type of count *****/
switch (Gbl.Stat.CountType)
{
case Sta_TOTAL_CLICKS:
2017-01-17 03:10:43 +01:00
Str_Copy (StrQueryCountType,"COUNT(*)",
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_COUNT_TYPE);
2014-12-01 23:55:08 +01:00
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 *****/
2018-10-29 22:22:02 +01:00
/* Allocate memory for the query */
2018-10-30 02:37:09 +01:00
if ((Query = (char *) malloc (Sta_MAX_BYTES_QUERY_ACCESS + 1)) == NULL)
2018-10-29 22:22:02 +01:00
Lay_NotEnoughMemoryExit ();
2014-12-01 23:55:08 +01:00
/* Start the query */
2015-09-25 01:48:00 +02:00
switch (Gbl.Stat.ClicksGroupedBy)
2014-12-01 23:55:08 +01:00
{
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_CRS_DETAILED_LIST:
2018-10-30 02:37:09 +01:00
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
2018-10-29 22:22:02 +01:00
"SELECT SQL_NO_CACHE LogCod,UsrCod,Role,"
"UNIX_TIMESTAMP(ClickTime) AS F,ActCod FROM %s",
LogTable);
2014-12-01 23:55:08 +01:00
break;
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_CRS_PER_USR:
2018-10-30 02:37:09 +01:00
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
2018-10-29 22:22:02 +01:00
"SELECT SQL_NO_CACHE UsrCod,%s AS Num FROM %s",
StrQueryCountType,LogTable);
2014-12-01 23:55:08 +01:00
break;
2018-10-07 14:01:25 +02:00
case Sta_CLICKS_CRS_PER_DAY:
case Sta_CLICKS_GBL_PER_DAY:
2018-10-30 02:37:09 +01:00
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
2018-10-29 22:22:02 +01:00
"SELECT SQL_NO_CACHE "
"DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%Y%%m%%d') AS Day,"
"%s FROM %s",
BrowserTimeZone,
StrQueryCountType,LogTable);
2014-12-01 23:55:08 +01:00
break;
2018-10-07 14:01:25 +02:00
case Sta_CLICKS_CRS_PER_DAY_AND_HOUR:
case Sta_CLICKS_GBL_PER_DAY_AND_HOUR:
2018-10-30 02:37:09 +01:00
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
2018-10-29 22:22:02 +01:00
"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);
2014-12-01 23:55:08 +01:00
break;
2018-10-07 14:01:25 +02:00
case Sta_CLICKS_CRS_PER_WEEK:
case Sta_CLICKS_GBL_PER_WEEK:
2015-11-21 21:42:27 +01:00
/* With %x%v the weeks are counted from monday to sunday.
With %X%V the weeks are counted from sunday to saturday. */
2018-10-30 02:37:09 +01:00
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
2018-10-29 22:22:02 +01:00
(Gbl.Prefs.FirstDayOfWeek == 0) ?
"SELECT SQL_NO_CACHE " // Weeks start on monday
"DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%x%%v') AS Week,"
"%s FROM %s" :
"SELECT SQL_NO_CACHE " // Weeks start on sunday
"DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%X%%V') AS Week,"
"%s FROM %s",
BrowserTimeZone,
StrQueryCountType,LogTable);
2014-12-01 23:55:08 +01:00
break;
2018-10-07 14:01:25 +02:00
case Sta_CLICKS_CRS_PER_MONTH:
case Sta_CLICKS_GBL_PER_MONTH:
2018-10-30 02:37:09 +01:00
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
2018-10-29 22:22:02 +01:00
"SELECT SQL_NO_CACHE "
"DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%Y%%m') AS Month,"
"%s FROM %s",
BrowserTimeZone,
StrQueryCountType,LogTable);
2014-12-01 23:55:08 +01:00
break;
2018-10-07 14:01:25 +02:00
case Sta_CLICKS_CRS_PER_YEAR:
case Sta_CLICKS_GBL_PER_YEAR:
2018-10-30 02:37:09 +01:00
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
2018-10-29 22:22:02 +01:00
"SELECT SQL_NO_CACHE "
"DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%Y') AS Year,"
"%s FROM %s",
BrowserTimeZone,
StrQueryCountType,LogTable);
2018-10-07 14:01:25 +02:00
break;
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_CRS_PER_HOUR:
case Sta_CLICKS_GBL_PER_HOUR:
2018-10-30 02:37:09 +01:00
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
2018-10-29 22:22:02 +01:00
"SELECT SQL_NO_CACHE "
"DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%H') AS Hour,"
"%s FROM %s",
BrowserTimeZone,
StrQueryCountType,LogTable);
2014-12-01 23:55:08 +01:00
break;
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_CRS_PER_MINUTE:
case Sta_CLICKS_GBL_PER_MINUTE:
2018-10-30 02:37:09 +01:00
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
2018-10-29 22:22:02 +01:00
"SELECT SQL_NO_CACHE "
"DATE_FORMAT(CONVERT_TZ(ClickTime,@@session.time_zone,'%s'),'%%H%%i') AS Minute,"
"%s FROM %s",
BrowserTimeZone,
StrQueryCountType,LogTable);
2014-12-01 23:55:08 +01:00
break;
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_CRS_PER_ACTION:
case Sta_CLICKS_GBL_PER_ACTION:
2018-10-30 02:37:09 +01:00
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
2018-10-29 22:22:02 +01:00
"SELECT SQL_NO_CACHE ActCod,%s AS Num FROM %s",
StrQueryCountType,LogTable);
2014-12-01 23:55:08 +01:00
break;
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_GBL_PER_PLUGIN:
2018-10-30 02:37:09 +01:00
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
2018-10-29 22:22:02 +01:00
"SELECT SQL_NO_CACHE log_ws.PlgCod,%s AS Num FROM %s,log_ws",
StrQueryCountType,LogTable);
2014-12-01 23:55:08 +01:00
break;
2018-10-07 14:01:25 +02:00
case Sta_CLICKS_GBL_PER_API_FUNCTION:
2018-10-30 02:37:09 +01:00
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
2018-10-29 22:22:02 +01:00
"SELECT SQL_NO_CACHE log_ws.FunCod,%s AS Num FROM %s,log_ws",
StrQueryCountType,LogTable);
2014-12-01 23:55:08 +01:00
break;
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_GBL_PER_BANNER:
2018-10-30 02:37:09 +01:00
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
2018-10-29 22:22:02 +01:00
"SELECT SQL_NO_CACHE log_banners.BanCod,%s AS Num FROM %s,log_banners",
StrQueryCountType,LogTable);
2014-12-01 23:55:08 +01:00
break;
2015-10-11 14:12:20 +02:00
case Sta_CLICKS_GBL_PER_COUNTRY:
2018-10-30 02:37:09 +01:00
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
2018-10-29 22:22:02 +01:00
"SELECT SQL_NO_CACHE CtyCod,%s AS Num FROM %s",
StrQueryCountType,LogTable);
2015-10-11 14:12:20 +02:00
break;
case Sta_CLICKS_GBL_PER_INSTITUTION:
2018-10-30 02:37:09 +01:00
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
2018-10-29 22:22:02 +01:00
"SELECT SQL_NO_CACHE InsCod,%s AS Num FROM %s",
StrQueryCountType,LogTable);
2015-10-11 14:12:20 +02:00
break;
case Sta_CLICKS_GBL_PER_CENTRE:
2018-10-30 02:37:09 +01:00
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
2018-10-29 22:22:02 +01:00
"SELECT SQL_NO_CACHE CtrCod,%s AS Num FROM %s",
StrQueryCountType,LogTable);
2015-10-11 14:12:20 +02:00
break;
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_GBL_PER_DEGREE:
2018-10-30 02:37:09 +01:00
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
2018-10-29 22:22:02 +01:00
"SELECT SQL_NO_CACHE DegCod,%s AS Num FROM %s",
StrQueryCountType,LogTable);
2014-12-01 23:55:08 +01:00
break;
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_GBL_PER_COURSE:
2018-10-30 02:37:09 +01:00
snprintf (Query,Sta_MAX_BYTES_QUERY_ACCESS + 1,
2018-10-29 22:22:02 +01:00
"SELECT SQL_NO_CACHE CrsCod,%s AS Num FROM %s",
StrQueryCountType,LogTable);
2014-12-01 23:55:08 +01:00
break;
}
2015-11-11 03:00:22 +01:00
sprintf (QueryAux," WHERE %s.ClickTime"
2017-03-24 01:09:27 +01:00
" BETWEEN FROM_UNIXTIME(%ld) AND FROM_UNIXTIME(%ld)",
2015-11-11 03:00:22 +01:00
LogTable,
(long) Gbl.DateRange.TimeUTC[0],
(long) Gbl.DateRange.TimeUTC[1]);
2018-10-30 02:37:09 +01:00
Str_Concat (Query,QueryAux,
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2015-03-24 17:47:26 +01:00
2015-09-30 23:26:48 +02:00
switch (GlobalOrCourse)
2014-12-01 23:55:08 +01:00
{
2015-09-30 23:26:48 +02:00
case Sta_SHOW_GLOBAL_ACCESSES:
2014-12-01 23:55:08 +01:00
/* Scope */
2015-10-11 17:40:07 +02:00
switch (Gbl.Scope.Current)
{
2019-04-03 20:57:04 +02:00
case Hie_UNK:
case Hie_SYS:
2015-10-11 17:40:07 +02:00
break;
2019-04-03 20:57:04 +02:00
case Hie_CTY:
if (Gbl.Hierarchy.Cty.CtyCod > 0)
2015-10-11 17:40:07 +02:00
{
2017-03-24 01:09:27 +01:00
sprintf (QueryAux," AND %s.CtyCod=%ld",
2019-04-03 20:57:04 +02:00
LogTable,Gbl.Hierarchy.Cty.CtyCod);
2018-10-30 02:37:09 +01:00
Str_Concat (Query,QueryAux,
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2015-10-11 17:40:07 +02:00
}
break;
2019-04-03 20:57:04 +02:00
case Hie_INS:
if (Gbl.Hierarchy.Ins.InsCod > 0)
2015-10-11 17:40:07 +02:00
{
2017-03-24 01:09:27 +01:00
sprintf (QueryAux," AND %s.InsCod=%ld",
2019-04-03 20:57:04 +02:00
LogTable,Gbl.Hierarchy.Ins.InsCod);
2018-10-30 02:37:09 +01:00
Str_Concat (Query,QueryAux,
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2015-10-11 17:40:07 +02:00
}
break;
2019-04-03 20:57:04 +02:00
case Hie_CTR:
if (Gbl.Hierarchy.Ctr.CtrCod > 0)
2015-10-11 17:40:07 +02:00
{
2017-03-24 01:09:27 +01:00
sprintf (QueryAux," AND %s.CtrCod=%ld",
2019-04-03 20:57:04 +02:00
LogTable,Gbl.Hierarchy.Ctr.CtrCod);
2018-10-30 02:37:09 +01:00
Str_Concat (Query,QueryAux,
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2015-10-11 17:40:07 +02:00
}
break;
2019-04-03 20:57:04 +02:00
case Hie_DEG:
if (Gbl.Hierarchy.Deg.DegCod > 0)
2015-10-11 17:40:07 +02:00
{
2017-03-24 01:09:27 +01:00
sprintf (QueryAux," AND %s.DegCod=%ld",
2019-04-03 20:57:04 +02:00
LogTable,Gbl.Hierarchy.Deg.DegCod);
2018-10-30 02:37:09 +01:00
Str_Concat (Query,QueryAux,
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2015-10-11 17:40:07 +02:00
}
break;
2019-04-03 20:57:04 +02:00
case Hie_CRS:
if (Gbl.Hierarchy.Level == Hie_CRS)
2015-10-11 17:40:07 +02:00
{
2017-03-24 01:09:27 +01:00
sprintf (QueryAux," AND %s.CrsCod=%ld",
2019-04-04 10:45:15 +02:00
LogTable,Gbl.Hierarchy.Crs.CrsCod);
2018-10-30 02:37:09 +01:00
Str_Concat (Query,QueryAux,
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2015-10-11 17:40:07 +02:00
}
break;
}
2015-03-24 17:47:26 +01:00
2014-12-01 23:55:08 +01:00
/* Type of users */
switch (Gbl.Stat.Role)
{
2017-05-23 18:15:59 +02:00
case Sta_ROLE_IDENTIFIED_USRS:
2017-03-24 01:09:27 +01:00
sprintf (StrRole," AND %s.Role<>%u",
2017-05-18 19:13:41 +02:00
LogTable,(unsigned) Rol_UNK);
2014-12-01 23:55:08 +01:00
break;
2017-05-23 18:15:59 +02:00
case Sta_ROLE_ALL_USRS:
2014-12-01 23:55:08 +01:00
switch (Gbl.Stat.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:
2017-03-24 01:09:27 +01:00
sprintf (StrRole," AND %s.Role<>%u",
2017-05-18 19:13:41 +02:00
LogTable,(unsigned) Rol_UNK);
2014-12-01 23:55:08 +01:00
break;
}
break;
2017-05-23 18:15:59 +02:00
case Sta_ROLE_INS_ADMINS:
2017-03-24 01:09:27 +01:00
sprintf (StrRole," AND %s.Role=%u",
2015-04-07 21:44:24 +02:00
LogTable,(unsigned) Rol_INS_ADM);
2014-12-01 23:55:08 +01:00
break;
2017-05-23 18:15:59 +02:00
case Sta_ROLE_CTR_ADMINS:
2017-03-24 01:09:27 +01:00
sprintf (StrRole," AND %s.Role=%u",
2015-04-07 21:44:24 +02:00
LogTable,(unsigned) Rol_CTR_ADM);
2014-12-01 23:55:08 +01:00
break;
2017-05-23 18:15:59 +02:00
case Sta_ROLE_DEG_ADMINS:
2017-03-24 01:09:27 +01:00
sprintf (StrRole," AND %s.Role=%u",
2015-04-07 21:44:24 +02:00
LogTable,(unsigned) Rol_DEG_ADM);
2014-12-01 23:55:08 +01:00
break;
2017-05-23 18:15:59 +02:00
case Sta_ROLE_TEACHERS:
2017-03-24 01:09:27 +01:00
sprintf (StrRole," AND %s.Role=%u",
2017-05-18 19:13:41 +02:00
LogTable,(unsigned) Rol_TCH);
2014-12-01 23:55:08 +01:00
break;
2017-05-23 18:15:59 +02:00
case Sta_ROLE_NON_EDITING_TEACHERS:
2017-05-22 20:37:46 +02:00
sprintf (StrRole," AND %s.Role=%u",
LogTable,(unsigned) Rol_NET);
break;
2017-05-23 18:15:59 +02:00
case Sta_ROLE_STUDENTS:
2017-03-24 01:09:27 +01:00
sprintf (StrRole," AND %s.Role=%u",
2017-05-18 19:13:41 +02:00
LogTable,(unsigned) Rol_STD);
2014-12-01 23:55:08 +01:00
break;
2017-05-23 18:15:59 +02:00
case Sta_ROLE_USERS:
2017-03-24 01:09:27 +01:00
sprintf (StrRole," AND %s.Role=%u",
2017-05-18 19:13:41 +02:00
LogTable,(unsigned) Rol_USR);
2014-12-01 23:55:08 +01:00
break;
2017-05-23 18:15:59 +02:00
case Sta_ROLE_GUESTS:
2017-03-24 01:09:27 +01:00
sprintf (StrRole," AND %s.Role=%u",
2017-05-18 19:13:41 +02:00
LogTable,(unsigned) Rol_GST);
2014-12-01 23:55:08 +01:00
break;
2017-05-23 18:15:59 +02:00
case Sta_ROLE_UNKNOWN_USRS:
2017-03-24 01:09:27 +01:00
sprintf (StrRole," AND %s.Role=%u",
2017-05-18 19:13:41 +02:00
LogTable,(unsigned) Rol_UNK);
2014-12-01 23:55:08 +01:00
break;
2017-05-23 18:15:59 +02:00
case Sta_ROLE_ME:
2017-03-24 01:09:27 +01:00
sprintf (StrRole," AND %s.UsrCod=%ld",
2014-12-01 23:55:08 +01:00
LogTable,Gbl.Usrs.Me.UsrDat.UsrCod);
break;
}
2018-10-30 02:37:09 +01:00
Str_Concat (Query,StrRole,
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2014-12-01 23:55:08 +01:00
2015-09-25 01:48:00 +02:00
switch (Gbl.Stat.ClicksGroupedBy)
2014-12-01 23:55:08 +01:00
{
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_GBL_PER_PLUGIN:
2018-10-07 14:01:25 +02:00
case Sta_CLICKS_GBL_PER_API_FUNCTION:
2014-12-01 23:55:08 +01:00
sprintf (QueryAux," AND %s.LogCod=log_ws.LogCod",
LogTable);
2018-10-30 02:37:09 +01:00
Str_Concat (Query,QueryAux,
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2014-12-01 23:55:08 +01:00
break;
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_GBL_PER_BANNER:
2014-12-01 23:55:08 +01:00
sprintf (QueryAux," AND %s.LogCod=log_banners.LogCod",
LogTable);
2018-10-30 02:37:09 +01:00
Str_Concat (Query,QueryAux,
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2014-12-01 23:55:08 +01:00
break;
default:
break;
}
break;
2015-09-30 23:26:48 +02:00
case Sta_SHOW_COURSE_ACCESSES:
2017-03-24 01:09:27 +01:00
sprintf (QueryAux," AND %s.CrsCod=%ld",
2019-04-04 10:45:15 +02:00
LogTable,Gbl.Hierarchy.Crs.CrsCod);
2018-10-30 02:37:09 +01:00
Str_Concat (Query,QueryAux,
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2017-05-29 10:32:45 +02:00
/***** Initialize data structure of the user *****/
Usr_UsrDataConstructor (&UsrDat);
2018-10-30 02:37:09 +01:00
LengthQuery = strlen (Query);
2014-12-01 23:55:08 +01:00
NumUsr = 0;
2019-03-11 13:33:34 +01:00
Ptr = Gbl.Usrs.Selected.List[Rol_UNK];
2014-12-01 23:55:08 +01:00
while (*Ptr)
{
2017-03-13 14:22:36 +01:00
Par_GetNextStrUntilSeparParamMult (&Ptr,UsrDat.EncryptedUsrCod,
Cry_BYTES_ENCRYPTED_STR_SHA256_BASE64);
2014-12-01 23:55:08 +01:00
Usr_GetUsrCodFromEncryptedUsrCod (&UsrDat);
if (UsrDat.UsrCod > 0)
{
LengthQuery = LengthQuery + 25 + 10 + 1;
2017-03-08 01:21:21 +01:00
if (LengthQuery > Sta_MAX_BYTES_QUERY_ACCESS - 128)
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ("Query is too large.");
sprintf (QueryAux,
2017-03-24 01:09:27 +01:00
NumUsr ? " OR %s.UsrCod=%ld" :
" AND (%s.UsrCod=%ld",
2014-12-01 23:55:08 +01:00
LogTable,UsrDat.UsrCod);
2018-10-30 02:37:09 +01:00
Str_Concat (Query,QueryAux,
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2014-12-01 23:55:08 +01:00
NumUsr++;
}
}
2018-10-30 02:37:09 +01:00
Str_Concat (Query,")",
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2017-05-29 10:32:45 +02:00
/***** Free memory used by the data of the user *****/
Usr_UsrDataDestructor (&UsrDat);
2014-12-01 23:55:08 +01:00
break;
}
/* Select action */
if (Gbl.Stat.NumAction != ActAll)
{
2017-03-24 01:09:27 +01:00
sprintf (QueryAux," AND %s.ActCod=%ld",
2018-04-24 13:21:53 +02:00
LogTable,Act_GetActCod (Gbl.Stat.NumAction));
2018-10-30 02:37:09 +01:00
Str_Concat (Query,QueryAux,
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2014-12-01 23:55:08 +01:00
}
/* End the query */
2015-09-25 01:48:00 +02:00
switch (Gbl.Stat.ClicksGroupedBy)
2014-12-01 23:55:08 +01:00
{
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_CRS_DETAILED_LIST:
2018-10-30 02:37:09 +01:00
Str_Concat (Query," ORDER BY F",
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2014-12-01 23:55:08 +01:00
break;
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_CRS_PER_USR:
2014-12-01 23:55:08 +01:00
sprintf (QueryAux," GROUP BY %s.UsrCod ORDER BY Num DESC",LogTable);
2018-10-30 02:37:09 +01:00
Str_Concat (Query,QueryAux,
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2014-12-01 23:55:08 +01:00
break;
2018-10-07 14:01:25 +02:00
case Sta_CLICKS_CRS_PER_DAY:
case Sta_CLICKS_GBL_PER_DAY:
2018-10-30 02:37:09 +01:00
Str_Concat (Query," GROUP BY Day DESC",
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2014-12-01 23:55:08 +01:00
break;
2018-10-07 14:01:25 +02:00
case Sta_CLICKS_CRS_PER_DAY_AND_HOUR:
case Sta_CLICKS_GBL_PER_DAY_AND_HOUR:
2018-10-30 02:37:09 +01:00
Str_Concat (Query," GROUP BY Day DESC,Hour",
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2014-12-01 23:55:08 +01:00
break;
2018-10-07 14:01:25 +02:00
case Sta_CLICKS_CRS_PER_WEEK:
case Sta_CLICKS_GBL_PER_WEEK:
2018-10-30 02:37:09 +01:00
Str_Concat (Query," GROUP BY Week DESC",
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2014-12-01 23:55:08 +01:00
break;
2018-10-07 14:01:25 +02:00
case Sta_CLICKS_CRS_PER_MONTH:
case Sta_CLICKS_GBL_PER_MONTH:
2018-10-30 02:37:09 +01:00
Str_Concat (Query," GROUP BY Month DESC",
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2014-12-01 23:55:08 +01:00
break;
2018-10-07 14:01:25 +02:00
case Sta_CLICKS_CRS_PER_YEAR:
case Sta_CLICKS_GBL_PER_YEAR:
2018-10-30 02:37:09 +01:00
Str_Concat (Query," GROUP BY Year DESC",
2018-10-07 14:01:25 +02:00
Sta_MAX_BYTES_QUERY_ACCESS);
break;
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_CRS_PER_HOUR:
case Sta_CLICKS_GBL_PER_HOUR:
2018-10-30 02:37:09 +01:00
Str_Concat (Query," GROUP BY Hour",
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2014-12-01 23:55:08 +01:00
break;
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_CRS_PER_MINUTE:
case Sta_CLICKS_GBL_PER_MINUTE:
2018-10-30 02:37:09 +01:00
Str_Concat (Query," GROUP BY Minute",
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2014-12-01 23:55:08 +01:00
break;
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_CRS_PER_ACTION:
case Sta_CLICKS_GBL_PER_ACTION:
2014-12-01 23:55:08 +01:00
sprintf (QueryAux," GROUP BY %s.ActCod ORDER BY Num DESC",LogTable);
2018-10-30 02:37:09 +01:00
Str_Concat (Query,QueryAux,
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2014-12-01 23:55:08 +01:00
break;
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_GBL_PER_PLUGIN:
2018-10-30 02:37:09 +01:00
Str_Concat (Query," GROUP BY log_ws.PlgCod ORDER BY Num DESC",
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2014-12-01 23:55:08 +01:00
break;
2018-10-07 14:01:25 +02:00
case Sta_CLICKS_GBL_PER_API_FUNCTION:
2018-10-30 02:37:09 +01:00
Str_Concat (Query," GROUP BY log_ws.FunCod ORDER BY Num DESC",
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2014-12-01 23:55:08 +01:00
break;
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_GBL_PER_BANNER:
2018-10-30 02:37:09 +01:00
Str_Concat (Query," GROUP BY log_banners.BanCod ORDER BY Num DESC",
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2014-12-01 23:55:08 +01:00
break;
2015-10-11 14:12:20 +02:00
case Sta_CLICKS_GBL_PER_COUNTRY:
sprintf (QueryAux," GROUP BY %s.CtyCod ORDER BY Num DESC",LogTable);
2018-10-30 02:37:09 +01:00
Str_Concat (Query,QueryAux,
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2015-10-11 14:12:20 +02:00
break;
case Sta_CLICKS_GBL_PER_INSTITUTION:
sprintf (QueryAux," GROUP BY %s.InsCod ORDER BY Num DESC",LogTable);
2018-10-30 02:37:09 +01:00
Str_Concat (Query,QueryAux,
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2015-10-11 14:12:20 +02:00
break;
case Sta_CLICKS_GBL_PER_CENTRE:
sprintf (QueryAux," GROUP BY %s.CtrCod ORDER BY Num DESC",LogTable);
2018-10-30 02:37:09 +01:00
Str_Concat (Query,QueryAux,
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2015-10-11 14:12:20 +02:00
break;
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_GBL_PER_DEGREE:
2014-12-01 23:55:08 +01:00
sprintf (QueryAux," GROUP BY %s.DegCod ORDER BY Num DESC",LogTable);
2018-10-30 02:37:09 +01:00
Str_Concat (Query,QueryAux,
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2014-12-01 23:55:08 +01:00
break;
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_GBL_PER_COURSE:
2014-12-01 23:55:08 +01:00
sprintf (QueryAux," GROUP BY %s.CrsCod ORDER BY Num DESC",LogTable);
2018-10-30 02:37:09 +01:00
Str_Concat (Query,QueryAux,
2017-03-08 01:21:21 +01:00
Sta_MAX_BYTES_QUERY_ACCESS);
2014-12-01 23:55:08 +01:00
break;
}
/***** Write query for debug *****/
2015-10-11 17:40:07 +02:00
/*
2018-10-07 14:01:25 +02:00
if (Gbl.Usrs.Me.Role.Logged == Rol_SYS_ADM)
2019-02-16 14:37:34 +01:00
Ale_ShowFixedAlert (Ale_INFO,Query);
2015-10-11 17:40:07 +02:00
*/
2014-12-01 23:55:08 +01:00
/***** Make the query *****/
2018-11-14 23:40:56 +01:00
NumRows = DB_QuerySELECT (&mysql_res,"can not get clicks",
"%s",
Query);
2014-12-01 23:55:08 +01:00
/***** Count the number of rows in result *****/
if (NumRows == 0)
2019-02-16 18:25:41 +01:00
Ale_ShowAlert (Ale_INFO,Txt_There_are_no_accesses_with_the_selected_search_criteria);
2014-12-01 23:55:08 +01:00
else
{
2015-09-30 23:10:15 +02:00
/***** Put the table with the clicks *****/
2015-09-25 01:48:00 +02:00
if (Gbl.Stat.ClicksGroupedBy == Sta_CLICKS_CRS_DETAILED_LIST)
2017-06-10 21:38:10 +02:00
Box_StartBox ("100%",Txt_List_of_detailed_clicks,NULL,
2017-06-12 15:03:29 +02:00
NULL,Box_NOT_CLOSABLE);
2014-12-01 23:55:08 +01:00
else
2017-06-11 20:21:44 +02:00
Box_StartBox (NULL,Txt_STAT_TYPE_COUNT_CAPS[Gbl.Stat.CountType],NULL,
2017-06-12 15:03:29 +02:00
NULL,Box_NOT_CLOSABLE);
2015-11-12 01:27:33 +01:00
fprintf (Gbl.F.Out,"<table");
if (Sta_CellPadding[Gbl.Stat.ClicksGroupedBy])
fprintf (Gbl.F.Out," class=\"CELLS_PAD_%u\"",
Sta_CellPadding[Gbl.Stat.ClicksGroupedBy]);
fprintf (Gbl.F.Out,">");
2014-12-01 23:55:08 +01:00
2015-09-25 01:48:00 +02:00
switch (Gbl.Stat.ClicksGroupedBy)
2014-12-01 23:55:08 +01:00
{
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_CRS_DETAILED_LIST:
2014-12-01 23:55:08 +01:00
Sta_ShowDetailedAccessesList (NumRows,mysql_res);
break;
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_CRS_PER_USR:
2015-10-11 14:12:20 +02:00
Sta_ShowNumHitsPerUsr (NumRows,mysql_res);
2014-12-01 23:55:08 +01:00
break;
2018-10-07 14:01:25 +02:00
case Sta_CLICKS_CRS_PER_DAY:
case Sta_CLICKS_GBL_PER_DAY:
Sta_ShowNumHitsPerDay (NumRows,mysql_res);
2014-12-01 23:55:08 +01:00
break;
2018-10-07 14:01:25 +02:00
case Sta_CLICKS_CRS_PER_DAY_AND_HOUR:
case Sta_CLICKS_GBL_PER_DAY_AND_HOUR:
Sta_ShowDistrAccessesPerDayAndHour (NumRows,mysql_res);
2014-12-01 23:55:08 +01:00
break;
2018-10-07 14:01:25 +02:00
case Sta_CLICKS_CRS_PER_WEEK:
case Sta_CLICKS_GBL_PER_WEEK:
Sta_ShowNumHitsPerWeek (NumRows,mysql_res);
2014-12-01 23:55:08 +01:00
break;
2018-10-07 14:01:25 +02:00
case Sta_CLICKS_CRS_PER_MONTH:
case Sta_CLICKS_GBL_PER_MONTH:
Sta_ShowNumHitsPerMonth (NumRows,mysql_res);
break;
case Sta_CLICKS_CRS_PER_YEAR:
case Sta_CLICKS_GBL_PER_YEAR:
Sta_ShowNumHitsPerYear (NumRows,mysql_res);
2014-12-01 23:55:08 +01:00
break;
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_CRS_PER_HOUR:
case Sta_CLICKS_GBL_PER_HOUR:
2015-10-11 14:12:20 +02:00
Sta_ShowNumHitsPerHour (NumRows,mysql_res);
2014-12-01 23:55:08 +01:00
break;
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_CRS_PER_MINUTE:
case Sta_CLICKS_GBL_PER_MINUTE:
2014-12-01 23:55:08 +01:00
Sta_ShowAverageAccessesPerMinute (NumRows,mysql_res);
break;
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_CRS_PER_ACTION:
case Sta_CLICKS_GBL_PER_ACTION:
2015-10-11 14:12:20 +02:00
Sta_ShowNumHitsPerAction (NumRows,mysql_res);
2014-12-01 23:55:08 +01:00
break;
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_GBL_PER_PLUGIN:
2015-10-11 14:12:20 +02:00
Sta_ShowNumHitsPerPlugin (NumRows,mysql_res);
2014-12-01 23:55:08 +01:00
break;
2018-10-07 14:01:25 +02:00
case Sta_CLICKS_GBL_PER_API_FUNCTION:
2015-10-11 14:12:20 +02:00
Sta_ShowNumHitsPerWSFunction (NumRows,mysql_res);
2014-12-01 23:55:08 +01:00
break;
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_GBL_PER_BANNER:
2015-10-11 14:12:20 +02:00
Sta_ShowNumHitsPerBanner (NumRows,mysql_res);
2014-12-01 23:55:08 +01:00
break;
2015-10-11 14:12:20 +02:00
case Sta_CLICKS_GBL_PER_COUNTRY:
Sta_ShowNumHitsPerCountry (NumRows,mysql_res);
break;
case Sta_CLICKS_GBL_PER_INSTITUTION:
Sta_ShowNumHitsPerInstitution (NumRows,mysql_res);
break;
case Sta_CLICKS_GBL_PER_CENTRE:
Sta_ShowNumHitsPerCentre (NumRows,mysql_res);
break;
case Sta_CLICKS_GBL_PER_DEGREE:
Sta_ShowNumHitsPerDegree (NumRows,mysql_res);
2014-12-01 23:55:08 +01:00
break;
2015-09-25 01:48:00 +02:00
case Sta_CLICKS_GBL_PER_COURSE:
2015-10-11 14:12:20 +02:00
Sta_ShowNumHitsPerCourse (NumRows,mysql_res);
2014-12-01 23:55:08 +01:00
break;
}
2015-10-28 21:47:42 +01:00
fprintf (Gbl.F.Out,"</table>");
2014-12-01 23:55:08 +01:00
2017-06-12 14:16:33 +02:00
/* End box and section */
2017-06-10 21:38:10 +02:00
Box_EndBox ();
2017-05-25 13:43:54 +02:00
Lay_EndSection ();
2014-12-01 23:55:08 +01:00
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
2016-07-04 14:03:04 +02:00
/***** Free memory used by list of selected users' codes *****/
2016-01-17 15:10:54 +01:00
if (Gbl.Action.Act == ActSeeAccCrs)
2016-07-04 14:03:04 +02:00
Usr_FreeListsSelectedUsrsCods ();
2014-12-01 23:55:08 +01:00
2015-10-28 21:47:42 +01:00
/***** Write time zone used in the calculation of these statistics *****/
switch (Gbl.Stat.ClicksGroupedBy)
{
2018-10-07 14:01:25 +02:00
case Sta_CLICKS_CRS_PER_DAY:
case Sta_CLICKS_GBL_PER_DAY:
case Sta_CLICKS_CRS_PER_DAY_AND_HOUR:
case Sta_CLICKS_GBL_PER_DAY_AND_HOUR:
case Sta_CLICKS_CRS_PER_WEEK:
case Sta_CLICKS_GBL_PER_WEEK:
case Sta_CLICKS_CRS_PER_MONTH:
case Sta_CLICKS_GBL_PER_MONTH:
case Sta_CLICKS_CRS_PER_YEAR:
case Sta_CLICKS_GBL_PER_YEAR:
2015-10-28 21:47:42 +01:00
case Sta_CLICKS_CRS_PER_HOUR:
case Sta_CLICKS_GBL_PER_HOUR:
case Sta_CLICKS_CRS_PER_MINUTE:
case Sta_CLICKS_GBL_PER_MINUTE:
fprintf (Gbl.F.Out,"<p class=\"DAT_SMALL CENTER_MIDDLE\">%s: %s</p>",
Txt_Time_zone_used_in_the_calculation_of_these_statistics,
BrowserTimeZone);
break;
default:
break;
}
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************* Show a listing of detailed clicks ***********************/
/*****************************************************************************/
static void Sta_ShowDetailedAccessesList (unsigned long NumRows,MYSQL_RES *mysql_res)
{
extern const char *Txt_Show_previous_X_clicks;
extern const char *Txt_PAGES_Previous;
extern const char *Txt_Clicks;
extern const char *Txt_of_PART_OF_A_TOTAL;
extern const char *Txt_page;
extern const char *Txt_Show_next_X_clicks;
extern const char *Txt_PAGES_Next;
extern const char *Txt_No_INDEX;
extern const char *Txt_User_ID;
extern const char *Txt_Name;
2019-02-11 21:39:45 +01:00
extern const char *Txt_Role;
2014-12-01 23:55:08 +01:00
extern const char *Txt_Date;
extern const char *Txt_Action;
extern const char *Txt_LOG_More_info;
2015-03-12 14:45:40 +01:00
extern const char *Txt_ROLES_SINGUL_Abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
2015-12-29 11:35:01 +01:00
extern const char *Txt_Today;
2014-12-01 23:55:08 +01:00
unsigned long NumRow;
unsigned long FirstRow; // First row to show
unsigned long LastRow; // Last rows to show
unsigned long NumPagesBefore;
unsigned long NumPagesAfter;
unsigned long NumPagsTotal;
struct UsrData UsrDat;
MYSQL_ROW row;
long LogCod;
Rol_Role_t RoleFromLog;
2015-10-24 20:46:11 +02:00
unsigned UniqueId;
2014-12-01 23:55:08 +01:00
long ActCod;
2017-03-07 01:56:41 +01:00
char ActTxt[Act_MAX_BYTES_ACTION_TXT + 1];
2014-12-01 23:55:08 +01:00
/***** Initialize estructura of data of the user *****/
Usr_UsrDataConstructor (&UsrDat);
/***** Compute the first and the last row to show *****/
FirstRow = Gbl.Stat.FirstRow;
LastRow = Gbl.Stat.LastRow;
if (FirstRow == 0 && LastRow == 0) // Call from main form
{
// Show last clicks
FirstRow = (NumRows / Gbl.Stat.RowsPerPage - 1) * Gbl.Stat.RowsPerPage + 1;
if ((FirstRow + Gbl.Stat.RowsPerPage - 1) < NumRows)
FirstRow += Gbl.Stat.RowsPerPage;
LastRow = NumRows;
}
if (FirstRow < 1) // For security reasons; really it should never be less than 1
FirstRow = 1;
if (LastRow > NumRows)
LastRow = NumRows;
if ((LastRow - FirstRow) >= Gbl.Stat.RowsPerPage) // For if there have been clicks that have increased the number of rows
LastRow = FirstRow + Gbl.Stat.RowsPerPage - 1;
/***** Compute the number total of pages *****/
/* Number of pages before the current one */
NumPagesBefore = (FirstRow-1) / Gbl.Stat.RowsPerPage;
if (NumPagesBefore * Gbl.Stat.RowsPerPage < (FirstRow-1))
NumPagesBefore++;
/* Number of pages after the current one */
NumPagesAfter = (NumRows - LastRow) / Gbl.Stat.RowsPerPage;
if (NumPagesAfter * Gbl.Stat.RowsPerPage < (NumRows - LastRow))
NumPagesAfter++;
/* Count the total number of pages */
NumPagsTotal = NumPagesBefore + 1 + NumPagesAfter;
/***** Put heading with backward and forward buttons *****/
fprintf (Gbl.F.Out,"<tr>"
2017-05-01 12:36:24 +02:00
"<td colspan=\"7\" class=\"LEFT_MIDDLE\">");
2017-06-11 20:09:59 +02:00
Tbl_StartTableWide (2);
2017-05-01 12:36:24 +02:00
fprintf (Gbl.F.Out,"<tr>");
2014-12-01 23:55:08 +01:00
/* Put link to jump to previous page (older clicks) */
if (FirstRow > 1)
{
2018-11-09 20:47:39 +01:00
Frm_StartFormAnchor (ActSeeAccCrs,Sta_STAT_RESULTS_SECTION_ID);
2019-02-11 22:15:18 +01:00
Dat_WriteParamsIniEndDates ();
2015-09-25 01:48:00 +02:00
Par_PutHiddenParamUnsigned ("GroupedBy",(unsigned) Sta_CLICKS_CRS_DETAILED_LIST);
2017-01-29 21:41:08 +01:00
Par_PutHiddenParamUnsigned ("StatAct" ,(unsigned) Gbl.Stat.NumAction);
Par_PutHiddenParamLong ("FirstRow",FirstRow - Gbl.Stat.RowsPerPage);
Par_PutHiddenParamLong ("LastRow" ,FirstRow - 1);
2014-12-01 23:55:08 +01:00
Par_PutHiddenParamLong ("RowsPage",Gbl.Stat.RowsPerPage);
2019-03-11 13:33:34 +01:00
Usr_PutHiddenParUsrCodAll (ActSeeAccCrs,Gbl.Usrs.Selected.List[Rol_UNK]);
2014-12-01 23:55:08 +01:00
}
2015-08-24 12:29:00 +02:00
fprintf (Gbl.F.Out,"<td class=\"LEFT_MIDDLE\" style=\"width:20%%;\">");
2014-12-01 23:55:08 +01:00
if (FirstRow > 1)
{
2018-10-18 02:02:32 +02:00
snprintf (Gbl.Title,sizeof (Gbl.Title),
Txt_Show_previous_X_clicks,
Gbl.Stat.RowsPerPage);
2018-11-09 20:47:39 +01:00
Frm_LinkFormSubmit (Gbl.Title,"TIT_TBL",NULL);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"<strong>&lt;%s</strong></a>",
Txt_PAGES_Previous);
}
fprintf (Gbl.F.Out,"</td>");
if (FirstRow > 1)
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2014-12-01 23:55:08 +01:00
/* Write number of current page */
2015-09-30 23:10:15 +02:00
fprintf (Gbl.F.Out,"<td class=\"DAT_N CENTER_MIDDLE\" style=\"width:60%%;\">"
2014-12-25 12:54:21 +01:00
"<strong>"
2014-12-01 23:55:08 +01:00
"%s %lu-%lu %s %lu (%s %ld %s %lu)"
2014-12-25 12:54:21 +01:00
"</strong>"
"</td>",
2014-12-01 23:55:08 +01:00
Txt_Clicks,
FirstRow,LastRow,Txt_of_PART_OF_A_TOTAL,NumRows,
2017-01-28 15:58:46 +01:00
Txt_page,NumPagesBefore + 1,Txt_of_PART_OF_A_TOTAL,NumPagsTotal);
2014-12-01 23:55:08 +01:00
/* Put link to jump to next page (more recent clicks) */
if (LastRow < NumRows)
{
2018-11-09 20:47:39 +01:00
Frm_StartFormAnchor (ActSeeAccCrs,Sta_STAT_RESULTS_SECTION_ID);
2019-02-11 22:15:18 +01:00
Dat_WriteParamsIniEndDates ();
2015-09-25 01:48:00 +02:00
Par_PutHiddenParamUnsigned ("GroupedBy",(unsigned) Sta_CLICKS_CRS_DETAILED_LIST);
2017-01-28 15:58:46 +01:00
Par_PutHiddenParamUnsigned ("StatAct" ,(unsigned) Gbl.Stat.NumAction);
Par_PutHiddenParamUnsigned ("FirstRow" ,(unsigned) (LastRow + 1));
Par_PutHiddenParamUnsigned ("LastRow" ,(unsigned) (LastRow + Gbl.Stat.RowsPerPage));
Par_PutHiddenParamUnsigned ("RowsPage" ,(unsigned) Gbl.Stat.RowsPerPage);
2019-03-11 13:33:34 +01:00
Usr_PutHiddenParUsrCodAll (ActSeeAccCrs,Gbl.Usrs.Selected.List[Rol_UNK]);
2014-12-01 23:55:08 +01:00
}
2015-08-24 12:29:00 +02:00
fprintf (Gbl.F.Out,"<td class=\"RIGHT_MIDDLE\" style=\"width:20%%;\">");
2014-12-01 23:55:08 +01:00
if (LastRow < NumRows)
{
2018-10-18 02:02:32 +02:00
snprintf (Gbl.Title,sizeof (Gbl.Title),
Txt_Show_next_X_clicks,
Gbl.Stat.RowsPerPage);
2018-11-09 20:47:39 +01:00
Frm_LinkFormSubmit (Gbl.Title,"TIT_TBL",NULL);
2016-07-01 17:13:41 +02:00
fprintf (Gbl.F.Out,"<strong>%s&gt;</strong>"
"</a>",
2014-12-01 23:55:08 +01:00
Txt_PAGES_Next);
}
fprintf (Gbl.F.Out,"</td>");
if (LastRow < NumRows)
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2014-12-01 23:55:08 +01:00
2017-05-01 12:36:24 +02:00
fprintf (Gbl.F.Out,"</tr>");
2017-06-11 20:09:59 +02:00
Tbl_EndTable ();
2017-05-01 12:36:24 +02:00
fprintf (Gbl.F.Out,"</td>"
2014-12-01 23:55:08 +01:00
"</tr>");
/***** Write heading *****/
fprintf (Gbl.F.Out,"<tr>"
2015-09-06 20:02:14 +02:00
"<th class=\"RIGHT_TOP\">"
2014-12-27 00:28:19 +01:00
"%s"
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"CENTER_TOP\">"
2014-12-27 00:28:19 +01:00
"%s"
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"LEFT_TOP\">"
2014-12-27 00:28:19 +01:00
"%s"
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"CENTER_TOP\">"
2014-12-27 00:28:19 +01:00
"%s"
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"CENTER_TOP\">"
2014-12-27 00:28:19 +01:00
"%s"
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"LEFT_TOP\">"
2014-12-27 00:28:19 +01:00
"%s"
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"LEFT_TOP\" style=\"width:10%%;\">"
2014-12-27 00:28:19 +01:00
"%s"
"</th>"
2014-12-01 23:55:08 +01:00
"</tr>",
Txt_No_INDEX,
Txt_User_ID,
Txt_Name,
2019-02-11 21:39:45 +01:00
Txt_Role,
2014-12-01 23:55:08 +01:00
Txt_Date,
Txt_Action,
Txt_LOG_More_info);
/***** Write rows back *****/
2015-10-24 20:46:11 +02:00
for (NumRow = LastRow, UniqueId = 1, Gbl.RowEvenOdd = 0;
2014-12-01 23:55:08 +01:00
NumRow >= FirstRow;
2015-10-24 20:46:11 +02:00
NumRow--, UniqueId++, Gbl.RowEvenOdd = 1 - Gbl.RowEvenOdd)
2014-12-01 23:55:08 +01:00
{
2017-04-25 14:48:47 +02:00
mysql_data_seek (mysql_res,(my_ulonglong) (NumRow - 1));
2014-12-01 23:55:08 +01:00
row = mysql_fetch_row (mysql_res);
/* Get log code */
LogCod = Str_ConvertStrCodToLongCod (row[0]);
/* Get user's data of the database */
UsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[1]);
2019-03-19 13:22:14 +01:00
Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat,Usr_DONT_GET_PREFS);
2014-12-01 23:55:08 +01:00
/* Get logged role */
if (sscanf (row[2],"%u",&RoleFromLog) != 1)
2017-06-04 18:18:54 +02:00
Lay_ShowErrorAndExit ("Wrong role.");
2014-12-01 23:55:08 +01:00
/* Write the number of row */
fprintf (Gbl.F.Out,"<tr>"
2015-09-03 17:14:30 +02:00
"<td class=\"LOG RIGHT_TOP COLOR%u\">"
2014-12-25 12:54:21 +01:00
"%ld&nbsp;"
"</td>",
2015-09-03 17:14:30 +02:00
Gbl.RowEvenOdd,NumRow);
2014-12-01 23:55:08 +01:00
/* Write the user's ID if user is a student */
2015-09-03 17:14:30 +02:00
fprintf (Gbl.F.Out,"<td class=\"LOG CENTER_TOP COLOR%u\">",
Gbl.RowEvenOdd);
2017-05-09 20:56:02 +02:00
ID_WriteUsrIDs (&UsrDat,NULL);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"&nbsp;</td>");
/* Write the first name and the surnames */
2015-09-03 17:14:30 +02:00
fprintf (Gbl.F.Out,"<td class=\"LOG LEFT_TOP COLOR%u\">"
2014-12-25 12:54:21 +01:00
"%s&nbsp;"
"</td>",
2015-09-03 17:14:30 +02:00
Gbl.RowEvenOdd,UsrDat.FullName);
2014-12-01 23:55:08 +01:00
/* Write the user's role */
2015-09-03 17:14:30 +02:00
fprintf (Gbl.F.Out,"<td class=\"LOG CENTER_TOP COLOR%u\">"
2014-12-25 12:54:21 +01:00
"%s&nbsp;"
"</td>",
2015-09-03 17:14:30 +02:00
Gbl.RowEvenOdd,
2015-03-12 14:45:40 +01:00
RoleFromLog < Rol_NUM_ROLES ? Txt_ROLES_SINGUL_Abc[RoleFromLog][UsrDat.Sex] :
2014-12-01 23:55:08 +01:00
"?");
2015-10-24 20:46:11 +02:00
/* Write the date-time (row[3]) */
2017-06-11 20:21:44 +02:00
fprintf (Gbl.F.Out,"<td id=\"log_date_%u\" class=\"LOG RIGHT_TOP COLOR%u\">"
2015-10-24 20:46:11 +02:00
"<script type=\"text/javascript\">"
2017-05-04 17:06:26 +02:00
"writeLocalDateHMSFromUTC('log_date_%u',%ld,"
2017-05-05 09:41:56 +02:00
"%u,',&nbsp;','%s',true,false,0x7);"
2015-10-24 21:41:41 +02:00
"</script>"
"</td>",
2015-10-24 20:46:11 +02:00
UniqueId,Gbl.RowEvenOdd,
2017-05-04 17:06:26 +02:00
UniqueId,(long) Dat_GetUNIXTimeFromStr (row[3]),
(unsigned) Gbl.Prefs.DateFormat,Txt_Today);
2014-12-01 23:55:08 +01:00
/* Write the action */
if (sscanf (row[4],"%ld",&ActCod) != 1)
Lay_ShowErrorAndExit ("Wrong action code.");
if (ActCod >= 0)
2015-09-03 17:14:30 +02:00
fprintf (Gbl.F.Out,"<td class=\"LOG LEFT_TOP COLOR%u\">"
2014-12-25 12:54:21 +01:00
"%s&nbsp;"
"</td>",
2015-09-03 17:14:30 +02:00
Gbl.RowEvenOdd,
2014-12-01 23:55:08 +01:00
Act_GetActionTextFromDB (ActCod,ActTxt));
else
2015-09-03 17:14:30 +02:00
fprintf (Gbl.F.Out,"<td class=\"LOG LEFT_TOP COLOR%u\">"
2014-12-25 12:54:21 +01:00
"?&nbsp;"
"</td>",
2015-09-03 17:14:30 +02:00
Gbl.RowEvenOdd);
2017-06-11 20:21:44 +02:00
2014-12-01 23:55:08 +01:00
/* Write the comments of the access */
2015-09-03 17:14:30 +02:00
fprintf (Gbl.F.Out,"<td class=\"LOG LEFT_TOP COLOR%u\">",
Gbl.RowEvenOdd);
2014-12-01 23:55:08 +01:00
Sta_WriteLogComments (LogCod);
fprintf (Gbl.F.Out,"</td>"
"</tr>");
}
/***** Free memory used by the data of the user *****/
Usr_UsrDataDestructor (&UsrDat);
}
/*****************************************************************************/
/******** Show a listing of with the number of clicks of each user ***********/
/*****************************************************************************/
static void Sta_WriteLogComments (long LogCod)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
/***** Get log comments from database *****/
2018-11-01 21:59:42 +01:00
if (DB_QuerySELECT (&mysql_res,"can not get log comments",
"SELECT Comments FROM log_comments WHERE LogCod=%ld",
LogCod))
2014-12-01 23:55:08 +01:00
{
/***** Get and write comments *****/
row = mysql_fetch_row (mysql_res);
fprintf (Gbl.F.Out,"%s",row[0]);
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
/*****************************************************************************/
/********* Show a listing of with the number of clicks of each user **********/
/*****************************************************************************/
2017-05-22 20:37:46 +02:00
static void Sta_ShowNumHitsPerUsr (unsigned long NumRows,MYSQL_RES *mysql_res)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_No_INDEX;
extern const char *Txt_Photo;
extern const char *Txt_ID;
extern const char *Txt_Name;
2019-02-11 21:39:45 +01:00
extern const char *Txt_Role;
2015-09-25 01:48:00 +02:00
extern const char *Txt_STAT_TYPE_COUNT_CAPS[Sta_NUM_COUNT_TYPES];
2015-03-12 14:45:40 +01:00
extern const char *Txt_ROLES_SINGUL_Abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
2014-12-01 23:55:08 +01:00
MYSQL_ROW row;
unsigned long NumRow;
2015-10-11 18:53:22 +02:00
struct Sta_Hits Hits;
2014-12-01 23:55:08 +01:00
unsigned BarWidth;
struct UsrData UsrDat;
2017-01-28 15:58:46 +01:00
char PhotoURL[PATH_MAX + 1];
2014-12-01 23:55:08 +01:00
bool ShowPhoto;
/***** Initialize user's data *****/
Usr_UsrDataConstructor (&UsrDat);
/***** Write heading *****/
fprintf (Gbl.F.Out,"<tr>"
2015-09-06 20:02:14 +02:00
"<th class=\"RIGHT_TOP\">"
2014-12-25 12:54:21 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"CENTER_TOP\">"
2014-12-25 12:54:21 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2016-10-24 19:06:50 +02:00
"<th class=\"LEFT_TOP\">"
2014-12-25 12:54:21 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"LEFT_TOP\">"
2014-12-25 12:54:21 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"CENTER_TOP\">"
2014-12-25 12:54:21 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2015-09-06 20:02:14 +02:00
"<th colspan=\"2\" class=\"LEFT_TOP\">"
2014-12-25 12:54:21 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2014-12-01 23:55:08 +01:00
"</tr>",
Txt_No_INDEX,
Txt_Photo,
Txt_ID,
Txt_Name,
2019-02-11 21:39:45 +01:00
Txt_Role,
2014-12-01 23:55:08 +01:00
Txt_STAT_TYPE_COUNT_CAPS[Gbl.Stat.CountType]);
/***** Write rows *****/
2015-10-11 18:53:22 +02:00
for (NumRow = 1, Hits.Max = 0.0, Gbl.RowEvenOdd = 0;
2014-12-01 23:55:08 +01:00
NumRow <= NumRows;
NumRow++, Gbl.RowEvenOdd = 1 - Gbl.RowEvenOdd)
{
row = mysql_fetch_row (mysql_res);
/* Get user's data from the database */
UsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[0]);
2019-03-19 13:22:14 +01:00
Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat,Usr_DONT_GET_PREFS); // Get the data of the user from the database
2014-12-01 23:55:08 +01:00
/* Write the number of row */
fprintf (Gbl.F.Out,"<tr>"
2015-09-03 17:14:30 +02:00
"<td class=\"LOG RIGHT_TOP COLOR%u\">"
2014-12-25 12:54:21 +01:00
"%ld&nbsp;"
"</td>",
2015-09-03 17:14:30 +02:00
Gbl.RowEvenOdd,NumRow);
2014-12-01 23:55:08 +01:00
/* Show the photo */
2015-09-03 17:14:30 +02:00
fprintf (Gbl.F.Out,"<td class=\"CENTER_TOP COLOR%u\">",
Gbl.RowEvenOdd);
2017-01-28 15:58:46 +01:00
ShowPhoto = Pho_ShowingUsrPhotoIsAllowed (&UsrDat,PhotoURL);
2014-12-30 15:14:43 +01:00
Pho_ShowUsrPhoto (&UsrDat,ShowPhoto ? PhotoURL :
NULL,
2016-01-14 10:31:09 +01:00
"PHOTO15x20",Pho_ZOOM,false);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"</td>");
/* Write the user's ID if user is a student in current course */
2016-10-24 19:06:50 +02:00
fprintf (Gbl.F.Out,"<td class=\"LOG LEFT_TOP COLOR%u\">",
2015-09-03 17:14:30 +02:00
Gbl.RowEvenOdd);
2017-05-09 20:56:02 +02:00
ID_WriteUsrIDs (&UsrDat,NULL);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"&nbsp;</td>");
/* Write the name and the surnames */
2015-09-03 17:14:30 +02:00
fprintf (Gbl.F.Out,"<td class=\"LOG LEFT_TOP COLOR%u\">"
2014-12-25 12:54:21 +01:00
"%s&nbsp;"
"</td>",
2015-09-03 17:14:30 +02:00
Gbl.RowEvenOdd,UsrDat.FullName);
2014-12-01 23:55:08 +01:00
/* Write user's role */
2015-09-03 17:14:30 +02:00
fprintf (Gbl.F.Out,"<td class=\"LOG CENTER_TOP COLOR%u\">"
2014-12-25 12:54:21 +01:00
"%s&nbsp;"
"</td>",
2015-09-03 17:14:30 +02:00
Gbl.RowEvenOdd,
2017-06-08 15:32:33 +02:00
Txt_ROLES_SINGUL_Abc[UsrDat.Roles.InCurrentCrs.Role][UsrDat.Sex]);
2014-12-01 23:55:08 +01:00
/* Write the number of clicks */
2015-10-11 18:53:22 +02:00
Hits.Num = Str_GetFloatNumFromStr (row[1]);
2014-12-01 23:55:08 +01:00
if (NumRow == 1)
2015-10-11 18:53:22 +02:00
Hits.Max = Hits.Num;
if (Hits.Max > 0.0)
2014-12-01 23:55:08 +01:00
{
2015-10-11 18:53:22 +02:00
BarWidth = (unsigned) (((Hits.Num * 375.0) / Hits.Max) + 0.5);
2014-12-01 23:55:08 +01:00
if (BarWidth == 0)
BarWidth = 1;
}
else
BarWidth = 0;
2015-09-03 17:14:30 +02:00
fprintf (Gbl.F.Out,"<td class=\"LOG LEFT_TOP COLOR%u\">",
Gbl.RowEvenOdd);
2014-12-01 23:55:08 +01:00
if (BarWidth)
2018-10-07 15:13:24 +02:00
fprintf (Gbl.F.Out,"<img src=\"%s/%c1x1.png\"" // Background
2015-07-22 18:59:44 +02:00
" alt=\"\" title=\"\""
2015-09-05 11:48:44 +02:00
" class=\"LEFT_TOP\""
2018-10-07 15:36:43 +02:00
" style=\"width:%upx; height:10px; padding-top:4px;\" />"
2014-12-29 21:35:12 +01:00
"&nbsp;",
2019-03-20 01:36:36 +01:00
Cfg_URL_ICON_PUBLIC,
2018-10-07 15:13:24 +02:00
UsrDat.Roles.InCurrentCrs.Role == Rol_STD ? 'o' : // Student
'r', // Non-editing teacher or teacher
2014-12-01 23:55:08 +01:00
BarWidth);
2016-10-03 14:12:01 +02:00
Str_WriteFloatNum (Gbl.F.Out,Hits.Num);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"&nbsp;</td>"
"</tr>");
}
/***** Free memory used by the data of the user *****/
Usr_UsrDataDestructor (&UsrDat);
}
/*****************************************************************************/
/********** Show a listing of with the number of clicks in each date *********/
/*****************************************************************************/
2018-10-07 14:01:25 +02:00
static void Sta_ShowNumHitsPerDay (unsigned long NumRows,MYSQL_RES *mysql_res)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_Date;
extern const char *Txt_Day;
2015-09-25 01:48:00 +02:00
extern const char *Txt_STAT_TYPE_COUNT_CAPS[Sta_NUM_COUNT_TYPES];
2014-12-01 23:55:08 +01:00
extern const char *Txt_DAYS_SMALL[7];
unsigned long NumRow;
2015-10-11 14:12:20 +02:00
struct Date ReadDate;
struct Date LastDate;
struct Date Date;
unsigned D;
unsigned NumDaysFromLastDateToCurrDate;
2016-12-11 19:30:42 +01:00
int NumDayWeek;
2015-10-11 18:53:22 +02:00
struct Sta_Hits Hits;
2014-12-01 23:55:08 +01:00
MYSQL_ROW row;
2017-05-05 02:03:28 +02:00
char StrDate[Cns_MAX_BYTES_DATE + 1];
2014-12-01 23:55:08 +01:00
/***** Initialize LastDate *****/
2016-09-12 00:50:24 +02:00
Dat_AssignDate (&LastDate,&Gbl.DateRange.DateEnd.Date);
2014-12-01 23:55:08 +01:00
/***** Write heading *****/
fprintf (Gbl.F.Out,"<tr>"
2017-06-11 20:21:44 +02:00
"<th class=\"CENTER_TOP\">"
2015-11-12 01:27:33 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2015-11-12 01:27:33 +01:00
"<th class=\"LEFT_TOP\">"
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"LEFT_TOP\">"
2014-12-25 12:54:21 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2014-12-01 23:55:08 +01:00
"</tr>",
Txt_Date,
Txt_Day,
Txt_STAT_TYPE_COUNT_CAPS[Gbl.Stat.CountType]);
/***** Compute maximum number of pages generated per day *****/
2015-10-11 18:53:22 +02:00
Sta_ComputeMaxAndTotalHits (&Hits,NumRows,mysql_res,1,1);
2014-12-01 23:55:08 +01:00
/***** Write rows beginning by the most recent day and ending by the oldest *****/
mysql_data_seek (mysql_res,0);
for (NumRow = 1;
NumRow <= NumRows;
NumRow++)
{
row = mysql_fetch_row (mysql_res);
/* Get year, month and day (row[0] holds the date in YYYYMMDD format) */
if (!(Dat_GetDateFromYYYYMMDD (&ReadDate,row[0])))
Lay_ShowErrorAndExit ("Wrong date.");
/* Get number of pages generated (in row[1]) */
2015-10-11 18:53:22 +02:00
Hits.Num = Str_GetFloatNumFromStr (row[1]);
2014-12-01 23:55:08 +01:00
Dat_AssignDate (&Date,&LastDate);
NumDaysFromLastDateToCurrDate = Dat_GetNumDaysBetweenDates (&ReadDate,&LastDate);
/* In the next loop (NumDaysFromLastDateToCurrDate-1) d<>as (the more recent) with 0 clicks are shown
2015-10-11 18:53:22 +02:00
and a last day (the oldest) with Hits.Num */
2014-12-01 23:55:08 +01:00
for (D = 1;
D <= NumDaysFromLastDateToCurrDate;
D++)
{
NumDayWeek = Dat_GetDayOfWeek (Date.Year,Date.Month,Date.Day);
/* Write the date */
2017-05-05 02:03:28 +02:00
Dat_ConvDateToDateStr (&Date,StrDate);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"<tr>"
2017-06-11 20:21:44 +02:00
"<td class=\"%s RIGHT_TOP\">"
2017-05-05 02:03:28 +02:00
"%s&nbsp;"
2014-12-25 12:54:21 +01:00
"</td>",
2014-12-01 23:55:08 +01:00
NumDayWeek == 6 ? "LOG_R" :
"LOG",
2017-05-05 02:03:28 +02:00
StrDate);
2014-12-01 23:55:08 +01:00
/* Write the day of the week */
2015-08-24 12:29:00 +02:00
fprintf (Gbl.F.Out,"<td class=\"%s LEFT_TOP\">"
2014-12-25 12:54:21 +01:00
"%s&nbsp;"
"</td>",
2014-12-01 23:55:08 +01:00
NumDayWeek == 6 ? "LOG_R" :
"LOG",
Txt_DAYS_SMALL[NumDayWeek]);
2017-05-05 02:03:28 +02:00
2018-10-07 14:01:25 +02:00
/* Draw bar proportional to number of hits */
2018-10-07 15:13:24 +02:00
Sta_DrawBarNumHits (NumDayWeek == 6 ? 'r' : // red background
'o', // orange background
2015-10-11 18:53:22 +02:00
D == NumDaysFromLastDateToCurrDate ? Hits.Num :
2015-10-11 14:12:20 +02:00
0.0,
2015-10-11 18:53:22 +02:00
Hits.Max,Hits.Total,500);
2014-12-01 23:55:08 +01:00
/* Decrease day */
Dat_GetDateBefore (&Date,&Date);
}
Dat_AssignDate (&LastDate,&Date);
}
2015-10-27 19:00:21 +01:00
NumDaysFromLastDateToCurrDate = Dat_GetNumDaysBetweenDates (&Gbl.DateRange.DateIni.Date,&LastDate);
2014-12-01 23:55:08 +01:00
/***** Finally NumDaysFromLastDateToCurrDate days are shown with 0 clicks
(the oldest days from the requested initial day until the first with clicks) *****/
for (D = 1;
D <= NumDaysFromLastDateToCurrDate;
D++)
{
NumDayWeek = Dat_GetDayOfWeek (Date.Year,Date.Month,Date.Day);
/* Write the date */
2017-05-05 02:03:28 +02:00
Dat_ConvDateToDateStr (&Date,StrDate);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"<tr>"
2015-08-24 12:29:00 +02:00
"<td class=\"%s RIGHT_TOP\">"
2017-05-05 02:03:28 +02:00
"%s&nbsp;"
2014-12-25 12:54:21 +01:00
"</td>",
2014-12-01 23:55:08 +01:00
NumDayWeek == 6 ? "LOG_R" :
"LOG",
2017-05-05 02:03:28 +02:00
StrDate);
2014-12-01 23:55:08 +01:00
/* Write the day of the week */
2015-08-24 12:29:00 +02:00
fprintf (Gbl.F.Out,"<td class=\"%s LEFT_TOP\">"
2014-12-25 12:54:21 +01:00
"%s&nbsp;"
"</td>",
2014-12-01 23:55:08 +01:00
NumDayWeek == 6 ? "LOG_R" :
"LOG",
Txt_DAYS_SMALL[NumDayWeek]);
2018-10-07 14:01:25 +02:00
/* Draw bar proportional to number of hits */
2018-10-07 15:13:24 +02:00
Sta_DrawBarNumHits (NumDayWeek == 6 ? 'r' : // red background
'o', // orange background
2015-10-11 18:53:22 +02:00
0.0,Hits.Max,Hits.Total,500);
2014-12-01 23:55:08 +01:00
/* Decrease day */
Dat_GetDateBefore (&Date,&Date);
}
}
/*****************************************************************************/
/************ Show graphic of number of pages generated per hour *************/
/*****************************************************************************/
2015-09-28 18:28:29 +02:00
#define GRAPH_DISTRIBUTION_PER_HOUR_HOUR_WIDTH 25
2017-01-28 15:58:46 +01:00
#define GRAPH_DISTRIBUTION_PER_HOUR_TOTAL_WIDTH (GRAPH_DISTRIBUTION_PER_HOUR_HOUR_WIDTH * 24)
2014-12-01 23:55:08 +01:00
2018-10-07 14:01:25 +02:00
static void Sta_ShowDistrAccessesPerDayAndHour (unsigned long NumRows,MYSQL_RES *mysql_res)
2014-12-01 23:55:08 +01:00
{
2019-02-22 21:47:50 +01:00
extern const char *The_ClassFormInBox[The_NUM_THEMES];
2014-12-01 23:55:08 +01:00
extern const char *Txt_Color_of_the_graphic;
extern const char *Txt_STAT_COLOR_TYPES[Sta_NUM_COLOR_TYPES];
extern const char *Txt_Date;
extern const char *Txt_Day;
2015-09-25 01:48:00 +02:00
extern const char *Txt_STAT_TYPE_COUNT_CAPS[Sta_NUM_COUNT_TYPES];
2014-12-01 23:55:08 +01:00
extern const char *Txt_DAYS_SMALL[7];
2015-10-11 14:12:20 +02:00
Sta_ColorType_t ColorType;
Sta_ColorType_t SelectedColorType;
2014-12-01 23:55:08 +01:00
unsigned long NumRow;
2015-10-11 14:12:20 +02:00
struct Date PreviousReadDate;
struct Date CurrentReadDate;
struct Date LastDate;
struct Date Date;
unsigned D;
unsigned NumDaysFromLastDateToCurrDate = 1;
unsigned NumDayWeek;
unsigned Hour;
unsigned ReadHour = 0;
2015-10-11 18:53:22 +02:00
struct Sta_Hits Hits;
2015-10-11 14:12:20 +02:00
float NumAccPerHour[24];
float NumAccPerHourZero[24];
2014-12-01 23:55:08 +01:00
MYSQL_ROW row;
2017-05-05 02:03:28 +02:00
char StrDate[Cns_MAX_BYTES_DATE + 1];
2014-12-01 23:55:08 +01:00
/***** Get selected color type *****/
SelectedColorType = Sta_GetStatColorType ();
/***** Put a selector for the type of color *****/
fprintf (Gbl.F.Out,"<tr>"
2016-12-27 16:45:37 +01:00
"<td colspan=\"26\" class=\"CENTER_MIDDLE\">");
2014-12-01 23:55:08 +01:00
2018-11-09 20:47:39 +01:00
Frm_StartFormAnchor (Gbl.Action.Act,Sta_STAT_RESULTS_SECTION_ID);
2019-02-11 22:15:18 +01:00
Dat_WriteParamsIniEndDates ();
2015-09-25 01:48:00 +02:00
Par_PutHiddenParamUnsigned ("GroupedBy",(unsigned) Gbl.Stat.ClicksGroupedBy);
2014-12-01 23:55:08 +01:00
Par_PutHiddenParamUnsigned ("CountType",(unsigned) Gbl.Stat.CountType);
2017-01-29 21:41:08 +01:00
Par_PutHiddenParamUnsigned ("StatAct" ,(unsigned) Gbl.Stat.NumAction);
2016-01-17 15:10:54 +01:00
if (Gbl.Action.Act == ActSeeAccCrs)
2019-03-11 13:33:34 +01:00
Usr_PutHiddenParUsrCodAll (ActSeeAccCrs,Gbl.Usrs.Selected.List[Rol_UNK]);
2016-01-17 15:10:54 +01:00
else // Gbl.Action.Act == ActSeeAccGbl
2014-12-01 23:55:08 +01:00
{
Par_PutHiddenParamUnsigned ("Role",(unsigned) Gbl.Stat.Role);
2016-11-06 13:06:21 +01:00
Sta_PutHiddenParamScopeSta ();
2014-12-01 23:55:08 +01:00
}
2016-12-27 16:45:37 +01:00
fprintf (Gbl.F.Out,"<label class=\"%s\">%s:&nbsp;"
"<select name=\"ColorType\""
2015-10-22 14:49:48 +02:00
" onchange=\"document.getElementById('%s').submit();\">",
2019-02-22 21:47:50 +01:00
The_ClassFormInBox[Gbl.Prefs.Theme],
2016-12-27 16:45:37 +01:00
Txt_Color_of_the_graphic,
2016-01-14 10:31:09 +01:00
Gbl.Form.Id);
2014-12-01 23:55:08 +01:00
for (ColorType = (Sta_ColorType_t) 0;
ColorType < Sta_NUM_COLOR_TYPES;
ColorType++)
{
fprintf (Gbl.F.Out,"<option value=\"%u\"",(unsigned) ColorType);
if (ColorType == SelectedColorType)
fprintf (Gbl.F.Out," selected=\"selected\"");
fprintf (Gbl.F.Out,">%s",Txt_STAT_COLOR_TYPES[ColorType]);
}
2016-12-27 16:45:37 +01:00
fprintf (Gbl.F.Out,"</select>"
"</label>");
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2015-03-13 00:16:02 +01:00
fprintf (Gbl.F.Out,"</td>"
2014-12-01 23:55:08 +01:00
"</tr>");
/***** Compute maximum number of pages generated per day-hour *****/
2015-10-11 18:53:22 +02:00
Sta_ComputeMaxAndTotalHits (&Hits,NumRows,mysql_res,2,1);
2014-12-01 23:55:08 +01:00
/***** Initialize LastDate *****/
2016-09-12 00:50:24 +02:00
Dat_AssignDate (&LastDate,&Gbl.DateRange.DateEnd.Date);
2014-12-01 23:55:08 +01:00
/***** Reset number of pages generated per hour *****/
for (Hour = 0;
Hour < 24;
Hour++)
NumAccPerHour[Hour] = NumAccPerHourZero[Hour] = 0.0;
/***** Write heading *****/
fprintf (Gbl.F.Out,"<tr>"
2017-06-11 20:21:44 +02:00
"<th rowspan=\"3\" class=\"CENTER_TOP\">"
2015-11-12 01:27:33 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2015-11-12 01:27:33 +01:00
"<th rowspan=\"3\" class=\"LEFT_TOP\">"
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2015-09-06 20:02:14 +02:00
"<th colspan=\"24\" class=\"LEFT_TOP\""
2015-09-24 18:02:21 +02:00
" style=\"width:%upx;\">"
2014-12-25 12:54:21 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2014-12-01 23:55:08 +01:00
"</tr>",
Txt_Date,
Txt_Day,
2015-09-24 18:02:21 +02:00
GRAPH_DISTRIBUTION_PER_HOUR_TOTAL_WIDTH,
2015-09-23 14:31:47 +02:00
Txt_STAT_TYPE_COUNT_CAPS[Gbl.Stat.CountType]);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"<tr>"
2015-08-24 12:29:00 +02:00
"<td colspan=\"24\" class=\"LEFT_TOP\""
2015-09-24 18:02:21 +02:00
" style=\"width:%upx;\">",
GRAPH_DISTRIBUTION_PER_HOUR_TOTAL_WIDTH);
2015-10-11 18:53:22 +02:00
Sta_DrawBarColors (SelectedColorType,Hits.Max);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"</td>"
"</tr>"
"<tr>");
for (Hour = 0;
Hour < 24;
Hour++)
2015-09-24 18:02:21 +02:00
fprintf (Gbl.F.Out,"<td class=\"LOG CENTER_TOP\" style=\"width:%upx;\">"
2014-12-25 12:54:21 +01:00
"%02uh"
"</td>",
2015-09-24 18:02:21 +02:00
GRAPH_DISTRIBUTION_PER_HOUR_HOUR_WIDTH,Hour);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"</tr>");
/***** Write rows beginning by the most recent day and ending by the oldest one *****/
mysql_data_seek (mysql_res,0);
for (NumRow = 1;
NumRow <= NumRows;
NumRow++)
{
row = mysql_fetch_row (mysql_res);
/* Get year, month and day (row[0] holds the date in YYYYMMDD format) */
if (!(Dat_GetDateFromYYYYMMDD (&CurrentReadDate,row[0])))
Lay_ShowErrorAndExit ("Wrong date.");
/* Get the hour (in row[1] is the hour in formato HH) */
if (sscanf (row[1],"%02u",&ReadHour) != 1)
Lay_ShowErrorAndExit ("Wrong hour.");
/* Get number of pages generated (in row[2]) */
2015-10-11 18:53:22 +02:00
Hits.Num = Str_GetFloatNumFromStr (row[2]);
2014-12-01 23:55:08 +01:00
/* If this is the first read date, initialize PreviousReadDate */
if (NumRow == 1)
Dat_AssignDate (&PreviousReadDate,&CurrentReadDate);
2015-11-11 03:00:22 +01:00
/* Update number of hits per hour */
2014-12-01 23:55:08 +01:00
if (PreviousReadDate.Year != CurrentReadDate.Year ||
PreviousReadDate.Month != CurrentReadDate.Month ||
PreviousReadDate.Day != CurrentReadDate.Day) // Current read date (CurrentReadDate) is older than previous read date (PreviousReadDate) */
{
2015-11-11 03:00:22 +01:00
/* In the next loop we show (NumDaysFromLastDateToCurrDate-1) days with 0 clicks
2015-10-11 18:53:22 +02:00
and a last day (older) with Hits.Num */
2014-12-01 23:55:08 +01:00
Dat_AssignDate (&Date,&LastDate);
NumDaysFromLastDateToCurrDate = Dat_GetNumDaysBetweenDates (&PreviousReadDate,&LastDate);
for (D = 1;
D <= NumDaysFromLastDateToCurrDate;
D++)
{
NumDayWeek = Dat_GetDayOfWeek (Date.Year,Date.Month,Date.Day);
/* Write the date */
2017-05-05 02:03:28 +02:00
Dat_ConvDateToDateStr (&Date,StrDate);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"<tr>"
2017-06-11 20:21:44 +02:00
"<td class=\"%s RIGHT_TOP\">"
2017-05-05 02:03:28 +02:00
"%s&nbsp;"
2014-12-25 12:54:21 +01:00
"</td>",
2014-12-01 23:55:08 +01:00
NumDayWeek == 6 ? "LOG_R" :
"LOG",
2017-05-05 02:03:28 +02:00
StrDate);
2014-12-01 23:55:08 +01:00
/* Write the day of the week */
2015-08-24 12:29:00 +02:00
fprintf (Gbl.F.Out,"<td class=\"%s LEFT_TOP\">"
2014-12-25 12:54:21 +01:00
"%s&nbsp;"
"</td>",
2014-12-01 23:55:08 +01:00
NumDayWeek == 6 ? "LOG_R" :
"LOG",
Txt_DAYS_SMALL[NumDayWeek]);
/* Draw a cell with the color proportional to the number of clicks */
if (D == NumDaysFromLastDateToCurrDate)
2015-10-11 18:53:22 +02:00
Sta_DrawAccessesPerHourForADay (SelectedColorType,NumAccPerHour,Hits.Max);
2014-12-01 23:55:08 +01:00
else // D < NumDaysFromLastDateToCurrDate
2015-10-11 18:53:22 +02:00
Sta_DrawAccessesPerHourForADay (SelectedColorType,NumAccPerHourZero,Hits.Max);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"</tr>");
/* Decrease day */
Dat_GetDateBefore (&Date,&Date);
}
Dat_AssignDate (&LastDate,&Date);
Dat_AssignDate (&PreviousReadDate,&CurrentReadDate);
/* Reset number of pages generated per hour */
for (Hour = 0;
Hour < 24;
Hour++)
NumAccPerHour[Hour] = 0.0;
}
2015-10-11 18:53:22 +02:00
NumAccPerHour[ReadHour] = Hits.Num;
2014-12-01 23:55:08 +01:00
}
/***** Show the clicks of the oldest day with clicks *****/
/* In the next loop we show (NumDaysFromLastDateToCurrDate-1) days (more recent) with 0 clicks
2015-10-11 18:53:22 +02:00
and a last day (older) with Hits.Num clicks */
2014-12-01 23:55:08 +01:00
Dat_AssignDate (&Date,&LastDate);
NumDaysFromLastDateToCurrDate = Dat_GetNumDaysBetweenDates (&PreviousReadDate,&LastDate);
for (D = 1;
D <= NumDaysFromLastDateToCurrDate;
D++)
{
NumDayWeek = Dat_GetDayOfWeek (Date.Year,Date.Month,Date.Day);
/* Write the date */
2017-05-05 02:03:28 +02:00
Dat_ConvDateToDateStr (&Date,StrDate);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"<tr>"
2015-08-24 12:29:00 +02:00
"<td class=\"%s RIGHT_TOP\">"
2017-05-05 02:03:28 +02:00
"%s&nbsp;"
2014-12-25 12:54:21 +01:00
"</td>",
2014-12-01 23:55:08 +01:00
NumDayWeek == 6 ? "LOG_R" :
"LOG",
2017-05-05 02:03:28 +02:00
StrDate);
2014-12-01 23:55:08 +01:00
/* Write the day of the week */
2015-08-24 12:29:00 +02:00
fprintf (Gbl.F.Out,"<td class=\"%s LEFT_TOP\">"
2014-12-25 12:54:21 +01:00
"%s&nbsp;"
"</td>",
2014-12-01 23:55:08 +01:00
NumDayWeek == 6 ? "LOG_R" :
"LOG",
Txt_DAYS_SMALL[NumDayWeek]);
/* Draw the color proporcional al number of clicks */
if (D == NumDaysFromLastDateToCurrDate)
2015-10-11 18:53:22 +02:00
Sta_DrawAccessesPerHourForADay (SelectedColorType,NumAccPerHour,Hits.Max);
2014-12-01 23:55:08 +01:00
else // D < NumDaysFromLastDateToCurrDate
2015-10-11 18:53:22 +02:00
Sta_DrawAccessesPerHourForADay (SelectedColorType,NumAccPerHourZero,Hits.Max);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"</tr>");
/* Decrease day */
Dat_GetDateBefore (&Date,&Date);
}
/***** Finally NumDaysFromLastDateToCurrDate days are shown with 0 clicks
(the oldest days since the initial day requested by the user until the first with clicks) *****/
Dat_AssignDate (&LastDate,&Date);
2015-10-27 19:00:21 +01:00
NumDaysFromLastDateToCurrDate = Dat_GetNumDaysBetweenDates (&Gbl.DateRange.DateIni.Date,&LastDate);
2014-12-01 23:55:08 +01:00
for (D = 1;
D <= NumDaysFromLastDateToCurrDate;
D++)
{
NumDayWeek = Dat_GetDayOfWeek (Date.Year,Date.Month,Date.Day);
/* Write the date */
2017-05-05 02:03:28 +02:00
Dat_ConvDateToDateStr (&Date,StrDate);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"<tr>"
2015-08-24 12:29:00 +02:00
"<td class=\"%s RIGHT_TOP\">"
2017-05-05 02:03:28 +02:00
"%s&nbsp;"
2014-12-25 12:54:21 +01:00
"</td>",
2014-12-01 23:55:08 +01:00
NumDayWeek == 6 ? "LOG_R" :
"LOG",
2017-05-05 02:03:28 +02:00
StrDate);
2014-12-01 23:55:08 +01:00
/* Write the day of the week */
2015-08-24 12:29:00 +02:00
fprintf (Gbl.F.Out,"<td class=\"%s LEFT_TOP\">"
2014-12-25 12:54:21 +01:00
"%s&nbsp;"
"</td>",
2014-12-01 23:55:08 +01:00
NumDayWeek == 6 ? "LOG_R" :
"LOG",
Txt_DAYS_SMALL[NumDayWeek]);
/* Draw the color proportional to number of clicks */
2015-10-11 18:53:22 +02:00
Sta_DrawAccessesPerHourForADay (SelectedColorType,NumAccPerHourZero,Hits.Max);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"</tr>");
/* Decrease day */
Dat_GetDateBefore (&Date,&Date);
}
}
2019-02-12 14:46:14 +01:00
/*****************************************************************************/
/********* Put hidden parameter for the type of figure (statistic) ***********/
/*****************************************************************************/
static void Sta_PutHiddenParamScopeSta (void)
{
Sco_PutParamScope ("ScopeSta",Gbl.Scope.Current);
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/********************** Get type of color for statistics *********************/
/*****************************************************************************/
static Sta_ColorType_t Sta_GetStatColorType (void)
{
2017-01-29 21:41:08 +01:00
return (Sta_ColorType_t)
Par_GetParToUnsignedLong ("ColorType",
0,
Sta_NUM_COLOR_TYPES - 1,
(unsigned long) Sta_COLOR_TYPE_DEF);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************************* Draw a bar with colors ****************************/
/*****************************************************************************/
2015-10-11 18:53:22 +02:00
static void Sta_DrawBarColors (Sta_ColorType_t ColorType,float HitsMax)
2014-12-01 23:55:08 +01:00
{
2015-10-11 18:53:22 +02:00
unsigned Interval;
unsigned NumColor;
unsigned R;
unsigned G;
unsigned B;
2014-12-01 23:55:08 +01:00
2015-10-11 18:53:22 +02:00
/***** Write numbers from 0 to Hits.Max *****/
2017-06-11 20:09:59 +02:00
Tbl_StartTableWide (0);
2017-05-01 12:36:24 +02:00
fprintf (Gbl.F.Out,"<tr>"
2015-08-24 12:29:00 +02:00
"<td colspan=\"%u\" class=\"LOG LEFT_BOTTOM\""
2015-09-24 18:02:21 +02:00
" style=\"width:%upx;\">"
2014-12-25 12:54:21 +01:00
"0"
"</td>",
(GRAPH_DISTRIBUTION_PER_HOUR_TOTAL_WIDTH/5)/2,
(GRAPH_DISTRIBUTION_PER_HOUR_TOTAL_WIDTH/5)/2);
2014-12-01 23:55:08 +01:00
for (Interval = 1;
Interval <= 4;
Interval++)
{
2015-08-24 12:29:00 +02:00
fprintf (Gbl.F.Out,"<td colspan=\"%u\" class=\"LOG CENTER_BOTTOM\""
2015-09-24 18:02:21 +02:00
" style=\"width:%upx;\">",
2014-12-25 12:54:21 +01:00
GRAPH_DISTRIBUTION_PER_HOUR_TOTAL_WIDTH/5,
GRAPH_DISTRIBUTION_PER_HOUR_TOTAL_WIDTH/5);
2016-10-03 14:12:01 +02:00
Str_WriteFloatNum (Gbl.F.Out,(float) Interval * HitsMax / 5.0);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"</td>");
}
2015-08-24 12:29:00 +02:00
fprintf (Gbl.F.Out,"<td colspan=\"%u\" class=\"LOG RIGHT_BOTTOM\""
2015-09-24 18:02:21 +02:00
" style=\"width:%upx;\">",
2014-12-25 12:54:21 +01:00
(GRAPH_DISTRIBUTION_PER_HOUR_TOTAL_WIDTH/5)/2,
(GRAPH_DISTRIBUTION_PER_HOUR_TOTAL_WIDTH/5)/2);
2016-10-03 14:12:01 +02:00
Str_WriteFloatNum (Gbl.F.Out,HitsMax);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"</td>"
"</tr>"
"<tr>");
/***** Draw colors *****/
for (NumColor = 0;
NumColor < GRAPH_DISTRIBUTION_PER_HOUR_TOTAL_WIDTH;
NumColor++)
{
Sta_SetColor (ColorType,(float) NumColor,(float) GRAPH_DISTRIBUTION_PER_HOUR_TOTAL_WIDTH,&R,&G,&B);
2015-09-24 18:02:21 +02:00
fprintf (Gbl.F.Out,"<td class=\"LEFT_MIDDLE\" style=\"width:1px;"
2014-12-25 12:54:21 +01:00
" background-color:#%02X%02X%02X;\">"
2015-07-22 18:59:44 +02:00
"<img src=\"%s/tr1x14.gif\""
" alt=\"\" title=\"\" />"
2014-12-25 12:54:21 +01:00
"</td>",
2019-03-20 01:36:36 +01:00
R,G,B,Cfg_URL_ICON_PUBLIC);
2014-12-01 23:55:08 +01:00
}
2017-05-01 12:36:24 +02:00
fprintf (Gbl.F.Out,"</tr>");
2017-06-11 20:09:59 +02:00
Tbl_EndTable ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/********************* Draw accesses per hour for a day **********************/
/*****************************************************************************/
2015-10-11 18:53:22 +02:00
static void Sta_DrawAccessesPerHourForADay (Sta_ColorType_t ColorType,float HitsNum[24],float HitsMax)
2014-12-01 23:55:08 +01:00
{
2015-10-11 14:12:20 +02:00
unsigned Hour;
unsigned R;
unsigned G;
unsigned B;
2014-12-01 23:55:08 +01:00
for (Hour = 0;
Hour < 24;
Hour++)
{
2015-10-11 18:53:22 +02:00
Sta_SetColor (ColorType,HitsNum[Hour],HitsMax,&R,&G,&B);
2015-08-24 12:29:00 +02:00
fprintf (Gbl.F.Out,"<td class=\"LOG LEFT_MIDDLE\" title=\"");
2016-10-03 14:12:01 +02:00
Str_WriteFloatNum (Gbl.F.Out,HitsNum[Hour]);
2015-09-24 18:02:21 +02:00
fprintf (Gbl.F.Out,"\" style=\"width:%upx;"
2014-12-25 12:54:21 +01:00
" background-color:#%02X%02X%02X;\">"
"</td>",
GRAPH_DISTRIBUTION_PER_HOUR_HOUR_WIDTH,R,G,B);
2014-12-01 23:55:08 +01:00
}
}
/*****************************************************************************/
/************************* Set color depending on ratio **********************/
/*****************************************************************************/
2015-10-11 18:53:22 +02:00
// Hits.Max must be > 0
2014-12-01 23:55:08 +01:00
/*
Black Blue Cyan Green Yellow Red
+------------+------------+------------+------------+------------+
| 0.2 | 0.2 | 0.2 | 0.2 | 0.2 |
+------------+------------+------------+------------+------------+
0.0 0.2 0.4 0.6 0.8 1.0
*/
2015-10-11 18:53:22 +02:00
static void Sta_SetColor (Sta_ColorType_t ColorType,float HitsNum,float HitsMax,
unsigned *R,unsigned *G,unsigned *B)
2014-12-01 23:55:08 +01:00
{
2015-10-11 18:53:22 +02:00
float Result = (HitsNum / HitsMax);
2014-12-01 23:55:08 +01:00
switch (ColorType)
{
case Sta_COLOR:
if (Result < 0.2) // Black -> Blue
{
*R = 0;
*G = 0;
*B = (unsigned) (Result * 256.0 / 0.2 + 0.5);
if (*B == 256)
*B = 255;
}
else if (Result < 0.4) // Blue -> Cyan
{
*R = 0;
*G = (unsigned) ((Result-0.2) * 256.0 / 0.2 + 0.5);
if (*G == 256)
*G = 255;
*B = 255;
}
else if (Result < 0.6) // Cyan -> Green
{
*R = 0;
*G = 255;
*B = 256 - (unsigned) ((Result-0.4) * 256.0 / 0.2 + 0.5);
if (*B == 256)
*B = 255;
}
else if (Result < 0.8) // Green -> Yellow
{
*R = (unsigned) ((Result-0.6) * 256.0 / 0.2 + 0.5);
if (*R == 256)
*R = 255;
*G = 255;
*B = 0;
}
else // Yellow -> Red
{
*R = 255;
*G = 256 - (unsigned) ((Result-0.8) * 256.0 / 0.2 + 0.5);
if (*G == 256)
*G = 255;
*B = 0;
}
break;
case Sta_BLACK_TO_WHITE:
*B = (unsigned) (Result * 256.0 + 0.5);
if (*B == 256)
*B = 255;
*R = *G = *B;
break;
case Sta_WHITE_TO_BLACK:
*B = 256 - (unsigned) (Result * 256.0 + 0.5);
if (*B == 256)
*B = 255;
*R = *G = *B;
break;
}
}
/*****************************************************************************/
/********** Show listing with number of pages generated per week *************/
/*****************************************************************************/
2018-10-07 14:01:25 +02:00
static void Sta_ShowNumHitsPerWeek (unsigned long NumRows,
2015-10-11 14:12:20 +02:00
MYSQL_RES *mysql_res)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_Week;
2015-09-25 01:48:00 +02:00
extern const char *Txt_STAT_TYPE_COUNT_CAPS[Sta_NUM_COUNT_TYPES];
2014-12-01 23:55:08 +01:00
unsigned long NumRow;
2015-10-11 14:12:20 +02:00
struct Date ReadDate;
struct Date LastDate;
struct Date Date;
unsigned W;
2018-10-07 14:01:25 +02:00
unsigned NumWeeksBetweenLastDateAndCurDate;
2015-10-11 18:53:22 +02:00
struct Sta_Hits Hits;
2014-12-01 23:55:08 +01:00
MYSQL_ROW row;
/***** Initialize LastDate to avoid warning *****/
2015-10-27 19:00:21 +01:00
Dat_CalculateWeekOfYear (&Gbl.DateRange.DateEnd.Date); // Changes Week and Year
2016-09-12 00:50:24 +02:00
Dat_AssignDate (&LastDate,&Gbl.DateRange.DateEnd.Date);
2014-12-01 23:55:08 +01:00
/***** Write heading *****/
fprintf (Gbl.F.Out,"<tr>"
2015-11-12 01:27:33 +01:00
"<th class=\"LEFT_TOP\">"
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"LEFT_TOP\">"
2014-12-25 12:54:21 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2014-12-01 23:55:08 +01:00
"</tr>",
Txt_Week,
Txt_STAT_TYPE_COUNT_CAPS[Gbl.Stat.CountType]);
/***** Compute maximum number of pages generated per week *****/
2015-10-11 18:53:22 +02:00
Sta_ComputeMaxAndTotalHits (&Hits,NumRows,mysql_res,1,1);
2014-12-01 23:55:08 +01:00
/***** Write rows *****/
mysql_data_seek (mysql_res,0);
for (NumRow = 1;
NumRow <= NumRows;
NumRow++)
{
row = mysql_fetch_row (mysql_res);
/* Get year and week (row[0] holds date in YYYYWW format) */
if (sscanf (row[0],"%04u%02u",&ReadDate.Year,&ReadDate.Week) != 2)
Lay_ShowErrorAndExit ("Wrong date.");
/* Get number of pages generated (in row[1]) */
2015-10-11 18:53:22 +02:00
Hits.Num = Str_GetFloatNumFromStr (row[1]);
2014-12-01 23:55:08 +01:00
Dat_AssignDate (&Date,&LastDate);
2018-10-07 14:01:25 +02:00
NumWeeksBetweenLastDateAndCurDate = Dat_GetNumWeeksBetweenDates (&ReadDate,&LastDate);
2014-12-01 23:55:08 +01:00
for (W = 1;
2018-10-07 14:01:25 +02:00
W <= NumWeeksBetweenLastDateAndCurDate;
2014-12-01 23:55:08 +01:00
W++)
{
/* Write week */
fprintf (Gbl.F.Out,"<tr>"
2015-11-12 01:27:33 +01:00
"<td class=\"LOG LEFT_TOP\">"
2015-10-31 02:11:38 +01:00
"%04u-%02u&nbsp;"
2014-12-25 12:54:21 +01:00
"</td>",
2015-10-31 02:11:38 +01:00
Date.Year,Date.Week);
2014-12-01 23:55:08 +01:00
2018-10-07 14:01:25 +02:00
/* Draw bar proportional to number of hits */
2018-10-07 15:13:24 +02:00
Sta_DrawBarNumHits ('o', // orange background
2018-10-07 14:01:25 +02:00
W == NumWeeksBetweenLastDateAndCurDate ? Hits.Num :
0.0,
2015-10-11 18:53:22 +02:00
Hits.Max,Hits.Total,500);
2014-12-01 23:55:08 +01:00
/* Decrement week */
Dat_GetWeekBefore (&Date,&Date);
}
Dat_AssignDate (&LastDate,&Date);
}
/***** Finally, show the old weeks without pages generated *****/
2015-10-27 19:00:21 +01:00
Dat_CalculateWeekOfYear (&Gbl.DateRange.DateIni.Date); // Changes Week and Year
2018-10-07 14:01:25 +02:00
NumWeeksBetweenLastDateAndCurDate = Dat_GetNumWeeksBetweenDates (&Gbl.DateRange.DateIni.Date,
&LastDate);
2014-12-01 23:55:08 +01:00
for (W = 1;
2018-10-07 14:01:25 +02:00
W <= NumWeeksBetweenLastDateAndCurDate;
2014-12-01 23:55:08 +01:00
W++)
{
/* Write week */
fprintf (Gbl.F.Out,"<tr>"
2015-11-12 01:27:33 +01:00
"<td class=\"LOG LEFT_TOP\">"
2015-10-31 02:11:38 +01:00
"%04u-%02u&nbsp;"
2014-12-25 12:54:21 +01:00
"</td>",
2015-10-31 02:11:38 +01:00
Date.Year,Date.Week);
2014-12-01 23:55:08 +01:00
2018-10-07 14:01:25 +02:00
/* Draw bar proportional to number of hits */
2018-10-07 15:13:24 +02:00
Sta_DrawBarNumHits ('o', // orange background
0.0,Hits.Max,Hits.Total,500);
2014-12-01 23:55:08 +01:00
/* Decrement week */
Dat_GetWeekBefore (&Date,&Date);
}
}
/*****************************************************************************/
/********** Show a graph with the number of clicks in each month *************/
/*****************************************************************************/
2018-10-07 14:01:25 +02:00
static void Sta_ShowNumHitsPerMonth (unsigned long NumRows,
2015-10-11 14:12:20 +02:00
MYSQL_RES *mysql_res)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_Month;
2015-09-25 01:48:00 +02:00
extern const char *Txt_STAT_TYPE_COUNT_CAPS[Sta_NUM_COUNT_TYPES];
2014-12-01 23:55:08 +01:00
unsigned long NumRow;
2015-10-11 14:12:20 +02:00
struct Date ReadDate;
struct Date LastDate;
struct Date Date;
unsigned M;
2018-10-07 14:01:25 +02:00
unsigned NumMonthsBetweenLastDateAndCurDate;
2015-10-11 18:53:22 +02:00
struct Sta_Hits Hits;
2014-12-01 23:55:08 +01:00
MYSQL_ROW row;
/***** Initialize LastDate *****/
2016-09-12 00:50:24 +02:00
Dat_AssignDate (&LastDate,&Gbl.DateRange.DateEnd.Date);
2014-12-01 23:55:08 +01:00
/***** Write heading *****/
fprintf (Gbl.F.Out,"<tr>"
2015-11-12 01:27:33 +01:00
"<th class=\"LEFT_TOP\">"
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"LEFT_TOP\">"
2014-12-25 12:54:21 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2014-12-01 23:55:08 +01:00
"</tr>",
Txt_Month,
Txt_STAT_TYPE_COUNT_CAPS[Gbl.Stat.CountType]);
/***** Compute maximum number of pages generated per month *****/
2015-10-11 18:53:22 +02:00
Sta_ComputeMaxAndTotalHits (&Hits,NumRows,mysql_res,1,1);
2014-12-01 23:55:08 +01:00
/***** Write rows *****/
mysql_data_seek (mysql_res,0);
for (NumRow = 1;
NumRow <= NumRows;
NumRow++)
{
row = mysql_fetch_row (mysql_res);
/* Get the year and the month (in row[0] is the date in YYYYMM format) */
if (sscanf (row[0],"%04u%02u",&ReadDate.Year,&ReadDate.Month) != 2)
Lay_ShowErrorAndExit ("Wrong date.");
/* Get number of pages generated (in row[1]) */
2015-10-11 18:53:22 +02:00
Hits.Num = Str_GetFloatNumFromStr (row[1]);
2014-12-01 23:55:08 +01:00
Dat_AssignDate (&Date,&LastDate);
2018-10-07 14:01:25 +02:00
NumMonthsBetweenLastDateAndCurDate = Dat_GetNumMonthsBetweenDates (&ReadDate,
&LastDate);
2014-12-01 23:55:08 +01:00
for (M = 1;
2018-10-07 14:01:25 +02:00
M <= NumMonthsBetweenLastDateAndCurDate;
2014-12-01 23:55:08 +01:00
M++)
{
/* Write the month */
fprintf (Gbl.F.Out,"<tr>"
2015-11-12 01:27:33 +01:00
"<td class=\"LOG LEFT_TOP\">"
2015-10-31 02:11:38 +01:00
"%04u-%02u&nbsp;"
2014-12-25 12:54:21 +01:00
"</td>",
2015-10-31 02:11:38 +01:00
Date.Year,Date.Month);
2014-12-01 23:55:08 +01:00
2018-10-07 14:01:25 +02:00
/* Draw bar proportional to number of hits */
2018-10-07 15:13:24 +02:00
Sta_DrawBarNumHits ('o', // orange background
2018-10-07 14:01:25 +02:00
M == NumMonthsBetweenLastDateAndCurDate ? Hits.Num :
0.0,
2015-10-11 18:53:22 +02:00
Hits.Max,Hits.Total,500);
2014-12-01 23:55:08 +01:00
/* Decrease month */
Dat_GetMonthBefore (&Date,&Date);
}
Dat_AssignDate (&LastDate,&Date);
}
/***** Finally, show the oldest months without clicks *****/
2018-10-07 14:01:25 +02:00
NumMonthsBetweenLastDateAndCurDate = Dat_GetNumMonthsBetweenDates (&Gbl.DateRange.DateIni.Date,
&LastDate);
2014-12-01 23:55:08 +01:00
for (M = 1;
2018-10-07 14:01:25 +02:00
M <= NumMonthsBetweenLastDateAndCurDate;
2014-12-01 23:55:08 +01:00
M++)
{
/* Write the month */
fprintf (Gbl.F.Out,"<tr>"
2015-11-12 01:27:33 +01:00
"<td class=\"LOG LEFT_TOP\">"
2015-10-31 02:11:38 +01:00
"%04u-%02u&nbsp;"
2014-12-25 12:54:21 +01:00
"</td>",
2015-10-31 02:11:38 +01:00
Date.Year,Date.Month);
2014-12-01 23:55:08 +01:00
2018-10-07 14:01:25 +02:00
/* Draw bar proportional to number of hits */
2018-10-07 15:13:24 +02:00
Sta_DrawBarNumHits ('o', // orange background
0.0,Hits.Max,Hits.Total,500);
2014-12-01 23:55:08 +01:00
/* Decrease month */
Dat_GetMonthBefore (&Date,&Date);
}
}
2018-10-07 14:01:25 +02:00
/*****************************************************************************/
/*********** Show a graph with the number of clicks in each year *************/
/*****************************************************************************/
static void Sta_ShowNumHitsPerYear (unsigned long NumRows,
MYSQL_RES *mysql_res)
{
extern const char *Txt_Year;
extern const char *Txt_STAT_TYPE_COUNT_CAPS[Sta_NUM_COUNT_TYPES];
unsigned long NumRow;
struct Date ReadDate;
struct Date LastDate;
struct Date Date;
unsigned Y;
unsigned NumYearsBetweenLastDateAndCurDate;
struct Sta_Hits Hits;
MYSQL_ROW row;
/***** Initialize LastDate *****/
Dat_AssignDate (&LastDate,&Gbl.DateRange.DateEnd.Date);
/***** Write heading *****/
fprintf (Gbl.F.Out,"<tr>"
"<th class=\"LEFT_TOP\">"
"%s"
"</th>"
"<th class=\"LEFT_TOP\">"
"%s"
"</th>"
"</tr>",
Txt_Year,
Txt_STAT_TYPE_COUNT_CAPS[Gbl.Stat.CountType]);
/***** Compute maximum number of pages generated per year *****/
Sta_ComputeMaxAndTotalHits (&Hits,NumRows,mysql_res,1,1);
/***** Write rows *****/
mysql_data_seek (mysql_res,0);
for (NumRow = 1;
NumRow <= NumRows;
NumRow++)
{
row = mysql_fetch_row (mysql_res);
/* Get the year (in row[0] is the date in YYYY format) */
if (sscanf (row[0],"%04u",&ReadDate.Year) != 1)
Lay_ShowErrorAndExit ("Wrong date.");
/* Get number of pages generated (in row[1]) */
Hits.Num = Str_GetFloatNumFromStr (row[1]);
Dat_AssignDate (&Date,&LastDate);
NumYearsBetweenLastDateAndCurDate = Dat_GetNumYearsBetweenDates (&ReadDate,
&LastDate);
for (Y = 1;
Y <= NumYearsBetweenLastDateAndCurDate;
Y++)
{
/* Write the year */
fprintf (Gbl.F.Out,"<tr>"
"<td class=\"LOG LEFT_TOP\">"
"%04u&nbsp;"
"</td>",
Date.Year);
/* Draw bar proportional to number of hits */
2018-10-07 15:13:24 +02:00
Sta_DrawBarNumHits ('o', // orange background
2018-10-07 14:01:25 +02:00
Y == NumYearsBetweenLastDateAndCurDate ? Hits.Num :
0.0,
Hits.Max,Hits.Total,500);
/* Decrease year */
Dat_GetYearBefore (&Date,&Date);
}
Dat_AssignDate (&LastDate,&Date);
}
/***** Finally, show the oldest years without clicks *****/
NumYearsBetweenLastDateAndCurDate = Dat_GetNumYearsBetweenDates (&Gbl.DateRange.DateIni.Date,
&LastDate);
for (Y = 1;
Y <= NumYearsBetweenLastDateAndCurDate;
Y++)
{
/* Write the year */
fprintf (Gbl.F.Out,"<tr>"
"<td class=\"LOG LEFT_TOP\">"
"%04u&nbsp;"
"</td>",
Date.Year);
/* Draw bar proportional to number of hits */
2018-10-07 15:13:24 +02:00
Sta_DrawBarNumHits ('o', // orange background
0.0,Hits.Max,Hits.Total,500);
2018-10-07 14:01:25 +02:00
/* Decrease year */
Dat_GetYearBefore (&Date,&Date);
}
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/**************** Show graphic of number of pages generated per hour ***************/
/*****************************************************************************/
2015-09-28 18:28:29 +02:00
#define DIGIT_WIDTH 6
2014-12-01 23:55:08 +01:00
2015-10-11 14:12:20 +02:00
static void Sta_ShowNumHitsPerHour (unsigned long NumRows,
MYSQL_RES *mysql_res)
2014-12-01 23:55:08 +01:00
{
unsigned long NumRow;
2015-10-11 18:53:22 +02:00
struct Sta_Hits Hits;
2014-12-01 23:55:08 +01:00
unsigned NumDays;
2015-10-11 14:12:20 +02:00
unsigned Hour = 0;
unsigned ReadHour = 0;
unsigned H;
unsigned NumDigits;
unsigned ColumnWidth;
2014-12-01 23:55:08 +01:00
MYSQL_ROW row;
2015-10-27 19:00:21 +01:00
if ((NumDays = Dat_GetNumDaysBetweenDates (&Gbl.DateRange.DateIni.Date,&Gbl.DateRange.DateEnd.Date)))
2014-12-01 23:55:08 +01:00
{
/***** Compute maximum number of pages generated per hour *****/
2015-10-11 18:53:22 +02:00
Sta_ComputeMaxAndTotalHits (&Hits,NumRows,mysql_res,1,NumDays);
2014-12-01 23:55:08 +01:00
/***** Compute width of columns (one for each hour) *****/
/* Maximum number of d<>gits. If less than 4, set it to 4 to ensure a minimum width */
2015-10-11 18:53:22 +02:00
NumDigits = (Hits.Max >= 1000) ? (unsigned) floor (log10 ((double) Hits.Max)) + 1 :
4;
2015-09-28 18:28:29 +02:00
ColumnWidth = NumDigits * DIGIT_WIDTH + 2;
2014-12-01 23:55:08 +01:00
/***** Draw the graphic *****/
2017-04-25 14:48:47 +02:00
mysql_data_seek (mysql_res,0);
2014-12-01 23:55:08 +01:00
NumRow = 1;
fprintf (Gbl.F.Out,"<tr>");
while (Hour < 24)
{
2015-10-11 18:53:22 +02:00
Hits.Num = 0.0;
2014-12-01 23:55:08 +01:00
if (NumRow <= NumRows) // If not read yet all the results of the query
{
row = mysql_fetch_row (mysql_res); // Get next result
NumRow++;
if (sscanf (row[0],"%02u",&ReadHour) != 1) // In row[0] is the date in HH format
Lay_ShowErrorAndExit ("Wrong hour.");
2015-10-11 18:53:22 +02:00
2014-12-01 23:55:08 +01:00
for (H = Hour;
H < ReadHour;
H++, Hour++)
2015-10-11 18:53:22 +02:00
Sta_WriteAccessHour (H,&Hits,ColumnWidth);
Hits.Num = Str_GetFloatNumFromStr (row[1]) / (float) NumDays;
Sta_WriteAccessHour (ReadHour,&Hits,ColumnWidth);
2014-12-01 23:55:08 +01:00
Hour++;
}
else
for (H = ReadHour + 1;
H < 24;
H++, Hour++)
2015-10-11 18:53:22 +02:00
Sta_WriteAccessHour (H,&Hits,ColumnWidth);
2014-12-01 23:55:08 +01:00
}
fprintf (Gbl.F.Out,"</tr>");
}
}
/*****************************************************************************/
/**** Write a column of the graphic of the number of clicks in each hour *****/
/*****************************************************************************/
2015-10-11 18:53:22 +02:00
static void Sta_WriteAccessHour (unsigned Hour,struct Sta_Hits *Hits,unsigned ColumnWidth)
2014-12-01 23:55:08 +01:00
{
2015-09-23 14:31:47 +02:00
unsigned BarHeight;
2014-12-01 23:55:08 +01:00
2015-08-24 12:29:00 +02:00
fprintf (Gbl.F.Out,"<td class=\"DAT_SMALL CENTER_BOTTOM\""
2015-09-24 18:02:21 +02:00
" style=\"width:%upx;\">",
2014-12-01 23:55:08 +01:00
ColumnWidth);
/* Draw bar with a height porportional to the number of clicks */
2015-10-11 18:53:22 +02:00
if (Hits->Num > 0.0)
2014-12-01 23:55:08 +01:00
{
fprintf (Gbl.F.Out,"%u%%<br />",
2015-10-11 18:53:22 +02:00
(unsigned) (((Hits->Num * 100.0) /
Hits->Total) + 0.5));
2016-10-03 14:12:01 +02:00
Str_WriteFloatNum (Gbl.F.Out,Hits->Num);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"<br />");
2015-10-11 18:53:22 +02:00
BarHeight = (unsigned) (((Hits->Num * 500.0) / Hits->Max) + 0.5);
2015-09-23 14:31:47 +02:00
if (BarHeight == 0)
BarHeight = 1;
2018-10-07 15:13:24 +02:00
fprintf (Gbl.F.Out,"<img src=\"%s/o1x1.png\"" // Orange background
2015-07-22 18:59:44 +02:00
" alt=\"\" title=\"\""
2018-10-07 15:25:57 +02:00
" style=\"width:10px; height:%upx;\" />",
2019-03-20 01:36:36 +01:00
Cfg_URL_ICON_PUBLIC,BarHeight);
2014-12-01 23:55:08 +01:00
}
else
2015-09-05 19:19:39 +02:00
fprintf (Gbl.F.Out,"0%%<br />0");
2014-12-01 23:55:08 +01:00
/* Write the hour */
2015-09-05 19:19:39 +02:00
fprintf (Gbl.F.Out,"<br />%uh</td>",Hour);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/**** Show a listing with the number of clicks in every minute of the day ***/
/*****************************************************************************/
2017-01-28 15:58:46 +01:00
#define Sta_NUM_MINUTES_PER_DAY (60 * 24) // 1440 minutes in a day
#define Sta_WIDTH_SEMIDIVISION_GRAPHIC 30
#define Sta_NUM_DIVISIONS_X 10
2014-12-01 23:55:08 +01:00
static void Sta_ShowAverageAccessesPerMinute (unsigned long NumRows,MYSQL_RES *mysql_res)
{
2015-10-11 14:12:20 +02:00
unsigned long NumRow = 1;
2014-12-01 23:55:08 +01:00
MYSQL_ROW row;
unsigned NumDays;
2015-10-11 14:12:20 +02:00
unsigned MinuteDay = 0;
unsigned ReadHour;
unsigned MinuteRead;
unsigned MinuteDayRead = 0;
unsigned i;
2015-10-11 18:53:22 +02:00
struct Sta_Hits Hits;
2017-01-28 15:58:46 +01:00
float NumClicksPerMin[Sta_NUM_MINUTES_PER_DAY];
2015-10-11 14:12:20 +02:00
float Power10LeastOrEqual;
float MaxX;
float IncX;
2014-12-01 23:55:08 +01:00
char *Format;
2015-10-27 19:00:21 +01:00
if ((NumDays = Dat_GetNumDaysBetweenDates (&Gbl.DateRange.DateIni.Date,&Gbl.DateRange.DateEnd.Date)))
2014-12-01 23:55:08 +01:00
{
/***** Compute number of clicks (and m<>ximo) in every minute *****/
2015-10-11 18:53:22 +02:00
Hits.Max = 0.0;
2017-01-28 15:58:46 +01:00
while (MinuteDay < Sta_NUM_MINUTES_PER_DAY)
2014-12-01 23:55:08 +01:00
{
if (NumRow <= NumRows) // If not all the result of the query are yet read
{
row = mysql_fetch_row (mysql_res); // Get next result
NumRow++;
if (sscanf (row[0],"%02u%02u",&ReadHour,&MinuteRead) != 2) // In row[0] is the date in formato HHMM
Lay_ShowErrorAndExit ("Wrong hour-minute.");
/* Get number of pages generated */
2015-10-11 18:53:22 +02:00
Hits.Num = Str_GetFloatNumFromStr (row[1]);
2015-10-11 14:12:20 +02:00
MinuteDayRead = ReadHour * 60 + MinuteRead;
2014-12-01 23:55:08 +01:00
for (i = MinuteDay;
i < MinuteDayRead;
i++, MinuteDay++)
NumClicksPerMin[i] = 0.0;
2015-10-11 18:53:22 +02:00
NumClicksPerMin[MinuteDayRead] = Hits.Num / (float) NumDays;
if (NumClicksPerMin[MinuteDayRead] > Hits.Max)
Hits.Max = NumClicksPerMin[MinuteDayRead];
2014-12-01 23:55:08 +01:00
MinuteDay++;
}
else
for (i = MinuteDayRead + 1;
2017-01-28 15:58:46 +01:00
i < Sta_NUM_MINUTES_PER_DAY;
2014-12-01 23:55:08 +01:00
i++, MinuteDay++)
NumClicksPerMin[i] = 0.0;
}
/***** Compute the maximum value of X and the increment of the X axis *****/
2015-10-11 18:53:22 +02:00
if (Hits.Max <= 0.000001)
2014-12-01 23:55:08 +01:00
MaxX = 0.000001;
else
{
2015-10-11 18:53:22 +02:00
Power10LeastOrEqual = (float) pow (10.0,floor (log10 ((double) Hits.Max)));
MaxX = ceil (Hits.Max / Power10LeastOrEqual) * Power10LeastOrEqual;
2014-12-01 23:55:08 +01:00
}
2017-01-28 15:58:46 +01:00
IncX = MaxX / (float) Sta_NUM_DIVISIONS_X;
2014-12-01 23:55:08 +01:00
if (IncX >= 1.0)
Format = "%.0f";
else if (IncX >= 0.1)
Format = "%.1f";
else if (IncX >= 0.01)
Format = "%.2f";
else if (IncX >= 0.001)
Format = "%.3f";
else
Format = "%f";
2014-12-21 01:58:30 +01:00
/***** X axis tags *****/
2014-12-01 23:55:08 +01:00
Sta_WriteLabelsXAxisAccMin (IncX,Format);
2014-12-21 01:58:30 +01:00
/***** Y axis and graphic *****/
2014-12-01 23:55:08 +01:00
for (i = 0;
2017-01-28 15:58:46 +01:00
i < Sta_NUM_MINUTES_PER_DAY;
2014-12-01 23:55:08 +01:00
i++)
Sta_WriteAccessMinute (i,NumClicksPerMin[i],MaxX);
2014-12-21 01:58:30 +01:00
/***** X axis *****/
2014-12-01 23:55:08 +01:00
/* First division (left) */
fprintf (Gbl.F.Out,"<tr>"
2015-09-24 18:02:21 +02:00
"<td class=\"LEFT_MIDDLE\" style=\"width:%upx;\">"
2015-07-22 18:59:44 +02:00
"<img src=\"%s/ejexizq24x1.gif\""
" alt=\"\" title=\"\""
2015-09-24 18:02:21 +02:00
" style=\"display:block; width:%upx; height:1px;\" />"
2014-12-01 23:55:08 +01:00
"</td>",
2019-03-20 01:36:36 +01:00
Sta_WIDTH_SEMIDIVISION_GRAPHIC,Cfg_URL_ICON_PUBLIC,
2017-01-28 15:58:46 +01:00
Sta_WIDTH_SEMIDIVISION_GRAPHIC);
2014-12-01 23:55:08 +01:00
/* All the intermediate divisions */
for (i = 0;
2017-01-28 15:58:46 +01:00
i < Sta_NUM_DIVISIONS_X * 2;
2014-12-01 23:55:08 +01:00
i++)
2015-09-24 18:02:21 +02:00
fprintf (Gbl.F.Out,"<td class=\"LEFT_MIDDLE\" style=\"width:%upx;\">"
2015-07-22 18:59:44 +02:00
"<img src=\"%s/ejex24x1.gif\""
" alt=\"\" title=\"\""
2014-12-30 15:14:43 +01:00
" style=\"display:block;"
2015-09-24 18:02:21 +02:00
" width:%upx; height:1px;\" />"
2014-12-01 23:55:08 +01:00
"</td>",
2019-03-20 01:36:36 +01:00
Sta_WIDTH_SEMIDIVISION_GRAPHIC,Cfg_URL_ICON_PUBLIC,
2017-01-28 15:58:46 +01:00
Sta_WIDTH_SEMIDIVISION_GRAPHIC);
2014-12-01 23:55:08 +01:00
/* Last division (right) */
2015-09-24 18:02:21 +02:00
fprintf (Gbl.F.Out,"<td class=\"LEFT_MIDDLE\" style=\"width:%upx;\">"
2015-07-22 18:59:44 +02:00
"<img src=\"%s/tr24x1.gif\""
" alt=\"\" title=\"\""
2015-09-24 18:02:21 +02:00
" style=\"display:block; width:%upx; height:1px;\" />"
2014-12-01 23:55:08 +01:00
"</td>"
"</tr>",
2019-03-20 01:36:36 +01:00
Sta_WIDTH_SEMIDIVISION_GRAPHIC,Cfg_URL_ICON_PUBLIC,
2017-01-28 15:58:46 +01:00
Sta_WIDTH_SEMIDIVISION_GRAPHIC);
2014-12-01 23:55:08 +01:00
/***** Write again the labels of the X axis *****/
Sta_WriteLabelsXAxisAccMin (IncX,Format);
}
}
/*****************************************************************************/
/****** Write labels of the X axis in the graphic of clicks per minute *******/
/*****************************************************************************/
2017-01-28 15:58:46 +01:00
#define Sta_WIDTH_DIVISION_GRAPHIC (Sta_WIDTH_SEMIDIVISION_GRAPHIC * 2) // 60
2014-12-01 23:55:08 +01:00
static void Sta_WriteLabelsXAxisAccMin (float IncX,const char *Format)
{
unsigned i;
float NumX;
fprintf (Gbl.F.Out,"<tr>");
for (i = 0, NumX = 0;
2017-01-28 15:58:46 +01:00
i <= Sta_NUM_DIVISIONS_X;
2014-12-01 23:55:08 +01:00
i++, NumX += IncX)
{
2015-08-24 12:29:00 +02:00
fprintf (Gbl.F.Out,"<td colspan=\"2\" class=\"LOG CENTER_BOTTOM\""
2015-09-24 18:02:21 +02:00
" style=\"width:%upx;\">",
2017-01-28 15:58:46 +01:00
Sta_WIDTH_DIVISION_GRAPHIC);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,Format,NumX);
fprintf (Gbl.F.Out,"</td>");
}
fprintf (Gbl.F.Out,"</tr>");
}
/*****************************************************************************/
/***** Write a row of the graphic with number of clicks in every minute ******/
/*****************************************************************************/
2017-01-28 15:58:46 +01:00
#define Sta_WIDTH_GRAPHIC (Sta_WIDTH_DIVISION_GRAPHIC * Sta_NUM_DIVISIONS_X) // 60 * 10 = 600
2014-12-01 23:55:08 +01:00
2015-10-11 18:53:22 +02:00
static void Sta_WriteAccessMinute (unsigned Minute,float HitsNum,float MaxX)
2014-12-01 23:55:08 +01:00
{
unsigned BarWidth;
/***** Start row *****/
fprintf (Gbl.F.Out,"<tr>");
/***** Labels of the Y axis, and Y axis *****/
2014-12-25 12:54:21 +01:00
if (!Minute)
// If minute 0
2015-08-24 12:29:00 +02:00
fprintf (Gbl.F.Out,"<td rowspan=\"30\" class=\"LOG LEFT_TOP\""
2015-09-24 18:02:21 +02:00
" style=\"width:%upx;"
2014-12-25 12:54:21 +01:00
" background-image:url('%s/ejey24x30.gif');"
2015-09-28 18:28:29 +02:00
" background-size:30px 30px;"
2014-12-25 12:54:21 +01:00
" background-repeat:repeat;\">"
"00h"
"</td>",
2019-03-20 01:36:36 +01:00
Sta_WIDTH_SEMIDIVISION_GRAPHIC,Cfg_URL_ICON_PUBLIC);
2017-01-28 15:58:46 +01:00
else if (Minute == (Sta_NUM_MINUTES_PER_DAY - 30))
2014-12-25 12:54:21 +01:00
// If 23:30
2015-08-24 12:29:00 +02:00
fprintf (Gbl.F.Out,"<td rowspan=\"30\" class=\"LOG LEFT_BOTTOM\""
2015-09-24 18:02:21 +02:00
" style=\"width:%upx;"
2014-12-25 12:54:21 +01:00
" background-image:url('%s/ejey24x30.gif');"
2015-09-28 18:28:29 +02:00
" background-size:30px 30px;"
2014-12-25 12:54:21 +01:00
" background-repeat:repeat;\">"
"24h"
"</td>",
2019-03-20 01:36:36 +01:00
Sta_WIDTH_SEMIDIVISION_GRAPHIC,Cfg_URL_ICON_PUBLIC);
2014-12-25 12:54:21 +01:00
else if (!(Minute % 30) && (Minute % 60))
// If minute is multiple of 30 but not of 60 (i.e.: 30, 90, 150...)
2015-08-24 12:29:00 +02:00
fprintf (Gbl.F.Out,"<td rowspan=\"60\" class=\"LOG LEFT_MIDDLE\""
2015-09-24 18:02:21 +02:00
" style=\"width:%upx;"
2014-12-25 12:54:21 +01:00
" background-image:url('%s/ejey24x60.gif');"
2015-09-28 18:28:29 +02:00
" background-size:30px 60px;"
2014-12-25 12:54:21 +01:00
" background-repeat:repeat;\">"
"%02uh"
"</td>",
2019-03-20 01:36:36 +01:00
Sta_WIDTH_SEMIDIVISION_GRAPHIC,Cfg_URL_ICON_PUBLIC,(Minute + 30) / 60);
2014-12-01 23:55:08 +01:00
2017-06-12 14:16:33 +02:00
/***** Start cell for the graphic *****/
2015-08-24 12:29:00 +02:00
fprintf (Gbl.F.Out,"<td colspan=\"%u\" class=\"LEFT_BOTTOM\""
2015-09-24 18:02:21 +02:00
" style=\"width:%upx; height:1px;"
2015-01-13 14:19:08 +01:00
" background-image:url('%s/malla%c48x1.gif');"
2015-09-28 18:28:29 +02:00
" background-size:60px 1px;"
2015-01-13 14:19:08 +01:00
" background-repeat:repeat;\">",
2019-03-20 01:36:36 +01:00
Sta_NUM_DIVISIONS_X * 2,Sta_WIDTH_GRAPHIC,Cfg_URL_ICON_PUBLIC,
2014-12-01 23:55:08 +01:00
(Minute % 60) == 0 ? 'v' :
'h');
2018-10-07 15:13:24 +02:00
/***** Draw bar with a width proportional to the number of hits *****/
2015-10-11 18:53:22 +02:00
if (HitsNum != 0.0)
2017-01-28 15:58:46 +01:00
if ((BarWidth = (unsigned) (((HitsNum * (float) Sta_WIDTH_GRAPHIC / MaxX)) + 0.5)) != 0)
2018-10-07 15:13:24 +02:00
fprintf (Gbl.F.Out,"<img src=\"%s/%c1x1.png\""
2015-07-22 18:59:44 +02:00
" alt=\"\" title=\"\""
2014-12-30 15:14:43 +01:00
" style=\"display:block;"
2015-09-24 18:02:21 +02:00
" width:%upx; height:1px;\" />",
2019-03-20 01:36:36 +01:00
Cfg_URL_ICON_PUBLIC,
2018-10-07 15:13:24 +02:00
(Minute % 60) == 0 ? 'r' : // red background
'o', // orange background
2014-12-01 23:55:08 +01:00
BarWidth);
2017-06-12 14:16:33 +02:00
/***** End cell of graphic and end row *****/
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"</td>"
"</tr>");
}
/*****************************************************************************/
/**** Show a listing of accesses with the number of clicks a each action *****/
/*****************************************************************************/
2015-10-11 14:12:20 +02:00
static void Sta_ShowNumHitsPerAction (unsigned long NumRows,
MYSQL_RES *mysql_res)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_Action;
2015-09-25 01:48:00 +02:00
extern const char *Txt_STAT_TYPE_COUNT_CAPS[Sta_NUM_COUNT_TYPES];
2014-12-01 23:55:08 +01:00
unsigned long NumRow;
2015-10-11 18:53:22 +02:00
struct Sta_Hits Hits;
2014-12-01 23:55:08 +01:00
MYSQL_ROW row;
long ActCod;
2017-03-07 01:56:41 +01:00
char ActTxt[Act_MAX_BYTES_ACTION_TXT + 1];
2014-12-01 23:55:08 +01:00
/***** Write heading *****/
fprintf (Gbl.F.Out,"<tr>"
2015-09-06 20:02:14 +02:00
"<th class=\"RIGHT_TOP\">"
2015-11-12 01:27:33 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"LEFT_TOP\">"
2014-12-25 12:54:21 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2014-12-01 23:55:08 +01:00
"</tr>",
Txt_Action,
Txt_STAT_TYPE_COUNT_CAPS[Gbl.Stat.CountType]);
/***** Compute maximum number of pages generated per day *****/
2015-10-11 18:53:22 +02:00
Sta_ComputeMaxAndTotalHits (&Hits,NumRows,mysql_res,1,1);
2014-12-01 23:55:08 +01:00
/***** Write rows *****/
2017-04-25 14:48:47 +02:00
mysql_data_seek (mysql_res,0);
2014-12-01 23:55:08 +01:00
for (NumRow = 1;
NumRow <= NumRows;
NumRow++)
{
row = mysql_fetch_row (mysql_res);
/* Write the action */
2016-10-08 20:25:26 +02:00
ActCod = Str_ConvertStrCodToLongCod (row[0]);
2014-12-01 23:55:08 +01:00
if (ActCod >= 0)
fprintf (Gbl.F.Out,"<tr>"
2015-08-24 12:29:00 +02:00
"<td class=\"LOG RIGHT_TOP\">"
2014-12-25 12:54:21 +01:00
"%s&nbsp;"
"</td>",
2014-12-01 23:55:08 +01:00
Act_GetActionTextFromDB (ActCod,ActTxt));
else
fprintf (Gbl.F.Out,"<tr>"
2015-08-24 12:29:00 +02:00
"<td class=\"LOG RIGHT_TOP\">"
2014-12-25 12:54:21 +01:00
"?&nbsp;"
"</td>");
2014-12-01 23:55:08 +01:00
2018-10-07 14:01:25 +02:00
/* Draw bar proportional to number of hits */
2015-10-11 18:53:22 +02:00
Hits.Num = Str_GetFloatNumFromStr (row[1]);
2018-10-07 15:13:24 +02:00
Sta_DrawBarNumHits ('o', // orange background
Hits.Num,Hits.Max,Hits.Total,500);
2014-12-01 23:55:08 +01:00
}
}
/*****************************************************************************/
/*************** Show number of clicks distributed by plugin *****************/
/*****************************************************************************/
2015-10-11 14:12:20 +02:00
static void Sta_ShowNumHitsPerPlugin (unsigned long NumRows,
MYSQL_RES *mysql_res)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_Plugin;
2015-09-25 01:48:00 +02:00
extern const char *Txt_STAT_TYPE_COUNT_CAPS[Sta_NUM_COUNT_TYPES];
2014-12-01 23:55:08 +01:00
unsigned long NumRow;
2015-10-11 18:53:22 +02:00
struct Sta_Hits Hits;
2014-12-01 23:55:08 +01:00
MYSQL_ROW row;
struct Plugin Plg;
/***** Write heading *****/
fprintf (Gbl.F.Out,"<tr>"
2015-09-06 20:02:14 +02:00
"<th class=\"RIGHT_TOP\">"
2015-11-12 01:27:33 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"LEFT_TOP\">"
2014-12-25 12:54:21 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2014-12-01 23:55:08 +01:00
"</tr>",
Txt_Plugin,
Txt_STAT_TYPE_COUNT_CAPS[Gbl.Stat.CountType]);
/***** Compute maximum number of pages generated per plugin *****/
2015-10-11 18:53:22 +02:00
Sta_ComputeMaxAndTotalHits (&Hits,NumRows,mysql_res,1,1);
2014-12-01 23:55:08 +01:00
/***** Write rows *****/
2017-04-25 14:48:47 +02:00
mysql_data_seek (mysql_res,0);
2014-12-01 23:55:08 +01:00
for (NumRow = 1;
NumRow <= NumRows;
NumRow++)
{
row = mysql_fetch_row (mysql_res);
/* Write the plugin */
if (sscanf (row[0],"%ld",&Plg.PlgCod) != 1)
Lay_ShowErrorAndExit ("Wrong plugin code.");
fprintf (Gbl.F.Out,"<tr>"
2015-08-24 12:29:00 +02:00
"<td class=\"LOG RIGHT_TOP\">");
2014-12-01 23:55:08 +01:00
if (Plg_GetDataOfPluginByCod (&Plg))
fprintf (Gbl.F.Out,"%s",Plg.Name);
else
fprintf (Gbl.F.Out,"?");
fprintf (Gbl.F.Out,"&nbsp;</td>");
2018-10-07 14:01:25 +02:00
/* Draw bar proportional to number of hits */
2015-10-11 18:53:22 +02:00
Hits.Num = Str_GetFloatNumFromStr (row[1]);
2018-10-07 15:13:24 +02:00
Sta_DrawBarNumHits ('o', // orange background
Hits.Num,Hits.Max,Hits.Total,500);
2014-12-01 23:55:08 +01:00
}
}
/*****************************************************************************/
/******** Show number of clicks distributed by web service function **********/
/*****************************************************************************/
2015-10-11 14:12:20 +02:00
static void Sta_ShowNumHitsPerWSFunction (unsigned long NumRows,
MYSQL_RES *mysql_res)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_Function;
2015-09-25 01:48:00 +02:00
extern const char *Txt_STAT_TYPE_COUNT_CAPS[Sta_NUM_COUNT_TYPES];
2014-12-01 23:55:08 +01:00
unsigned long NumRow;
2015-10-11 18:53:22 +02:00
struct Sta_Hits Hits;
2014-12-01 23:55:08 +01:00
MYSQL_ROW row;
long FunCod;
/***** Write heading *****/
fprintf (Gbl.F.Out,"<tr>"
2015-09-06 20:02:14 +02:00
"<th class=\"LEFT_TOP\">"
2015-11-12 01:27:33 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"LEFT_TOP\">"
2014-12-25 12:54:21 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2014-12-01 23:55:08 +01:00
"</tr>",
Txt_Function,
Txt_STAT_TYPE_COUNT_CAPS[Gbl.Stat.CountType]);
/***** Compute maximum number of pages generated per function *****/
2015-10-11 18:53:22 +02:00
Sta_ComputeMaxAndTotalHits (&Hits,NumRows,mysql_res,1,1);
2014-12-01 23:55:08 +01:00
/***** Write rows *****/
2017-04-25 14:48:47 +02:00
mysql_data_seek (mysql_res,0);
2014-12-01 23:55:08 +01:00
for (NumRow = 1;
NumRow <= NumRows;
NumRow++)
{
row = mysql_fetch_row (mysql_res);
/* Write the plugin */
if (sscanf (row[0],"%ld",&FunCod) != 1)
Lay_ShowErrorAndExit ("Wrong function code.");
fprintf (Gbl.F.Out,"<tr>"
2015-08-24 12:29:00 +02:00
"<td class=\"LOG LEFT_TOP\">"
2014-12-25 12:54:21 +01:00
"%s&nbsp;"
"</td>",
2014-12-01 23:55:08 +01:00
Svc_GetFunctionNameFromFunCod (FunCod));
2018-10-07 14:01:25 +02:00
/* Draw bar proportional to number of hits */
2015-10-11 18:53:22 +02:00
Hits.Num = Str_GetFloatNumFromStr (row[1]);
2018-10-07 15:13:24 +02:00
Sta_DrawBarNumHits ('o', // orange background
Hits.Num,Hits.Max,Hits.Total,500);
2014-12-01 23:55:08 +01:00
}
}
/*****************************************************************************/
/******** Show number of clicks distributed by web service function **********/
/*****************************************************************************/
2015-10-11 14:12:20 +02:00
static void Sta_ShowNumHitsPerBanner (unsigned long NumRows,
MYSQL_RES *mysql_res)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_Banner;
2015-09-25 01:48:00 +02:00
extern const char *Txt_STAT_TYPE_COUNT_CAPS[Sta_NUM_COUNT_TYPES];
2014-12-01 23:55:08 +01:00
unsigned long NumRow;
float NumClicks;
float MaxClicks = 0.0;
float TotalClicks = 0.0;
MYSQL_ROW row;
struct Banner Ban;
/***** Write heading *****/
fprintf (Gbl.F.Out,"<tr>"
2015-09-06 20:02:14 +02:00
"<th class=\"CENTER_TOP\">"
2015-11-12 01:27:33 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"LEFT_TOP\">"
2014-12-25 12:54:21 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2014-12-01 23:55:08 +01:00
"</tr>",
Txt_Banner,
Txt_STAT_TYPE_COUNT_CAPS[Gbl.Stat.CountType]);
/***** Compute maximum number of clicks per banner *****/
for (NumRow = 1;
NumRow <= NumRows;
NumRow++)
{
row = mysql_fetch_row (mysql_res);
/* Get number of pages generated */
NumClicks = Str_GetFloatNumFromStr (row[1]);
if (NumRow == 1)
MaxClicks = NumClicks;
TotalClicks += NumClicks;
}
/***** Write rows *****/
2017-04-25 14:48:47 +02:00
mysql_data_seek (mysql_res,0);
2014-12-01 23:55:08 +01:00
for (NumRow = 1;
NumRow <= NumRows;
NumRow++)
{
row = mysql_fetch_row (mysql_res);
/* Write the banner */
if (sscanf (row[0],"%ld",&(Ban.BanCod)) != 1)
Lay_ShowErrorAndExit ("Wrong banner code.");
Ban_GetDataOfBannerByCod (&Ban);
fprintf (Gbl.F.Out,"<tr>"
2015-08-24 12:29:00 +02:00
"<td class=\"LOG LEFT_TOP\">"
2014-12-01 23:55:08 +01:00
"<a href=\"%s\" title=\"%s\" class=\"DAT\" target=\"_blank\">"
2019-03-20 01:36:36 +01:00
"<img src=\"%s/%s\""
2015-07-22 18:59:44 +02:00
" alt=\"%s\" title=\"%s\""
2015-09-05 19:19:39 +02:00
" class=\"BANNER_SMALL\""
2015-09-28 18:28:29 +02:00
" style=\"margin:0 10px 5px 0;\" />"
2014-12-01 23:55:08 +01:00
"</a>",
Ban.WWW,
Ban.FullName,
2019-03-20 01:36:36 +01:00
Cfg_URL_BANNER_PUBLIC,
2014-12-01 23:55:08 +01:00
Ban.Img,
2016-10-28 10:03:37 +02:00
Ban.ShrtName,
2015-07-22 18:59:44 +02:00
Ban.FullName);
2014-12-01 23:55:08 +01:00
/* Draw bar proportional to number of clicks */
NumClicks = Str_GetFloatNumFromStr (row[1]);
2018-10-07 15:13:24 +02:00
Sta_DrawBarNumHits ('o', // orange background
NumClicks,MaxClicks,TotalClicks,500);
2015-10-11 14:12:20 +02:00
}
}
/*****************************************************************************/
/******* Show a listing with the number of hits distributed by country *******/
/*****************************************************************************/
static void Sta_ShowNumHitsPerCountry (unsigned long NumRows,
MYSQL_RES *mysql_res)
{
extern const char *Txt_No_INDEX;
extern const char *Txt_Country;
extern const char *Txt_STAT_TYPE_COUNT_CAPS[Sta_NUM_COUNT_TYPES];
unsigned long NumRow;
unsigned long Ranking;
2015-10-11 18:53:22 +02:00
struct Sta_Hits Hits;
2015-10-11 14:12:20 +02:00
MYSQL_ROW row;
long CtyCod;
/***** Write heading *****/
fprintf (Gbl.F.Out,"<tr>"
"<th class=\"CENTER_TOP\">"
"%s"
"</th>"
2015-11-19 20:04:41 +01:00
"<th class=\"CENTER_TOP\">"
2015-10-11 14:12:20 +02:00
"%s"
"</th>"
"<th class=\"LEFT_TOP\">"
"%s"
"</th>"
"</tr>",
Txt_No_INDEX,
Txt_Country,
Txt_STAT_TYPE_COUNT_CAPS[Gbl.Stat.CountType]);
/***** Compute maximum number of hits per country *****/
2015-10-11 18:53:22 +02:00
Sta_ComputeMaxAndTotalHits (&Hits,NumRows,mysql_res,1,1);
2015-10-11 14:12:20 +02:00
/***** Write rows *****/
2017-04-25 14:48:47 +02:00
mysql_data_seek (mysql_res,0);
2015-10-11 14:12:20 +02:00
for (NumRow = 1, Ranking = 0;
NumRow <= NumRows;
NumRow++)
{
/* Get country code */
row = mysql_fetch_row (mysql_res);
CtyCod = Str_ConvertStrCodToLongCod (row[0]);
/* Write ranking of this country */
fprintf (Gbl.F.Out,"<tr>"
2017-03-04 17:28:15 +01:00
"<td class=\"LOG RIGHT_MIDDLE\">");
2015-10-11 14:12:20 +02:00
if (CtyCod > 0)
fprintf (Gbl.F.Out,"%lu",++Ranking);
fprintf (Gbl.F.Out,"&nbsp;"
"</td>");
/* Write country */
Sta_WriteCountry (CtyCod);
/* Draw bar proportional to number of hits */
2015-10-11 18:53:22 +02:00
Hits.Num = Str_GetFloatNumFromStr (row[1]);
2018-10-07 15:13:24 +02:00
Sta_DrawBarNumHits ('o', // orange background
Hits.Num,Hits.Max,Hits.Total,375);
2015-10-11 14:12:20 +02:00
}
}
/*****************************************************************************/
/************************ Write country with an icon *************************/
/*****************************************************************************/
static void Sta_WriteCountry (long CtyCod)
{
struct Country Cty;
/***** Start cell *****/
2015-11-11 21:14:33 +01:00
fprintf (Gbl.F.Out,"<td class=\"LOG LEFT_MIDDLE\">");
2015-10-11 14:12:20 +02:00
if (CtyCod > 0) // Hit with a country selected
{
/***** Get data of country *****/
Cty.CtyCod = CtyCod;
2015-12-09 19:51:17 +01:00
Cty_GetDataOfCountryByCod (&Cty,Cty_GET_BASIC_DATA);
2015-10-11 14:12:20 +02:00
/***** Form to go to country *****/
2015-11-19 18:33:16 +01:00
Cty_DrawCountryMapAndNameWithLink (&Cty,ActSeeCtyInf,
2017-03-04 19:46:46 +01:00
"COUNTRY_TINY",
"COUNTRY_MAP_TINY",
"LOG");
2015-10-11 14:12:20 +02:00
}
else // Hit with no country selected
/***** No country selected *****/
2015-11-11 21:14:33 +01:00
fprintf (Gbl.F.Out,"&nbsp;-&nbsp;");
2015-10-11 14:12:20 +02:00
/***** End cell *****/
fprintf (Gbl.F.Out,"</td>");
}
/*****************************************************************************/
/***** Show a listing with the number of hits distributed by institution *****/
/*****************************************************************************/
static void Sta_ShowNumHitsPerInstitution (unsigned long NumRows,
MYSQL_RES *mysql_res)
{
extern const char *Txt_No_INDEX;
extern const char *Txt_Institution;
extern const char *Txt_STAT_TYPE_COUNT_CAPS[Sta_NUM_COUNT_TYPES];
unsigned long NumRow;
unsigned long Ranking;
2015-10-11 18:53:22 +02:00
struct Sta_Hits Hits;
2015-10-11 14:12:20 +02:00
MYSQL_ROW row;
long InsCod;
/***** Write heading *****/
fprintf (Gbl.F.Out,"<tr>"
"<th class=\"CENTER_TOP\">"
"%s"
"</th>"
2015-11-19 20:04:41 +01:00
"<th class=\"CENTER_TOP\">"
2015-10-11 14:12:20 +02:00
"%s"
"</th>"
"<th class=\"LEFT_TOP\">"
"%s"
"</th>"
"</tr>",
Txt_No_INDEX,
Txt_Institution,
Txt_STAT_TYPE_COUNT_CAPS[Gbl.Stat.CountType]);
/***** Compute maximum number of hits per institution *****/
2015-10-11 18:53:22 +02:00
Sta_ComputeMaxAndTotalHits (&Hits,NumRows,mysql_res,1,1);
2015-10-11 14:12:20 +02:00
/***** Write rows *****/
2017-04-25 14:48:47 +02:00
mysql_data_seek (mysql_res,0);
2015-10-11 14:12:20 +02:00
for (NumRow = 1, Ranking = 0;
NumRow <= NumRows;
NumRow++)
{
/* Get institution code */
row = mysql_fetch_row (mysql_res);
InsCod = Str_ConvertStrCodToLongCod (row[0]);
/* Write ranking of this institution */
fprintf (Gbl.F.Out,"<tr>"
"<td class=\"LOG RIGHT_TOP\">");
if (InsCod > 0)
fprintf (Gbl.F.Out,"%lu",++Ranking);
fprintf (Gbl.F.Out,"&nbsp;"
"</td>");
/* Write institution */
Sta_WriteInstitution (InsCod);
/* Draw bar proportional to number of hits */
2015-10-11 18:53:22 +02:00
Hits.Num = Str_GetFloatNumFromStr (row[1]);
2018-10-07 15:13:24 +02:00
Sta_DrawBarNumHits ('o', // orange background
Hits.Num,Hits.Max,Hits.Total,375);
2015-10-11 14:12:20 +02:00
}
}
/*****************************************************************************/
/********************** Write institution with an icon ***********************/
/*****************************************************************************/
static void Sta_WriteInstitution (long InsCod)
{
2016-10-28 10:03:37 +02:00
struct Instit Ins;
2015-10-11 14:12:20 +02:00
/***** Start cell *****/
fprintf (Gbl.F.Out,"<td class=\"LOG LEFT_MIDDLE\"");
if (InsCod > 0) // Hit with an institution selected
{
/***** Get data of institution *****/
Ins.InsCod = InsCod;
2015-12-09 19:51:17 +01:00
Ins_GetDataOfInstitutionByCod (&Ins,Ins_GET_BASIC_DATA);
2015-10-11 14:12:20 +02:00
/***** Title in cell *****/
fprintf (Gbl.F.Out,"title=\"%s\">",
Ins.FullName);
/***** Form to go to institution *****/
2015-11-19 18:33:16 +01:00
Ins_DrawInstitutionLogoAndNameWithLink (&Ins,ActSeeInsInf,
"LOG","CENTER_TOP");
2014-12-01 23:55:08 +01:00
}
2015-10-11 14:12:20 +02:00
else // Hit with no institution selected
/***** No institution selected *****/
fprintf (Gbl.F.Out,">&nbsp;-&nbsp;");
/***** End cell *****/
fprintf (Gbl.F.Out,"</td>");
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2015-10-11 14:12:20 +02:00
/******* Show a listing with the number of hits distributed by centre ********/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2015-10-11 14:12:20 +02:00
static void Sta_ShowNumHitsPerCentre (unsigned long NumRows,
MYSQL_RES *mysql_res)
{
extern const char *Txt_No_INDEX;
extern const char *Txt_Centre;
extern const char *Txt_STAT_TYPE_COUNT_CAPS[Sta_NUM_COUNT_TYPES];
unsigned long NumRow;
unsigned long Ranking;
2015-10-11 18:53:22 +02:00
struct Sta_Hits Hits;
2015-10-11 14:12:20 +02:00
MYSQL_ROW row;
long CtrCod;
/***** Write heading *****/
fprintf (Gbl.F.Out,"<tr>"
"<th class=\"CENTER_TOP\">"
"%s"
"</th>"
"<th class=\"CENTER_TOP\">"
"%s"
"</th>"
"<th class=\"LEFT_TOP\">"
"%s"
"</th>"
"</tr>",
Txt_No_INDEX,
Txt_Centre,
Txt_STAT_TYPE_COUNT_CAPS[Gbl.Stat.CountType]);
/***** Compute maximum number of hits per centre *****/
2015-10-11 18:53:22 +02:00
Sta_ComputeMaxAndTotalHits (&Hits,NumRows,mysql_res,1,1);
2015-10-11 14:12:20 +02:00
/***** Write rows *****/
2017-04-25 14:48:47 +02:00
mysql_data_seek (mysql_res,0);
2015-10-11 14:12:20 +02:00
for (NumRow = 1, Ranking = 0;
NumRow <= NumRows;
NumRow++)
{
/* Get centre code */
row = mysql_fetch_row (mysql_res);
CtrCod = Str_ConvertStrCodToLongCod (row[0]);
/* Write ranking of this centre */
fprintf (Gbl.F.Out,"<tr>"
"<td class=\"LOG RIGHT_TOP\">");
if (CtrCod > 0)
fprintf (Gbl.F.Out,"%lu",++Ranking);
fprintf (Gbl.F.Out,"&nbsp;"
"</td>");
/* Write centre */
Sta_WriteCentre (CtrCod);
/* Draw bar proportional to number of hits */
2015-10-11 18:53:22 +02:00
Hits.Num = Str_GetFloatNumFromStr (row[1]);
2018-10-07 15:13:24 +02:00
Sta_DrawBarNumHits ('o', // orange background
Hits.Num,Hits.Max,Hits.Total,375);
2015-10-11 14:12:20 +02:00
}
}
/*****************************************************************************/
/************************* Write centre with an icon *************************/
/*****************************************************************************/
static void Sta_WriteCentre (long CtrCod)
{
struct Centre Ctr;
/***** Start cell *****/
fprintf (Gbl.F.Out,"<td class=\"LOG LEFT_MIDDLE\"");
if (CtrCod > 0) // Hit with a centre selected
{
/***** Get data of centre *****/
Ctr.CtrCod = CtrCod;
Ctr_GetDataOfCentreByCod (&Ctr);
/***** Title in cell *****/
fprintf (Gbl.F.Out,"title=\"%s\">",
Ctr.FullName);
/***** Form to go to centre *****/
2015-11-19 19:37:44 +01:00
Ctr_DrawCentreLogoAndNameWithLink (&Ctr,ActSeeCtrInf,
"LOG","CENTER_TOP");
2015-10-11 14:12:20 +02:00
}
else // Hit with no centre selected
/***** No centre selected *****/
fprintf (Gbl.F.Out,">&nbsp;-&nbsp;");
/***** End cell *****/
fprintf (Gbl.F.Out,"</td>");
}
/*****************************************************************************/
/******* Show a listing with the number of hits distributed by degree ********/
/*****************************************************************************/
static void Sta_ShowNumHitsPerDegree (unsigned long NumRows,
MYSQL_RES *mysql_res)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_No_INDEX;
extern const char *Txt_Degree;
2015-09-25 01:48:00 +02:00
extern const char *Txt_STAT_TYPE_COUNT_CAPS[Sta_NUM_COUNT_TYPES];
2015-10-11 14:12:20 +02:00
unsigned long NumRow;
unsigned long Ranking;
2015-10-11 18:53:22 +02:00
struct Sta_Hits Hits;
2014-12-01 23:55:08 +01:00
MYSQL_ROW row;
long DegCod;
/***** Write heading *****/
fprintf (Gbl.F.Out,"<tr>"
2015-09-06 20:02:14 +02:00
"<th class=\"CENTER_TOP\">"
2014-12-25 12:54:21 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2015-11-19 20:04:41 +01:00
"<th class=\"CENTER_TOP\">"
2014-12-25 12:54:21 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"LEFT_TOP\">"
2014-12-25 12:54:21 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2014-12-01 23:55:08 +01:00
"</tr>",
Txt_No_INDEX,
Txt_Degree,
Txt_STAT_TYPE_COUNT_CAPS[Gbl.Stat.CountType]);
2015-10-11 14:12:20 +02:00
/***** Compute maximum number of hits per degree *****/
2015-10-11 18:53:22 +02:00
Sta_ComputeMaxAndTotalHits (&Hits,NumRows,mysql_res,1,1);
2014-12-01 23:55:08 +01:00
/***** Write rows *****/
2017-04-25 14:48:47 +02:00
mysql_data_seek (mysql_res,0);
2014-12-01 23:55:08 +01:00
for (NumRow = 1, Ranking = 0;
NumRow <= NumRows;
NumRow++)
{
/* Get degree code */
2015-10-11 14:12:20 +02:00
row = mysql_fetch_row (mysql_res);
2014-12-01 23:55:08 +01:00
DegCod = Str_ConvertStrCodToLongCod (row[0]);
/* Write ranking of this degree */
fprintf (Gbl.F.Out,"<tr>"
2015-08-24 12:29:00 +02:00
"<td class=\"LOG RIGHT_TOP\">");
2015-01-18 17:11:29 +01:00
if (DegCod > 0)
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"%lu",++Ranking);
2014-12-25 12:54:21 +01:00
fprintf (Gbl.F.Out,"&nbsp;"
"</td>");
2014-12-01 23:55:08 +01:00
/* Write degree */
Sta_WriteDegree (DegCod);
2015-10-11 14:12:20 +02:00
/* Draw bar proportional to number of hits */
2015-10-11 18:53:22 +02:00
Hits.Num = Str_GetFloatNumFromStr (row[1]);
2018-10-07 15:13:24 +02:00
Sta_DrawBarNumHits ('o', // orange background
Hits.Num,Hits.Max,Hits.Total,375);
2015-10-11 14:12:20 +02:00
}
}
/*****************************************************************************/
/************************* Write degree with an icon *************************/
/*****************************************************************************/
static void Sta_WriteDegree (long DegCod)
{
struct Degree Deg;
/***** Start cell *****/
fprintf (Gbl.F.Out,"<td class=\"LOG LEFT_MIDDLE\"");
if (DegCod > 0) // Hit with a degree selected
{
/***** Get data of degree *****/
Deg.DegCod = DegCod;
Deg_GetDataOfDegreeByCod (&Deg);
/***** Title in cell *****/
fprintf (Gbl.F.Out,"title=\"%s\">",
Deg.FullName);
/***** Form to go to degree *****/
2015-11-19 20:04:41 +01:00
Deg_DrawDegreeLogoAndNameWithLink (&Deg,ActSeeDegInf,
"LOG","CENTER_TOP");
2014-12-01 23:55:08 +01:00
}
2015-10-11 14:12:20 +02:00
else // Hit with no degree selected
/***** No degree selected *****/
fprintf (Gbl.F.Out,">&nbsp;-&nbsp;");
/***** End cell *****/
fprintf (Gbl.F.Out,"</td>");
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/********* Show a listing with the number of clicks to each course ***********/
/*****************************************************************************/
2015-10-11 14:12:20 +02:00
static void Sta_ShowNumHitsPerCourse (unsigned long NumRows,
MYSQL_RES *mysql_res)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_No_INDEX;
extern const char *Txt_Degree;
extern const char *Txt_Year_OF_A_DEGREE;
extern const char *Txt_Course;
2015-09-25 01:48:00 +02:00
extern const char *Txt_STAT_TYPE_COUNT_CAPS[Sta_NUM_COUNT_TYPES];
2014-12-01 23:55:08 +01:00
extern const char *Txt_Go_to_X;
2017-01-28 15:58:46 +01:00
extern const char *Txt_YEAR_OF_DEGREE[1 + Deg_MAX_YEARS_PER_DEGREE]; // Declaration in swad_degree.c
2014-12-01 23:55:08 +01:00
unsigned long NumRow;
unsigned long Ranking;
2015-10-11 18:53:22 +02:00
struct Sta_Hits Hits;
2014-12-01 23:55:08 +01:00
MYSQL_ROW row;
bool CrsOK;
struct Course Crs;
/***** Write heading *****/
fprintf (Gbl.F.Out,"<tr>"
2015-09-06 20:02:14 +02:00
"<th class=\"CENTER_TOP\">"
2014-12-25 12:54:21 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2015-11-19 20:04:41 +01:00
"<th class=\"CENTER_TOP\">"
2014-12-25 12:54:21 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"CENTER_TOP\">"
2014-12-25 12:54:21 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2015-11-19 20:04:41 +01:00
"<th class=\"CENTER_TOP\">"
2014-12-25 12:54:21 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"LEFT_TOP\">"
2014-12-25 12:54:21 +01:00
"%s"
2015-09-05 19:19:39 +02:00
"</th>"
2014-12-01 23:55:08 +01:00
"</tr>",
Txt_No_INDEX,
Txt_Degree,
Txt_Year_OF_A_DEGREE,
Txt_Course,
Txt_STAT_TYPE_COUNT_CAPS[Gbl.Stat.CountType]);
/***** Compute maximum number of pages generated per course *****/
2015-10-11 18:53:22 +02:00
Sta_ComputeMaxAndTotalHits (&Hits,NumRows,mysql_res,1,1);
2014-12-01 23:55:08 +01:00
/***** Write rows *****/
2017-04-25 14:48:47 +02:00
mysql_data_seek (mysql_res,0);
2015-10-11 14:12:20 +02:00
for (NumRow = 1, Ranking = 0;
2014-12-01 23:55:08 +01:00
NumRow <= NumRows;
NumRow++)
{
/* Get degree, the year and the course */
row = mysql_fetch_row (mysql_res);
/* Get course code */
Crs.CrsCod = Str_ConvertStrCodToLongCod (row[0]);
/* Get data of current degree */
CrsOK = Crs_GetDataOfCourseByCod (&Crs);
/* Write ranking of this course */
fprintf (Gbl.F.Out,"<tr>"
2015-08-24 12:29:00 +02:00
"<td class=\"LOG RIGHT_TOP\">");
2014-12-01 23:55:08 +01:00
if (CrsOK)
fprintf (Gbl.F.Out,"%lu",++Ranking);
fprintf (Gbl.F.Out,"&nbsp;</td>");
/* Write degree */
Sta_WriteDegree (Crs.DegCod);
/* Write degree year */
2015-08-24 12:29:00 +02:00
fprintf (Gbl.F.Out,"<td class=\"LOG CENTER_TOP\">"
2014-12-25 12:54:21 +01:00
"%s&nbsp;"
"</td>",
2014-12-01 23:55:08 +01:00
CrsOK ? Txt_YEAR_OF_DEGREE[Crs.Year] :
"-");
/* Write course, including link */
2015-08-24 12:29:00 +02:00
fprintf (Gbl.F.Out,"<td class=\"LOG LEFT_TOP\">");
2014-12-01 23:55:08 +01:00
if (CrsOK)
{
2018-11-09 20:47:39 +01:00
Frm_StartFormGoTo (ActSeeCrsInf);
2014-12-01 23:55:08 +01:00
Crs_PutParamCrsCod (Crs.CrsCod);
2018-10-18 02:02:32 +02:00
snprintf (Gbl.Title,sizeof (Gbl.Title),
Txt_Go_to_X,
Crs.FullName);
2018-11-09 20:47:39 +01:00
Frm_LinkFormSubmit (Gbl.Title,"LOG",NULL);
2016-07-01 17:13:41 +02:00
fprintf (Gbl.F.Out,"%s"
"</a>",
2016-10-28 10:03:37 +02:00
Crs.ShrtName);
2014-12-01 23:55:08 +01:00
}
else
fprintf (Gbl.F.Out,"-");
fprintf (Gbl.F.Out,"&nbsp;");
if (CrsOK)
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"</td>");
2018-10-07 14:01:25 +02:00
/* Draw bar proportional to number of hits */
2015-10-11 18:53:22 +02:00
Hits.Num = Str_GetFloatNumFromStr (row[1]);
2018-10-07 15:13:24 +02:00
Sta_DrawBarNumHits ('o', // orange background
Hits.Num,Hits.Max,Hits.Total,375);
2015-10-11 18:53:22 +02:00
}
}
/*****************************************************************************/
/*************** Compute maximum and total number of hits ********************/
/*****************************************************************************/
2016-09-12 00:50:24 +02:00
void Sta_ComputeMaxAndTotalHits (struct Sta_Hits *Hits,
unsigned long NumRows,
MYSQL_RES *mysql_res,unsigned Field,
unsigned Divisor)
2015-10-11 18:53:22 +02:00
{
unsigned long NumRow;
MYSQL_ROW row;
2016-10-08 21:19:47 +02:00
/***** For each row... *****/
2015-10-11 18:53:22 +02:00
for (NumRow = 1, Hits->Max = Hits->Total = 0.0;
NumRow <= NumRows;
NumRow++)
{
2016-10-08 21:19:47 +02:00
/* Get row */
2015-10-11 18:53:22 +02:00
row = mysql_fetch_row (mysql_res);
/* Get number of hits */
Hits->Num = Str_GetFloatNumFromStr (row[Field]);
if (Divisor > 1)
Hits->Num /= (float) Divisor;
/* Update total hits */
Hits->Total += Hits->Num;
/* Update maximum hits */
if (Hits->Num > Hits->Max)
Hits->Max = Hits->Num;
2014-12-01 23:55:08 +01:00
}
}
/*****************************************************************************/
2015-10-11 14:12:20 +02:00
/********************* Draw a bar with the number of hits ********************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2018-10-07 15:13:24 +02:00
static void Sta_DrawBarNumHits (char Color,
float HitsNum,float HitsMax,float HitsTotal,
unsigned MaxBarWidth)
2014-12-01 23:55:08 +01:00
{
unsigned BarWidth;
2015-08-24 12:29:00 +02:00
fprintf (Gbl.F.Out,"<td class=\"LOG LEFT_MIDDLE\">");
2015-10-11 14:12:20 +02:00
2015-10-11 18:53:22 +02:00
if (HitsNum != 0.0)
2014-12-01 23:55:08 +01:00
{
2015-10-11 14:12:20 +02:00
/***** Draw bar with a with proportional to the number of hits *****/
2015-10-11 18:53:22 +02:00
BarWidth = (unsigned) (((HitsNum * (float) MaxBarWidth) / HitsMax) + 0.5);
2014-12-01 23:55:08 +01:00
if (BarWidth == 0)
BarWidth = 1;
2018-10-07 15:13:24 +02:00
fprintf (Gbl.F.Out,"<img src=\"%s/%c1x1.png\"" // Background
2015-07-22 18:59:44 +02:00
" alt=\"\" title=\"\""
2018-10-07 15:25:57 +02:00
" class=\"LEFT_MIDDLE\""
" style=\"width:%upx; height:10px;\" />"
2014-12-21 01:58:30 +01:00
"&nbsp;",
2019-03-20 01:36:36 +01:00
Cfg_URL_ICON_PUBLIC,Color,BarWidth);
2014-12-01 23:55:08 +01:00
2015-10-11 14:12:20 +02:00
/***** Write the number of hits *****/
2016-10-03 14:12:01 +02:00
Str_WriteFloatNum (Gbl.F.Out,HitsNum);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"&nbsp;(%u",
2015-10-11 18:53:22 +02:00
(unsigned) (((HitsNum * 100.0) /
HitsTotal) + 0.5));
2014-12-01 23:55:08 +01:00
}
else
2015-10-11 14:12:20 +02:00
/***** Write the number of clicks *****/
2014-12-21 01:58:30 +01:00
fprintf (Gbl.F.Out,"0&nbsp;(0");
2015-10-11 14:12:20 +02:00
2014-12-21 01:58:30 +01:00
fprintf (Gbl.F.Out,"%%)&nbsp;"
2014-12-01 23:55:08 +01:00
"</td>"
"</tr>");
}
/*****************************************************************************/
2019-02-12 14:46:14 +01:00
/**************** Compute the time used to generate the page *****************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2019-02-12 14:46:14 +01:00
void Sta_ComputeTimeToGeneratePage (void)
2014-12-01 23:55:08 +01:00
{
2019-02-12 14:46:14 +01:00
if (gettimeofday (&Gbl.tvPageCreated, &Gbl.tz))
// Error in gettimeofday
Gbl.TimeGenerationInMicroseconds = 0;
else
2014-12-01 23:55:08 +01:00
{
2019-02-12 14:46:14 +01:00
if (Gbl.tvPageCreated.tv_usec < Gbl.tvStart.tv_usec)
{
Gbl.tvPageCreated.tv_sec--;
Gbl.tvPageCreated.tv_usec += 1000000;
}
Gbl.TimeGenerationInMicroseconds = (Gbl.tvPageCreated.tv_sec - Gbl.tvStart.tv_sec) * 1000000L +
Gbl.tvPageCreated.tv_usec - Gbl.tvStart.tv_usec;
2014-12-01 23:55:08 +01:00
}
}
2016-11-06 15:36:26 +01:00
/*****************************************************************************/
2019-02-12 14:46:14 +01:00
/****************** Compute the time used to send the page *******************/
2016-11-06 15:36:26 +01:00
/*****************************************************************************/
2019-02-12 14:46:14 +01:00
void Sta_ComputeTimeToSendPage (void)
2016-11-06 15:36:26 +01:00
{
2019-02-12 14:46:14 +01:00
if (gettimeofday (&Gbl.tvPageSent, &Gbl.tz))
// Error in gettimeofday
Gbl.TimeSendInMicroseconds = 0;
else
{
if (Gbl.tvPageSent.tv_usec < Gbl.tvPageCreated.tv_usec)
{
Gbl.tvPageSent.tv_sec--;
Gbl.tvPageSent.tv_usec += 1000000;
}
Gbl.TimeSendInMicroseconds = (Gbl.tvPageSent.tv_sec - Gbl.tvPageCreated.tv_sec) * 1000000L +
Gbl.tvPageSent.tv_usec - Gbl.tvPageCreated.tv_usec;
}
2016-11-06 15:36:26 +01:00
}
/*****************************************************************************/
2019-02-12 14:46:14 +01:00
/************** Write the time to generate and send the page *****************/
2016-11-06 15:36:26 +01:00
/*****************************************************************************/
2019-02-12 14:46:14 +01:00
void Sta_WriteTimeToGenerateAndSendPage (void)
2016-11-06 15:36:26 +01:00
{
2019-02-12 14:46:14 +01:00
extern const char *Txt_PAGE1_Page_generated_in;
extern const char *Txt_PAGE2_and_sent_in;
char StrTimeGenerationInMicroseconds[Dat_MAX_BYTES_TIME + 1];
char StrTimeSendInMicroseconds[Dat_MAX_BYTES_TIME + 1];
2016-11-06 15:36:26 +01:00
2019-02-12 14:46:14 +01:00
Sta_WriteTime (StrTimeGenerationInMicroseconds,Gbl.TimeGenerationInMicroseconds);
Sta_WriteTime (StrTimeSendInMicroseconds,Gbl.TimeSendInMicroseconds);
fprintf (Gbl.F.Out,"%s %s %s %s",
Txt_PAGE1_Page_generated_in,StrTimeGenerationInMicroseconds,
Txt_PAGE2_and_sent_in,StrTimeSendInMicroseconds);
2016-11-06 15:36:26 +01:00
}
2015-10-19 21:49:45 +02:00
/*****************************************************************************/
2019-02-12 14:46:14 +01:00
/********* Write time (given in microseconds) depending on amount ************/
2015-10-19 21:49:45 +02:00
/*****************************************************************************/
2019-02-12 14:46:14 +01:00
void Sta_WriteTime (char Str[Dat_MAX_BYTES_TIME],long TimeInMicroseconds)
2015-10-19 21:49:45 +02:00
{
2019-02-12 14:46:14 +01:00
if (TimeInMicroseconds < 1000L)
snprintf (Str,Dat_MAX_BYTES_TIME + 1,
"%ld &micro;s",
TimeInMicroseconds);
else if (TimeInMicroseconds < 1000000L)
snprintf (Str,Dat_MAX_BYTES_TIME + 1,
"%ld ms",
TimeInMicroseconds / 1000);
else if (TimeInMicroseconds < (60 * 1000000L))
snprintf (Str,Dat_MAX_BYTES_TIME + 1,
"%.1f s",
(float) TimeInMicroseconds / 1E6);
else
snprintf (Str,Dat_MAX_BYTES_TIME + 1,
"%ld min, %ld s",
TimeInMicroseconds / (60 * 1000000L),
(TimeInMicroseconds / 1000000L) % 60);
2015-10-19 21:49:45 +02:00
}
2016-11-06 13:06:21 +01:00
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2019-02-12 14:46:14 +01:00
/*************** Put a link to show last clicks in real time *****************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2019-02-12 14:46:14 +01:00
void Sta_PutLinkToLastClicks (void)
2014-12-01 23:55:08 +01:00
{
2019-02-12 14:46:14 +01:00
extern const char *Txt_Last_clicks;
2014-12-01 23:55:08 +01:00
2019-02-12 14:46:14 +01:00
Lay_PutContextualLinkIconText (ActLstClk,NULL,NULL,
"mouse-pointer.svg",
Txt_Last_clicks);
2014-12-01 23:55:08 +01:00
}
2015-03-09 12:38:52 +01:00
/*****************************************************************************/
2019-02-12 14:46:14 +01:00
/****************************** Show last clicks *****************************/
2015-03-09 12:38:52 +01:00
/*****************************************************************************/
2019-02-12 14:46:14 +01:00
void Sta_ShowLastClicks (void)
2015-03-09 12:38:52 +01:00
{
2019-02-12 14:46:14 +01:00
extern const char *Hlp_USERS_Connected_last_clicks;
extern const char *Txt_Last_clicks_in_real_time;
2015-03-09 12:38:52 +01:00
2019-02-12 14:46:14 +01:00
/***** Contextual links *****/
fprintf (Gbl.F.Out,"<div class=\"CONTEXT_MENU\">");
2015-03-09 12:38:52 +01:00
2019-02-12 14:46:14 +01:00
/* Put form to go to test edition and configuration */
Sta_PutLinkToGlobalHits ();
2015-03-09 12:38:52 +01:00
2019-02-12 14:46:14 +01:00
/* Put form to go to test edition and configuration */
Sta_PutLinkToCourseHits ();
2017-05-25 19:57:34 +02:00
2019-02-12 14:46:14 +01:00
fprintf (Gbl.F.Out,"</div>");
2017-05-25 19:57:34 +02:00
2019-02-12 14:46:14 +01:00
/***** Start box *****/
Box_StartBox (NULL,Txt_Last_clicks_in_real_time,NULL,
Hlp_USERS_Connected_last_clicks,Box_NOT_CLOSABLE);
2017-05-25 19:57:34 +02:00
2019-02-12 14:46:14 +01:00
/***** Get and show last clicks *****/
fprintf (Gbl.F.Out,"<div id=\"lastclicks\"" // Used for AJAX based refresh
" class=\"CENTER_MIDDLE\">");
Sta_GetAndShowLastClicks ();
fprintf (Gbl.F.Out,"</div>"); // Used for AJAX based refresh
2017-05-25 19:57:34 +02:00
2019-02-12 14:46:14 +01:00
/***** End box *****/
Box_EndBox ();
2017-05-25 19:57:34 +02:00
}
2015-03-16 14:05:16 +01:00
/*****************************************************************************/
2019-02-12 14:46:14 +01:00
/**************** Get last clicks from database and show them ****************/
2015-03-16 14:05:16 +01:00
/*****************************************************************************/
2019-02-12 14:46:14 +01:00
void Sta_GetAndShowLastClicks (void)
2015-03-16 14:05:16 +01:00
{
2019-02-12 14:46:14 +01:00
extern const char *Txt_Click;
extern const char *Txt_ELAPSED_TIME;
extern const char *Txt_Role;
extern const char *Txt_Country;
extern const char *Txt_Institution;
extern const char *Txt_Centre;
extern const char *Txt_Degree;
extern const char *Txt_Action;
extern const char *Txt_ROLES_SINGUL_Abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned long NumRow;
unsigned long NumRows;
long ActCod;
const char *ClassRow;
time_t TimeDiff;
struct Country Cty;
struct Instit Ins;
struct Centre Ctr;
struct Degree Deg;
2015-03-16 14:05:16 +01:00
2019-02-12 14:46:14 +01:00
/***** Get last clicks from database *****/
/* Important for maximum performance:
do the LIMIT in the big log table before the JOIN */
NumRows = DB_QuerySELECT (&mysql_res,"can not get last clicks",
"SELECT last_logs.LogCod,last_logs.ActCod,"
"last_logs.Dif,last_logs.Role,"
"last_logs.CtyCod,last_logs.InsCod,"
"last_logs.CtrCod,last_logs.DegCod,"
"actions.Txt"
" FROM"
" (SELECT LogCod,ActCod,"
"UNIX_TIMESTAMP()-UNIX_TIMESTAMP(ClickTime) AS Dif,"
"Role,CtyCod,InsCod,CtrCod,DegCod"
" FROM log_recent ORDER BY LogCod DESC LIMIT 20)"
2019-02-24 21:45:46 +01:00
" AS last_logs LEFT JOIN actions" // LEFT JOIN because action may be not present in table of actions
" ON last_logs.ActCod=actions.ActCod"
" WHERE actions.Language='es'" // TODO: Change to user's language
" OR actions.Language IS NULL"); // When action is not present in table of actions
2015-03-16 14:05:16 +01:00
2019-02-12 14:46:14 +01:00
/***** Write list of connected users *****/
Tbl_StartTableCenter (1);
2015-03-16 14:05:16 +01:00
fprintf (Gbl.F.Out,"<tr>"
2019-02-12 14:46:14 +01:00
"<th class=\"LEFT_MIDDLE\""
" style=\"width:85px;\">"
"%s" // Click
2015-03-16 17:46:32 +01:00
"</th>"
2019-02-12 14:46:14 +01:00
"<th class=\"RIGHT_MIDDLE\""
" style=\"width:50px;\">"
"%s" // Elapsed time
2015-03-16 17:46:32 +01:00
"</th>"
2019-02-12 14:46:14 +01:00
"<th class=\"LEFT_MIDDLE\""
" style=\"width:100px;\">"
"%s" // Role
2015-03-16 17:46:32 +01:00
"</th>"
2019-02-12 14:46:14 +01:00
"<th class=\"LEFT_MIDDLE\""
" style=\"width:100px;\">"
"%s" // Country
2015-03-16 14:05:16 +01:00
"</th>"
2019-02-12 14:46:14 +01:00
"<th class=\"LEFT_MIDDLE\""
" style=\"width:150px;\">"
"%s" // Institution
2015-03-16 14:05:16 +01:00
"</th>"
2019-02-12 14:46:14 +01:00
"<th class=\"LEFT_MIDDLE\""
" style=\"width:150px;\">"
"%s" // Centre
2019-01-11 12:32:41 +01:00
"</th>"
"<th class=\"LEFT_MIDDLE\""
" style=\"width:200px;\">"
"%s" // Degree
"</th>"
"<th class=\"LEFT_MIDDLE\""
" style=\"width:275px;\">"
"%s" // Action
"</th>"
"</tr>",
Txt_Click,
Txt_ELAPSED_TIME,
Txt_Role,
Txt_Country,
Txt_Institution,
Txt_Centre,
Txt_Degree,
Txt_Action);
for (NumRow = 0;
NumRow < NumRows;
NumRow++)
{
row = mysql_fetch_row (mysql_res);
/* Get action code (row[1]) */
ActCod = Str_ConvertStrCodToLongCod (row[1]);
/* Use a special color for this row depending on the action */
ClassRow = (Act_GetBrowserTab (Act_GetActionFromActCod (ActCod)) == Act_DOWNLD_FILE) ? "DAT_SMALL_YELLOW LEFT_MIDDLE" :
(ActCod == Act_GetActCod (ActLogIn ) ||
ActCod == Act_GetActCod (ActLogInNew)) ? "DAT_SMALL_GREEN" :
(ActCod == Act_GetActCod (ActLogOut )) ? "DAT_SMALL_RED" :
(ActCod == Act_GetActCod (ActWebSvc )) ? "DAT_SMALL_BLUE" :
"DAT_SMALL_GREY";
/* Compute elapsed time from last access */
if (sscanf (row[2],"%ld",&TimeDiff) != 1)
TimeDiff = (time_t) 0;
/* Get country code (row[4]) */
Cty.CtyCod = Str_ConvertStrCodToLongCod (row[4]);
Cty_GetCountryName (Cty.CtyCod,Cty.Name[Gbl.Prefs.Language]);
/* Get institution code (row[5]) */
Ins.InsCod = Str_ConvertStrCodToLongCod (row[5]);
Ins_GetShortNameOfInstitution (&Ins);
/* Get centre code (row[6]) */
Ctr.CtrCod = Str_ConvertStrCodToLongCod (row[6]);
Ctr_GetShortNameOfCentreByCod (&Ctr);
/* Get degree code (row[7]) */
Deg.DegCod = Str_ConvertStrCodToLongCod (row[7]);
Deg_GetShortNameOfDegreeByCod (&Deg);
/* Print table row */
fprintf (Gbl.F.Out,"<tr>"
"<td class=\"%s LEFT_MIDDLE\">"
"%s" // Click
"</td>"
"<td class=\"%s RIGHT_MIDDLE\">" // Elapsed time
"",
ClassRow,row[0],
ClassRow);
Dat_WriteHoursMinutesSecondsFromSeconds (TimeDiff);
fprintf (Gbl.F.Out,"</td>"
"<td class=\"%s LEFT_MIDDLE\">"
"%s" // Role
"</td>"
"<td class=\"%s LEFT_MIDDLE\">"
"%s" // Country
"</td>"
"<td class=\"%s LEFT_MIDDLE\">"
"%s" // Institution
"</td>"
"<td class=\"%s LEFT_MIDDLE\">"
"%s" // Centre
"</td>"
"<td class=\"%s LEFT_MIDDLE\">"
"%s" // Degree
"</td>"
2019-02-24 21:45:46 +01:00
"<td class=\"%s LEFT_MIDDLE\">",
2019-01-11 12:32:41 +01:00
ClassRow,Txt_ROLES_SINGUL_Abc[Rol_ConvertUnsignedStrToRole (row[3])][Usr_SEX_UNKNOWN],
ClassRow,Cty.Name[Gbl.Prefs.Language],
ClassRow,Ins.ShrtName,
ClassRow,Ctr.ShrtName,
ClassRow,Deg.ShrtName,
2019-02-24 21:45:46 +01:00
ClassRow);
if (row[8])
if (row[8][0])
fprintf (Gbl.F.Out,"%s",row[8]); // Action
fprintf (Gbl.F.Out,"</td>"
"</tr>");
2019-01-11 12:32:41 +01:00
}
Tbl_EndTable ();
/***** Free structure that stores the query result *****/
mysql_free_result (mysql_res);
}