Version19.9

This commit is contained in:
Antonio Cañas Vargas 2019-09-23 01:48:28 +02:00
parent 1f02939f6c
commit f946925237
7 changed files with 329 additions and 154 deletions

View File

@ -661,13 +661,11 @@ CREATE TABLE IF NOT EXISTS mch_players (
-- Table mch_results: stores the current match results
--
CREATE TABLE IF NOT EXISTS mch_results (
MchResCod INT NOT NULL AUTO_INCREMENT,
MchCod INT NOT NULL,
UsrCod INT NOT NULL,
NumQsts INT NOT NULL DEFAULT 0,
NumQstsNotBlank INT NOT NULL DEFAULT 0,
Score DOUBLE PRECISION NOT NULL DEFAULT 0,
UNIQUE INDEX(MchResCod),
UNIQUE INDEX(MchCod,UsrCod));
--
-- Table gam_questions: stores the questions in the games

View File

@ -468,10 +468,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.8.2 (2019-09-22)"
#define Log_PLATFORM_VERSION "SWAD 19.9 (2019-09-23)"
#define CSS_FILE "swad19.3.css"
#define JS_FILE "swad18.130.2.js"
/*
Version 19.9: Sep 23, 2019 View matches results. Not finished. (245579 lines)
2 changes necessary in database:
DROP TABLE IF EXISTS mch_results;
CREATE TABLE IF NOT EXISTS mch_results (MchCod INT NOT NULL,UsrCod INT NOT NULL,NumQsts INT NOT NULL DEFAULT 0,NumQstsNotBlank INT NOT NULL DEFAULT 0,Score DOUBLE PRECISION NOT NULL DEFAULT 0,UNIQUE INDEX(MchCod,UsrCod));
Version 19.8.2: Sep 22, 2019 View matches results. Not finished. (245429 lines)
Version 19.8.1: Sep 22, 2019 View matches results. Not finished. (245474 lines)
Version 19.8: Sep 22, 2019 View matches results. Not finished.

View File

@ -1436,26 +1436,23 @@ mysql> DESCRIBE mch_players;
/***** Table mch_results *****/
/*
mysql> DESCRIBE mch_results;
+-----------------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+---------+------+-----+---------+----------------+
| MchResCod | int(11) | NO | PRI | NULL | auto_increment |
| MchCod | int(11) | NO | MUL | NULL | |
| UsrCod | int(11) | NO | | NULL | |
| NumQsts | int(11) | NO | | 0 | |
| NumQstsNotBlank | int(11) | NO | | 0 | |
| Score | double | NO | | 0 | |
+-----------------+---------+------+-----+---------+----------------+
6 rows in set (0.01 sec)
+-----------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+---------+------+-----+---------+-------+
| MchCod | int(11) | NO | PRI | NULL | |
| UsrCod | int(11) | NO | PRI | NULL | |
| NumQsts | int(11) | NO | | 0 | |
| NumQstsNotBlank | int(11) | NO | | 0 | |
| Score | double | NO | | 0 | |
+-----------------+---------+------+-----+---------+-------+
5 rows in set (0.00 sec)
*/
DB_CreateTable ("CREATE TABLE IF NOT EXISTS mch_results ("
"MchResCod INT NOT NULL AUTO_INCREMENT,"
"MchCod INT NOT NULL,"
"UsrCod INT NOT NULL,"
"NumQsts INT NOT NULL DEFAULT 0,"
"NumQstsNotBlank INT NOT NULL DEFAULT 0,"
"Score DOUBLE PRECISION NOT NULL DEFAULT 0,"
"UNIQUE INDEX(MchResCod),"
"UNIQUE INDEX(MchCod,UsrCod))");
/***** Table gam_questions *****/

View File

@ -192,6 +192,8 @@ static void Mch_RegisterMeAsPlayerInMatch (long MchCod);
static void Mch_GetNumPlayers (struct Match *Match);
static int Mch_GetQstAnsFromDB (long MchCod,unsigned QstInd);
static void Mch_ComputeScore (struct Match *Match,unsigned NumQsts,
unsigned *NumQstsNotBlank,double *TotalScore);
static unsigned Mch_GetNumUsrsWhoHaveChosenAns (long MchCod,unsigned QstInd,unsigned AnsInd);
static unsigned Mch_GetNumUsrsWhoHaveAnswerMch (long MchCod);
@ -2286,6 +2288,9 @@ void Mch_ReceiveQstAnsFromStd (void)
unsigned QstInd;
unsigned StdAnsInd;
int PreviousStdAnsInd;
unsigned NumQsts;
unsigned NumQstsNotBlank;
double TotalScore;
/***** Remove old players.
This function must be called before getting match status. *****/
@ -2331,6 +2336,20 @@ void Mch_ReceiveQstAnsFromStd (void)
" VALUES"
" (%ld,%ld,%u,%u)",
Match.MchCod,Gbl.Usrs.Me.UsrDat.UsrCod,QstInd,StdAnsInd);
/***** Update student's match result *****/
NumQsts = Gam_GetNumQstsGame (Match.GamCod);
Mch_ComputeScore (&Match,NumQsts,&NumQstsNotBlank,&TotalScore);
Str_SetDecimalPointToUS (); // To print the floating point as a dot
DB_QueryREPLACE ("can not update match result",
"REPLACE mch_results"
" (MchCod,UsrCod,NumQsts,NumQstsNotBlank,Score)"
" VALUES"
" (%ld,%ld,%u,%u,'%lf')",
Match.MchCod,Gbl.Usrs.Me.UsrDat.UsrCod,
NumQsts,NumQstsNotBlank,TotalScore);
Str_SetDecimalPointToLocal (); // Return to local system
}
/***** Show current match status *****/
@ -2339,6 +2358,126 @@ void Mch_ReceiveQstAnsFromStd (void)
fprintf (Gbl.F.Out,"</div>");
}
/*****************************************************************************/
/******************** Compute match score for a student **********************/
/*****************************************************************************/
static void Mch_ComputeScore (struct Match *Match,unsigned NumQsts,
unsigned *NumQstsNotBlank,double *TotalScore)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumQst;
unsigned NumQstNotBlank;
unsigned QstInd;
unsigned NumOpt;
long QstCod;
long LongNum;
double ScoreThisQst;
bool AnswerIsNotBlank;
struct UsrAnswer
{
unsigned QstInd;
unsigned AnsInd;
} *UsrAnswers;
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION]; // Indexes of all answers of this question
bool AnswersUsr[Tst_MAX_OPTIONS_PER_QUESTION];
/***** Get user's answers *****/
/* Query database */
*NumQstsNotBlank = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get user's answers",
"SELECT QstInd," // row[0]
"AnsInd" // row[1]
" FROM mch_answers"
" WHERE MchCod=%ld AND UsrCod=%ld",
Match->MchCod,Gbl.Usrs.Me.UsrDat.UsrCod);
/* Allocate memory for answers */
if ((UsrAnswers = (struct UsrAnswer *) malloc (*NumQstsNotBlank *
sizeof (struct UsrAnswer))) == NULL)
Lay_NotEnoughMemoryExit ();
/* Get answers from database */
for (NumQstNotBlank = 0;
NumQstNotBlank < *NumQstsNotBlank;
NumQstNotBlank++)
{
row = mysql_fetch_row (mysql_res);
/* Get question index (row[0]) */
if ((LongNum = Str_ConvertStrCodToLongCod (row[0])) < 0)
Lay_ShowErrorAndExit ("Wrong question index.");
UsrAnswers[NumQstNotBlank].QstInd = (unsigned) LongNum;
/* Get answer index (row[1]) */
if ((LongNum = Str_ConvertStrCodToLongCod (row[1])) < 0)
Lay_ShowErrorAndExit ("Wrong answer index.");
UsrAnswers[NumQstNotBlank].AnsInd = (unsigned) LongNum;
}
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_res);
/***** For each question in match... *****/
for (NumQst = 0, *TotalScore = 0.0;
NumQst < NumQsts;
NumQst++)
{
QstInd = NumQst + 1;
/***** Get question code *****/
QstCod = Gam_GetQstCodFromQstInd (Match->GamCod,QstInd);
/***** Get answers of test question from database *****/
/* Query database */
Gbl.Test.Answer.NumOptions = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get answers of a question",
"SELECT Correct" // row[0]
" FROM tst_answers"
" WHERE QstCod=%ld ORDER BY AnsInd",
QstCod);
for (NumOpt = 0;
NumOpt < Gbl.Test.Answer.NumOptions;
NumOpt++)
{
/* Get next answer */
row = mysql_fetch_row (mysql_res);
/* Assign correctness (row[0]) of this answer (this option) */
Gbl.Test.Answer.Options[NumOpt].Correct = (row[0][0] == 'Y');
}
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_res);
/***** Get indexes for this question *****/
// TODO: Answers should be shuffled?
for (NumOpt = 0;
NumOpt < Gbl.Test.Answer.NumOptions;
NumOpt++)
Indexes[NumOpt] = NumOpt;
/***** Get the user's answers for this question *****/
for (NumOpt = 0;
NumOpt < Gbl.Test.Answer.NumOptions;
NumOpt++)
AnswersUsr[NumOpt] = false;
for (NumQstNotBlank = 0;
NumQstNotBlank < *NumQstsNotBlank;
NumQstNotBlank++)
if (UsrAnswers[NumQstNotBlank].QstInd == QstInd)
if (UsrAnswers[NumQstNotBlank].AnsInd < Gbl.Test.Answer.NumOptions)
AnswersUsr[UsrAnswers[NumQstNotBlank].AnsInd] = true;
/***** Compute the total score of this question *****/
Tst_ComputeScoreQst (Indexes,AnswersUsr,&ScoreThisQst,&AnswerIsNotBlank);
/***** Compute total score *****/
*TotalScore += ScoreThisQst;
}
}
/*****************************************************************************/
/*** Get number of users who selected this answer and draw proportional bar **/
/*****************************************************************************/

