From 79e85830030f18a8d124c6cf46327057d60c4ea1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Ca=C3=B1as=20Vargas?= Date: Sat, 8 Oct 2016 20:25:26 +0200 Subject: [PATCH] Version 16.17 --- sql/cambios.sql | 3 +- swad_changelog.h | 7 +++- swad_report.c | 107 +++++++++++++++++++++++++++++++++++++++++++---- swad_statistic.c | 16 ++++--- 4 files changed, 116 insertions(+), 17 deletions(-) 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,"
\n"); } +/*****************************************************************************/ +/******** Write section for user's global hits in user's usage report ********/ +/*****************************************************************************/ + +static void Rep_WriteSectionHitsPerAction (const struct UsrFigures *UsrFigures) + { + extern struct Act_Actions Act_Actions[Act_NUM_ACTIONS]; + extern Act_Action_t Act_FromActCodToAction[1+Act_MAX_ACTION_COD]; + extern const char *Txt_TABS_FULL_TXT[Tab_NUM_TABS]; + char Query[512]; + MYSQL_RES *mysql_res; + MYSQL_ROW row; + unsigned long NumRows; + unsigned long NumRow; + struct Sta_Hits Hits; + long ActCod; + char ActTxt[Act_MAX_LENGTH_ACTION_TXT+1]; + long NumClicks; + + /***** Start of section *****/ + 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,"
\n"); + } + /*****************************************************************************/ /****** Write section for user's current courses in user's usage report ******/ /*****************************************************************************/ @@ -825,7 +909,7 @@ static void Rep_WriteSectionHistoricCourses (const struct UsrFigures *UsrFigures /********* Historic clicks of a user without course selected ***********/ Rep_GetAndWriteMyHistoricClicsWithoutCrs (UsrFigures->FirstClickTimeUTC,tm_FirstClickTime, - MaxHitsPerYear); + MaxHitsPerYear); /***** Historic courses in which the user clicked as student/teacher *****/ for (Role = Rol_STUDENT; @@ -833,8 +917,8 @@ static void Rep_WriteSectionHistoricCourses (const struct UsrFigures *UsrFigures Role++) /* List my courses with this role */ Rep_GetAndWriteMyHistoricCrss (Role, - UsrFigures->FirstClickTimeUTC,tm_FirstClickTime, - MaxHitsPerYear); + UsrFigures->FirstClickTimeUTC,tm_FirstClickTime, + MaxHitsPerYear); /***** End of section *****/ fprintf (Gbl.F.Rep,"" @@ -897,6 +981,9 @@ static unsigned long Rep_GetMaxHitsPerYear (time_t FirstClickTimeUTC) if (sscanf (row[0],"%lu",&MaxHitsPerYear) != 1) Lay_ShowErrorAndExit ("Error when getting maximum hits."); + /***** Free structure that stores the query result *****/ + DB_FreeMySQLResult (&mysql_res); + return MaxHitsPerYear; } @@ -1226,10 +1313,14 @@ static void Rep_ShowMyHitsPerYear (bool AnyCourse,long CrsCod,Rol_Role_t Role, Rep_DrawBarNumHits (Year == LastYear ? Hits.Num : 0.0, Hits.Max,Rep_MAX_BAR_WIDTH); + 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,"" ""