mirror of https://github.com/acanas/swad-core.git
Version 16.251.10
This commit is contained in:
parent
b1e722435d
commit
3964984d31
|
@ -587,10 +587,11 @@ CREATE TABLE IF NOT EXISTS games (
|
|||
-- Table gam_answers: stores the answers to the games
|
||||
--
|
||||
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(QstCod,AnsInd));
|
||||
UNIQUE INDEX(GamCod,QstCod,AnsInd));
|
||||
--
|
||||
-- Table gam_grp: stores the groups associated to each game
|
||||
--
|
||||
|
|
|
@ -238,19 +238,24 @@
|
|||
/****************************** 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 JS_FILE "swad16.206.3.js"
|
||||
|
||||
// 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
|
||||
/*
|
||||
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.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.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)
|
||||
1 change necessary in database:
|
||||
2 changes necessary in database:
|
||||
ALTER TABLE gam_answers DROP COLUMN Answer;
|
||||
UPDATE actions SET Obsolete='Y' WHERE ActCod='1663';
|
||||
|
||||
|
|
|
@ -1278,17 +1278,19 @@ mysql> DESCRIBE gam_answers;
|
|||
+---------+------------+------+-----+---------+-------+
|
||||
| Field | Type | Null | Key | Default | Extra |
|
||||
+---------+------------+------+-----+---------+-------+
|
||||
| GamCod | int(11) | NO | PRI | NULL | |
|
||||
| QstCod | int(11) | NO | PRI | NULL | |
|
||||
| AnsInd | tinyint(4) | NO | PRI | NULL | |
|
||||
| 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 ("
|
||||
"GamCod INT NOT NULL,"
|
||||
"QstCod INT NOT NULL,"
|
||||
"AnsInd TINYINT NOT NULL,"
|
||||
"NumUsrs INT NOT NULL DEFAULT 0,"
|
||||
"UNIQUE INDEX(QstCod,AnsInd))");
|
||||
"UNIQUE INDEX(GamCod,QstCod,AnsInd))");
|
||||
|
||||
/***** Table gam_grp *****/
|
||||
/*
|
||||
|
|
|
@ -136,11 +136,6 @@ static void Rmt_InitQst (struct GameQuestion *GameQst);
|
|||
static void Rmt_PutParamQstCod (long QstCod);
|
||||
static long Rmt_GetParamQstCod (void);
|
||||
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_GetNextQuestionIndexInGame (long GamCod);
|
||||
|
@ -156,9 +151,7 @@ static void Rmt_AllocateListSelectedQuestions (void);
|
|||
static void Rmt_FreeListsSelectedQuestions (void);
|
||||
static unsigned Rmt_CountNumQuestionsInList (void);
|
||||
|
||||
// static void Rmt_WriteQstStem (const char *Stem);
|
||||
static void Rmt_WriteAnswersOfAQst (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestions,
|
||||
struct Game *Game,struct GameQuestion *GameQst);
|
||||
static unsigned Rmt_GetNumUsrsWhoAnswered (long GamCod,long QstCod,unsigned AnsInd);
|
||||
static void Rmt_DrawBarNumUsrs (unsigned NumUsrs,unsigned MaxUsrs);
|
||||
|
||||
// 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");
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*********** 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 **********************/
|
||||
/*****************************************************************************/
|
||||
|
@ -3117,14 +2843,12 @@ static void Rmt_ListOneOrMoreQuestionsForEdition (struct Game *Game,
|
|||
Act_FormStart (ActReqRemGamQst);
|
||||
Rmt_PutParamGameCod (Game->GamCod);
|
||||
Rmt_PutParamQstCod (GameQst->QstCod);
|
||||
// Tst_PutParamQstCod ();
|
||||
Ico_PutIconRemove ();
|
||||
Act_FormEnd ();
|
||||
|
||||
/* Write icon to edit the question */
|
||||
Act_FormStart (ActEdiOneTstQst);
|
||||
Rmt_PutParamQstCod (GameQst->QstCod);
|
||||
// Tst_PutParamQstCod ();
|
||||
fprintf (Gbl.F.Out,"<input type=\"image\" src=\"%s/edit64x64.png\""
|
||||
" alt=\"%s\" title=\"%s\""
|
||||
" class=\"ICO20x20\" />",
|
||||
|
@ -3169,8 +2893,8 @@ static void Rmt_ListOneOrMoreQuestionsForEdition (struct Game *Game,
|
|||
"TEST_IMG_EDIT_LIST_STEM_CONTAINER",
|
||||
"TEST_IMG_EDIT_LIST_STEM");
|
||||
Tst_WriteQstFeedback (row[3],"TEST_EDI_LIGHT");
|
||||
// Tst_WriteAnswersEdit (Gbl.Test.QstCod);
|
||||
Rmt_WriteAnswersOfAQst (Tst_SHOW_GAME_RESULT,Game,GameQst);
|
||||
Tst_WriteAnswersGameResult (Game,GameQst->QstInd,GameQst->QstCod);
|
||||
|
||||
fprintf (Gbl.F.Out,"</td>"
|
||||
"</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;
|
||||
|
||||
***** Get answers of this question *****
|
||||
NumAnswers = Rmt_GetNumUsrsWhoAnswered (GameQst->QstCod,&mysql_res); // Result: AnsInd,NumUsrs,Answer
|
||||
/***** Get number of users who selected this answer *****/
|
||||
NumUsrsThisAnswer = Rmt_GetNumUsrsWhoAnswered (Game->GamCod,QstCod,AnsInd);
|
||||
|
||||
***** Write the answers *****
|
||||
if (NumAnswers)
|
||||
/***** Show stats of this answer *****/
|
||||
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 *
|
||||
if (NumAnswers > Rmt_MAX_ANSWERS_PER_QUESTION)
|
||||
Lay_ShowErrorAndExit ("Wrong number of answers.");
|
||||
|
||||
* 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 ();
|
||||
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.");
|
||||
}
|
||||
|
||||
***** Free structure that stores the query result *****
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
*/
|
||||
return NumUsrs;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -3545,9 +3131,7 @@ static void Rmt_DrawBarNumUsrs (unsigned NumUsrs,unsigned MaxUsrs)
|
|||
BarWidth);
|
||||
|
||||
/***** Write the number of users *****/
|
||||
fprintf (Gbl.F.Out,"%s</td>"
|
||||
"</tr>",
|
||||
Gbl.Title);
|
||||
fprintf (Gbl.F.Out,"%s</td>",Gbl.Title);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
@ -113,7 +113,7 @@ void Rmt_RemoveGames (Sco_Scope_t Scope,long Cod);
|
|||
void Rmt_RequestEditQuestion (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);
|
||||
|
||||
|
|
31
swad_test.c
31
swad_test.c
|
@ -194,7 +194,6 @@ static void Tst_WriteAnswersEdit (long QstCod);
|
|||
static void Tst_WriteAnswersTestToAnswer (unsigned NumQst,long QstCod,bool Shuffle);
|
||||
static void Tst_WriteAnswersTestResult (unsigned NumQst,long QstCod,
|
||||
double *ScoreThisQst,bool *AnswerIsNotBlank);
|
||||
static void Tst_WriteAnswersGameResult (unsigned NumQst,long QstCod);
|
||||
|
||||
static void Tst_WriteTFAnsViewTest (unsigned NumQst);
|
||||
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_WriteChoiceAnsAssessTest (unsigned NumQst,MYSQL_RES *mysql_res,
|
||||
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_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.");
|
||||
|
||||
Tst_WriteQstAndAnsTest (Tst_SHOW_TEST_TO_ANSWER,
|
||||
NumQst,QstCod,row,
|
||||
NULL,NumQst,QstCod,row,
|
||||
&ScoreThisQst, // Not used here
|
||||
&AnswerIsNotBlank); // Not used here
|
||||
}
|
||||
|
@ -934,7 +933,7 @@ static void Tst_ShowTestResultAfterAssess (long TstCod,unsigned *NumQstsNotBlank
|
|||
|
||||
/***** Write question and answers *****/
|
||||
Tst_WriteQstAndAnsTest (Tst_SHOW_TEST_RESULT,
|
||||
NumQst,QstCod,row,
|
||||
NULL,NumQst,QstCod,row,
|
||||
&ScoreThisQst,&AnswerIsNotBlank);
|
||||
|
||||
/***** 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,
|
||||
struct Game *Game,
|
||||
unsigned NumQst,long QstCod,MYSQL_ROW row,
|
||||
double *ScoreThisQst,bool *AnswerIsNotBlank)
|
||||
{
|
||||
|
@ -1041,7 +1041,7 @@ void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestio
|
|||
Tst_WriteAnswersTestToAnswer (NumQst,QstCod,(row[3][0] == 'Y'));
|
||||
break;
|
||||
case Tst_SHOW_GAME_RESULT:
|
||||
Tst_WriteAnswersGameResult (NumQst,QstCod);
|
||||
Tst_WriteAnswersGameResult (Game,NumQst,QstCod);
|
||||
break;
|
||||
}
|
||||
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 **************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Tst_WriteAnswersGameResult (unsigned NumQst,long QstCod)
|
||||
void Tst_WriteAnswersGameResult (struct Game *Game,unsigned NumQst,long QstCod)
|
||||
{
|
||||
/***** Write parameter with question code *****/
|
||||
Tst_WriteParamQstCod (NumQst,QstCod);
|
||||
|
@ -3561,7 +3561,7 @@ static void Tst_WriteAnswersGameResult (unsigned NumQst,long QstCod)
|
|||
break;
|
||||
case Tst_ANS_UNIQUE_CHOICE:
|
||||
case Tst_ANS_MULTIPLE_CHOICE:
|
||||
Tst_WriteChoiceAnsViewGame (NumQst,QstCod);
|
||||
Tst_WriteChoiceAnsViewGame (Game,NumQst,QstCod);
|
||||
break;
|
||||
default:
|
||||
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 *********/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Tst_WriteChoiceAnsViewGame (unsigned NumQst,long QstCod)
|
||||
static void Tst_WriteChoiceAnsViewGame (struct Game *Game,unsigned NumQst,long QstCod)
|
||||
{
|
||||
unsigned NumOpt;
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
unsigned Index;
|
||||
unsigned AnsInd;
|
||||
bool ErrorInIndex = false;
|
||||
|
||||
/***** Get answers of a question from database *****/
|
||||
|
@ -4082,9 +4082,9 @@ static void Tst_WriteChoiceAnsViewGame (unsigned NumQst,long QstCod)
|
|||
/***** Assign index (row[0]).
|
||||
Index is 0,1,2,3... if no 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;
|
||||
}
|
||||
else
|
||||
|
@ -4122,8 +4122,11 @@ static void Tst_WriteChoiceAnsViewGame (unsigned NumQst,long QstCod)
|
|||
Img_ShowImage (&Gbl.Test.Answer.Options[NumOpt].Image,
|
||||
"TEST_IMG_SHOW_ANS_CONTAINER",
|
||||
"TEST_IMG_SHOW_ANS");
|
||||
fprintf (Gbl.F.Out,"</td>"
|
||||
"</tr>");
|
||||
fprintf (Gbl.F.Out,"</td>");
|
||||
|
||||
/* Get number of users who selected this answer and draw proportional bar */
|
||||
Rmt_GetAndDrawBarNumUsrsWhoAnswered (Game,QstCod,AnsInd);
|
||||
fprintf (Gbl.F.Out,"</tr>");
|
||||
}
|
||||
|
||||
/***** End table *****/
|
||||
|
@ -8311,7 +8314,7 @@ static void Tst_ShowTestResult (time_t TstTimeUTC)
|
|||
|
||||
/***** Write questions and answers *****/
|
||||
Tst_WriteQstAndAnsTest (Tst_SHOW_TEST_RESULT,
|
||||
NumQst,QstCod,row,
|
||||
NULL,NumQst,QstCod,row,
|
||||
&ScoreThisQst, // Not used here
|
||||
&AnswerIsNotBlank); // Not used here
|
||||
}
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
/********************************* Headers ***********************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "swad_remote_control.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Public constants ******************************/
|
||||
/*****************************************************************************/
|
||||
|
@ -143,6 +145,7 @@ void Tst_ShowNewTest (void);
|
|||
void Tst_AssessTest (void);
|
||||
|
||||
void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestions,
|
||||
struct Game *Game,
|
||||
unsigned NumQst,long QstCod,MYSQL_ROW row,
|
||||
double *ScoreThisQst,bool *AnswerIsNotBlank);
|
||||
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);
|
||||
void Tst_WriteParamEditQst (void);
|
||||
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_CheckIfNumberOfAnswersIsOne (void);
|
||||
|
||||
|
|
Loading…
Reference in New Issue