Version19.89

This commit is contained in:
Antonio Cañas Vargas 2019-12-10 21:52:22 +01:00
parent 5137e9f5a9
commit 05db22eb5e
10 changed files with 223 additions and 174 deletions

View File

@ -13097,7 +13097,7 @@ SELECT projects.PrjCod,COUNT(prj_usr.UsrCod) AS NumStds FROM projects LEFT JOIN
SELECT COUNT(*) FROM tst_answers,gam_questions WHERE gam_questions.GamCod=6 AND gam_questions.QstCod=tst_answers.QstCod;
SELECT MIN(QstInd) FROM gam_questions WHERE GamCod=47 AND QstInd>5;

View File

@ -639,7 +639,7 @@ CREATE TABLE IF NOT EXISTS mch_matches (
Title VARCHAR(2047) NOT NULL,
QstInd INT NOT NULL DEFAULT 0,
QstCod INT NOT NULL DEFAULT -1,
Showing ENUM('nothing','stem','answers','results') NOT NULL DEFAULT 'nothing',
Showing ENUM('start','stem','answers','results','end') NOT NULL DEFAULT 'start',
NumCols INT NOT NULL DEFAULT 1,
ShowQstResults ENUM('N','Y') NOT NULL DEFAULT 'N',
ShowUsrResults ENUM('N','Y') NOT NULL DEFAULT 'N',

View File

@ -4811,9 +4811,9 @@ int swad__getMatchStatus (struct soap *soap,
"Type of answer not valid in a game.");
/***** Join match *****/
getMatchStatusOut->matchCode = 0; // == 0 ==> wait
if (Match.Status.Playing && // Match is being played
Match.Status.QstInd < Mch_AFTER_LAST_QUESTION) // Unfinished
getMatchStatusOut->matchCode = 0; // == 0 ==> wait
if (Match.Status.Playing && // Match is being played
Match.Status.Showing != Mch_END) // Unfinished
/* Update players */
getMatchStatusOut->matchCode = Mch_RegisterMeAsPlayerInMatch (&Match) ? matchCode : // > 0 ==> OK
-1; // < 0 ==> can not join this match

View File

@ -2166,7 +2166,7 @@ const struct Act_Actions Act_Actions[Act_NUM_ACTIONS] =
[ActJoiMch ] = {1780,-1,TabUnk,ActSeeAllGam ,0x008, 0, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_NEW_TAB,Mch_GetMatchBeingPlayed ,Mch_JoinMatchAsStd ,NULL},
[ActSeeMchAnsQstStd ] = {1808,-1,TabUnk,ActSeeAllGam ,0x008, 0, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_2ND_TAB,Mch_GetMatchBeingPlayed ,Mch_JoinMatchAsStd ,NULL},
[ActRemMchAnsQstStd ] = {1809,-1,TabUnk,ActSeeAllGam ,0x008, 0, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_2ND_TAB,Mch_GetMatchBeingPlayed ,Mch_RemoveQuestionAnswer ,NULL},
[ActRemMchAnsQstStd ] = {1809,-1,TabUnk,ActSeeAllGam ,0x008, 0, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_2ND_TAB,Mch_GetMatchBeingPlayed ,Mch_RemoveMyQuestionAnswer ,NULL},
[ActAnsMchQstStd ] = {1651,-1,TabUnk,ActSeeAllGam ,0x008, 0, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_2ND_TAB,Mch_GetMatchBeingPlayed ,Mch_ReceiveQuestionAnswer ,NULL},
[ActRefMchStd ] = {1782,-1,TabUnk,ActSeeAllGam ,0x008, 0, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_AJAX_RFRESH,Mch_GetMatchBeingPlayed ,Mch_RefreshMatchStd ,NULL},

View File

@ -490,13 +490,19 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - *
En OpenSWAD:
ps2pdf source.ps destination.pdf
*/
#define Log_PLATFORM_VERSION "SWAD 19.88.11 (2019-12-10)"
#define Log_PLATFORM_VERSION "SWAD 19.89 (2019-12-10)"
#define CSS_FILE "swad19.88.5.css"
#define JS_FILE "swad19.70.js"
/*
// TODO: Hacer un nuevo rol en los TFG: tutor externo (profesor de áreas no vinculadas con el centro, profesionales de empresas, etc.)
// TODO: Impedir la creación y edición de proyectos si no son editables.
// TODO: ¿Poner en color rojo las fechas de los juegos que tengan todas las partidas terminadas?
Version 19.89: Dec 10, 2019 Game dates are in red colour if all their matches are finished or ot don't have matches. (248186 lines)
4 changes necessary in database:
ALTER TABLE mch_matches CHANGE COLUMN Showing Showing ENUM('nothing','stem','answers','results','start','end') NOT NULL DEFAULT 'nothing';
UPDATE mch_matches SET Showing='start' WHERE QstInd='0' AND Showing='nothing';
UPDATE mch_matches SET Showing='end' WHERE QstInd='2147483647' AND Showing='nothing';
ALTER TABLE mch_matches CHANGE COLUMN Showing Showing ENUM('start','stem','answers','results','end') NOT NULL DEFAULT 'start';
Version 19.88.11: Dec 10, 2019 Fixed bug in selection of groups. (248141 lines)
Version 19.88.10: Dec 10, 2019 Fixed bug in matches results. (248145 lines)

View File

@ -1372,23 +1372,23 @@ mysql> DESCRIBE mch_groups;
/***** Table mch_matches *****/
/*
mysql> DESCRIBE mch_matches;
+----------------+--------------------------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------------------------------------+------+-----+---------+----------------+
| MchCod | int(11) | NO | PRI | NULL | auto_increment |
| GamCod | int(11) | NO | MUL | NULL | |
| UsrCod | int(11) | NO | | NULL | |
| StartTime | datetime | NO | | NULL | |
| EndTime | datetime | NO | | NULL | |
| Title | varchar(2047) | NO | | NULL | |
| QstInd | int(11) | NO | | 0 | |
| QstCod | int(11) | NO | | -1 | |
| Showing | enum('nothing','stem','answers','results') | NO | | nothing | |
| NumCols | int(11) | NO | | 1 | |
| ShowQstResults | enum('N','Y') | NO | | N | |
| ShowUsrResults | enum('N','Y') | NO | | N | |
+----------------+--------------------------------------------+------+-----+---------+----------------+
12 rows in set (0.01 sec)
+----------------+------------------------------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+------------------------------------------------+------+-----+---------+----------------+
| MchCod | int(11) | NO | PRI | NULL | auto_increment |
| GamCod | int(11) | NO | MUL | NULL | |
| UsrCod | int(11) | NO | | NULL | |
| StartTime | datetime | NO | | NULL | |
| EndTime | datetime | NO | | NULL | |
| Title | varchar(2047) | NO | | NULL | |
| QstInd | int(11) | NO | | 0 | |
| QstCod | int(11) | NO | | -1 | |
| Showing | enum('start','stem','answers','results','end') | NO | | start | |
| NumCols | int(11) | NO | | 1 | |
| ShowQstResults | enum('N','Y') | NO | | N | |
| ShowUsrResults | enum('N','Y') | NO | | N | |
+----------------+------------------------------------------------+------+-----+---------+----------------+
12 rows in set (0.00 sec)
*/
DB_CreateTable ("CREATE TABLE IF NOT EXISTS mch_matches ("
"MchCod INT NOT NULL AUTO_INCREMENT,"
@ -1399,7 +1399,7 @@ mysql> DESCRIBE mch_matches;
"Title VARCHAR(2047) NOT NULL," // Gam_MAX_BYTES_TITLE
"QstInd INT NOT NULL DEFAULT 0,"
"QstCod INT NOT NULL DEFAULT -1,"
"Showing ENUM('nothing','stem','answers','results') NOT NULL DEFAULT 'nothing',"
"Showing ENUM('start','stem','answers','results','end') NOT NULL DEFAULT 'start',"
"NumCols INT NOT NULL DEFAULT 1,"
"ShowQstResults ENUM('N','Y') NOT NULL DEFAULT 'N',"
"ShowUsrResults ENUM('N','Y') NOT NULL DEFAULT 'N',"

View File

@ -160,7 +160,7 @@ static void Gam_PutParamsOneQst (void);
static void Gam_ExchangeQuestions (long GamCod,
unsigned QstIndTop,unsigned QstIndBottom);
static bool Gam_GetNumMchsGameAndCheckIfEditable (struct Game *Game);
static bool Gam_CheckIfEditable (const struct Game *Game);
static long Gam_GetCurrentGamCod (void);
@ -251,8 +251,8 @@ static void Gam_ListAllGames (void)
HTM_TR_End ();
/***** Write all the games *****/
for (NumGame = Pagination.FirstItemVisible;
/***** Write all games *****/
for (NumGame = Pagination.FirstItemVisible;
NumGame <= Pagination.LastItemVisible;
NumGame++)
{
@ -442,6 +442,7 @@ static void Gam_ShowOneGame (struct Game *Game,bool ShowOnlyThisGame)
static unsigned UniqueId = 0;
char *Id;
Dat_StartEndTime_t StartEndTime;
const char *Color;
char Txt[Cns_MAX_BYTES_TEXT + 1];
/***** Set anchor string *****/
@ -470,21 +471,22 @@ static void Gam_ShowOneGame (struct Game *Game,bool ShowOnlyThisGame)
/***** Start/end date/time *****/
UniqueId++;
for (StartEndTime = (Dat_StartEndTime_t) 0;
for (StartEndTime = (Dat_StartEndTime_t) 0;
StartEndTime <= (Dat_StartEndTime_t) (Dat_NUM_START_END_TIME - 1);
StartEndTime++)
{
if (asprintf (&Id,"gam_date_%u_%u",(unsigned) StartEndTime,UniqueId) < 0)
Lay_NotEnoughMemoryExit ();
Color = Game->NumUnfinishedMchs ? (Game->Hidden ? "DATE_GREEN_LIGHT":
"DATE_GREEN") :
(Game->Hidden ? "DATE_RED_LIGHT":
"DATE_RED");
if (ShowOnlyThisGame)
HTM_TD_Begin ("id=\"%s\" class=\"%s LT\"",
Id,Game->Hidden ? "DATE_GREEN_LIGHT":
"DATE_GREEN");
Id,Color);
else
HTM_TD_Begin ("id=\"%s\" class=\"%s LT COLOR%u\"",
Id,Game->Hidden ? "DATE_GREEN_LIGHT":
"DATE_GREEN",
Gbl.RowEvenOdd);
Id,Color,Gbl.RowEvenOdd);
if (Game->TimeUTC[Dat_START_TIME])
Dat_WriteLocalDateHMSFromUTC (Id,Game->TimeUTC[StartEndTime],
Gbl.Prefs.DateFormat,Dat_SEPARATOR_BREAK,
@ -934,6 +936,9 @@ void Gam_GetDataOfGameByCod (struct Game *Game)
/* Get number of matches */
Game->NumMchs = Mch_GetNumMchsInGame (Game->GamCod);
/* Get number of unfinished matches */
Game->NumUnfinishedMchs = Mch_GetNumUnfinishedMchsInGame (Game->GamCod);
}
else
/* Initialize to empty game */
@ -989,6 +994,7 @@ static void Gam_ResetGame (struct Game *Game)
Game->Title[0] = '\0';
Game->NumQsts = 0;
Game->NumMchs = 0;
Game->NumUnfinishedMchs = 0;
Game->Hidden = false;
}
@ -1514,7 +1520,7 @@ void Gam_RequestNewQuestion (void)
Gam_GetDataOfGameByCod (&Game);
/***** Check if game has matches *****/
if (Gam_GetNumMchsGameAndCheckIfEditable (&Game))
if (Gam_CheckIfEditable (&Game))
{
/***** Show form to create a new question in this game *****/
Gam_SetCurrentGamCod (Game.GamCod); // Used to pass parameter
@ -1540,9 +1546,10 @@ void Gam_ListTstQuestionsToSelect (void)
/***** Get parameters *****/
if ((Game.GamCod = Gam_GetParams ()) == -1L)
Lay_ShowErrorAndExit ("Code of game is missing.");
Gam_GetDataOfGameByCod (&Game);
/***** Check if game has matches *****/
if (Gam_GetNumMchsGameAndCheckIfEditable (&Game))
if (Gam_CheckIfEditable (&Game))
{
/***** List several test questions for selection *****/
Gam_SetCurrentGamCod (Game.GamCod); // Used to pass parameter
@ -1683,9 +1690,10 @@ unsigned Gam_GetPrevQuestionIndexInGame (long GamCod,unsigned QstInd)
/***** Get previous question index (row[0]) *****/
row = mysql_fetch_row (mysql_res);
if (row[0])
if (sscanf (row[0],"%u",&PrevQstInd) != 1)
Lay_ShowErrorAndExit ("Error when getting previous question index.");
if (row)
if (row[0])
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);
@ -1716,9 +1724,10 @@ unsigned Gam_GetNextQuestionIndexInGame (long GamCod,unsigned QstInd)
/***** Get next question index (row[0]) *****/
row = mysql_fetch_row (mysql_res);
if (row[0])
if (sscanf (row[0],"%u",&NextQstInd) != 1)
Lay_ShowErrorAndExit ("Error when getting next question index.");
if (row)
if (row[0])
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);
@ -1737,7 +1746,7 @@ static void Gam_ListGameQuestions (struct Game *Game)
extern const char *Txt_This_game_has_no_questions;
MYSQL_RES *mysql_res;
unsigned NumQsts;
bool ICanEditQuestions = Gam_GetNumMchsGameAndCheckIfEditable (Game);
bool ICanEditQuestions = Gam_CheckIfEditable (Game);
/***** Get data of questions from database *****/
NumQsts = (unsigned) DB_QuerySELECT (&mysql_res,"can not get data of a question",
@ -1996,7 +2005,7 @@ void Gam_AddTstQuestionsToGame (void)
Gam_GetDataOfGameByCod (&Game);
/***** Check if game has matches *****/
if (Gam_GetNumMchsGameAndCheckIfEditable (&Game))
if (Gam_CheckIfEditable (&Game))
{
/***** Get selected questions *****/
/* Allocate space for selected question codes */
@ -2122,7 +2131,7 @@ void Gam_RequestRemoveQst (void)
Gam_GetDataOfGameByCod (&Game);
/***** Check if game has matches *****/
if (Gam_GetNumMchsGameAndCheckIfEditable (&Game))
if (Gam_CheckIfEditable (&Game))
{
/***** Get question index *****/
QstInd = Gam_GetParamQstInd ();
@ -2160,7 +2169,7 @@ void Gam_RemoveQst (void)
Gam_GetDataOfGameByCod (&Game);
/***** Check if game has matches *****/
if (Gam_GetNumMchsGameAndCheckIfEditable (&Game))
if (Gam_CheckIfEditable (&Game))
{
/***** Get question index *****/
QstInd = Gam_GetParamQstInd ();
@ -2220,7 +2229,7 @@ void Gam_MoveUpQst (void)
Gam_GetDataOfGameByCod (&Game);
/***** Check if game has matches *****/
if (Gam_GetNumMchsGameAndCheckIfEditable (&Game))
if (Gam_CheckIfEditable (&Game))
{
/***** Get question index *****/
QstIndBottom = Gam_GetParamQstInd ();
@ -2271,7 +2280,7 @@ void Gam_MoveDownQst (void)
Gam_GetDataOfGameByCod (&Game);
/***** Check if game has matches *****/
if (Gam_GetNumMchsGameAndCheckIfEditable (&Game))
if (Gam_CheckIfEditable (&Game))
{
/***** Get question index *****/
QstIndTop = Gam_GetParamQstInd ();
@ -2365,16 +2374,13 @@ static void Gam_ExchangeQuestions (long GamCod,
/*****************************************************************************/
/*********** Get number of matches and check is edition is possible **********/
/*****************************************************************************/
// Games with matches should not be edited
// Before calling this function, number of matches must be calculated
static bool Gam_GetNumMchsGameAndCheckIfEditable (struct Game *Game)
static bool Gam_CheckIfEditable (const struct Game *Game)
{
/***** Get number of matches *****/
Game->NumMchs = Mch_GetNumMchsInGame (Game->GamCod);
if (Gam_CheckIfICanEditGames ())
/***** Questions are editable only if game has no matches *****/
return (bool) (Game->NumMchs == 0);
return (bool) (Game->NumMchs == 0); // Games with matches should not be edited
else
return false; // Questions are not editable
}

View File

@ -45,17 +45,18 @@ struct GameSelected
struct Game
{
long GamCod; // Game code
long CrsCod; // Course code
long UsrCod; // Author code
double MaxGrade; // Score range [0...max.score]
// will be converted to
// grade range [0...max.grade]
long GamCod; // Game code
long CrsCod; // Course code
long UsrCod; // Author code
double MaxGrade; // Score range [0...max.score]
// will be converted to
// grade range [0...max.grade]
char Title[Gam_MAX_BYTES_TITLE + 1];
time_t TimeUTC[Dat_NUM_START_END_TIME];
bool Hidden; // Game is hidden
unsigned NumQsts; // Number of questions in the game
unsigned NumMchs; // Number of matches in the game
bool Hidden; // Game is hidden
unsigned NumQsts; // Number of questions in the game
unsigned NumMchs; // Number of matches in the game
unsigned NumUnfinishedMchs; // Number of unfinished matches in the game
};
#define Gam_NUM_ORDERS 3

View File

@ -77,10 +77,11 @@ typedef enum
const char *Mch_ShowingStringsDB[Mch_NUM_SHOWING] =
{
"nothing",
"stem",
"answers",
"results",
[Mch_START ] = "start",
[Mch_STEM ] = "stem",
[Mch_ANSWERS] = "answers",
[Mch_RESULTS] = "results",
[Mch_END ] = "end",
};
#define Mch_MAX_COLS 4
@ -205,7 +206,7 @@ static void Mch_SetMatchAsNotBeingPlayed (long MchCod);
static bool Mch_GetIfMatchIsBeingPlayed (long MchCod);
static void Mch_GetNumPlayers (struct Match *Match);
static void Mch_RemoveAnswerToMatchQuestion (const struct Match *Match);
static void Mch_RemoveMyAnswerToMatchQuestion (const struct Match *Match);
static double Mch_ComputeScore (unsigned NumQsts);
@ -357,7 +358,7 @@ void Mch_GetDataOfMatchByCod (struct Match *Match)
Match->Status.QstInd = 0;
Match->Status.QstCod = -1L;
Match->Status.QstStartTimeUTC = (time_t) 0;
Match->Status.Showing = Mch_STEM;
Match->Status.Showing = Mch_START;
Match->Status.Playing = false;
Match->Status.NumPlayers = 0;
Match->Status.NumCols = Mch_NUM_COLS_DEFAULT;
@ -576,8 +577,8 @@ static void Mch_ListOneOrMoreMatchesTimes (const struct Match *Match,unsigned Un
Lay_NotEnoughMemoryExit ();
HTM_TD_Begin ("id=\"%s\" class=\"%s LT COLOR%u\"",
Id,
Match->Status.QstInd >= Mch_AFTER_LAST_QUESTION ? "DATE_RED" :
"DATE_GREEN",
Match->Status.Showing == Mch_END ? "DATE_RED" :
"DATE_GREEN",
Gbl.RowEvenOdd);
Dat_WriteLocalDateHMSFromUTC (Id,Match->TimeUTC[StartEndTime],
Gbl.Prefs.DateFormat,Dat_SEPARATOR_BREAK,
@ -703,7 +704,7 @@ static void Mch_ListOneOrMoreMatchesStatus (const struct Match *Match,unsigned N
HTM_TD_Begin ("class=\"DAT CT COLOR%u\"",Gbl.RowEvenOdd);
if (Match->Status.QstInd < Mch_AFTER_LAST_QUESTION) // Unfinished match
if (Match->Status.Showing != Mch_END) // Match not over
{
/* Current question index / total of questions */
HTM_DIV_Begin ("class=\"DAT\"");
@ -717,8 +718,8 @@ static void Mch_ListOneOrMoreMatchesStatus (const struct Match *Match,unsigned N
ActResMch,
NULL,
Mch_PutParamsPlay,
Match->Status.QstInd < Mch_AFTER_LAST_QUESTION ? "play.svg" :
"flag-checkered.svg",
Match->Status.Showing == Mch_END ? "flag-checkered.svg" :
"play.svg",
Gbl.Usrs.Me.Role.Logged == Rol_STD ? Txt_Play :
Txt_Resume);
@ -915,9 +916,9 @@ static void Mch_GetMatchDataFromRow (MYSQL_RES *mysql_res,
Match->Status.ShowUsrResults = (row[11][0] == 'Y');
/***** Get whether the match is being played or not *****/
if (Match->Status.QstInd >= Mch_AFTER_LAST_QUESTION) // Finished
if (Match->Status.Showing == Mch_END) // Match over
Match->Status.Playing = false;
else // Unfinished
else // Match not over
Match->Status.Playing = Mch_GetIfMatchIsBeingPlayed (Match->MchCod);
}
@ -1680,8 +1681,8 @@ static void Mch_UpdateElapsedTimeInQuestion (const struct Match *Match)
{
/***** Update elapsed time in current question in database *****/
if (Match->Status.Playing && // Match is being played
Match->Status.QstInd > 0 &&
Match->Status.QstInd < Mch_AFTER_LAST_QUESTION)
Match->Status.Showing != Mch_START &&
Match->Status.Showing != Mch_END)
DB_QueryINSERT ("can not update elapsed time in question",
"INSERT INTO mch_times (MchCod,QstInd,ElapsedTime)"
" VALUES (%ld,%u,SEC_TO_TIME(%u))"
@ -1786,11 +1787,11 @@ void Mch_PlayPauseMatch (void)
/***** Update status *****/
if (Match.Status.Playing) // Match is being played ==> pause it
Match.Status.Playing = false; // Pause match
Match.Status.Playing = false; // Pause match
else // Match is paused, not being played ==> play it
/* If unfinished, update status */
if (Match.Status.QstInd < Mch_AFTER_LAST_QUESTION) // Unfinished
Match.Status.Playing = true; // Start/resume match
/* If not over, update status */
if (Match.Status.Showing != Mch_END) // Match not over
Match.Status.Playing = true; // Start/resume match
/***** Update match status in database *****/
Mch_UpdateMatchStatusInDB (&Match);
@ -1931,24 +1932,22 @@ void Mch_ForwardMatch (void)
static void Mch_SetMatchStatusToPrev (struct Match *Match)
{
/***** What to show *****/
if (Match->Status.QstInd == 0) // Start
Mch_SetMatchStatusToStart (Match);
else if (Match->Status.QstInd >= Mch_AFTER_LAST_QUESTION) // End
Mch_SetMatchStatusToPrevQst (Match);
else // Between start and end
switch (Match->Status.Showing)
{
case Mch_NOTHING:
case Mch_STEM:
Mch_SetMatchStatusToPrevQst (Match);
break;
case Mch_ANSWERS:
Match->Status.Showing = Mch_STEM;
break;
case Mch_RESULTS:
Match->Status.Showing = Mch_ANSWERS;
break;
}
switch (Match->Status.Showing)
{
case Mch_START:
Mch_SetMatchStatusToStart (Match);
break;
case Mch_STEM:
case Mch_END:
Mch_SetMatchStatusToPrevQst (Match);
break;
case Mch_ANSWERS:
Match->Status.Showing = Mch_STEM;
break;
case Mch_RESULTS:
Match->Status.Showing = Mch_ANSWERS;
break;
}
}
static void Mch_SetMatchStatusToPrevQst (struct Match *Match)
@ -1956,15 +1955,15 @@ static void Mch_SetMatchStatusToPrevQst (struct Match *Match)
/***** Get index of the previous question *****/
Match->Status.QstInd = Gam_GetPrevQuestionIndexInGame (Match->GamCod,
Match->Status.QstInd);
if (Match->Status.QstInd == 0) // Start of questions has been reached
Mch_SetMatchStatusToStart (Match);
else
if (Match->Status.QstInd) // Start of questions not reached
{
Match->Status.QstCod = Gam_GetQstCodFromQstInd (Match->GamCod,
Match->Status.QstInd);
Match->Status.Showing = Match->Status.ShowQstResults ? Mch_RESULTS :
Mch_ANSWERS;
}
else // Start of questions reached
Mch_SetMatchStatusToStart (Match);
}
static void Mch_SetMatchStatusToStart (struct Match *Match)
@ -1972,7 +1971,7 @@ static void Mch_SetMatchStatusToStart (struct Match *Match)
Match->Status.QstInd = 0; // Before first question
Match->Status.QstCod = -1L;
Match->Status.Playing = false;
Match->Status.Showing = Mch_NOTHING;
Match->Status.Showing = Mch_START;
}
/*****************************************************************************/
@ -1982,29 +1981,27 @@ static void Mch_SetMatchStatusToStart (struct Match *Match)
static void Mch_SetMatchStatusToNext (struct Match *Match)
{
/***** What to show *****/
if (Match->Status.QstInd == 0) // Start
Mch_SetMatchStatusToNextQst (Match);
else if (Match->Status.QstInd >= Mch_AFTER_LAST_QUESTION) // End
Mch_SetMatchStatusToEnd (Match);
else // Between start and end
switch (Match->Status.Showing)
{
case Mch_NOTHING:
Match->Status.Showing = Mch_STEM;
break;
case Mch_STEM:
Match->Status.Showing = Mch_ANSWERS;
break;
case Mch_ANSWERS:
if (Match->Status.ShowQstResults)
Match->Status.Showing = Mch_RESULTS;
else
Mch_SetMatchStatusToNextQst (Match);
break;
case Mch_RESULTS:
switch (Match->Status.Showing)
{
case Mch_START:
Mch_SetMatchStatusToNextQst (Match);
break;
case Mch_STEM:
Match->Status.Showing = Mch_ANSWERS;
break;
case Mch_ANSWERS:
if (Match->Status.ShowQstResults)
Match->Status.Showing = Mch_RESULTS;
else
Mch_SetMatchStatusToNextQst (Match);
break;
}
break;
case Mch_RESULTS:
Mch_SetMatchStatusToNextQst (Match);
break;
case Mch_END:
Mch_SetMatchStatusToEnd (Match);
break;
}
}
static void Mch_SetMatchStatusToNextQst (struct Match *Match)
@ -2014,14 +2011,14 @@ static void Mch_SetMatchStatusToNextQst (struct Match *Match)
Match->Status.QstInd);
/***** Get question code *****/
if (Match->Status.QstInd >= Mch_AFTER_LAST_QUESTION) // Finished
Mch_SetMatchStatusToEnd (Match);
else // Unfinished
if (Match->Status.QstInd < Mch_AFTER_LAST_QUESTION) // End of questions not reached
{
Match->Status.QstCod = Gam_GetQstCodFromQstInd (Match->GamCod,
Match->Status.QstInd);
Match->Status.Showing = Mch_STEM;
}
else // End of questions reached
Mch_SetMatchStatusToEnd (Match);
}
static void Mch_SetMatchStatusToEnd (struct Match *Match)
@ -2029,7 +2026,7 @@ static void Mch_SetMatchStatusToEnd (struct Match *Match)
Match->Status.QstInd = Mch_AFTER_LAST_QUESTION; // After last question
Match->Status.QstCod = -1L;
Match->Status.Playing = false;
Match->Status.Showing = Mch_NOTHING;
Match->Status.Showing = Mch_END;
}
/*****************************************************************************/
@ -2074,7 +2071,7 @@ static void Mch_ShowMatchStatusForStd (struct Match *Match,Mch_Update_t Update)
}
/*****************************************************************************/
/******************* Get number of questions of a game *********************/
/********************** Get number of matches in a game **********************/
/*****************************************************************************/
unsigned Mch_GetNumMchsInGame (long GamCod)
@ -2091,6 +2088,24 @@ unsigned Mch_GetNumMchsInGame (long GamCod)
GamCod);
}
/*****************************************************************************/
/*************** Get number of unfinished matches in a game ******************/
/*****************************************************************************/
unsigned Mch_GetNumUnfinishedMchsInGame (long GamCod)
{
/***** Trivial check *****/
if (GamCod < 0) // A non-existing game...
return 0; // ...has no matches
/***** Get number of matches in a game from database *****/
return
(unsigned) DB_QueryCOUNT ("can not get number of unfinished matches of a game",
"SELECT COUNT(*) FROM mch_matches"
" WHERE GamCod=%ld AND Showing<>'%s'",
GamCod,Mch_ShowingStringsDB[Mch_END]);
}
/*****************************************************************************/
/************ Check if I belong to any of the groups of a match **************/
/*****************************************************************************/
@ -2176,8 +2191,8 @@ static void Mch_ShowRefreshablePartTch (struct Match *Match)
/***** Write elapsed time in question *****/
HTM_DIV_Begin ("class=\"MCH_TIME_QST\"");
if (Match->Status.QstInd > 0 &&
Match->Status.QstInd < Mch_AFTER_LAST_QUESTION)
if (Match->Status.Showing != Mch_START &&
Match->Status.Showing != Mch_END)
{
Mch_GetElapsedTimeInQuestion (Match,&Time);
Dat_WriteHoursMinutesSeconds (&Time);
@ -2193,8 +2208,8 @@ static void Mch_ShowRefreshablePartTch (struct Match *Match)
HTM_Txt (Txt_MATCH_respond);
HTM_BR ();
HTM_STRONG_Begin ();
if (Match->Status.QstInd > 0 &&
Match->Status.QstInd < Mch_AFTER_LAST_QUESTION)
if (Match->Status.Showing != Mch_START &&
Match->Status.Showing != Mch_END)
HTM_Unsigned (NumAnswerersQst);
else
HTM_Hyphen ();
@ -2223,10 +2238,10 @@ static void Mch_ShowRightColumnTch (const struct Match *Match)
Mch_ShowMatchTitle (Match);
/***** Bottom row: current question and possible answers *****/
if (Match->Status.QstInd < Mch_AFTER_LAST_QUESTION) // Not finished
Mch_ShowQuestionAndAnswersTch (Match);
else // Finished
if (Match->Status.Showing == Mch_END) // Match over
Mch_ShowMatchScore (Match);
else // Match not over
Mch_ShowQuestionAndAnswersTch (Match);
/***** End right container *****/
HTM_DIV_End ();
@ -2251,8 +2266,8 @@ static void Mch_ShowLeftColumnStd (const struct Match *Match,
/***** Write number of question *****/
Mch_ShowNumQstInMatch (Match);
if (Match->Status.QstInd > 0 &&
Match->Status.QstInd < Mch_AFTER_LAST_QUESTION)
if (Match->Status.Showing != Mch_START &&
Match->Status.Showing != Mch_END)
{
/***** Write whether question is answered or not *****/
Mch_PutIfAnswered (Match,Answered);
@ -2285,9 +2300,11 @@ static void Mch_ShowRightColumnStd (struct Match *Match,
Mch_ShowMatchTitle (Match);
/***** Bottom row *****/
if (Match->Status.Playing) // Match is being played
if (Match->Status.Playing) // Match is being played
{
if (Match->Status.QstInd < Mch_AFTER_LAST_QUESTION) // Match not over
if (Match->Status.Showing == Mch_END) // Match over
Mch_ShowWaitImage (Txt_Please_wait_);
else // Match not over
{
HTM_DIV_Begin ("class=\"MCH_BOTTOM\"");
@ -2304,10 +2321,8 @@ static void Mch_ShowRightColumnStd (struct Match *Match,
HTM_DIV_End ();
}
else // Match over
Mch_ShowWaitImage (Txt_Please_wait_);
}
else // Match is not being played
else // Match is not being played
Mch_ShowWaitImage (Txt_Please_wait_);
/***** End right container *****/
@ -2325,12 +2340,18 @@ static void Mch_ShowNumQstInMatch (const struct Match *Match)
unsigned NumQsts = Gam_GetNumQstsGame (Match->GamCod);
HTM_DIV_Begin ("class=\"MCH_NUM_QST\"");
if (Match->Status.QstInd == 0) // Not started
HTM_Txt (Txt_MATCH_Start);
else if (Match->Status.QstInd >= Mch_AFTER_LAST_QUESTION) // Finished
HTM_Txt (Txt_MATCH_End);
else
HTM_TxtF ("%u/%u",Match->Status.QstInd,NumQsts);
switch (Match->Status.Showing)
{
case Mch_START: // Not started
HTM_Txt (Txt_MATCH_Start);
break;
case Mch_END: // Match over
HTM_Txt (Txt_MATCH_End);
break;
default:
HTM_TxtF ("%u/%u",Match->Status.QstInd,NumQsts);
break;
}
HTM_DIV_End ();
}
@ -2351,7 +2372,7 @@ static void Mch_PutMatchControlButtons (const struct Match *Match)
/***** Left button *****/
HTM_DIV_Begin ("class=\"MCH_BUTTON_LEFT_CONTAINER\"");
if (Match->Status.QstInd == 0)
if (Match->Status.Showing == Mch_START)
/* Put button to close browser tab */
Mch_PutBigButtonClose ();
else
@ -2368,23 +2389,31 @@ static void Mch_PutMatchControlButtons (const struct Match *Match)
Mch_ICON_PAUSE,Txt_Pause);
else // Match is paused, not being played
{
if (Match->Status.QstInd < Mch_AFTER_LAST_QUESTION) // Not finished
/* Put button to play match */
Mch_PutBigButton (ActPlyPauMch,"play_pause",Match->MchCod,
Mch_ICON_PLAY,Match->Status.QstInd == 0 ? Txt_Start :
Txt_Resume);
else // Finished
/* Put disabled button to play match */
Mch_PutBigButtonOff (Mch_ICON_PLAY);
switch (Match->Status.Showing)
{
case Mch_START: // Match just started, before first question
/* Put button to start playing match */
Mch_PutBigButton (ActPlyPauMch,"play_pause",Match->MchCod,
Mch_ICON_PLAY,Txt_Start);
break;
case Mch_END: // Match over
/* Put disabled button to play match */
Mch_PutBigButtonOff (Mch_ICON_PLAY);
break;
default:
/* Put button to resume match */
Mch_PutBigButton (ActPlyPauMch,"play_pause",Match->MchCod,
Mch_ICON_PLAY,Txt_Resume);
}
}
HTM_DIV_End ();
/***** Right button *****/
HTM_DIV_Begin ("class=\"MCH_BUTTON_RIGHT_CONTAINER\"");
if (Match->Status.QstInd >= Mch_AFTER_LAST_QUESTION) // Finished
if (Match->Status.Showing == Mch_END) // Match over
/* Put button to close browser tab */
Mch_PutBigButtonClose ();
else
else // Match not over
/* Put button to show answers */
Mch_PutBigButton (ActFwdMch,"forward",Match->MchCod,
Mch_ICON_NEXT,Txt_Go_forward);
@ -2584,8 +2613,8 @@ static void Mch_ShowQuestionAndAnswersTch (const struct Match *Match)
MYSQL_ROW row;
/***** Trivial check: question index should be correct *****/
if (Match->Status.QstInd == 0 ||
Match->Status.QstInd >= Mch_AFTER_LAST_QUESTION)
if (Match->Status.Showing == Mch_START ||
Match->Status.Showing == Mch_END)
return;
/***** Get data of question from database *****/
@ -2625,7 +2654,9 @@ static void Mch_ShowQuestionAndAnswersTch (const struct Match *Match)
/***** Write answers? *****/
switch (Match->Status.Showing)
{
case Mch_NOTHING:
case Mch_START:
/* Don't write anything */
break;
case Mch_STEM:
/* Don't write anything */
break;
@ -2644,6 +2675,9 @@ static void Mch_ShowQuestionAndAnswersTch (const struct Match *Match)
"MCH_TCH_ANS",
true); // Show result
break;
case Mch_END:
/* Don't write anything */
break;
}
HTM_DIV_End (); // Bottom
@ -3114,7 +3148,7 @@ bool Mch_RegisterMeAsPlayerInMatch (struct Match *Match)
return false;
/***** Trivial check: match must not be over *****/
if (Match->Status.QstInd >= Mch_AFTER_LAST_QUESTION) // Finished
if (Match->Status.Showing == Mch_END) // Match over
return false;
/***** Trivial check: only a student can join a match *****/
@ -3161,7 +3195,7 @@ void Mch_JoinMatchAsStd (void)
/****** Remove student's answer to a question and show match as student ******/
/*****************************************************************************/
void Mch_RemoveQuestionAnswer (void)
void Mch_RemoveMyQuestionAnswer (void)
{
struct Match Match;
unsigned QstInd;
@ -3179,7 +3213,7 @@ void Mch_RemoveQuestionAnswer (void)
Match.Status.Showing == Mch_ANSWERS && // Teacher's screen is showing answers
QstInd == Match.Status.QstInd) // Removing answer to the current question being played
/***** Remove answer to this question *****/
Mch_RemoveAnswerToMatchQuestion (&Match);
Mch_RemoveMyAnswerToMatchQuestion (&Match);
/***** Show current match status *****/
HTM_DIV_Begin ("id=\"match\" class=\"MCH_CONT\"");
@ -3392,7 +3426,7 @@ void Mch_ReceiveQuestionAnswer (void)
/********************* Remove answer to match question ***********************/
/*****************************************************************************/
static void Mch_RemoveAnswerToMatchQuestion (const struct Match *Match)
static void Mch_RemoveMyAnswerToMatchQuestion (const struct Match *Match)
{
DB_QueryDELETE ("can not remove your answer to the match question",
"DELETE FROM mch_answers"

View File

@ -37,15 +37,16 @@
#define Mch_AFTER_LAST_QUESTION ((unsigned)((1UL << 31) - 1)) // 2^31 - 1, don't change this number because it is used in database to indicate that a match is finished
#define Mch_NUM_SHOWING 4
#define Mch_NUM_SHOWING 5
typedef enum
{
Mch_NOTHING, // Don't show anything
Mch_START, // Start: don't show anything
Mch_STEM, // Showing only the question stem
Mch_ANSWERS, // Showing the question stem and the answers
Mch_RESULTS, // Showing the results
Mch_END, // End: don't show anything
} Mch_Showing_t;
#define Mch_SHOWING_DEFAULT Mch_NOTHING
#define Mch_SHOWING_DEFAULT Mch_START
struct Match
{
@ -109,13 +110,14 @@ void Mch_BackMatch (void);
void Mch_ForwardMatch (void);
unsigned Mch_GetNumMchsInGame (long GamCod);
unsigned Mch_GetNumUnfinishedMchsInGame (long GamCod);
bool Mch_CheckIfICanPlayThisMatchBasedOnGrps (const struct Match *Match);
bool Mch_RegisterMeAsPlayerInMatch (struct Match *Match);
void Mch_GetMatchBeingPlayed (void);
void Mch_JoinMatchAsStd (void);
void Mch_RemoveQuestionAnswer (void);
void Mch_RemoveMyQuestionAnswer (void);
void Mch_RefreshMatchTch (void);
void Mch_RefreshMatchStd (void);