diff --git a/sql/swad.sql b/sql/swad.sql index 37f04cf97..1580e0140 100644 --- a/sql/swad.sql +++ b/sql/swad.sql @@ -613,14 +613,14 @@ CREATE TABLE IF NOT EXISTS games ( UNIQUE INDEX(GamCod), INDEX(CrsCod)); -- --- Table gam_answers: stores the answers to the games +-- Table gam_answers: stores the answers to the matches -- CREATE TABLE IF NOT EXISTS gam_answers ( GamCod INT NOT NULL, - QstCod INT NOT NULL, + QstInd INT NOT NULL, AnsInd TINYINT NOT NULL, NumUsrs INT NOT NULL DEFAULT 0, - UNIQUE INDEX(GamCod,QstCod,AnsInd)); + UNIQUE INDEX(GamCod,QstInd,AnsInd)); -- -- Table gam_grp: stores the groups associated to each match in a game -- diff --git a/swad_action.c b/swad_action.c index 5bdc4fc0f..e18f09324 100644 --- a/swad_action.c +++ b/swad_action.c @@ -608,10 +608,11 @@ Assessment: 455. ActFrmNewMch Put form to create a new match (by a teacher) NEW. ActReqRemMch Request the removal of a match (by a teacher) NEW. ActRemMch Confirm the removal of a match (by a teacher) - 456. ActGamTch1stQst Show first question when playing a game (by a teacher) + 456. ActNewMch Create a new match showing first question in a new browser tab (by a teacher) + NEW. ActResMch Resume an unfinished match showing current question in a new browser tab (by a teacher) 457. ActGamTchNxtQst Show next question when playing a game (by a teacher) 458. ActGamTchAns Show answers of current question when playing a game (by a teacher) - NEW. ActGamTchEnd End playing a game (by a teacher) + NEW. ActEndMch Finish a match (by a teacher) NEW. ActPlyMchStd Play a game (by a student) NEW. ActGamStdCurQst Show current question when playing a game (by a student) @@ -2146,10 +2147,11 @@ struct Act_Actions Act_Actions[Act_NUM_ACTIONS] = /* ActFrmNewMch */{1670,-1,TabUnk,ActSeeAllGam ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Gam_RequestNewMatch ,NULL}, /* ActReqRemMch */{1783,-1,TabUnk,ActSeeAllGam ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Gam_RequestRemoveMatch ,NULL}, /* ActRemMch */{1784,-1,TabUnk,ActSeeAllGam ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Gam_RemoveMatch ,NULL}, - /* ActGamTch1stQst */{1671,-1,TabUnk,ActSeeAllGam ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_NEW_TAB,NULL ,Gam_CreateAndStartNewMatch ,NULL}, + /* ActNewMch */{1671,-1,TabUnk,ActSeeAllGam ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_NEW_TAB,NULL ,Gam_CreateAndStartNewMatch ,NULL}, + /* ActResMch */{1785,-1,TabUnk,ActSeeAllGam ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_NEW_TAB,NULL ,Gam_ResumeUnfinishedMatch ,NULL}, /* ActGamTchNxtQst */{1672,-1,TabUnk,ActSeeAllGam ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_2ND_TAB,NULL ,Gam_MatchTchNextQuestion ,NULL}, /* ActGamTchAns */{1673,-1,TabUnk,ActSeeAllGam ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_2ND_TAB,NULL ,Gam_MatchTchShowAnswers ,NULL}, - /* ActGamTchEnd */{1781,-1,TabUnk,ActSeeAllGam ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_2ND_TAB,NULL ,Gam_MatchTchEnd ,NULL}, + /* ActEndMch */{1781,-1,TabUnk,ActSeeAllGam ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_2ND_TAB,NULL ,Gam_MatchTchEnd ,NULL}, /* ActPlyMchStd */{1779,-1,TabUnk,ActSeeAllGam ,0x008, 0, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Gam_PlayMatchStd ,NULL}, /* ActGamStdCurQst */{1780,-1,TabUnk,ActSeeAllGam ,0x008, 0, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_NEW_TAB,Gam_GetMatchBeingPlayed ,Gam_ShowNewMatchToMeAsStd ,NULL}, @@ -4876,7 +4878,7 @@ Act_Action_t Act_FromActCodToAction[1 + Act_MAX_ACTION_COD] = // Do not reuse un ActUp_GamQst, // #1668 ActDwnGamQst, // #1669 ActFrmNewMch, // #1670 - ActGamTch1stQst, // #1671 + ActNewMch, // #1671 ActGamTchNxtQst, // #1672 ActGamTchAns, // #1673 ActSeePrj, // #1674 @@ -4986,10 +4988,11 @@ Act_Action_t Act_FromActCodToAction[1 + Act_MAX_ACTION_COD] = // Do not reuse un ActUnlAllPrj, // #1778 ActPlyMchStd, // #1779 ActGamStdCurQst, // #1780 - ActGamTchEnd, // #1781 + ActEndMch, // #1781 ActRefGamStd, // #1782 ActReqRemMch, // #1783 ActRemMch, // #1784 + ActResMch, // #1785 }; /*****************************************************************************/ diff --git a/swad_action.h b/swad_action.h index e85831605..72ee58007 100644 --- a/swad_action.h +++ b/swad_action.h @@ -64,9 +64,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 + 4 + 64 + 38 + 12 + 42 + 36 + 19 + 110 + 169 + 437 + 176 + 169 + 16 + 67) +#define Act_NUM_ACTIONS (1 + 4 + 64 + 38 + 12 + 42 + 36 + 19 + 110 + 170 + 437 + 176 + 169 + 16 + 67) -#define Act_MAX_ACTION_COD 1784 +#define Act_MAX_ACTION_COD 1785 #define Act_MAX_OPTIONS_IN_MENU_PER_TAB 13 @@ -610,58 +610,59 @@ typedef signed int Act_Action_t; // Must be a signed type, because -1 is used to #define ActFrmNewMch (ActChgCrsTT1stDay + 117) #define ActReqRemMch (ActChgCrsTT1stDay + 118) #define ActRemMch (ActChgCrsTT1stDay + 119) -#define ActGamTch1stQst (ActChgCrsTT1stDay + 120) -#define ActGamTchNxtQst (ActChgCrsTT1stDay + 121) -#define ActGamTchAns (ActChgCrsTT1stDay + 122) -#define ActGamTchEnd (ActChgCrsTT1stDay + 123) -#define ActPlyMchStd (ActChgCrsTT1stDay + 124) -#define ActGamStdCurQst (ActChgCrsTT1stDay + 125) -#define ActRefGamStd (ActChgCrsTT1stDay + 126) -#define ActAnsGam (ActChgCrsTT1stDay + 127) -#define ActFrmNewGam (ActChgCrsTT1stDay + 128) -#define ActEdiOneGam (ActChgCrsTT1stDay + 129) -#define ActNewGam (ActChgCrsTT1stDay + 130) -#define ActChgGam (ActChgCrsTT1stDay + 131) -#define ActReqRemGam (ActChgCrsTT1stDay + 132) -#define ActRemGam (ActChgCrsTT1stDay + 133) -#define ActReqRstGam (ActChgCrsTT1stDay + 134) -#define ActRstGam (ActChgCrsTT1stDay + 135) -#define ActHidGam (ActChgCrsTT1stDay + 136) -#define ActShoGam (ActChgCrsTT1stDay + 137) -#define ActAddOneGamQst (ActChgCrsTT1stDay + 138) -#define ActGamLstTstQst (ActChgCrsTT1stDay + 139) -#define ActAddTstQstToGam (ActChgCrsTT1stDay + 140) -#define ActReqRemGamQst (ActChgCrsTT1stDay + 141) -#define ActRemGamQst (ActChgCrsTT1stDay + 142) -#define ActUp_GamQst (ActChgCrsTT1stDay + 143) -#define ActDwnGamQst (ActChgCrsTT1stDay + 144) +#define ActNewMch (ActChgCrsTT1stDay + 120) +#define ActResMch (ActChgCrsTT1stDay + 121) +#define ActGamTchNxtQst (ActChgCrsTT1stDay + 122) +#define ActGamTchAns (ActChgCrsTT1stDay + 123) +#define ActEndMch (ActChgCrsTT1stDay + 124) +#define ActPlyMchStd (ActChgCrsTT1stDay + 125) +#define ActGamStdCurQst (ActChgCrsTT1stDay + 126) +#define ActRefGamStd (ActChgCrsTT1stDay + 127) +#define ActAnsGam (ActChgCrsTT1stDay + 128) +#define ActFrmNewGam (ActChgCrsTT1stDay + 129) +#define ActEdiOneGam (ActChgCrsTT1stDay + 130) +#define ActNewGam (ActChgCrsTT1stDay + 131) +#define ActChgGam (ActChgCrsTT1stDay + 132) +#define ActReqRemGam (ActChgCrsTT1stDay + 133) +#define ActRemGam (ActChgCrsTT1stDay + 134) +#define ActReqRstGam (ActChgCrsTT1stDay + 135) +#define ActRstGam (ActChgCrsTT1stDay + 136) +#define ActHidGam (ActChgCrsTT1stDay + 137) +#define ActShoGam (ActChgCrsTT1stDay + 138) +#define ActAddOneGamQst (ActChgCrsTT1stDay + 139) +#define ActGamLstTstQst (ActChgCrsTT1stDay + 140) +#define ActAddTstQstToGam (ActChgCrsTT1stDay + 141) +#define ActReqRemGamQst (ActChgCrsTT1stDay + 142) +#define ActRemGamQst (ActChgCrsTT1stDay + 143) +#define ActUp_GamQst (ActChgCrsTT1stDay + 144) +#define ActDwnGamQst (ActChgCrsTT1stDay + 145) -#define ActSeeSvy (ActChgCrsTT1stDay + 145) -#define ActAnsSvy (ActChgCrsTT1stDay + 146) -#define ActFrmNewSvy (ActChgCrsTT1stDay + 147) -#define ActEdiOneSvy (ActChgCrsTT1stDay + 148) -#define ActNewSvy (ActChgCrsTT1stDay + 149) -#define ActChgSvy (ActChgCrsTT1stDay + 150) -#define ActReqRemSvy (ActChgCrsTT1stDay + 151) -#define ActRemSvy (ActChgCrsTT1stDay + 152) -#define ActReqRstSvy (ActChgCrsTT1stDay + 153) -#define ActRstSvy (ActChgCrsTT1stDay + 154) -#define ActHidSvy (ActChgCrsTT1stDay + 155) -#define ActShoSvy (ActChgCrsTT1stDay + 156) -#define ActEdiOneSvyQst (ActChgCrsTT1stDay + 157) -#define ActRcvSvyQst (ActChgCrsTT1stDay + 158) -#define ActReqRemSvyQst (ActChgCrsTT1stDay + 159) -#define ActRemSvyQst (ActChgCrsTT1stDay + 160) +#define ActSeeSvy (ActChgCrsTT1stDay + 146) +#define ActAnsSvy (ActChgCrsTT1stDay + 147) +#define ActFrmNewSvy (ActChgCrsTT1stDay + 148) +#define ActEdiOneSvy (ActChgCrsTT1stDay + 149) +#define ActNewSvy (ActChgCrsTT1stDay + 150) +#define ActChgSvy (ActChgCrsTT1stDay + 151) +#define ActReqRemSvy (ActChgCrsTT1stDay + 152) +#define ActRemSvy (ActChgCrsTT1stDay + 153) +#define ActReqRstSvy (ActChgCrsTT1stDay + 154) +#define ActRstSvy (ActChgCrsTT1stDay + 155) +#define ActHidSvy (ActChgCrsTT1stDay + 156) +#define ActShoSvy (ActChgCrsTT1stDay + 157) +#define ActEdiOneSvyQst (ActChgCrsTT1stDay + 158) +#define ActRcvSvyQst (ActChgCrsTT1stDay + 159) +#define ActReqRemSvyQst (ActChgCrsTT1stDay + 160) +#define ActRemSvyQst (ActChgCrsTT1stDay + 161) -#define ActSeeOneExaAnn (ActChgCrsTT1stDay + 161) -#define ActSeeDatExaAnn (ActChgCrsTT1stDay + 162) -#define ActEdiExaAnn (ActChgCrsTT1stDay + 163) -#define ActRcvExaAnn (ActChgCrsTT1stDay + 164) -#define ActPrnExaAnn (ActChgCrsTT1stDay + 165) -#define ActReqRemExaAnn (ActChgCrsTT1stDay + 166) -#define ActRemExaAnn (ActChgCrsTT1stDay + 167) -#define ActHidExaAnn (ActChgCrsTT1stDay + 168) -#define ActShoExaAnn (ActChgCrsTT1stDay + 169) +#define ActSeeOneExaAnn (ActChgCrsTT1stDay + 162) +#define ActSeeDatExaAnn (ActChgCrsTT1stDay + 163) +#define ActEdiExaAnn (ActChgCrsTT1stDay + 164) +#define ActRcvExaAnn (ActChgCrsTT1stDay + 165) +#define ActPrnExaAnn (ActChgCrsTT1stDay + 166) +#define ActReqRemExaAnn (ActChgCrsTT1stDay + 167) +#define ActRemExaAnn (ActChgCrsTT1stDay + 168) +#define ActHidExaAnn (ActChgCrsTT1stDay + 169) +#define ActShoExaAnn (ActChgCrsTT1stDay + 170) /*****************************************************************************/ /******************************** Files tab **********************************/ diff --git a/swad_changelog.h b/swad_changelog.h index 3bd0cc04a..01680a2c7 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -432,6 +432,8 @@ Lo de mutear anuncios, en principio prefiero hacer una opci // TODO: En Actividades, en Juegos, en Encuestas, en Asistencia poner filtros de Pasados (rojo), Actuales (verde), Futuros (azul). // Pensar si en Agenda se puede poner igual. +// TODO: Cambiar QstInd al rango 1,2,3... (código especial 0 en lugar de -1) en swad_survey + /*****************************************************************************/ /****************************** Public constants *****************************/ /*****************************************************************************/ @@ -451,10 +453,31 @@ En OpenSWAD: ps2pdf source.ps destination.pdf */ -#define Log_PLATFORM_VERSION "SWAD 18.125 (2019-05-29)" +#define Log_PLATFORM_VERSION "SWAD 18.126.1 (2019-05-29)" #define CSS_FILE "swad18.123.css" #define JS_FILE "swad18.123.js" /* + Version 18.126.1: May 30, 2019 New option to resume an unfinished match. (243415 lines) + 11 changes necessary in database: +UPDATE actions SET Txt='Preparar partida (como profesor)' WHERE ActCod='1670' AND Language='es'; +UPDATE actions SET Txt='Comenzar partida (como profesor)' WHERE ActCod='1671' AND Language='es'; +UPDATE actions SET Txt='Mostrar siguiente pregunta en partida (como profesor)' WHERE ActCod='1672' AND Language='es'; +UPDATE actions SET Txt='Mostrar respuestas de pregunta en partida (como profesor)' WHERE ActCod='1673' AND Language='es'; +UPDATE actions SET Txt='Prepararse a jugar (como estudiante)' WHERE ActCod='1779' AND Language='es'; +UPDATE actions SET Txt='Unirse a partida (como estudiante)' WHERE ActCod='1780' AND Language='es'; +UPDATE actions SET Txt='Finalizar partida (como profesor)' WHERE ActCod='1781' AND Language='es'; +INSERT INTO actions (ActCod,Language,Obsolete,Txt) VALUES ('1782','es','N','Refrescar partida (como estudiante)'); +INSERT INTO actions (ActCod,Language,Obsolete,Txt) VALUES ('1783','es','N','Solicitar eliminar partida (como profesor)'); +INSERT INTO actions (ActCod,Language,Obsolete,Txt) VALUES ('1784','es','N','Eliminar partida (como profesor)'); +INSERT INTO actions (ActCod,Language,Obsolete,Txt) VALUES ('1785','es','N','Reanudar partida (como profesor)'); + + Version 18.126: May 30, 2019 Question index range changes from 0,1,2... to 1,2,3... (? lines) + 2 changes necessary in database: +UPDATE gam_questions SET QstInd=QstInd+1; +UPDATE gam_matches SET QstInd=QstInd+1; +DROP TABLE gam_answers; +CREATE TABLE IF NOT EXISTS gam_answers (GamCod INT NOT NULL,QstInd INT NOT NULL,AnsInd TINYINT NOT NULL,NumUsrs INT NOT NULL DEFAULT 0,UNIQUE INDEX(GamCod,QstInd,AnsInd)); + Version 18.125: May 29, 2019 Unification of tables of matches (saved and current) into one table. (243371 lines) 2 changes necessary in database: DROP TABLE gam_matches; diff --git a/swad_database.c b/swad_database.c index 503aa02de..990666e4c 100644 --- a/swad_database.c +++ b/swad_database.c @@ -1341,18 +1341,18 @@ mysql> DESCRIBE gam_answers; | Field | Type | Null | Key | Default | Extra | +---------+------------+------+-----+---------+-------+ | GamCod | int(11) | NO | PRI | NULL | | -| QstCod | int(11) | NO | PRI | NULL | | +| QstInd | int(11) | NO | PRI | NULL | | | AnsInd | tinyint(4) | NO | PRI | NULL | | | NumUsrs | int(11) | NO | | 0 | | +---------+------------+------+-----+---------+-------+ -4 rows in set (0,00 sec) +4 rows in set (0.00 sec) */ DB_CreateTable ("CREATE TABLE IF NOT EXISTS gam_answers (" "GamCod INT NOT NULL," - "QstCod INT NOT NULL," + "QstInd INT NOT NULL," "AnsInd TINYINT NOT NULL," "NumUsrs INT NOT NULL DEFAULT 0," - "UNIQUE INDEX(GamCod,QstCod,AnsInd))"); + "UNIQUE INDEX(GamCod,QstInd,AnsInd))"); /***** Table gam_grp *****/ /* diff --git a/swad_game.c b/swad_game.c index 42a567437..0464192c1 100644 --- a/swad_game.c +++ b/swad_game.c @@ -87,7 +87,7 @@ struct Match char Title[Gam_MAX_BYTES_TITLE + 1]; struct { - int QstInd; + unsigned QstInd; // 0 means that the game has not started. First question has index 0. long QstCod; time_t QstStartTimeUTC; bool ShowAnswers; @@ -100,8 +100,8 @@ struct Match /*****************************************************************************/ long Gam_CurrentGamCod = -1L; // Used as parameter in contextual links -long Gam_CurrentQstCod = -1L; // Used as parameter in contextual links long Gam_CurrentMchCod = -1L; // Used as parameter in contextual links +unsigned Gam_CurrentQstInd = 0; // Used as parameter in contextual links /*****************************************************************************/ /***************************** Private prototypes ****************************/ @@ -139,17 +139,15 @@ static void Gam_GetAndWriteNamesOfGrpsAssociatedToMatch (struct Match *Match); static bool Gam_CheckIfIPlayThisMatchBasedOnGrps (long GamCod); static unsigned Gam_GetNumQstsGame (long GamCod); -static void Gam_PutParamQstCod (long QstCod); -static long Gam_GetParamQstCod (void); static void Gam_PutParamQstInd (unsigned QstInd); static unsigned Gam_GetParamQstInd (void); -static void Gam_RemAnswersOfAQuestion (long QstCod); +static unsigned Gam_GetQstIndFromStr (const char *UnsignedStr); +static void Gam_RemAnswersOfAQuestion (long GamCod,unsigned QstInd); -static int Gam_GetQstIndFromQstCod (long GamCod,long QstCod); // TODO: Remove this function because a question code can be repeated static long Gam_GetQstCodFromQstInd (long GamCod,unsigned QstInd); -static int Gam_GetMaxQuestionIndexInGame (long GamCod); -static int Gam_GetPrevQuestionIndexInGame (long GamCod,int QstInd); -static int Gam_GetNextQuestionIndexInGame (long GamCod,int QstInd); +static unsigned Gam_GetMaxQuestionIndexInGame (long GamCod); +static unsigned Gam_GetPrevQuestionIndexInGame (long GamCod,unsigned QstInd); +static unsigned Gam_GetNextQuestionIndexInGame (long GamCod,unsigned QstInd); static void Gam_ListGameQuestions (struct Game *Game); static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts, MYSQL_RES *mysql_res); @@ -160,7 +158,7 @@ static void Gam_AllocateListSelectedQuestions (void); static void Gam_FreeListsSelectedQuestions (void); static unsigned Gam_CountNumQuestionsInList (void); -static unsigned Gam_GetNumUsrsWhoAnswered (long GamCod,long QstCod,unsigned AnsInd); +static unsigned Gam_GetNumUsrsWhoAnswered (long GamCod,unsigned QstInd,unsigned AnsInd); static void Gam_DrawBarNumUsrs (unsigned NumUsrs,unsigned MaxUsrs); static void Gam_PutParamsOneQst (void); @@ -188,7 +186,7 @@ static void Gam_PlayGameShowQuestionAndAnswers (long MchCod, bool ShowAnswers); static void Gam_PutBigButtonToContinue (Act_Action_t NextAction, long MchCod,unsigned QstInd); -static void Gam_PutBigButtonToEnd (long GamCod); +static void Gam_PutBigButtonToFinishMatch (long GamCod); static void Gam_ShowQuestionBeingPlayed (struct Match *Match); @@ -1944,24 +1942,6 @@ void Gam_RequestNewQuestion (void) false); // Do not put button to play } -/*****************************************************************************/ -/****************** Write parameter with code of question ********************/ -/*****************************************************************************/ - -static void Gam_PutParamQstCod (long QstCod) - { - Par_PutHiddenParamLong ("QstCod",QstCod); - } - -/*****************************************************************************/ -/******************* Get parameter with code of question *********************/ -/*****************************************************************************/ - -static long Gam_GetParamQstCod (void) - { - return Par_GetParToLong ("QstCod"); - } - /*****************************************************************************/ /****************** Write parameter with index of question *******************/ /*****************************************************************************/ @@ -1977,55 +1957,39 @@ static void Gam_PutParamQstInd (unsigned QstInd) static unsigned Gam_GetParamQstInd (void) { - long LongInt; + long LongNum; - LongInt = Par_GetParToLong ("QstInd"); - if (LongInt < 0) + LongNum = Par_GetParToLong ("QstInd"); + if (LongNum < 0) Lay_ShowErrorAndExit ("Wrong question index."); - return (unsigned) LongInt; + return (unsigned) LongNum; + } + +/*****************************************************************************/ +/******************* Get parameter with index of question ********************/ +/*****************************************************************************/ + +static unsigned Gam_GetQstIndFromStr (const char *UnsignedStr) + { + long LongNum; + + LongNum = Str_ConvertStrCodToLongCod (UnsignedStr); + return (LongNum > 0) ? (unsigned) LongNum : + 0; } /*****************************************************************************/ /********************** Remove answers of a game question ********************/ /*****************************************************************************/ -static void Gam_RemAnswersOfAQuestion (long QstCod) +static void Gam_RemAnswersOfAQuestion (long GamCod,unsigned QstInd) { /***** Remove answers *****/ DB_QueryDELETE ("can not remove the answers of a question", - "DELETE FROM gam_answers WHERE QstCod=%ld", - QstCod); - } - -/*****************************************************************************/ -/******************** Get next question index in a game **********************/ -/*****************************************************************************/ -// TODO: Remove this function because a question code can be repeated - -static int Gam_GetQstIndFromQstCod (long GamCod,long QstCod) - { - MYSQL_RES *mysql_res; - MYSQL_ROW row; - int QstInd = -1; - - /***** Get number of games with a field value from database *****/ - if (!DB_QuerySELECT (&mysql_res,"can not get question index", - "SELECT QstInd FROM gam_questions" - " WHERE GamCod=%ld AND QstCod=%ld", - GamCod,QstCod)) - Lay_ShowErrorAndExit ("Error when getting question index."); - - /***** Get question index (row[0]) *****/ - row = mysql_fetch_row (mysql_res); - if (row[0]) - if (sscanf (row[0],"%d",&QstInd) != 1) - Lay_ShowErrorAndExit ("Error when getting question index."); - - /***** Free structure that stores the query result *****/ - DB_FreeMySQLResult (&mysql_res); - - return QstInd; + "DELETE FROM gam_answers" + " WHERE GamCod=%ld AND QstInd=%u", + GamCod,QstInd); } /*****************************************************************************/ @@ -2059,14 +2023,14 @@ static long Gam_GetQstCodFromQstInd (long GamCod,unsigned QstInd) /*****************************************************************************/ /****************** Get maximum question index in a game *********************/ /*****************************************************************************/ -// Question index can be 0, 1, 2,... -// Return -1 if no questions +// Question index can be 1, 2, 3... +// Return 0 if no questions -static int Gam_GetMaxQuestionIndexInGame (long GamCod) +static unsigned Gam_GetMaxQuestionIndexInGame (long GamCod) { MYSQL_RES *mysql_res; MYSQL_ROW row; - int QstInd = -1; + unsigned QstInd = 0; /***** Get maximum question index in a game from database *****/ DB_QuerySELECT (&mysql_res,"can not get last question index", @@ -2074,7 +2038,7 @@ static int Gam_GetMaxQuestionIndexInGame (long GamCod) GamCod); row = mysql_fetch_row (mysql_res); if (row[0]) // There are questions - if (sscanf (row[0],"%d",&QstInd) != 1) + if (sscanf (row[0],"%u",&QstInd) != 1) Lay_ShowErrorAndExit ("Error when getting last question index."); /***** Free structure that stores the query result *****/ @@ -2086,28 +2050,28 @@ static int Gam_GetMaxQuestionIndexInGame (long GamCod) /*****************************************************************************/ /*********** Get previous question index to a given index in a game **********/ /*****************************************************************************/ -// Question index can be 0, 1, 2,... -// Return -1 if no previous question +// Question index can be 1, 2, 3... +// Return 0 if no previous question -static int Gam_GetPrevQuestionIndexInGame (long GamCod,int QstInd) +static unsigned Gam_GetPrevQuestionIndexInGame (long GamCod,unsigned QstInd) { MYSQL_RES *mysql_res; MYSQL_ROW row; - int PrevQstInd = -1; + unsigned PrevQstInd = 0; /***** Get previous question index in a game from database *****/ // Although indexes are always continuous... // ...this implementation works even with non continuous indexes if (!DB_QuerySELECT (&mysql_res,"can not get previous question index", "SELECT MAX(QstInd) FROM gam_questions" - " WHERE GamCod=%ld AND QstInd<%d", + " WHERE GamCod=%ld AND QstInd<%u", GamCod,QstInd)) Lay_ShowErrorAndExit ("Error: previous question index not found."); /***** Get previous question index (row[0]) *****/ row = mysql_fetch_row (mysql_res); if (row[0]) - if (sscanf (row[0],"%d",&PrevQstInd) != 1) + if (sscanf (row[0],"%u",&PrevQstInd) != 1) Lay_ShowErrorAndExit ("Error when getting previous question index."); /***** Free structure that stores the query result *****/ @@ -2119,28 +2083,28 @@ static int Gam_GetPrevQuestionIndexInGame (long GamCod,int QstInd) /*****************************************************************************/ /************* Get next question index to a given index in a game ************/ /*****************************************************************************/ -// Question index can be 0, 1, 2,... -// Return -1 if no next question +// Question index can be 1, 2, 3... +// Return 0 if no next question -static int Gam_GetNextQuestionIndexInGame (long GamCod,int QstInd) +static unsigned Gam_GetNextQuestionIndexInGame (long GamCod,unsigned QstInd) { MYSQL_RES *mysql_res; MYSQL_ROW row; - int NextQstInd = -1; + unsigned NextQstInd = 0; /***** Get next question index in a game from database *****/ // Although indexes are always continuous... // ...this implementation works even with non continuous indexes if (!DB_QuerySELECT (&mysql_res,"can not get next question index", "SELECT MIN(QstInd) FROM gam_questions" - " WHERE GamCod=%ld AND QstInd>%d", + " WHERE GamCod=%ld AND QstInd>%u", GamCod,QstInd)) Lay_ShowErrorAndExit ("Error: next question index not found."); /***** Get next question index (row[0]) *****/ row = mysql_fetch_row (mysql_res); if (row[0]) - if (sscanf (row[0],"%d",&NextQstInd) != 1) + if (sscanf (row[0],"%u",&NextQstInd) != 1) Lay_ShowErrorAndExit ("Error when getting next question index."); /***** Free structure that stores the query result *****/ @@ -2173,11 +2137,12 @@ static void Gam_ListGameQuestions (struct Game *Game) /***** Get data of questions from database *****/ NumQsts = (unsigned) DB_QuerySELECT (&mysql_res,"can not get data of a question", - "SELECT tst_questions.QstCod," // row[0] - "tst_questions.AnsType," // row[1] - "tst_questions.Stem," // row[2] - "tst_questions.Feedback," // row[3] - "tst_questions.MedCod" // row[4] + "SELECT gam_questions.QstInd," // row[0] + "gam_questions.QstCod," // row[1] + "tst_questions.AnsType," // row[2] + "tst_questions.Stem," // row[3] + "tst_questions.Feedback," // row[4] + "tst_questions.MedCod" // row[5] " FROM gam_questions,tst_questions" " WHERE gam_questions.GamCod=%ld" " AND gam_questions.QstCod=tst_questions.QstCod" @@ -2238,9 +2203,13 @@ static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts, extern const char *Txt_TST_STR_ANSWER_TYPES[Tst_NUM_ANS_TYPES]; unsigned NumQst; MYSQL_ROW row; - unsigned UniqueId; + unsigned QstInd; + unsigned MaxQstInd; long QstCod; - char StrNumQst[10 + 1]; + char StrQstInd[10 + 1]; + + /***** Get maximum question index *****/ + MaxQstInd = Gam_GetMaxQuestionIndexInGame (GamCod); /***** Write the heading *****/ Tbl_StartTableWideMargin (2); @@ -2265,50 +2234,52 @@ static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts, Txt_Question); /***** Write rows *****/ - for (NumQst = 0, UniqueId = 1; + for (NumQst = 0; NumQst < NumQsts; - NumQst++, UniqueId++) + NumQst++) { Gbl.RowEvenOdd = NumQst % 2; - snprintf (StrNumQst,sizeof (StrNumQst), - "%u", - NumQst + 1); - row = mysql_fetch_row (mysql_res); /* - row[0] QstCod - row[1] AnsType - row[2] Stem - row[3] Feedback - row[4] MedCod + row[0] QstInd + row[1] QstCod + row[2] AnsType + row[3] Stem + row[4] Feedback + row[5] MedCod */ /***** Create test question *****/ Tst_QstConstructor (); - /* row[0] holds the code of the question */ - if ((QstCod = Str_ConvertStrCodToLongCod (row[0])) <= 0) - Lay_ShowErrorAndExit ("Wrong code of question."); + /* Get question index (row[0]) */ + QstInd = Gam_GetQstIndFromStr (row[0]); + snprintf (StrQstInd,sizeof (StrQstInd), + "%u", + QstInd); + + /* Get question code (row[1]) */ + QstCod = Str_ConvertStrCodToLongCod (row[1]); /***** Icons *****/ Gam_CurrentGamCod = GamCod; - Gam_CurrentQstCod = QstCod; + Gam_CurrentQstInd = QstInd; fprintf (Gbl.F.Out,"" "",Gbl.RowEvenOdd); /* Put icon to remove the question */ Frm_StartForm (ActReqRemGamQst); Gam_PutParamGameCod (GamCod); - Gam_PutParamQstCod (QstCod); + Gam_PutParamQstInd (QstInd); Ico_PutIconRemove (); Frm_EndForm (); /* Put icon to move up the question */ - if (NumQst) + if (QstInd > 1) { snprintf (Gbl.Title,sizeof (Gbl.Title), Txt_Move_up_X, - StrNumQst); + StrQstInd); Lay_PutContextualLinkOnlyIcon (ActUp_GamQst,NULL,Gam_PutParamsOneQst, "arrow-up.svg", Gbl.Title); @@ -2317,11 +2288,11 @@ static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts, Ico_PutIconOff ("arrow-up.svg",Txt_Movement_not_allowed); /* Put icon to move down the question */ - if (NumQst + 1 < NumQsts) + if (QstInd < MaxQstInd) { snprintf (Gbl.Title,sizeof (Gbl.Title), Txt_Move_down_X, - StrNumQst); + StrQstInd); Lay_PutContextualLinkOnlyIcon (ActDwnGamQst,NULL,Gam_PutParamsOneQst, "arrow-down.svg", Gbl.Title); @@ -2339,10 +2310,10 @@ static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts, fprintf (Gbl.F.Out,"" "
%s
", Gbl.RowEvenOdd, - StrNumQst); + StrQstInd); - /* Write answer type (row[1]) */ - Gbl.Test.AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]); + /* Write answer type (row[2]) */ + Gbl.Test.AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[2]); fprintf (Gbl.F.Out,"
%s
" "", Txt_TST_STR_ANSWER_TYPES[Gbl.Test.AnswerType]); @@ -2359,13 +2330,13 @@ static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts, Tst_GetAndWriteTagsQst (Gbl.Test.QstCod); fprintf (Gbl.F.Out,""); - /* Write stem (row[2]) */ + /* Write stem (row[3]) */ fprintf (Gbl.F.Out,"", Gbl.RowEvenOdd); - Tst_WriteQstStem (row[2],"TEST_EDI"); + Tst_WriteQstStem (row[3],"TEST_EDI"); - /* Get media (row[4]) */ - Gbl.Test.Media.MedCod = Str_ConvertStrCodToLongCod (row[4]); + /* Get media (row[5]) */ + Gbl.Test.Media.MedCod = Str_ConvertStrCodToLongCod (row[5]); Med_GetMediaDataByCod (&Gbl.Test.Media); /* Show media */ @@ -2373,11 +2344,11 @@ static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts, "TEST_MED_EDIT_LIST_STEM_CONTAINER", "TEST_MED_EDIT_LIST_STEM"); - /* Show feedback (row[3]) */ - Tst_WriteQstFeedback (row[3],"TEST_EDI_LIGHT"); + /* Show feedback (row[4]) */ + Tst_WriteQstFeedback (row[4],"TEST_EDI_LIGHT"); /* Show answers */ - Tst_WriteAnswersGameResult (GamCod,NumQst,QstCod, + Tst_WriteAnswersGameResult (GamCod,QstInd,QstCod, "TEST_EDI",true); // Show result fprintf (Gbl.F.Out,"" @@ -2435,7 +2406,7 @@ void Gam_AddTstQuestionsToGame (void) const char *Ptr; char LongStr[1 + 10 + 1]; long QstCod; - int MaxQstInd; + unsigned MaxQstInd; /***** Get game code *****/ if ((Game.GamCod = Gam_GetParamGameCod ()) == -1L) @@ -2475,7 +2446,7 @@ void Gam_AddTstQuestionsToGame (void) " (GamCod,QstCod,QstInd)" " VALUES" " (%ld,%ld,%u)", - Game.GamCod,QstCod,(unsigned) (MaxQstInd + 1)); + Game.GamCod,QstCod,MaxQstInd + 1); } /***** Free space for selected question codes *****/ @@ -2543,12 +2514,12 @@ static unsigned Gam_CountNumQuestionsInList (void) /*** Get number of users who selected this answer and draw proportional bar **/ /*****************************************************************************/ -void Gam_GetAndDrawBarNumUsrsWhoAnswered (long GamCod,long QstCod,unsigned AnsInd,unsigned NumUsrs) +void Gam_GetAndDrawBarNumUsrsWhoAnswered (long GamCod,unsigned QstInd,unsigned AnsInd,unsigned NumUsrs) { unsigned NumUsrsThisAnswer; /***** Get number of users who selected this answer *****/ - NumUsrsThisAnswer = Gam_GetNumUsrsWhoAnswered (GamCod,QstCod,AnsInd); + NumUsrsThisAnswer = Gam_GetNumUsrsWhoAnswered (GamCod,QstInd,AnsInd); /***** Show stats of this answer *****/ Gam_DrawBarNumUsrs (NumUsrsThisAnswer,NumUsrs); @@ -2558,7 +2529,7 @@ void Gam_GetAndDrawBarNumUsrsWhoAnswered (long GamCod,long QstCod,unsigned AnsIn /**** Get number of users who selected a given answer of a game question *****/ /*****************************************************************************/ -static unsigned Gam_GetNumUsrsWhoAnswered (long GamCod,long QstCod,unsigned AnsInd) +static unsigned Gam_GetNumUsrsWhoAnswered (long GamCod,unsigned QstInd,unsigned AnsInd) { MYSQL_RES *mysql_res; MYSQL_ROW row; @@ -2567,8 +2538,8 @@ static unsigned Gam_GetNumUsrsWhoAnswered (long GamCod,long QstCod,unsigned AnsI /***** Get answers of a question from database *****/ if (DB_QuerySELECT (&mysql_res,"can not get number of users who answered", "SELECT NumUsrs FROM gam_answers" - " WHERE GamCod=%ld AND QstCod=%ld AND AnsInd=%u", - GamCod,QstCod,AnsInd)) + " WHERE GamCod=%ld AND QstInd=%u AND AnsInd=%u", + GamCod,QstInd,AnsInd)) { row = mysql_fetch_row (mysql_res); if (row[0]) // There are users who selected this answer @@ -2629,7 +2600,7 @@ static void Gam_DrawBarNumUsrs (unsigned NumUsrs,unsigned MaxUsrs) static void Gam_PutParamsOneQst (void) { Gam_PutParamGameCod (Gam_CurrentGamCod); - Gam_PutParamQstCod (Gam_CurrentQstCod); + Gam_PutParamQstInd (Gam_CurrentQstInd); } /*****************************************************************************/ @@ -2641,7 +2612,6 @@ void Gam_RequestRemoveQst (void) extern const char *Txt_Do_you_really_want_to_remove_the_question_X; extern const char *Txt_Remove_question; struct Game Game; - long QstCod; unsigned QstInd; /***** Get parameters *****/ @@ -2649,20 +2619,16 @@ void Gam_RequestRemoveQst (void) if ((Game.GamCod = Gam_GetParamGameCod ()) == -1L) Lay_ShowErrorAndExit ("Code of game is missing."); - /* Get question code */ - if ((QstCod = Gam_GetParamQstCod ()) <= 0) - Lay_ShowErrorAndExit ("Wrong code of question."); - /* Get question index */ - QstInd = (unsigned) Gam_GetQstIndFromQstCod (Game.GamCod,QstCod); // TODO: Remove this function because a question code can be repeated + QstInd = Gam_GetParamQstInd (); /***** Show question and button to remove question *****/ Gam_CurrentGamCod = Game.GamCod; - Gam_CurrentQstCod = QstCod; + Gam_CurrentQstInd = QstInd; Ale_ShowAlertAndButton (ActRemGamQst,NULL,NULL,Gam_PutParamsOneQst, Btn_REMOVE_BUTTON,Txt_Remove_question, Ale_QUESTION,Txt_Do_you_really_want_to_remove_the_question_X, - (unsigned long) (QstInd + 1)); + QstInd); /***** Show current game *****/ Gam_ShowOneGame (Game.GamCod, @@ -2680,7 +2646,6 @@ void Gam_RemoveQst (void) { extern const char *Txt_Question_removed; struct Game Game; - long QstCod; unsigned QstInd; /***** Get parameters *****/ @@ -2688,25 +2653,26 @@ void Gam_RemoveQst (void) if ((Game.GamCod = Gam_GetParamGameCod ()) == -1L) Lay_ShowErrorAndExit ("Code of game is missing."); - /* Get question code */ - if ((QstCod = Gam_GetParamQstCod ()) <= 0) - Lay_ShowErrorAndExit ("Wrong code of question."); - /* Get question index */ - QstInd = (unsigned) Gam_GetQstIndFromQstCod (Game.GamCod,QstCod); // TODO: Remove this function because a question code can be repeated + QstInd = Gam_GetParamQstInd (); /***** Remove the question from all the tables *****/ /* Remove answers from this test question */ - Gam_RemAnswersOfAQuestion (QstCod); + Gam_RemAnswersOfAQuestion (Game.GamCod,QstInd); /* Remove the question itself */ DB_QueryDELETE ("can not remove a question", - "DELETE FROM gam_questions WHERE QstCod=%ld", - QstCod); + "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 gam_answers SET QstInd=QstInd-1" + " WHERE GamCod=%ld AND 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", @@ -2730,38 +2696,35 @@ 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 Game Game; - long QstCod; - int QstIndTop; - int QstIndBottom; + unsigned QstIndTop; + unsigned QstIndBottom; /***** Get parameters *****/ /* Get game code */ if ((Game.GamCod = Gam_GetParamGameCod ()) == -1L) Lay_ShowErrorAndExit ("Code of game is missing."); - /* Get question code */ - if ((QstCod = Gam_GetParamQstCod ()) <= 0) - Lay_ShowErrorAndExit ("Wrong code of question."); - /* Get question index */ - QstIndBottom = Gam_GetQstIndFromQstCod (Game.GamCod,QstCod); // TODO: Remove this function because a question code can be repeated + QstIndBottom = Gam_GetParamQstInd (); /***** Move up question *****/ - if (QstIndBottom > 0) + if (QstIndBottom > 1) { /* Indexes of questions to be exchanged */ QstIndTop = Gam_GetPrevQuestionIndexInGame (Game.GamCod,QstIndBottom); - if (QstIndTop < 0) + if (!QstIndTop) Lay_ShowErrorAndExit ("Wrong index of question."); /* Exchange questions */ - Gam_ExchangeQuestions (Game.GamCod, - (unsigned) QstIndTop,(unsigned) QstIndBottom); + 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); /***** Show current game *****/ Gam_ShowOneGame (Game.GamCod, @@ -2778,43 +2741,45 @@ 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 Game Game; - long QstCod; - int QstIndTop; - int QstIndBottom; - int MaxQstInd; // -1 if no questions + unsigned QstIndTop; + unsigned QstIndBottom; + unsigned MaxQstInd; // 0 if no questions /***** Get parameters *****/ /* Get game code */ if ((Game.GamCod = Gam_GetParamGameCod ()) == -1L) Lay_ShowErrorAndExit ("Code of game is missing."); - /* Get question code */ - if ((QstCod = Gam_GetParamQstCod ()) <= 0) - Lay_ShowErrorAndExit ("Wrong code of question."); - /* Get question index */ - QstIndTop = Gam_GetQstIndFromQstCod (Game.GamCod,QstCod); // TODO: Remove this function because a question code can be repeated + QstIndTop = Gam_GetParamQstInd (); /* Get maximum question index */ MaxQstInd = Gam_GetMaxQuestionIndexInGame (Game.GamCod); /***** Move down question *****/ - if (MaxQstInd > 0) + if (MaxQstInd) + { if (QstIndTop < MaxQstInd) { /* Indexes of questions to be exchanged */ QstIndBottom = Gam_GetNextQuestionIndexInGame (Game.GamCod,QstIndTop); - if (QstIndBottom < 0) + if (!QstIndBottom) Lay_ShowErrorAndExit ("Wrong index of question."); /* Exchange questions */ - Gam_ExchangeQuestions (Game.GamCod, - (unsigned) QstIndTop,(unsigned) 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 + Ale_ShowAlert (Ale_WARNING,Txt_This_game_has_no_questions); /***** Show current game *****/ Gam_ShowOneGame (Game.GamCod, @@ -2846,14 +2811,14 @@ static void Gam_ExchangeQuestions (long GamCod, /***** Exchange indexes of questions *****/ /* Example: - QstIndTop = 0; QstCodTop = 218 - QstIndBottom = 1; QstCodBottom = 220 + QstIndTop = 1; QstCodTop = 218 + QstIndBottom = 2; QstCodBottom = 220 +--------+--------+ +--------+--------+ +--------+--------+ | QstInd | QstCod | | QstInd | QstCod | | QstInd | QstCod | +--------+--------+ +--------+--------+ +--------+--------+ - | 0 | 218 | -----> | 1 | 218 | = | 0 | 220 | - | 1 | 220 | | 0 | 220 | | 1 | 218 | - | 2 | 232 | | 2 | 232 | | 2 | 232 | + | 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 questions", @@ -2996,7 +2961,7 @@ void Gam_GetDataOfMatchByCod (struct Match *Match) Match->TimeUTC[Gam_START_TIME] = Match->TimeUTC[Gam_END_TIME ] = (time_t) 0; Match->Title[0] = '\0'; - Match->Status.QstInd = -1; + Match->Status.QstInd = 0; Match->Status.QstCod = -1L; Match->Status.QstStartTimeUTC = (time_t) 0; Match->Status.ShowAnswers = false; @@ -3031,7 +2996,7 @@ static void Gam_ListOneOrMoreMatchesForEdition (unsigned NumMatches, extern const char *Txt_ROLES_SINGUL_Abc[Rol_NUM_ROLES][Usr_NUM_SEXS]; extern const char *Txt_START_END_TIME[Dat_NUM_START_END_TIME]; extern const char *Txt_Match; - extern const char *Txt_Continue; + extern const char *Txt_Resume; extern const char *Txt_Today; unsigned NumMatch; unsigned UniqueId; @@ -3083,14 +3048,14 @@ static void Gam_ListOneOrMoreMatchesForEdition (unsigned NumMatches, Ico_PutIconRemove (); Frm_EndForm (); - /* Put icon to continue playing the match */ + /* Put icon to continue playing an unfinished match */ if (!Match.Status.Finished) { Gam_CurrentMchCod = Match.MchCod; - Lay_PutContextualLinkOnlyIcon (ActGamTchNxtQst,NULL, // TODO: Continue on a new tab!!!! + Lay_PutContextualLinkOnlyIcon (ActResMch,NULL, Gam_PutParamCurrentMchCod, "play.svg", - Txt_Continue); + Txt_Resume); } fprintf (Gbl.F.Out,""); @@ -3211,7 +3176,7 @@ static void Gam_GetMatchDataFromRow (MYSQL_RES *mysql_res, row[10] Finished */ /* Current question index (row[6]) */ - Match->Status.QstInd = (int) Str_ConvertStrCodToLongCod (row[6]); + Match->Status.QstInd = Gam_GetQstIndFromStr (row[6]); /* Current question code (row[7]) */ Match->Status.QstCod = Str_ConvertStrCodToLongCod (row[7]); @@ -3395,7 +3360,7 @@ static void Gam_PutBigButtonToPlayMatchTch (struct Game *Game) Lay_StartSection (Gam_NEW_MATCH_SECTION_ID); /***** Start form *****/ - Frm_StartForm (ActGamTch1stQst); + Frm_StartForm (ActNewMch); Gam_PutParamGameCod (Game->GamCod); Gam_PutParamQstInd (0); // Start by first question in game @@ -3513,7 +3478,7 @@ static long Gam_CreateMatch (struct Match *Match) "QstInd,QstCod,QstStartTime,ShowingAnswers,Finished)" " VALUES" " (%ld,%ld,NOW(),NOW(),'%s'," - "-1,-1,FROM_UNIXTIME(0),'N','N')", + "0,-1,FROM_UNIXTIME(0),'N','N')", Match->GamCod, Gbl.Usrs.Me.UsrDat.UsrCod, Match->Title); @@ -3525,6 +3490,37 @@ static long Gam_CreateMatch (struct Match *Match) return MchCod; } +/*****************************************************************************/ +/**** Resume an unfinished match and show current question (by a teacher) ****/ +/*****************************************************************************/ + +void Gam_ResumeUnfinishedMatch (void) + { + struct Match Match; + + /***** Get parameters *****/ + /* Get match code */ + if ((Match.MchCod = Gam_GetParamMatchCod ()) == -1L) + Lay_ShowErrorAndExit ("Code of match is missing."); + + /***** Get data of the match from database *****/ + Gam_GetDataOfMatchByCod (&Match); + + if (Match.Status.Finished) + { + /***** Show alert *****/ + Ale_ShowAlert (Ale_WARNING,"Partida finalizada."); // TODO: Need translation!!!!! + + /***** Button to close browser tab *****/ + Btn_PutCloseButton ("Cerrar"); // TODO: Need translation!!!!! + } + else // Unfinished match + /***** Show questions and possible answers *****/ + Gam_PlayGameShowQuestionAndAnswers (Match.MchCod, + Match.Status.QstInd, // Resume last question index shown + Match.Status.ShowAnswers); // Show answers? + } + /*****************************************************************************/ /***************** Insert/update a game match being played *******************/ /*****************************************************************************/ @@ -3546,7 +3542,7 @@ static void Gam_UpdateMatchBeingPlayed (long MchCod,unsigned QstInd,long QstCod, DB_QueryUPDATE ("can not update match being played", "UPDATE gam_matches,games" " SET gam_matches.EndTime=NOW()," - "gam_matches.QstInd=%d," + "gam_matches.QstInd=%u," "gam_matches.QstCod=%ld," "gam_matches.ShowingAnswers='N'," "gam_matches.QstStartTime=NOW()" @@ -3611,7 +3607,7 @@ static void Gam_PlayGameShowQuestionAndAnswers (long MchCod, { MYSQL_RES *mysql_res; MYSQL_ROW row; - int NxtQstInd; + unsigned NxtQstInd; long QstCod; struct Match Match; @@ -3638,8 +3634,7 @@ static void Gam_PlayGameShowQuestionAndAnswers (long MchCod, fprintf (Gbl.F.Out,"
"); /* Write number of question */ - fprintf (Gbl.F.Out,"
%u
", - QstInd + 1); + fprintf (Gbl.F.Out,"
%u
",QstInd); fprintf (Gbl.F.Out,"
"); @@ -3678,12 +3673,12 @@ static void Gam_PlayGameShowQuestionAndAnswers (long MchCod, { /* Get index of the next question */ NxtQstInd = Gam_GetNextQuestionIndexInGame (Match.GamCod,Match.Status.QstInd); - if (NxtQstInd >= 0) // Not last question + if (NxtQstInd) // Not last question /* Put button to show next question */ Gam_PutBigButtonToContinue (ActGamTchNxtQst,Match.MchCod,(unsigned) NxtQstInd); - else // Last question + else // Last question /* Put button to end */ - Gam_PutBigButtonToEnd (Match.MchCod); + Gam_PutBigButtonToFinishMatch (Match.MchCod); } else /* Put button to show answers */ @@ -3733,10 +3728,10 @@ static void Gam_PutBigButtonToContinue (Act_Action_t NextAction, } /*****************************************************************************/ -/********************* Put a big button to end a match ***********************/ +/******************** Put a big button to finish a match *********************/ /*****************************************************************************/ -static void Gam_PutBigButtonToEnd (long MchCod) +static void Gam_PutBigButtonToFinishMatch (long MchCod) { extern const char *Txt_Finish; @@ -3744,7 +3739,7 @@ static void Gam_PutBigButtonToEnd (long MchCod) fprintf (Gbl.F.Out,"
"); /***** Start form *****/ - Frm_StartForm (ActGamTchEnd); + Frm_StartForm (ActEndMch); Gam_PutParamMatchCod (MchCod); /***** Put icon with link *****/ @@ -3864,7 +3859,7 @@ static void Gam_ShowQuestionBeingPlayed (struct Match *Match) /***** Show question *****/ /* Write number of question */ fprintf (Gbl.F.Out,"
%u
", - Match->Status.QstInd + 1); + Match->Status.QstInd); fprintf (Gbl.F.Out,"
"); diff --git a/swad_game.h b/swad_game.h index 7c3420c6c..b989a81f8 100644 --- a/swad_game.h +++ b/swad_game.h @@ -109,7 +109,7 @@ void Gam_RemoveGames (Hie_Level_t Scope,long Cod); void Gam_RequestNewQuestion (void); -void Gam_GetAndDrawBarNumUsrsWhoAnswered (long GamCod,long QstCod,unsigned AnsInd,unsigned NumUsrs); +void Gam_GetAndDrawBarNumUsrsWhoAnswered (long GamCod,unsigned QstInd,unsigned AnsInd,unsigned NumUsrs); void Gam_AddTstQuestionsToGame (void); @@ -127,6 +127,7 @@ void Gam_PlayMatchStd (void); void Gam_ReceiveGameAnswers (void); void Gam_CreateAndStartNewMatch (void); +void Gam_ResumeUnfinishedMatch (void); void Gam_MatchTchNextQuestion (void); void Gam_MatchTchShowAnswers (void); void Gam_MatchTchEnd (void); diff --git a/swad_survey.c b/swad_survey.c index b3e1c012a..7b91cd934 100644 --- a/swad_survey.c +++ b/swad_survey.c @@ -3530,12 +3530,12 @@ void Svy_RequestRemoveQst (void) SvyQst.QstInd = Svy_GetQstIndFromQstCod (SvyQst.QstCod); /***** Show question and button to remove question *****/ - Svy_CurrentSvyCod = SvyCod; + Svy_CurrentSvyCod = SvyCod; Svy_CurrentQstCod = SvyQst.QstCod; Ale_ShowAlertAndButton (ActRemSvyQst,NULL,NULL,Svy_PutParamsRemoveOneQst, Btn_REMOVE_BUTTON,Txt_Remove_question, Ale_QUESTION,Txt_Do_you_really_want_to_remove_the_question_X, - (unsigned long) (SvyQst.QstInd + 1)); + (long) SvyQst.QstInd + 1); /***** Show current survey *****/ Svy_ShowOneSurvey (SvyCod,&SvyQst,true); diff --git a/swad_test.c b/swad_test.c index 93683e903..4b1c066c3 100644 --- a/swad_test.c +++ b/swad_test.c @@ -209,7 +209,7 @@ static void Tst_WriteChoiceAnsViewTest (unsigned NumQst,long QstCod,bool Shuffle static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat, unsigned NumQst,MYSQL_RES *mysql_res, double *ScoreThisQst,bool *AnswerIsNotBlank); -static void Tst_WriteChoiceAnsViewGame (long GamCod,unsigned NumQst,long QstCod, +static void Tst_WriteChoiceAnsViewGame (long GamCod,unsigned QstInd,long QstCod, const char *Class, bool ShowResult); @@ -3525,12 +3525,12 @@ static void Tst_WriteAnswersTestResult (struct UsrData *UsrDat, /************** Write answers of a question when viewing a game **************/ /*****************************************************************************/ -void Tst_WriteAnswersGameResult (long GamCod,unsigned NumQst,long QstCod, +void Tst_WriteAnswersGameResult (long GamCod,unsigned QstInd,long QstCod, const char *Class,bool ShowResult) { /***** Write answer depending on type *****/ if (Gbl.Test.AnswerType == Tst_ANS_UNIQUE_CHOICE) - Tst_WriteChoiceAnsViewGame (GamCod,NumQst,QstCod, + Tst_WriteChoiceAnsViewGame (GamCod,QstInd,QstCod, Class,ShowResult); else Ale_ShowAlert (Ale_ERROR,"Type of answer not valid in a game."); @@ -4044,7 +4044,7 @@ static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat, /******** Write single or multiple choice answer when viewing a test *********/ /*****************************************************************************/ -static void Tst_WriteChoiceAnsViewGame (long GamCod,unsigned NumQst,long QstCod, +static void Tst_WriteChoiceAnsViewGame (long GamCod,unsigned QstInd,long QstCod, const char *Class, bool ShowResult) { @@ -4125,7 +4125,7 @@ static void Tst_WriteChoiceAnsViewGame (long GamCod,unsigned NumQst,long QstCod, "", - NumQst,NumOpt, + QstInd,NumOpt, Class, Gbl.Test.Answer.Options[NumOpt].Text); Med_ShowMedia (&Gbl.Test.Answer.Options[NumOpt].Media, @@ -4142,7 +4142,7 @@ static void Tst_WriteChoiceAnsViewGame (long GamCod,unsigned NumQst,long QstCod, ""); /* Get number of users who selected this answer and draw proportional bar */ - Gam_GetAndDrawBarNumUsrsWhoAnswered (GamCod,QstCod,AnsInd, + Gam_GetAndDrawBarNumUsrsWhoAnswered (GamCod,QstInd,AnsInd, 0); // TODO: NumUsrs fprintf (Gbl.F.Out,"" ""); @@ -6338,7 +6338,7 @@ void Tst_RequestRemoveQst (void) Tst_PutParamsRemoveQst, Btn_REMOVE_BUTTON,Txt_Remove_question, Ale_QUESTION,Txt_Do_you_really_want_to_remove_the_question_X, - (unsigned long) Gbl.Test.QstCod); + Gbl.Test.QstCod); /***** Continue editing questions *****/ if (EditingOnlyThisQst) diff --git a/swad_test.h b/swad_test.h index d610fff2d..8085adf02 100644 --- a/swad_test.h +++ b/swad_test.h @@ -154,7 +154,7 @@ bool Tst_GetOneQuestionByCod (long QstCod,MYSQL_RES **mysql_res); void Tst_WriteParamEditQst (void); unsigned Tst_GetNumAnswersQst (long QstCod); unsigned Tst_GetAnswersQst (long QstCod,MYSQL_RES **mysql_res,bool Shuffle); -void Tst_WriteAnswersGameResult (long GamCod,unsigned NumQst,long QstCod, +void Tst_WriteAnswersGameResult (long GamCod,unsigned QstInd,long QstCod, const char *Class,bool ShowResult); bool Tst_CheckIfQuestionIsValidForGame (long QstCod); void Tst_WriteAnsTF (char AnsTF); diff --git a/swad_text.c b/swad_text.c index 2b8be6b3e..a0ffc5ac6 100644 --- a/swad_text.c +++ b/swad_text.c @@ -8952,25 +8952,25 @@ const char *Txt_Do_you_really_want_to_remove_the_project_X = // Warning: it is v "Você realmente deseja remover o projeto %s?"; #endif -const char *Txt_Do_you_really_want_to_remove_the_question_X = // Warning: it is very important to include %lu in the following sentences +const char *Txt_Do_you_really_want_to_remove_the_question_X = // Warning: it is very important to include %ld in the following sentences #if L==1 // ca - "De veres voleu eliminar pregunta %lu?"; + "De veres voleu eliminar pregunta %ld?"; #elif L==2 // de - "Wollen Sie die Frage %lu wirklich entfernen?"; + "Wollen Sie die Frage %ld wirklich entfernen?"; #elif L==3 // en - "Do you really want to remove the question %lu?"; + "Do you really want to remove the question %ld?"; #elif L==4 // es - "¿Realmente desea eliminar la pregunta %lu?"; + "¿Realmente desea eliminar la pregunta %ld?"; #elif L==5 // fr - "Voulez-vous vraiment supprimer la question %lu?"; + "Voulez-vous vraiment supprimer la question %ld?"; #elif L==6 // gn - "¿Realmente desea eliminar la pregunta %lu?"; // Okoteve traducción + "¿Realmente desea eliminar la pregunta %ld?"; // Okoteve traducción #elif L==7 // it - "Vuoi realmente rimuovere la domanda %lu?"; + "Vuoi realmente rimuovere la domanda %ld?"; #elif L==8 // pl - "Czy na pewno chcesz usunac pytanie %lu?"; + "Czy na pewno chcesz usunac pytanie %ld?"; #elif L==9 // pt - "Você realmente deseja remover a questão %lu?"; + "Você realmente deseja remover a questão %ld?"; #endif const char *Txt_Do_you_really_want_to_remove_the_survey_X = // Warning: it is very important to include %s in the following sentences @@ -33012,6 +33012,27 @@ const char *Txt_results_per_page = "resultados por página"; #endif +const char *Txt_Resume = // Resume a game match +#if L==1 // ca + "Reprendre"; +#elif L==2 // de + "Fortsetzen"; +#elif L==3 // en + "Resume"; +#elif L==4 // es + "Reanudar"; +#elif L==5 // fr + "Reprendre"; +#elif L==6 // gn + "Reanudar"; // Okoteve traducción +#elif L==7 // it + "Riprendi"; +#elif L==8 // pl + "Wznów"; +#elif L==9 // pt + "Retomar"; +#endif + const char *Txt_Retype_new_password = #if L==1 // ca "Reescriviu la nova contrasenya";