mirror of https://github.com/acanas/swad-core.git
Version19.12
This commit is contained in:
parent
b7987d6356
commit
b4bc3aa6ef
|
@ -12879,3 +12879,18 @@ REPLACE gam_time (MchCod,QstInd,ElapsedTime) VALUES (61,1,ADDTIME(ElapsedTime,SE
|
|||
INSERT INTO gam_time (MchCod,QstInd) VALUES (61,1,SEC_TO_TIME(1)) ON DUPLICATE KEY UPDATE ElapsedTime=ADDTIME(ElapsedTime,SEC_TO_TIME(1));
|
||||
|
||||
|
||||
|
||||
----------------
|
||||
|
||||
SELECT gam_questions.QstCod,
|
||||
gam_questions.QstInd,
|
||||
mch_indexes.Indexes
|
||||
FROM mch_matches,gam_questions,mch_indexes
|
||||
WHERE mch_matches.MchCod=69
|
||||
AND mch_matches.GamCod=gam_questions.GamCod
|
||||
AND mch_matches.MchCod=mch_indexes.MchCod
|
||||
AND gam_questions.QstInd=mch_indexes.QstInd
|
||||
ORDER BY gam_questions.QstInd;
|
||||
|
||||
|
||||
SELECT Correct FROM tst_answers WHERE QstCod=1787 ORDER BY AnsInd;
|
||||
|
|
11
sql/swad.sql
11
sql/swad.sql
|
@ -613,11 +613,12 @@ CREATE TABLE IF NOT EXISTS gam_games (
|
|||
--
|
||||
-- Table mch_answers: stores the users' answers to the matches
|
||||
--
|
||||
CREATE TABLE IF NOT EXISTS mch_answers ("
|
||||
MchCod INT NOT NULL,"
|
||||
UsrCod INT NOT NULL,"
|
||||
QstInd INT NOT NULL,"
|
||||
AnsInd TINYINT NOT NULL,"
|
||||
CREATE TABLE IF NOT EXISTS mch_answers (
|
||||
MchCod INT NOT NULL,
|
||||
UsrCod INT NOT NULL,
|
||||
QstInd INT NOT NULL,
|
||||
NumOpt TINYINT NOT NULL,
|
||||
AnsInd TINYINT NOT NULL,
|
||||
UNIQUE INDEX(MchCod,UsrCod,QstInd));
|
||||
--
|
||||
-- Table mch_groups: stores the groups associated to each match in a game
|
||||
|
|
|
@ -470,10 +470,15 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - *
|
|||
En OpenSWAD:
|
||||
ps2pdf source.ps destination.pdf
|
||||
*/
|
||||
#define Log_PLATFORM_VERSION "SWAD 19.11 (2019-09-23)"
|
||||
#define Log_PLATFORM_VERSION "SWAD 19.12 (2019-09-24)"
|
||||
#define CSS_FILE "swad19.3.css"
|
||||
#define JS_FILE "swad18.130.2.js"
|
||||
/*
|
||||
*
|
||||
Version 19.12: Sep 24, 2019 View matches results. Not finished. (245973 lines)
|
||||
1 change necessary in database:
|
||||
ALTER TABLE mch_answers ADD COLUMN NumOpt TINYINT NOT NULL AFTER QstInd;
|
||||
|
||||
Version 19.11: Sep 23, 2019 Create indexes when a match is created. (245933 lines)
|
||||
Version 19.10.3: Sep 23, 2019 View matches results. Not finished. (245815 lines)
|
||||
Version 19.10.2: Sep 23, 2019 View matches results. Not finished. (245812 lines)
|
||||
|
|
|
@ -1339,15 +1339,17 @@ mysql> DESCRIBE mch_answers;
|
|||
| MchCod | int(11) | NO | PRI | NULL | |
|
||||
| UsrCod | int(11) | NO | PRI | NULL | |
|
||||
| QstInd | int(11) | NO | PRI | NULL | |
|
||||
| AnsInd | tinyint(4) | NO | PRI | NULL | |
|
||||
| NumOpt | tinyint(4) | NO | | NULL | |
|
||||
| AnsInd | tinyint(4) | NO | | NULL | |
|
||||
+--------+------------+------+-----+---------+-------+
|
||||
4 rows in set (0.00 sec)
|
||||
5 rows in set (0.00 sec)
|
||||
*/
|
||||
DB_CreateTable ("CREATE TABLE IF NOT EXISTS mch_answers ("
|
||||
"MchCod INT NOT NULL,"
|
||||
"UsrCod INT NOT NULL,"
|
||||
"QstInd INT NOT NULL,"
|
||||
"AnsInd TINYINT NOT NULL,"
|
||||
"NumOpt TINYINT NOT NULL," // Number of button on screen (Always ordered: 0,1,2,3)
|
||||
"AnsInd TINYINT NOT NULL," // Answer index (Can be shuffled: 0,3,1,2)
|
||||
"UNIQUE INDEX(MchCod,UsrCod,QstInd))");
|
||||
|
||||
/***** Table mch_groups *****/
|
||||
|
|
14
swad_game.c
14
swad_game.c
|
@ -1382,13 +1382,13 @@ void Gam_PutParamQstInd (unsigned QstInd)
|
|||
|
||||
unsigned Gam_GetParamQstInd (void)
|
||||
{
|
||||
long LongNum;
|
||||
long QstInd;
|
||||
|
||||
LongNum = Par_GetParToLong ("QstInd");
|
||||
if (LongNum < 0)
|
||||
QstInd = Par_GetParToLong ("QstInd");
|
||||
if (QstInd < 0)
|
||||
Lay_ShowErrorAndExit ("Wrong question index.");
|
||||
|
||||
return (unsigned) LongNum;
|
||||
return (unsigned) QstInd;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -1397,10 +1397,10 @@ unsigned Gam_GetParamQstInd (void)
|
|||
|
||||
unsigned Gam_GetQstIndFromStr (const char *UnsignedStr)
|
||||
{
|
||||
long LongNum;
|
||||
long QstInd;
|
||||
|
||||
LongNum = Str_ConvertStrCodToLongCod (UnsignedStr);
|
||||
return (LongNum > 0) ? (unsigned) LongNum :
|
||||
QstInd = Str_ConvertStrCodToLongCod (UnsignedStr);
|
||||
return (QstInd > 0) ? (unsigned) QstInd :
|
||||
0;
|
||||
}
|
||||
|
||||
|
|
228
swad_match.c
228
swad_match.c
|
@ -99,6 +99,12 @@ struct Match
|
|||
} Status;
|
||||
};
|
||||
|
||||
struct Mch_UsrAnswer
|
||||
{
|
||||
int NumOpt; // < 0 ==> no answer selected
|
||||
int AnsInd; // < 0 ==> no answer selected
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Private constants *****************************/
|
||||
/*****************************************************************************/
|
||||
|
@ -177,8 +183,8 @@ static void Mch_ShowMatchTitle (struct Match *Match);
|
|||
static void Mch_ShowQuestionAndAnswersTch (struct Match *Match);
|
||||
static void Mch_ShowQuestionAndAnswersStd (struct Match *Match);
|
||||
|
||||
static void Mch_PutParamAnswer (unsigned AnsInd);
|
||||
static unsigned Mch_GetParamAnswer (void);
|
||||
static void Mch_PutParamNumOpt (unsigned NumOpt);
|
||||
static unsigned Mch_GetParamNumOpt (void);
|
||||
|
||||
static void Mch_PutBigButton (Act_Action_t NextAction,long MchCod,
|
||||
const char *Icon,const char *Txt);
|
||||
|
@ -194,7 +200,8 @@ static bool Mch_GetIfMatchIsBeingPlayed (long MchCod);
|
|||
static void Mch_RegisterMeAsPlayerInMatch (long MchCod);
|
||||
static void Mch_GetNumPlayers (struct Match *Match);
|
||||
|
||||
static int Mch_GetQstAnsFromDB (long MchCod,long UsrCod,unsigned QstInd);
|
||||
static void Mch_GetQstAnsFromDB (long MchCod,long UsrCod,unsigned QstInd,
|
||||
struct Mch_UsrAnswer *UsrAnswer);
|
||||
static void Mch_ComputeScore (struct Match *Match,unsigned NumQsts,long UsrCod,
|
||||
unsigned *NumQstsNotBlank,double *TotalScore);
|
||||
|
||||
|
@ -1088,7 +1095,7 @@ static void Mch_CreateIndexes (long GamCod,long MchCod)
|
|||
DB_QuerySELECT (&mysql_res,"can not get questions of a game",
|
||||
"SELECT gam_questions.QstCod," // row[0]
|
||||
"gam_questions.QstInd," // row[1]
|
||||
"tst_questions.AnsType" // row[2]
|
||||
"tst_questions.AnsType," // row[2]
|
||||
"tst_questions.Shuffle" // row[3]
|
||||
" FROM gam_questions,tst_questions"
|
||||
" WHERE gam_questions.GamCod=%ld"
|
||||
|
@ -1153,10 +1160,10 @@ static void Mch_ReorderAnswer (long MchCod,unsigned QstInd,
|
|||
DB_QuerySELECT (&mysql_res,"can not get questions of a game",
|
||||
"SELECT AnsInd" // row[0]
|
||||
" FROM tst_answers"
|
||||
" WHERE GamCod=%ld"
|
||||
" WHERE QstCod=%ld"
|
||||
" ORDER BY %s",
|
||||
QstCod,
|
||||
Shuffle ? "RAND(NOW())" :
|
||||
Shuffle ? "RAND()" : // Use RAND() because is really random; RAND(NOW()) repeats order
|
||||
"AnsInd");
|
||||
|
||||
/***** For each answer in question... *****/
|
||||
|
@ -1170,10 +1177,10 @@ static void Mch_ReorderAnswer (long MchCod,unsigned QstInd,
|
|||
if ((LongNum = Str_ConvertStrCodToLongCod (row[0])) < 0)
|
||||
Lay_ShowErrorAndExit ("Wrong answer index.");
|
||||
AnsInd = (unsigned) LongNum;
|
||||
snprintf (StrOneAnswer,sizeof (StrOneAnswer),
|
||||
"%u",AnsInd);
|
||||
|
||||
/* Concatenate answer index to list of answers */
|
||||
snprintf (StrOneAnswer,10 + 1,
|
||||
"%u",AnsInd);
|
||||
if (NumAns)
|
||||
Str_Concat (StrAnswersOneQst,",",
|
||||
Tst_MAX_BYTES_ANSWERS_ONE_QST);
|
||||
|
@ -1193,6 +1200,38 @@ static void Mch_ReorderAnswer (long MchCod,unsigned QstInd,
|
|||
MchCod,QstInd,StrAnswersOneQst);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************** Get indexes for a question from database ******************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void Mch_GetIndexes (long MchCod,unsigned QstInd,
|
||||
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION])
|
||||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
char StrIndexesOneQst[Tst_MAX_BYTES_INDEXES_ONE_QST + 1];
|
||||
|
||||
/***** Get indexes for a question from database *****/
|
||||
if (!DB_QuerySELECT (&mysql_res,"can not get data of a question",
|
||||
"SELECT Indexes" // row[0]
|
||||
" FROM mch_indexes"
|
||||
" WHERE MchCod=%ld AND QstInd=%u",
|
||||
MchCod,QstInd))
|
||||
Lay_ShowErrorAndExit ("No indexes found for a question.");
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
|
||||
/* Get indexes (row[0]) */
|
||||
Str_Copy (StrIndexesOneQst,row[0],
|
||||
Tst_MAX_BYTES_INDEXES_ONE_QST);
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
|
||||
/***** Get indexes from string *****/
|
||||
Par_ReplaceCommaBySeparatorMultiple (StrIndexesOneQst);
|
||||
Tst_GetIndexesFromStr (StrIndexesOneQst,Indexes);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************* Create groups associated to a match *********************/
|
||||
/*****************************************************************************/
|
||||
|
@ -1976,7 +2015,10 @@ static void Mch_ShowQuestionAndAnswersTch (struct Match *Match)
|
|||
"TEST_MED_EDIT_LIST_STEM_CONTAINER",
|
||||
"TEST_MED_EDIT_LIST_STEM");
|
||||
|
||||
/* Write answers? */
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
|
||||
/***** Write answers? *****/
|
||||
switch (Match->Status.Showing)
|
||||
{
|
||||
case Mch_NOTHING:
|
||||
|
@ -2013,14 +2055,9 @@ static void Mch_ShowQuestionAndAnswersTch (struct Match *Match)
|
|||
|
||||
static void Mch_ShowQuestionAndAnswersStd (struct Match *Match)
|
||||
{
|
||||
bool Shuffle = false; // TODO: Read shuffle from question
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
int StdAnsInd;
|
||||
struct Mch_UsrAnswer UsrAnswer;
|
||||
unsigned NumOptions;
|
||||
unsigned NumOpt;
|
||||
unsigned Index;
|
||||
bool ErrorInIndex = false;
|
||||
|
||||
/***** Show question *****/
|
||||
/* Write buttons for answers? */
|
||||
|
@ -2030,24 +2067,14 @@ static void Mch_ShowQuestionAndAnswersStd (struct Match *Match)
|
|||
{
|
||||
/***** Get student's answer to this question
|
||||
(<0 ==> no answer) *****/
|
||||
StdAnsInd = Mch_GetQstAnsFromDB (Match->MchCod,
|
||||
Mch_GetQstAnsFromDB (Match->MchCod,
|
||||
Gbl.Usrs.Me.UsrDat.UsrCod,
|
||||
Match->Status.QstInd);
|
||||
Match->Status.QstInd,
|
||||
&UsrAnswer);
|
||||
|
||||
/***** Get number of options in this question *****/
|
||||
NumOptions = Tst_GetNumAnswersQst (Match->Status.QstCod);
|
||||
|
||||
/***** Get answers of question from database *****/
|
||||
Shuffle = false;
|
||||
NumOptions = Tst_GetAnswersQst (Match->Status.QstCod,&mysql_res,Shuffle);
|
||||
/*
|
||||
row[0] AnsInd
|
||||
row[1] Answer
|
||||
row[2] Feedback
|
||||
row[3] MedCod
|
||||
row[4] Correct
|
||||
*/
|
||||
|
||||
/***** Start table *****/
|
||||
Tbl_StartTableWide (8);
|
||||
|
||||
|
@ -2055,24 +2082,7 @@ static void Mch_ShowQuestionAndAnswersStd (struct Match *Match)
|
|||
NumOpt < NumOptions;
|
||||
NumOpt++)
|
||||
{
|
||||
/***** Get next answer *****/
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
|
||||
/***** 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 (Index >= Tst_MAX_OPTIONS_PER_QUESTION)
|
||||
ErrorInIndex = true;
|
||||
}
|
||||
else
|
||||
ErrorInIndex = true;
|
||||
if (ErrorInIndex)
|
||||
Lay_ShowErrorAndExit ("Wrong index of answer when showing a test.");
|
||||
|
||||
/***** Start row *****/
|
||||
// if (NumOpt % 2 == 0)
|
||||
fprintf (Gbl.F.Out,"<tr>");
|
||||
|
||||
/***** Write letter for this option *****/
|
||||
|
@ -2086,12 +2096,12 @@ static void Mch_ShowQuestionAndAnswersStd (struct Match *Match)
|
|||
Frm_StartForm (ActAnsMchQstStd);
|
||||
Mch_PutParamMchCod (Match->MchCod); // Current match being played
|
||||
Gam_PutParamQstInd (Match->Status.QstInd); // Current question index shown
|
||||
Mch_PutParamAnswer (Index); // Index for this option
|
||||
Mch_PutParamNumOpt (NumOpt); // Number of button
|
||||
fprintf (Gbl.F.Out,"<button type=\"submit\""
|
||||
" onmousedown=\"document.getElementById('%s').submit();"
|
||||
"return false;\" class=\"",
|
||||
Gbl.Form.Id);
|
||||
if (StdAnsInd == (int) NumOpt) // Student's answer
|
||||
if (UsrAnswer.NumOpt == (int) NumOpt) // Student's answer
|
||||
fprintf (Gbl.F.Out,"MATCH_STD_ANSWER_SELECTED ");
|
||||
fprintf (Gbl.F.Out,"MATCH_STD_BUTTON BT_%c\">"
|
||||
"%c"
|
||||
|
@ -2104,7 +2114,6 @@ static void Mch_ShowQuestionAndAnswersStd (struct Match *Match)
|
|||
fprintf (Gbl.F.Out,"</td>");
|
||||
|
||||
/***** End row *****/
|
||||
// if (NumOpt % 2 == 1)
|
||||
fprintf (Gbl.F.Out,"</tr>");
|
||||
}
|
||||
|
||||
|
@ -2116,29 +2125,28 @@ static void Mch_ShowQuestionAndAnswersStd (struct Match *Match)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************* Write parameter with student's answer *******************/
|
||||
/****** Write parameter with number of option (button) pressed by user *******/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Mch_PutParamAnswer (unsigned AnsInd)
|
||||
static void Mch_PutParamNumOpt (unsigned NumOpt)
|
||||
{
|
||||
Par_PutHiddenParamUnsigned ("Ans",AnsInd);
|
||||
Par_PutHiddenParamUnsigned ("NumOpt",NumOpt);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************* Get parameter with student's answer *********************/
|
||||
/******* Get parameter with number of option (button) pressed by user ********/
|
||||
/*****************************************************************************/
|
||||
|
||||
static unsigned Mch_GetParamAnswer (void)
|
||||
static unsigned Mch_GetParamNumOpt (void)
|
||||
{
|
||||
long LongNum;
|
||||
long NumOpt;
|
||||
|
||||
LongNum = Par_GetParToLong ("Ans");
|
||||
if (LongNum < 0)
|
||||
Lay_ShowErrorAndExit ("Wrong answer index.");
|
||||
NumOpt = Par_GetParToLong ("NumOpt");
|
||||
if (NumOpt < 0)
|
||||
Lay_ShowErrorAndExit ("Wrong number of option.");
|
||||
|
||||
return (unsigned) LongNum;
|
||||
return (unsigned) NumOpt;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -2384,32 +2392,41 @@ void Mch_RefreshMatchStd (void)
|
|||
/**** Receive previous question answer in a match question from database *****/
|
||||
/*****************************************************************************/
|
||||
|
||||
static int Mch_GetQstAnsFromDB (long MchCod,long UsrCod,unsigned QstInd)
|
||||
static void Mch_GetQstAnsFromDB (long MchCod,long UsrCod,unsigned QstInd,
|
||||
struct Mch_UsrAnswer *UsrAnswer)
|
||||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
unsigned NumRows;
|
||||
int AnsInd = -1; // <0 ==> no answer selected
|
||||
|
||||
/***** Set default values for number of option and answer index *****/
|
||||
UsrAnswer->NumOpt = -1; // < 0 ==> no answer selected
|
||||
UsrAnswer->AnsInd = -1; // < 0 ==> no answer selected
|
||||
|
||||
/***** Get student's answer *****/
|
||||
NumRows = (unsigned) DB_QuerySELECT (&mysql_res,"can not get student's answer to a match question",
|
||||
"SELECT AnsInd FROM mch_answers"
|
||||
NumRows = (unsigned) DB_QuerySELECT (&mysql_res,"can not get user's answer to a match question",
|
||||
"SELECT NumOpt," // row[0]
|
||||
"AnsInd" // row[1]
|
||||
" FROM mch_answers"
|
||||
" WHERE MchCod=%ld"
|
||||
" AND UsrCod=%ld"
|
||||
" AND QstInd=%u",
|
||||
MchCod,UsrCod,QstInd);
|
||||
if (NumRows) // Answer found...
|
||||
{
|
||||
/***** Get answer index *****/
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
if (sscanf (row[0],"%d",&AnsInd) != 1)
|
||||
|
||||
/***** Get number of option index (row[0]) *****/
|
||||
if (sscanf (row[0],"%d",&(UsrAnswer->NumOpt)) != 1)
|
||||
Lay_ShowErrorAndExit ("Error when getting student's answer to a match question.");
|
||||
|
||||
/***** Get answer index (row[1]) *****/
|
||||
if (sscanf (row[1],"%d",&(UsrAnswer->AnsInd)) != 1)
|
||||
Lay_ShowErrorAndExit ("Error when getting student's answer to a match question.");
|
||||
}
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
|
||||
return AnsInd;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -2420,8 +2437,9 @@ void Mch_ReceiveQstAnsFromStd (void)
|
|||
{
|
||||
struct Match Match;
|
||||
unsigned QstInd;
|
||||
unsigned StdAnsInd;
|
||||
int PreviousStdAnsInd;
|
||||
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION];
|
||||
struct Mch_UsrAnswer PreviousUsrAnswer;
|
||||
struct Mch_UsrAnswer UsrAnswer;
|
||||
unsigned NumQsts;
|
||||
unsigned NumQstsNotBlank;
|
||||
double TotalScore;
|
||||
|
@ -2437,39 +2455,53 @@ void Mch_ReceiveQstAnsFromStd (void)
|
|||
/***** Get question index from form *****/
|
||||
QstInd = Gam_GetParamQstInd ();
|
||||
|
||||
/***** Get indexes for this question from database *****/
|
||||
Mch_GetIndexes (Match.MchCod,QstInd,Indexes);
|
||||
|
||||
/***** Check that question index is the current one being played *****/
|
||||
if (QstInd == Match.Status.QstInd) // Receiving an answer
|
||||
// to the current question being played
|
||||
{
|
||||
/***** Get answer index *****/
|
||||
/*-------+--------------+
|
||||
| Button | Answer index |
|
||||
+--------+--------------+
|
||||
| a | 0 |
|
||||
| b | 1 |
|
||||
| c | 2 |
|
||||
| d | 3 |
|
||||
| ... | ... |
|
||||
+--------+-------------*/
|
||||
StdAnsInd = Mch_GetParamAnswer ();
|
||||
/*
|
||||
Indexes[4] = {0,3,1,2}
|
||||
+-------+--------+----------+---------+
|
||||
| Button | Option | Answer | Correct |
|
||||
| letter | number | index | |
|
||||
| screen | screen | database | |
|
||||
+--------+--------+----------+---------+
|
||||
| a | 0 | 0 | |
|
||||
| b | 1 | 3 | |
|
||||
| c | 2 | 1 | Y | <---- User press button #2 (index = 1, correct)
|
||||
| d | 3 | 2 | |
|
||||
+--------+--------+----------+---------+
|
||||
UsrAnswer.NumOpt = 2
|
||||
UsrAnswer.AnsInd = 1
|
||||
*/
|
||||
UsrAnswer.NumOpt = Mch_GetParamNumOpt ();
|
||||
UsrAnswer.AnsInd = Indexes[UsrAnswer.NumOpt];
|
||||
|
||||
/***** Get previous student's answer to this question
|
||||
(<0 ==> no answer) *****/
|
||||
PreviousStdAnsInd = Mch_GetQstAnsFromDB (Match.MchCod,Gbl.Usrs.Me.UsrDat.UsrCod,QstInd);
|
||||
Mch_GetQstAnsFromDB (Match.MchCod,Gbl.Usrs.Me.UsrDat.UsrCod,QstInd,
|
||||
&PreviousUsrAnswer);
|
||||
|
||||
/***** Store student's answer *****/
|
||||
if (PreviousStdAnsInd == (int) StdAnsInd)
|
||||
DB_QueryDELETE ("can not register your answer to the match question",
|
||||
if (PreviousUsrAnswer.AnsInd == UsrAnswer.AnsInd)
|
||||
DB_QueryDELETE ("can not remove your answer to the match question",
|
||||
"DELETE FROM mch_answers"
|
||||
" WHERE MchCod=%ld AND UsrCod=%ld AND QstInd=%u",
|
||||
Match.MchCod,Gbl.Usrs.Me.UsrDat.UsrCod,QstInd);
|
||||
else
|
||||
else if (UsrAnswer.NumOpt >= 0 &&
|
||||
UsrAnswer.AnsInd >= 0)
|
||||
DB_QueryREPLACE ("can not register your answer to the match question",
|
||||
"REPLACE mch_answers"
|
||||
" (MchCod,UsrCod,QstInd,AnsInd)"
|
||||
" (MchCod,UsrCod,QstInd,NumOpt,AnsInd)"
|
||||
" VALUES"
|
||||
" (%ld,%ld,%u,%u)",
|
||||
Match.MchCod,Gbl.Usrs.Me.UsrDat.UsrCod,QstInd,StdAnsInd);
|
||||
" (%ld,%ld,%u,%d,%d)",
|
||||
Match.MchCod,Gbl.Usrs.Me.UsrDat.UsrCod,QstInd,
|
||||
UsrAnswer.NumOpt,
|
||||
UsrAnswer.AnsInd);
|
||||
|
||||
/***** Update student's match result *****/
|
||||
NumQsts = Gam_GetNumQstsGame (Match.GamCod);
|
||||
|
@ -2529,7 +2561,7 @@ static void Mch_ComputeScore (struct Match *Match,unsigned NumQsts,long UsrCod,
|
|||
double ScoreThisQst;
|
||||
bool AnswerIsNotBlank;
|
||||
long LongNum;
|
||||
int AnsInd;
|
||||
struct Mch_UsrAnswer UsrAnswer;
|
||||
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION]; // Indexes of all answers of this question
|
||||
bool AnswersUsr[Tst_MAX_OPTIONS_PER_QUESTION];
|
||||
|
||||
|
@ -2540,11 +2572,11 @@ static void Mch_ComputeScore (struct Match *Match,unsigned NumQsts,long UsrCod,
|
|||
"SELECT gam_questions.QstCod," // row[0]
|
||||
"gam_questions.QstInd," // row[1]
|
||||
"mch_indexes.Indexes" // row[2]
|
||||
" FROM mch_matches,gam_questions,mch_questions"
|
||||
" FROM mch_matches,gam_questions,mch_indexes"
|
||||
" WHERE mch_matches.MchCod=%ld"
|
||||
" AND mch_matches.GamCod=gam_questions.GamCod"
|
||||
" AND mch_matches.MchCod=mch_indexes.MchCod"
|
||||
" AND mch_matches.QstInd=mch_indexes.QstInd"
|
||||
" AND gam_questions.QstInd=mch_indexes.QstInd"
|
||||
" ORDER BY gam_questions.QstInd");
|
||||
|
||||
/***** For each question in match... *****/
|
||||
|
@ -2568,20 +2600,22 @@ static void Mch_ComputeScore (struct Match *Match,unsigned NumQsts,long UsrCod,
|
|||
Tst_MAX_BYTES_INDEXES_ONE_QST);
|
||||
|
||||
/***** Get answers selected by user for this question *****/
|
||||
AnsInd = Mch_GetQstAnsFromDB (Match->MchCod,UsrCod,QstInd);
|
||||
if (AnsInd >= 0) // AnsInd >= 0 ==> answer selected
|
||||
Mch_GetQstAnsFromDB (Match->MchCod,UsrCod,QstInd,&UsrAnswer);
|
||||
if (UsrAnswer.AnsInd >= 0) // AnsInd >= 0 ==> answer selected
|
||||
{
|
||||
snprintf (Gbl.Test.StrAnswersOneQst[NumQst],Tst_MAX_BYTES_ANSWERS_ONE_QST + 1,
|
||||
"%d",AnsInd);
|
||||
"%d",UsrAnswer.AnsInd);
|
||||
(*NumQstsNotBlank)++;
|
||||
}
|
||||
else // AnsInd < 0 ==> no answer selected
|
||||
Gbl.Test.StrAnswersOneQst[NumQst][0] = '\0'; // Empty answer
|
||||
|
||||
/***** Get indexes for this question from string *****/
|
||||
Par_ReplaceCommaBySeparatorMultiple (Gbl.Test.StrIndexesOneQst[NumQst]);
|
||||
Tst_GetIndexesFromStr (Gbl.Test.StrIndexesOneQst[NumQst],Indexes);
|
||||
|
||||
/***** Get the user's answers for this question from string *****/
|
||||
Par_ReplaceCommaBySeparatorMultiple (Gbl.Test.StrAnswersOneQst[NumQst]);
|
||||
Tst_GetAnswersFromStr (Gbl.Test.StrAnswersOneQst[NumQst],AnswersUsr);
|
||||
|
||||
/***** Get correct answers of test question from database *****/
|
||||
|
@ -3486,7 +3520,7 @@ static void Mch_GetMatchResultQuestionsFromDB (long MchCod,long UsrCod)
|
|||
unsigned NumQst;
|
||||
long LongNum;
|
||||
unsigned QstInd;
|
||||
int AnsInd;
|
||||
struct Mch_UsrAnswer UsrAnswer;
|
||||
|
||||
/***** Get questions and answers of a match result *****/
|
||||
NumQsts = (unsigned)
|
||||
|
@ -3521,11 +3555,11 @@ static void Mch_GetMatchResultQuestionsFromDB (long MchCod,long UsrCod)
|
|||
Tst_MAX_BYTES_INDEXES_ONE_QST);
|
||||
|
||||
/* Get answers selected by user for this question */
|
||||
AnsInd = Mch_GetQstAnsFromDB (MchCod,UsrCod,QstInd);
|
||||
if (AnsInd >= 0) // AnsInd >= 0 ==> answer selected
|
||||
Mch_GetQstAnsFromDB (MchCod,UsrCod,QstInd,&UsrAnswer);
|
||||
if (UsrAnswer.AnsInd >= 0) // UsrAnswer.AnsInd >= 0 ==> answer selected
|
||||
snprintf (Gbl.Test.StrAnswersOneQst[NumQst],Tst_MAX_BYTES_ANSWERS_ONE_QST + 1,
|
||||
"%d",AnsInd);
|
||||
else // AnsInd < 0 ==> no answer selected
|
||||
"%d",UsrAnswer.AnsInd);
|
||||
else // UsrAnswer.AnsInd < 0 ==> no answer selected
|
||||
Gbl.Test.StrAnswersOneQst[NumQst][0] = '\0'; // Empty answer
|
||||
|
||||
/* Replace each comma by a separator of multiple parameters */
|
||||
|
|
|
@ -48,6 +48,8 @@ void Mch_RemoveMatchTch (void);
|
|||
|
||||
void Mch_CreateNewMatchTch (void);
|
||||
void Mch_RequestStartResumeMatchTch (void);
|
||||
void Mch_GetIndexes (long MchCod,unsigned QstInd,
|
||||
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION]);
|
||||
void Mch_PauseMatchTch (void);
|
||||
void Mch_ResumeMatchTch (void);
|
||||
void Mch_ToggleDisplayResultsMatchTch (void);
|
||||
|
|
|
@ -981,9 +981,11 @@ bool Par_GetNextStrUntilSeparParamMult (const char **StrSrc,char *StrDst,size_t
|
|||
do
|
||||
if ((Ch = (unsigned char) **StrSrc))
|
||||
(*StrSrc)++;
|
||||
while (Ch && Ch < 32); // Skip special characters (the separator will be a special character less than 32)
|
||||
while (Ch && Ch < 32); // Skip special characters
|
||||
// (the separator will be a special character
|
||||
// less than 32)
|
||||
|
||||
while (Ch >= 32)
|
||||
while (Ch >= 32) // Until special character or end
|
||||
{
|
||||
CharsFound = true;
|
||||
if (i < LongMax)
|
||||
|
|
|
@ -85,6 +85,7 @@ unsigned Par_GetParAndChangeFormat (const char *ParamName,char *ParamValue,size_
|
|||
Str_ChangeTo_t ChangeTo,bool RemoveLeadingAndTrailingSpaces);
|
||||
|
||||
bool Par_GetNextStrUntilSeparParamMult (const char **StrSrc,char *StrDst,size_t LongMax);
|
||||
bool Par_GetNextStrUntilComma (const char **StrSrc,char *StrDst,size_t LongMax);
|
||||
void Par_ReplaceSeparatorMultipleByComma (const char *StrSrc,char *StrDst);
|
||||
void Par_ReplaceCommaBySeparatorMultiple (char *Str);
|
||||
|
||||
|
|
78
swad_test.c
78
swad_test.c
|
@ -4017,13 +4017,22 @@ void Tst_GetIndexesFromStr (const char StrIndexesOneQst[Tst_MAX_BYTES_INDEXES_ON
|
|||
const char *Ptr;
|
||||
char StrOneIndex[10 + 1];
|
||||
|
||||
/***** Initialize to 0 *****/
|
||||
for (NumOpt = 0, Ptr = StrIndexesOneQst;
|
||||
NumOpt < Gbl.Test.Answer.NumOptions;
|
||||
NumOpt < Tst_MAX_OPTIONS_PER_QUESTION && *Ptr;
|
||||
NumOpt++)
|
||||
Indexes[NumOpt] = 0;
|
||||
|
||||
/***** Get indexes from string *****/
|
||||
for (NumOpt = 0, Ptr = StrIndexesOneQst;
|
||||
NumOpt < Tst_MAX_OPTIONS_PER_QUESTION && *Ptr;
|
||||
NumOpt++)
|
||||
{
|
||||
Par_GetNextStrUntilSeparParamMult (&Ptr,StrOneIndex,10);
|
||||
if (sscanf (StrOneIndex,"%u",&(Indexes[NumOpt])) != 1)
|
||||
Lay_ShowErrorAndExit ("Wrong index of answer when assessing a test.");
|
||||
Lay_ShowErrorAndExit ("Wrong index of answer.");
|
||||
if (Indexes[NumOpt] >= Tst_MAX_OPTIONS_PER_QUESTION)
|
||||
Lay_ShowErrorAndExit ("Wrong index of answer.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4136,12 +4145,10 @@ static void Tst_WriteChoiceAnsViewMatch (long MchCod,unsigned QstInd,long QstCod
|
|||
unsigned NumOpt;
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
unsigned AnsInd;
|
||||
unsigned NumAnswerersQst;
|
||||
bool Correct;
|
||||
bool ErrorInIndex = false;
|
||||
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION]; // Indexes of all answers of this question
|
||||
|
||||
/***** Get number of users who hasve answered this question from database *****/
|
||||
/***** Get number of users who have answered this question from database *****/
|
||||
NumAnswerersQst = Mch_GetNumUsrsWhoHaveAnswerQst (MchCod,QstInd);
|
||||
|
||||
/***** Get answers of a question from database *****/
|
||||
|
@ -4154,45 +4161,47 @@ static void Tst_WriteChoiceAnsViewMatch (long MchCod,unsigned QstInd,long QstCod
|
|||
row[4] Correct
|
||||
*/
|
||||
|
||||
/***** Start table *****/
|
||||
Tbl_StartTableWide (2);
|
||||
|
||||
for (NumOpt = 0;
|
||||
NumOpt < Gbl.Test.Answer.NumOptions;
|
||||
NumOpt++)
|
||||
{
|
||||
/***** Get next answer *****/
|
||||
/* Get next answer */
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
|
||||
/***** Allocate memory for text in this choice answer *****/
|
||||
/* Allocate memory for text in this choice answer */
|
||||
if (!Tst_AllocateTextChoiceAnswer (NumOpt))
|
||||
/* Abort on error */
|
||||
Ale_ShowAlertsAndExit ();
|
||||
|
||||
/***** 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",&AnsInd) == 1)
|
||||
{
|
||||
if (AnsInd >= Tst_MAX_OPTIONS_PER_QUESTION)
|
||||
ErrorInIndex = true;
|
||||
}
|
||||
else
|
||||
ErrorInIndex = true;
|
||||
if (ErrorInIndex)
|
||||
Lay_ShowErrorAndExit ("Wrong index of answer when showing a test.");
|
||||
|
||||
/***** Copy text (row[1]) and convert it, that is in HTML, to rigorous HTML ******/
|
||||
/* Copy text (row[1]) and convert it, that is in HTML, to rigorous HTML */
|
||||
Str_Copy (Gbl.Test.Answer.Options[NumOpt].Text,row[1],
|
||||
Tst_MAX_BYTES_ANSWER_OR_FEEDBACK);
|
||||
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
||||
Gbl.Test.Answer.Options[NumOpt].Text,
|
||||
Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false);
|
||||
|
||||
/***** Get media (row[3]) *****/
|
||||
/* Get media (row[3]) */
|
||||
Gbl.Test.Answer.Options[NumOpt].Media.MedCod = Str_ConvertStrCodToLongCod (row[3]);
|
||||
Med_GetMediaDataByCod (&Gbl.Test.Answer.Options[NumOpt].Media);
|
||||
|
||||
/* Get if correct (row[4]) */
|
||||
Gbl.Test.Answer.Options[NumOpt].Correct = (row[4][0] == 'Y');
|
||||
}
|
||||
|
||||
/* Free structure that stores the query result */
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
|
||||
/***** Get indexes for this question in match *****/
|
||||
Mch_GetIndexes (MchCod,QstInd,Indexes);
|
||||
|
||||
/***** Start table *****/
|
||||
Tbl_StartTableWide (2);
|
||||
|
||||
/***** Show one row for each option *****/
|
||||
for (NumOpt = 0;
|
||||
NumOpt < Gbl.Test.Answer.NumOptions;
|
||||
NumOpt++)
|
||||
{
|
||||
/***** Start row for this option *****/
|
||||
fprintf (Gbl.F.Out,"<tr>");
|
||||
|
||||
|
@ -4212,22 +4221,18 @@ static void Tst_WriteChoiceAnsViewMatch (long MchCod,unsigned QstInd,long QstCod
|
|||
"</label>",
|
||||
QstInd,NumOpt,
|
||||
Class,
|
||||
Gbl.Test.Answer.Options[NumOpt].Text);
|
||||
Med_ShowMedia (&Gbl.Test.Answer.Options[NumOpt].Media,
|
||||
Gbl.Test.Answer.Options[Indexes[NumOpt]].Text);
|
||||
Med_ShowMedia (&Gbl.Test.Answer.Options[Indexes[NumOpt]].Media,
|
||||
"TEST_MED_SHOW_CONTAINER",
|
||||
"TEST_MED_SHOW");
|
||||
|
||||
/* Show result (number of users who answered? */
|
||||
if (ShowResult)
|
||||
{
|
||||
/* Get if correct (row[4]) */
|
||||
Correct = (row[4][0] == 'Y');
|
||||
|
||||
/* Get number of users who selected this answer
|
||||
and draw proportional bar */
|
||||
Mch_GetAndDrawBarNumUsrsWhoHaveChosenAns (MchCod,QstInd,AnsInd,
|
||||
NumAnswerersQst,Correct);
|
||||
}
|
||||
Mch_GetAndDrawBarNumUsrsWhoHaveChosenAns (MchCod,QstInd,Indexes[NumOpt],
|
||||
NumAnswerersQst,
|
||||
Gbl.Test.Answer.Options[Indexes[NumOpt]].Correct);
|
||||
|
||||
fprintf (Gbl.F.Out,"</td>");
|
||||
|
||||
|
@ -4237,9 +4242,6 @@ static void Tst_WriteChoiceAnsViewMatch (long MchCod,unsigned QstInd,long QstCod
|
|||
|
||||
/***** End table *****/
|
||||
Tbl_EndTable ();
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
Loading…
Reference in New Issue