Version 16.251.10

This commit is contained in:
Antonio Cañas Vargas 2017-09-06 23:17:52 +02:00
parent b1e722435d
commit 3964984d31
7 changed files with 70 additions and 471 deletions

View File

@ -587,10 +587,11 @@ CREATE TABLE IF NOT EXISTS games (
-- Table gam_answers: stores the answers to the games -- Table gam_answers: stores the answers to the games
-- --
CREATE TABLE IF NOT EXISTS gam_answers ( CREATE TABLE IF NOT EXISTS gam_answers (
GamCod INT NOT NULL,
QstCod INT NOT NULL, QstCod INT NOT NULL,
AnsInd TINYINT NOT NULL, AnsInd TINYINT NOT NULL,
NumUsrs INT NOT NULL DEFAULT 0, NumUsrs INT NOT NULL DEFAULT 0,
UNIQUE INDEX(QstCod,AnsInd)); UNIQUE INDEX(GamCod,QstCod,AnsInd));
-- --
-- Table gam_grp: stores the groups associated to each game -- Table gam_grp: stores the groups associated to each game
-- --

View File

@ -238,19 +238,24 @@
/****************************** Public constants *****************************/ /****************************** Public constants *****************************/
/*****************************************************************************/ /*****************************************************************************/
#define Log_PLATFORM_VERSION "SWAD 16.251.9 (2017-09-06)" #define Log_PLATFORM_VERSION "SWAD 16.251.10 (2017-09-06)"
#define CSS_FILE "swad16.251.8.css" #define CSS_FILE "swad16.251.8.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.10:Sep 06, 2017 Listing games for remote control. Not finished. (226913 lines)
2 changes necessary in database:
DROP TABLE IF EXISTS gam_answers;
CREATE TABLE IF NOT EXISTS gam_answers (GamCod INT NOT NULL,QstCod INT NOT NULL,AnsInd TINYINT NOT NULL,NumUsrs INT NOT NULL DEFAULT 0,UNIQUE INDEX(GamCod,QstCod,AnsInd));
Version 16.251.9: Sep 06, 2017 Listing games for remote control. Not finished. (227273 lines) Version 16.251.9: Sep 06, 2017 Listing games for remote control. Not finished. (227273 lines)
Version 16.251.8: Sep 06, 2017 Listing games for remote control. Not finished. (227211 lines) Version 16.251.8: Sep 06, 2017 Listing games for remote control. Not finished. (227211 lines)
Version 16.251.7: Sep 04, 2017 Listing games for remote control. Not finished. (227218 lines) Version 16.251.7: Sep 04, 2017 Listing games for remote control. Not finished. (227218 lines)
Version 16.251.6: Sep 01, 2017 Listing games for remote control. Not finished. (227111 lines) 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: 2 changes necessary in database:
ALTER TABLE gam_answers DROP COLUMN Answer; ALTER TABLE gam_answers DROP COLUMN Answer;
UPDATE actions SET Obsolete='Y' WHERE ActCod='1663'; UPDATE actions SET Obsolete='Y' WHERE ActCod='1663';

View File

@ -1278,17 +1278,19 @@ mysql> DESCRIBE gam_answers;
+---------+------------+------+-----+---------+-------+ +---------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra | | Field | Type | Null | Key | Default | Extra |
+---------+------------+------+-----+---------+-------+ +---------+------------+------+-----+---------+-------+
| GamCod | int(11) | NO | PRI | NULL | |
| QstCod | int(11) | NO | PRI | NULL | | | QstCod | int(11) | NO | PRI | NULL | |
| AnsInd | tinyint(4) | NO | PRI | NULL | | | AnsInd | tinyint(4) | NO | PRI | NULL | |
| NumUsrs | int(11) | NO | | 0 | | | NumUsrs | int(11) | NO | | 0 | |
+---------+------------+------+-----+---------+-------+ +---------+------------+------+-----+---------+-------+
3 rows in set (0,00 sec) 4 rows in set (0,00 sec)
*/ */
DB_CreateTable ("CREATE TABLE IF NOT EXISTS gam_answers (" DB_CreateTable ("CREATE TABLE IF NOT EXISTS gam_answers ("
"GamCod INT NOT NULL,"
"QstCod INT NOT NULL," "QstCod INT NOT NULL,"
"AnsInd TINYINT NOT NULL," "AnsInd TINYINT NOT NULL,"
"NumUsrs INT NOT NULL DEFAULT 0," "NumUsrs INT NOT NULL DEFAULT 0,"
"UNIQUE INDEX(QstCod,AnsInd))"); "UNIQUE INDEX(GamCod,QstCod,AnsInd))");
/***** Table gam_grp *****/ /***** Table gam_grp *****/
/* /*

View File

@ -136,11 +136,6 @@ static void Rmt_InitQst (struct GameQuestion *GameQst);
static void Rmt_PutParamQstCod (long QstCod); static void Rmt_PutParamQstCod (long QstCod);
static long Rmt_GetParamQstCod (void); 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 bool Rmt_CheckIfAnswerExists (long QstCod,unsigned AnsInd);
// static bool Rmt_AllocateTextChoiceAnswer (struct GameQuestion *GameQst,unsigned NumAns);
// static void Rmt_FreeTextChoiceAnswers (struct GameQuestion *GameQst,unsigned NumAnswers);
// 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);
@ -156,9 +151,7 @@ static void Rmt_AllocateListSelectedQuestions (void);
static void Rmt_FreeListsSelectedQuestions (void); static void Rmt_FreeListsSelectedQuestions (void);
static unsigned Rmt_CountNumQuestionsInList (void); static unsigned Rmt_CountNumQuestionsInList (void);
// static void Rmt_WriteQstStem (const char *Stem); static unsigned Rmt_GetNumUsrsWhoAnswered (long GamCod,long QstCod,unsigned AnsInd);
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);
@ -2629,273 +2622,6 @@ static void Rmt_RemAnswersOfAQuestion (long QstCod)
DB_QueryDELETE (Query,"can not remove the answers of a question"); DB_QueryDELETE (Query,"can not remove the answers of a question");
} }
/*****************************************************************************/
/*********** Convert a string with the answer type to answer type ************/
/*****************************************************************************/
/*
static Rmt_AnswerType_t Rmt_ConvertFromStrAnsTypDBToAnsTyp (const char *StrAnsTypeBD)
{
Rmt_AnswerType_t AnsType;
for (AnsType = (Rmt_AnswerType_t) 0;
AnsType < Rmt_NUM_ANS_TYPES;
AnsType++)
if (!strcmp (StrAnsTypeBD,Rmt_StrAnswerTypesDB[AnsType]))
return AnsType;
return (Rmt_AnswerType_t) 0;
}
*/
/*****************************************************************************/
/*********** Check if an answer of a question exists in database *************/
/*****************************************************************************/
/*
static bool Rmt_CheckIfAnswerExists (long QstCod,unsigned AnsInd)
{
char Query[256];
***** Get answers of a question from database *****
sprintf (Query,"SELECT COUNT(*) FROM gam_answers"
" WHERE QstCod=%ld AND AnsInd=%u",
QstCod,AnsInd);
return (DB_QueryCOUNT (Query,"can not check if an answer exists") != 0);
}
*/
/*****************************************************************************/
/**** Get number of users who selected a given answer of a game question *****/
/*****************************************************************************/
unsigned Rmt_GetNumUsrsWhoAnswered (long GamCod,long QstCod,unsigned AnsInd)
{
char Query[128];
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumUsrs = 0; // Default returned value
/***** Get answers of a question from database *****/
sprintf (Query,"SELECT NumUsrs FROM gam_answers"
" WHERE GamCod=%ld AND QstCod=%ld AND AnsInd=%u",
GamCod,QstCod,AnsInd);
DB_QuerySELECT (Query,&mysql_res,"can not get number of users who answered");
row = mysql_fetch_row (mysql_res);
if (row[0]) // There are users who selected this answer
if (sscanf (row[0],"%u",&NumUsrs) != 1)
Lay_ShowErrorAndExit ("Error when getting number of users who answered.");
return NumUsrs;
}
/*****************************************************************************/
/******************* Allocate memory for a choice answer *********************/
/*****************************************************************************/
/*
static bool Rmt_AllocateTextChoiceAnswer (struct GameQuestion *GameQst,unsigned NumAns)
{
Rmt_FreeTextChoiceAnswer (GameQst,NumAns);
if ((GameQst->AnsChoice[NumAns].Text = malloc (Rmt_MAX_BYTES_ANSWER + 1)) == NULL)
{
sprintf (Gbl.Alert.Txt,"Not enough memory to store answer.");
return false;
}
GameQst->AnsChoice[NumAns].Text[0] = '\0';
return true;
}
*/
/*****************************************************************************/
/******************** Free memory of all choice answers **********************/
/*****************************************************************************/
/*
static void Rmt_FreeTextChoiceAnswers (struct GameQuestion *GameQst,unsigned NumAnswers)
{
unsigned NumAns;
for (NumAns = 0;
NumAns < NumAnswers;
NumAns++)
Rmt_FreeTextChoiceAnswer (GameQst,NumAns);
}
*/
/*****************************************************************************/
/********************** Free memory of a choice answer ***********************/
/*****************************************************************************/
/*
static void Rmt_FreeTextChoiceAnswer (struct GameQuestion *GameQst,unsigned NumAns)
{
if (GameQst->AnsChoice[NumAns].Text)
{
free ((void *) GameQst->AnsChoice[NumAns].Text);
GameQst->AnsChoice[NumAns].Text = NULL;
}
}
*/
/*****************************************************************************/
/************************ Receive a question of a game ***********************/
/*****************************************************************************/
/*
void Rmt_ReceiveQst (void)
{
extern const char *Txt_You_must_type_the_stem_of_the_question;
extern const char *Txt_You_can_not_leave_empty_intermediate_answers;
extern const char *Txt_You_must_type_at_least_the_first_two_answers;
extern const char *Txt_The_game_has_been_modified;
char Txt[Cns_MAX_BYTES_TEXT + 1];
char Query[512 + Cns_MAX_BYTES_TEXT];
struct Game Game;
struct GameQuestion GameQst;
unsigned NumAns;
char AnsStr[8 + 10 + 1];
unsigned NumLastAns;
bool ThereIsEndOfAnswers;
bool Error = false;
***** Initialize new question to zero *****
Rmt_InitQst (&GameQst);
***** Get parameters from form *****
* Get game code *
if ((Game.GamCod = Rmt_GetParamGameCod ()) == -1L)
Lay_ShowErrorAndExit ("Code of game is missing.");
* Get question code *
GameQst.QstCod = Rmt_GetParamQstCod ();
* Get answer type *
GameQst.AnswerType = (Rmt_AnswerType_t)
Par_GetParToUnsignedLong ("AnswerType",
0,
Rmt_NUM_ANS_TYPES - 1,
(unsigned long) Rmt_ANSWER_TYPE_DEFAULT);
* Get question text *
Par_GetParToHTML ("Txt",Txt,Cns_MAX_BYTES_TEXT);
* Get the texts of the answers *
for (NumAns = 0;
NumAns < Rmt_MAX_ANSWERS_PER_QUESTION;
NumAns++)
{
if (!Rmt_AllocateTextChoiceAnswer (&GameQst,NumAns))
Lay_ShowErrorAndExit (Gbl.Alert.Txt);
sprintf (AnsStr,"AnsStr%u",NumAns);
Par_GetParToHTML (AnsStr,GameQst.AnsChoice[NumAns].Text,Rmt_MAX_BYTES_ANSWER);
}
***** Make sure that stem and answer are not empty *****
if (Txt[0])
{
if (GameQst.AnsChoice[0].Text[0]) // If the first answer has been filled
{
for (NumAns = 0, NumLastAns = 0, ThereIsEndOfAnswers = false;
!Error && NumAns < Rmt_MAX_ANSWERS_PER_QUESTION;
NumAns++)
if (GameQst.AnsChoice[NumAns].Text[0])
{
if (ThereIsEndOfAnswers)
{
Ale_ShowAlert (Ale_WARNING,Txt_You_can_not_leave_empty_intermediate_answers);
Error = true;
}
else
NumLastAns = NumAns;
}
else
ThereIsEndOfAnswers = true;
if (!Error)
{
if (NumLastAns < 1)
{
Ale_ShowAlert (Ale_WARNING,Txt_You_must_type_at_least_the_first_two_answers);
Error = true;
}
}
}
else // If first answer is empty
{
Ale_ShowAlert (Ale_WARNING,Txt_You_must_type_at_least_the_first_two_answers);
Error = true;
}
}
else
{
Ale_ShowAlert (Ale_WARNING,Txt_You_must_type_the_stem_of_the_question);
Error = true;
}
if (Error)
Tst_ShowFormAskSelectTstsForGame (Game.GamCod);
else
{
***** Form is received OK ==> insert question and answer in the database *****
if (GameQst.QstCod < 0) // It's a new question
{
GameQst.QstInd = Rmt_GetNextQuestionIndexInGame (Game.GamCod);
* Insert question in the table of questions *
sprintf (Query,"INSERT INTO gam_questions"
" (GamCod,QstInd,AnsType,Stem)"
" VALUES"
" (%ld,%u,'%s','%s')",
Game.GamCod,GameQst.QstInd,Rmt_StrAnswerTypesDB[GameQst.AnswerType],Txt);
GameQst.QstCod = DB_QueryINSERTandReturnCode (Query,"can not create question");
}
else // It's an existing question
{
* Update question *
sprintf (Query,"UPDATE gam_questions SET Stem='%s',AnsType='%s'"
" WHERE QstCod=%ld AND GamCod=%ld",
Txt,Rmt_StrAnswerTypesDB[GameQst.AnswerType],
GameQst.QstCod,Game.GamCod);
DB_QueryUPDATE (Query,"can not update question");
}
* Insert, update or delete answers in the answers table *
for (NumAns = 0;
NumAns < Rmt_MAX_ANSWERS_PER_QUESTION;
NumAns++)
if (Rmt_CheckIfAnswerExists (GameQst.QstCod,NumAns)) // If this answer exists...
{
if (GameQst.AnsChoice[NumAns].Text[0]) // Answer is not empty
{
* Update answer text *
sprintf (Query,"UPDATE gam_answers SET Answer='%s'"
" WHERE QstCod=%ld AND AnsInd=%u",
GameQst.AnsChoice[NumAns].Text,GameQst.QstCod,NumAns);
DB_QueryUPDATE (Query,"can not update answer");
}
else // Answer is empty
{
* Delete answer from database *
sprintf (Query,"DELETE FROM gam_answers"
" WHERE QstCod=%ld AND AnsInd=%u",
GameQst.QstCod,NumAns);
DB_QueryDELETE (Query,"can not delete answer");
}
}
else // If this answer does not exist...
{
if (GameQst.AnsChoice[NumAns].Text[0]) // Answer is not empty
{
* Create answer into database *
sprintf (Query,"INSERT INTO gam_answers"
" (QstCod,AnsInd,NumUsrs,Answer)"
" VALUES"
" (%ld,%u,0,'%s')",
GameQst.QstCod,NumAns,GameQst.AnsChoice[NumAns].Text);
DB_QueryINSERT (Query,"can not create answer");
}
}
***** List the questions of this game, including the new one just inserted into the database *****
Ale_ShowAlert (Ale_SUCCESS,Txt_The_game_has_been_modified);
}
***** Free answers *****
Rmt_FreeTextChoiceAnswers (&GameQst,Rmt_MAX_ANSWERS_PER_QUESTION);
***** Show current game *****
Rmt_ShowOneGame (Game.GamCod,&GameQst,true);
}
*/
/*****************************************************************************/ /*****************************************************************************/
/******************** Get next question index in a game **********************/ /******************** Get next question index in a game **********************/
/*****************************************************************************/ /*****************************************************************************/
@ -3117,14 +2843,12 @@ static void Rmt_ListOneOrMoreQuestionsForEdition (struct Game *Game,
Act_FormStart (ActReqRemGamQst); Act_FormStart (ActReqRemGamQst);
Rmt_PutParamGameCod (Game->GamCod); Rmt_PutParamGameCod (Game->GamCod);
Rmt_PutParamQstCod (GameQst->QstCod); Rmt_PutParamQstCod (GameQst->QstCod);
// Tst_PutParamQstCod ();
Ico_PutIconRemove (); Ico_PutIconRemove ();
Act_FormEnd (); Act_FormEnd ();
/* Write icon to edit the question */ /* Write icon to edit the question */
Act_FormStart (ActEdiOneTstQst); Act_FormStart (ActEdiOneTstQst);
Rmt_PutParamQstCod (GameQst->QstCod); Rmt_PutParamQstCod (GameQst->QstCod);
// Tst_PutParamQstCod ();
fprintf (Gbl.F.Out,"<input type=\"image\" src=\"%s/edit64x64.png\"" fprintf (Gbl.F.Out,"<input type=\"image\" src=\"%s/edit64x64.png\""
" alt=\"%s\" title=\"%s\"" " alt=\"%s\" title=\"%s\""
" class=\"ICO20x20\" />", " class=\"ICO20x20\" />",
@ -3169,8 +2893,8 @@ static void Rmt_ListOneOrMoreQuestionsForEdition (struct Game *Game,
"TEST_IMG_EDIT_LIST_STEM_CONTAINER", "TEST_IMG_EDIT_LIST_STEM_CONTAINER",
"TEST_IMG_EDIT_LIST_STEM"); "TEST_IMG_EDIT_LIST_STEM");
Tst_WriteQstFeedback (row[3],"TEST_EDI_LIGHT"); Tst_WriteQstFeedback (row[3],"TEST_EDI_LIGHT");
// Tst_WriteAnswersEdit (Gbl.Test.QstCod); Tst_WriteAnswersGameResult (Game,GameQst->QstInd,GameQst->QstCod);
Rmt_WriteAnswersOfAQst (Tst_SHOW_GAME_RESULT,Game,GameQst);
fprintf (Gbl.F.Out,"</td>" fprintf (Gbl.F.Out,"</td>"
"</tr>"); "</tr>");
@ -3326,183 +3050,45 @@ static unsigned Rmt_CountNumQuestionsInList (void)
} }
/*****************************************************************************/ /*****************************************************************************/
/****************** Write the heading of a game question *******************/ /*** Get number of users who selected this answer and draw proportional bar **/
/*****************************************************************************/ /*****************************************************************************/
/*
static void Rmt_WriteQstStem (const char *Stem) void Rmt_GetAndDrawBarNumUsrsWhoAnswered (struct Game *Game,long QstCod,unsigned AnsInd)
{ {
char *HeadingRigorousHTML;
size_t Length;
* Convert the stem, that is in HTML, to rigorous HTML *
Length = strlen (Stem) * Str_MAX_BYTES_PER_CHAR;
if ((HeadingRigorousHTML = malloc (Length + 1)) == NULL)
Lay_ShowErrorAndExit ("Not enough memory to store stem of question.");
Str_Copy (HeadingRigorousHTML,Stem,
Length);
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
HeadingRigorousHTML,Length,false);
* Write the stem *
fprintf (Gbl.F.Out,"%s",HeadingRigorousHTML);
* Free memory allocated for the stem *
free ((void *) HeadingRigorousHTML);
}
*/
/*****************************************************************************/
/************** Get and write the answers of a game question ***************/
/*****************************************************************************/
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 NumAns;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumUsrsThisAnswer; unsigned NumUsrsThisAnswer;
***** Get answers of this question ***** /***** Get number of users who selected this answer *****/
NumAnswers = Rmt_GetNumUsrsWhoAnswered (GameQst->QstCod,&mysql_res); // Result: AnsInd,NumUsrs,Answer NumUsrsThisAnswer = Rmt_GetNumUsrsWhoAnswered (Game->GamCod,QstCod,AnsInd);
***** Write the answers ***** /***** Show stats of this answer *****/
if (NumAnswers) if (Game->Status.ICanViewResults)
Rmt_DrawBarNumUsrs (NumUsrsThisAnswer,Game->NumUsrs);
}
/*****************************************************************************/
/**** Get number of users who selected a given answer of a game question *****/
/*****************************************************************************/
static unsigned Rmt_GetNumUsrsWhoAnswered (long GamCod,long QstCod,unsigned AnsInd)
{
char Query[256];
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumUsrs = 0; // Default returned value
/***** Get answers of a question from database *****/
sprintf (Query,"SELECT NumUsrs FROM gam_answers"
" WHERE GamCod=%ld AND QstCod=%ld AND AnsInd=%u",
GamCod,QstCod,AnsInd);
if (DB_QuerySELECT (Query,&mysql_res,"can not get number of users who answered"))
{ {
* Check number of answers * row = mysql_fetch_row (mysql_res);
if (NumAnswers > Rmt_MAX_ANSWERS_PER_QUESTION) if (row[0]) // There are users who selected this answer
Lay_ShowErrorAndExit ("Wrong number of answers."); if (sscanf (row[0],"%u",&NumUsrs) != 1)
Lay_ShowErrorAndExit ("Error when getting number of users who answered.");
* Write one row for each answer *
Tbl_StartTable (5);
for (NumAns = 0;
NumAns < NumAnswers;
NumAns++)
{
row = mysql_fetch_row (mysql_res);
* Get number of users who have marked this answer (row[1]) *
if (sscanf (row[1],"%u",&NumUsrsThisAnswer) != 1)
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 *
if (!Rmt_AllocateTextChoiceAnswer (GameQst,NumAns))
Lay_ShowErrorAndExit (Gbl.Alert.Txt);
Str_Copy (GameQst->AnsChoice[NumAns].Text,row[2],
Rmt_MAX_BYTES_ANSWER);
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
GameQst->AnsChoice[NumAns].Text,Rmt_MAX_BYTES_ANSWER,false);
* Selectors and label with the letter of the answer *
fprintf (Gbl.F.Out,"<tr>");
if (PutFormAnswerGame)
{
* Write selector to choice this answer *
fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP\">"
"<input type=\"");
if (GameQst->AnswerType == Rmt_ANS_UNIQUE_CHOICE)
fprintf (Gbl.F.Out,"radio\""
" onclick=\"selectUnselectRadio(this,this.form.Ans%010u,%u)\"",
(unsigned) GameQst->QstCod,NumAnswers);
else // GameQst->AnswerType == Rmt_ANS_MULTIPLE_CHOICE
fprintf (Gbl.F.Out,"checkbox\"");
fprintf (Gbl.F.Out," id=\"Ans%010u_%010u\" name=\"Ans%010u\""
" value=\"%u\" />"
"</td>",
(unsigned) GameQst->QstCod,NumAns,(unsigned) GameQst->QstCod,
NumAns);
}
* Write the number of option *
fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP\" style=\"width:50px;\">"
"<label for=\"Ans%010u_%010u\" class=\"DAT\">"
"%u)"
"</label>"
"</td>",
(unsigned) GameQst->QstCod,NumAns,NumAns + 1);
* Write the text of the answer *
fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP\">"
"<label for=\"Ans%010u_%010u\" class=\"DAT\">%s</label>"
"</td>",
(unsigned) GameQst->QstCod,NumAns,
GameQst->AnsChoice[NumAns].Text);
* Show stats of this answer *
if (Game->Status.ICanViewResults)
Rmt_DrawBarNumUsrs (NumUsrsThisAnswer,Game->NumUsrs);
fprintf (Gbl.F.Out,"</tr>");
* Free memory allocated for the answer *
Rmt_FreeTextChoiceAnswer (GameQst,NumAns);
}
Tbl_EndTable ();
} }
***** Free structure that stores the query result ***** return NumUsrs;
DB_FreeMySQLResult (&mysql_res);
*/
} }
/*****************************************************************************/ /*****************************************************************************/
@ -3545,9 +3131,7 @@ static void Rmt_DrawBarNumUsrs (unsigned NumUsrs,unsigned MaxUsrs)
BarWidth); BarWidth);
/***** Write the number of users *****/ /***** Write the number of users *****/
fprintf (Gbl.F.Out,"%s</td>" fprintf (Gbl.F.Out,"%s</td>",Gbl.Title);
"</tr>",
Gbl.Title);
} }
/*****************************************************************************/ /*****************************************************************************/

