Version 16.17

This commit is contained in:
Antonio Cañas Vargas 2016-10-08 20:25:26 +02:00
parent 0b253eb929
commit 79e8583003
4 changed files with 116 additions and 17 deletions

View File

@ -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; 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;

View File

@ -142,17 +142,20 @@
// TODO: FIX BUG: Centre and degree admins should see buttons to admin users even a course is not selected // 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 *****************************/ /****************************** 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 CSS_FILE "swad15.229.css"
#define JS_FILE "swad15.238.1.js" #define JS_FILE "swad15.238.1.js"
// Number of lines (includes comments but not blank lines) has been got with the following command: // 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 // 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.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. 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. 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.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.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.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) Changes in form to create new account. (205271 lines)
Version 16.3: Sep 26, 2016 Message translated. Version 16.3: Sep 26, 2016 Message translated.
Code refactoring of list with empty accounts for an ID. (205287 lines) Code refactoring of list with empty accounts for an ID. (205287 lines)

View File

@ -32,6 +32,7 @@
#include "swad_global.h" #include "swad_global.h"
#include "swad_ID.h" #include "swad_ID.h"
#include "swad_profile.h" #include "swad_profile.h"
#include "swad_tab.h"
/*****************************************************************************/ /*****************************************************************************/
/****************************** Public constants *****************************/ /****************************** Public constants *****************************/
@ -44,6 +45,7 @@
#define Rep_FILENAME_ROOT "report" #define Rep_FILENAME_ROOT "report"
#define Rep_MIN_CLICKS_CRS 100 // Minimum number of clicks to show a course in historic log #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_MAX_BAR_WIDTH 50 // Maximum width of graphic bar
// #define Rep_BLOCK "═" // HTML code for a block in 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, static void Rep_WriteSectionUsrFigures (const struct UsrFigures *UsrFigures,
const struct tm *tm_FirstClickTime, const struct tm *tm_FirstClickTime,
const struct CurrentTimeUTC *CurrentTimeUTC); const struct CurrentTimeUTC *CurrentTimeUTC);
static void Rep_WriteSectionHitsPerAction (const struct UsrFigures *UsrFigures);
static void Rep_WriteSectionGlobalHits (const struct UsrFigures *UsrFigures, static void Rep_WriteSectionGlobalHits (const struct UsrFigures *UsrFigures,
const struct tm *tm_FirstClickTime); const struct tm *tm_FirstClickTime);
static void Rep_WriteSectionCurrentCourses (const struct UsrFigures *UsrFigures, 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); gmtime_r (&UsrFigures.FirstClickTimeUTC,&tm_FirstClickTime);
Rep_WriteSectionUsrFigures (&UsrFigures,&tm_FirstClickTime,CurrentTimeUTC); Rep_WriteSectionUsrFigures (&UsrFigures,&tm_FirstClickTime,CurrentTimeUTC);
/***** Global hits *****/ /***** Global count of hits *****/
Rep_WriteSectionGlobalHits (&UsrFigures,&tm_FirstClickTime); Rep_WriteSectionGlobalHits (&UsrFigures,&tm_FirstClickTime);
/***** Global hits distributed by action *****/
Rep_WriteSectionHitsPerAction (&UsrFigures);
/***** Current courses *****/ /***** Current courses *****/
MaxHitsPerYear = Rep_GetMaxHitsPerYear (UsrFigures.FirstClickTimeUTC); MaxHitsPerYear = Rep_GetMaxHitsPerYear (UsrFigures.FirstClickTimeUTC);
Rep_WriteSectionCurrentCourses (&UsrFigures,&tm_FirstClickTime, 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, static void Rep_WriteSectionGlobalHits (const struct UsrFigures *UsrFigures,
const struct tm *tm_FirstClickTime) const struct tm *tm_FirstClickTime)
{ {
extern const char *Txt_Hits;
/***** Start of section *****/ /***** Start of section *****/
fprintf (Gbl.F.Rep,"<section>" fprintf (Gbl.F.Rep,"<section>"
"<h3>%s</h3>", "<h3>%s</h3>",
Txt_Hits); "Accesos (clics) por a&ntilde;o"); // TODO: Need translation!!!!
/***** Global (in any course) hits per year *****/ /***** Global (in any course) hits per year *****/
Rep_ShowMyHitsPerYear (true,-1L, // Any course Rep_ShowMyHitsPerYear (true,-1L, // Any course
@ -767,6 +771,86 @@ static void Rep_WriteSectionGlobalHits (const struct UsrFigures *UsrFigures,
fprintf (Gbl.F.Rep,"</section>\n"); fprintf (Gbl.F.Rep,"</section>\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,"<section>"
"<h3>%s</h3>",
"Accesos (clics) por acci&oacute;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,"&nbsp;");
if (ActCod >= 0)
{
if (Txt_TABS_FULL_TXT[Act_Actions[Act_FromActCodToAction[ActCod]].Tab])
fprintf (Gbl.F.Rep,"%s &gt; ",
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,"<br />");
}
/***** Draw bar for the rest of the clicks *****/
if (UsrFigures->NumClicks > NumClicks)
fprintf (Gbl.F.Rep,"%ld&nbsp;(%s)<br />",
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,"</section>\n");
}
/*****************************************************************************/ /*****************************************************************************/
/****** Write section for user's current courses in user's usage report ******/ /****** 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 ***********/ /********* Historic clicks of a user without course selected ***********/
Rep_GetAndWriteMyHistoricClicsWithoutCrs (UsrFigures->FirstClickTimeUTC,tm_FirstClickTime, Rep_GetAndWriteMyHistoricClicsWithoutCrs (UsrFigures->FirstClickTimeUTC,tm_FirstClickTime,
MaxHitsPerYear); MaxHitsPerYear);
/***** Historic courses in which the user clicked as student/teacher *****/ /***** Historic courses in which the user clicked as student/teacher *****/
for (Role = Rol_STUDENT; for (Role = Rol_STUDENT;
@ -833,8 +917,8 @@ static void Rep_WriteSectionHistoricCourses (const struct UsrFigures *UsrFigures
Role++) Role++)
/* List my courses with this role */ /* List my courses with this role */
Rep_GetAndWriteMyHistoricCrss (Role, Rep_GetAndWriteMyHistoricCrss (Role,
UsrFigures->FirstClickTimeUTC,tm_FirstClickTime, UsrFigures->FirstClickTimeUTC,tm_FirstClickTime,
MaxHitsPerYear); MaxHitsPerYear);
/***** End of section *****/ /***** End of section *****/
fprintf (Gbl.F.Rep,"</ul>" fprintf (Gbl.F.Rep,"</ul>"
@ -897,6 +981,9 @@ static unsigned long Rep_GetMaxHitsPerYear (time_t FirstClickTimeUTC)
if (sscanf (row[0],"%lu",&MaxHitsPerYear) != 1) if (sscanf (row[0],"%lu",&MaxHitsPerYear) != 1)
Lay_ShowErrorAndExit ("Error when getting maximum hits."); Lay_ShowErrorAndExit ("Error when getting maximum hits.");
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return MaxHitsPerYear; return MaxHitsPerYear;
} }
@ -1226,10 +1313,14 @@ static void Rep_ShowMyHitsPerYear (bool AnyCourse,long CrsCod,Rol_Role_t Role,
Rep_DrawBarNumHits (Year == LastYear ? Hits.Num : Rep_DrawBarNumHits (Year == LastYear ? Hits.Num :
0.0, 0.0,
Hits.Max,Rep_MAX_BAR_WIDTH); Hits.Max,Rep_MAX_BAR_WIDTH);
fprintf (Gbl.F.Rep,"<br />");
} }
LastYear = Year; LastYear = Year;
} }
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
/***** Finally, show the oldest years without clicks *****/ /***** Finally, show the oldest years without clicks *****/
for (Year = LastYear; for (Year = LastYear;
Year >= Gbl.DateRange.DateIni.Date.Year; 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 */ /* Draw bar proportional to number of hits */
Rep_DrawBarNumHits (0.0,Hits.Max,Rep_MAX_BAR_WIDTH); Rep_DrawBarNumHits (0.0,Hits.Max,Rep_MAX_BAR_WIDTH);
fprintf (Gbl.F.Rep,"<br />");
} }
} }
@ -1271,7 +1363,6 @@ static void Rep_DrawBarNumHits (float HitsNum,float HitsMax,
fprintf (Gbl.F.Rep,"&nbsp;"); fprintf (Gbl.F.Rep,"&nbsp;");
Str_WriteFloatNum (Gbl.F.Rep,HitsNum); Str_WriteFloatNum (Gbl.F.Rep,HitsNum);
} }
fprintf (Gbl.F.Rep,"<br />");
} }
/*****************************************************************************/ /*****************************************************************************/

