Version19.199.2

This commit is contained in:
acanas 2020-04-27 00:06:58 +02:00
parent 0f1838739c
commit 787e62fda8
6 changed files with 272 additions and 219 deletions

View File

@ -802,10 +802,10 @@ CREATE TABLE IF NOT EXISTS mch_results (
-- --
CREATE TABLE IF NOT EXISTS gam_questions ( CREATE TABLE IF NOT EXISTS gam_questions (
GamCod INT NOT NULL, GamCod INT NOT NULL,
QstCod INT NOT NULL,
QstInd INT NOT NULL DEFAULT 0, QstInd INT NOT NULL DEFAULT 0,
INDEX(GamCod), QstCod INT NOT NULL,
INDEX(QstCod)); UNIQUE INDEX(GamCod,QstInd),
UNIQUE INDEX(GamCod,QstCod));
-- --
-- Table mch_times: stores the elapsed time in every question in every match played -- Table mch_times: stores the elapsed time in every question in every match played
-- --

View File

@ -544,10 +544,18 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - *
En OpenSWAD: En OpenSWAD:
ps2pdf source.ps destination.pdf 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 CSS_FILE "swad19.193.1.css"
#define JS_FILE "swad19.193.1.js" #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.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.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) Version 19.198: Apr 26, 2020 Remove set of questions. (299054 lines)

View File

@ -1586,18 +1586,18 @@ mysql> DESCRIBE gam_questions;
+--------+---------+------+-----+---------+-------+ +--------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra | | Field | Type | Null | Key | Default | Extra |
+--------+---------+------+-----+---------+-------+ +--------+---------+------+-----+---------+-------+
| GamCod | int(11) | NO | MUL | NULL | | | GamCod | int(11) | NO | PRI | NULL | |
| QstCod | int(11) | NO | MUL | NULL | | | QstInd | int(11) | NO | PRI | 0 | |
| QstInd | int(11) | NO | | 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 (" DB_CreateTable ("CREATE TABLE IF NOT EXISTS gam_questions ("
"GamCod INT NOT NULL," "GamCod INT NOT NULL,"
"QstCod INT NOT NULL,"
"QstInd INT NOT NULL DEFAULT 0," "QstInd INT NOT NULL DEFAULT 0,"
"INDEX(GamCod)," "QstCod INT NOT NULL,"
"INDEX(QstCod))"); "UNIQUE INDEX(GamCod,QstInd),"
"UNIQUE INDEX(GamCod,QstCod))");
/***** Table mch_answers *****/ /***** Table mch_answers *****/
/* /*

View File

@ -3547,7 +3547,6 @@ void Exa_RemoveQst (void)
void Exa_MoveUpQst (void) void Exa_MoveUpQst (void)
{ {
extern const char *Txt_The_question_has_been_moved_up;
extern const char *Txt_Movement_not_allowed; extern const char *Txt_Movement_not_allowed;
struct Exa_Exams Exams; struct Exa_Exams Exams;
struct Exa_Exam Exam; struct Exa_Exam Exam;
@ -3585,9 +3584,6 @@ void Exa_MoveUpQst (void)
/* Exchange questions */ /* Exchange questions */
Exa_ExchangeQuestions (Exam.ExaCod,QstIndTop,QstIndBottom); Exa_ExchangeQuestions (Exam.ExaCod,QstIndTop,QstIndBottom);
/* Success alert */
Ale_ShowAlert (Ale_SUCCESS,Txt_The_question_has_been_moved_up);
} }
else else
Ale_ShowAlert (Ale_WARNING,Txt_Movement_not_allowed); Ale_ShowAlert (Ale_WARNING,Txt_Movement_not_allowed);
@ -3607,7 +3603,6 @@ void Exa_MoveUpQst (void)
void Exa_MoveDownQst (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_Movement_not_allowed;
extern const char *Txt_This_exam_has_no_questions; extern const char *Txt_This_exam_has_no_questions;
struct Exa_Exams Exams; struct Exa_Exams Exams;
@ -3652,9 +3647,6 @@ void Exa_MoveDownQst (void)
/* Exchange questions */ /* Exchange questions */
Exa_ExchangeQuestions (Exam.ExaCod,QstIndTop,QstIndBottom); Exa_ExchangeQuestions (Exam.ExaCod,QstIndTop,QstIndBottom);
/* Success alert */
Ale_ShowAlert (Ale_SUCCESS,Txt_The_question_has_been_moved_down);
} }
else else
Ale_ShowAlert (Ale_WARNING,Txt_Movement_not_allowed); Ale_ShowAlert (Ale_WARNING,Txt_Movement_not_allowed);

