From 787e62fda857b5b60cb004be670fb1de3352c616 Mon Sep 17 00:00:00 2001 From: acanas Date: Mon, 27 Apr 2020 00:06:58 +0200 Subject: [PATCH] Version19.199.2 --- sql/swad.sql | 6 +- swad_changelog.h | 10 +- swad_database.c | 14 +- swad_exam.c | 8 -- swad_game.c | 365 +++++++++++++++++++++++++++-------------------- swad_text.c | 88 ++++++------ 6 files changed, 272 insertions(+), 219 deletions(-) diff --git a/sql/swad.sql b/sql/swad.sql index 222ed9c0b..f72d3a1da 100644 --- a/sql/swad.sql +++ b/sql/swad.sql @@ -802,10 +802,10 @@ CREATE TABLE IF NOT EXISTS mch_results ( -- CREATE TABLE IF NOT EXISTS gam_questions ( GamCod INT NOT NULL, - QstCod INT NOT NULL, QstInd INT NOT NULL DEFAULT 0, - INDEX(GamCod), - INDEX(QstCod)); + QstCod INT NOT NULL, + UNIQUE INDEX(GamCod,QstInd), + UNIQUE INDEX(GamCod,QstCod)); -- -- Table mch_times: stores the elapsed time in every question in every match played -- diff --git a/swad_changelog.h b/swad_changelog.h index 09d9d3ec7..c15cbbad8 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -544,10 +544,18 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - * En OpenSWAD: ps2pdf source.ps destination.pdf */ -#define Log_PLATFORM_VERSION "SWAD 19.199.1 (2020-04-26)" +#define Log_PLATFORM_VERSION "SWAD 19.199.2 (2020-04-27)" #define CSS_FILE "swad19.193.1.css" #define JS_FILE "swad19.193.1.js" /* + Version 19.199.2: Apr 27, 2020 Changes moving questions in a game up and down. (299345 lines) + 4 changes necessary in database: +ALTER TABLE gam_questions CHANGE COLUMN QstInd QstInd INT NOT NULL DEFAULT 0 AFTER GamCod; +ALTER TABLE gam_questions DROP INDEX GamCod; +ALTER TABLE gam_questions DROP INDEX QstCod; +ALTER TABLE gam_questions ADD UNIQUE INDEX(GamCod,QstInd); +ALTER TABLE gam_questions ADD UNIQUE INDEX(GamCod,QstCod); + Version 19.199.1: Apr 26, 2020 Changes moving set of questions up and down. (299308 lines) 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) diff --git a/swad_database.c b/swad_database.c index 49caee07d..7fca67661 100644 --- a/swad_database.c +++ b/swad_database.c @@ -1586,18 +1586,18 @@ mysql> DESCRIBE gam_questions; +--------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------+---------+------+-----+---------+-------+ -| GamCod | int(11) | NO | MUL | NULL | | -| QstCod | int(11) | NO | MUL | NULL | | -| QstInd | int(11) | NO | | 0 | | +| GamCod | int(11) | NO | PRI | NULL | | +| QstInd | int(11) | NO | PRI | 0 | | +| QstCod | int(11) | NO | | NULL | | +--------+---------+------+-----+---------+-------+ -3 rows in set (0,00 sec) +3 rows in set (0.00 sec) */ DB_CreateTable ("CREATE TABLE IF NOT EXISTS gam_questions (" "GamCod INT NOT NULL," - "QstCod INT NOT NULL," "QstInd INT NOT NULL DEFAULT 0," - "INDEX(GamCod)," - "INDEX(QstCod))"); + "QstCod INT NOT NULL," + "UNIQUE INDEX(GamCod,QstInd)," + "UNIQUE INDEX(GamCod,QstCod))"); /***** Table mch_answers *****/ /* diff --git a/swad_exam.c b/swad_exam.c index c9a585cbb..a8fb7abc2 100644 --- a/swad_exam.c +++ b/swad_exam.c @@ -3547,7 +3547,6 @@ void Exa_RemoveQst (void) void Exa_MoveUpQst (void) { - extern const char *Txt_The_question_has_been_moved_up; extern const char *Txt_Movement_not_allowed; struct Exa_Exams Exams; struct Exa_Exam Exam; @@ -3585,9 +3584,6 @@ void Exa_MoveUpQst (void) /* Exchange questions */ Exa_ExchangeQuestions (Exam.ExaCod,QstIndTop,QstIndBottom); - - /* Success alert */ - Ale_ShowAlert (Ale_SUCCESS,Txt_The_question_has_been_moved_up); } else Ale_ShowAlert (Ale_WARNING,Txt_Movement_not_allowed); @@ -3607,7 +3603,6 @@ void Exa_MoveUpQst (void) void Exa_MoveDownQst (void) { - extern const char *Txt_The_question_has_been_moved_down; extern const char *Txt_Movement_not_allowed; extern const char *Txt_This_exam_has_no_questions; struct Exa_Exams Exams; @@ -3652,9 +3647,6 @@ void Exa_MoveDownQst (void) /* Exchange questions */ Exa_ExchangeQuestions (Exam.ExaCod,QstIndTop,QstIndBottom); - - /* Success alert */ - Ale_ShowAlert (Ale_SUCCESS,Txt_The_question_has_been_moved_down); } else Ale_ShowAlert (Ale_WARNING,Txt_Movement_not_allowed); diff --git a/swad_game.c b/swad_game.c index 76328ba95..11ee3d6e0 100644 --- a/swad_game.c +++ b/swad_game.c @@ -150,6 +150,8 @@ static void Gam_UpdateGame (struct Gam_Game *Game,const char *Txt); static void Gam_RemAnswersOfAQuestion (long GamCod,unsigned QstInd); +static unsigned Gam_GetQstIndFromQstCod (long GamCod,long QstCod); + static unsigned Gam_GetMaxQuestionIndexInGame (long GamCod); static void Gam_ListGameQuestions (struct Gam_Games *Games,struct Gam_Game *Game); static void Gam_ListOneOrMoreQuestionsForEdition (struct Gam_Games *Games, @@ -157,7 +159,8 @@ static void Gam_ListOneOrMoreQuestionsForEdition (struct Gam_Games *Games, MYSQL_RES *mysql_res, bool ICanEditQuestions); static void Gam_ListQuestionForEdition (const struct Tst_Question *Question, - unsigned QstInd,bool QuestionExists); + unsigned QstInd,bool QuestionExists, + const char *Anchor); static void Gam_PutIconToAddNewQuestions (void *Games); static void Gam_PutButtonToAddNewQuestions (struct Gam_Games *Games); @@ -1684,15 +1687,13 @@ void Gam_RequestNewQuestion (void) Gam_GetDataOfGameByCod (&Game); /***** Check if game has matches *****/ - if (Gam_CheckIfEditable (&Game)) - { - /***** Show form to create a new question in this game *****/ - Games.GamCod = Game.GamCod; - Tst_RequestSelectTestsForGame (&Games); - } - else + if (!Gam_CheckIfEditable (&Game)) Lay_NoPermissionExit (); + /***** Show form to create a new question in this game *****/ + Games.GamCod = Game.GamCod; + Tst_RequestSelectTestsForGame (&Games); + /***** Show current game *****/ Gam_ShowOnlyOneGame (&Games,&Game, true, // List game questions @@ -1720,14 +1721,12 @@ void Gam_ListTstQuestionsToSelect (void) Gam_GetDataOfGameByCod (&Game); /***** Check if game has matches *****/ - if (Gam_CheckIfEditable (&Game)) - { - /***** List several test questions for selection *****/ - Games.GamCod = Game.GamCod; - Tst_ListQuestionsToSelectForGame (&Games); - } - else + if (!Gam_CheckIfEditable (&Game)) Lay_NoPermissionExit (); + + /***** List several test questions for selection *****/ + Games.GamCod = Game.GamCod; + Tst_ListQuestionsToSelectForGame (&Games); } /*****************************************************************************/ @@ -1770,6 +1769,35 @@ static void Gam_RemAnswersOfAQuestion (long GamCod,unsigned QstInd) GamCod,QstInd); } +/*****************************************************************************/ +/************ Get question index given game and code of question *************/ +/*****************************************************************************/ + +static unsigned Gam_GetQstIndFromQstCod (long GamCod,long QstCod) + { + MYSQL_RES *mysql_res; + MYSQL_ROW row; + unsigned QstInd = 0; // Return 0 is question is not present in game + + /***** Get question index in a game given the question code *****/ + if (DB_QuerySELECT (&mysql_res,"can not get question index", + "SELECT QstInd FROM gam_questions" + " WHERE GamCod=%ld AND QstCod=%ld", + GamCod,QstCod)) + { + /***** Get question code (row[0]) *****/ + row = mysql_fetch_row (mysql_res); + QstInd = Str_ConvertStrToUnsigned (row[0]); + if (QstInd == 0) + Lay_ShowErrorAndExit ("Error: wrong question index."); + } + + /***** Free structure that stores the query result *****/ + DB_FreeMySQLResult (&mysql_res); + + return QstInd; + } + /*****************************************************************************/ /************ Get question code given game and index of question *************/ /*****************************************************************************/ @@ -1970,11 +1998,12 @@ static void Gam_ListOneOrMoreQuestionsForEdition (struct Gam_Games *Games, struct Tst_Question Question; unsigned QstInd; unsigned MaxQstInd; + char *Anchor = NULL; char StrQstInd[Cns_MAX_DECIMAL_DIGITS_UINT + 1]; bool QuestionExists; /***** Get maximum question index *****/ - MaxQstInd = Gam_GetMaxQuestionIndexInGame (GamCod); + MaxQstInd = Gam_GetMaxQuestionIndexInGame (GamCod); // 0 is no questions in game /***** Write the heading *****/ HTM_TABLE_BeginWideMarginPadding (2); @@ -2015,11 +2044,19 @@ static void Gam_ListOneOrMoreQuestionsForEdition (struct Gam_Games *Games, /* Get question code (row[1]) */ Question.QstCod = Str_ConvertStrCodToLongCod (row[1]); - /***** Icons *****/ + /* Initialize context */ Games->GamCod = GamCod; Games->QstInd = QstInd; + + /***** Build anchor string *****/ + // The same question may appear more than once. + // In that case, the page will be positioned in the first occurrence. + Frm_SetAnchorStr (Question.QstCod,&Anchor); + + /***** Begin row *****/ HTM_TR_Begin (NULL); + /***** Icons *****/ HTM_TD_Begin ("class=\"BT%u\"",Gbl.RowEvenOdd); /* Put icon to remove the question */ @@ -2037,7 +2074,7 @@ static void Gam_ListOneOrMoreQuestionsForEdition (struct Gam_Games *Games, /* Put icon to move up the question */ if (ICanEditQuestions && QstInd > 1) { - Lay_PutContextualLinkOnlyIcon (ActUp_GamQst,NULL, + Lay_PutContextualLinkOnlyIcon (ActUp_GamQst,Anchor, Gam_PutParamsOneQst,Games, "arrow-up.svg", Str_BuildStringStr (Txt_Move_up_X, @@ -2050,7 +2087,7 @@ static void Gam_ListOneOrMoreQuestionsForEdition (struct Gam_Games *Games, /* Put icon to move down the question */ if (ICanEditQuestions && QstInd < MaxQstInd) { - Lay_PutContextualLinkOnlyIcon (ActDwnGamQst,NULL, + Lay_PutContextualLinkOnlyIcon (ActDwnGamQst,Anchor, Gam_PutParamsOneQst,Games, "arrow-down.svg", Str_BuildStringStr (Txt_Move_down_X, @@ -2069,10 +2106,14 @@ static void Gam_ListOneOrMoreQuestionsForEdition (struct Gam_Games *Games, /***** Question *****/ QuestionExists = Tst_GetQstDataFromDB (&Question); - Gam_ListQuestionForEdition (&Question,QstInd,QuestionExists); + Gam_ListQuestionForEdition (&Question,QstInd,QuestionExists,Anchor); + /***** End row *****/ HTM_TR_End (); + /***** Free anchor string *****/ + Frm_FreeAnchorStr (Anchor); + /***** Destroy test question *****/ Tst_QstDestructor (&Question); } @@ -2086,7 +2127,8 @@ static void Gam_ListOneOrMoreQuestionsForEdition (struct Gam_Games *Games, /*****************************************************************************/ static void Gam_ListQuestionForEdition (const struct Tst_Question *Question, - unsigned QstInd,bool QuestionExists) + unsigned QstInd,bool QuestionExists, + const char *Anchor) { extern const char *Txt_Question_removed; @@ -2110,6 +2152,7 @@ static void Gam_ListQuestionForEdition (const struct Tst_Question *Question, /***** Write stem (row[3]) and media *****/ HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd); + HTM_ARTICLE_Begin (Anchor); if (QuestionExists) { /* Write stem */ @@ -2133,6 +2176,7 @@ static void Gam_ListQuestionForEdition (const struct Tst_Question *Question, HTM_Txt (Txt_Question_removed); HTM_SPAN_End (); } + HTM_ARTICLE_End (); HTM_TD_End (); } @@ -2171,12 +2215,15 @@ static void Gam_PutButtonToAddNewQuestions (struct Gam_Games *Games) void Gam_AddTstQuestionsToGame (void) { extern const char *Txt_No_questions_have_been_added; + extern const char *Txt_A_question_has_been_added; + extern const char *Txt_X_questions_have_been_added; struct Gam_Games Games; struct Gam_Game Game; const char *Ptr; char LongStr[Cns_MAX_DECIMAL_DIGITS_LONG + 1]; long QstCod; unsigned MaxQstInd; + unsigned NumQstsAdded; /***** Reset games context *****/ Gam_ResetGames (&Games); @@ -2190,30 +2237,35 @@ void Gam_AddTstQuestionsToGame (void) Gam_GetDataOfGameByCod (&Game); /***** Check if game has matches *****/ - if (Gam_CheckIfEditable (&Game)) + if (!Gam_CheckIfEditable (&Game)) + Lay_NoPermissionExit (); + + /***** Get selected questions *****/ + /* Allocate space for selected question codes */ + Gam_AllocateListSelectedQuestions (&Games); + + /* Get question codes */ + Par_GetParMultiToText ("QstCods",Games.ListQuestions, + Gam_MAX_BYTES_LIST_SELECTED_QUESTIONS); + + /* Check number of questions */ + NumQstsAdded = 0; + if (Gam_CountNumQuestionsInList (&Games)) // If questions selected... { - /***** Get selected questions *****/ - /* Allocate space for selected question codes */ - Gam_AllocateListSelectedQuestions (&Games); - - /* Get question codes */ - Par_GetParMultiToText ("QstCods",Games.ListQuestions, - Gam_MAX_BYTES_LIST_SELECTED_QUESTIONS); - - /* Check number of questions */ - if (Gam_CountNumQuestionsInList (&Games)) // If questions selected... + /***** Insert questions in database *****/ + Ptr = Games.ListQuestions; + while (*Ptr) { - /***** Insert questions in database *****/ - Ptr = Games.ListQuestions; - while (*Ptr) - { - /* Get next code */ - Par_GetNextStrUntilSeparParamMult (&Ptr,LongStr,Cns_MAX_DECIMAL_DIGITS_LONG); - if (sscanf (LongStr,"%ld",&QstCod) != 1) - Lay_ShowErrorAndExit ("Wrong question code."); + /* Get next code */ + Par_GetNextStrUntilSeparParamMult (&Ptr,LongStr,Cns_MAX_DECIMAL_DIGITS_LONG); + if (sscanf (LongStr,"%ld",&QstCod) != 1) + Lay_ShowErrorAndExit ("Wrong question code."); + /* Check if question is already present in game */ + if (Gam_GetQstIndFromQstCod (Game.GamCod,QstCod) == 0) // This question is not yet in this game + { /* Get current maximum index */ - MaxQstInd = Gam_GetMaxQuestionIndexInGame (Game.GamCod); // -1 if no questions + MaxQstInd = Gam_GetMaxQuestionIndexInGame (Game.GamCod); // 0 is no questions in game /* Insert question in the table of questions */ DB_QueryINSERT ("can not create question", @@ -2222,16 +2274,22 @@ void Gam_AddTstQuestionsToGame (void) " VALUES" " (%ld,%ld,%u)", Game.GamCod,QstCod,MaxQstInd + 1); + + NumQstsAdded++; } } - else - Ale_ShowAlert (Ale_WARNING,Txt_No_questions_have_been_added); - - /***** Free space for selected question codes *****/ - Gam_FreeListsSelectedQuestions (&Games); } + + /***** Show warning in no questions added *****/ + if (NumQstsAdded == 0) + Ale_ShowAlert (Ale_WARNING,Txt_No_questions_have_been_added); + else if (NumQstsAdded == 1) + Ale_ShowAlert (Ale_SUCCESS,Txt_A_question_has_been_added); else - Lay_NoPermissionExit (); + Ale_ShowAlert (Ale_SUCCESS,Txt_X_questions_have_been_added,NumQstsAdded); + + /***** Free space for selected question codes *****/ + Gam_FreeListsSelectedQuestions (&Games); /***** Show current game *****/ Gam_ShowOnlyOneGame (&Games,&Game, @@ -2313,23 +2371,21 @@ void Gam_RequestRemoveQst (void) Gam_GetDataOfGameByCod (&Game); /***** Check if game has matches *****/ - if (Gam_CheckIfEditable (&Game)) - { - /***** Get question index *****/ - QstInd = Gam_GetParamQstInd (); - - /***** Show question and button to remove question *****/ - Games.GamCod = Game.GamCod; - Games.QstInd = QstInd; - Ale_ShowAlertAndButton (ActRemGamQst,NULL,NULL, - Gam_PutParamsOneQst,&Games, - Btn_REMOVE_BUTTON,Txt_Remove_question, - Ale_QUESTION,Txt_Do_you_really_want_to_remove_the_question_X, - QstInd); - } - else + if (!Gam_CheckIfEditable (&Game)) Lay_NoPermissionExit (); + /***** Get question index *****/ + QstInd = Gam_GetParamQstInd (); + + /***** Show question and button to remove question *****/ + Games.GamCod = Game.GamCod; + Games.QstInd = QstInd; + Ale_ShowAlertAndButton (ActRemGamQst,NULL,NULL, + Gam_PutParamsOneQst,&Games, + Btn_REMOVE_BUTTON,Txt_Remove_question, + Ale_QUESTION,Txt_Do_you_really_want_to_remove_the_question_X, + QstInd); + /***** Show current game *****/ Gam_ShowOnlyOneGame (&Games,&Game, true, // List game questions @@ -2359,42 +2415,40 @@ void Gam_RemoveQst (void) Gam_GetDataOfGameByCod (&Game); /***** Check if game has matches *****/ - if (Gam_CheckIfEditable (&Game)) - { - /***** Get question index *****/ - QstInd = Gam_GetParamQstInd (); - - /***** Remove the question from all the tables *****/ - /* Remove answers from this test question */ - Gam_RemAnswersOfAQuestion (Game.GamCod,QstInd); - - /* Remove the question itself */ - DB_QueryDELETE ("can not remove a question", - "DELETE FROM gam_questions" - " WHERE GamCod=%ld AND QstInd=%u", - Game.GamCod,QstInd); - if (!mysql_affected_rows (&Gbl.mysql)) - Lay_ShowErrorAndExit ("The question to be removed does not exist."); - - /* Change index of questions greater than this */ - DB_QueryUPDATE ("can not update indexes of questions in table of answers", - "UPDATE mch_answers,mch_matches" - " SET mch_answers.QstInd=mch_answers.QstInd-1" - " WHERE mch_matches.GamCod=%ld" - " AND mch_matches.MchCod=mch_answers.MchCod" - " AND mch_answers.QstInd>%u", - Game.GamCod,QstInd); - DB_QueryUPDATE ("can not update indexes of questions", - "UPDATE gam_questions SET QstInd=QstInd-1" - " WHERE GamCod=%ld AND QstInd>%u", - Game.GamCod,QstInd); - - /***** Write message *****/ - Ale_ShowAlert (Ale_SUCCESS,Txt_Question_removed); - } - else + if (!Gam_CheckIfEditable (&Game)) Lay_NoPermissionExit (); + /***** Get question index *****/ + QstInd = Gam_GetParamQstInd (); + + /***** Remove the question from all the tables *****/ + /* Remove answers from this test question */ + Gam_RemAnswersOfAQuestion (Game.GamCod,QstInd); + + /* Remove the question itself */ + DB_QueryDELETE ("can not remove a question", + "DELETE FROM gam_questions" + " WHERE GamCod=%ld AND QstInd=%u", + Game.GamCod,QstInd); + if (!mysql_affected_rows (&Gbl.mysql)) + Lay_ShowErrorAndExit ("The question to be removed does not exist."); + + /* Change index of questions greater than this */ + DB_QueryUPDATE ("can not update indexes of questions in table of answers", + "UPDATE mch_answers,mch_matches" + " SET mch_answers.QstInd=mch_answers.QstInd-1" + " WHERE mch_matches.GamCod=%ld" + " AND mch_matches.MchCod=mch_answers.MchCod" + " AND mch_answers.QstInd>%u", + Game.GamCod,QstInd); + DB_QueryUPDATE ("can not update indexes of questions", + "UPDATE gam_questions SET QstInd=QstInd-1" + " WHERE GamCod=%ld AND QstInd>%u", + Game.GamCod,QstInd); + + /***** Write message *****/ + Ale_ShowAlert (Ale_SUCCESS,Txt_Question_removed); + /***** Show current game *****/ Gam_ShowOnlyOneGame (&Games,&Game, true, // List game questions @@ -2407,7 +2461,6 @@ void Gam_RemoveQst (void) void Gam_MoveUpQst (void) { - extern const char *Txt_The_question_has_been_moved_up; extern const char *Txt_Movement_not_allowed; struct Gam_Games Games; struct Gam_Game Game; @@ -2426,30 +2479,25 @@ void Gam_MoveUpQst (void) Gam_GetDataOfGameByCod (&Game); /***** Check if game has matches *****/ - if (Gam_CheckIfEditable (&Game)) + if (!Gam_CheckIfEditable (&Game)) + Lay_NoPermissionExit (); + + /***** Get question index *****/ + QstIndBottom = Gam_GetParamQstInd (); + + /***** Move up question *****/ + if (QstIndBottom > 1) { - /***** Get question index *****/ - QstIndBottom = Gam_GetParamQstInd (); + /* Indexes of questions to be exchanged */ + QstIndTop = Gam_GetPrevQuestionIndexInGame (Game.GamCod,QstIndBottom); + if (!QstIndTop) + Lay_ShowErrorAndExit ("Wrong index of question."); - /***** Move up question *****/ - if (QstIndBottom > 1) - { - /* Indexes of questions to be exchanged */ - QstIndTop = Gam_GetPrevQuestionIndexInGame (Game.GamCod,QstIndBottom); - if (!QstIndTop) - Lay_ShowErrorAndExit ("Wrong index of question."); - - /* Exchange questions */ - Gam_ExchangeQuestions (Game.GamCod,QstIndTop,QstIndBottom); - - /* Success alert */ - Ale_ShowAlert (Ale_SUCCESS,Txt_The_question_has_been_moved_up); - } - else - Ale_ShowAlert (Ale_WARNING,Txt_Movement_not_allowed); + /* Exchange questions */ + Gam_ExchangeQuestions (Game.GamCod,QstIndTop,QstIndBottom); } else - Lay_NoPermissionExit (); + Ale_ShowAlert (Ale_WARNING,Txt_Movement_not_allowed); /***** Show current game *****/ Gam_ShowOnlyOneGame (&Games,&Game, @@ -2463,7 +2511,6 @@ void Gam_MoveUpQst (void) void Gam_MoveDownQst (void) { - extern const char *Txt_The_question_has_been_moved_down; extern const char *Txt_Movement_not_allowed; extern const char *Txt_This_game_has_no_questions; struct Gam_Games Games; @@ -2484,38 +2531,33 @@ void Gam_MoveDownQst (void) Gam_GetDataOfGameByCod (&Game); /***** Check if game has matches *****/ - if (Gam_CheckIfEditable (&Game)) + if (!Gam_CheckIfEditable (&Game)) + Lay_NoPermissionExit (); + + /***** Get question index *****/ + QstIndTop = Gam_GetParamQstInd (); + + /***** Get maximum question index *****/ + MaxQstInd = Gam_GetMaxQuestionIndexInGame (Game.GamCod); // 0 is no questions in game + + /***** Move down question *****/ + if (MaxQstInd) { - /***** Get question index *****/ - QstIndTop = Gam_GetParamQstInd (); - - /***** Get maximum question index *****/ - MaxQstInd = Gam_GetMaxQuestionIndexInGame (Game.GamCod); - - /***** Move down question *****/ - if (MaxQstInd) + if (QstIndTop < MaxQstInd) { - if (QstIndTop < MaxQstInd) - { - /* Indexes of questions to be exchanged */ - QstIndBottom = Gam_GetNextQuestionIndexInGame (Game.GamCod,QstIndTop); - if (!QstIndBottom) - Lay_ShowErrorAndExit ("Wrong index of question."); + /* Indexes of questions to be exchanged */ + QstIndBottom = Gam_GetNextQuestionIndexInGame (Game.GamCod,QstIndTop); + if (!QstIndBottom) + Lay_ShowErrorAndExit ("Wrong index of question."); - /* Exchange questions */ - Gam_ExchangeQuestions (Game.GamCod,QstIndTop,QstIndBottom); - - /* Success alert */ - Ale_ShowAlert (Ale_SUCCESS,Txt_The_question_has_been_moved_down); - } - else - Ale_ShowAlert (Ale_WARNING,Txt_Movement_not_allowed); + /* Exchange questions */ + Gam_ExchangeQuestions (Game.GamCod,QstIndTop,QstIndBottom); } else - Ale_ShowAlert (Ale_WARNING,Txt_This_game_has_no_questions); + Ale_ShowAlert (Ale_WARNING,Txt_Movement_not_allowed); } else - Lay_NoPermissionExit (); + Ale_ShowAlert (Ale_WARNING,Txt_This_game_has_no_questions); /***** Show current game *****/ Gam_ShowOnlyOneGame (&Games,&Game, @@ -2547,25 +2589,36 @@ static void Gam_ExchangeQuestions (long GamCod, Example: QstIndTop = 1; QstCodTop = 218 QstIndBottom = 2; QstCodBottom = 220 - +--------+--------+ +--------+--------+ +--------+--------+ - | QstInd | QstCod | | QstInd | QstCod | | QstInd | QstCod | - +--------+--------+ +--------+--------+ +--------+--------+ - | 1 | 218 | -----> | 2 | 218 | = | 1 | 220 | - | 2 | 220 | | 1 | 220 | | 2 | 218 | - | 3 | 232 | | 3 | 232 | | 3 | 232 | - +--------+--------+ +--------+--------+ +--------+--------+ - */ + Step 1 Step 2 Step 3 + +--------+--------+ +--------+--------+ +--------+--------+ +--------+--------+ + | QstInd | QstCod | | QstInd | QstCod | | QstInd | QstCod | | QstInd | QstCod | + +--------+--------+ +--------+--------+ +--------+--------+ +--------+--------+ + | 1 | 218 |-->| -2 | 218 |-->| -2 | 218 |-->| 2 | 218 | + | 2 | 220 | | 2 | 220 | | 1 | 220 | | 1 | 220 | + | 3 | 232 | | 3 | 232 | | 3 | 232 | | 3 | 232 | + +--------+--------+ +--------+--------+ +--------+--------+ +--------+--------+ + */ + /* Step 1: change temporarily top index to minus bottom index + in order to not repeat unique index (GamCod,QstInd) */ DB_QueryUPDATE ("can not exchange indexes of questions", - "UPDATE gam_questions SET QstInd=%u" + "UPDATE gam_questions SET QstInd=-%u" " WHERE GamCod=%ld AND QstCod=%ld", - QstIndBottom, - GamCod,QstCodTop); + QstIndBottom, + GamCod,QstCodTop); + /* Step 2: change bottom index to old top index */ DB_QueryUPDATE ("can not exchange indexes of questions", "UPDATE gam_questions SET QstInd=%u" " WHERE GamCod=%ld AND QstCod=%ld", - QstIndTop, - GamCod,QstCodBottom); + QstIndTop, + GamCod,QstCodBottom); + + /* Step 3: change top index to old bottom index */ + DB_QueryUPDATE ("can not exchange indexes of questions", + "UPDATE gam_questions SET QstInd=%u" + " WHERE GamCod=%ld AND QstCod=%ld", + QstIndBottom, + GamCod,QstCodTop); /***** Unlock table *****/ Gbl.DB.LockedTables = false; // Set to false before the following unlock... diff --git a/swad_text.c b/swad_text.c index 5c104049d..f7b09a255 100644 --- a/swad_text.c +++ b/swad_text.c @@ -291,11 +291,53 @@ const char *Txt_A_message_has_been_sent_to_email_address_X_to_confirm_that_addre " para confirmar esse endereço."; #endif +const char *Txt_A_question_has_been_added = +#if L==1 // ca + "S'ha afegit una pregunta."; +#elif L==2 // de + "Eine Frage wurde hinzugefügt."; +#elif L==3 // en + "A question has been added."; +#elif L==4 // es + "Se ha añadido una pregunta."; +#elif L==5 // fr + "Une question a été ajout%eacute;e."; +#elif L==6 // gn + "Se ha añadido una pregunta."; // Okoteve traducción +#elif L==7 // it + "È stata aggiunta una domanda."; +#elif L==8 // pl + "Pytanie zostało dodane."; +#elif L==9 // pt + "Uma pergunta foi adicionada."; +#endif + +const char *Txt_X_questions_have_been_added = // Warning: it is very important to include %u in the following sentences +#if L==1 // ca + "S'han afegit %u preguntes."; +#elif L==2 // de + "%u Fragen wurden hinzugefügt."; +#elif L==3 // en + "%u questions have been added."; +#elif L==4 // es + "Se han añadido %u preguntas."; +#elif L==5 // fr + "%u questions ont été ajoutées."; +#elif L==6 // gn + "Se han añadido %u preguntas."; // Okoteve traducción +#elif L==7 // it + "Sono state aggiunte %u domande."; +#elif L==8 // pl + "Dodano %u pytań."; +#elif L==9 // pt + "%u perguntas foram adicionadas."; +#endif + const char *Txt_A_student_can_belong_to_several_groups = #if L==1 // ca "Un estudiant pot pertànyer a diversos grups"; #elif L==2 // de - "Ein Student kann mehreren Gruppen angehören"; + "Ein Student kann mehreren Gruppen angehören"; #elif L==3 // en "A student can belong to several groups"; #elif L==4 // es @@ -391,7 +433,7 @@ const char *Txt_A_teacher_or_administrator_has_enroled_you_as_X_into_the_course_ " ou você prefere para ser removido/a da disciplina?"; #endif -const char *Txt_A_user_can_not_have_more_than_X_IDs = +const char *Txt_A_user_can_not_have_more_than_X_IDs = // Warning: it is very important to include %u in the following sentences #if L==1 // ca "Un usuari no pot tenir més de %u IDs (DNI/cèdulas)"; #elif L==2 // de @@ -49420,48 +49462,6 @@ const char *Txt_The_properties_of_file_X_have_been_saved = // Warning: it is ver "As propriedades do arquivo %s foram salvas."; #endif -const char *Txt_The_question_has_been_moved_down = -#if L==1 // ca - "La pregunta ha estat moguda cap avall."; -#elif L==2 // de - "Die Frage wurde nach unten bewegt."; -#elif L==3 // en - "The question has been moved down."; -#elif L==4 // es - "La pregunta se ha movido hacia abajo."; -#elif L==5 // fr - "La question a été déplacée vers le bas."; -#elif L==6 // gn - "La pregunta se ha movido hacia abajo."; // Okoteve traducción -#elif L==7 // it - "La questione è stata abbattuta."; -#elif L==8 // pl - "Pytanie zostało przeniesione."; -#elif L==9 // pt - "A pergunta foi movida para baixo."; -#endif - -const char *Txt_The_question_has_been_moved_up = -#if L==1 // ca - "La pregunta ha estat moguda cap amunt."; -#elif L==2 // de - "Die Frage wurde nach oben verschoben."; -#elif L==3 // en - "The question has been moved up."; -#elif L==4 // es - "La pregunta se ha movido hacia arriba."; -#elif L==5 // fr - "La question a été déplacée vers le haut."; -#elif L==6 // gn - "La pregunta se ha movido hacia arriba."; // Okoteve traducción -#elif L==7 // it - "La questione è stata spostata."; -#elif L==8 // pl - "Pytanie zostało poruszone."; -#elif L==9 // pt - "A pergunta foi movida para cima."; -#endif - const char *Txt_The_record_field_X_already_exists = // Warning: it is very important to include %s in the following sentences #if L==1 // ca "El campo de ficha %s ya existe."; // Necessita traduccio