From a266d553412b7cc1794a6a9430f845219937a192 Mon Sep 17 00:00:00 2001 From: acanas Date: Fri, 16 Jul 2021 13:24:42 +0200 Subject: [PATCH] Version 20.95.2: Jul 16, 2021 Queries moved to module swad_exam_database. --- swad_changelog.h | 3 +- swad_exam_database.c | 194 ++++++++++++++++++++++++++++++++++++++++++- swad_exam_database.h | 11 ++- swad_exam_result.c | 149 ++------------------------------- 4 files changed, 211 insertions(+), 146 deletions(-) diff --git a/swad_changelog.h b/swad_changelog.h index 1fbdfe2a..9f1c3bb2 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -602,13 +602,14 @@ TODO: FIX BUG, URGENT! En las fechas como par TODO: En las encuestas, que los estudiantes no puedan ver los resultados hasta que no finalice el plazo. */ -#define Log_PLATFORM_VERSION "SWAD 20.95.1 (2021-07-15)" +#define Log_PLATFORM_VERSION "SWAD 20.95.2 (2021-07-16)" #define CSS_FILE "swad20.45.css" #define JS_FILE "swad20.69.1.js" /* TODO: Rename CENTRE to CENTER in help wiki. TODO: Rename ASSESSMENT.Announcements to ASSESSMENT.Calls_for_exams + Version 20.95.2: Jul 16, 2021 Queries moved to module swad_exam_database. (314137 lines) Version 20.95.1: Jul 15, 2021 Queries moved to module swad_exam_database. (314082 lines) Version 20.95: Jul 08, 2021 New module swad_exam_database for database queries related to exams. (313981 lines) Version 20.94.10: Jun 29, 2021 Code refactoring related to HTML output. (313860 lines) diff --git a/swad_exam_database.c b/swad_exam_database.c index 89451881..ba2a83d1 100644 --- a/swad_exam_database.c +++ b/swad_exam_database.c @@ -25,14 +25,14 @@ /********************************* Headers ***********************************/ /*****************************************************************************/ -//#define _GNU_SOURCE // For asprintf -//#include // For asprintf +#define _GNU_SOURCE // For asprintf +#include // For asprintf //#include // For system, getenv, etc. //#include // For string functions //#include "swad_action.h" #include "swad_database.h" -//#include "swad_error.h" +#include "swad_error.h" #include "swad_exam_database.h" #include "swad_exam_log.h" #include "swad_exam_print.h" @@ -97,6 +97,21 @@ unsigned Exa_DB_GetSomeQstsFromSetToPrint (MYSQL_RES **mysql_res, NumQstsToPrint); } +/*****************************************************************************/ +/********** Get validity and answer type from a question in a set ************/ +/*****************************************************************************/ + +unsigned Exa_DB_GetValidityAndTypeOfQuestion (MYSQL_RES **mysql_res,long QstCod) + { + return (unsigned) + DB_QuerySELECT (mysql_res,"can not get a question", + "SELECT Invalid," // row[0] + "AnsType" // row[1] + " FROM exa_set_questions" + " WHERE QstCod=%ld", + QstCod); + } + /*****************************************************************************/ /************** Get answers text for a question in an exam set ***************/ /*****************************************************************************/ @@ -527,3 +542,176 @@ unsigned Exa_DB_GetExamLog (MYSQL_RES **mysql_res,long PrnCod) " ORDER BY exa_log.LogCod", PrnCod); } + +/*****************************************************************************/ +/*** Get all users who have answered any session question in a given exam ****/ +/*****************************************************************************/ + +unsigned Exa_DB_GetAllUsrsWhoHaveMadeExam (MYSQL_RES **mysql_res,long ExaCod) + { + return (unsigned) + DB_QuerySELECT (mysql_res,"can not get users in exam", + "SELECT users.UsrCod" // row[0] + " FROM (SELECT DISTINCT exa_prints.UsrCod AS UsrCod" + " FROM exa_prints," + "exa_sessions," + "exa_exams" + " WHERE exa_sessions.ExaCod=%ld" + " AND exa_sessions.SesCod=exa_prints.SesCod" + " AND exa_sessions.ExaCod=exa_exams.ExaCod" + " AND exa_exams.CrsCod=%ld) AS users," // Extra check + "usr_data" + " WHERE users.UsrCod=usr_data.UsrCod" + " ORDER BY usr_data.Surname1," + "usr_data.Surname2," + "usr_data.FirstName", + ExaCod, + Gbl.Hierarchy.Crs.CrsCod); + } + +/*****************************************************************************/ +/*** Get all users who have answered any question in a given exam session ****/ +/*****************************************************************************/ + +unsigned Exa_DB_GetAllUsrsWhoHaveMadeSession (MYSQL_RES **mysql_res,long SesCod) + { + return (unsigned) + DB_QuerySELECT (mysql_res,"can not get users in session", + "SELECT users.UsrCod" // row[0] + " FROM (SELECT exa_prints.UsrCod AS UsrCod" + " FROM exa_prints,exa_sessions,exa_exams" + " WHERE exa_prints.SesCod=%ld" + " AND exa_prints.SesCod=exa_sessions.SesCod" + " AND exa_sessions.ExaCod=exa_exams.ExaCod" + " AND exa_exams.CrsCod=%ld) AS users," // Extra check + "usr_data" + " WHERE users.UsrCod=usr_data.UsrCod" + " ORDER BY usr_data.Surname1," + "usr_data.Surname2," + "usr_data.FirstName", + SesCod, + Gbl.Hierarchy.Crs.CrsCod); + } + +/*****************************************************************************/ +/********* Show the sessions results of a user in the current course *********/ +/*****************************************************************************/ + +unsigned Exa_DB_GetResults (MYSQL_RES **mysql_res, + Usr_MeOrOther_t MeOrOther, + long SesCod, // <= 0 ==> any + long ExaCod, // <= 0 ==> any + const char *ExamsSelectedCommas) + { + char *SesSubQuery; + char *HidSesSubQuery; + char *HidExaSubQuery; + char *ExaSubQuery; + long UsrCod; + unsigned NumResults; + + /***** Set user *****/ + UsrCod = (MeOrOther == Usr_ME) ? Gbl.Usrs.Me.UsrDat.UsrCod : + Gbl.Usrs.Other.UsrDat.UsrCod; + + /***** Build sessions subquery *****/ + if (SesCod > 0) // One unique session + { + if (asprintf (&SesSubQuery," AND exa_prints.SesCod=%ld",SesCod) < 0) + Err_NotEnoughMemoryExit (); + } + else // All sessions of selected exams + { + if (asprintf (&SesSubQuery,"%s","") < 0) + Err_NotEnoughMemoryExit (); + } + + /***** Subquery: get hidden sessions? + · A student will not be able to see their results in hidden sessions + · A teacher will be able to see results from other users even in hidden sessions + *****/ + switch (MeOrOther) + { + case Usr_ME: // A student watching her/his results + if (asprintf (&HidSesSubQuery," AND exa_sessions.Hidden='N'") < 0) + Err_NotEnoughMemoryExit (); + break; + case Usr_OTHER: // A teacher/admin watching the results of other users + default: + if (asprintf (&HidSesSubQuery,"%s","") < 0) + Err_NotEnoughMemoryExit (); + break; + } + + /***** Build exams subquery *****/ + if (ExaCod > 0) // One unique exams + { + if (asprintf (&ExaSubQuery," AND exa_sessions.ExaCod=%ld",ExaCod) < 0) + Err_NotEnoughMemoryExit (); + } + else if (ExamsSelectedCommas) + { + if (ExamsSelectedCommas[0]) // Selected exams + { + if (asprintf (&ExaSubQuery," AND exa_sessions.ExaCod IN (%s)", + ExamsSelectedCommas) < 0) + Err_NotEnoughMemoryExit (); + } + else + { + if (asprintf (&ExaSubQuery,"%s","") < 0) + Err_NotEnoughMemoryExit (); + } + } + else // All exams + { + if (asprintf (&ExaSubQuery,"%s","") < 0) + Err_NotEnoughMemoryExit (); + } + + /***** Subquery: get hidden exams? + · A student will not be able to see their results in hidden exams + · A teacher will be able to see results from other users even in hidden exams + *****/ + switch (MeOrOther) + { + case Usr_ME: // A student watching her/his results + if (asprintf (&HidExaSubQuery," AND exa_exams.Hidden='N'") < 0) + Err_NotEnoughMemoryExit (); + break; + case Usr_OTHER: // A teacher/admin watching the results of other users + default: + if (asprintf (&HidExaSubQuery,"%s","") < 0) + Err_NotEnoughMemoryExit (); + break; + } + + /***** Make database query *****/ + // Do not filter by groups, because a student who has changed groups + // must be able to access exams taken in other groups + NumResults = (unsigned) + DB_QuerySELECT (mysql_res,"can not get sessions results", + "SELECT exa_prints.PrnCod" // row[0] + " FROM exa_prints,exa_sessions,exa_exams" + " WHERE exa_prints.UsrCod=%ld" + "%s" // Session subquery + " AND exa_prints.SesCod=exa_sessions.SesCod" + "%s" // Hidden sessions subquery + "%s" // Exams subquery + " AND exa_sessions.ExaCod=exa_exams.ExaCod" + "%s" // Hidden exams subquery + " AND exa_exams.CrsCod=%ld" // Extra check + " ORDER BY exa_sessions.Title", + UsrCod, + SesSubQuery, + HidSesSubQuery, + ExaSubQuery, + HidExaSubQuery, + Gbl.Hierarchy.Crs.CrsCod); + free (HidExaSubQuery); + free (ExaSubQuery); + free (HidSesSubQuery); + free (SesSubQuery); + + return NumResults; + } diff --git a/swad_exam_database.h b/swad_exam_database.h index 947f7b3d..0a91f01d 100644 --- a/swad_exam_database.h +++ b/swad_exam_database.h @@ -42,6 +42,7 @@ unsigned Exa_DB_GetExamSets (MYSQL_RES **mysql_res,long ExaCod); unsigned Exa_DB_GetSomeQstsFromSetToPrint (MYSQL_RES **mysql_res, long SetCod,unsigned NumQstsToPrint); +unsigned Exa_DB_GetValidityAndTypeOfQuestion (MYSQL_RES **mysql_res,long QstCod); unsigned Exa_DB_GetQstAnswersTextFromSet (MYSQL_RES **mysql_res,long QstCod); unsigned Exa_DB_GetQstAnswersCorrFromSet (MYSQL_RES **mysql_res,long QstCod); @@ -67,11 +68,17 @@ void Exa_DB_RemovePrintQuestionsInCrs (long CrsCod); bool Exa_DB_CheckIfSessionIsTheSameAsTheLast (long PrnCod); bool Exa_DB_CheckIfUserAgentIsTheSameAsTheLast (long PrnCod,const char *UserAgentDB); - void Exa_DB_LogAccess (long LogCod,long PrnCod,ExaLog_Action_t Action); void Exa_DB_LogSession (long LogCod,long PrnCod); void Exa_DB_LogUserAgent (long LogCod,long PrnCod,const char *UserAgentDB); - unsigned Exa_DB_GetExamLog (MYSQL_RES **mysql_res,long PrnCod); +unsigned Exa_DB_GetAllUsrsWhoHaveMadeExam (MYSQL_RES **mysql_res,long ExaCod); +unsigned Exa_DB_GetAllUsrsWhoHaveMadeSession (MYSQL_RES **mysql_res,long SesCod); +unsigned Exa_DB_GetResults (MYSQL_RES **mysql_res, + Usr_MeOrOther_t MeOrOther, + long SesCod, // <= 0 ==> any + long ExaCod, // <= 0 ==> any + const char *ExamsSelectedCommas); + #endif diff --git a/swad_exam_result.c b/swad_exam_result.c index 11dc4919..cd2fd836 100644 --- a/swad_exam_result.c +++ b/swad_exam_result.c @@ -37,6 +37,7 @@ #include "swad_date.h" #include "swad_error.h" #include "swad_exam.h" +#include "swad_exam_database.h" #include "swad_exam_log.h" #include "swad_exam_print.h" #include "swad_exam_result.h" @@ -438,22 +439,7 @@ static void ExaRes_ListAllResultsInExa (struct Exa_Exams *Exams,long ExaCod) ExaRes_ShowHeaderResults (Usr_OTHER); /***** Get all users who have answered any session question in this exam *****/ - NumUsrs = (unsigned) - DB_QuerySELECT (&mysql_res,"can not get users in exam", - "SELECT users.UsrCod" // row[0] - " FROM (SELECT DISTINCT exa_prints.UsrCod AS UsrCod" - " FROM exa_prints,exa_sessions,exa_exams" - " WHERE exa_sessions.ExaCod=%ld" - " AND exa_sessions.SesCod=exa_prints.SesCod" - " AND exa_sessions.ExaCod=exa_exams.ExaCod" - " AND exa_exams.CrsCod=%ld) AS users," // Extra check - "usr_data" - " WHERE users.UsrCod=usr_data.UsrCod" - " ORDER BY usr_data.Surname1," - "usr_data.Surname2," - "usr_data.FirstName", - ExaCod, - Gbl.Hierarchy.Crs.CrsCod); + NumUsrs = Exa_DB_GetAllUsrsWhoHaveMadeExam (&mysql_res,ExaCod); /***** List sessions results for each user *****/ for (NumUsr = 0; @@ -530,22 +516,7 @@ static void ExaRes_ListAllResultsInSes (struct Exa_Exams *Exams,long SesCod) ExaRes_ShowHeaderResults (Usr_OTHER); /***** Get all users who have answered any session question in this exam *****/ - NumUsrs = (unsigned) - DB_QuerySELECT (&mysql_res,"can not get users in session", - "SELECT users.UsrCod" // row[0] - " FROM (SELECT exa_prints.UsrCod AS UsrCod" // row[0] - " FROM exa_prints,exa_sessions,exa_exams" - " WHERE exa_prints.SesCod=%ld" - " AND exa_prints.SesCod=exa_sessions.SesCod" - " AND exa_sessions.ExaCod=exa_exams.ExaCod" - " AND exa_exams.CrsCod=%ld) AS users," // Extra check - "usr_data" - " WHERE users.UsrCod=usr_data.UsrCod" - " ORDER BY usr_data.Surname1," - "usr_data.Surname2," - "usr_data.FirstName", - SesCod, - Gbl.Hierarchy.Crs.CrsCod); + NumUsrs = Exa_DB_GetAllUsrsWhoHaveMadeSession (&mysql_res,SesCod); /***** List sessions results for each user *****/ for (NumUsr = 0; @@ -805,10 +776,6 @@ static void ExaRes_ShowResults (struct Exa_Exams *Exams, const char *ExamsSelectedCommas) { extern const char *Txt_Result; - char *SesSubQuery; - char *HidSesSubQuery; - char *HidExaSubQuery; - char *ExaSubQuery; MYSQL_RES *mysql_res; struct UsrData *UsrDat; unsigned NumResults; @@ -838,106 +805,14 @@ static void ExaRes_ShowResults (struct Exa_Exams *Exams, TotalScore.All = TotalScore.Valid = 0.0; - /***** Set user *****/ - UsrDat = (MeOrOther == Usr_ME) ? &Gbl.Usrs.Me.UsrDat : - &Gbl.Usrs.Other.UsrDat; - - /***** Build sessions subquery *****/ - if (SesCod > 0) // One unique session - { - if (asprintf (&SesSubQuery," AND exa_prints.SesCod=%ld",SesCod) < 0) - Err_NotEnoughMemoryExit (); - } - else // All sessions of selected exams - { - if (asprintf (&SesSubQuery,"%s","") < 0) - Err_NotEnoughMemoryExit (); - } - - /***** Subquery: get hidden sessions? - · A student will not be able to see their results in hidden sessions - · A teacher will be able to see results from other users even in hidden sessions - *****/ - switch (MeOrOther) - { - case Usr_ME: // A student watching her/his results - if (asprintf (&HidSesSubQuery," AND exa_sessions.Hidden='N'") < 0) - Err_NotEnoughMemoryExit (); - break; - default: // A teacher/admin watching the results of other users - if (asprintf (&HidSesSubQuery,"%s","") < 0) - Err_NotEnoughMemoryExit (); - break; - } - - /***** Build exams subquery *****/ - if (ExaCod > 0) // One unique exams - { - if (asprintf (&ExaSubQuery," AND exa_sessions.ExaCod=%ld",ExaCod) < 0) - Err_NotEnoughMemoryExit (); - } - else if (ExamsSelectedCommas) - { - if (ExamsSelectedCommas[0]) // Selected exams - { - if (asprintf (&ExaSubQuery," AND exa_sessions.ExaCod IN (%s)", - ExamsSelectedCommas) < 0) - Err_NotEnoughMemoryExit (); - } - else - { - if (asprintf (&ExaSubQuery,"%s","") < 0) - Err_NotEnoughMemoryExit (); - } - } - else // All exams - { - if (asprintf (&ExaSubQuery,"%s","") < 0) - Err_NotEnoughMemoryExit (); - } - - /***** Subquery: get hidden exams? - · A student will not be able to see their results in hidden exams - · A teacher will be able to see results from other users even in hidden exams - *****/ - switch (MeOrOther) - { - case Usr_ME: // A student watching her/his results - if (asprintf (&HidExaSubQuery," AND exa_exams.Hidden='N'") < 0) - Err_NotEnoughMemoryExit (); - break; - default: // A teacher/admin watching the results of other users - if (asprintf (&HidExaSubQuery,"%s","") < 0) - Err_NotEnoughMemoryExit (); - break; - } - /***** Make database query *****/ // Do not filter by groups, because a student who has changed groups // must be able to access exams taken in other groups - NumResults = (unsigned) - DB_QuerySELECT (&mysql_res,"can not get sessions results", - "SELECT exa_prints.PrnCod" // row[0] - " FROM exa_prints,exa_sessions,exa_exams" - " WHERE exa_prints.UsrCod=%ld" - "%s" // Session subquery - " AND exa_prints.SesCod=exa_sessions.SesCod" - "%s" // Hidden sessions subquery - "%s" // Exams subquery - " AND exa_sessions.ExaCod=exa_exams.ExaCod" - "%s" // Hidden exams subquery - " AND exa_exams.CrsCod=%ld" // Extra check - " ORDER BY exa_sessions.Title", - UsrDat->UsrCod, - SesSubQuery, - HidSesSubQuery, - ExaSubQuery, - HidExaSubQuery, - Gbl.Hierarchy.Crs.CrsCod); - free (HidExaSubQuery); - free (ExaSubQuery); - free (HidSesSubQuery); - free (SesSubQuery); + NumResults = Exa_DB_GetResults (&mysql_res,MeOrOther,SesCod,ExaCod,ExamsSelectedCommas); + + /***** Set user *****/ + UsrDat = (MeOrOther == Usr_ME) ? &Gbl.Usrs.Me.UsrDat : + &Gbl.Usrs.Other.UsrDat; /***** Show user's data *****/ HTM_TR_Begin (NULL); @@ -1571,13 +1446,7 @@ static void ExaRes_ComputeValidPrintScore (struct ExaPrn_Print *Print) Question.QstCod = Print->PrintedQuestions[QstInd].QstCod; /***** Get validity and answer type from database *****/ - QuestionExists = (DB_QuerySELECT (&mysql_res,"can not get a question", - "SELECT Invalid," // row[0] - "AnsType" // row[1] - " FROM exa_set_questions" - " WHERE QstCod=%ld", - Question.QstCod) != 0); - if (QuestionExists) + if ((QuestionExists = (Exa_DB_GetValidityAndTypeOfQuestion (&mysql_res,Question.QstCod) != 0))) { row = mysql_fetch_row (mysql_res);