View File

@ -113,7 +113,7 @@ 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_GetAndDrawBarNumUsrsWhoAnswered (struct Game *Game,long QstCod,unsigned AnsInd);
void Rmt_AddTstQuestionsToGame (void); void Rmt_AddTstQuestionsToGame (void);

View File

@ -194,7 +194,6 @@ static void Tst_WriteAnswersEdit (long QstCod);
static void Tst_WriteAnswersTestToAnswer (unsigned NumQst,long QstCod,bool Shuffle); static void Tst_WriteAnswersTestToAnswer (unsigned NumQst,long QstCod,bool Shuffle);
static void Tst_WriteAnswersTestResult (unsigned NumQst,long QstCod, static void Tst_WriteAnswersTestResult (unsigned NumQst,long QstCod,
double *ScoreThisQst,bool *AnswerIsNotBlank); double *ScoreThisQst,bool *AnswerIsNotBlank);
static void Tst_WriteAnswersGameResult (unsigned NumQst,long QstCod);
static void Tst_WriteTFAnsViewTest (unsigned NumQst); static void Tst_WriteTFAnsViewTest (unsigned NumQst);
static void Tst_WriteTFAnsAssessTest (unsigned NumQst,MYSQL_RES *mysql_res, static void Tst_WriteTFAnsAssessTest (unsigned NumQst,MYSQL_RES *mysql_res,
@ -203,7 +202,7 @@ static void Tst_WriteTFAnsAssessTest (unsigned NumQst,MYSQL_RES *mysql_res,
static void Tst_WriteChoiceAnsViewTest (unsigned NumQst,long QstCod,bool Shuffle); static void Tst_WriteChoiceAnsViewTest (unsigned NumQst,long QstCod,bool Shuffle);
static void Tst_WriteChoiceAnsAssessTest (unsigned NumQst,MYSQL_RES *mysql_res, static void Tst_WriteChoiceAnsAssessTest (unsigned NumQst,MYSQL_RES *mysql_res,
double *ScoreThisQst,bool *AnswerIsNotBlank); double *ScoreThisQst,bool *AnswerIsNotBlank);
static void Tst_WriteChoiceAnsViewGame (unsigned NumQst,long QstCod); static void Tst_WriteChoiceAnsViewGame (struct Game *Game,unsigned NumQst,long QstCod);
static void Tst_WriteTextAnsViewTest (unsigned NumQst); static void Tst_WriteTextAnsViewTest (unsigned NumQst);
static void Tst_WriteTextAnsAssessTest (unsigned NumQst,MYSQL_RES *mysql_res, static void Tst_WriteTextAnsAssessTest (unsigned NumQst,MYSQL_RES *mysql_res,
@ -833,7 +832,7 @@ static void Tst_ShowTestQuestionsWhenSeeing (MYSQL_RES *mysql_res)
Lay_ShowErrorAndExit ("Wrong code of question."); Lay_ShowErrorAndExit ("Wrong code of question.");
Tst_WriteQstAndAnsTest (Tst_SHOW_TEST_TO_ANSWER, Tst_WriteQstAndAnsTest (Tst_SHOW_TEST_TO_ANSWER,
NumQst,QstCod,row, NULL,NumQst,QstCod,row,
&ScoreThisQst, // Not used here &ScoreThisQst, // Not used here
&AnswerIsNotBlank); // Not used here &AnswerIsNotBlank); // Not used here
} }
@ -934,7 +933,7 @@ static void Tst_ShowTestResultAfterAssess (long TstCod,unsigned *NumQstsNotBlank
/***** Write question and answers *****/ /***** Write question and answers *****/
Tst_WriteQstAndAnsTest (Tst_SHOW_TEST_RESULT, Tst_WriteQstAndAnsTest (Tst_SHOW_TEST_RESULT,
NumQst,QstCod,row, NULL,NumQst,QstCod,row,
&ScoreThisQst,&AnswerIsNotBlank); &ScoreThisQst,&AnswerIsNotBlank);
/***** Store test result question in database *****/ /***** Store test result question in database *****/
@ -974,6 +973,7 @@ static void Tst_ShowTestResultAfterAssess (long TstCod,unsigned *NumQstsNotBlank
/*****************************************************************************/ /*****************************************************************************/
void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestions, void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestions,
struct Game *Game,
unsigned NumQst,long QstCod,MYSQL_ROW row, unsigned NumQst,long QstCod,MYSQL_ROW row,
double *ScoreThisQst,bool *AnswerIsNotBlank) double *ScoreThisQst,bool *AnswerIsNotBlank)
{ {
@ -1041,7 +1041,7 @@ void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestio
Tst_WriteAnswersTestToAnswer (NumQst,QstCod,(row[3][0] == 'Y')); Tst_WriteAnswersTestToAnswer (NumQst,QstCod,(row[3][0] == 'Y'));
break; break;
case Tst_SHOW_GAME_RESULT: case Tst_SHOW_GAME_RESULT:
Tst_WriteAnswersGameResult (NumQst,QstCod); Tst_WriteAnswersGameResult (Game,NumQst,QstCod);
break; break;
} }
fprintf (Gbl.F.Out,"</td>" fprintf (Gbl.F.Out,"</td>"
@ -3545,7 +3545,7 @@ static void Tst_WriteAnswersTestResult (unsigned NumQst,long QstCod,
/************** Write answers of a question when viewing a game **************/ /************** Write answers of a question when viewing a game **************/
/*****************************************************************************/ /*****************************************************************************/
static void Tst_WriteAnswersGameResult (unsigned NumQst,long QstCod) void Tst_WriteAnswersGameResult (struct Game *Game,unsigned NumQst,long QstCod)
{ {
/***** Write parameter with question code *****/ /***** Write parameter with question code *****/
Tst_WriteParamQstCod (NumQst,QstCod); Tst_WriteParamQstCod (NumQst,QstCod);
@ -3561,7 +3561,7 @@ static void Tst_WriteAnswersGameResult (unsigned NumQst,long QstCod)
break; break;
case Tst_ANS_UNIQUE_CHOICE: case Tst_ANS_UNIQUE_CHOICE:
case Tst_ANS_MULTIPLE_CHOICE: case Tst_ANS_MULTIPLE_CHOICE:
Tst_WriteChoiceAnsViewGame (NumQst,QstCod); Tst_WriteChoiceAnsViewGame (Game,NumQst,QstCod);
break; break;
default: default:
break; break;
@ -4045,12 +4045,12 @@ static void Tst_WriteChoiceAnsAssessTest (unsigned NumQst,MYSQL_RES *mysql_res,
/******** Write single or multiple choice answer when viewing a test *********/ /******** Write single or multiple choice answer when viewing a test *********/
/*****************************************************************************/ /*****************************************************************************/
static void Tst_WriteChoiceAnsViewGame (unsigned NumQst,long QstCod) static void Tst_WriteChoiceAnsViewGame (struct Game *Game,unsigned NumQst,long QstCod)
{ {
unsigned NumOpt; unsigned NumOpt;
MYSQL_RES *mysql_res; MYSQL_RES *mysql_res;
MYSQL_ROW row; MYSQL_ROW row;
unsigned Index; unsigned AnsInd;
bool ErrorInIndex = false; bool ErrorInIndex = false;
/***** Get answers of a question from database *****/ /***** Get answers of a question from database *****/
@ -4082,9 +4082,9 @@ static void Tst_WriteChoiceAnsViewGame (unsigned NumQst,long QstCod)
/***** Assign index (row[0]). /***** Assign index (row[0]).
Index is 0,1,2,3... if no shuffle Index is 0,1,2,3... if no shuffle
or 1,3,0,2... (example) if shuffle *****/ or 1,3,0,2... (example) if shuffle *****/
if (sscanf (row[0],"%u",&Index) == 1) if (sscanf (row[0],"%u",&AnsInd) == 1)
{ {
if (Index >= Tst_MAX_OPTIONS_PER_QUESTION) if (AnsInd >= Tst_MAX_OPTIONS_PER_QUESTION)
ErrorInIndex = true; ErrorInIndex = true;
} }
else else
@ -4122,8 +4122,11 @@ static void Tst_WriteChoiceAnsViewGame (unsigned NumQst,long QstCod)
Img_ShowImage (&Gbl.Test.Answer.Options[NumOpt].Image, Img_ShowImage (&Gbl.Test.Answer.Options[NumOpt].Image,
"TEST_IMG_SHOW_ANS_CONTAINER", "TEST_IMG_SHOW_ANS_CONTAINER",
"TEST_IMG_SHOW_ANS"); "TEST_IMG_SHOW_ANS");
fprintf (Gbl.F.Out,"</td>" fprintf (Gbl.F.Out,"</td>");
"</tr>");
/* Get number of users who selected this answer and draw proportional bar */
Rmt_GetAndDrawBarNumUsrsWhoAnswered (Game,QstCod,AnsInd);
fprintf (Gbl.F.Out,"</tr>");
} }
/***** End table *****/ /***** End table *****/
@ -8311,7 +8314,7 @@ static void Tst_ShowTestResult (time_t TstTimeUTC)
/***** Write questions and answers *****/ /***** Write questions and answers *****/
Tst_WriteQstAndAnsTest (Tst_SHOW_TEST_RESULT, Tst_WriteQstAndAnsTest (Tst_SHOW_TEST_RESULT,
NumQst,QstCod,row, NULL,NumQst,QstCod,row,
&ScoreThisQst, // Not used here &ScoreThisQst, // Not used here
&AnswerIsNotBlank); // Not used here &AnswerIsNotBlank); // Not used here
} }

View File

@ -27,6 +27,8 @@
/********************************* Headers ***********************************/ /********************************* Headers ***********************************/
/*****************************************************************************/ /*****************************************************************************/
#include "swad_remote_control.h"
/*****************************************************************************/ /*****************************************************************************/
/***************************** Public constants ******************************/ /***************************** Public constants ******************************/
/*****************************************************************************/ /*****************************************************************************/
@ -143,6 +145,7 @@ void Tst_ShowNewTest (void);
void Tst_AssessTest (void); void Tst_AssessTest (void);
void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestions, void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestions,
struct Game *Game,
unsigned NumQst,long QstCod,MYSQL_ROW row, unsigned NumQst,long QstCod,MYSQL_ROW row,
double *ScoreThisQst,bool *AnswerIsNotBlank); double *ScoreThisQst,bool *AnswerIsNotBlank);
void Tst_WriteQstStem (const char *Stem,const char *ClassStem); void Tst_WriteQstStem (const char *Stem,const char *ClassStem);
@ -156,6 +159,7 @@ void Tst_ListQuestionsToSelect (void);
bool Tst_GetOneQuestionByCod (long QstCod,MYSQL_RES **mysql_res); 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_WriteAnswersGameResult (struct Game *Game,unsigned NumQst,long QstCod);
void Tst_WriteAnsTF (char AnsTF); void Tst_WriteAnsTF (char AnsTF);
void Tst_CheckIfNumberOfAnswersIsOne (void); void Tst_CheckIfNumberOfAnswersIsOne (void);