diff --git a/swad_action.c b/swad_action.c index 0559657a2..52f079d30 100644 --- a/swad_action.c +++ b/swad_action.c @@ -507,6 +507,8 @@ Assessment: NEW. ActAddTstQstToGam Add selected test questions to game NEW. ActReqRemGamQst Request the removal of a question of a game NEW. ActRemGamQst Confirm the removal of a question of a game + NEW. ActUp_GamQst, Move up a question of a game + NEW. ActDwnGamQst, Move down a question of a game 361. ActSeeOneExaAnn Show one exam announcement 362. ActSeeDatExaAnn Show exam announcements of a given date @@ -1967,6 +1969,8 @@ struct Act_Actions Act_Actions[Act_NUM_ACTIONS] = /* ActAddTstQstToGam */{1667,-1,TabUnk,ActSeeAllGam ,0x3E0,0x3C0,0x3C0,0x3C0,0x3C0,0x3C0,0x3C0,Act_CONT_NORM,Act_THIS_WINDOW,NULL ,Gam_AddTstQuestionsToGame ,NULL}, /* ActReqRemGamQst */{1664,-1,TabUnk,ActSeeAllGam ,0x3E0,0x3C0,0x3C0,0x3C0,0x3C0,0x3C0,0x3C0,Act_CONT_NORM,Act_THIS_WINDOW,NULL ,Gam_RequestRemoveQst ,NULL}, /* ActRemGamQst */{1665,-1,TabUnk,ActSeeAllGam ,0x3E0,0x3C0,0x3C0,0x3C0,0x3C0,0x3C0,0x3C0,Act_CONT_NORM,Act_THIS_WINDOW,NULL ,Gam_RemoveQst ,NULL}, + /* ActUp_GamQst */{1668,-1,TabUnk,ActSeeAllGam ,0x3E0,0x3C0,0x3C0,0x3C0,0x3C0,0x3C0,0x3C0,Act_CONT_NORM,Act_THIS_WINDOW,NULL ,Gam_MoveUpQst ,NULL}, + /* ActDwnGamQst */{1669,-1,TabUnk,ActSeeAllGam ,0x3E0,0x3C0,0x3C0,0x3C0,0x3C0,0x3C0,0x3C0,Act_CONT_NORM,Act_THIS_WINDOW,NULL ,Gam_MoveDownQst ,NULL}, /* ActSeeOneSvy */{ 982,-1,TabUnk,ActSeeAllSvy ,0x3F8,0x3C0,0x3C0,0x3C0,0x3C0,0x3C0,0x3C0,Act_CONT_NORM,Act_THIS_WINDOW,NULL ,Svy_SeeOneSurvey ,NULL}, /* ActAnsSvy */{ 983,-1,TabUnk,ActSeeAllSvy ,0x3F8,0x3C0,0x3C0,0x3C0,0x3C0,0x3C0,0x3C0,Act_CONT_NORM,Act_THIS_WINDOW,NULL ,Svy_ReceiveSurveyAnswers ,NULL}, @@ -4711,6 +4715,8 @@ Act_Action_t Act_FromActCodToAction[1 + Act_MAX_ACTION_COD] = // Do not reuse un ActRemGamQst, // #1665 ActGamLstTstQst, // #1666 ActAddTstQstToGam, // #1667 + ActUp_GamQst, // #1668 + ActDwnGamQst, // #1669 }; /*****************************************************************************/ diff --git a/swad_action.h b/swad_action.h index d50509578..84a319319 100644 --- a/swad_action.h +++ b/swad_action.h @@ -57,9 +57,9 @@ typedef enum typedef signed int Act_Action_t; // Must be a signed type, because -1 is used to indicate obsolete action -#define Act_NUM_ACTIONS (1 + 9 + 43 + 17 + 47 + 33 + 24 + 115 + 90 + 416 + 165 + 172 + 42 + 14 + 97) +#define Act_NUM_ACTIONS (1 + 9 + 43 + 17 + 47 + 33 + 24 + 115 + 92 + 416 + 165 + 172 + 42 + 14 + 97) -#define Act_MAX_ACTION_COD 1667 +#define Act_MAX_ACTION_COD 1669 #define Act_MAX_OPTIONS_IN_MENU_PER_TAB 12 @@ -502,33 +502,35 @@ typedef signed int Act_Action_t; // Must be a signed type, because -1 is used to #define ActAddTstQstToGam (ActChgCalCrs1stDay + 63) #define ActReqRemGamQst (ActChgCalCrs1stDay + 64) #define ActRemGamQst (ActChgCalCrs1stDay + 65) +#define ActUp_GamQst (ActChgCalCrs1stDay + 66) +#define ActDwnGamQst (ActChgCalCrs1stDay + 67) -#define ActSeeOneSvy (ActChgCalCrs1stDay + 66) -#define ActAnsSvy (ActChgCalCrs1stDay + 67) -#define ActFrmNewSvy (ActChgCalCrs1stDay + 68) -#define ActEdiOneSvy (ActChgCalCrs1stDay + 69) -#define ActNewSvy (ActChgCalCrs1stDay + 70) -#define ActChgSvy (ActChgCalCrs1stDay + 71) -#define ActReqRemSvy (ActChgCalCrs1stDay + 72) -#define ActRemSvy (ActChgCalCrs1stDay + 73) -#define ActReqRstSvy (ActChgCalCrs1stDay + 74) -#define ActRstSvy (ActChgCalCrs1stDay + 75) -#define ActHidSvy (ActChgCalCrs1stDay + 76) -#define ActShoSvy (ActChgCalCrs1stDay + 77) -#define ActEdiOneSvyQst (ActChgCalCrs1stDay + 78) -#define ActRcvSvyQst (ActChgCalCrs1stDay + 79) -#define ActReqRemSvyQst (ActChgCalCrs1stDay + 80) -#define ActRemSvyQst (ActChgCalCrs1stDay + 81) +#define ActSeeOneSvy (ActChgCalCrs1stDay + 68) +#define ActAnsSvy (ActChgCalCrs1stDay + 69) +#define ActFrmNewSvy (ActChgCalCrs1stDay + 70) +#define ActEdiOneSvy (ActChgCalCrs1stDay + 71) +#define ActNewSvy (ActChgCalCrs1stDay + 72) +#define ActChgSvy (ActChgCalCrs1stDay + 73) +#define ActReqRemSvy (ActChgCalCrs1stDay + 74) +#define ActRemSvy (ActChgCalCrs1stDay + 75) +#define ActReqRstSvy (ActChgCalCrs1stDay + 76) +#define ActRstSvy (ActChgCalCrs1stDay + 77) +#define ActHidSvy (ActChgCalCrs1stDay + 78) +#define ActShoSvy (ActChgCalCrs1stDay + 79) +#define ActEdiOneSvyQst (ActChgCalCrs1stDay + 80) +#define ActRcvSvyQst (ActChgCalCrs1stDay + 81) +#define ActReqRemSvyQst (ActChgCalCrs1stDay + 82) +#define ActRemSvyQst (ActChgCalCrs1stDay + 83) -#define ActSeeOneExaAnn (ActChgCalCrs1stDay + 82) -#define ActSeeDatExaAnn (ActChgCalCrs1stDay + 83) -#define ActEdiExaAnn (ActChgCalCrs1stDay + 84) -#define ActRcvExaAnn (ActChgCalCrs1stDay + 85) -#define ActPrnExaAnn (ActChgCalCrs1stDay + 86) -#define ActReqRemExaAnn (ActChgCalCrs1stDay + 87) -#define ActRemExaAnn (ActChgCalCrs1stDay + 88) -#define ActHidExaAnn (ActChgCalCrs1stDay + 89) -#define ActShoExaAnn (ActChgCalCrs1stDay + 90) +#define ActSeeOneExaAnn (ActChgCalCrs1stDay + 84) +#define ActSeeDatExaAnn (ActChgCalCrs1stDay + 85) +#define ActEdiExaAnn (ActChgCalCrs1stDay + 86) +#define ActRcvExaAnn (ActChgCalCrs1stDay + 87) +#define ActPrnExaAnn (ActChgCalCrs1stDay + 88) +#define ActReqRemExaAnn (ActChgCalCrs1stDay + 89) +#define ActRemExaAnn (ActChgCalCrs1stDay + 90) +#define ActHidExaAnn (ActChgCalCrs1stDay + 91) +#define ActShoExaAnn (ActChgCalCrs1stDay + 92) /*****************************************************************************/ /******************************** Files tab **********************************/ diff --git a/swad_changelog.h b/swad_changelog.h index 90fc3f0d9..cd191e629 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -234,17 +234,26 @@ // TODO: "Solicitar inscripción" como superusuario: "Usted no tiene permiso para realizar esta acción" +// TODO: "Administrar varios profesores no editores" -> debería poder hacerlo un profesor (Perico) + /*****************************************************************************/ /****************************** Public constants *****************************/ /*****************************************************************************/ -#define Log_PLATFORM_VERSION "SWAD 16.252.3 (2017-09-11)" +#define Log_PLATFORM_VERSION "SWAD 16.253 (2017-09-11)" #define CSS_FILE "swad16.252.2.css" #define JS_FILE "swad16.206.3.js" // Number of lines (includes comments but not blank lines) has been got with the following command: // nl swad*.c swad*.h css/swad*.css py/swad*.py js/swad*.js soap/swad*?.h sql/swad*.sql | tail -1 /* + Version 16.253: Sep 11, 2017 Actions to move up and down questions in a game. (227070 lines) + 4 changes necessary in database: +UPDATE actions SET Txt='Subir posición item teoría' WHERE ActCod='221' AND Language='es'; +UPDATE actions SET Txt='Bajar posición item teoría' WHERE ActCod='220' AND Language='es'; +INSERT INTO actions (ActCod,Language,Obsolete,Txt) VALUES ('1668','es','N','Subir posición pregunta juego'); +INSERT INTO actions (ActCod,Language,Obsolete,Txt) VALUES ('1669','es','N','Bajar posición pregunta juego'); + Version 16.252.3: Sep 11, 2017 HTML optimization in icons. (226822 lines) Version 16.252.2: Sep 10, 2017 Code refactoring in edition of syllabus. (226819 lines) Version 16.252.1: Sep 09, 2017 Icons to move up and down questions in a game. (226864 lines) diff --git a/swad_game.c b/swad_game.c index 00f686210..b2df4430f 100644 --- a/swad_game.c +++ b/swad_game.c @@ -122,8 +122,11 @@ static void Gam_PutParamQstCod (long QstCod); static long Gam_GetParamQstCod (void); static void Gam_RemAnswersOfAQuestion (long QstCod); -static unsigned Gam_GetQstIndFromQstCod (long QstCod); -static unsigned Gam_GetNextQuestionIndexInGame (long GamCod); +static unsigned Gam_GetQstIndFromQstCod (long GamCod,long QstCod); +static long Gam_GetQstCodFromQstInd (long GamCod,unsigned QstInd); +static int Gam_GetMaxQuestionIndexInGame (long GamCod); +static unsigned Gam_GetNextQuestionIndexInGame (long GamCod,unsigned QstInd); +static unsigned Gam_GetPrevQuestionIndexInGame (long GamCod,unsigned QstInd); static void Gam_ListGameQuestions (struct Game *Game); static void Gam_ListOneOrMoreQuestionsForEdition (struct Game *Game, unsigned NumQsts, @@ -141,6 +144,9 @@ static void Gam_DrawBarNumUsrs (unsigned NumUsrs,unsigned MaxUsrs); // static void Gam_PutIconToRemoveOneQst (void); static void Gam_PutParamsOneQst (void); +static void Gam_ExchangeQuestions (long GamCod, + unsigned QstIndTop,unsigned QstIndBottom); + static void Gam_ReceiveAndStoreUserAnswersToAGame (long GamCod); static void Gam_IncreaseAnswerInDB (long QstCod,unsigned AnsInd); static void Gam_RegisterIHaveAnsweredGame (long GamCod); @@ -944,7 +950,7 @@ void Gam_GetListGames (void) { /* Get next game code */ row = mysql_fetch_row (mysql_res); - if ((Gbl.Games.LstGamCods[NumGame] = Str_ConvertStrCodToLongCod (row[0])) < 0) + if ((Gbl.Games.LstGamCods[NumGame] = Str_ConvertStrCodToLongCod (row[0])) <= 0) Lay_ShowErrorAndExit ("Error: wrong game code."); } } @@ -2571,27 +2577,26 @@ static void Gam_RemAnswersOfAQuestion (long QstCod) /******************** Get next question index in a game **********************/ /*****************************************************************************/ -static unsigned Gam_GetQstIndFromQstCod (long QstCod) +static unsigned Gam_GetQstIndFromQstCod (long GamCod,long QstCod) { - char Query[128]; + char Query[256]; MYSQL_RES *mysql_res; MYSQL_ROW row; - unsigned long NumRows; unsigned QstInd = 0; /***** Get number of games with a field value from database *****/ - sprintf (Query,"SELECT QstInd FROM gam_questions WHERE QstCod=%ld", - QstCod); - NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get question index"); + sprintf (Query,"SELECT QstInd FROM gam_questions" + " WHERE GamCod=%ld AND QstCod=%ld", + GamCod,QstCod); + if (!DB_QuerySELECT (Query,&mysql_res,"can not get question index")) + { + Ale_ShowAlert (Ale_INFO,Query); + Lay_ShowErrorAndExit ("Error when getting question index."); + } - /***** Get number of users *****/ - if (NumRows) - { - row = mysql_fetch_row (mysql_res); - if (sscanf (row[0],"%u",&QstInd) != 1) - Lay_ShowErrorAndExit ("Error when getting question index."); - } - else + /***** Get question index (row[0]) *****/ + row = mysql_fetch_row (mysql_res); + if (sscanf (row[0],"%u",&QstInd) != 1) Lay_ShowErrorAndExit ("Error when getting question index."); /***** Free structure that stores the query result *****/ @@ -2601,15 +2606,46 @@ static unsigned Gam_GetQstIndFromQstCod (long QstCod) } /*****************************************************************************/ -/******************* Get next question index in a game *********************/ +/************ Get question code given game and index of question *************/ /*****************************************************************************/ -static unsigned Gam_GetNextQuestionIndexInGame (long GamCod) +static long Gam_GetQstCodFromQstInd (long GamCod,unsigned QstInd) + { + char Query[256]; + MYSQL_RES *mysql_res; + MYSQL_ROW row; + long QstCod; + + /***** Get question code of thw question to be moved up *****/ + sprintf (Query,"SELECT QstCod FROM gam_questions" + " WHERE GamCod=%ld AND QstInd=%u", + GamCod,QstInd); + if (!DB_QuerySELECT (Query,&mysql_res,"can not get question code")) + Lay_ShowErrorAndExit ("Error: wrong question code."); + + /***** Get question code (row[0]) *****/ + row = mysql_fetch_row (mysql_res); + if ((QstCod = Str_ConvertStrCodToLongCod (row[0])) <= 0) + Lay_ShowErrorAndExit ("Error: wrong question code."); + + /***** Free structure that stores the query result *****/ + DB_FreeMySQLResult (&mysql_res); + + return QstCod; + } + +/*****************************************************************************/ +/****************** Get maximum question index in a game *********************/ +/*****************************************************************************/ +// Question index can be 0, 1, 2,... +// Return -1 if no questions + +static int Gam_GetMaxQuestionIndexInGame (long GamCod) { char Query[128]; MYSQL_RES *mysql_res; MYSQL_ROW row; - unsigned QstInd = 0; + int QstInd = -1; /***** Get maximum question index in a game from database *****/ sprintf (Query,"SELECT MAX(QstInd) FROM gam_questions WHERE GamCod=%ld", @@ -2617,11 +2653,8 @@ static unsigned Gam_GetNextQuestionIndexInGame (long GamCod) DB_QuerySELECT (Query,&mysql_res,"can not get last question index"); row = mysql_fetch_row (mysql_res); if (row[0]) // There are questions - { - if (sscanf (row[0],"%u",&QstInd) != 1) + if (sscanf (row[0],"%d",&QstInd) != 1) Lay_ShowErrorAndExit ("Error when getting last question index."); - QstInd++; - } /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); @@ -2629,6 +2662,68 @@ static unsigned Gam_GetNextQuestionIndexInGame (long GamCod) return QstInd; } +/*****************************************************************************/ +/*********** Get previous question index to a given index in a game **********/ +/*****************************************************************************/ + +static unsigned Gam_GetPrevQuestionIndexInGame (long GamCod,unsigned QstInd) + { + char Query[256]; + MYSQL_RES *mysql_res; + MYSQL_ROW row; + unsigned PrevQstInd; + + /***** Get previous question index in a game from database *****/ + // Although indexes are always continuous... + // ...this implementation works even with non continuous indexes + sprintf (Query,"SELECT MAX(QstInd) FROM gam_questions" + " WHERE GamCod=%ld AND QstInd<%u", + GamCod,QstInd); + if (!DB_QuerySELECT (Query,&mysql_res,"can not get previous question index")) + Lay_ShowErrorAndExit ("Error: previous question index not found."); + + /***** Get previous question index (row[0]) *****/ + row = mysql_fetch_row (mysql_res); + if (sscanf (row[0],"%u",&PrevQstInd) != 1) + Lay_ShowErrorAndExit ("Error when getting previous question index."); + + /***** Free structure that stores the query result *****/ + DB_FreeMySQLResult (&mysql_res); + + return PrevQstInd; + } + +/*****************************************************************************/ +/************* Get next question index to a given index in a game ************/ +/*****************************************************************************/ + +static unsigned Gam_GetNextQuestionIndexInGame (long GamCod,unsigned QstInd) + { + char Query[256]; + MYSQL_RES *mysql_res; + MYSQL_ROW row; + unsigned NextQstInd; + + /***** Get next question index in a game from database *****/ + // Although indexes are always continuous... + // ...this implementation works even with non continuous indexes + sprintf (Query,"SELECT MIN(QstInd) FROM gam_questions" + " WHERE GamCod=%ld AND QstInd>%u", + GamCod,QstInd); + if (!DB_QuerySELECT (Query,&mysql_res,"can not get next question index")) + Lay_ShowErrorAndExit ("Error: next question index not found."); + + /***** Get next question index (row[0]) *****/ + row = mysql_fetch_row (mysql_res); + if (sscanf (row[0],"%u",&NextQstInd) != 1) + Lay_ShowErrorAndExit ("Error when getting next question index."); + + /***** Free structure that stores the query result *****/ + DB_FreeMySQLResult (&mysql_res); + + return NextQstInd; + } + /*****************************************************************************/ /************************ List the questions of a game ***********************/ /*****************************************************************************/ @@ -2780,11 +2875,12 @@ static void Gam_ListOneOrMoreQuestionsForEdition (struct Game *Game, Tst_QstConstructor (); /* row[0] holds the code of the question */ - if ((QstCod = Str_ConvertStrCodToLongCod (row[0])) < 0) + if ((QstCod = Str_ConvertStrCodToLongCod (row[0])) <= 0) Lay_ShowErrorAndExit ("Wrong code of question."); - Gbl.Test.QstCod = QstCod; /***** Icons *****/ + Gbl.Games.CurrentGamCod = Game->GamCod; + Gbl.Games.CurrentQstCod = QstCod; fprintf (Gbl.F.Out,"