View File

@ -2638,7 +2638,7 @@ void Prj_GetDataOfProjectByCod (struct Project *Prj)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
long NumLong;
long LongNum;
Prj_Proposal_t Proposal;
if (Prj->PrjCod > 0)
@ -2693,9 +2693,9 @@ void Prj_GetDataOfProjectByCod (struct Project *Prj)
Prj_NONPREASSIG;
/* Get if project is preassigned or not (row[6]) */
NumLong = Str_ConvertStrCodToLongCod (row[6]);
if (NumLong >= 0)
Prj->NumStds = (unsigned) NumLong;
LongNum = Str_ConvertStrCodToLongCod (row[6]);
if (LongNum >= 0)
Prj->NumStds = (unsigned) LongNum;
else
Prj->NumStds = 1;

View File

@ -3284,7 +3284,8 @@ unsigned Tst_GetAnswersQst (long QstCod,MYSQL_RES **mysql_res,bool Shuffle)
"Feedback," // row[2]
"MedCod," // row[3]
"Correct" // row[4]
" FROM tst_answers WHERE QstCod=%ld ORDER BY %s",
" FROM tst_answers"
" WHERE QstCod=%ld ORDER BY %s",
QstCod,
Shuffle ? "RAND(NOW())" :
"AnsInd");
@ -3794,7 +3795,6 @@ static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat,
extern const char *Txt_TST_Answer_given_by_the_user;
extern const char *Txt_TST_Answer_given_by_the_teachers;
unsigned NumOpt;
MYSQL_ROW row;
char StrOneIndex[10 + 1];
const char *Ptr;
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION]; // Indexes of all answers of this question
@ -3805,10 +3805,152 @@ static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat,
char *Class;
char *Str;
} Ans;
unsigned NumOptTotInQst = 0;
unsigned NumOptCorrInQst = 0;
unsigned NumAnsGood = 0;
unsigned NumAnsBad = 0;
/***** Get text and correctness of answers for this question
from database (one row per answer) *****/
Tst_GetChoiceAns (mysql_res);
/***** Get indexes for this question from string *****/
for (NumOpt = 0, Ptr = Gbl.Test.StrIndexesOneQst[NumQst];
NumOpt < Gbl.Test.Answer.NumOptions;
NumOpt++)
{
Par_GetNextStrUntilSeparParamMult (&Ptr,StrOneIndex,10);
if (sscanf (StrOneIndex,"%u",&(Indexes[NumOpt])) != 1)
Lay_ShowErrorAndExit ("Wrong index of answer when assessing a test.");
}
/***** Get the user's answers for this question from string *****/
for (NumOpt = 0;
NumOpt < Tst_MAX_OPTIONS_PER_QUESTION;
NumOpt++)
AnswersUsr[NumOpt] = false;
for (NumOpt = 0, Ptr = Gbl.Test.StrAnswersOneQst[NumQst];
NumOpt < Gbl.Test.Answer.NumOptions;
NumOpt++)
if (*Ptr)
{
Par_GetNextStrUntilSeparParamMult (&Ptr,StrOneIndex,10);
if (sscanf (StrOneIndex,"%d",&AnsUsr) != 1)
Lay_ShowErrorAndExit ("Bad user's answer.");
if (AnsUsr < 0 || AnsUsr >= Tst_MAX_OPTIONS_PER_QUESTION)
Lay_ShowErrorAndExit ("Bad user's answer.");
AnswersUsr[AnsUsr] = true;
}
/***** Compute the total score of this question *****/
Tst_ComputeScoreQst (Indexes,AnswersUsr,ScoreThisQst,AnswerIsNotBlank);
/***** Start table *****/
Tbl_StartTable (2);
fprintf (Gbl.F.Out,"<tr>");
Tst_WriteHeadUserCorrect (UsrDat);
fprintf (Gbl.F.Out,"<td></td>"
"<td></td>"
"</tr>");
/***** Write answers (one row per answer) *****/
for (NumOpt = 0;
NumOpt < Gbl.Test.Answer.NumOptions;
NumOpt++)
{
fprintf (Gbl.F.Out,"<tr>");
/* Draw icon depending on user's answer */
if (AnswersUsr[Indexes[NumOpt]] == true) // This answer has been selected by the user
{
if (Gbl.Test.Config.Feedback == Tst_FEEDBACK_EACH_GOOD_BAD ||
Gbl.Test.Config.Feedback == Tst_FEEDBACK_FULL_FEEDBACK)
{
if (Gbl.Test.Answer.Options[Indexes[NumOpt]].Correct)
{
Ans.Class = "ANS_OK";
Ans.Str = "&check;";
}
else
{
Ans.Class = "ANS_BAD";
Ans.Str = "&cross;";
}
}
else
{
Ans.Class = "ANS_0";
Ans.Str = "&bull;";
}
fprintf (Gbl.F.Out,"<td class=\"%s CENTER_TOP\" title=\"%s\">%s</td>",
Ans.Class,Txt_TST_Answer_given_by_the_user,Ans.Str);
}
else // This answer has NOT been selected by the user
fprintf (Gbl.F.Out,"<td></td>");
/* Draw icon that indicates whether the answer is correct */
if (Gbl.Test.Config.Feedback == Tst_FEEDBACK_EACH_GOOD_BAD ||
Gbl.Test.Config.Feedback == Tst_FEEDBACK_FULL_FEEDBACK)
{
if (Gbl.Test.Answer.Options[Indexes[NumOpt]].Correct)
fprintf (Gbl.F.Out,"<td class=\"ANS_0 CENTER_TOP\" title=\"%s\">&bull;</td>",
Txt_TST_Answer_given_by_the_teachers);
else
fprintf (Gbl.F.Out,"<td></td>");
}
else
fprintf (Gbl.F.Out,"<td class=\"ANS_0 CENTER_TOP\">?</td>");
/* Answer letter (a, b, c,...) */
fprintf (Gbl.F.Out,"<td class=\"ANS_TXT LEFT_TOP\">"
"%c)&nbsp;"
"</td>",
'a' + (char) NumOpt);
/* Answer text and feedback */
fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP\">"
"<div class=\"ANS_TXT\">"
"%s",
Gbl.Test.Answer.Options[Indexes[NumOpt]].Text);
Med_ShowMedia (&Gbl.Test.Answer.Options[Indexes[NumOpt]].Media,
"TEST_MED_SHOW_CONTAINER",
"TEST_MED_SHOW");
fprintf (Gbl.F.Out,"</div>");
if (Gbl.Test.Config.Feedback == Tst_FEEDBACK_FULL_FEEDBACK)
if (Gbl.Test.Answer.Options[Indexes[NumOpt]].Feedback)
if (Gbl.Test.Answer.Options[Indexes[NumOpt]].Feedback[0])
fprintf (Gbl.F.Out,"<div class=\"TEST_EXA_LIGHT\">"
"%s"
"</div>",
Gbl.Test.Answer.Options[Indexes[NumOpt]].Feedback);
fprintf (Gbl.F.Out,"</td>"
"</tr>");
}
/***** Write the total score of this question *****/
if (Gbl.Test.Config.Feedback == Tst_FEEDBACK_EACH_RESULT ||
Gbl.Test.Config.Feedback == Tst_FEEDBACK_EACH_GOOD_BAD ||
Gbl.Test.Config.Feedback == Tst_FEEDBACK_FULL_FEEDBACK)
{
Tst_WriteScoreStart (4);
if (*ScoreThisQst == 0.0)
fprintf (Gbl.F.Out,"ANS_0");
else if (*ScoreThisQst > 0.0)
fprintf (Gbl.F.Out,"ANS_OK");
else
fprintf (Gbl.F.Out,"ANS_BAD");
fprintf (Gbl.F.Out,"\">%.2lf",*ScoreThisQst);
Tst_WriteScoreEnd ();
}
/***** End table *****/
Tbl_EndTable ();
}
/*****************************************************************************/
/************************ Get choice answer from row *************************/
/*****************************************************************************/
void Tst_GetChoiceAns (MYSQL_RES *mysql_res)
{
unsigned NumOpt;
MYSQL_ROW row;
/***** Get text and correctness of answers for this question
from database (one row per answer) *****/
@ -3859,118 +4001,31 @@ static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat,
/***** Assign correctness (row[4]) of this answer (this option) *****/
Gbl.Test.Answer.Options[NumOpt].Correct = (row[4][0] == 'Y');
}
}
/***** Get indexes for this question from string *****/
for (NumOpt = 0, Ptr = Gbl.Test.StrIndexesOneQst[NumQst];
NumOpt < Gbl.Test.Answer.NumOptions;
NumOpt++)
{
Par_GetNextStrUntilSeparParamMult (&Ptr,StrOneIndex,10);
if (sscanf (StrOneIndex,"%u",&(Indexes[NumOpt])) != 1)
Lay_ShowErrorAndExit ("Wrong index of answer when assessing a test.");
}
/*****************************************************************************/
/********************* Compute the score of this question ********************/
/*****************************************************************************/
/***** Get the user's answers for this question from string *****/
for (NumOpt = 0;
NumOpt < Tst_MAX_OPTIONS_PER_QUESTION;
NumOpt++)
AnswersUsr[NumOpt] = false;
for (NumOpt = 0, Ptr = Gbl.Test.StrAnswersOneQst[NumQst];
NumOpt < Gbl.Test.Answer.NumOptions;
NumOpt++)
if (*Ptr)
{
Par_GetNextStrUntilSeparParamMult (&Ptr,StrOneIndex,10);
if (sscanf (StrOneIndex,"%d",&AnsUsr) != 1)
Lay_ShowErrorAndExit ("Bad user's answer.");
if (AnsUsr < 0 || AnsUsr >= Tst_MAX_OPTIONS_PER_QUESTION)
Lay_ShowErrorAndExit ("Bad user's answer.");
AnswersUsr[AnsUsr] = true;
}
void Tst_ComputeScoreQst (unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION], // Indexes of all answers of this question
bool AnswersUsr[Tst_MAX_OPTIONS_PER_QUESTION],
double *ScoreThisQst,bool *AnswerIsNotBlank)
{
unsigned NumOpt;
unsigned NumOptTotInQst = 0;
unsigned NumOptCorrInQst = 0;
unsigned NumAnsGood = 0;
unsigned NumAnsBad = 0;
/***** Start table *****/
Tbl_StartTable (2);
fprintf (Gbl.F.Out,"<tr>");
Tst_WriteHeadUserCorrect (UsrDat);
fprintf (Gbl.F.Out,"<td></td>"
"<td></td>"
"</tr>");
/***** Write answers (one row per answer) *****/
/***** Compute the total score of this question *****/
for (NumOpt = 0;
NumOpt < Gbl.Test.Answer.NumOptions;
NumOpt++)
{
fprintf (Gbl.F.Out,"<tr>");
/* Draw icon depending on user's answer */
if (AnswersUsr[Indexes[NumOpt]] == true) // This answer has been selected by the user
{
if (Gbl.Test.Config.Feedback == Tst_FEEDBACK_EACH_GOOD_BAD ||
Gbl.Test.Config.Feedback == Tst_FEEDBACK_FULL_FEEDBACK)
{
if (Gbl.Test.Answer.Options[Indexes[NumOpt]].Correct)
{
Ans.Class = "ANS_OK";
Ans.Str = "&check;";
}
else
{
Ans.Class = "ANS_BAD";
Ans.Str = "&cross;";
}
}
else
{
Ans.Class = "ANS_0";
Ans.Str = "&bull;";
}
fprintf (Gbl.F.Out,"<td class=\"%s CENTER_TOP\" title=\"%s\">%s</td>",
Ans.Class,Txt_TST_Answer_given_by_the_user,Ans.Str);
}
else // This answer has NOT been selected by the user
fprintf (Gbl.F.Out,"<td></td>");
/* Draw icon that indicates whether the answer is correct */
if (Gbl.Test.Config.Feedback == Tst_FEEDBACK_EACH_GOOD_BAD ||
Gbl.Test.Config.Feedback == Tst_FEEDBACK_FULL_FEEDBACK)
{
if (Gbl.Test.Answer.Options[Indexes[NumOpt]].Correct)
fprintf (Gbl.F.Out,"<td class=\"ANS_0 CENTER_TOP\" title=\"%s\">&bull;</td>",
Txt_TST_Answer_given_by_the_teachers);
else
fprintf (Gbl.F.Out,"<td></td>");
}
else
fprintf (Gbl.F.Out,"<td class=\"ANS_0 CENTER_TOP\">?</td>");
/* Answer letter (a, b, c,...) */
fprintf (Gbl.F.Out,"<td class=\"ANS_TXT LEFT_TOP\">"
"%c)&nbsp;"
"</td>",
'a' + (char) NumOpt);
/* Answer text and feedback */
fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP\">"
"<div class=\"ANS_TXT\">"
"%s",
Gbl.Test.Answer.Options[Indexes[NumOpt]].Text);
Med_ShowMedia (&Gbl.Test.Answer.Options[Indexes[NumOpt]].Media,
"TEST_MED_SHOW_CONTAINER",
"TEST_MED_SHOW");
fprintf (Gbl.F.Out,"</div>");
if (Gbl.Test.Config.Feedback == Tst_FEEDBACK_FULL_FEEDBACK)
if (Gbl.Test.Answer.Options[Indexes[NumOpt]].Feedback)
if (Gbl.Test.Answer.Options[Indexes[NumOpt]].Feedback[0])
fprintf (Gbl.F.Out,"<div class=\"TEST_EXA_LIGHT\">"
"%s"
"</div>",
Gbl.Test.Answer.Options[Indexes[NumOpt]].Feedback);
fprintf (Gbl.F.Out,"</td>"
"</tr>");
NumOptTotInQst++;
if (Gbl.Test.Answer.Options[Indexes[NumOpt]].Correct)
NumOptCorrInQst++;
if (AnswersUsr[Indexes[NumOpt]] == true) // This answer has been selected by the user
{
if (Gbl.Test.Answer.Options[Indexes[NumOpt]].Correct)
@ -3978,14 +4033,10 @@ static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat,
else
NumAnsBad++;
}
if (Gbl.Test.Answer.Options[Indexes[NumOpt]].Correct)
NumOptCorrInQst++;
}
/***** The answer is blank? *****/
/* The answer is blank? */
*AnswerIsNotBlank = NumAnsGood != 0 || NumAnsBad != 0;
/***** Compute and write the total score of this question *****/
if (*AnswerIsNotBlank)
{
/* Compute the score */
@ -4018,25 +4069,6 @@ static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat,
}
else // Answer is blank
*ScoreThisQst = 0.0;
/* Write the score */
if (Gbl.Test.Config.Feedback == Tst_FEEDBACK_EACH_RESULT ||
Gbl.Test.Config.Feedback == Tst_FEEDBACK_EACH_GOOD_BAD ||
Gbl.Test.Config.Feedback == Tst_FEEDBACK_FULL_FEEDBACK)
{
Tst_WriteScoreStart (4);
if (*ScoreThisQst == 0.0)
fprintf (Gbl.F.Out,"ANS_0");
else if (*ScoreThisQst > 0.0)
fprintf (Gbl.F.Out,"ANS_OK");
else
fprintf (Gbl.F.Out,"ANS_BAD");
fprintf (Gbl.F.Out,"\">%.2lf",*ScoreThisQst);
Tst_WriteScoreEnd ();
}
/***** End table *****/
Tbl_EndTable ();
}
/*****************************************************************************/

View File

@ -158,6 +158,10 @@ void Tst_WriteAnswersMatchResult (long MchCod,unsigned QstInd,long QstCod,
const char *Class,bool ShowResult);
bool Tst_CheckIfQuestionIsValidForGame (long QstCod);
void Tst_WriteAnsTF (char AnsTF);
void Tst_GetChoiceAns (MYSQL_RES *mysql_res);
void Tst_ComputeScoreQst (unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION],
bool AnswersUsr[Tst_MAX_OPTIONS_PER_QUESTION],
double *ScoreThisQst,bool *AnswerIsNotBlank);
void Tst_CheckIfNumberOfAnswersIsOne (void);
unsigned long Tst_GetTagsQst (long QstCod,MYSQL_RES **mysql_res);