Version 16.251.6

This commit is contained in:
Antonio Cañas Vargas 2017-09-01 14:36:25 +02:00
parent da3a9ce439
commit b67b63f256
6 changed files with 186 additions and 109 deletions

View File

@ -238,13 +238,14 @@
/****************************** Public constants *****************************/ /****************************** Public constants *****************************/
/*****************************************************************************/ /*****************************************************************************/
#define Log_PLATFORM_VERSION "SWAD 16.251.5 (2017-09-01)" #define Log_PLATFORM_VERSION "SWAD 16.251.6 (2017-09-01)"
#define CSS_FILE "swad16.235.1.css" #define CSS_FILE "swad16.235.1.css"
#define JS_FILE "swad16.206.3.js" #define JS_FILE "swad16.206.3.js"
// Number of lines (includes comments but not blank lines) has been got with the following command: // Number of lines (includes comments but not blank lines) has been got with the following command:
// nl swad*.c swad*.h css/swad*.css py/swad*.py js/swad*.js soap/swad*?.h sql/swad*.sql | tail -1 // nl swad*.c swad*.h css/swad*.css py/swad*.py js/swad*.js soap/swad*?.h sql/swad*.sql | tail -1
/* /*
Version 16.251.6: Sep 01, 2017 Listing games for remote control. Not finished. (227111 lines)
Version 16.251.5: Sep 01, 2017 Listing games for remote control. Not finished. (227045 lines) Version 16.251.5: Sep 01, 2017 Listing games for remote control. Not finished. (227045 lines)
1 change necessary in database: 1 change necessary in database:
ALTER TABLE gam_answers DROP COLUMN Answer; ALTER TABLE gam_answers DROP COLUMN Answer;

View File

@ -716,8 +716,8 @@ struct Globals
unsigned Num; // Number of surveys unsigned Num; // Number of surveys
long *LstGamCods; // List of game codes long *LstGamCods; // List of game codes
Rmt_Order_t SelectedOrder; Rmt_Order_t SelectedOrder;
long GamCodToEdit; // Used as parameter in contextual links long CurrentGamCod; // Used as parameter in contextual links
long GamQstCodToEdit; // Used as parameter in contextual links long CurrentQstCod; // Used as parameter in contextual links
unsigned CurrentPage; unsigned CurrentPage;
char *ListQuestions; char *ListQuestions;
} Games; } Games;

View File

@ -138,10 +138,9 @@ static long Rmt_GetParamQstCod (void);
static void Rmt_RemAnswersOfAQuestion (long QstCod); static void Rmt_RemAnswersOfAQuestion (long QstCod);
static Rmt_AnswerType_t Rmt_ConvertFromStrAnsTypDBToAnsTyp (const char *StrAnsTypeBD); static Rmt_AnswerType_t Rmt_ConvertFromStrAnsTypDBToAnsTyp (const char *StrAnsTypeBD);
// static bool Rmt_CheckIfAnswerExists (long QstCod,unsigned AnsInd); // static bool Rmt_CheckIfAnswerExists (long QstCod,unsigned AnsInd);
static unsigned Rmt_GetAnswersQst (long QstCod,MYSQL_RES **mysql_res); // static bool Rmt_AllocateTextChoiceAnswer (struct GameQuestion *GameQst,unsigned NumAns);
static bool Rmt_AllocateTextChoiceAnswer (struct GameQuestion *GameQst,unsigned NumAns);
// static void Rmt_FreeTextChoiceAnswers (struct GameQuestion *GameQst,unsigned NumAnswers); // static void Rmt_FreeTextChoiceAnswers (struct GameQuestion *GameQst,unsigned NumAnswers);
static void Rmt_FreeTextChoiceAnswer (struct GameQuestion *GameQst,unsigned NumAns); // static void Rmt_FreeTextChoiceAnswer (struct GameQuestion *GameQst,unsigned NumAns);
static unsigned Rmt_GetQstIndFromQstCod (long QstCod); static unsigned Rmt_GetQstIndFromQstCod (long QstCod);
static unsigned Rmt_GetNextQuestionIndexInGame (long GamCod); static unsigned Rmt_GetNextQuestionIndexInGame (long GamCod);
@ -154,7 +153,8 @@ static void Rmt_FreeListsSelectedQuestions (void);
static unsigned Rmt_CountNumQuestionsInList (void); static unsigned Rmt_CountNumQuestionsInList (void);
static void Rmt_WriteQstStem (const char *Stem); static void Rmt_WriteQstStem (const char *Stem);
static void Rmt_WriteAnswersOfAQst (struct Game *Game,struct GameQuestion *GameQst,bool PutFormAnswerGame); static void Rmt_WriteAnswersOfAQst (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestions,
struct Game *Game,struct GameQuestion *GameQst);
static void Rmt_DrawBarNumUsrs (unsigned NumUsrs,unsigned MaxUsrs); static void Rmt_DrawBarNumUsrs (unsigned NumUsrs,unsigned MaxUsrs);
// static void Rmt_PutIconToRemoveOneQst (void); // static void Rmt_PutIconToRemoveOneQst (void);
@ -798,14 +798,14 @@ void Rmt_PutHiddenParamGameOrder (void)
} }
/*****************************************************************************/ /*****************************************************************************/
/******************* Put a link (form) to edit one game ********************/ /******************** Put a link (form) to edit one game *********************/
/*****************************************************************************/ /*****************************************************************************/
static void Rmt_PutFormsToRemEditOneGame (long GamCod,bool Visible) static void Rmt_PutFormsToRemEditOneGame (long GamCod,bool Visible)
{ {
extern const char *Txt_Reset; extern const char *Txt_Reset;
Gbl.Games.GamCodToEdit = GamCod; // Used as parameters in contextual links Gbl.Games.CurrentGamCod = GamCod; // Used as parameter in contextual links
/***** Put form to remove game *****/ /***** Put form to remove game *****/
Ico_PutContextualIconToRemove (ActReqRemGam,Rmt_PutParams); Ico_PutContextualIconToRemove (ActReqRemGam,Rmt_PutParams);
@ -832,8 +832,8 @@ static void Rmt_PutFormsToRemEditOneGame (long GamCod,bool Visible)
static void Rmt_PutParams (void) static void Rmt_PutParams (void)
{ {
if (Gbl.Games.GamCodToEdit > 0) if (Gbl.Games.CurrentGamCod > 0)
Rmt_PutParamGameCod (Gbl.Games.GamCodToEdit); Rmt_PutParamGameCod (Gbl.Games.CurrentGamCod);
Att_PutHiddenParamAttOrder (); Att_PutHiddenParamAttOrder ();
Grp_PutParamWhichGrps (); Grp_PutParamWhichGrps ();
Pag_PutHiddenParamPagNum (Pag_SURVEYS,Gbl.Games.CurrentPage); Pag_PutHiddenParamPagNum (Pag_SURVEYS,Gbl.Games.CurrentPage);
@ -1505,7 +1505,7 @@ void Rmt_AskRemGame (void)
Lay_ShowErrorAndExit ("You can not remove this game."); Lay_ShowErrorAndExit ("You can not remove this game.");
/***** Show question and button to remove game *****/ /***** Show question and button to remove game *****/
Gbl.Games.GamCodToEdit = Game.GamCod; Gbl.Games.CurrentGamCod = Game.GamCod;
sprintf (Gbl.Alert.Txt,Txt_Do_you_really_want_to_remove_the_game_X, sprintf (Gbl.Alert.Txt,Txt_Do_you_really_want_to_remove_the_game_X,
Game.Title); Game.Title);
Ale_ShowAlertAndButton (Ale_QUESTION,Gbl.Alert.Txt, Ale_ShowAlertAndButton (Ale_QUESTION,Gbl.Alert.Txt,
@ -1597,7 +1597,7 @@ void Rmt_AskResetGame (void)
Ale_ShowAlert (Ale_WARNING,Gbl.Alert.Txt); Ale_ShowAlert (Ale_WARNING,Gbl.Alert.Txt);
/***** Button of confirmation of reset *****/ /***** Button of confirmation of reset *****/
Gbl.Games.GamCodToEdit = Game.GamCod; Gbl.Games.CurrentGamCod = Game.GamCod;
Rmt_PutButtonToResetGame (); Rmt_PutButtonToResetGame ();
/***** Show games again *****/ /***** Show games again *****/
@ -1812,7 +1812,7 @@ void Rmt_RequestCreatOrEditGame (void)
} }
/***** Start form *****/ /***** Start form *****/
Gbl.Games.GamCodToEdit = Game.GamCod; Gbl.Games.CurrentGamCod = Game.GamCod;
Act_FormStart (ItsANewGame ? ActNewGam : Act_FormStart (ItsANewGame ? ActNewGam :
ActChgGam); ActChgGam);
Rmt_PutParams (); Rmt_PutParams ();
@ -2658,52 +2658,33 @@ static bool Rmt_CheckIfAnswerExists (long QstCod,unsigned AnsInd)
} }
*/ */
/*****************************************************************************/ /*****************************************************************************/
/************** Get answers of a game question from database ***************/ /**** Get number of users who selected a given answer of a game question *****/
/*****************************************************************************/ /*****************************************************************************/
static unsigned Rmt_GetAnswersQst (long QstCod,MYSQL_RES **mysql_res) unsigned Rmt_GetNumUsrsWhoAnswered (long GamCod,long QstCod,unsigned AnsInd)
{ {
char Query[1024]; char Query[128];
unsigned long NumRows; MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumUsrs = 0; // Default returned value
/***** Get answers of a question from database *****/ /***** Get answers of a question from database *****/
sprintf (Query,"SELECT AnsInd,NumUsrs,Answer FROM" sprintf (Query,"SELECT NumUsrs FROM gam_answers"
"(" " WHERE GamCod=%ld AND QstCod=%ld AND AnsInd=%u",
"SELECT tst_answers.AnsInd AS AnsInd," GamCod,QstCod,AnsInd);
"gam_answers.NumUsrs AS NumUsrs,tst_answers.Answer AS Answer" DB_QuerySELECT (Query,&mysql_res,"can not get number of users who answered");
" FROM tst_answers,gam_answers" row = mysql_fetch_row (mysql_res);
" WHERE tst_answers.QstCod=%ld" if (row[0]) // There are users who selected this answer
" AND gam_answers.QstCod=%ld" if (sscanf (row[0],"%u",&NumUsrs) != 1)
" AND tst_answers.QstCod=gam_answers.QstCod" Lay_ShowErrorAndExit ("Error when getting number of users who answered.");
" AND tst_answers.AnsInd=gam_answers.AnsInd"
" UNION "
"SELECT AnsInd,0 AS NumUsrs,Answer FROM tst_answers"
" WHERE QstCod=%ld"
" AND NOT EXISTS"
" (SELECT * FROM gam_answers"
" WHERE QstCod=%ld"
" AND tst_answers.QstCod=gam_answers.QstCod"
" AND tst_answers.AnsInd=gam_answers.AnsInd)"
") AS answers"
" ORDER BY AnsInd",
QstCod,QstCod,
QstCod,QstCod);
NumRows = DB_QuerySELECT (Query,mysql_res,"can not get answers of a question");
/***** Count number of rows of result *****/ return NumUsrs;
if (NumRows == 0)
{
Ale_ShowAlert (Ale_ERROR,"Error when getting answers of a question.");
Ale_ShowAlert (Ale_INFO,Query);
}
return (unsigned) NumRows;
} }
/*****************************************************************************/ /*****************************************************************************/
/******************* Allocate memory for a choice answer *********************/ /******************* Allocate memory for a choice answer *********************/
/*****************************************************************************/ /*****************************************************************************/
/*
static bool Rmt_AllocateTextChoiceAnswer (struct GameQuestion *GameQst,unsigned NumAns) static bool Rmt_AllocateTextChoiceAnswer (struct GameQuestion *GameQst,unsigned NumAns)
{ {
Rmt_FreeTextChoiceAnswer (GameQst,NumAns); Rmt_FreeTextChoiceAnswer (GameQst,NumAns);
@ -2715,7 +2696,7 @@ static bool Rmt_AllocateTextChoiceAnswer (struct GameQuestion *GameQst,unsigned
GameQst->AnsChoice[NumAns].Text[0] = '\0'; GameQst->AnsChoice[NumAns].Text[0] = '\0';
return true; return true;
} }
*/
/*****************************************************************************/ /*****************************************************************************/
/******************** Free memory of all choice answers **********************/ /******************** Free memory of all choice answers **********************/
/*****************************************************************************/ /*****************************************************************************/
@ -2733,7 +2714,7 @@ static void Rmt_FreeTextChoiceAnswers (struct GameQuestion *GameQst,unsigned Num
/*****************************************************************************/ /*****************************************************************************/
/********************** Free memory of a choice answer ***********************/ /********************** Free memory of a choice answer ***********************/
/*****************************************************************************/ /*****************************************************************************/
/*
static void Rmt_FreeTextChoiceAnswer (struct GameQuestion *GameQst,unsigned NumAns) static void Rmt_FreeTextChoiceAnswer (struct GameQuestion *GameQst,unsigned NumAns)
{ {
if (GameQst->AnsChoice[NumAns].Text) if (GameQst->AnsChoice[NumAns].Text)
@ -2742,7 +2723,7 @@ static void Rmt_FreeTextChoiceAnswer (struct GameQuestion *GameQst,unsigned NumA
GameQst->AnsChoice[NumAns].Text = NULL; GameQst->AnsChoice[NumAns].Text = NULL;
} }
} }
*/
/*****************************************************************************/ /*****************************************************************************/
/************************ Receive a question of a game ***********************/ /************************ Receive a question of a game ***********************/
/*****************************************************************************/ /*****************************************************************************/
@ -2955,12 +2936,10 @@ static unsigned Rmt_GetNextQuestionIndexInGame (long GamCod)
MYSQL_ROW row; MYSQL_ROW row;
unsigned QstInd = 0; unsigned QstInd = 0;
/***** Get number of games with a field value from database *****/ /***** Get maximum question index in a game from database *****/
sprintf (Query,"SELECT MAX(QstInd) FROM gam_questions WHERE GamCod=%ld", sprintf (Query,"SELECT MAX(QstInd) FROM gam_questions WHERE GamCod=%ld",
GamCod); GamCod);
DB_QuerySELECT (Query,&mysql_res,"can not get last question index"); DB_QuerySELECT (Query,&mysql_res,"can not get last question index");
/***** Get number of users *****/
row = mysql_fetch_row (mysql_res); row = mysql_fetch_row (mysql_res);
if (row[0]) // There are questions if (row[0]) // There are questions
{ {
@ -2997,7 +2976,13 @@ static void Rmt_ListGameQuestions (struct Game *Game,struct GameQuestion *GameQs
unsigned NumQst; unsigned NumQst;
bool Editing = (Gbl.Action.Act == ActEdiOneGam || bool Editing = (Gbl.Action.Act == ActEdiOneGam ||
Gbl.Action.Act == ActEdiOneGamQst); Gbl.Action.Act == ActEdiOneGamQst);
bool PutFormAnswerGame = Game->Status.ICanAnswer && !Editing; Tst_ActionToDoWithQuestions_t ActionToDoWithQuestions;
/***** How to show the questions ******/
if (Game->Status.ICanAnswer && !Editing)
ActionToDoWithQuestions = Tst_SHOW_GAME_TO_ANSWER;
else
ActionToDoWithQuestions = Tst_SHOW_GAME_RESULT;
/***** Get data of questions from database *****/ /***** Get data of questions from database *****/
sprintf (Query,"SELECT gam_questions.QstCod,gam_questions.QstInd," sprintf (Query,"SELECT gam_questions.QstCod,gam_questions.QstInd,"
@ -3010,14 +2995,14 @@ static void Rmt_ListGameQuestions (struct Game *Game,struct GameQuestion *GameQs
NumQsts = (unsigned) DB_QuerySELECT (Query,&mysql_res,"can not get data of a question"); NumQsts = (unsigned) DB_QuerySELECT (Query,&mysql_res,"can not get data of a question");
/***** Start box *****/ /***** Start box *****/
Gbl.Games.GamCodToEdit = Game->GamCod; Gbl.Games.CurrentGamCod = Game->GamCod;
Box_StartBox (NULL,Txt_Questions,Game->Status.ICanEdit ? Rmt_PutIconToAddNewQuestions : Box_StartBox (NULL,Txt_Questions,Game->Status.ICanEdit ? Rmt_PutIconToAddNewQuestions :
NULL, NULL,
Hlp_ASSESSMENT_Games_questions,Box_NOT_CLOSABLE); Hlp_ASSESSMENT_Games_questions,Box_NOT_CLOSABLE);
if (NumQsts) if (NumQsts)
{ {
if (PutFormAnswerGame) if (ActionToDoWithQuestions == Tst_SHOW_GAME_TO_ANSWER)
{ {
/***** Start form to send answers to game *****/ /***** Start form to send answers to game *****/
Act_FormStart (ActAnsGam); Act_FormStart (ActAnsGam);
@ -3104,14 +3089,14 @@ static void Rmt_ListGameQuestions (struct Game *Game,struct GameQuestion *GameQs
fprintf (Gbl.F.Out,"<td class=\"DAT LEFT_TOP COLOR%u\">", fprintf (Gbl.F.Out,"<td class=\"DAT LEFT_TOP COLOR%u\">",
Gbl.RowEvenOdd); Gbl.RowEvenOdd);
Rmt_WriteQstStem (row[3]); Rmt_WriteQstStem (row[3]);
Rmt_WriteAnswersOfAQst (Game,GameQst,PutFormAnswerGame); Rmt_WriteAnswersOfAQst (ActionToDoWithQuestions,Game,GameQst);
fprintf (Gbl.F.Out,"</td>" fprintf (Gbl.F.Out,"</td>"
"</tr>"); "</tr>");
} }
Tbl_EndTable (); Tbl_EndTable ();
if (PutFormAnswerGame) if (ActionToDoWithQuestions == Tst_SHOW_GAME_TO_ANSWER)
{ {
/***** Button to create/modify game *****/ /***** Button to create/modify game *****/
Btn_PutConfirmButton (Txt_Done); Btn_PutConfirmButton (Txt_Done);
@ -3302,25 +3287,85 @@ static void Rmt_WriteQstStem (const char *Stem)
/************** Get and write the answers of a game question ***************/ /************** Get and write the answers of a game question ***************/
/*****************************************************************************/ /*****************************************************************************/
static void Rmt_WriteAnswersOfAQst (struct Game *Game,struct GameQuestion *GameQst,bool PutFormAnswerGame) static void Rmt_WriteAnswersOfAQst (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestions,
struct Game *Game,struct GameQuestion *GameQst)
{ {
extern const char *Txt_Question_removed;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
double ScoreThisQst;
bool AnswerIsNotBlank;
/***** Query database *****/
if (Tst_GetOneQuestionByCod (GameQst->QstCod,&mysql_res)) // Question exists
{
/***** Get row of the result of the query *****/
row = mysql_fetch_row (mysql_res);
/*
row[ 0] QstCod
row[ 1] UNIX_TIMESTAMP(EditTime)
row[ 2] AnsType
row[ 3] Shuffle
row[ 4] Stem
row[ 5] Feedback
row[ 6] ImageName
row[ 7] ImageTitle
row[ 8] ImageURL
row[ 9] NumHits
row[10] NumHitsNotBlank
row[11] Score
*/
/***** Write question and answers *****/
Gbl.Games.CurrentGamCod = Game->GamCod;
Tst_WriteQstAndAnsTest (ActionToDoWithQuestions,
GameQst->QstInd,GameQst->QstCod,row,
&ScoreThisQst,&AnswerIsNotBlank);
}
else
/***** Question does not exists *****/
fprintf (Gbl.F.Out,"<tr>"
"<td class=\"TEST_NUM_QST RIGHT_TOP COLOR%u\">"
"%u"
"</td>"
"<td class=\"DAT_LIGHT LEFT_TOP COLOR%u\">"
"%s"
"</td>"
"</tr>",
Gbl.RowEvenOdd,GameQst->QstInd + 1,
Gbl.RowEvenOdd,Txt_Question_removed);
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
/*
unsigned NumAnswers; unsigned NumAnswers;
unsigned NumAns; unsigned NumAns;
MYSQL_RES *mysql_res; MYSQL_RES *mysql_res;
MYSQL_ROW row; MYSQL_ROW row;
unsigned NumUsrsThisAnswer; unsigned NumUsrsThisAnswer;
/***** Get answers of this question *****/ ***** Get answers of this question *****
NumAnswers = Rmt_GetAnswersQst (GameQst->QstCod,&mysql_res); // Result: AnsInd,NumUsrs,Answer NumAnswers = Rmt_GetNumUsrsWhoAnswered (GameQst->QstCod,&mysql_res); // Result: AnsInd,NumUsrs,Answer
/***** Write the answers *****/ ***** Write the answers *****
if (NumAnswers) if (NumAnswers)
{ {
/* Check number of answers */ * Check number of answers *
if (NumAnswers > Rmt_MAX_ANSWERS_PER_QUESTION) if (NumAnswers > Rmt_MAX_ANSWERS_PER_QUESTION)
Lay_ShowErrorAndExit ("Wrong number of answers."); Lay_ShowErrorAndExit ("Wrong number of answers.");
/* Write one row for each answer */ * Write one row for each answer *
Tbl_StartTable (5); Tbl_StartTable (5);
for (NumAns = 0; for (NumAns = 0;
NumAns < NumAnswers; NumAns < NumAnswers;
@ -3328,11 +3373,11 @@ static void Rmt_WriteAnswersOfAQst (struct Game *Game,struct GameQuestion *GameQ
{ {
row = mysql_fetch_row (mysql_res); row = mysql_fetch_row (mysql_res);
/* Get number of users who have marked this answer (row[1]) */ * Get number of users who have marked this answer (row[1]) *
if (sscanf (row[1],"%u",&NumUsrsThisAnswer) != 1) if (sscanf (row[1],"%u",&NumUsrsThisAnswer) != 1)
Lay_ShowErrorAndExit ("Error when getting number of users who have marked an answer."); Lay_ShowErrorAndExit ("Error when getting number of users who have marked an answer.");
/* Convert the answer (row[2]), that is in HTML, to rigorous HTML */ * Convert the answer (row[2]), that is in HTML, to rigorous HTML *
if (!Rmt_AllocateTextChoiceAnswer (GameQst,NumAns)) if (!Rmt_AllocateTextChoiceAnswer (GameQst,NumAns))
Lay_ShowErrorAndExit (Gbl.Alert.Txt); Lay_ShowErrorAndExit (Gbl.Alert.Txt);
Str_Copy (GameQst->AnsChoice[NumAns].Text,row[2], Str_Copy (GameQst->AnsChoice[NumAns].Text,row[2],
@ -3340,12 +3385,12 @@ static void Rmt_WriteAnswersOfAQst (struct Game *Game,struct GameQuestion *GameQ
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML, Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
GameQst->AnsChoice[NumAns].Text,Rmt_MAX_BYTES_ANSWER,false); GameQst->AnsChoice[NumAns].Text,Rmt_MAX_BYTES_ANSWER,false);
/* Selectors and label with the letter of the answer */ * Selectors and label with the letter of the answer *
fprintf (Gbl.F.Out,"<tr>"); fprintf (Gbl.F.Out,"<tr>");
if (PutFormAnswerGame) if (PutFormAnswerGame)
{ {
/* Write selector to choice this answer */ * Write selector to choice this answer *
fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP\">" fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP\">"
"<input type=\""); "<input type=\"");
if (GameQst->AnswerType == Rmt_ANS_UNIQUE_CHOICE) if (GameQst->AnswerType == Rmt_ANS_UNIQUE_CHOICE)
@ -3361,7 +3406,7 @@ static void Rmt_WriteAnswersOfAQst (struct Game *Game,struct GameQuestion *GameQ
NumAns); NumAns);
} }
/* Write the number of option */ * Write the number of option *
fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP\" style=\"width:50px;\">" fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP\" style=\"width:50px;\">"
"<label for=\"Ans%010u_%010u\" class=\"DAT\">" "<label for=\"Ans%010u_%010u\" class=\"DAT\">"
"%u)" "%u)"
@ -3369,27 +3414,28 @@ static void Rmt_WriteAnswersOfAQst (struct Game *Game,struct GameQuestion *GameQ
"</td>", "</td>",
(unsigned) GameQst->QstCod,NumAns,NumAns + 1); (unsigned) GameQst->QstCod,NumAns,NumAns + 1);
/* Write the text of the answer */ * Write the text of the answer *
fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP\">" fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP\">"
"<label for=\"Ans%010u_%010u\" class=\"DAT\">%s</label>" "<label for=\"Ans%010u_%010u\" class=\"DAT\">%s</label>"
"</td>", "</td>",
(unsigned) GameQst->QstCod,NumAns, (unsigned) GameQst->QstCod,NumAns,
GameQst->AnsChoice[NumAns].Text); GameQst->AnsChoice[NumAns].Text);
/* Show stats of this answer */ * Show stats of this answer *
if (Game->Status.ICanViewResults) if (Game->Status.ICanViewResults)
Rmt_DrawBarNumUsrs (NumUsrsThisAnswer,Game->NumUsrs); Rmt_DrawBarNumUsrs (NumUsrsThisAnswer,Game->NumUsrs);
fprintf (Gbl.F.Out,"</tr>"); fprintf (Gbl.F.Out,"</tr>");
/* Free memory allocated for the answer */ * Free memory allocated for the answer *
Rmt_FreeTextChoiceAnswer (GameQst,NumAns); Rmt_FreeTextChoiceAnswer (GameQst,NumAns);
} }
Tbl_EndTable (); Tbl_EndTable ();
} }
/***** Free structure that stores the query result *****/ ***** Free structure that stores the query result *****
DB_FreeMySQLResult (&mysql_res); DB_FreeMySQLResult (&mysql_res);
*/
} }
/*****************************************************************************/ /*****************************************************************************/
@ -3452,8 +3498,8 @@ static void Rmt_PutIconToRemoveOneQst (void)
static void Rmt_PutParamsRemoveOneQst (void) static void Rmt_PutParamsRemoveOneQst (void)
{ {
Rmt_PutParamGameCod (Gbl.Games.GamCodToEdit); Rmt_PutParamGameCod (Gbl.Games.CurrentGamCod);
Rmt_PutParamQstCod (Gbl.Games.GamQstCodToEdit); Rmt_PutParamQstCod (Gbl.Games.CurrentQstCod);
} }
/*****************************************************************************/ /*****************************************************************************/
@ -3480,8 +3526,8 @@ void Rmt_RequestRemoveQst (void)
GameQst.QstInd = Rmt_GetQstIndFromQstCod (GameQst.QstCod); GameQst.QstInd = Rmt_GetQstIndFromQstCod (GameQst.QstCod);
/***** Show question and button to remove question *****/ /***** Show question and button to remove question *****/
Gbl.Games.GamCodToEdit = Game.GamCod; Gbl.Games.CurrentGamCod = Game.GamCod;
Gbl.Games.GamQstCodToEdit = GameQst.QstCod; Gbl.Games.CurrentQstCod = GameQst.QstCod;
sprintf (Gbl.Alert.Txt,Txt_Do_you_really_want_to_remove_the_question_X, sprintf (Gbl.Alert.Txt,Txt_Do_you_really_want_to_remove_the_question_X,
(unsigned long) (GameQst.QstInd + 1)); (unsigned long) (GameQst.QstInd + 1));
Ale_ShowAlertAndButton (Ale_QUESTION,Gbl.Alert.Txt, Ale_ShowAlertAndButton (Ale_QUESTION,Gbl.Alert.Txt,

View File

@ -113,6 +113,8 @@ void Rmt_RemoveGames (Sco_Scope_t Scope,long Cod);
void Rmt_RequestEditQuestion (void); void Rmt_RequestEditQuestion (void);
// void Rmt_ReceiveQst (void); // void Rmt_ReceiveQst (void);
unsigned Rmt_GetNumUsrsWhoAnswered (long GamCod,long QstCod,unsigned AnsInd);
void Rmt_AddTstQuestionsToGame (void); void Rmt_AddTstQuestionsToGame (void);
void Rmt_RequestRemoveQst (void); void Rmt_RequestRemoveQst (void);

View File

@ -130,13 +130,6 @@ typedef enum
Tst_STATUS_ERROR = 2, Tst_STATUS_ERROR = 2,
} Tst_Status_t; } Tst_Status_t;
typedef enum
{
Tst_SHOW_QUESTIONS,
Tst_EDIT_QUESTIONS,
Tst_SELECT_QUESTIONS_FOR_GAME,
} Tst_ActionToDoWithQuestions_t;
/*****************************************************************************/ /*****************************************************************************/
/************** External global variables from others modules ****************/ /************** External global variables from others modules ****************/
/*****************************************************************************/ /*****************************************************************************/
@ -161,8 +154,6 @@ static Tst_Status_t Tst_GetTstStatus (unsigned NumTst);
static unsigned Tst_GetNumAccessesTst (void); static unsigned Tst_GetNumAccessesTst (void);
static void Tst_ShowTestQuestionsWhenSeeing (MYSQL_RES *mysql_res); static void Tst_ShowTestQuestionsWhenSeeing (MYSQL_RES *mysql_res);
static void Tst_ShowTestResultAfterAssess (long TstCod,unsigned *NumQstsNotBlank,double *TotalScore); static void Tst_ShowTestResultAfterAssess (long TstCod,unsigned *NumQstsNotBlank,double *TotalScore);
static void Tst_WriteQstAndAnsTest (unsigned NumQst,long QstCod,MYSQL_ROW row,
double *ScoreThisQst,bool *AnswerIsNotBlank);
static void Tst_PutFormToEditQstImage (struct Image *Image,int NumImgInForm, static void Tst_PutFormToEditQstImage (struct Image *Image,int NumImgInForm,
const char *ClassContainer, const char *ClassContainer,
const char *ClassImg, const char *ClassImg,
@ -193,7 +184,6 @@ static void Tst_ShowFormAnswerTypes (unsigned NumCols);
static unsigned long Tst_GetQuestions (MYSQL_RES **mysql_res); static unsigned long Tst_GetQuestions (MYSQL_RES **mysql_res);
static unsigned long Tst_GetQuestionsForTest (MYSQL_RES **mysql_res); static unsigned long Tst_GetQuestionsForTest (MYSQL_RES **mysql_res);
static void Tst_ListOneQstToEdit (void); static void Tst_ListOneQstToEdit (void);
static bool Tst_GetOneQuestionByCod (long QstCod,MYSQL_RES **mysql_res);
static void Tst_ListOneOrMoreQuestionsForEdition (unsigned long NumRows, static void Tst_ListOneOrMoreQuestionsForEdition (unsigned long NumRows,
MYSQL_RES *mysql_res); MYSQL_RES *mysql_res);
static void Tst_ListOneOrMoreQuestionsForSelection (long GamCod, static void Tst_ListOneOrMoreQuestionsForSelection (long GamCod,
@ -429,7 +419,7 @@ void Tst_ShowNewTest (void)
if (Tst_CheckIfNextTstAllowed ()) if (Tst_CheckIfNextTstAllowed ())
{ {
/***** Check that all parameters used to generate a test are valid *****/ /***** Check that all parameters used to generate a test are valid *****/
if (Tst_GetParamsTst (Tst_SHOW_QUESTIONS)) // Get parameters from form if (Tst_GetParamsTst (Tst_SHOW_TST_TO_ANSWER)) // Get parameters from form
{ {
/***** Get questions *****/ /***** Get questions *****/
if ((NumRows = Tst_GetQuestionsForTest (&mysql_res)) == 0) // Query database if ((NumRows = Tst_GetQuestionsForTest (&mysql_res)) == 0) // Query database
@ -835,7 +825,8 @@ static void Tst_ShowTestQuestionsWhenSeeing (MYSQL_RES *mysql_res)
if ((QstCod = Str_ConvertStrCodToLongCod (row[0])) < 0) if ((QstCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
Lay_ShowErrorAndExit ("Wrong code of question."); Lay_ShowErrorAndExit ("Wrong code of question.");
Tst_WriteQstAndAnsTest (NumQst,QstCod,row, Tst_WriteQstAndAnsTest (Tst_SHOW_TST_TO_ANSWER,
NumQst,QstCod,row,
&ScoreThisQst, // Not used here &ScoreThisQst, // Not used here
&AnswerIsNotBlank); // Not used here &AnswerIsNotBlank); // Not used here
} }
@ -935,7 +926,8 @@ static void Tst_ShowTestResultAfterAssess (long TstCod,unsigned *NumQstsNotBlank
Lay_ShowErrorAndExit ("Wrong code of question."); Lay_ShowErrorAndExit ("Wrong code of question.");
/***** Write question and answers *****/ /***** Write question and answers *****/
Tst_WriteQstAndAnsTest (NumQst,QstCod,row, Tst_WriteQstAndAnsTest (Tst_SHOW_TST_RESULT,
NumQst,QstCod,row,
&ScoreThisQst,&AnswerIsNotBlank); &ScoreThisQst,&AnswerIsNotBlank);
/***** Store test result question in database *****/ /***** Store test result question in database *****/
@ -974,8 +966,9 @@ static void Tst_ShowTestResultAfterAssess (long TstCod,unsigned *NumQstsNotBlank
/********** Write a row of a test, with one question and its answer **********/ /********** Write a row of a test, with one question and its answer **********/
/*****************************************************************************/ /*****************************************************************************/
static void Tst_WriteQstAndAnsTest (unsigned NumQst,long QstCod,MYSQL_ROW row, void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestions,
double *ScoreThisQst,bool *AnswerIsNotBlank) unsigned NumQst,long QstCod,MYSQL_ROW row,
double *ScoreThisQst,bool *AnswerIsNotBlank)
{ {
extern const char *Txt_TST_STR_ANSWER_TYPES[Tst_NUM_ANS_TYPES]; extern const char *Txt_TST_STR_ANSWER_TYPES[Tst_NUM_ANS_TYPES];
/* /*
@ -1020,15 +1013,30 @@ static void Tst_WriteQstAndAnsTest (unsigned NumQst,long QstCod,MYSQL_ROW row,
"TEST_IMG_SHOW_STEM_CONTAINER", "TEST_IMG_SHOW_STEM_CONTAINER",
"TEST_IMG_SHOW_STEM"); "TEST_IMG_SHOW_STEM");
if (Gbl.Action.Act == ActSeeTst) switch (ActionToDoWithQuestions)
Tst_WriteAnswersOfAQstViewTest (NumQst,QstCod,(row[3][0] == 'Y'));
else // Assessing test / Viewing old test result
{ {
Tst_WriteAnswersOfAQstAssessTest (NumQst,QstCod,ScoreThisQst,AnswerIsNotBlank); case Tst_SHOW_TST_TO_ANSWER:
Tst_WriteAnswersOfAQstViewTest (NumQst,QstCod,(row[3][0] == 'Y'));
break;
case Tst_SHOW_TST_RESULT:
Tst_WriteAnswersOfAQstAssessTest (NumQst,QstCod,ScoreThisQst,AnswerIsNotBlank);
/* Write question feedback (row[5]) */ /* Write question feedback (row[5]) */
if (Gbl.Test.Config.FeedbackType == Tst_FEEDBACK_FULL_FEEDBACK) if (Gbl.Test.Config.FeedbackType == Tst_FEEDBACK_FULL_FEEDBACK)
Tst_WriteQstFeedback (row[5],"TEST_EXA_LIGHT"); Tst_WriteQstFeedback (row[5],"TEST_EXA_LIGHT");
break;
case Tst_EDIT_TST:
break;
case Tst_SELECT_QUESTIONS_FOR_GAME:
break;
case Tst_SHOW_GAME_TO_ANSWER:
// TODO: Change this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Tst_WriteAnswersOfAQstViewTest (NumQst,QstCod,(row[3][0] == 'Y'));
break;
case Tst_SHOW_GAME_RESULT:
// TODO: Change this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Tst_WriteAnswersOfAQstAssessTest (NumQst,QstCod,ScoreThisQst,AnswerIsNotBlank);
break;
} }
fprintf (Gbl.F.Out,"</td>" fprintf (Gbl.F.Out,"</td>"
"</tr>"); "</tr>");
@ -2382,7 +2390,7 @@ void Tst_ListQuestionsToEdit (void)
unsigned long NumRows; unsigned long NumRows;
/***** Get parameters, query the database and list the questions *****/ /***** Get parameters, query the database and list the questions *****/
if (Tst_GetParamsTst (Tst_EDIT_QUESTIONS)) // Get parameters from the form if (Tst_GetParamsTst (Tst_EDIT_TST)) // Get parameters from the form
{ {
if ((NumRows = Tst_GetQuestions (&mysql_res)) != 0) // Query database if ((NumRows = Tst_GetQuestions (&mysql_res)) != 0) // Query database
{ {
@ -2764,7 +2772,7 @@ static void Tst_ListOneQstToEdit (void)
/*****************************************************************************/ /*****************************************************************************/
// Return true on success, false on error // Return true on success, false on error
static bool Tst_GetOneQuestionByCod (long QstCod,MYSQL_RES **mysql_res) bool Tst_GetOneQuestionByCod (long QstCod,MYSQL_RES **mysql_res)
{ {
char Query[512]; char Query[512];
@ -4592,8 +4600,8 @@ static bool Tst_GetParamsTst (Tst_ActionToDoWithQuestions_t ActionToDoWithQuesti
/***** Types of answer *****/ /***** Types of answer *****/
switch (ActionToDoWithQuestions) switch (ActionToDoWithQuestions)
{ {
case Tst_SHOW_QUESTIONS: case Tst_SHOW_TST_TO_ANSWER:
case Tst_EDIT_QUESTIONS: case Tst_EDIT_TST:
/* Get parameter that indicates if all types of answer are selected */ /* Get parameter that indicates if all types of answer are selected */
Gbl.Test.AllAnsTypes = Par_GetParToBool ("AllAnsTypes"); Gbl.Test.AllAnsTypes = Par_GetParToBool ("AllAnsTypes");
@ -4612,12 +4620,14 @@ static bool Tst_GetParamsTst (Tst_ActionToDoWithQuestions_t ActionToDoWithQuesti
Gbl.Test.AllAnsTypes = false; Gbl.Test.AllAnsTypes = false;
sprintf (Gbl.Test.ListAnsTypes,"%u",(unsigned) Tst_ANS_UNIQUE_CHOICE); sprintf (Gbl.Test.ListAnsTypes,"%u",(unsigned) Tst_ANS_UNIQUE_CHOICE);
break; break;
default:
break;
} }
/***** Get other parameters, depending on action *****/ /***** Get other parameters, depending on action *****/
switch (ActionToDoWithQuestions) switch (ActionToDoWithQuestions)
{ {
case Tst_SHOW_QUESTIONS: case Tst_SHOW_TST_TO_ANSWER:
Tst_GetParamNumQst (); Tst_GetParamNumQst ();
if (Gbl.Test.NumQsts < Gbl.Test.Config.Min || if (Gbl.Test.NumQsts < Gbl.Test.Config.Min ||
Gbl.Test.NumQsts > Gbl.Test.Config.Max) Gbl.Test.NumQsts > Gbl.Test.Config.Max)
@ -4628,7 +4638,7 @@ static bool Tst_GetParamsTst (Tst_ActionToDoWithQuestions_t ActionToDoWithQuesti
Error = true; Error = true;
} }
break; break;
case Tst_EDIT_QUESTIONS: case Tst_EDIT_TST:
/* Get starting and ending dates */ /* Get starting and ending dates */
Dat_GetIniEndDatesFromForm (); Dat_GetIniEndDatesFromForm ();
@ -4650,6 +4660,8 @@ static bool Tst_GetParamsTst (Tst_ActionToDoWithQuestions_t ActionToDoWithQuesti
/* Order question by stem */ /* Order question by stem */
Gbl.Test.SelectedOrder = Tst_ORDER_STEM; Gbl.Test.SelectedOrder = Tst_ORDER_STEM;
break; break;
default:
break;
} }
return !Error; return !Error;
@ -6178,7 +6190,7 @@ void Tst_RequestRemoveQst (void)
/* Get other parameters */ /* Get other parameters */
if (!EditingOnlyThisQst) if (!EditingOnlyThisQst)
if (!Tst_GetParamsTst (Tst_EDIT_QUESTIONS)) if (!Tst_GetParamsTst (Tst_EDIT_TST))
Lay_ShowErrorAndExit ("Wrong test parameters."); Lay_ShowErrorAndExit ("Wrong test parameters.");
/***** Show question and button to remove question *****/ /***** Show question and button to remove question *****/
@ -8188,7 +8200,8 @@ static void Tst_ShowTestResult (time_t TstTimeUTC)
Lay_ShowErrorAndExit ("Wrong code of question."); Lay_ShowErrorAndExit ("Wrong code of question.");
/***** Write questions and answers *****/ /***** Write questions and answers *****/
Tst_WriteQstAndAnsTest (NumQst,QstCod,row, Tst_WriteQstAndAnsTest (Tst_SHOW_TST_RESULT,
NumQst,QstCod,row,
&ScoreThisQst, // Not used here &ScoreThisQst, // Not used here
&AnswerIsNotBlank); // Not used here &AnswerIsNotBlank); // Not used here
} }

View File

@ -67,6 +67,16 @@ typedef enum
Tst_PLUGGABLE_YES = 2, Tst_PLUGGABLE_YES = 2,
} Tst_Pluggable_t; } Tst_Pluggable_t;
typedef enum
{
Tst_SHOW_TST_TO_ANSWER, // Showing a test to a student
Tst_SHOW_TST_RESULT, // Showing the assessment of a test
Tst_EDIT_TST, // Editing test questions
Tst_SELECT_QUESTIONS_FOR_GAME, // Selecting test questions for a game
Tst_SHOW_GAME_TO_ANSWER, // Showing a game to a student
Tst_SHOW_GAME_RESULT, // Showing the assessment of a game
} Tst_ActionToDoWithQuestions_t;
#define Tst_NUM_TYPES_FEEDBACK 5 #define Tst_NUM_TYPES_FEEDBACK 5
typedef enum typedef enum
{ {
@ -131,6 +141,10 @@ struct Tst_Stats
void Tst_ShowFormAskTst (void); void Tst_ShowFormAskTst (void);
void Tst_ShowNewTest (void); void Tst_ShowNewTest (void);
void Tst_AssessTest (void); void Tst_AssessTest (void);
void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestions,
unsigned NumQst,long QstCod,MYSQL_ROW row,
double *ScoreThisQst,bool *AnswerIsNotBlank);
void Tst_WriteQstStem (const char *Stem,const char *ClassStem); void Tst_WriteQstStem (const char *Stem,const char *ClassStem);
void Tst_WriteQstFeedback (const char *Feedback,const char *ClassFeedback); void Tst_WriteQstFeedback (const char *Feedback,const char *ClassFeedback);
@ -139,6 +153,7 @@ void Tst_ShowFormAskEditTsts (void);
void Tst_ShowFormAskSelectTstsForGame (long GamCod); void Tst_ShowFormAskSelectTstsForGame (long GamCod);
void Tst_ListQuestionsToEdit (void); void Tst_ListQuestionsToEdit (void);
void Tst_ListQuestionsToSelect (void); void Tst_ListQuestionsToSelect (void);
bool Tst_GetOneQuestionByCod (long QstCod,MYSQL_RES **mysql_res);
void Tst_WriteParamEditQst (void); void Tst_WriteParamEditQst (void);
unsigned Tst_GetAnswersQst (long QstCod,MYSQL_RES **mysql_res,bool Shuffle); unsigned Tst_GetAnswersQst (long QstCod,MYSQL_RES **mysql_res,bool Shuffle);
void Tst_WriteAnsTF (char AnsTF); void Tst_WriteAnsTF (char AnsTF);