View File

@ -273,9 +273,11 @@ void Sta_LogAccess (const char *Comments)
/***** Insert access into database *****/ /***** Insert access into database *****/
/* Log access in historical log (log_full) */ /* 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)" "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')", "'%u',NOW(),'%ld','%ld','%s')",
Act_Actions[Gbl.Action.Act].ActCod, Act_Actions[Gbl.Action.Act].ActCod,
Gbl.CurrentCty.Cty.CtyCod, Gbl.CurrentCty.Cty.CtyCod,
@ -298,9 +300,11 @@ void Sta_LogAccess (const char *Comments)
LogCod = DB_QueryINSERTandReturnCode (Query,"can not log access (full)"); LogCod = DB_QueryINSERTandReturnCode (Query,"can not log access (full)");
/* Log access in recent log (log_recent) */ /* 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)" "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')", "'%u',NOW(),'%ld','%ld','%s')",
LogCod,Act_Actions[Gbl.Action.Act].ActCod, LogCod,Act_Actions[Gbl.Action.Act].ActCod,
Gbl.CurrentCty.Cty.CtyCod, Gbl.CurrentCty.Cty.CtyCod,
@ -3002,8 +3006,8 @@ static void Sta_ShowNumHitsPerAction (unsigned long NumRows,
row = mysql_fetch_row (mysql_res); row = mysql_fetch_row (mysql_res);
/* Write the action */ /* Write the action */
if (sscanf (row[0],"%ld",&ActCod) != 1) ActCod = Str_ConvertStrCodToLongCod (row[0]);
Lay_ShowErrorAndExit ("Wrong action code.");
if (ActCod >= 0) if (ActCod >= 0)
fprintf (Gbl.F.Out,"<tr>" fprintf (Gbl.F.Out,"<tr>"
"<td class=\"LOG RIGHT_TOP\">" "<td class=\"LOG RIGHT_TOP\">"