From ef2e43cdcc1dfa04c347a7bfbb23f1ddd7b1083f Mon Sep 17 00:00:00 2001 From: acanas Date: Tue, 27 Jul 2021 21:33:09 +0200 Subject: [PATCH] Version 20.96: Jul 27, 2021 Queries moved to module swad_exam_database. --- swad_changelog.h | 3 +- swad_exam.c | 109 ++----------- swad_exam.h | 2 - swad_exam_database.c | 362 ++++++++++++++++++++++++++++++++++++++++++- swad_exam_database.h | 24 +++ swad_exam_print.c | 54 ++++--- swad_exam_set.c | 287 ++-------------------------------- swad_exam_set.h | 3 - 8 files changed, 440 insertions(+), 404 deletions(-) diff --git a/swad_changelog.h b/swad_changelog.h index a860bf01..bc7dcb0f 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.3 (2021-07-20)" +#define Log_PLATFORM_VERSION "SWAD 20.96 (2021-07-27)" #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.96: Jul 27, 2021 Queries moved to module swad_exam_database. (314247 lines) Version 20.95.3: Jul 20, 2021 Queries moved to module swad_exam_database. (314210 lines) 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) diff --git a/swad_exam.c b/swad_exam.c index 082a90c3..4b7a0475 100644 --- a/swad_exam.c +++ b/swad_exam.c @@ -795,63 +795,16 @@ static Exa_Order_t Exa_GetParamOrder (void) void Exa_GetListExams (struct Exa_Exams *Exams,Exa_Order_t SelectedOrder) { - static const char *OrderBySubQuery[Exa_NUM_ORDERS] = - { - [Exa_ORDER_BY_START_DATE] = "StartTime DESC,EndTime DESC,exa_exams.Title DESC", - [Exa_ORDER_BY_END_DATE ] = "EndTime DESC,StartTime DESC,exa_exams.Title DESC", - [Exa_ORDER_BY_TITLE ] = "exa_exams.Title", - }; MYSQL_RES *mysql_res; MYSQL_ROW row; - char *HiddenSubQuery; unsigned NumExam; /***** Free list of exams *****/ if (Exams->LstIsRead) Exa_FreeListExams (Exams); - /***** Subquery: get hidden exams depending on user's role *****/ - switch (Gbl.Usrs.Me.Role.Logged) - { - case Rol_STD: - if (asprintf (&HiddenSubQuery," AND exa_exams.Hidden='N'") < 0) - Err_NotEnoughMemoryExit (); - break; - case Rol_NET: - case Rol_TCH: - case Rol_DEG_ADM: - case Rol_CTR_ADM: - case Rol_INS_ADM: - case Rol_SYS_ADM: - if (asprintf (&HiddenSubQuery,"%s","") < 0) - Err_NotEnoughMemoryExit (); - break; - default: - Err_WrongRoleExit (); - break; - } - /***** Get list of exams from database *****/ - Exams->Num = (unsigned) - DB_QuerySELECT (&mysql_res,"can not get exams", - "SELECT exa_exams.ExaCod," // row[0] - "MIN(exa_sessions.StartTime) AS StartTime," // row[1] - "MAX(exa_sessions.EndTime) AS EndTime" // row[2] - " FROM exa_exams" - " LEFT JOIN exa_sessions" - " ON exa_exams.ExaCod=exa_sessions.ExaCod" - " WHERE exa_exams.CrsCod=%ld" - "%s" - " GROUP BY exa_exams.ExaCod" - " ORDER BY %s", - Gbl.Hierarchy.Crs.CrsCod, - HiddenSubQuery, - OrderBySubQuery[SelectedOrder]); - - /***** Free allocated memory for subquery *****/ - free (HiddenSubQuery); - - if (Exams->Num) // Exams found... + if ((Exams->Num = Exa_DB_GetListExams (&mysql_res,SelectedOrder))) // Exams found... { /***** Create list of exams *****/ if ((Exams->Lst = malloc ((size_t) Exams->Num * @@ -956,25 +909,14 @@ void Exa_GetDataOfExamByCod (struct Exa_Exam *Exam) } /***** Get exam data from database *****/ - if (DB_QuerySELECT (&mysql_res,"can not get exam data", - "SELECT ExaCod," // row[0] - "CrsCod," // row[1] - "Hidden," // row[2] - "UsrCod," // row[3] - "MaxGrade," // row[4] - "Visibility," // row[5] - "Title" // row[6] - " FROM exa_exams" - " WHERE ExaCod=%ld", - Exam->ExaCod)) // Exam found... + if (Exa_DB_GetDataOfExamByCod (&mysql_res,Exam->ExaCod)) // Exam found... { /* Get row */ row = mysql_fetch_row (mysql_res); - /* Get code of the exam (row[0]) */ + /* Get code of the exam (row[0]) + and code of the course (row[1]) */ Exam->ExaCod = Str_ConvertStrCodToLongCod (row[0]); - - /* Get code of the course (row[1]) */ Exam->CrsCod = Str_ConvertStrCodToLongCod (row[1]); /* Get whether the exam is hidden (row[2]) */ @@ -994,16 +936,13 @@ void Exa_GetDataOfExamByCod (struct Exa_Exam *Exam) /* Get the title of the exam (row[6]) */ Str_Copy (Exam->Title,row[6],sizeof (Exam->Title) - 1); - /* Get number of sets */ - Exam->NumSets = Exa_DB_GetNumSetsExam (Exam->ExaCod); - - /* Get number of questions */ - Exam->NumQsts = Exa_DB_GetNumQstsExam (Exam->ExaCod); - - /* Get number of sessions */ - Exam->NumSess = Exa_DB_GetNumSessionsInExam (Exam->ExaCod); - - /* Get number of open sessions */ + /* Get number of sets, + number of questions, + number of sessions + and number of open sessions */ + Exam->NumSets = Exa_DB_GetNumSetsExam (Exam->ExaCod); + Exam->NumQsts = Exa_DB_GetNumQstsExam (Exam->ExaCod); + Exam->NumSess = Exa_DB_GetNumSessionsInExam (Exam->ExaCod); Exam->NumOpenSess = Exa_DB_GetNumOpenSessionsInExam (Exam->ExaCod); } else @@ -1016,20 +955,14 @@ void Exa_GetDataOfExamByCod (struct Exa_Exam *Exam) if (Exam->ExaCod > 0) { /***** Get start and end times from database *****/ - if (DB_QuerySELECT (&mysql_res,"can not get exam data", - "SELECT UNIX_TIMESTAMP(MIN(StartTime))," // row[0] - "UNIX_TIMESTAMP(MAX(EndTime))" // row[1] - " FROM exa_sessions" - " WHERE ExaCod=%ld", - Exam->ExaCod)) + if (Exa_DB_GetExamStartEnd (&mysql_res,Exam->ExaCod)) { /* Get row */ row = mysql_fetch_row (mysql_res); - /* Get start date (row[0] holds the start UTC time) */ + /* Get start date (row[0] holds the start UTC time) + and end date (row[1] holds the end UTC time) */ Exam->TimeUTC[Dat_START_TIME] = Dat_GetUNIXTimeFromStr (row[0]); - - /* Get end date (row[1] holds the end UTC time) */ Exam->TimeUTC[Dat_END_TIME ] = Dat_GetUNIXTimeFromStr (row[1]); } @@ -1059,20 +992,6 @@ void Exa_FreeListExams (struct Exa_Exams *Exams) } } -/*****************************************************************************/ -/********************** Get exam text from database **************************/ -/*****************************************************************************/ - -void Exa_DB_GetExamTxt (long ExaCod,char Txt[Cns_MAX_BYTES_TEXT + 1]) - { - /***** Get text of exam from database *****/ - DB_QuerySELECTString (Txt,Cns_MAX_BYTES_TEXT,"can not get exam text", - "SELECT Txt" - " FROM exa_exams" - " WHERE ExaCod=%ld", - ExaCod); - } - /*****************************************************************************/ /*************** Ask for confirmation of removing of an exam *****************/ /*****************************************************************************/ diff --git a/swad_exam.h b/swad_exam.h index 130ca79e..90cdffb7 100644 --- a/swad_exam.h +++ b/swad_exam.h @@ -68,8 +68,6 @@ void Exa_GetDataOfExamByCod (struct Exa_Exam *Exam); void Exa_GetDataOfExamByFolder (struct Exa_Exam *Exam); void Exa_FreeListExams (struct Exa_Exams *Exams); -void Exa_DB_GetExamTxt (long ExaCod,char Txt[Cns_MAX_BYTES_TEXT + 1]); - void Exa_AskRemExam (void); void Exa_RemoveExam (void); void Exa_RemoveCrsExams (long CrsCod); diff --git a/swad_exam_database.c b/swad_exam_database.c index b083e3ae..d5b1f35a 100644 --- a/swad_exam_database.c +++ b/swad_exam_database.c @@ -33,6 +33,7 @@ #include "swad_exam_database.h" #include "swad_exam_log.h" #include "swad_exam_print.h" +#include "swad_exam_set.h" #include "swad_global.h" /*****************************************************************************/ @@ -59,6 +60,215 @@ extern struct Globals Gbl; static void Exa_DB_RemoveUsrSesResultsInCrs (long UsrCod,long CrsCod,const char *TableName); +/*****************************************************************************/ +/*********************** Get list of all the exams *************************/ +/*****************************************************************************/ + +unsigned Exa_DB_GetListExams (MYSQL_RES **mysql_res,Exa_Order_t SelectedOrder) + { + static const char *OrderBySubQuery[Exa_NUM_ORDERS] = + { + [Exa_ORDER_BY_START_DATE] = "StartTime DESC,EndTime DESC,exa_exams.Title DESC", + [Exa_ORDER_BY_END_DATE ] = "EndTime DESC,StartTime DESC,exa_exams.Title DESC", + [Exa_ORDER_BY_TITLE ] = "exa_exams.Title", + }; + char *HiddenSubQuery; + unsigned NumExams; + + /***** Subquery: get hidden exams depending on user's role *****/ + switch (Gbl.Usrs.Me.Role.Logged) + { + case Rol_STD: + if (asprintf (&HiddenSubQuery," AND exa_exams.Hidden='N'") < 0) + Err_NotEnoughMemoryExit (); + break; + case Rol_NET: + case Rol_TCH: + case Rol_DEG_ADM: + case Rol_CTR_ADM: + case Rol_INS_ADM: + case Rol_SYS_ADM: + if (asprintf (&HiddenSubQuery,"%s","") < 0) + Err_NotEnoughMemoryExit (); + break; + default: + Err_WrongRoleExit (); + break; + } + + /***** Get list of exams from database *****/ + NumExams = (unsigned) + DB_QuerySELECT (mysql_res,"can not get exams", + "SELECT exa_exams.ExaCod," // row[0] + "MIN(exa_sessions.StartTime) AS StartTime," // row[1] + "MAX(exa_sessions.EndTime) AS EndTime" // row[2] + " FROM exa_exams" + " LEFT JOIN exa_sessions" + " ON exa_exams.ExaCod=exa_sessions.ExaCod" + " WHERE exa_exams.CrsCod=%ld" + "%s" + " GROUP BY exa_exams.ExaCod" + " ORDER BY %s", + Gbl.Hierarchy.Crs.CrsCod, + HiddenSubQuery, + OrderBySubQuery[SelectedOrder]); + + /***** Free allocated memory for subquery *****/ + free (HiddenSubQuery); + + return NumExams; + } + +/*****************************************************************************/ +/********************** Get exam data using its code *************************/ +/*****************************************************************************/ + +unsigned Exa_DB_GetDataOfExamByCod (MYSQL_RES **mysql_res,long ExaCod) + { + return (unsigned) + DB_QuerySELECT (mysql_res,"can not get exam data", + "SELECT ExaCod," // row[0] + "CrsCod," // row[1] + "Hidden," // row[2] + "UsrCod," // row[3] + "MaxGrade," // row[4] + "Visibility," // row[5] + "Title" // row[6] + " FROM exa_exams" + " WHERE ExaCod=%ld", + ExaCod); + } + +/*****************************************************************************/ +/*********************** Get exam start and end times ************************/ +/*****************************************************************************/ + +unsigned Exa_DB_GetExamStartEnd (MYSQL_RES **mysql_res,long ExaCod) + { + return (unsigned) + DB_QuerySELECT (mysql_res,"can not get exam data", + "SELECT UNIX_TIMESTAMP(MIN(StartTime))," // row[0] + "UNIX_TIMESTAMP(MAX(EndTime))" // row[1] + " FROM exa_sessions" + " WHERE ExaCod=%ld", + ExaCod); + } + +/*****************************************************************************/ +/********************** Get exam text from database **************************/ +/*****************************************************************************/ + +void Exa_DB_GetExamTxt (long ExaCod,char Txt[Cns_MAX_BYTES_TEXT + 1]) + { + /***** Get text of exam from database *****/ + DB_QuerySELECTString (Txt,Cns_MAX_BYTES_TEXT,"can not get exam text", + "SELECT Txt" + " FROM exa_exams" + " WHERE ExaCod=%ld", + ExaCod); + } + +/*****************************************************************************/ +/********************** Create a new set of questions ************************/ +/*****************************************************************************/ + +long Exa_DB_CreateSet (const struct ExaSet_Set *Set,unsigned SetInd) + { + return + DB_QueryINSERTandReturnCode ("can not create new set of questions", + "INSERT INTO exa_sets" + " (ExaCod,SetInd,NumQstsToPrint,Title)" + " VALUES" + " (%ld,%u,%u,'%s')", + Set->ExaCod, + SetInd, + Set->NumQstsToPrint, + Set->Title); + } + +/*****************************************************************************/ +/******************** Update an existing set of questions ********************/ +/*****************************************************************************/ + +void Exa_DB_UpdateSet (const struct ExaSet_Set *Set) + { + DB_QueryUPDATE ("can not update set of questions", + "UPDATE exa_sets" + " SET ExaCod=%ld," + "SetInd=%u," + "NumQstsToPrint=%u," + "Title='%s'" + " WHERE SetCod=%ld", + Set->ExaCod, + Set->SetInd, + Set->NumQstsToPrint, + Set->Title, + Set->SetCod); + } + +/*****************************************************************************/ +/************************ Update set title in database ***********************/ +/*****************************************************************************/ + +void Exa_DB_UpdateSetTitle (const struct ExaSet_Set *Set, + const char NewTitle[ExaSet_MAX_BYTES_TITLE + 1]) + { + /***** Update set of questions changing old title by new title *****/ + DB_QueryUPDATE ("can not update the title of a set of questions", + "UPDATE exa_sets" + " SET Title='%s'" + " WHERE SetCod=%ld" + " AND ExaCod=%ld", // Extra check + NewTitle, + Set->SetCod, + Set->ExaCod); + } + +/*****************************************************************************/ +/****** Update number of questions to appear in exam print in database *******/ +/*****************************************************************************/ + +void Exa_DB_UpdateNumQstsToExam (const struct ExaSet_Set *Set, + unsigned NumQstsToPrint) + { + /***** Update set of questions changing old number by new number *****/ + DB_QueryUPDATE ("can not update the number of questions to appear in exam print", + "UPDATE exa_sets" + " SET NumQstsToPrint=%u" + " WHERE SetCod=%ld" + " AND ExaCod=%ld", // Extra check + NumQstsToPrint, + Set->SetCod, + Set->ExaCod); + } + +/*****************************************************************************/ +/*********************** Get number of sets in an exam ***********************/ +/*****************************************************************************/ + +unsigned Exa_DB_GetNumSetsExam (long ExaCod) + { + return (unsigned) + DB_QueryCOUNT ("can not get number of sets in an exam", + "SELECT COUNT(*)" + " FROM exa_sets" + " WHERE ExaCod=%ld", + ExaCod); + } + +/*****************************************************************************/ +/************* Get total number of questions to print in an exam *************/ +/*****************************************************************************/ + +unsigned Exa_DB_GetNumQstsExam (long ExaCod) + { + return DB_QuerySELECTUnsigned ("can not get number of questions to print in an exam", + "SELECT SUM(NumQstsToPrint)" + " FROM exa_sets" + " WHERE ExaCod=%ld", + ExaCod); + } + /*****************************************************************************/ /***************** Get sets of questions in a given exam *********************/ /*****************************************************************************/ @@ -68,14 +278,162 @@ unsigned Exa_DB_GetExamSets (MYSQL_RES **mysql_res,long ExaCod) return (unsigned) DB_QuerySELECT (mysql_res,"can not get sets of questions", "SELECT SetCod," // row[0] - "NumQstsToPrint," // row[1] - "Title" // row[2] + "SetInd," // row[1] + "NumQstsToPrint," // row[2] + "Title" // row[3] " FROM exa_sets" " WHERE ExaCod=%ld" " ORDER BY SetInd", ExaCod); } +/*****************************************************************************/ +/*********************** Get set data using its code *************************/ +/*****************************************************************************/ + +unsigned Exa_DB_GetDataOfSetByCod (MYSQL_RES **mysql_res,long SetCod) + { + return (unsigned) + DB_QuerySELECT (mysql_res,"can not get set data", + "SELECT SetCod," // row[0] + "ExaCod," // row[1] + "SetInd," // row[2] + "NumQstsToPrint," // row[3] + "Title" // row[4] + " FROM exa_sets" + " WHERE SetCod=%ld", + SetCod); + } + +/*****************************************************************************/ +/************** Check if the title of a set of questions exists **************/ +/*****************************************************************************/ + +bool Exa_DB_CheckIfSimilarSetExists (const struct ExaSet_Set *Set, + const char Title[ExaSet_MAX_BYTES_TITLE + 1]) + { + /***** Get number of set of questions with a field value from database *****/ + return (DB_QueryCOUNT ("can not get similar sets of questions", + "SELECT COUNT(*)" + " FROM exa_sets," + "exa_exams" + " WHERE exa_sets.ExaCod=%ld" + " AND exa_sets.Title='%s'" + " AND exa_sets.SetCod<>%ld" + " AND exa_sets.ExaCod=exa_exams.ExaCod" + " AND exa_exams.CrsCod=%ld", // Extra check + Set->ExaCod,Title, + Set->SetCod, + Gbl.Hierarchy.Crs.CrsCod) != 0); + } + +/*****************************************************************************/ +/****************** Get set index given exam and set code ********************/ +/*****************************************************************************/ + +unsigned Exa_DB_GetSetIndFromSetCod (long ExaCod,long SetCod) + { + return DB_QuerySELECTUnsigned ("can not get set index", + "SELECT SetInd" // row[0] + " FROM exa_sets" + " WHERE SetCod=%u" + " AND ExaCod=%ld", // Extra check + SetCod,ExaCod); + } + +/*****************************************************************************/ +/****************** Get set code given exam and set index ********************/ +/*****************************************************************************/ + +long Exa_DB_GetSetCodFromSetInd (long ExaCod,unsigned SetInd) + { + long SetCod; + + /***** Get set code from set index *****/ + SetCod = DB_QuerySELECTCode ("can not get set code", + "SELECT SetCod" + " FROM exa_sets" + " WHERE ExaCod=%ld" + " AND SetInd=%u", + ExaCod, + SetInd); + if (SetCod <= 0) + Err_WrongSetExit (); + + return SetCod; + } + +/*****************************************************************************/ +/********************* Get maximum set index in an exam **********************/ +/*****************************************************************************/ +// Question index can be 1, 2, 3... +// Return 0 if no questions + +unsigned Exa_DB_GetMaxSetIndexInExam (long ExaCod) + { + /***** Get maximum set index in an exam from database *****/ + return DB_QuerySELECTUnsigned ("can not get max set index", + "SELECT MAX(SetInd)" + " FROM exa_sets" + " WHERE ExaCod=%ld", + ExaCod); + } + +/*****************************************************************************/ +/*********** Get previous set index to a given set index in an exam **********/ +/*****************************************************************************/ +// Input set index can be 1, 2, 3... n-1 +// Return set index will be 1, 2, 3... n if previous set exists, or 0 if no previous set + +unsigned Exa_DB_GetPrevSetIndexInExam (long ExaCod,unsigned SetInd) + { + /***** Get previous set index in an exam from database *****/ + // Although indexes are always continuous... + // ...this implementation works even with non continuous indexes + return DB_QuerySELECTUnsigned ("can not get previous set index", + "SELECT COALESCE(MAX(SetInd),0)" + " FROM exa_sets" + " WHERE ExaCod=%ld" + " AND SetInd<%u", + ExaCod, + SetInd); + } + +/*****************************************************************************/ +/*************** Get next set index to a given index in an exam **************/ +/*****************************************************************************/ +// Input set index can be 0, 1, 2, 3... n-1 +// Return set index will be 1, 2, 3... n if next set exists, or 0 if no next set + +unsigned Exa_DB_GetNextSetIndexInExam (long ExaCod,unsigned SetInd) + { + /***** Get next set index in an exam from database *****/ + // Although indexes are always continuous... + // ...this implementation works even with non continuous indexes + return DB_QuerySELECTUnsigned ("can not get next set index", + "SELECT COALESCE(MIN(SetInd),0)" + " FROM exa_sets" + " WHERE ExaCod=%ld" + " AND SetInd>%u", + ExaCod, + SetInd); + } + +/*****************************************************************************/ +/********************* Get number of questions in a set **********************/ +/*****************************************************************************/ + +unsigned Exa_DB_GetNumQstsInSet (long SetCod) + { + /***** Get number of questions in set from database *****/ + return (unsigned) + DB_QueryCOUNT ("can not get number of questions in a set", + "SELECT COUNT(*)" + " FROM exa_set_questions" + " WHERE SetCod=%ld", + SetCod); + } + /*****************************************************************************/ /******************* Get some random questions from a set ********************/ /*****************************************************************************/ diff --git a/swad_exam_database.h b/swad_exam_database.h index 2af9bd97..8a36e80f 100644 --- a/swad_exam_database.h +++ b/swad_exam_database.h @@ -30,6 +30,7 @@ #include "swad_exam_log.h" #include "swad_exam_print.h" #include "swad_exam_session.h" +#include "swad_exam_set.h" #include "swad_test_type.h" /*****************************************************************************/ @@ -40,7 +41,30 @@ /***************************** Public prototypes *****************************/ /*****************************************************************************/ +unsigned Exa_DB_GetListExams (MYSQL_RES **mysql_res,Exa_Order_t SelectedOrder); +unsigned Exa_DB_GetDataOfExamByCod (MYSQL_RES **mysql_res,long ExaCod); +unsigned Exa_DB_GetExamStartEnd (MYSQL_RES **mysql_res,long ExaCod); +void Exa_DB_GetExamTxt (long ExaCod,char Txt[Cns_MAX_BYTES_TEXT + 1]); + +long Exa_DB_CreateSet (const struct ExaSet_Set *Set,unsigned SetInd); +void Exa_DB_UpdateSet (const struct ExaSet_Set *Set); +void Exa_DB_UpdateSetTitle (const struct ExaSet_Set *Set, + const char NewTitle[ExaSet_MAX_BYTES_TITLE + 1]); +void Exa_DB_UpdateNumQstsToExam (const struct ExaSet_Set *Set, + unsigned NumQstsToPrint); +unsigned Exa_DB_GetNumSetsExam (long ExaCod); +unsigned Exa_DB_GetNumQstsExam (long ExaCod); unsigned Exa_DB_GetExamSets (MYSQL_RES **mysql_res,long ExaCod); +unsigned Exa_DB_GetDataOfSetByCod (MYSQL_RES **mysql_res,long SetCod); +bool Exa_DB_CheckIfSimilarSetExists (const struct ExaSet_Set *Set, + const char Title[ExaSet_MAX_BYTES_TITLE + 1]); +unsigned Exa_DB_GetSetIndFromSetCod (long ExaCod,long SetCod); +long Exa_DB_GetSetCodFromSetInd (long ExaCod,unsigned SetInd); +unsigned Exa_DB_GetMaxSetIndexInExam (long ExaCod); +unsigned Exa_DB_GetPrevSetIndexInExam (long ExaCod,unsigned SetInd); +unsigned Exa_DB_GetNextSetIndexInExam (long ExaCod,unsigned SetInd); + +unsigned Exa_DB_GetNumQstsInSet (long SetCod); unsigned Exa_DB_GetSomeQstsFromSetToPrint (MYSQL_RES **mysql_res, long SetCod,unsigned NumQstsToPrint); unsigned Exa_DB_GetValidityAndTypeOfQuestion (MYSQL_RES **mysql_res,long QstCod); diff --git a/swad_exam_print.c b/swad_exam_print.c index bbabde23..d9315f3e 100644 --- a/swad_exam_print.c +++ b/swad_exam_print.c @@ -339,34 +339,38 @@ static void ExaPrn_GetQuestionsForNewPrintFromDB (struct ExaPrn_Print *Print,lon /***** Get questions from all sets *****/ Print->NumQsts.All = 0; - if ((NumSets = Exa_DB_GetExamSets (&mysql_res,ExaCod))) - /***** For each set in exam... *****/ - for (NumSet = 0; - NumSet < NumSets; - NumSet++) - { - /***** Create set of questions *****/ - ExaSet_ResetSet (&Set); + NumSets = Exa_DB_GetExamSets (&mysql_res,ExaCod); - /***** Get set data *****/ - row = mysql_fetch_row (mysql_res); - /* - row[0] SetCod - row[1] NumQstsToPrint - row[2] Title - */ - /* Get set code (row[0]) - and set index (row[1]) */ - Set.SetCod = Str_ConvertStrCodToLongCod (row[0]); - Set.NumQstsToPrint = Str_ConvertStrToUnsigned (row[1]); + /***** For each set in exam... *****/ + for (NumSet = 0; + NumSet < NumSets; + NumSet++) + { + /***** Create set of questions *****/ + ExaSet_ResetSet (&Set); - /* Get the title of the set (row[2]) */ - Str_Copy (Set.Title,row[2],sizeof (Set.Title) - 1); + /***** Get set data *****/ + row = mysql_fetch_row (mysql_res); + /* + row[0] SetCod + row[1] SetInd + row[2] NumQstsToPrint + row[3] Title + */ + /* Get set code (row[0]), + set index (row[1]), + and number of questions to print (row[2]) */ + Set.SetCod = Str_ConvertStrCodToLongCod (row[0]); + Set.SetInd = Str_ConvertStrToUnsigned (row[1]); + Set.NumQstsToPrint = Str_ConvertStrToUnsigned (row[2]); - /***** Questions in this set *****/ - NumQstsFromSet = ExaPrn_GetSomeQstsFromSetToPrint (Print,&Set,&NumQstsInPrint); - Print->NumQsts.All += NumQstsFromSet; - } + /* Get the title of the set (row[3]) */ + Str_Copy (Set.Title,row[3],sizeof (Set.Title) - 1); + + /***** Questions in this set *****/ + NumQstsFromSet = ExaPrn_GetSomeQstsFromSetToPrint (Print,&Set,&NumQstsInPrint); + Print->NumQsts.All += NumQstsFromSet; + } /***** Check *****/ if (Print->NumQsts.All != NumQstsInPrint) diff --git a/swad_exam_set.c b/swad_exam_set.c index 394d7f1e..9d5be3cf 100644 --- a/swad_exam_set.c +++ b/swad_exam_set.c @@ -37,6 +37,7 @@ #include "swad_database.h" #include "swad_error.h" #include "swad_exam.h" +#include "swad_exam_database.h" #include "swad_exam_result.h" #include "swad_exam_session.h" #include "swad_exam_set.h" @@ -65,8 +66,6 @@ extern struct Globals Gbl; #define ExaSet_MAX_SELECTED_QUESTIONS 10000 #define ExaSet_MAX_BYTES_LIST_SELECTED_QUESTIONS (ExaSet_MAX_SELECTED_QUESTIONS * (Cns_MAX_DECIMAL_DIGITS_LONG + 1)) -#define ExaSet_AFTER_LAST_SET ((unsigned)((1UL << 31) - 1)) // 2^31 - 1, don't change this number because it is used in database to indicate that a session is finished - /*****************************************************************************/ /******************************* Private types *******************************/ /*****************************************************************************/ @@ -81,11 +80,6 @@ extern struct Globals Gbl; static void ExaSet_PutParamsOneQst (void *Exams); -static unsigned Exa_DB_GetNumQstsInSet (long SetCod); - -static bool Exa_DB_CheckIfSimilarSetExists (const struct ExaSet_Set *Set, - const char Title[ExaSet_MAX_BYTES_TITLE + 1]); - static void ExaSet_PutFormNewSet (struct Exa_Exams *Exams, struct Exa_Exam *Exam, struct ExaSet_Set *Set, @@ -96,21 +90,9 @@ static bool ExaSet_CheckSetTitleReceivedFromForm (const struct ExaSet_Set *Set, static void ExaSet_CreateSet (struct ExaSet_Set *Set); static void ExaSet_UpdateSet (const struct ExaSet_Set *Set); -static void Exa_DB_UpdateSetTitle (const struct ExaSet_Set *Set, - const char NewTitle[ExaSet_MAX_BYTES_TITLE + 1]); -static void Exa_DB_UpdateNumQstsToExam (const struct ExaSet_Set *Set, - unsigned NumQstsToPrint); static void ExaSet_PutParamSetCod (long SetCod); -static unsigned ExaSet_GetSetIndFromSetCod (long ExaCod,long SetCod); -static long ExaSet_GetSetCodFromSetInd (long ExaCod,unsigned SetInd); - -static unsigned Exa_DB_GetMaxSetIndexInExam (long ExaCod); - -static unsigned Exa_DB_GetPrevSetIndexInExam (long ExaCod,unsigned SetInd); -static unsigned Exa_DB_GetNextSetIndexInExam (long ExaCod,unsigned SetInd); - static void ExaSet_ListSetQuestions (struct Exa_Exams *Exams, const struct Exa_Exam *Exam, const struct ExaSet_Set *Set); @@ -185,21 +167,6 @@ long ExaSet_GetParamSetCod (void) return Par_GetParToLong ("SetCod"); } -/*****************************************************************************/ -/********************* Get number of questions in a set **********************/ -/*****************************************************************************/ - -static unsigned Exa_DB_GetNumQstsInSet (long SetCod) - { - /***** Get number of questions in set from database *****/ - return (unsigned) - DB_QueryCOUNT ("can not get number of questions in a set", - "SELECT COUNT(*)" - " FROM exa_set_questions" - " WHERE SetCod=%ld", - SetCod); - } - /*****************************************************************************/ /*********************** Get set data using its code *************************/ /*****************************************************************************/ @@ -219,15 +186,7 @@ void ExaSet_GetDataOfSetByCod (struct ExaSet_Set *Set) } /***** Get data of set of questions from database *****/ - if (DB_QuerySELECT (&mysql_res,"can not get set data", - "SELECT SetCod," // row[0] - "ExaCod," // row[1] - "SetInd," // row[2] - "NumQstsToPrint," // row[3] - "Title" // row[4] - " FROM exa_sets" - " WHERE SetCod=%ld", - Set->SetCod)) // Set found... + if (Exa_DB_GetDataOfSetByCod (&mysql_res,Set->SetCod)) // Set found... { /* Get row */ row = mysql_fetch_row (mysql_res); @@ -262,28 +221,6 @@ void ExaSet_GetDataOfSetByCod (struct ExaSet_Set *Set) DB_FreeMySQLResult (&mysql_res); } -/*****************************************************************************/ -/************** Check if the title of a set of questions exists **************/ -/*****************************************************************************/ - -static bool Exa_DB_CheckIfSimilarSetExists (const struct ExaSet_Set *Set, - const char Title[ExaSet_MAX_BYTES_TITLE + 1]) - { - /***** Get number of set of questions with a field value from database *****/ - return (DB_QueryCOUNT ("can not get similar sets of questions", - "SELECT COUNT(*)" - " FROM exa_sets," - "exa_exams" - " WHERE exa_sets.ExaCod=%ld" - " AND exa_sets.Title='%s'" - " AND exa_sets.SetCod<>%ld" - " AND exa_sets.ExaCod=exa_exams.ExaCod" - " AND exa_exams.CrsCod=%ld", // Extra check - Set->ExaCod,Title, - Set->SetCod, - Gbl.Hierarchy.Crs.CrsCod) != 0); - } - /*****************************************************************************/ /********************* Put a form to create/edit an exam **********************/ /*****************************************************************************/ @@ -549,16 +486,7 @@ static void ExaSet_CreateSet (struct ExaSet_Set *Set) MaxSetInd = Exa_DB_GetMaxSetIndexInExam (Set->ExaCod); /***** Create a new exam *****/ - Set->SetCod = - DB_QueryINSERTandReturnCode ("can not create new set of questions", - "INSERT INTO exa_sets" - " (ExaCod,SetInd,NumQstsToPrint,Title)" - " VALUES" - " (%ld,%u,%u,'%s')", - Set->ExaCod, - MaxSetInd + 1, - Set->NumQstsToPrint, - Set->Title); + Set->SetCod = Exa_DB_CreateSet (Set,MaxSetInd + 1); /***** Write success message *****/ Ale_ShowAlert (Ale_SUCCESS,Txt_Created_new_set_of_questions_X, @@ -574,88 +502,12 @@ static void ExaSet_UpdateSet (const struct ExaSet_Set *Set) extern const char *Txt_The_set_of_questions_has_been_modified; /***** Update the data of the set of questions *****/ - DB_QueryUPDATE ("can not update set of questions", - "UPDATE exa_sets" - " SET ExaCod=%ld," - "SetInd=%u," - "NumQstsToPrint=%u," - "Title='%s'" - " WHERE SetCod=%ld", - Set->ExaCod, - Set->SetInd, - Set->NumQstsToPrint, - Set->Title, - Set->SetCod); + Exa_DB_UpdateSet (Set); /***** Write success message *****/ Ale_ShowAlert (Ale_SUCCESS,Txt_The_set_of_questions_has_been_modified); } -/*****************************************************************************/ -/************************ Update set title in database ***********************/ -/*****************************************************************************/ - -static void Exa_DB_UpdateSetTitle (const struct ExaSet_Set *Set, - const char NewTitle[ExaSet_MAX_BYTES_TITLE + 1]) - { - /***** Update set of questions changing old title by new title *****/ - DB_QueryUPDATE ("can not update the title of a set of questions", - "UPDATE exa_sets" - " SET Title='%s'" - " WHERE SetCod=%ld" - " AND ExaCod=%ld", // Extra check - NewTitle, - Set->SetCod, - Set->ExaCod); - } - -/*****************************************************************************/ -/****** Update number of questions to appear in exam print in database *******/ -/*****************************************************************************/ - -static void Exa_DB_UpdateNumQstsToExam (const struct ExaSet_Set *Set, - unsigned NumQstsToPrint) - { - /***** Update set of questions changing old number by new number *****/ - DB_QueryUPDATE ("can not update the number of questions to appear in exam print", - "UPDATE exa_sets" - " SET NumQstsToPrint=%u" - " WHERE SetCod=%ld" - " AND ExaCod=%ld", // Extra check - NumQstsToPrint, - Set->SetCod, - Set->ExaCod); - } - -/*****************************************************************************/ -/******************* Get number of questions of an exam *********************/ -/*****************************************************************************/ - -unsigned Exa_DB_GetNumSetsExam (long ExaCod) - { - /***** Get number of sets in an exam from database *****/ - return (unsigned) - DB_QueryCOUNT ("can not get number of sets in an exam", - "SELECT COUNT(*)" - " FROM exa_sets" - " WHERE ExaCod=%ld", - ExaCod); - } - -/*****************************************************************************/ -/******************* Get number of questions of an exam *********************/ -/*****************************************************************************/ - -unsigned Exa_DB_GetNumQstsExam (long ExaCod) - { - /***** Get total number of questions to appear in exam print *****/ - return DB_QuerySELECTUnsigned ("can not get number of questions in an exam print", - "SELECT SUM(NumQstsToPrint)" - " FROM exa_sets" - " WHERE ExaCod=%ld", - ExaCod); - } - /*****************************************************************************/ /********** Request the creation or edition of an set of questions ***********/ /*****************************************************************************/ @@ -771,114 +623,6 @@ static void ExaSet_PutParamSetCod (long SetCod) Par_PutHiddenParamUnsigned (NULL,"SetCod",SetCod); } -/*****************************************************************************/ -/****************** Get set index given exam and set code ********************/ -/*****************************************************************************/ - -static unsigned ExaSet_GetSetIndFromSetCod (long ExaCod,long SetCod) - { - MYSQL_RES *mysql_res; - MYSQL_ROW row; - long SetInd; - - /***** Get set index from set code *****/ - if (!DB_QuerySELECT (&mysql_res,"can not get set index", - "SELECT SetInd" // row[0] - " FROM exa_sets" - " WHERE SetCod=%u" - " AND ExaCod=%ld", // Extra check - SetCod,ExaCod)) - Err_WrongSetExit (); - - /***** Get set code (row[0]) *****/ - row = mysql_fetch_row (mysql_res); - SetInd = Str_ConvertStrToUnsigned (row[0]); - - /***** Free structure that stores the query result *****/ - DB_FreeMySQLResult (&mysql_res); - - return SetInd; - } - -/*****************************************************************************/ -/****************** Get set code given exam and set index ********************/ -/*****************************************************************************/ - -static long ExaSet_GetSetCodFromSetInd (long ExaCod,unsigned SetInd) - { - long SetCod; - - /***** Get set code from set index *****/ - SetCod = DB_QuerySELECTCode ("can not get set code", - "SELECT SetCod" - " FROM exa_sets" - " WHERE ExaCod=%ld" - " AND SetInd=%u", - ExaCod, - SetInd); - if (SetCod <= 0) - Err_WrongSetExit (); - - return SetCod; - } - -/*****************************************************************************/ -/********************* Get maximum set index in an exam **********************/ -/*****************************************************************************/ -// Question index can be 1, 2, 3... -// Return 0 if no questions - -static unsigned Exa_DB_GetMaxSetIndexInExam (long ExaCod) - { - /***** Get maximum set index in an exam from database *****/ - return DB_QuerySELECTUnsigned ("can not get max set index", - "SELECT MAX(SetInd)" - " FROM exa_sets" - " WHERE ExaCod=%ld", - ExaCod); - } - -/*****************************************************************************/ -/*********** Get previous set index to a given set index in an exam **********/ -/*****************************************************************************/ -// Input set index can be 1, 2, 3... n-1 -// Return set index will be 1, 2, 3... n if previous set exists, or 0 if no previous set - -static unsigned Exa_DB_GetPrevSetIndexInExam (long ExaCod,unsigned SetInd) - { - /***** Get previous set index in an exam from database *****/ - // Although indexes are always continuous... - // ...this implementation works even with non continuous indexes - return DB_QuerySELECTUnsigned ("can not get previous set index", - "SELECT COALESCE(MAX(SetInd),0)" - " FROM exa_sets" - " WHERE ExaCod=%ld" - " AND SetInd<%u", - ExaCod, - SetInd); - } - -/*****************************************************************************/ -/*************** Get next set index to a given index in an exam **************/ -/*****************************************************************************/ -// Input set index can be 0, 1, 2, 3... n-1 -// Return set index will be 1, 2, 3... n if next set exists, or big number if no next set - -static unsigned Exa_DB_GetNextSetIndexInExam (long ExaCod,unsigned SetInd) - { - /***** Get next set index in an exam from database *****/ - // Although indexes are always continuous... - // ...this implementation works even with non continuous indexes - return DB_QuerySELECTUnsigned ("can not get next set index", - "SELECT COALESCE(MIN(SetInd),%u)" - " FROM exa_sets" - " WHERE ExaCod=%ld" - " AND SetInd>%u", - ExaSet_AFTER_LAST_SET, // End of sets has been reached - ExaCod, - SetInd); - } - /*****************************************************************************/ /************************* List the sets of an exam **************************/ /*****************************************************************************/ @@ -898,24 +642,15 @@ void ExaSet_ListExamSets (struct Exa_Exams *Exams, MaxSetInd = Exa_DB_GetMaxSetIndexInExam (Exam->ExaCod); /***** Get data of set of questions from database *****/ - NumSets = (unsigned) - DB_QuerySELECT (&mysql_res,"can not get sets of questions", - "SELECT SetCod," // row[0] - "SetInd," // row[1] - "NumQstsToPrint," // row[2] - "Title" // row[3] - " FROM exa_sets" - " WHERE ExaCod=%ld" - " ORDER BY SetInd", - Exam->ExaCod); + NumSets = Exa_DB_GetExamSets (&mysql_res,Exam->ExaCod); /***** Begin box *****/ - Exams->ExaCod = Exam->ExaCod; Box_BoxBegin (NULL,Txt_Sets_of_questions, NULL,NULL, Hlp_ASSESSMENT_Exams_question_sets,Box_NOT_CLOSABLE); /***** Show table with sets *****/ + Exams->ExaCod = Exam->ExaCod; if (NumSets) ExaSet_ListOneOrMoreSetsForEdition (Exams,Exam, MaxSetInd, @@ -1861,7 +1596,7 @@ void ExaSet_MoveUpSet (void) Err_NoPermissionExit (); /***** Get set index *****/ - SetIndBottom = ExaSet_GetSetIndFromSetCod (Exam.ExaCod,Set.SetCod); + SetIndBottom = Exa_DB_GetSetIndFromSetCod (Exam.ExaCod,Set.SetCod); /***** Move up set *****/ if (SetIndBottom > 1) @@ -1909,7 +1644,7 @@ void ExaSet_MoveDownSet (void) Err_NoPermissionExit (); /***** Get set index *****/ - SetIndTop = ExaSet_GetSetIndFromSetCod (Exam.ExaCod,Set.SetCod); + SetIndTop = Exa_DB_GetSetIndFromSetCod (Exam.ExaCod,Set.SetCod); /***** Get maximum set index *****/ MaxSetInd = Exa_DB_GetMaxSetIndexInExam (Exam.ExaCod); @@ -1919,7 +1654,7 @@ void ExaSet_MoveDownSet (void) { /* Indexes of sets to be exchanged */ SetIndBottom = Exa_DB_GetNextSetIndexInExam (Exam.ExaCod,SetIndTop); - if (SetIndBottom == ExaSet_AFTER_LAST_SET) + if (SetIndBottom == 0) Err_ShowErrorAndExit ("Wrong set index."); /* Exchange sets */ @@ -2200,8 +1935,8 @@ static void ExaSet_ExchangeSets (long ExaCod, Gbl.DB.LockedTables = true; /***** Get set codes of the sets to be moved *****/ - SetCodTop = ExaSet_GetSetCodFromSetInd (ExaCod,SetIndTop); - SetCodBottom = ExaSet_GetSetCodFromSetInd (ExaCod,SetIndBottom); + SetCodTop = Exa_DB_GetSetCodFromSetInd (ExaCod,SetIndTop); + SetCodBottom = Exa_DB_GetSetCodFromSetInd (ExaCod,SetIndBottom); /***** Exchange indexes of sets *****/ /* diff --git a/swad_exam_set.h b/swad_exam_set.h index ce12fed2..8d7cf09a 100644 --- a/swad_exam_set.h +++ b/swad_exam_set.h @@ -48,9 +48,6 @@ void ExaSet_ReceiveFormSet (void); void ExaSet_ChangeSetTitle (void); void ExaSet_ChangeNumQstsToExam (void); -unsigned Exa_DB_GetNumSetsExam (long ExaCod); -unsigned Exa_DB_GetNumQstsExam (long ExaCod); - void ExaSet_RequestCreatOrEditSet (void); void ExaSet_ReqSelectQstsToAddToSet (void); void ExaSet_ListQstsToAddToSet (void);