From 665cbada441f313da78d10979765c87265bff4ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Ca=C3=B1as=20Vargas?= Date: Tue, 16 Jul 2019 22:33:28 +0200 Subject: [PATCH] Version18.133 --- css/swad18.132.2.css | 14 ++- sql/swad.sql | 8 ++ swad_action.c | 47 +++++---- swad_action.h | 109 ++++++++++---------- swad_changelog.h | 9 +- swad_config.h | 4 +- swad_database.c | 18 ++++ swad_game.c | 240 ++++++++++++++++++++++++++++++------------- swad_game.h | 18 ++-- swad_layout.c | 17 ++- 10 files changed, 321 insertions(+), 163 deletions(-) diff --git a/css/swad18.132.2.css b/css/swad18.132.2.css index 5af9702a3..717193463 100644 --- a/css/swad18.132.2.css +++ b/css/swad18.132.2.css @@ -2570,7 +2570,10 @@ a:hover img.CENTRE_PHOTO_SHOW display:table; margin:5%; width:90%; - /* text-align:center; */ + } +.GAM_PLAY_CONTAINER_TOP + { + box-sizing:border-box; } .GAM_PLAY_TCH_NUM_QST @@ -2611,12 +2614,17 @@ a:hover img.CENTRE_PHOTO_SHOW font-size:16pt; } -.GAM_PLAY_STD_WAIT +.GAM_PLAY_STD_WAIT_CONTAINER + { + box-sizing:border-box; + text-align:center; + } +.GAM_PLAY_STD_WAIT_IMAGE { box-sizing:border-box; width:50%; - margin:0 auto; } + .GAM_PLAY_STD_NUM_QST { width:15%; diff --git a/sql/swad.sql b/sql/swad.sql index f39ac9fbe..4fda84f48 100644 --- a/sql/swad.sql +++ b/sql/swad.sql @@ -644,6 +644,14 @@ CREATE TABLE IF NOT EXISTS gam_matches ( UNIQUE INDEX(MchCod), INDEX(GamCod)); -- +-- Table gam_players: stores the current match players +-- +CREATE TABLE IF NOT EXISTS gam_players ( + MchCod INT NOT NULL, + UsrCod INT NOT NULL, + TS TIMESTAMP, + UNIQUE INDEX(MchCod,UsrCod)); +-- -- Table gam_questions: stores the questions in the games -- CREATE TABLE IF NOT EXISTS gam_questions ( diff --git a/swad_action.c b/swad_action.c index 54235fda0..31ea6802a 100644 --- a/swad_action.c +++ b/swad_action.c @@ -605,13 +605,14 @@ Assessment: 453. ActRemSvyQst Confirm the removal of a question of a survey 454. ActSeeGam Show one game - 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. 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. ActNxtMch Show next question when playing a game (by a teacher) - NEW. ActShoMch Show finished match results + 455. ActFrmNewMchTch Put form to create a new match (by a teacher) + NEW. ActReqRemMchTch Request the removal of a match (by a teacher) + NEW. ActRemMchTch Confirm the removal of a match (by a teacher) + 456. ActNewMchTch Create a new match showing first question in a new browser tab (by a teacher) + NEW. ActResMchTch Resume an unfinished match showing current question in a new browser tab (by a teacher) + 457. ActNxtMchTch Show next question when playing a game (by a teacher) + NEW. ActRefMchTch Refresh current question when playing a game (as teacher) + NEW. ActShoMchTch Show finished match results NEW. ActPlyMchStd Show current question when playing a game (as student) NEW. ActRefMchStd Refresh current question when playing a game (as student) @@ -2144,13 +2145,14 @@ struct Act_Actions Act_Actions[Act_NUM_ACTIONS] = /* ActSeeGam */{1650,-1,TabUnk,ActSeeAllGam ,0x238,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Gam_SeeOneGame ,NULL}, - /* 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}, - /* ActNewMch */{1671,-1,TabUnk,ActSeeAllGam ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_NEW_TAB,NULL ,Gam_CreateNewMatch ,NULL}, - /* ActResMch */{1785,-1,TabUnk,ActSeeAllGam ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_NEW_TAB,NULL ,Gam_ResumeUnfinishedMatch ,NULL}, - /* ActNxtMch */{1672,-1,TabUnk,ActSeeAllGam ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_2ND_TAB,NULL ,Gam_NextStatusMatch ,NULL}, - /* ActShoMch */{1786,-1,TabUnk,ActSeeAllGam ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Gam_ShowFinishedMatchResults ,NULL}, + /* ActFrmNewMchTch */{1670,-1,TabUnk,ActSeeAllGam ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Gam_RequestNewMatchTch ,NULL}, + /* ActReqRemMchTch */{1783,-1,TabUnk,ActSeeAllGam ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Gam_RequestRemoveMatchTch ,NULL}, + /* ActRemMchTch */{1784,-1,TabUnk,ActSeeAllGam ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Gam_RemoveMatchTch ,NULL}, + /* ActNewMchTch */{1671,-1,TabUnk,ActSeeAllGam ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_NEW_TAB,Gam_CreateNewMatchTch1 ,Gam_CreateNewMatchTch2 ,NULL}, + /* ActResMchTch */{1785,-1,TabUnk,ActSeeAllGam ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_NEW_TAB,Gam_GetMatchBeingPlayed ,Gam_ResumeUnfinishedMatchTch ,NULL}, + /* ActNxtMchTch */{1672,-1,TabUnk,ActSeeAllGam ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_2ND_TAB,Gam_GetMatchBeingPlayed ,Gam_NextStatusMatchTch ,NULL}, + /* ActRefMchTch */{1788,-1,TabUnk,ActSeeAllGam ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_AJAX_RFRESH,Gam_GetMatchBeingPlayed ,Gam_RefreshCurrentMatchTch ,NULL}, + /* ActShoMchTch */{1786,-1,TabUnk,ActSeeAllGam ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Gam_ShowFinishedMatchResults ,NULL}, /* ActPlyMchStd */{1780,-1,TabUnk,ActSeeAllGam ,0x008, 0, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_NEW_TAB,Gam_GetMatchBeingPlayed ,Gam_ShowMatchToMeAsStd ,NULL}, /* ActRefMchStd */{1782,-1,TabUnk,ActSeeAllGam ,0x008, 0, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_AJAX_RFRESH,Gam_GetMatchBeingPlayed ,Gam_RefreshCurrentMatchStd ,NULL}, @@ -4876,9 +4878,9 @@ Act_Action_t Act_FromActCodToAction[1 + Act_MAX_ACTION_COD] = // Do not reuse un ActAddTstQstToGam, // #1667 ActUp_GamQst, // #1668 ActDwnGamQst, // #1669 - ActFrmNewMch, // #1670 - ActNewMch, // #1671 - ActNxtMch, // #1672 + ActFrmNewMchTch, // #1670 + ActNewMchTch, // #1671 + ActNxtMchTch, // #1672 -1, // #1673 (obsolete action) ActSeePrj, // #1674 ActFrmNewPrj, // #1675 @@ -4986,14 +4988,15 @@ Act_Action_t Act_FromActCodToAction[1 + Act_MAX_ACTION_COD] = // Do not reuse un ActLckAllPrj, // #1777 ActUnlAllPrj, // #1778 -1, // #1779 (obsolete action) - ActPlyMchStd, // #1780 + ActPlyMchStd, // #1780 -1, // #1781 (obsolete action) ActRefMchStd, // #1782 - ActReqRemMch, // #1783 - ActRemMch, // #1784 - ActResMch, // #1785 - ActShoMch, // #1786 + ActReqRemMchTch, // #1783 + ActRemMchTch, // #1784 + ActResMchTch, // #1785 + ActShoMchTch, // #1786 ActCreMyAcc, // #1787 + ActRefMchTch, // #1788 }; /*****************************************************************************/ diff --git a/swad_action.h b/swad_action.h index fab01cc48..8b4dc2cd8 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 + 168 + 437 + 176 + 169 + 16 + 68) +#define Act_NUM_ACTIONS (1 + 4 + 64 + 38 + 12 + 42 + 36 + 19 + 110 + 169 + 437 + 176 + 169 + 16 + 68) -#define Act_MAX_ACTION_COD 1787 +#define Act_MAX_ACTION_COD 1788 #define Act_MAX_OPTIONS_IN_MENU_PER_TAB 13 @@ -607,60 +607,61 @@ typedef signed int Act_Action_t; // Must be a signed type, because -1 is used to #define ActSeeOneTstResOth (ActChgCrsTT1stDay + 115) #define ActSeeGam (ActChgCrsTT1stDay + 116) -#define ActFrmNewMch (ActChgCrsTT1stDay + 117) -#define ActReqRemMch (ActChgCrsTT1stDay + 118) -#define ActRemMch (ActChgCrsTT1stDay + 119) -#define ActNewMch (ActChgCrsTT1stDay + 120) -#define ActResMch (ActChgCrsTT1stDay + 121) -#define ActNxtMch (ActChgCrsTT1stDay + 122) -#define ActShoMch (ActChgCrsTT1stDay + 123) -#define ActPlyMchStd (ActChgCrsTT1stDay + 124) -#define ActRefMchStd (ActChgCrsTT1stDay + 125) -#define ActAnsMchQstStd (ActChgCrsTT1stDay + 126) -#define ActFrmNewGam (ActChgCrsTT1stDay + 127) -#define ActEdiOneGam (ActChgCrsTT1stDay + 128) -#define ActNewGam (ActChgCrsTT1stDay + 129) -#define ActChgGam (ActChgCrsTT1stDay + 130) -#define ActReqRemGam (ActChgCrsTT1stDay + 131) -#define ActRemGam (ActChgCrsTT1stDay + 132) -#define ActReqRstGam (ActChgCrsTT1stDay + 133) -#define ActRstGam (ActChgCrsTT1stDay + 134) -#define ActHidGam (ActChgCrsTT1stDay + 135) -#define ActShoGam (ActChgCrsTT1stDay + 136) -#define ActAddOneGamQst (ActChgCrsTT1stDay + 137) -#define ActGamLstTstQst (ActChgCrsTT1stDay + 138) -#define ActAddTstQstToGam (ActChgCrsTT1stDay + 139) -#define ActReqRemGamQst (ActChgCrsTT1stDay + 140) -#define ActRemGamQst (ActChgCrsTT1stDay + 141) -#define ActUp_GamQst (ActChgCrsTT1stDay + 142) -#define ActDwnGamQst (ActChgCrsTT1stDay + 143) +#define ActFrmNewMchTch (ActChgCrsTT1stDay + 117) +#define ActReqRemMchTch (ActChgCrsTT1stDay + 118) +#define ActRemMchTch (ActChgCrsTT1stDay + 119) +#define ActNewMchTch (ActChgCrsTT1stDay + 120) +#define ActResMchTch (ActChgCrsTT1stDay + 121) +#define ActNxtMchTch (ActChgCrsTT1stDay + 122) +#define ActRefMchTch (ActChgCrsTT1stDay + 123) +#define ActShoMchTch (ActChgCrsTT1stDay + 124) +#define ActPlyMchStd (ActChgCrsTT1stDay + 125) +#define ActRefMchStd (ActChgCrsTT1stDay + 126) +#define ActAnsMchQstStd (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 ActSeeSvy (ActChgCrsTT1stDay + 144) -#define ActAnsSvy (ActChgCrsTT1stDay + 145) -#define ActFrmNewSvy (ActChgCrsTT1stDay + 146) -#define ActEdiOneSvy (ActChgCrsTT1stDay + 147) -#define ActNewSvy (ActChgCrsTT1stDay + 148) -#define ActChgSvy (ActChgCrsTT1stDay + 149) -#define ActReqRemSvy (ActChgCrsTT1stDay + 150) -#define ActRemSvy (ActChgCrsTT1stDay + 151) -#define ActReqRstSvy (ActChgCrsTT1stDay + 152) -#define ActRstSvy (ActChgCrsTT1stDay + 153) -#define ActHidSvy (ActChgCrsTT1stDay + 154) -#define ActShoSvy (ActChgCrsTT1stDay + 155) -#define ActEdiOneSvyQst (ActChgCrsTT1stDay + 156) -#define ActRcvSvyQst (ActChgCrsTT1stDay + 157) -#define ActReqRemSvyQst (ActChgCrsTT1stDay + 158) -#define ActRemSvyQst (ActChgCrsTT1stDay + 159) +#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 ActSeeOneExaAnn (ActChgCrsTT1stDay + 160) -#define ActSeeDatExaAnn (ActChgCrsTT1stDay + 161) -#define ActEdiExaAnn (ActChgCrsTT1stDay + 162) -#define ActRcvExaAnn (ActChgCrsTT1stDay + 163) -#define ActPrnExaAnn (ActChgCrsTT1stDay + 164) -#define ActReqRemExaAnn (ActChgCrsTT1stDay + 165) -#define ActRemExaAnn (ActChgCrsTT1stDay + 166) -#define ActHidExaAnn (ActChgCrsTT1stDay + 167) -#define ActShoExaAnn (ActChgCrsTT1stDay + 168) +#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) /*****************************************************************************/ /******************************** Files tab **********************************/ diff --git a/swad_changelog.h b/swad_changelog.h index d9f11caae..b1de0b621 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -458,11 +458,16 @@ En OpenSWAD: ps2pdf source.ps destination.pdf */ -#define Log_PLATFORM_VERSION "SWAD 18.132.3 (2019-07-15)" +#define Log_PLATFORM_VERSION "SWAD 18.133 (2019-07-16)" #define CSS_FILE "swad18.132.2.css" #define JS_FILE "swad18.130.2.js" /* -TODO: Poner cronómetro o algo que se vaya actualizando para ver que va cambiando la respuesta del estudiante + Version 18.133: Jul 16, 2019 Display number of players in a game. (243604 lines) + 3 changes necessary in database: +DROP TABLE IF EXISTS gam_players; +CREATE TABLE IF NOT EXISTS gam_players (MchCod INT NOT NULL,UsrCod INT NOT NULL,TS TIMESTAMP,UNIQUE INDEX(MchCod,UsrCod)); +INSERT INTO actions (ActCod,Language,Obsolete,Txt) VALUES ('1788','es','N','Refrescar partida (como profesor)'); + Version 18.132.3: Jul 15, 2019 Reception of student answer to a match question. (243470 lines) Version 18.132.2: Jul 15, 2019 Reception of student answer to a match question. Not finished. (243456 lines) Version 18.132.1: Jul 15, 2019 Reception of student answer to a match question. Not finished. (243405 lines) diff --git a/swad_config.h b/swad_config.h index 25c0346a1..a00767e37 100644 --- a/swad_config.h +++ b/swad_config.h @@ -502,7 +502,9 @@ #define Cfg_TIME_TO_REFRESH_TIMELINE ((time_t)( 2UL * 1000UL)) // Initial refresh period of social timeline in miliseconds // This delay is increased 1 second on each refresh -#define Cfg_TIME_TO_REFRESH_GAME ((time_t)( 1UL * 1000UL)) // Refresh period of game being played in miliseconds + +#define Cfg_SECONDS_TO_REFRESH_GAME 1 // Refresh period of game being played in seconds +#define Cfg_TIME_TO_REFRESH_GAME ((time_t)(Cfg_SECONDS_TO_REFRESH_GAME * 1000UL)) // Refresh period of game being played in miliseconds #define Cfg_TIME_TO_REFRESH_LAST_CLICKS ((time_t)( 1UL * 1000UL)) // Refresh period of last clicks in miliseconds diff --git a/swad_database.c b/swad_database.c index ac400dcc2..5c890ad74 100644 --- a/swad_database.c +++ b/swad_database.c @@ -1401,6 +1401,24 @@ mysql> DESCRIBE gam_matches; "UNIQUE INDEX(MchCod)," "INDEX(GamCod)"); + /***** Table gam_players *****/ +/* +mysql> DESCRIBE gam_players; ++--------+-----------+------+-----+-------------------+-----------------------------+ +| Field | Type | Null | Key | Default | Extra | ++--------+-----------+------+-----+-------------------+-----------------------------+ +| MchCod | int(11) | NO | PRI | NULL | | +| UsrCod | int(11) | NO | PRI | NULL | | +| TS | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | ++--------+-----------+------+-----+-------------------+-----------------------------+ +3 rows in set (0.00 sec) +*/ + DB_CreateTable ("CREATE TABLE IF NOT EXISTS gam_players (" + "MchCod INT NOT NULL," + "UsrCod INT NOT NULL," + "TS TIMESTAMP," + "UNIQUE INDEX(MchCod,UsrCod))"); + /***** Table gam_questions *****/ /* mysql> DESCRIBE gam_questions; diff --git a/swad_game.c b/swad_game.c index 15900d7fd..8883693f1 100644 --- a/swad_game.c +++ b/swad_game.c @@ -182,7 +182,7 @@ static void Gam_PutButtonNewMatch (long GamCod); static void Gam_PutFormNewMatch (struct Game *Game); -static void Gam_CreateMatch (struct Match *Match); +static long Gam_CreateMatch (long GamCod,char Title[Gam_MAX_BYTES_TITLE + 1]); static void Gam_UpdateMatchBeingPlayed (struct Match *Match); static void Gam_ShowMatchStatusForTch (struct Match *Match); @@ -190,6 +190,12 @@ static void Gam_ShowAlertFinishedMatch (void); static void Gam_PlayGameShowQuestionAndAnswers (struct Match *Match); static void Gam_PutBigButton (long MchCod,const char *Txt,const char *Icon); +static void Gam_RemoveOldPlayers (void); +static void Gam_RemoveAllPlayersInMatch (long MchCod); +static void Gam_RegisterMeAsPlayerInMatch (long MchCod); +static void Gam_GetAndShowNumPlayersInMatch (long MchCod); +static unsigned Gam_GetNumPlayers (long MchCod); + static void Gam_ShowMatchStatusForStd (struct Match *Match); static int Gam_GetQstAnsFromDB (long MchCod,unsigned QstInd); @@ -460,7 +466,7 @@ static void Gam_ShowOneGame (long GamCod, if (ShowOnlyThisGame) /* Icon to start a new match */ - Lay_PutContextualLinkOnlyIcon (ActFrmNewMch,Gam_NEW_MATCH_SECTION_ID, + Lay_PutContextualLinkOnlyIcon (ActFrmNewMchTch,Gam_NEW_MATCH_SECTION_ID, Gam_PutParams, "play.svg", Txt_New_match); @@ -2793,7 +2799,7 @@ static void Gam_PutIconToPlayNewMatch (void) extern const char *Txt_New_match; /***** Put form to create a new question *****/ - Ico_PutContextualIconToAdd (ActFrmNewMch,Gam_NEW_MATCH_SECTION_ID,Gam_PutParams, + Ico_PutContextualIconToAdd (ActFrmNewMchTch,Gam_NEW_MATCH_SECTION_ID,Gam_PutParams, Txt_New_match); } @@ -2863,7 +2869,7 @@ static void Gam_ListOneOrMoreMatches (struct Game *Game, "",Gbl.RowEvenOdd); /* Put icon to remove the match */ - Frm_StartForm (ActReqRemMch); + Frm_StartForm (ActReqRemMchTch); Gam_PutParamMatchCod (Match.MchCod); Ico_PutIconRemove (); Frm_EndForm (); @@ -2928,7 +2934,7 @@ static void Gam_ListOneOrMoreMatches (struct Game *Game, if (Match.Status.Finished) /* Icon to inform about finished match */ // Ico_PutIconOff ("flag-checkered.svg",Txt_Finished_match); - Lay_PutContextualLinkOnlyIcon (ActShoMch,NULL, + Lay_PutContextualLinkOnlyIcon (ActShoMchTch,NULL, Gam_PutParamCurrentMchCod, "flag-checkered.svg", Txt_View_game_results); @@ -2956,7 +2962,7 @@ static void Gam_ListOneOrMoreMatches (struct Game *Game, case Rol_SYS_ADM: /* Icon to resume */ Gam_CurrentMchCod = Match.MchCod; - Lay_PutContextualLinkOnlyIcon (ActResMch,NULL, + Lay_PutContextualLinkOnlyIcon (ActResMchTch,NULL, Gam_PutParamCurrentMchCod, "play.svg", Txt_Resume); @@ -3053,7 +3059,7 @@ static void Gam_GetMatchDataFromRow (MYSQL_RES *mysql_res, /************** Request the removal of a match (game instance) ***************/ /*****************************************************************************/ -void Gam_RequestRemoveMatch (void) +void Gam_RequestRemoveMatchTch (void) { extern const char *Txt_Do_you_really_want_to_remove_the_match_X; extern const char *Txt_Remove_match; @@ -3069,7 +3075,7 @@ void Gam_RequestRemoveMatch (void) /***** Show question and button to remove question *****/ Gam_CurrentMchCod = Match.MchCod; - Ale_ShowAlertAndButton (ActRemMch,NULL,NULL,Gam_PutParamCurrentMchCod, + Ale_ShowAlertAndButton (ActRemMchTch,NULL,NULL,Gam_PutParamCurrentMchCod, Btn_REMOVE_BUTTON,Txt_Remove_match, Ale_QUESTION,Txt_Do_you_really_want_to_remove_the_match_X, Match.Title); @@ -3085,7 +3091,7 @@ void Gam_RequestRemoveMatch (void) /********************** Remove a match (game instance) ***********************/ /*****************************************************************************/ -void Gam_RemoveMatch (void) +void Gam_RemoveMatchTch (void) { extern const char *Txt_Match_X_removed; struct Match Match; @@ -3136,7 +3142,7 @@ static void Gam_PutButtonNewMatch (long GamCod) { extern const char *Txt_New_match; - Frm_StartFormAnchor (ActFrmNewMch,Gam_NEW_MATCH_SECTION_ID); + Frm_StartFormAnchor (ActFrmNewMchTch,Gam_NEW_MATCH_SECTION_ID); Gam_PutParamGameCod (GamCod); Btn_PutConfirmButton (Txt_New_match); Frm_EndForm (); @@ -3146,7 +3152,7 @@ static void Gam_PutButtonNewMatch (long GamCod) /******************* Start playing a game as a teacher ***********************/ /*****************************************************************************/ -void Gam_RequestNewMatch (void) +void Gam_RequestNewMatchTch (void) { long GamCod; @@ -3182,7 +3188,7 @@ static void Gam_PutFormNewMatch (struct Game *Game) Lay_StartSection (Gam_NEW_MATCH_SECTION_ID); /***** Start form *****/ - Frm_StartForm (ActNewMch); + Frm_StartForm (ActNewMchTch); Gam_PutParamGameCod (Game->GamCod); Gam_PutParamQstInd (0); // Start by first question in game @@ -3233,82 +3239,106 @@ static void Gam_PutFormNewMatch (struct Game *Game) /********* Create a new match and show first question (by a teacher) *********/ /*****************************************************************************/ -void Gam_CreateNewMatch (void) +void Gam_CreateNewMatchTch1 (void) { - struct Match Match; + long GamCod; + char Title[Gam_MAX_BYTES_TITLE + 1]; /***** Get form parameters *****/ /* Get match code */ - if ((Match.GamCod = Gam_GetParamGameCod ()) == -1L) + if ((GamCod = Gam_GetParamGameCod ()) == -1L) Lay_ShowErrorAndExit ("Code of game is missing."); /* Get match title */ - Par_GetParToText ("Title",Match.Title,Gam_MAX_BYTES_TITLE); + Par_GetParToText ("Title",Title,Gam_MAX_BYTES_TITLE); /* Get groups for this games */ Grp_GetParCodsSeveralGrps (); /***** Create a new match *****/ - Gam_CreateMatch (&Match); + Gbl.Games.MchCodBeingPlayed = Gam_CreateMatch (GamCod,Title); /***** Free memory for list of selected groups *****/ Grp_FreeListCodSelectedGrps (); + } + +void Gam_CreateNewMatchTch2 (void) + { + struct Match Match; + + /***** Get data of the match from database *****/ + Match.MchCod = Gbl.Games.MchCodBeingPlayed; + Gam_GetDataOfMatchByCod (&Match); /***** Show current match status *****/ + fprintf (Gbl.F.Out,"
"); + + fprintf (Gbl.F.Out,"
"); + Gam_GetAndShowNumPlayersInMatch (Match.MchCod); + fprintf (Gbl.F.Out,"
"); + Gam_ShowMatchStatusForTch (&Match); + + fprintf (Gbl.F.Out,"
"); } /*****************************************************************************/ /********************** Create a new match in a game *************************/ /*****************************************************************************/ -static void Gam_CreateMatch (struct Match *Match) +static long Gam_CreateMatch (long GamCod,char Title[Gam_MAX_BYTES_TITLE + 1]) { - /***** Initialize new match *****/ - Match->UsrCod = Gbl.Usrs.Me.UsrDat.UsrCod; // Player (me) - Match->Status.QstInd = 0; // Match has not started, so not the first question yet - Match->Status.QstCod = -1L; // Non-existent question - Match->Status.ShowingAnswers = false; // Don't show answers initially - Match->Status.Finished = false; // Game finished + long MchCod; /***** Insert this new match into database *****/ - Match->MchCod = DB_QueryINSERTandReturnCode ("can not create match", - "INSERT gam_matches" - " (GamCod,UsrCod,StartTime,EndTime,Title," - "QstInd,QstCod,QstStartTime,ShowingAnswers,Finished)" - " VALUES" - " (%ld,%ld,NOW(),NOW(),'%s'," - "%u,%ld,NOW(),'%c','%c')", - Match->GamCod,Match->UsrCod,Match->Title, - Match->Status.QstInd,Match->Status.QstCod, - Match->Status.ShowingAnswers ? 'Y' : - 'N', - Match->Status.Finished ? 'Y' : - 'N'); + MchCod = DB_QueryINSERTandReturnCode ("can not create match", + "INSERT gam_matches" + " (GamCod,UsrCod,StartTime,EndTime,Title," + "QstInd,QstCod,QstStartTime,ShowingAnswers,Finished)" + " VALUES" + " (%ld," // GamCod + "%ld," // UsrCod + "NOW()," // StartTime + "NOW()," // EndTime + "'%s'," // Title + "0," // QstInd: Match has not started, so not the first question yet + "-1," // QstCod: Non-existent question + "NOW()," // QstStartTime + "'N'," // ShowingAnswers: Don't show answers initially + "'N')", // Finished: Game unfinished + GamCod, + Gbl.Usrs.Me.UsrDat.UsrCod, // Game creator + Title); /***** Create groups associated to the match *****/ if (Gbl.Crs.Grps.LstGrpsSel.NumGrps) - Gam_CreateGrps (Match->MchCod); + Gam_CreateGrps (MchCod); + + return MchCod; } /*****************************************************************************/ /**** Resume an unfinished match and show current question (by a teacher) ****/ /*****************************************************************************/ -void Gam_ResumeUnfinishedMatch (void) +void Gam_ResumeUnfinishedMatchTch (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 *****/ + Match.MchCod = Gbl.Games.MchCodBeingPlayed; Gam_GetDataOfMatchByCod (&Match); /***** Show current match status *****/ + fprintf (Gbl.F.Out,"
"); + + fprintf (Gbl.F.Out,"
"); + Gam_GetAndShowNumPlayersInMatch (Match.MchCod); + fprintf (Gbl.F.Out,"
"); + Gam_ShowMatchStatusForTch (&Match); + + fprintf (Gbl.F.Out,"
"); } /*****************************************************************************/ @@ -3341,17 +3371,13 @@ static void Gam_UpdateMatchBeingPlayed (struct Match *Match) /*** Show next match status (show next question, answers...) (by a teacher) **/ /*****************************************************************************/ -void Gam_NextStatusMatch (void) +void Gam_NextStatusMatchTch (void) { struct Match Match; long NxtQstInd; - /***** 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 *****/ + Match.MchCod = Gbl.Games.MchCodBeingPlayed; Gam_GetDataOfMatchByCod (&Match); /***** If not yet finished, update status *****/ @@ -3407,10 +3433,22 @@ void Gam_NextStatusMatch (void) /* Update match status in database */ Gam_UpdateMatchBeingPlayed (&Match); + + /* Remove all players in this match */ + if (Match.Status.Finished) + Gam_RemoveAllPlayersInMatch (Match.MchCod); } /***** Show current match status *****/ + fprintf (Gbl.F.Out,"
"); + + fprintf (Gbl.F.Out,"
"); + Gam_GetAndShowNumPlayersInMatch (Match.MchCod); + fprintf (Gbl.F.Out,"
"); + Gam_ShowMatchStatusForTch (&Match); + + fprintf (Gbl.F.Out,"
"); } /*****************************************************************************/ @@ -3419,18 +3457,12 @@ void Gam_NextStatusMatch (void) static void Gam_ShowMatchStatusForTch (struct Match *Match) { - /***** Start container for match status *****/ - fprintf (Gbl.F.Out,"
"); - /***** Show current match status *****/ if (Match->Status.Finished) Gam_ShowAlertFinishedMatch (); else // Unfinished match /***** Show current question and possible answers *****/ Gam_PlayGameShowQuestionAndAnswers (Match); - - /***** End container for match status *****/ - fprintf (Gbl.F.Out,"
"); } /*****************************************************************************/ @@ -3545,7 +3577,7 @@ static void Gam_PutBigButton (long MchCod,const char *Txt,const char *Icon) fprintf (Gbl.F.Out,"
"); /***** Start form *****/ - Frm_StartForm (ActNxtMch); + Frm_StartForm (ActNxtMchTch); Gam_PutParamMatchCod (MchCod); /***** Put icon with link *****/ @@ -3566,6 +3598,63 @@ static void Gam_PutBigButton (long MchCod,const char *Txt,const char *Icon) fprintf (Gbl.F.Out,"
"); } +/*****************************************************************************/ +/*********************** Get number of players in a match ********************/ +/*****************************************************************************/ + +static void Gam_RemoveOldPlayers (void) + { + /***** Remove players who have left matches *****/ + DB_QueryDELETE ("can not remove old match players", + "DELETE FROM gam_players" + " WHERE TS"); - - /***** Show current question *****/ Gam_ShowMatchStatusForStd (&Match); - - /***** End container for match status *****/ fprintf (Gbl.F.Out,""); } +/*****************************************************************************/ +/*************** Refresh current game for a teacher via AJAX *****************/ +/*****************************************************************************/ + +void Gam_RefreshCurrentMatchTch (void) + { + if (!Gbl.Session.IsOpen) // If session has been closed, do not write anything + return; + + /***** Get and show number of players *****/ + Gam_GetAndShowNumPlayersInMatch (Gbl.Games.MchCodBeingPlayed); + } + /*****************************************************************************/ /*************** Refresh current game for a student via AJAX *****************/ /*****************************************************************************/ @@ -3623,7 +3721,7 @@ void Gam_RefreshCurrentMatchStd (void) Match.MchCod = Gbl.Games.MchCodBeingPlayed; Gam_GetDataOfMatchByCod (&Match); - /***** Show current question *****/ + /***** Show current match status *****/ Gam_ShowMatchStatusForStd (&Match); } @@ -3654,11 +3752,17 @@ static void Gam_ShowMatchStatusForStd (struct Match *Match) Gam_ShowAlertFinishedMatch (); else // Unfinished match { + /***** Update players ******/ + Gam_RemoveOldPlayers (); + Gam_RegisterMeAsPlayerInMatch (Match->MchCod); + if (Match->Status.QstInd == 0) // Not yet started { - fprintf (Gbl.F.Out,"" + "\"Please", + " class=\"GAM_PLAY_STD_WAIT_IMAGE\" />" + "", Cfg_URL_ICON_PUBLIC, "Por favor, espere a que el juego comience..."); // TODO: Need translation!!!!! } @@ -3847,13 +3951,9 @@ void Gam_ReceiveQstAnsFromStd (void) Match.MchCod,Gbl.Usrs.Me.UsrDat.UsrCod,QstInd,StdAnsInd); } - /***** Start container for match status *****/ + /***** Show current match status *****/ fprintf (Gbl.F.Out,"
"); - - /***** Show current question *****/ Gam_ShowMatchStatusForStd (&Match); - - /***** End container for match status *****/ fprintf (Gbl.F.Out,"
"); } diff --git a/swad_game.h b/swad_game.h index d1d0abcdf..b57b5eb43 100644 --- a/swad_game.h +++ b/swad_game.h @@ -116,23 +116,25 @@ void Gam_RemoveQst (void); void Gam_MoveUpQst (void); void Gam_MoveDownQst (void); -void Gam_RequestRemoveMatch (void); -void Gam_RemoveMatch (void); +void Gam_RequestRemoveMatchTch (void); +void Gam_RemoveMatchTch (void); -void Gam_RequestNewMatch (void); -// void Gam_PlayMatchStd (void); +void Gam_RequestNewMatchTch (void); -void Gam_ReceiveQstAnsFromStd (void); -void Gam_CreateNewMatch (void); -void Gam_ResumeUnfinishedMatch (void); -void Gam_NextStatusMatch (void); +void Gam_CreateNewMatchTch1 (void); +void Gam_CreateNewMatchTch2 (void); +void Gam_ResumeUnfinishedMatchTch (void); +void Gam_NextStatusMatchTch (void); void Gam_ShowFinishedMatchResults (void); void Gam_GetMatchBeingPlayed (void); void Gam_ShowMatchToMeAsStd (void); +void Gam_RefreshCurrentMatchTch (void); void Gam_RefreshCurrentMatchStd (void); +void Gam_ReceiveQstAnsFromStd (void); + unsigned Gam_GetNumCoursesWithGames (Hie_Level_t Scope); unsigned Gam_GetNumGames (Hie_Level_t Scope); float Gam_GetNumQstsPerCrsGame (Hie_Level_t Scope); diff --git a/swad_layout.c b/swad_layout.c index 3ea5dc33c..50f46f833 100644 --- a/swad_layout.c +++ b/swad_layout.c @@ -682,6 +682,9 @@ static void Lay_WriteScriptInit (void) case ActRemSocComGbl: RefreshNewTimeline = true; break; + case ActNewMchTch: + case ActResMchTch: + case ActNxtMchTch: case ActPlyMchStd: case ActAnsMchQstStd: RefreshGame = true; @@ -797,13 +800,21 @@ static void Lay_WriteScriptParamsAJAX (void) Act_GetActCod (ActRefOldSocPubUsr), Gbl.Usrs.Other.UsrDat.EncryptedUsrCod); break; - /* Parameters related with game refreshing */ + /* Parameters related with match refreshing */ + case ActNewMchTch: + case ActResMchTch: + case ActNxtMchTch: + fprintf (Gbl.F.Out,"var RefreshParamNxtActGam = \"act=%ld\";\n" + "var RefreshParamMchCod = \"MchCod=%ld\";\n", + Act_GetActCod (ActRefMchTch), + Gbl.Games.MchCodBeingPlayed); + break; case ActPlyMchStd: case ActAnsMchQstStd: fprintf (Gbl.F.Out,"var RefreshParamNxtActGam = \"act=%ld\";\n" "var RefreshParamMchCod = \"MchCod=%ld\";\n", - Act_GetActCod (ActRefMchStd), - Gbl.Games.MchCodBeingPlayed); + Act_GetActCod (ActRefMchStd), + Gbl.Games.MchCodBeingPlayed); break; /* Parameter related with clicks refreshing */ case ActLstClk: