From eb48ee477c3961a623108fbcdf7dc3608af9653d Mon Sep 17 00:00:00 2001 From: acanas Date: Sun, 26 Apr 2020 11:56:52 +0200 Subject: [PATCH] Version19.199 --- swad_changelog.h | 3 +- swad_exam.c | 306 ++++++++++++++++++++++++++++++++++++++++++++++- swad_exam.h | 1 + swad_game.c | 2 +- swad_text.c | 42 +++++++ 5 files changed, 351 insertions(+), 3 deletions(-) diff --git a/swad_changelog.h b/swad_changelog.h index b627b433f..230866a0d 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -544,10 +544,11 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - * En OpenSWAD: ps2pdf source.ps destination.pdf */ -#define Log_PLATFORM_VERSION "SWAD 19.198 (2020-04-26)" +#define Log_PLATFORM_VERSION "SWAD 19.199 (2020-04-26)" #define CSS_FILE "swad19.193.1.css" #define JS_FILE "swad19.193.1.js" /* + Version 19.199: Apr 26, 2020 Move set of questions up and down. (299344 lines) Version 19.198: Apr 26, 2020 Remove set of questions. (299054 lines) 3 changes necessary in database: ALTER TABLE exa_questions DROP INDEX ExaCod; diff --git a/swad_exam.c b/swad_exam.c index 0e2de98e4..8058bb0bb 100644 --- a/swad_exam.c +++ b/swad_exam.c @@ -172,8 +172,15 @@ static void ExaSet_PutParamSetCod (long SetCod); static void Exa_RemAnswersOfAQuestion (long ExaCod,unsigned QstInd); +static unsigned ExaSet_GetSetIndFromSetCod (long ExaCod,long SetCod); +static long ExaSet_GetSetCodFromSetInd (long ExaCod,unsigned SetInd); + static unsigned ExaSet_GetMaxSetIndexInExam (long ExaCod); static unsigned Exa_GetMaxQuestionIndexInExam (long ExaCod); + +static unsigned ExaSet_GetPrevSetIndexInExam (long ExaCod,unsigned SetInd); +static unsigned ExaSet_GetNextSetIndexInExam (long ExaCod,unsigned SetInd); + static void ExaSet_ListExamSets (struct Exa_Exams *Exams, struct Exa_Exam *Exam, struct ExaSet_Set *Set); @@ -201,6 +208,8 @@ static void Exa_AllocateListSelectedQuestions (struct Exa_Exams *Exams); static void Exa_FreeListsSelectedQuestions (struct Exa_Exams *Exams); static unsigned Exa_CountNumQuestionsInList (const struct Exa_Exams *Exams); +static void ExaSet_ExchangeSets (long ExaCod, + unsigned SetIndTop,unsigned SetIndBottom); static void Exa_ExchangeQuestions (long ExaCod, unsigned QstIndTop,unsigned QstIndBottom); @@ -2235,6 +2244,62 @@ static void Exa_RemAnswersOfAQuestion (long ExaCod,unsigned QstInd) ExaCod,QstInd); } +/*****************************************************************************/ +/****************** 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 FROM exa_sets" + " WHERE SetCod=%u" + " AND ExaCod=%ld", // Extra check + SetCod,ExaCod)) + Lay_ShowErrorAndExit ("Error: wrong set code."); + + /***** 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) + { + MYSQL_RES *mysql_res; + MYSQL_ROW row; + long SetCod; + + /***** Get set code from set index *****/ + if (!DB_QuerySELECT (&mysql_res,"can not get set code", + "SELECT SetCod FROM exa_sets" + " WHERE ExaCod=%ld AND SetInd=%u", + ExaCod,SetInd)) + Lay_ShowErrorAndExit ("Error: wrong set index."); + + /***** Get set code (row[0]) *****/ + row = mysql_fetch_row (mysql_res); + if ((SetCod = Str_ConvertStrCodToLongCod (row[0])) <= 0) + Lay_ShowErrorAndExit ("Error: wrong set code."); + + /***** Free structure that stores the query result *****/ + DB_FreeMySQLResult (&mysql_res); + + return SetCod; + } + /*****************************************************************************/ /************ Get question code given exam and index of question *************/ /*****************************************************************************/ @@ -2245,7 +2310,7 @@ long Exa_GetQstCodFromQstInd (long ExaCod,unsigned QstInd) MYSQL_ROW row; long QstCod; - /***** Get question code of thw question to be moved up *****/ + /***** Get question code of the question to be moved up *****/ if (!DB_QuerySELECT (&mysql_res,"can not get question code", "SELECT QstCod FROM exa_questions" " WHERE ExaCod=%ld AND QstInd=%u", @@ -2321,6 +2386,74 @@ static unsigned Exa_GetMaxQuestionIndexInExam (long ExaCod) return QstInd; } +/*****************************************************************************/ +/*********** 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 ExaSet_GetPrevSetIndexInExam (long ExaCod,unsigned SetInd) + { + MYSQL_RES *mysql_res; + MYSQL_ROW row; + unsigned PrevSetInd = 0; + + /***** Get previous set index in an exam from database *****/ + // Although indexes are always continuous... + // ...this implementation works even with non continuous indexes + if (!DB_QuerySELECT (&mysql_res,"can not get previous set index", + "SELECT MAX(SetInd) FROM exa_sets" + " WHERE ExaCod=%ld AND SetInd<%u", + ExaCod,SetInd)) + Lay_ShowErrorAndExit ("Error: previous set index not found."); + + /***** Get previous set index (row[0]) *****/ + row = mysql_fetch_row (mysql_res); + if (row) + if (row[0]) + if (sscanf (row[0],"%u",&PrevSetInd) != 1) + Lay_ShowErrorAndExit ("Error when getting previous set index."); + + /***** Free structure that stores the query result *****/ + DB_FreeMySQLResult (&mysql_res); + + return PrevSetInd; + } + +/*****************************************************************************/ +/*************** 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 + +static unsigned ExaSet_GetNextSetIndexInExam (long ExaCod,unsigned SetInd) + { + MYSQL_RES *mysql_res; + MYSQL_ROW row; + unsigned NextSetInd = ExaEvt_AFTER_LAST_QUESTION; // End of sets has been reached + + /***** Get next set index in an exam from database *****/ + // Although indexes are always continuous... + // ...this implementation works even with non continuous indexes + if (!DB_QuerySELECT (&mysql_res,"can not get next set index", + "SELECT MIN(SetInd) FROM exa_sets" + " WHERE ExaCod=%ld AND SetInd>%u", + ExaCod,SetInd)) + Lay_ShowErrorAndExit ("Error: next set index not found."); + + /***** Get next set index (row[0]) *****/ + row = mysql_fetch_row (mysql_res); + if (row) + if (row[0]) + if (sscanf (row[0],"%u",&NextSetInd) != 1) + Lay_ShowErrorAndExit ("Error when getting next set index."); + + /***** Free structure that stores the query result *****/ + DB_FreeMySQLResult (&mysql_res); + + return NextSetInd; + } + /*****************************************************************************/ /*********** Get previous question index to a given index in an exam **********/ /*****************************************************************************/ @@ -3154,6 +3287,61 @@ void ExaSet_RemoveSet (void) void ExaSet_MoveUpSet (void) { + extern const char *Txt_The_set_of_questions_has_been_moved_up; + extern const char *Txt_Movement_not_allowed; + struct Exa_Exams Exams; + struct Exa_Exam Exam; + struct ExaSet_Set Set; + unsigned SetIndTop; + unsigned SetIndBottom; + + /***** Reset exams context *****/ + Exa_ResetExams (&Exams); + + /***** Reset exam and set *****/ + Exa_ResetExam (&Exam); + ExaSet_ResetSet (&Set); + + /***** Get parameters *****/ + Exa_GetParams (&Exams); + if (Exams.ExaCod <= 0) + Lay_WrongExamExit (); + Set.ExaCod = Exam.ExaCod = Exams.ExaCod; + Set.SetCod = ExaSet_GetParamSetCod (); + if (Set.SetCod <= 0) + Lay_WrongSetExit (); + + /***** Get exam data from database *****/ + Exa_GetDataOfExamByCod (&Exam); + if (!Exa_CheckIfEditable (&Exam)) + Lay_NoPermissionExit (); + + /***** Get set data from database *****/ + ExaSet_GetDataOfSetByCod (&Set); + + /***** Get set index *****/ + SetIndBottom = ExaSet_GetSetIndFromSetCod (Exam.ExaCod,Set.SetCod); + + /***** Move up set *****/ + if (SetIndBottom > 1) + { + /* Indexes of sets to be exchanged */ + SetIndTop = ExaSet_GetPrevSetIndexInExam (Exam.ExaCod,SetIndBottom); + if (!SetIndTop) + Lay_ShowErrorAndExit ("Wrong index of set."); + + /* Exchange sets */ + ExaSet_ExchangeSets (Exam.ExaCod,SetIndTop,SetIndBottom); + + /* Success alert */ + Ale_ShowAlert (Ale_SUCCESS,Txt_The_set_of_questions_has_been_moved_up); + } + else + Ale_ShowAlert (Ale_WARNING,Txt_Movement_not_allowed); + + /***** Show current exam and its sets *****/ + Exa_PutFormsOneExam (&Exams,&Exam,&Set, + false); // It's not a new exam } /*****************************************************************************/ @@ -3162,6 +3350,71 @@ void ExaSet_MoveUpSet (void) void ExaSet_MoveDownSet (void) { + extern const char *Txt_The_set_of_questions_has_been_moved_down; + extern const char *Txt_Movement_not_allowed; + extern const char *Txt_This_exam_has_no_sets_of_questions; + struct Exa_Exams Exams; + struct Exa_Exam Exam; + struct ExaSet_Set Set; + unsigned SetIndTop; + unsigned SetIndBottom; + unsigned MaxSetInd; // 0 if no sets + + /***** Reset exams context *****/ + Exa_ResetExams (&Exams); + + /***** Reset exam and set *****/ + Exa_ResetExam (&Exam); + ExaSet_ResetSet (&Set); + + /***** Get parameters *****/ + Exa_GetParams (&Exams); + if (Exams.ExaCod <= 0) + Lay_WrongExamExit (); + Set.ExaCod = Exam.ExaCod = Exams.ExaCod; + Set.SetCod = ExaSet_GetParamSetCod (); + if (Set.SetCod <= 0) + Lay_WrongSetExit (); + + /***** Get exam data from database *****/ + Exa_GetDataOfExamByCod (&Exam); + if (!Exa_CheckIfEditable (&Exam)) + Lay_NoPermissionExit (); + + /***** Get set data from database *****/ + ExaSet_GetDataOfSetByCod (&Set); + + /***** Get set index *****/ + SetIndTop = ExaSet_GetSetIndFromSetCod (Exam.ExaCod,Set.SetCod); + + /***** Get maximum set index *****/ + MaxSetInd = ExaSet_GetMaxSetIndexInExam (Exam.ExaCod); + + /***** Move down set *****/ + if (MaxSetInd) + { + if (SetIndTop < MaxSetInd) + { + /* Indexes of sets to be exchanged */ + SetIndBottom = ExaSet_GetNextSetIndexInExam (Exam.ExaCod,SetIndTop); + if (!SetIndBottom) + Lay_ShowErrorAndExit ("Wrong index of set."); + + /* Exchange sets */ + ExaSet_ExchangeSets (Exam.ExaCod,SetIndTop,SetIndBottom); + + /* Success alert */ + Ale_ShowAlert (Ale_SUCCESS,Txt_The_set_of_questions_has_been_moved_down); + } + else + Ale_ShowAlert (Ale_WARNING,Txt_Movement_not_allowed); + } + else + Ale_ShowAlert (Ale_WARNING,Txt_This_exam_has_no_sets_of_questions); + + /***** Show current exam and its sets *****/ + Exa_PutFormsOneExam (&Exams,&Exam,&Set, + false); // It's not a new exam } /*****************************************************************************/ @@ -3414,6 +3667,57 @@ void Exa_MoveDownQst (void) false); // Do not put form to start new event } +/*****************************************************************************/ +/*********** Exchange the order of two consecutive sets in an exam ***********/ +/*****************************************************************************/ + +static void ExaSet_ExchangeSets (long ExaCod, + unsigned SetIndTop,unsigned SetIndBottom) + { + long SetCodTop; + long SetCodBottom; + + /***** Lock table to make the move atomic *****/ + DB_Query ("can not lock tables to exchange sets of questions", + "LOCK TABLES exa_sets WRITE"); + Gbl.DB.LockedTables = true; + + /***** Get set codes of the sets to be moved *****/ + SetCodTop = ExaSet_GetSetCodFromSetInd (ExaCod,SetIndTop); + SetCodBottom = ExaSet_GetSetCodFromSetInd (ExaCod,SetIndBottom); + + /***** Exchange indexes of sets *****/ + /* + Example: + SetIndTop = 1; SetCodTop = 218 + SetIndBottom = 2; SetCodBottom = 220 + +--------+--------+ +--------+--------+ +--------+--------+ + | SetInd | SetCod | | SetInd | SetCod | | SetInd | SetCod | + +--------+--------+ +--------+--------+ +--------+--------+ + | 1 | 218 | -----> | 2 | 218 | = | 1 | 220 | + | 2 | 220 | | 1 | 220 | | 2 | 218 | + | 3 | 232 | | 3 | 232 | | 3 | 232 | + +--------+--------+ +--------+--------+ +--------+--------+ + */ + DB_QueryUPDATE ("can not exchange indexes of sets", + "UPDATE exa_sets SET SetInd=%u" + " WHERE ExaCod=%ld AND SetCod=%ld", + SetIndBottom, + ExaCod,SetCodTop); + + DB_QueryUPDATE ("can not exchange indexes of sets", + "UPDATE exa_sets SET SetInd=%u" + " WHERE ExaCod=%ld AND SetCod=%ld", + SetIndTop, + ExaCod,SetCodBottom); + + /***** Unlock table *****/ + Gbl.DB.LockedTables = false; // Set to false before the following unlock... + // ...to not retry the unlock if error in unlocking + DB_Query ("can not unlock tables after exchanging sets of questions", + "UNLOCK TABLES"); + } + /*****************************************************************************/ /********* Exchange the order of two consecutive questions in an exam *********/ /*****************************************************************************/ diff --git a/swad_exam.h b/swad_exam.h index 1221fbbbc..fd1252de5 100644 --- a/swad_exam.h +++ b/swad_exam.h @@ -165,6 +165,7 @@ void Exa_ListQuestionsToSelect (void); void Exa_PutParamQstInd (unsigned QstInd); unsigned Exa_GetParamQstInd (void); long Exa_GetQstCodFromQstInd (long ExaCod,unsigned QstInd); + unsigned Exa_GetPrevQuestionIndexInExam (long ExaCod,unsigned QstInd); unsigned Exa_GetNextQuestionIndexInExam (long ExaCod,unsigned QstInd); diff --git a/swad_game.c b/swad_game.c index fdbd25e9e..76328ba95 100644 --- a/swad_game.c +++ b/swad_game.c @@ -1780,7 +1780,7 @@ long Gam_GetQstCodFromQstInd (long GamCod,unsigned QstInd) MYSQL_ROW row; long QstCod; - /***** Get question code of thw question to be moved up *****/ + /***** Get question code of the question to be moved up *****/ if (!DB_QuerySELECT (&mysql_res,"can not get question code", "SELECT QstCod FROM gam_questions" " WHERE GamCod=%ld AND QstInd=%u", diff --git a/swad_text.c b/swad_text.c index 5c104049d..676593c3d 100644 --- a/swad_text.c +++ b/swad_text.c @@ -49741,6 +49741,48 @@ const char *Txt_The_set_of_questions_has_been_modified = "O conjunto de perguntas foi modificado."; #endif +const char *Txt_The_set_of_questions_has_been_moved_down = +#if L==1 // ca + "El conjunt de preguntes ha estat mogut cap avall."; +#elif L==2 // de + "Der Satz von Fragen wurde nach unten bewegt."; +#elif L==3 // en + "The set of questions has been moved down."; +#elif L==4 // es + "El conjunto de preguntas se ha movido hacia abajo."; +#elif L==5 // fr + "L'ensemble de questions a été déplacé vers le bas."; +#elif L==6 // gn + "El conjunto de preguntas se ha movido hacia abajo."; // Okoteve traducción +#elif L==7 // it + "Il set di domande è stato abbattuto."; +#elif L==8 // pl + "Zestaw pytań zostało przeniesione."; +#elif L==9 // pt + "O conjunto de perguntas foi movido para baixo."; +#endif + +const char *Txt_The_set_of_questions_has_been_moved_up = +#if L==1 // ca + "El conjunt de preguntes ha estat mogut cap amunt."; +#elif L==2 // de + "Der Satz von Fragen wurde nach oben verschoben."; +#elif L==3 // en + "The set of questions has been moved up."; +#elif L==4 // es + "El conjunto de preguntas se ha movido hacia arriba."; +#elif L==5 // fr + "L'ensemble de questions a été déplacé vers le haut."; +#elif L==6 // gn + "El conjunto de preguntas se ha movido hacia arriba."; // Okoteve traducción +#elif L==7 // it + "Il set di domande è stato spostato."; +#elif L==8 // pl + "Zestaw pytań zostało poruszone."; +#elif L==9 // pt + "O conjunto de perguntas foi movido para cima."; +#endif + const char *Txt_The_size_of_the_file_exceeds_the_maximum_allowed_X = // Warning: it is very important to include %s in the following sentences #if L==1 // ca "La mida del fitxer"