View File

@ -150,6 +150,8 @@ static void Gam_UpdateGame (struct Gam_Game *Game,const char *Txt);
static void Gam_RemAnswersOfAQuestion (long GamCod,unsigned QstInd); static void Gam_RemAnswersOfAQuestion (long GamCod,unsigned QstInd);
static unsigned Gam_GetQstIndFromQstCod (long GamCod,long QstCod);
static unsigned Gam_GetMaxQuestionIndexInGame (long GamCod); static unsigned Gam_GetMaxQuestionIndexInGame (long GamCod);
static void Gam_ListGameQuestions (struct Gam_Games *Games,struct Gam_Game *Game); static void Gam_ListGameQuestions (struct Gam_Games *Games,struct Gam_Game *Game);
static void Gam_ListOneOrMoreQuestionsForEdition (struct Gam_Games *Games, static void Gam_ListOneOrMoreQuestionsForEdition (struct Gam_Games *Games,
@ -157,7 +159,8 @@ static void Gam_ListOneOrMoreQuestionsForEdition (struct Gam_Games *Games,
MYSQL_RES *mysql_res, MYSQL_RES *mysql_res,
bool ICanEditQuestions); bool ICanEditQuestions);
static void Gam_ListQuestionForEdition (const struct Tst_Question *Question, 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_PutIconToAddNewQuestions (void *Games);
static void Gam_PutButtonToAddNewQuestions (struct Gam_Games *Games); static void Gam_PutButtonToAddNewQuestions (struct Gam_Games *Games);
@ -1684,15 +1687,13 @@ void Gam_RequestNewQuestion (void)
Gam_GetDataOfGameByCod (&Game); Gam_GetDataOfGameByCod (&Game);
/***** Check if game has matches *****/ /***** Check if game has matches *****/
if (Gam_CheckIfEditable (&Game)) if (!Gam_CheckIfEditable (&Game))
{
/***** Show form to create a new question in this game *****/
Games.GamCod = Game.GamCod;
Tst_RequestSelectTestsForGame (&Games);
}
else
Lay_NoPermissionExit (); Lay_NoPermissionExit ();
/***** Show form to create a new question in this game *****/
Games.GamCod = Game.GamCod;
Tst_RequestSelectTestsForGame (&Games);
/***** Show current game *****/ /***** Show current game *****/
Gam_ShowOnlyOneGame (&Games,&Game, Gam_ShowOnlyOneGame (&Games,&Game,
true, // List game questions true, // List game questions
@ -1720,14 +1721,12 @@ void Gam_ListTstQuestionsToSelect (void)
Gam_GetDataOfGameByCod (&Game); Gam_GetDataOfGameByCod (&Game);
/***** Check if game has matches *****/ /***** Check if game has matches *****/
if (Gam_CheckIfEditable (&Game)) if (!Gam_CheckIfEditable (&Game))
{
/***** List several test questions for selection *****/
Games.GamCod = Game.GamCod;
Tst_ListQuestionsToSelectForGame (&Games);
}
else
Lay_NoPermissionExit (); 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); 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 *************/ /************ 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; struct Tst_Question Question;
unsigned QstInd; unsigned QstInd;
unsigned MaxQstInd; unsigned MaxQstInd;
char *Anchor = NULL;
char StrQstInd[Cns_MAX_DECIMAL_DIGITS_UINT + 1]; char StrQstInd[Cns_MAX_DECIMAL_DIGITS_UINT + 1];
bool QuestionExists; bool QuestionExists;
/***** Get maximum question index *****/ /***** Get maximum question index *****/
MaxQstInd = Gam_GetMaxQuestionIndexInGame (GamCod); MaxQstInd = Gam_GetMaxQuestionIndexInGame (GamCod); // 0 is no questions in game
/***** Write the heading *****/ /***** Write the heading *****/
HTM_TABLE_BeginWideMarginPadding (2); HTM_TABLE_BeginWideMarginPadding (2);
@ -2015,11 +2044,19 @@ static void Gam_ListOneOrMoreQuestionsForEdition (struct Gam_Games *Games,
/* Get question code (row[1]) */ /* Get question code (row[1]) */
Question.QstCod = Str_ConvertStrCodToLongCod (row[1]); Question.QstCod = Str_ConvertStrCodToLongCod (row[1]);
/***** Icons *****/ /* Initialize context */
Games->GamCod = GamCod; Games->GamCod = GamCod;
Games->QstInd = QstInd; 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); HTM_TR_Begin (NULL);
/***** Icons *****/
HTM_TD_Begin ("class=\"BT%u\"",Gbl.RowEvenOdd); HTM_TD_Begin ("class=\"BT%u\"",Gbl.RowEvenOdd);
/* Put icon to remove the question */ /* 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 */ /* Put icon to move up the question */
if (ICanEditQuestions && QstInd > 1) if (ICanEditQuestions && QstInd > 1)
{ {
Lay_PutContextualLinkOnlyIcon (ActUp_GamQst,NULL, Lay_PutContextualLinkOnlyIcon (ActUp_GamQst,Anchor,
Gam_PutParamsOneQst,Games, Gam_PutParamsOneQst,Games,
"arrow-up.svg", "arrow-up.svg",
Str_BuildStringStr (Txt_Move_up_X, 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 */ /* Put icon to move down the question */
if (ICanEditQuestions && QstInd < MaxQstInd) if (ICanEditQuestions && QstInd < MaxQstInd)
{ {
Lay_PutContextualLinkOnlyIcon (ActDwnGamQst,NULL, Lay_PutContextualLinkOnlyIcon (ActDwnGamQst,Anchor,
Gam_PutParamsOneQst,Games, Gam_PutParamsOneQst,Games,
"arrow-down.svg", "arrow-down.svg",
Str_BuildStringStr (Txt_Move_down_X, Str_BuildStringStr (Txt_Move_down_X,
@ -2069,10 +2106,14 @@ static void Gam_ListOneOrMoreQuestionsForEdition (struct Gam_Games *Games,
/***** Question *****/ /***** Question *****/
QuestionExists = Tst_GetQstDataFromDB (&Question); QuestionExists = Tst_GetQstDataFromDB (&Question);
Gam_ListQuestionForEdition (&Question,QstInd,QuestionExists); Gam_ListQuestionForEdition (&Question,QstInd,QuestionExists,Anchor);
/***** End row *****/
HTM_TR_End (); HTM_TR_End ();
/***** Free anchor string *****/
Frm_FreeAnchorStr (Anchor);
/***** Destroy test question *****/ /***** Destroy test question *****/
Tst_QstDestructor (&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, 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; 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 *****/ /***** Write stem (row[3]) and media *****/
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd); HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
HTM_ARTICLE_Begin (Anchor);
if (QuestionExists) if (QuestionExists)
{ {
/* Write stem */ /* Write stem */
@ -2133,6 +2176,7 @@ static void Gam_ListQuestionForEdition (const struct Tst_Question *Question,
HTM_Txt (Txt_Question_removed); HTM_Txt (Txt_Question_removed);
HTM_SPAN_End (); HTM_SPAN_End ();
} }
HTM_ARTICLE_End ();
HTM_TD_End (); HTM_TD_End ();
} }
@ -2171,12 +2215,15 @@ static void Gam_PutButtonToAddNewQuestions (struct Gam_Games *Games)
void Gam_AddTstQuestionsToGame (void) void Gam_AddTstQuestionsToGame (void)
{ {
extern const char *Txt_No_questions_have_been_added; 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_Games Games;
struct Gam_Game Game; struct Gam_Game Game;
const char *Ptr; const char *Ptr;
char LongStr[Cns_MAX_DECIMAL_DIGITS_LONG + 1]; char LongStr[Cns_MAX_DECIMAL_DIGITS_LONG + 1];
long QstCod; long QstCod;
unsigned MaxQstInd; unsigned MaxQstInd;
unsigned NumQstsAdded;
/***** Reset games context *****/ /***** Reset games context *****/
Gam_ResetGames (&Games); Gam_ResetGames (&Games);
@ -2190,30 +2237,35 @@ void Gam_AddTstQuestionsToGame (void)
Gam_GetDataOfGameByCod (&Game); Gam_GetDataOfGameByCod (&Game);
/***** Check if game has matches *****/ /***** 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 *****/ /***** Insert questions in database *****/
/* Allocate space for selected question codes */ Ptr = Games.ListQuestions;
Gam_AllocateListSelectedQuestions (&Games); while (*Ptr)
/* 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 *****/ /* Get next code */
Ptr = Games.ListQuestions; Par_GetNextStrUntilSeparParamMult (&Ptr,LongStr,Cns_MAX_DECIMAL_DIGITS_LONG);
while (*Ptr) 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 */ /* 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 */ /* Insert question in the table of questions */
DB_QueryINSERT ("can not create question", DB_QueryINSERT ("can not create question",
@ -2222,16 +2274,22 @@ void Gam_AddTstQuestionsToGame (void)
" VALUES" " VALUES"
" (%ld,%ld,%u)", " (%ld,%ld,%u)",
Game.GamCod,QstCod,MaxQstInd + 1); 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 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 *****/ /***** Show current game *****/
Gam_ShowOnlyOneGame (&Games,&Game, Gam_ShowOnlyOneGame (&Games,&Game,
@ -2313,23 +2371,21 @@ void Gam_RequestRemoveQst (void)
Gam_GetDataOfGameByCod (&Game); Gam_GetDataOfGameByCod (&Game);
/***** Check if game has matches *****/ /***** Check if game has matches *****/
if (Gam_CheckIfEditable (&Game)) 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
Lay_NoPermissionExit (); 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 *****/ /***** Show current game *****/
Gam_ShowOnlyOneGame (&Games,&Game, Gam_ShowOnlyOneGame (&Games,&Game,
true, // List game questions true, // List game questions
@ -2359,42 +2415,40 @@ void Gam_RemoveQst (void)
Gam_GetDataOfGameByCod (&Game); Gam_GetDataOfGameByCod (&Game);
/***** Check if game has matches *****/ /***** Check if game has matches *****/
if (Gam_CheckIfEditable (&Game)) 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
Lay_NoPermissionExit (); 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 *****/ /***** Show current game *****/
Gam_ShowOnlyOneGame (&Games,&Game, Gam_ShowOnlyOneGame (&Games,&Game,
true, // List game questions true, // List game questions
@ -2407,7 +2461,6 @@ void Gam_RemoveQst (void)
void Gam_MoveUpQst (void) void Gam_MoveUpQst (void)
{ {
extern const char *Txt_The_question_has_been_moved_up;
extern const char *Txt_Movement_not_allowed; extern const char *Txt_Movement_not_allowed;
struct Gam_Games Games; struct Gam_Games Games;
struct Gam_Game Game; struct Gam_Game Game;
@ -2426,30 +2479,25 @@ void Gam_MoveUpQst (void)
Gam_GetDataOfGameByCod (&Game); Gam_GetDataOfGameByCod (&Game);
/***** Check if game has matches *****/ /***** 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 *****/ /* Indexes of questions to be exchanged */
QstIndBottom = Gam_GetParamQstInd (); QstIndTop = Gam_GetPrevQuestionIndexInGame (Game.GamCod,QstIndBottom);
if (!QstIndTop)
Lay_ShowErrorAndExit ("Wrong index of question.");
/***** Move up question *****/ /* Exchange questions */
if (QstIndBottom > 1) Gam_ExchangeQuestions (Game.GamCod,QstIndTop,QstIndBottom);
{
/* 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);
} }
else else
Lay_NoPermissionExit (); Ale_ShowAlert (Ale_WARNING,Txt_Movement_not_allowed);
/***** Show current game *****/ /***** Show current game *****/
Gam_ShowOnlyOneGame (&Games,&Game, Gam_ShowOnlyOneGame (&Games,&Game,
@ -2463,7 +2511,6 @@ void Gam_MoveUpQst (void)
void Gam_MoveDownQst (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_Movement_not_allowed;
extern const char *Txt_This_game_has_no_questions; extern const char *Txt_This_game_has_no_questions;
struct Gam_Games Games; struct Gam_Games Games;
@ -2484,38 +2531,33 @@ void Gam_MoveDownQst (void)
Gam_GetDataOfGameByCod (&Game); Gam_GetDataOfGameByCod (&Game);
/***** Check if game has matches *****/ /***** 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 *****/ if (QstIndTop < MaxQstInd)
QstIndTop = Gam_GetParamQstInd ();
/***** Get maximum question index *****/
MaxQstInd = Gam_GetMaxQuestionIndexInGame (Game.GamCod);
/***** Move down question *****/
if (MaxQstInd)
{ {
if (QstIndTop < MaxQstInd) /* Indexes of questions to be exchanged */
{ QstIndBottom = Gam_GetNextQuestionIndexInGame (Game.GamCod,QstIndTop);
/* Indexes of questions to be exchanged */ if (!QstIndBottom)
QstIndBottom = Gam_GetNextQuestionIndexInGame (Game.GamCod,QstIndTop); Lay_ShowErrorAndExit ("Wrong index of question.");
if (!QstIndBottom)
Lay_ShowErrorAndExit ("Wrong index of question.");
/* Exchange questions */ /* Exchange questions */
Gam_ExchangeQuestions (Game.GamCod,QstIndTop,QstIndBottom); 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);
} }
else else
Ale_ShowAlert (Ale_WARNING,Txt_This_game_has_no_questions); Ale_ShowAlert (Ale_WARNING,Txt_Movement_not_allowed);
} }
else else
Lay_NoPermissionExit (); Ale_ShowAlert (Ale_WARNING,Txt_This_game_has_no_questions);
/***** Show current game *****/ /***** Show current game *****/
Gam_ShowOnlyOneGame (&Games,&Game, Gam_ShowOnlyOneGame (&Games,&Game,
@ -2547,25 +2589,36 @@ static void Gam_ExchangeQuestions (long GamCod,
Example: Example:
QstIndTop = 1; QstCodTop = 218 QstIndTop = 1; QstCodTop = 218
QstIndBottom = 2; QstCodBottom = 220 QstIndBottom = 2; QstCodBottom = 220
+--------+--------+ +--------+--------+ +--------+--------+ Step 1 Step 2 Step 3
| QstInd | QstCod | | QstInd | QstCod | | QstInd | QstCod | +--------+--------+ +--------+--------+ +--------+--------+ +--------+--------+
+--------+--------+ +--------+--------+ +--------+--------+ | QstInd | QstCod | | QstInd | QstCod | | QstInd | QstCod | | QstInd | QstCod |
| 1 | 218 | -----> | 2 | 218 | = | 1 | 220 | +--------+--------+ +--------+--------+ +--------+--------+ +--------+--------+
| 2 | 220 | | 1 | 220 | | 2 | 218 | | 1 | 218 |-->| -2 | 218 |-->| -2 | 218 |-->| 2 | 218 |
| 3 | 232 | | 3 | 232 | | 3 | 232 | | 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", 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", " WHERE GamCod=%ld AND QstCod=%ld",
QstIndBottom, QstIndBottom,
GamCod,QstCodTop); GamCod,QstCodTop);
/* Step 2: change bottom index to old top index */
DB_QueryUPDATE ("can not exchange indexes of questions", 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", " WHERE GamCod=%ld AND QstCod=%ld",
QstIndTop, QstIndTop,
GamCod,QstCodBottom); 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 *****/ /***** Unlock table *****/
Gbl.DB.LockedTables = false; // Set to false before the following unlock... Gbl.DB.LockedTables = false; // Set to false before the following unlock...

View File

@ -291,11 +291,53 @@ const char *Txt_A_message_has_been_sent_to_email_address_X_to_confirm_that_addre
" para confirmar esse endere&ccedil;o."; " para confirmar esse endere&ccedil;o.";
#endif #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&uuml;gt.";
#elif L==3 // en
"A question has been added.";
#elif L==4 // es
"Se ha a&ntilde;adido una pregunta.";
#elif L==5 // fr
"Une question a &eacute;t&eacute; ajout%eacute;e.";
#elif L==6 // gn
"Se ha a&ntilde;adido una pregunta."; // Okoteve traducción
#elif L==7 // it
"&Egrave; stata aggiunta una domanda.";
#elif L==8 // pl
"Pytanie zosta&lstrok;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&uuml;gt.";
#elif L==3 // en
"%u questions have been added.";
#elif L==4 // es
"Se han a&ntilde;adido %u preguntas.";
#elif L==5 // fr
"%u questions ont &eacute;t&eacute; ajout&eacute;es.";
#elif L==6 // gn
"Se han a&ntilde;adido %u preguntas."; // Okoteve traducción
#elif L==7 // it
"Sono state aggiunte %u domande.";
#elif L==8 // pl
"Dodano %u pyta&nacute;.";
#elif L==9 // pt
"%u perguntas foram adicionadas.";
#endif
const char *Txt_A_student_can_belong_to_several_groups = const char *Txt_A_student_can_belong_to_several_groups =
#if L==1 // ca #if L==1 // ca
"Un estudiant pot pert&agrave;nyer a diversos grups"; "Un estudiant pot pert&agrave;nyer a diversos grups";
#elif L==2 // de #elif L==2 // de
"Ein Student kann mehreren Gruppen angehören"; "Ein Student kann mehreren Gruppen angeh&ouml;ren";
#elif L==3 // en #elif L==3 // en
"A student can belong to several groups"; "A student can belong to several groups";
#elif L==4 // es #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&ecirc; prefere para ser removido/a da disciplina?"; " ou voc&ecirc; prefere para ser removido/a da disciplina?";
#endif #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 #if L==1 // ca
"Un usuari no pot tenir m&eacute;s de %u IDs (DNI/c&egrave;dulas)"; "Un usuari no pot tenir m&eacute;s de %u IDs (DNI/c&egrave;dulas)";
#elif L==2 // de #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."; "As propriedades do arquivo %s foram salvas.";
#endif #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 &eacute;t&eacute; d&eacute;plac&eacute;e vers le bas.";
#elif L==6 // gn
"La pregunta se ha movido hacia abajo."; // Okoteve traducción
#elif L==7 // it
"La questione &egrave; stata abbattuta.";
#elif L==8 // pl
"Pytanie zosta&lstrok;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 &eacute;t&eacute; d&eacute;plac&eacute;e vers le haut.";
#elif L==6 // gn
"La pregunta se ha movido hacia arriba."; // Okoteve traducción
#elif L==7 // it
"La questione &egrave; stata spostata.";
#elif L==8 // pl
"Pytanie zosta&lstrok;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 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 #if L==1 // ca
"El campo de ficha <strong>%s</strong> ya existe."; // Necessita traduccio "El campo de ficha <strong>%s</strong> ya existe."; // Necessita traduccio