diff --git a/sql/cambios.sql b/sql/cambios.sql
index 03a9bf542..96a86c5ea 100644
--- a/sql/cambios.sql
+++ b/sql/cambios.sql
@@ -11644,7 +11644,8 @@ CREATE TABLE IF NOT EXISTS usr_report (RepCod INT NOT NULL AUTO_INCREMENT,UsrCod
-
+--------------------------------------------------
+--------------------------------------------------
SELECT CrsCod,COUNT(*) AS N FROM crs_usr LEFT JOIN log_full ON (crs_usr.CrsCod=log_full.CrsCod AND crs_usr.UsrCod=log_full.UsrCod AND crs_usr.Role=log_full.Role) WHERE UsrCod='7' AND Role='3' GROUP BY CrsCod ORDER BY N DESC;
diff --git a/swad_changelog.h b/swad_changelog.h
index 077203941..12860464c 100644
--- a/swad_changelog.h
+++ b/swad_changelog.h
@@ -142,17 +142,20 @@
// TODO: FIX BUG: Centre and degree admins should see buttons to admin users even a course is not selected
+// TODO: Generar informe -> ¿Realmente desea generar un informe... (puede tardar varios segundos...)? -> Generar informe.
+
/*****************************************************************************/
/****************************** Public constants *****************************/
/*****************************************************************************/
-#define Log_PLATFORM_VERSION "SWAD 16.16.1 (2016-10-07)"
+#define Log_PLATFORM_VERSION "SWAD 16.17 (2016-10-08)"
#define CSS_FILE "swad15.229.css"
#define JS_FILE "swad15.238.1.js"
// Number of lines (includes comments but not blank lines) has been got with the following command:
// nl swad*.c swad*.h css/swad*.css py/swad*.py js/swad*.js soap/swad*.h sql/swad*.sql | tail -1
/*
+ Version 16.17: Oct 08, 2016 List of most frequent actions in user's usage report. (206189 lines)
Version 16.16.1: Oct 07, 2016 Fixed bug in user's usage report. (206108 lines)
Version 16.16: Oct 07, 2016 Order current courses in user's usage report by number of clicks.
Do not write number of users in historic courses.
@@ -207,7 +210,7 @@ INSERT INTO actions (ActCod,Language,Obsolete,Txt) VALUES ('1586','es','N','Soli
Version 16.4.1: Sep 29, 2016 Changes in hits in current courses in user's usage report. (205316 lines)
Version 16.4: Sep 29, 2016 Hits in current courses in user's usage report. (205299 lines)
Version 16.3.2: Sep 28, 2016 Changes in behaviour of button to follow user. (205277 lines)
- Version 16.3.1: Sep 28, 2016 Two different messagesrelated to new account merged into one.
+ Version 16.3.1: Sep 28, 2016 Two different messages related to new account merged into one.
Changes in form to create new account. (205271 lines)
Version 16.3: Sep 26, 2016 Message translated.
Code refactoring of list with empty accounts for an ID. (205287 lines)
diff --git a/swad_report.c b/swad_report.c
index c9b539677..8ecaa16ee 100644
--- a/swad_report.c
+++ b/swad_report.c
@@ -32,6 +32,7 @@
#include "swad_global.h"
#include "swad_ID.h"
#include "swad_profile.h"
+#include "swad_tab.h"
/*****************************************************************************/
/****************************** Public constants *****************************/
@@ -44,6 +45,7 @@
#define Rep_FILENAME_ROOT "report"
#define Rep_MIN_CLICKS_CRS 100 // Minimum number of clicks to show a course in historic log
+#define Rep_MAX_ACTIONS 50 // Maximum number of actions in list of frequent actions
#define Rep_MAX_BAR_WIDTH 50 // Maximum width of graphic bar
// #define Rep_BLOCK "═" // HTML code for a block in graphic bar
@@ -105,6 +107,7 @@ static void Rep_WriteSectionUsrInfo (void);
static void Rep_WriteSectionUsrFigures (const struct UsrFigures *UsrFigures,
const struct tm *tm_FirstClickTime,
const struct CurrentTimeUTC *CurrentTimeUTC);
+static void Rep_WriteSectionHitsPerAction (const struct UsrFigures *UsrFigures);
static void Rep_WriteSectionGlobalHits (const struct UsrFigures *UsrFigures,
const struct tm *tm_FirstClickTime);
static void Rep_WriteSectionCurrentCourses (const struct UsrFigures *UsrFigures,
@@ -234,9 +237,12 @@ static void Rep_CreateMyUsageReport (struct CurrentTimeUTC *CurrentTimeUTC,
gmtime_r (&UsrFigures.FirstClickTimeUTC,&tm_FirstClickTime);
Rep_WriteSectionUsrFigures (&UsrFigures,&tm_FirstClickTime,CurrentTimeUTC);
- /***** Global hits *****/
+ /***** Global count of hits *****/
Rep_WriteSectionGlobalHits (&UsrFigures,&tm_FirstClickTime);
+ /***** Global hits distributed by action *****/
+ Rep_WriteSectionHitsPerAction (&UsrFigures);
+
/***** Current courses *****/
MaxHitsPerYear = Rep_GetMaxHitsPerYear (UsrFigures.FirstClickTimeUTC);
Rep_WriteSectionCurrentCourses (&UsrFigures,&tm_FirstClickTime,
@@ -749,12 +755,10 @@ static void Rep_WriteSectionUsrFigures (const struct UsrFigures *UsrFigures,
static void Rep_WriteSectionGlobalHits (const struct UsrFigures *UsrFigures,
const struct tm *tm_FirstClickTime)
{
- extern const char *Txt_Hits;
-
/***** Start of section *****/
fprintf (Gbl.F.Rep,"%s
",
- Txt_Hits);
+ "Accesos (clics) por año"); // TODO: Need translation!!!!
/***** Global (in any course) hits per year *****/
Rep_ShowMyHitsPerYear (true,-1L, // Any course
@@ -767,6 +771,86 @@ static void Rep_WriteSectionGlobalHits (const struct UsrFigures *UsrFigures,
fprintf (Gbl.F.Rep,"%s
",
+ "Accesos (clics) por acción"); // TODO: Need translation!!!!
+
+ /***** Make the query *****/
+ sprintf (Query,"SELECT SQL_NO_CACHE ActCod,COUNT(*) AS N FROM log_full"
+ " WHERE ClickTime>=FROM_UNIXTIME('%ld') AND UsrCod='%ld'"
+ " GROUP BY ActCod ORDER BY N DESC LIMIT %u",
+ (long) UsrFigures->FirstClickTimeUTC,Gbl.Usrs.Me.UsrDat.UsrCod,
+ Rep_MAX_ACTIONS);
+ NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get clicks");
+
+ /***** Compute maximum number of hits per action *****/
+ Sta_ComputeMaxAndTotalHits (&Hits,NumRows,mysql_res,1,1);
+ mysql_data_seek (mysql_res,0);
+
+ /***** Write rows *****/
+ for (NumRow = 1, NumClicks = 0;
+ NumRow <= NumRows;
+ NumRow++)
+ {
+ row = mysql_fetch_row (mysql_res);
+
+ /* Get the action (row[0]) */
+ ActCod = Str_ConvertStrCodToLongCod (row[0]);
+
+ /* Get number hits (in row[1]) */
+ Hits.Num = Str_GetFloatNumFromStr (row[1]);
+ NumClicks += (long) Hits.Num;
+
+ /* Draw bar proportional to number of hits */
+ Rep_DrawBarNumHits (Hits.Num,Hits.Max,Rep_MAX_BAR_WIDTH);
+
+ /* Write action text */
+ fprintf (Gbl.F.Rep," ");
+ if (ActCod >= 0)
+ {
+ if (Txt_TABS_FULL_TXT[Act_Actions[Act_FromActCodToAction[ActCod]].Tab])
+ fprintf (Gbl.F.Rep,"%s > ",
+ Txt_TABS_FULL_TXT[Act_Actions[Act_FromActCodToAction[ActCod]].Tab]);
+ fprintf (Gbl.F.Rep,"%s",Act_GetActionTextFromDB (ActCod,ActTxt));
+ }
+ else
+ fprintf (Gbl.F.Rep,"?");
+ fprintf (Gbl.F.Rep,"
");
+ }
+
+ /***** Draw bar for the rest of the clicks *****/
+ if (UsrFigures->NumClicks > NumClicks)
+ fprintf (Gbl.F.Rep,"%ld (%s)
",
+ UsrFigures->NumClicks - NumClicks,
+ "otras acciones"); // TODO: Need translation!!!!
+
+ /***** Free structure that stores the query result *****/
+ DB_FreeMySQLResult (&mysql_res);
+
+ /***** End of section *****/
+ fprintf (Gbl.F.Rep,"
");
}
LastYear = Year;
}
+ /***** Free structure that stores the query result *****/
+ DB_FreeMySQLResult (&mysql_res);
+
/***** Finally, show the oldest years without clicks *****/
for (Year = LastYear;
Year >= Gbl.DateRange.DateIni.Date.Year;
@@ -1240,6 +1331,7 @@ static void Rep_ShowMyHitsPerYear (bool AnyCourse,long CrsCod,Rol_Role_t Role,
/* Draw bar proportional to number of hits */
Rep_DrawBarNumHits (0.0,Hits.Max,Rep_MAX_BAR_WIDTH);
+ fprintf (Gbl.F.Rep,"
");
}
}
@@ -1271,7 +1363,6 @@ static void Rep_DrawBarNumHits (float HitsNum,float HitsMax,
fprintf (Gbl.F.Rep," ");
Str_WriteFloatNum (Gbl.F.Rep,HitsNum);
}
- fprintf (Gbl.F.Rep,"
");
}
/*****************************************************************************/
diff --git a/swad_statistic.c b/swad_statistic.c
index dea9cb585..7ec686dc9 100644
--- a/swad_statistic.c
+++ b/swad_statistic.c
@@ -273,9 +273,11 @@ void Sta_LogAccess (const char *Comments)
/***** Insert access into database *****/
/* Log access in historical log (log_full) */
- sprintf (Query,"INSERT INTO log_full (ActCod,CtyCod,InsCod,CtrCod,DegCod,CrsCod,UsrCod,"
+ sprintf (Query,"INSERT INTO log_full "
+ "(ActCod,CtyCod,InsCod,CtrCod,DegCod,CrsCod,UsrCod,"
"Role,ClickTime,TimeToGenerate,TimeToSend,IP)"
- " VALUES ('%ld','%ld','%ld','%ld','%ld','%ld','%ld',"
+ " VALUES "
+ "('%ld','%ld','%ld','%ld','%ld','%ld','%ld',"
"'%u',NOW(),'%ld','%ld','%s')",
Act_Actions[Gbl.Action.Act].ActCod,
Gbl.CurrentCty.Cty.CtyCod,
@@ -298,9 +300,11 @@ void Sta_LogAccess (const char *Comments)
LogCod = DB_QueryINSERTandReturnCode (Query,"can not log access (full)");
/* Log access in recent log (log_recent) */
- sprintf (Query,"INSERT INTO log_recent (LogCod,ActCod,CtyCod,InsCod,CtrCod,DegCod,CrsCod,UsrCod,"
+ sprintf (Query,"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',"
+ " VALUES "
+ "('%ld','%ld','%ld','%ld','%ld','%ld','%ld','%ld',"
"'%u',NOW(),'%ld','%ld','%s')",
LogCod,Act_Actions[Gbl.Action.Act].ActCod,
Gbl.CurrentCty.Cty.CtyCod,
@@ -3002,8 +3006,8 @@ static void Sta_ShowNumHitsPerAction (unsigned long NumRows,
row = mysql_fetch_row (mysql_res);
/* Write the action */
- if (sscanf (row[0],"%ld",&ActCod) != 1)
- Lay_ShowErrorAndExit ("Wrong action code.");
+ ActCod = Str_ConvertStrCodToLongCod (row[0]);
+
if (ActCod >= 0)
fprintf (Gbl.F.Out,"