mirror of https://github.com/acanas/swad-core.git
Version 16.6
This commit is contained in:
parent
3f41ddb1d9
commit
999d53defe
|
@ -143,13 +143,14 @@
|
||||||
/****************************** Public constants *****************************/
|
/****************************** Public constants *****************************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
#define Log_PLATFORM_VERSION "SWAD 16.5 (2016-10-02)"
|
#define Log_PLATFORM_VERSION "SWAD 16.6 (2016-10-02)"
|
||||||
#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.6: Oct 02, 2016 Hits in historic courses in user's usage report. (205432 lines)
|
||||||
Version 16.5: Oct 02, 2016 Changes in hits in current courses in user's usage report. (205364 lines)
|
Version 16.5: Oct 02, 2016 Changes in hits in current courses in user's usage report. (205364 lines)
|
||||||
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)
|
||||||
|
|
|
@ -1999,7 +1999,7 @@ bool Crs_GetDataOfCourseByCod (struct Course *Crs)
|
||||||
unsigned long NumRows;
|
unsigned long NumRows;
|
||||||
bool CrsFound = false;
|
bool CrsFound = false;
|
||||||
|
|
||||||
if (Crs->CrsCod < 0)
|
if (Crs->CrsCod <= 0)
|
||||||
{
|
{
|
||||||
Crs->CrsCod = -1L;
|
Crs->CrsCod = -1L;
|
||||||
Crs->DegCod = -1L;
|
Crs->DegCod = -1L;
|
||||||
|
|
428
swad_report.c
428
swad_report.c
|
@ -77,20 +77,25 @@ extern struct Globals Gbl;
|
||||||
static void Rep_ShowOrPrintMyUsageReport (Rep_SeeOrPrint_t SeeOrPrint);
|
static void Rep_ShowOrPrintMyUsageReport (Rep_SeeOrPrint_t SeeOrPrint);
|
||||||
static void Rep_PutIconToPrintMyUsageReport (void);
|
static void Rep_PutIconToPrintMyUsageReport (void);
|
||||||
|
|
||||||
|
static unsigned long Rep_GetMaxHitsPerYear (const char *BrowserTimeZone,
|
||||||
|
time_t FirstClickTimeUTC);
|
||||||
static void Rep_GetAndWriteCurrentCrssOfAUsr (const struct UsrData *UsrDat,Rol_Role_t Role,
|
static void Rep_GetAndWriteCurrentCrssOfAUsr (const struct UsrData *UsrDat,Rol_Role_t Role,
|
||||||
const char *BrowserTimeZone,
|
const char *BrowserTimeZone,
|
||||||
time_t FirstClickTimeUTC,
|
time_t FirstClickTimeUTC,
|
||||||
struct tm *tm_FirstClickTime,
|
struct tm *tm_FirstClickTime,
|
||||||
unsigned long MaxHitsPerYear);
|
unsigned long MaxHitsPerYear);
|
||||||
static void Rep_WriteRowCrsData (MYSQL_ROW row,
|
static void Rep_GetAndWriteHistoricCrssOfAUsr (const struct UsrData *UsrDat,Rol_Role_t Role,
|
||||||
|
const char *BrowserTimeZone,
|
||||||
|
time_t FirstClickTimeUTC,
|
||||||
|
struct tm *tm_FirstClickTime,
|
||||||
|
unsigned long MaxHitsPerYear);
|
||||||
|
static void Rep_WriteRowCrsData (long CrsCod,Rol_Role_t Role,
|
||||||
const char *BrowserTimeZone,
|
const char *BrowserTimeZone,
|
||||||
time_t FirstClickTimeUTC,
|
time_t FirstClickTimeUTC,
|
||||||
struct tm *tm_FirstClickTime,
|
struct tm *tm_FirstClickTime,
|
||||||
unsigned long MaxHitsPerYear);
|
unsigned long MaxHitsPerYear);
|
||||||
|
|
||||||
static unsigned long Rep_GetMaxHitsPerYear (const char *BrowserTimeZone,
|
static void Rep_ShowMyHitsPerYear (bool AnyCourse,long CrsCod,Rol_Role_t Role,
|
||||||
time_t FirstClickTimeUTC);
|
|
||||||
static void Rep_ShowMyHitsPerYear (long CrsCod,
|
|
||||||
const char *BrowserTimeZone,
|
const char *BrowserTimeZone,
|
||||||
time_t FirstClickTimeUTC,
|
time_t FirstClickTimeUTC,
|
||||||
struct tm *tm_FirstClickTime,
|
struct tm *tm_FirstClickTime,
|
||||||
|
@ -141,12 +146,6 @@ static void Rep_ShowOrPrintMyUsageReport (Rep_SeeOrPrint_t SeeOrPrint)
|
||||||
extern const char *Txt_message;
|
extern const char *Txt_message;
|
||||||
extern const char *Txt_messages;
|
extern const char *Txt_messages;
|
||||||
extern const char *Txt_Courses;
|
extern const char *Txt_Courses;
|
||||||
extern const char *Txt_USER_in_COURSE;
|
|
||||||
extern const char *Txt_ROLES_SINGUL_Abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
|
|
||||||
extern const char *Txt_course;
|
|
||||||
extern const char *Txt_courses;
|
|
||||||
extern const char *Txt_teachers_ABBREVIATION;
|
|
||||||
extern const char *Txt_students_ABBREVIATION;
|
|
||||||
extern const char *Txt_Hits;
|
extern const char *Txt_Hits;
|
||||||
char BrowserTimeZone[Dat_MAX_BYTES_TIME_ZONE+1];
|
char BrowserTimeZone[Dat_MAX_BYTES_TIME_ZONE+1];
|
||||||
unsigned NumID;
|
unsigned NumID;
|
||||||
|
@ -157,7 +156,6 @@ static void Rep_ShowOrPrintMyUsageReport (Rep_SeeOrPrint_t SeeOrPrint)
|
||||||
unsigned NumFiles;
|
unsigned NumFiles;
|
||||||
unsigned NumPublicFiles;
|
unsigned NumPublicFiles;
|
||||||
Rol_Role_t Role;
|
Rol_Role_t Role;
|
||||||
unsigned NumCrss;
|
|
||||||
unsigned long MaxHitsPerYear;
|
unsigned long MaxHitsPerYear;
|
||||||
|
|
||||||
/***** Get client time zone *****/
|
/***** Get client time zone *****/
|
||||||
|
@ -337,47 +335,44 @@ static void Rep_ShowOrPrintMyUsageReport (Rep_SeeOrPrint_t SeeOrPrint)
|
||||||
|
|
||||||
fprintf (Gbl.F.Out,"</ul>");
|
fprintf (Gbl.F.Out,"</ul>");
|
||||||
|
|
||||||
/***** Courses *****/
|
/***** Current courses *****/
|
||||||
fprintf (Gbl.F.Out,"<h2>%s</h2>"
|
fprintf (Gbl.F.Out,"<h2>%s (actuales)</h2>" // TODO: Need translation!!!
|
||||||
"<ul>",
|
"<ul>",
|
||||||
Txt_Courses);
|
Txt_Courses);
|
||||||
|
|
||||||
/***** Number of courses in which the user is student/teacher *****/
|
/* Number of courses in which the user is student/teacher */
|
||||||
MaxHitsPerYear = Rep_GetMaxHitsPerYear (BrowserTimeZone,UsrFigures.FirstClickTimeUTC);
|
MaxHitsPerYear = Rep_GetMaxHitsPerYear (BrowserTimeZone,UsrFigures.FirstClickTimeUTC);
|
||||||
for (Role = Rol_STUDENT;
|
for (Role = Rol_STUDENT;
|
||||||
Role <= Rol_TEACHER;
|
Role <= Rol_TEACHER;
|
||||||
Role++)
|
Role++)
|
||||||
{
|
/* List my courses with this role */
|
||||||
NumCrss = Usr_GetNumCrssOfUsrWithARole (Gbl.Usrs.Me.UsrDat.UsrCod,Role);
|
Rep_GetAndWriteCurrentCrssOfAUsr (&Gbl.Usrs.Me.UsrDat,Role,
|
||||||
sprintf (Gbl.Title,Txt_USER_in_COURSE,Txt_ROLES_SINGUL_Abc[Role][Gbl.Usrs.Me.UsrDat.Sex]);
|
BrowserTimeZone,
|
||||||
fprintf (Gbl.F.Out,"<li>%s: %u %s",
|
UsrFigures.FirstClickTimeUTC,&tm_FirstClickTime,
|
||||||
Gbl.Title,
|
MaxHitsPerYear);
|
||||||
NumCrss,
|
|
||||||
NumCrss == 1 ? Txt_course :
|
|
||||||
Txt_courses);
|
|
||||||
if (NumCrss)
|
|
||||||
{
|
|
||||||
fprintf (Gbl.F.Out," (%u %s / %u %s)",
|
|
||||||
Usr_GetNumUsrsInCrssOfAUsr (Gbl.Usrs.Me.UsrDat.UsrCod,Role,Rol_TEACHER),
|
|
||||||
Txt_teachers_ABBREVIATION,
|
|
||||||
Usr_GetNumUsrsInCrssOfAUsr (Gbl.Usrs.Me.UsrDat.UsrCod,Role,Rol_STUDENT),
|
|
||||||
Txt_students_ABBREVIATION);
|
|
||||||
|
|
||||||
/* List my courses with this role */
|
|
||||||
Rep_GetAndWriteCurrentCrssOfAUsr (&Gbl.Usrs.Me.UsrDat,Role,
|
|
||||||
BrowserTimeZone,
|
|
||||||
UsrFigures.FirstClickTimeUTC,&tm_FirstClickTime,
|
|
||||||
MaxHitsPerYear);
|
|
||||||
}
|
|
||||||
fprintf (Gbl.F.Out,"</li>");
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf (Gbl.F.Out,"</ul>");
|
fprintf (Gbl.F.Out,"</ul>");
|
||||||
|
|
||||||
|
/***** Historic courses *****/
|
||||||
|
fprintf (Gbl.F.Out,"<h2>%s (histórico)</h2>" // TODO: Need translation!!!
|
||||||
|
"<ul>",
|
||||||
|
Txt_Courses);
|
||||||
|
|
||||||
|
/* Number of courses in which the user clicked as student/teacher */
|
||||||
|
for (Role = Rol_STUDENT;
|
||||||
|
Role <= Rol_TEACHER;
|
||||||
|
Role++)
|
||||||
|
/* List my courses with this role */
|
||||||
|
Rep_GetAndWriteHistoricCrssOfAUsr (&Gbl.Usrs.Me.UsrDat,Role,
|
||||||
|
BrowserTimeZone,
|
||||||
|
UsrFigures.FirstClickTimeUTC,&tm_FirstClickTime,
|
||||||
|
MaxHitsPerYear);
|
||||||
|
|
||||||
|
fprintf (Gbl.F.Out,"</ul>");
|
||||||
|
|
||||||
/***** Global hits *****/
|
/***** Global hits *****/
|
||||||
fprintf (Gbl.F.Out,"<h2>%s</h2>",Txt_Hits);
|
fprintf (Gbl.F.Out,"<h2>%s</h2>",Txt_Hits);
|
||||||
Rep_ShowMyHitsPerYear (-1L,
|
Rep_ShowMyHitsPerYear (true,-1L,Rol_UNKNOWN,
|
||||||
BrowserTimeZone,
|
BrowserTimeZone,
|
||||||
UsrFigures.FirstClickTimeUTC,
|
UsrFigures.FirstClickTimeUTC,
|
||||||
&tm_FirstClickTime,
|
&tm_FirstClickTime,
|
||||||
|
@ -405,133 +400,6 @@ static void Rep_PutIconToPrintMyUsageReport (void)
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/************************** Write courses of a user **************************/
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
static void Rep_GetAndWriteCurrentCrssOfAUsr (const struct UsrData *UsrDat,Rol_Role_t Role,
|
|
||||||
const char *BrowserTimeZone,
|
|
||||||
time_t FirstClickTimeUTC,
|
|
||||||
struct tm *tm_FirstClickTime,
|
|
||||||
unsigned long MaxHitsPerYear)
|
|
||||||
{
|
|
||||||
char Query[1024];
|
|
||||||
MYSQL_RES *mysql_res;
|
|
||||||
MYSQL_ROW row;
|
|
||||||
unsigned NumCrss;
|
|
||||||
unsigned NumCrs;
|
|
||||||
|
|
||||||
/***** Get courses of a user from database *****/
|
|
||||||
/*
|
|
||||||
SELECT degrees.DegCod 0
|
|
||||||
courses.CrsCod 1
|
|
||||||
courses.FullName 2
|
|
||||||
courses.Year 3
|
|
||||||
degrees.FullName 4
|
|
||||||
*/
|
|
||||||
sprintf (Query,"SELECT degrees.DegCod,courses.CrsCod,courses.FullName,courses.Year,degrees.FullName"
|
|
||||||
" FROM crs_usr,courses,degrees"
|
|
||||||
" WHERE crs_usr.UsrCod='%ld'"
|
|
||||||
" AND crs_usr.Role='%u'"
|
|
||||||
" AND crs_usr.CrsCod=courses.CrsCod"
|
|
||||||
" AND courses.DegCod=degrees.DegCod"
|
|
||||||
" ORDER BY degrees.FullName,courses.Year,courses.FullName",
|
|
||||||
UsrDat->UsrCod,(unsigned) Role);
|
|
||||||
|
|
||||||
/***** List the courses (one row per course) *****/
|
|
||||||
if ((NumCrss = (unsigned) DB_QuerySELECT (Query,&mysql_res,"can not get courses of a user")))
|
|
||||||
{
|
|
||||||
/* Heading row */
|
|
||||||
fprintf (Gbl.F.Out,"<ol>");
|
|
||||||
|
|
||||||
/* Write courses */
|
|
||||||
for (NumCrs = 1;
|
|
||||||
NumCrs <= NumCrss;
|
|
||||||
NumCrs++)
|
|
||||||
{
|
|
||||||
/* Get next course */
|
|
||||||
row = mysql_fetch_row (mysql_res);
|
|
||||||
|
|
||||||
/* Write data of this course */
|
|
||||||
Rep_WriteRowCrsData (row,
|
|
||||||
BrowserTimeZone,FirstClickTimeUTC,tm_FirstClickTime,
|
|
||||||
MaxHitsPerYear);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* End table */
|
|
||||||
fprintf (Gbl.F.Out,"</ol>");
|
|
||||||
}
|
|
||||||
|
|
||||||
/***** Free structure that stores the query result *****/
|
|
||||||
DB_FreeMySQLResult (&mysql_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/************** Write the data of a course (result of a query) ***************/
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
static void Rep_WriteRowCrsData (MYSQL_ROW row,
|
|
||||||
const char *BrowserTimeZone,
|
|
||||||
time_t FirstClickTimeUTC,
|
|
||||||
struct tm *tm_FirstClickTime,
|
|
||||||
unsigned long MaxHitsPerYear)
|
|
||||||
{
|
|
||||||
extern const char *Txt_YEAR_OF_DEGREE[1+Deg_MAX_YEARS_PER_DEGREE];
|
|
||||||
extern const char *Txt_teachers_ABBREVIATION;
|
|
||||||
extern const char *Txt_students_ABBREVIATION;
|
|
||||||
struct Degree Deg;
|
|
||||||
long CrsCod;
|
|
||||||
unsigned Year;
|
|
||||||
unsigned NumTchs;
|
|
||||||
unsigned NumStds;
|
|
||||||
|
|
||||||
/*
|
|
||||||
SELECT degrees.DegCod 0
|
|
||||||
courses.CrsCod 1
|
|
||||||
courses.FullName 2
|
|
||||||
courses.Year 3
|
|
||||||
degrees.FullName 4
|
|
||||||
*/
|
|
||||||
|
|
||||||
/***** Get degree code (row[0]) *****/
|
|
||||||
if ((Deg.DegCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
|
|
||||||
Lay_ShowErrorAndExit ("Wrong code of degree.");
|
|
||||||
if (!Deg_GetDataOfDegreeByCod (&Deg))
|
|
||||||
Lay_ShowErrorAndExit ("Degree not found.");
|
|
||||||
|
|
||||||
/***** Get course code (row[1]) *****/
|
|
||||||
if ((CrsCod = Str_ConvertStrCodToLongCod (row[1])) < 0)
|
|
||||||
Lay_ShowErrorAndExit ("Wrong code of course.");
|
|
||||||
|
|
||||||
/***** Get number of teachers and students in this course *****/
|
|
||||||
NumTchs = Usr_GetNumUsrsInCrs (Rol_TEACHER,CrsCod);
|
|
||||||
NumStds = Usr_GetNumUsrsInCrs (Rol_STUDENT,CrsCod);
|
|
||||||
|
|
||||||
/***** Start row *****/
|
|
||||||
fprintf (Gbl.F.Out,"<li>");
|
|
||||||
|
|
||||||
/***** Write course full name (row[2]) *****/
|
|
||||||
fprintf (Gbl.F.Out,"<strong>%s</strong> -",row[2]);
|
|
||||||
|
|
||||||
/***** Write year (row[3]) *****/
|
|
||||||
if ((Year = Deg_ConvStrToYear (row[3])))
|
|
||||||
fprintf (Gbl.F.Out," %s",Txt_YEAR_OF_DEGREE[Year]);
|
|
||||||
|
|
||||||
/***** Write degree full name (row[4]) *****/
|
|
||||||
fprintf (Gbl.F.Out," %s",row[4]);
|
|
||||||
|
|
||||||
/***** Write number of teachers / students in course *****/
|
|
||||||
fprintf (Gbl.F.Out," (%u %s / %u %s)<br />",
|
|
||||||
NumTchs,Txt_teachers_ABBREVIATION,
|
|
||||||
NumStds,Txt_students_ABBREVIATION);
|
|
||||||
|
|
||||||
/***** Write hits per year for this course *****/
|
|
||||||
Rep_ShowMyHitsPerYear (CrsCod,
|
|
||||||
BrowserTimeZone,FirstClickTimeUTC,tm_FirstClickTime,
|
|
||||||
MaxHitsPerYear);
|
|
||||||
|
|
||||||
fprintf (Gbl.F.Out,"</li>");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/************ Get the maximum number of hits per course-year-role ************/
|
/************ Get the maximum number of hits per course-year-role ************/
|
||||||
|
@ -549,12 +417,12 @@ static unsigned long Rep_GetMaxHitsPerYear (const char *BrowserTimeZone,
|
||||||
sprintf (Query,"SELECT MAX(N) FROM (SELECT "
|
sprintf (Query,"SELECT MAX(N) FROM (SELECT "
|
||||||
"CrsCod,"
|
"CrsCod,"
|
||||||
"YEAR(CONVERT_TZ(ClickTime,@@session.time_zone,'%s')) AS Year,"
|
"YEAR(CONVERT_TZ(ClickTime,@@session.time_zone,'%s')) AS Year,"
|
||||||
|
"Role,"
|
||||||
"COUNT(*) AS N"
|
"COUNT(*) AS N"
|
||||||
" FROM log_full"
|
" FROM log_full"
|
||||||
" WHERE ClickTime>=FROM_UNIXTIME('%ld')"
|
" WHERE ClickTime>=FROM_UNIXTIME('%ld')"
|
||||||
" AND UsrCod='%ld'"
|
" AND UsrCod='%ld'"
|
||||||
" AND CrsCod>'0'"
|
" GROUP BY CrsCod,Year,Role)"
|
||||||
" GROUP BY CrsCod,Year)"
|
|
||||||
" AS hits_per_crs_year",
|
" AS hits_per_crs_year",
|
||||||
BrowserTimeZone,
|
BrowserTimeZone,
|
||||||
(long) FirstClickTimeUTC,
|
(long) FirstClickTimeUTC,
|
||||||
|
@ -570,11 +438,216 @@ static unsigned long Rep_GetMaxHitsPerYear (const char *BrowserTimeZone,
|
||||||
return MaxHitsPerYear;
|
return MaxHitsPerYear;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/************************** Write courses of a user **************************/
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static void Rep_GetAndWriteCurrentCrssOfAUsr (const struct UsrData *UsrDat,Rol_Role_t Role,
|
||||||
|
const char *BrowserTimeZone,
|
||||||
|
time_t FirstClickTimeUTC,
|
||||||
|
struct tm *tm_FirstClickTime,
|
||||||
|
unsigned long MaxHitsPerYear)
|
||||||
|
{
|
||||||
|
extern const char *Txt_USER_in_COURSE;
|
||||||
|
extern const char *Txt_ROLES_SINGUL_Abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
|
||||||
|
extern const char *Txt_course;
|
||||||
|
extern const char *Txt_courses;
|
||||||
|
extern const char *Txt_teachers_ABBREVIATION;
|
||||||
|
extern const char *Txt_students_ABBREVIATION;
|
||||||
|
char Query[1024];
|
||||||
|
MYSQL_RES *mysql_res;
|
||||||
|
MYSQL_ROW row;
|
||||||
|
unsigned NumCrss;
|
||||||
|
unsigned NumCrs;
|
||||||
|
long CrsCod;
|
||||||
|
|
||||||
|
NumCrss = Usr_GetNumCrssOfUsrWithARole (UsrDat->UsrCod,Role);
|
||||||
|
sprintf (Gbl.Title,Txt_USER_in_COURSE,Txt_ROLES_SINGUL_Abc[Role][Gbl.Usrs.Me.UsrDat.Sex]);
|
||||||
|
fprintf (Gbl.F.Out,"<li>%s %u %s",
|
||||||
|
Gbl.Title,
|
||||||
|
NumCrss,
|
||||||
|
NumCrss == 1 ? Txt_course :
|
||||||
|
Txt_courses);
|
||||||
|
if (NumCrss)
|
||||||
|
{
|
||||||
|
fprintf (Gbl.F.Out," (%u %s / %u %s)",
|
||||||
|
Usr_GetNumUsrsInCrssOfAUsr (Gbl.Usrs.Me.UsrDat.UsrCod,Role,Rol_TEACHER),
|
||||||
|
Txt_teachers_ABBREVIATION,
|
||||||
|
Usr_GetNumUsrsInCrssOfAUsr (Gbl.Usrs.Me.UsrDat.UsrCod,Role,Rol_STUDENT),
|
||||||
|
Txt_students_ABBREVIATION);
|
||||||
|
|
||||||
|
/***** Get courses of a user from database *****/
|
||||||
|
sprintf (Query,"SELECT courses.CrsCod,degrees.FullName,courses.Year,courses.FullName"
|
||||||
|
" FROM crs_usr,courses,degrees"
|
||||||
|
" WHERE crs_usr.UsrCod='%ld'"
|
||||||
|
" AND crs_usr.Role='%u'"
|
||||||
|
" AND crs_usr.CrsCod=courses.CrsCod"
|
||||||
|
" AND courses.DegCod=degrees.DegCod"
|
||||||
|
" ORDER BY degrees.FullName,courses.Year,courses.FullName",
|
||||||
|
UsrDat->UsrCod,(unsigned) Role);
|
||||||
|
|
||||||
|
/***** List the courses (one row per course) *****/
|
||||||
|
if ((NumCrss = (unsigned) DB_QuerySELECT (Query,&mysql_res,"can not get courses of a user")))
|
||||||
|
{
|
||||||
|
/* Heading row */
|
||||||
|
fprintf (Gbl.F.Out,"<ol>");
|
||||||
|
|
||||||
|
/* Write courses */
|
||||||
|
for (NumCrs = 1;
|
||||||
|
NumCrs <= NumCrss;
|
||||||
|
NumCrs++)
|
||||||
|
{
|
||||||
|
/* Get next course */
|
||||||
|
row = mysql_fetch_row (mysql_res);
|
||||||
|
|
||||||
|
/* Get course code (row[0]) */
|
||||||
|
CrsCod = Str_ConvertStrCodToLongCod (row[0]);
|
||||||
|
|
||||||
|
/* Write data of this course */
|
||||||
|
Rep_WriteRowCrsData (CrsCod,Role,
|
||||||
|
BrowserTimeZone,FirstClickTimeUTC,tm_FirstClickTime,
|
||||||
|
MaxHitsPerYear);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* End table */
|
||||||
|
fprintf (Gbl.F.Out,"</ol>");
|
||||||
|
}
|
||||||
|
|
||||||
|
/***** Free structure that stores the query result *****/
|
||||||
|
DB_FreeMySQLResult (&mysql_res);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf (Gbl.F.Out,"</li>");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/************************** Write courses of a user **************************/
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static void Rep_GetAndWriteHistoricCrssOfAUsr (const struct UsrData *UsrDat,Rol_Role_t Role,
|
||||||
|
const char *BrowserTimeZone,
|
||||||
|
time_t FirstClickTimeUTC,
|
||||||
|
struct tm *tm_FirstClickTime,
|
||||||
|
unsigned long MaxHitsPerYear)
|
||||||
|
{
|
||||||
|
extern const char *Txt_ROLES_SINGUL_abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
|
||||||
|
char Query[1024];
|
||||||
|
MYSQL_RES *mysql_res;
|
||||||
|
MYSQL_ROW row;
|
||||||
|
unsigned NumCrss;
|
||||||
|
unsigned NumCrs;
|
||||||
|
long CrsCod;
|
||||||
|
|
||||||
|
/***** Get courses of a user from database *****/
|
||||||
|
sprintf (Query,"SELECT CrsCod,"
|
||||||
|
"COUNT(*) AS N"
|
||||||
|
" FROM log_full"
|
||||||
|
" WHERE UsrCod='%ld' AND Role='%u'"
|
||||||
|
" GROUP BY CrsCod ORDER BY N DESC",
|
||||||
|
UsrDat->UsrCod,(unsigned) Role);
|
||||||
|
|
||||||
|
/***** List the courses (one row per course) *****/
|
||||||
|
if ((NumCrss = (unsigned) DB_QuerySELECT (Query,&mysql_res,"can not get courses of a user")))
|
||||||
|
{
|
||||||
|
/* Heading row */
|
||||||
|
sprintf (Gbl.Title,"Accesos como %s", // TODO: Need translation
|
||||||
|
Txt_ROLES_SINGUL_abc[Role][Gbl.Usrs.Me.UsrDat.Sex]);
|
||||||
|
fprintf (Gbl.F.Out,"<li>%s:"
|
||||||
|
"<ol>",
|
||||||
|
Gbl.Title);
|
||||||
|
|
||||||
|
/* Write courses */
|
||||||
|
for (NumCrs = 1;
|
||||||
|
NumCrs <= NumCrss;
|
||||||
|
NumCrs++)
|
||||||
|
{
|
||||||
|
/* Get next course */
|
||||||
|
row = mysql_fetch_row (mysql_res);
|
||||||
|
|
||||||
|
/* Get course code (row[0]) */
|
||||||
|
CrsCod = Str_ConvertStrCodToLongCod (row[0]);
|
||||||
|
|
||||||
|
/* Write data of this course */
|
||||||
|
Rep_WriteRowCrsData (CrsCod,Role,
|
||||||
|
BrowserTimeZone,FirstClickTimeUTC,tm_FirstClickTime,
|
||||||
|
MaxHitsPerYear);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* End of list */
|
||||||
|
fprintf (Gbl.F.Out,"</ol>"
|
||||||
|
"</li>");
|
||||||
|
}
|
||||||
|
|
||||||
|
/***** Free structure that stores the query result *****/
|
||||||
|
DB_FreeMySQLResult (&mysql_res);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/************** Write the data of a course (result of a query) ***************/
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static void Rep_WriteRowCrsData (long CrsCod,Rol_Role_t Role,
|
||||||
|
const char *BrowserTimeZone,
|
||||||
|
time_t FirstClickTimeUTC,
|
||||||
|
struct tm *tm_FirstClickTime,
|
||||||
|
unsigned long MaxHitsPerYear)
|
||||||
|
{
|
||||||
|
extern const char *Txt_YEAR_OF_DEGREE[1+Deg_MAX_YEARS_PER_DEGREE];
|
||||||
|
extern const char *Txt_teachers_ABBREVIATION;
|
||||||
|
extern const char *Txt_students_ABBREVIATION;
|
||||||
|
struct Course Crs;
|
||||||
|
struct Degree Deg;
|
||||||
|
|
||||||
|
/***** Get course data *****/
|
||||||
|
Crs.CrsCod = CrsCod;
|
||||||
|
Crs_GetDataOfCourseByCod (&Crs);
|
||||||
|
|
||||||
|
/***** Get degree data *****/
|
||||||
|
Deg.DegCod = Crs.DegCod;
|
||||||
|
Deg_GetDataOfDegreeByCod (&Deg);
|
||||||
|
|
||||||
|
/***** Start row *****/
|
||||||
|
fprintf (Gbl.F.Out,"<li>");
|
||||||
|
|
||||||
|
if (CrsCod > 0) // CrsCod > 0 in log ==> course selected
|
||||||
|
{
|
||||||
|
if (Crs.CrsCod > 0) // Course exists
|
||||||
|
{
|
||||||
|
/***** Write course full name *****/
|
||||||
|
fprintf (Gbl.F.Out,"<strong>%s</strong> -",Crs.FullName);
|
||||||
|
|
||||||
|
/***** Write year *****/
|
||||||
|
if (Crs.Year)
|
||||||
|
fprintf (Gbl.F.Out," %s",Txt_YEAR_OF_DEGREE[Crs.Year]);
|
||||||
|
|
||||||
|
/***** Write degree full name *****/
|
||||||
|
fprintf (Gbl.F.Out," %s",Deg.FullName);
|
||||||
|
|
||||||
|
/***** Write number of teachers / students in course *****/
|
||||||
|
fprintf (Gbl.F.Out," (%u %s / %u %s)",
|
||||||
|
Usr_GetNumUsrsInCrs (Rol_TEACHER,Crs.CrsCod),Txt_teachers_ABBREVIATION,
|
||||||
|
Usr_GetNumUsrsInCrs (Rol_STUDENT,Crs.CrsCod),Txt_students_ABBREVIATION);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fprintf (Gbl.F.Out,"(asignatura desconocida/eliminada)"); // TODO: Need translation
|
||||||
|
}
|
||||||
|
else // CrsCod <= 0 in log ==> no course selected
|
||||||
|
fprintf (Gbl.F.Out,"(asignatura no seleccionada)"); // TODO: Need translation
|
||||||
|
|
||||||
|
/***** Write hits per year for this course *****/
|
||||||
|
fprintf (Gbl.F.Out,"<br />");
|
||||||
|
Rep_ShowMyHitsPerYear (false,CrsCod,Role,
|
||||||
|
BrowserTimeZone,FirstClickTimeUTC,tm_FirstClickTime,
|
||||||
|
MaxHitsPerYear);
|
||||||
|
|
||||||
|
fprintf (Gbl.F.Out,"</li>");
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/********************** Write my hits grouped by years ***********************/
|
/********************** Write my hits grouped by years ***********************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static void Rep_ShowMyHitsPerYear (long CrsCod,
|
static void Rep_ShowMyHitsPerYear (bool AnyCourse,long CrsCod,Rol_Role_t Role,
|
||||||
const char *BrowserTimeZone,
|
const char *BrowserTimeZone,
|
||||||
time_t FirstClickTimeUTC,
|
time_t FirstClickTimeUTC,
|
||||||
struct tm *tm_FirstClickTime,
|
struct tm *tm_FirstClickTime,
|
||||||
|
@ -582,6 +655,7 @@ static void Rep_ShowMyHitsPerYear (long CrsCod,
|
||||||
{
|
{
|
||||||
char Query[1024];
|
char Query[1024];
|
||||||
char SubQueryCrs[128];
|
char SubQueryCrs[128];
|
||||||
|
char SubQueryRol[128];
|
||||||
MYSQL_RES *mysql_res;
|
MYSQL_RES *mysql_res;
|
||||||
MYSQL_ROW row;
|
MYSQL_ROW row;
|
||||||
unsigned long NumRows;
|
unsigned long NumRows;
|
||||||
|
@ -592,21 +666,27 @@ static void Rep_ShowMyHitsPerYear (long CrsCod,
|
||||||
struct Sta_Hits Hits;
|
struct Sta_Hits Hits;
|
||||||
|
|
||||||
/***** Make the query *****/
|
/***** Make the query *****/
|
||||||
if (CrsCod > 0)
|
if (AnyCourse)
|
||||||
sprintf (SubQueryCrs," AND CrsCod='%ld'",CrsCod);
|
|
||||||
else
|
|
||||||
SubQueryCrs[0] = '\0';
|
SubQueryCrs[0] = '\0';
|
||||||
|
else
|
||||||
|
sprintf (SubQueryCrs," AND CrsCod='%ld'",CrsCod);
|
||||||
|
|
||||||
|
if (Role == Rol_UNKNOWN) // Here Rol_UNKNOWN means any role
|
||||||
|
SubQueryRol[0] = '\0';
|
||||||
|
else
|
||||||
|
sprintf (SubQueryRol," AND Role='%u'",(unsigned) Role);
|
||||||
|
|
||||||
sprintf (Query,"SELECT SQL_NO_CACHE "
|
sprintf (Query,"SELECT SQL_NO_CACHE "
|
||||||
"YEAR(CONVERT_TZ(ClickTime,@@session.time_zone,'%s')) AS Year,"
|
"YEAR(CONVERT_TZ(ClickTime,@@session.time_zone,'%s')) AS Year,"
|
||||||
"COUNT(*) FROM log_full"
|
"COUNT(*) FROM log_full"
|
||||||
" WHERE ClickTime>=FROM_UNIXTIME('%ld')"
|
" WHERE ClickTime>=FROM_UNIXTIME('%ld')"
|
||||||
" AND UsrCod='%ld'%s"
|
" AND UsrCod='%ld'%s%s"
|
||||||
" GROUP BY Year DESC",
|
" GROUP BY Year DESC",
|
||||||
BrowserTimeZone,
|
BrowserTimeZone,
|
||||||
(long) FirstClickTimeUTC,
|
(long) FirstClickTimeUTC,
|
||||||
Gbl.Usrs.Me.UsrDat.UsrCod,
|
Gbl.Usrs.Me.UsrDat.UsrCod,
|
||||||
SubQueryCrs);
|
SubQueryCrs,
|
||||||
|
SubQueryRol);
|
||||||
NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get clicks");
|
NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get clicks");
|
||||||
|
|
||||||
/***** Initialize first year *****/
|
/***** Initialize first year *****/
|
||||||
|
|
Loading…
Reference in New Issue