mirror of https://github.com/acanas/swad-core.git
Version19.152
This commit is contained in:
parent
2e74679789
commit
5592e9b8b3
|
@ -497,7 +497,7 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - *
|
||||||
En OpenSWAD:
|
En OpenSWAD:
|
||||||
ps2pdf source.ps destination.pdf
|
ps2pdf source.ps destination.pdf
|
||||||
*/
|
*/
|
||||||
#define Log_PLATFORM_VERSION "SWAD 19.151.4 (2020-03-22)"
|
#define Log_PLATFORM_VERSION "SWAD 19.152 (2020-03-23)"
|
||||||
#define CSS_FILE "swad19.146.css"
|
#define CSS_FILE "swad19.146.css"
|
||||||
#define JS_FILE "swad19.91.1.js"
|
#define JS_FILE "swad19.91.1.js"
|
||||||
/*
|
/*
|
||||||
|
@ -524,6 +524,7 @@ Param
|
||||||
// TODO: Oresti Baños: cambiar ojos por candados en descriptores para prohibir/permitir y dejar los ojos para poder elegir descriptores
|
// TODO: Oresti Baños: cambiar ojos por candados en descriptores para prohibir/permitir y dejar los ojos para poder elegir descriptores
|
||||||
// TODO: Si el alumno ha marcado "Permitir que los profesores...", entonces pedir confirmación al pulsar el botón azul, para evitar que se envíe por error antes de tiempo
|
// TODO: Si el alumno ha marcado "Permitir que los profesores...", entonces pedir confirmación al pulsar el botón azul, para evitar que se envíe por error antes de tiempo
|
||||||
|
|
||||||
|
Version 19.152: Mar 23, 2020 Code refactoring in tests. (283525 lines)
|
||||||
Version 19.151.4: Mar 22, 2020 Code refactoring in tests. (283471 lines)
|
Version 19.151.4: Mar 22, 2020 Code refactoring in tests. (283471 lines)
|
||||||
Version 19.151.3: Mar 22, 2020 Code refactoring in tests. (283433 lines)
|
Version 19.151.3: Mar 22, 2020 Code refactoring in tests. (283433 lines)
|
||||||
Version 19.151.2: Mar 21, 2020 Code refactoring in tests. (283446 lines)
|
Version 19.151.2: Mar 21, 2020 Code refactoring in tests. (283446 lines)
|
||||||
|
|
22
swad_game.c
22
swad_game.c
|
@ -156,7 +156,7 @@ static void Gam_ListGameQuestions (struct Game *Game);
|
||||||
static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts,
|
static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts,
|
||||||
MYSQL_RES *mysql_res,
|
MYSQL_RES *mysql_res,
|
||||||
bool ICanEditQuestions);
|
bool ICanEditQuestions);
|
||||||
static void Gam_ListQuestionForEdition (long QstCod,const char *StrQstInd);
|
static void Gam_ListQuestionForEdition (long QstCod,unsigned QstInd);
|
||||||
static void Gam_PutIconToAddNewQuestions (void);
|
static void Gam_PutIconToAddNewQuestions (void);
|
||||||
static void Gam_PutButtonToAddNewQuestions (void);
|
static void Gam_PutButtonToAddNewQuestions (void);
|
||||||
|
|
||||||
|
@ -1972,7 +1972,7 @@ static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts,
|
||||||
HTM_TD_End ();
|
HTM_TD_End ();
|
||||||
|
|
||||||
/***** Question *****/
|
/***** Question *****/
|
||||||
Gam_ListQuestionForEdition (QstCod,StrQstInd);
|
Gam_ListQuestionForEdition (QstCod,QstInd);
|
||||||
|
|
||||||
HTM_TR_End ();
|
HTM_TR_End ();
|
||||||
|
|
||||||
|
@ -1988,9 +1988,8 @@ static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts,
|
||||||
/********************** List game question for edition ***********************/
|
/********************** List game question for edition ***********************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static void Gam_ListQuestionForEdition (long QstCod,const char *StrQstInd)
|
static void Gam_ListQuestionForEdition (long QstCod,unsigned QstInd)
|
||||||
{
|
{
|
||||||
extern const char *Txt_TST_STR_ANSWER_TYPES[Tst_NUM_ANS_TYPES];
|
|
||||||
extern const char *Txt_Question_removed;
|
extern const char *Txt_Question_removed;
|
||||||
MYSQL_RES *mysql_res;
|
MYSQL_RES *mysql_res;
|
||||||
MYSQL_ROW row;
|
MYSQL_ROW row;
|
||||||
|
@ -2018,23 +2017,14 @@ static void Gam_ListQuestionForEdition (long QstCod,const char *StrQstInd)
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/***** Number of question and answer type *****/
|
/***** Number of question and answer type (row[1]) *****/
|
||||||
HTM_TD_Begin ("class=\"RT COLOR%u\"",Gbl.RowEvenOdd);
|
HTM_TD_Begin ("class=\"RT COLOR%u\"",Gbl.RowEvenOdd);
|
||||||
|
Tst_WriteNumQst (QstInd);
|
||||||
/* Write number of question */
|
|
||||||
HTM_DIV_Begin ("class=\"BIG_INDEX\"");
|
|
||||||
HTM_Txt (StrQstInd);
|
|
||||||
HTM_DIV_End ();
|
|
||||||
|
|
||||||
/* Write answer type (row[1]) */
|
|
||||||
HTM_DIV_Begin ("class=\"DAT_SMALL\"");
|
|
||||||
if (QstExists)
|
if (QstExists)
|
||||||
{
|
{
|
||||||
AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
|
AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
|
||||||
HTM_Txt (Txt_TST_STR_ANSWER_TYPES[AnswerType]);
|
Tst_WriteAnswerType (AnswerType);
|
||||||
}
|
}
|
||||||
HTM_DIV_End ();
|
|
||||||
|
|
||||||
HTM_TD_End ();
|
HTM_TD_End ();
|
||||||
|
|
||||||
/***** Write question code *****/
|
/***** Write question code *****/
|
||||||
|
|
|
@ -649,12 +649,14 @@ struct Globals
|
||||||
bool PutIconPrint;
|
bool PutIconPrint;
|
||||||
} ContextualIcons;
|
} ContextualIcons;
|
||||||
} TimeTable;
|
} TimeTable;
|
||||||
|
/*
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
long QstCodes[TstCfg_MAX_QUESTIONS_PER_TEST]; // Codes of the sent/received questions in a test
|
long QstCodes[TstCfg_MAX_QUESTIONS_PER_TEST]; // Codes of the sent/received questions in a test
|
||||||
char StrIndexesOneQst[TstCfg_MAX_QUESTIONS_PER_TEST][Tst_MAX_BYTES_INDEXES_ONE_QST + 1]; // 0 1 2 3, 3 0 2 1, etc.
|
char StrIndexesOneQst[TstCfg_MAX_QUESTIONS_PER_TEST][Tst_MAX_BYTES_INDEXES_ONE_QST + 1]; // 0 1 2 3, 3 0 2 1, etc.
|
||||||
char StrAnswersOneQst[TstCfg_MAX_QUESTIONS_PER_TEST][Tst_MAX_BYTES_ANSWERS_ONE_QST + 1]; // Answers selected by user
|
char StrAnswersOneQst[TstCfg_MAX_QUESTIONS_PER_TEST][Tst_MAX_BYTES_ANSWERS_ONE_QST + 1]; // Answers selected by user
|
||||||
} Test;
|
} Test;
|
||||||
|
*/
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
struct DateTime DateIni; // TODO: Remove in future versions
|
struct DateTime DateIni; // TODO: Remove in future versions
|
||||||
|
|
19
swad_match.c
19
swad_match.c
|
@ -222,7 +222,7 @@ static void Mch_GetNumPlayers (struct Match *Match);
|
||||||
|
|
||||||
static void Mch_RemoveMyAnswerToMatchQuestion (const struct Match *Match);
|
static void Mch_RemoveMyAnswerToMatchQuestion (const struct Match *Match);
|
||||||
|
|
||||||
static double Mch_ComputeScore (unsigned NumQsts);
|
static double Mch_ComputeScore (unsigned NumQsts,const struct Tst_UsrAnswers *UsrAnswers);
|
||||||
|
|
||||||
static unsigned Mch_GetNumUsrsWhoHaveAnswerMch (long MchCod);
|
static unsigned Mch_GetNumUsrsWhoHaveAnswerMch (long MchCod);
|
||||||
|
|
||||||
|
@ -3674,6 +3674,7 @@ void Mch_ReceiveQuestionAnswer (void)
|
||||||
struct Mch_UsrAnswer UsrAnswer;
|
struct Mch_UsrAnswer UsrAnswer;
|
||||||
unsigned NumQsts;
|
unsigned NumQsts;
|
||||||
unsigned NumQstsNotBlank;
|
unsigned NumQstsNotBlank;
|
||||||
|
struct Tst_UsrAnswers UsrAnswers;
|
||||||
double TotalScore;
|
double TotalScore;
|
||||||
|
|
||||||
/***** Get data of the match from database *****/
|
/***** Get data of the match from database *****/
|
||||||
|
@ -3730,8 +3731,9 @@ void Mch_ReceiveQuestionAnswer (void)
|
||||||
|
|
||||||
/***** Update student's match result *****/
|
/***** Update student's match result *****/
|
||||||
McR_GetMatchResultQuestionsFromDB (Match.MchCod,Gbl.Usrs.Me.UsrDat.UsrCod,
|
McR_GetMatchResultQuestionsFromDB (Match.MchCod,Gbl.Usrs.Me.UsrDat.UsrCod,
|
||||||
&NumQsts,&NumQstsNotBlank);
|
&NumQsts,&NumQstsNotBlank,
|
||||||
TotalScore = Mch_ComputeScore (NumQsts);
|
&UsrAnswers);
|
||||||
|
TotalScore = Mch_ComputeScore (NumQsts,&UsrAnswers);
|
||||||
|
|
||||||
Str_SetDecimalPointToUS (); // To print the floating point as a dot
|
Str_SetDecimalPointToUS (); // To print the floating point as a dot
|
||||||
if (DB_QueryCOUNT ("can not get if match result exists",
|
if (DB_QueryCOUNT ("can not get if match result exists",
|
||||||
|
@ -3788,7 +3790,7 @@ static void Mch_RemoveMyAnswerToMatchQuestion (const struct Match *Match)
|
||||||
/******************** Compute match score for a student **********************/
|
/******************** Compute match score for a student **********************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static double Mch_ComputeScore (unsigned NumQsts)
|
static double Mch_ComputeScore (unsigned NumQsts,const struct Tst_UsrAnswers *UsrAnswers)
|
||||||
{
|
{
|
||||||
unsigned NumQst;
|
unsigned NumQst;
|
||||||
struct Tst_Question Question;
|
struct Tst_Question Question;
|
||||||
|
@ -3807,16 +3809,17 @@ static double Mch_ComputeScore (unsigned NumQsts)
|
||||||
NumQst++)
|
NumQst++)
|
||||||
{
|
{
|
||||||
/***** Get indexes for this question from string *****/
|
/***** Get indexes for this question from string *****/
|
||||||
Tst_GetIndexesFromStr (Gbl.Test.StrIndexesOneQst[NumQst],Indexes);
|
Tst_GetIndexesFromStr (UsrAnswers->StrIndexesOneQst[NumQst],Indexes);
|
||||||
|
|
||||||
/***** Get the user's answers for this question from string *****/
|
/***** Get the user's answers for this question from string *****/
|
||||||
Tst_GetAnswersFromStr (Gbl.Test.StrAnswersOneQst[NumQst],AnswersUsr);
|
Tst_GetAnswersFromStr (UsrAnswers->StrAnswersOneQst[NumQst],AnswersUsr);
|
||||||
|
|
||||||
/***** Get correct answers of test question from database *****/
|
/***** Get correct answers of test question from database *****/
|
||||||
Tst_GetCorrectAnswersFromDB (Gbl.Test.QstCodes[NumQst],&Question);
|
Tst_GetCorrectAnswersFromDB (UsrAnswers->QstCodes[NumQst],&Question);
|
||||||
|
|
||||||
/***** Compute the total score of this question *****/
|
/***** Compute the total score of this question *****/
|
||||||
Tst_ComputeScoreQst (&Question,Indexes,AnswersUsr,&ScoreThisQst,&AnswerIsNotBlank);
|
Tst_ComputeScoreQst (&Question,
|
||||||
|
Indexes,AnswersUsr,&ScoreThisQst,&AnswerIsNotBlank);
|
||||||
|
|
||||||
/***** Compute total score *****/
|
/***** Compute total score *****/
|
||||||
TotalScore += ScoreThisQst;
|
TotalScore += ScoreThisQst;
|
||||||
|
|
|
@ -1007,6 +1007,7 @@ void McR_ShowOneMchResult (void)
|
||||||
char *Id;
|
char *Id;
|
||||||
unsigned NumQsts;
|
unsigned NumQsts;
|
||||||
unsigned NumQstsNotBlank;
|
unsigned NumQstsNotBlank;
|
||||||
|
struct Tst_UsrAnswers UsrAnswers;
|
||||||
double TotalScore;
|
double TotalScore;
|
||||||
bool ShowPhoto;
|
bool ShowPhoto;
|
||||||
char PhotoURL[PATH_MAX + 1];
|
char PhotoURL[PATH_MAX + 1];
|
||||||
|
@ -1067,7 +1068,8 @@ void McR_ShowOneMchResult (void)
|
||||||
{
|
{
|
||||||
/***** Get questions and user's answers of the match result from database *****/
|
/***** Get questions and user's answers of the match result from database *****/
|
||||||
McR_GetMatchResultQuestionsFromDB (Match.MchCod,UsrDat->UsrCod,
|
McR_GetMatchResultQuestionsFromDB (Match.MchCod,UsrDat->UsrCod,
|
||||||
&NumQsts,&NumQstsNotBlank);
|
&NumQsts,&NumQstsNotBlank,
|
||||||
|
&UsrAnswers);
|
||||||
|
|
||||||
/***** Begin box *****/
|
/***** Begin box *****/
|
||||||
Box_BoxBegin (NULL,Match.Title,NULL,
|
Box_BoxBegin (NULL,Match.Title,NULL,
|
||||||
|
@ -1192,7 +1194,7 @@ void McR_ShowOneMchResult (void)
|
||||||
HTM_TR_End ();
|
HTM_TR_End ();
|
||||||
|
|
||||||
/***** Write answers and solutions *****/
|
/***** Write answers and solutions *****/
|
||||||
TsR_ShowTestResult (UsrDat,NumQsts,TimeUTC[Dat_START_TIME],
|
TsR_ShowTestResult (UsrDat,NumQsts,&UsrAnswers,TimeUTC[Dat_START_TIME],
|
||||||
Game.Visibility);
|
Game.Visibility);
|
||||||
|
|
||||||
/***** End table *****/
|
/***** End table *****/
|
||||||
|
@ -1222,7 +1224,8 @@ void McR_ShowOneMchResult (void)
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
void McR_GetMatchResultQuestionsFromDB (long MchCod,long UsrCod,
|
void McR_GetMatchResultQuestionsFromDB (long MchCod,long UsrCod,
|
||||||
unsigned *NumQsts,unsigned *NumQstsNotBlank)
|
unsigned *NumQsts,unsigned *NumQstsNotBlank,
|
||||||
|
struct Tst_UsrAnswers *UsrAnswers)
|
||||||
{
|
{
|
||||||
MYSQL_RES *mysql_res;
|
MYSQL_RES *mysql_res;
|
||||||
MYSQL_ROW row;
|
MYSQL_ROW row;
|
||||||
|
@ -1252,7 +1255,7 @@ void McR_GetMatchResultQuestionsFromDB (long MchCod,long UsrCod,
|
||||||
row = mysql_fetch_row (mysql_res);
|
row = mysql_fetch_row (mysql_res);
|
||||||
|
|
||||||
/* Get question code (row[0]) */
|
/* Get question code (row[0]) */
|
||||||
if ((Gbl.Test.QstCodes[NumQst] = Str_ConvertStrCodToLongCod (row[0])) < 0)
|
if ((UsrAnswers->QstCodes[NumQst] = Str_ConvertStrCodToLongCod (row[0])) < 0)
|
||||||
Lay_ShowErrorAndExit ("Wrong code of question.");
|
Lay_ShowErrorAndExit ("Wrong code of question.");
|
||||||
|
|
||||||
/* Get question index (row[1]) */
|
/* Get question index (row[1]) */
|
||||||
|
@ -1261,24 +1264,24 @@ void McR_GetMatchResultQuestionsFromDB (long MchCod,long UsrCod,
|
||||||
QstInd = (unsigned) LongNum;
|
QstInd = (unsigned) LongNum;
|
||||||
|
|
||||||
/* Get indexes for this question (row[2]) */
|
/* Get indexes for this question (row[2]) */
|
||||||
Str_Copy (Gbl.Test.StrIndexesOneQst[NumQst],row[2],
|
Str_Copy (UsrAnswers->StrIndexesOneQst[NumQst],row[2],
|
||||||
Tst_MAX_BYTES_INDEXES_ONE_QST);
|
Tst_MAX_BYTES_INDEXES_ONE_QST);
|
||||||
|
|
||||||
/* Get answers selected by user for this question */
|
/* Get answers selected by user for this question */
|
||||||
Mch_GetQstAnsFromDB (MchCod,UsrCod,QstInd,&UsrAnswer);
|
Mch_GetQstAnsFromDB (MchCod,UsrCod,QstInd,&UsrAnswer);
|
||||||
if (UsrAnswer.AnsInd >= 0) // UsrAnswer.AnsInd >= 0 ==> answer selected
|
if (UsrAnswer.AnsInd >= 0) // UsrAnswer.AnsInd >= 0 ==> answer selected
|
||||||
{
|
{
|
||||||
snprintf (Gbl.Test.StrAnswersOneQst[NumQst],Tst_MAX_BYTES_ANSWERS_ONE_QST + 1,
|
snprintf (UsrAnswers->StrAnswersOneQst[NumQst],Tst_MAX_BYTES_ANSWERS_ONE_QST + 1,
|
||||||
"%d",UsrAnswer.AnsInd);
|
"%d",UsrAnswer.AnsInd);
|
||||||
(*NumQstsNotBlank)++;
|
(*NumQstsNotBlank)++;
|
||||||
}
|
}
|
||||||
else // UsrAnswer.AnsInd < 0 ==> no answer selected
|
else // UsrAnswer.AnsInd < 0 ==> no answer selected
|
||||||
Gbl.Test.StrAnswersOneQst[NumQst][0] = '\0'; // Empty answer
|
UsrAnswers->StrAnswersOneQst[NumQst][0] = '\0'; // Empty answer
|
||||||
|
|
||||||
/* Replace each comma by a separator of multiple parameters */
|
/* Replace each comma by a separator of multiple parameters */
|
||||||
/* In database commas are used as separators instead of special chars */
|
/* In database commas are used as separators instead of special chars */
|
||||||
Par_ReplaceCommaBySeparatorMultiple (Gbl.Test.StrIndexesOneQst[NumQst]);
|
Par_ReplaceCommaBySeparatorMultiple (UsrAnswers->StrIndexesOneQst[NumQst]);
|
||||||
Par_ReplaceCommaBySeparatorMultiple (Gbl.Test.StrAnswersOneQst[NumQst]);
|
Par_ReplaceCommaBySeparatorMultiple (UsrAnswers->StrAnswersOneQst[NumQst]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***** Free structure that stores the query result *****/
|
/***** Free structure that stores the query result *****/
|
||||||
|
|
|
@ -50,6 +50,7 @@ void McR_ShowAllMchResultsInMch (void);
|
||||||
|
|
||||||
void McR_ShowOneMchResult (void);
|
void McR_ShowOneMchResult (void);
|
||||||
void McR_GetMatchResultQuestionsFromDB (long MchCod,long UsrCod,
|
void McR_GetMatchResultQuestionsFromDB (long MchCod,long UsrCod,
|
||||||
unsigned *NumQsts,unsigned *NumQstsNotBlank);
|
unsigned *NumQsts,unsigned *NumQstsNotBlank,
|
||||||
|
struct Tst_UsrAnswers *UsrAnswers);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -927,25 +927,30 @@ void Str_ConvertStrFloatCommaToStrFloatPoint (char *Str)
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
// This function may change Str on wrong double
|
// This function may change Str on wrong double
|
||||||
|
|
||||||
double Str_GetDoubleFromStr (char *Str)
|
double Str_GetDoubleFromStr (const char *Str)
|
||||||
{
|
{
|
||||||
|
char *StrPoint;
|
||||||
double DoubleNum;
|
double DoubleNum;
|
||||||
|
|
||||||
/***** Trivial check *****/
|
/***** Trivial check *****/
|
||||||
if (Str == NULL) // If no string...
|
if (Str == NULL) // If no string...
|
||||||
return 0.0; // ...the number is reset to 0
|
return 0.0; // ...the number is reset to 0
|
||||||
|
|
||||||
|
/***** Copy source string to temporary string to convert to point *****/
|
||||||
|
if (asprintf (&StrPoint,"%s",Str) < 0)
|
||||||
|
Lay_NotEnoughMemoryExit ();
|
||||||
|
|
||||||
/***** The string is "scanned" in floating point
|
/***** The string is "scanned" in floating point
|
||||||
(it must have a point, not a comma as decimal separator) *****/
|
(it must have a point, not a comma as decimal separator) *****/
|
||||||
Str_ConvertStrFloatCommaToStrFloatPoint (Str);
|
Str_ConvertStrFloatCommaToStrFloatPoint (StrPoint);
|
||||||
Str_SetDecimalPointToUS (); // To get the decimal point as a dot
|
Str_SetDecimalPointToUS (); // To get the decimal point as a dot
|
||||||
if (sscanf (Str,"%lf",&DoubleNum) != 1)
|
if (sscanf (StrPoint,"%lf",&DoubleNum) != 1) // If the string does not hold a valid number...
|
||||||
{ // If the string does not hold a valid number...
|
DoubleNum = 0.0; // ...the number is reset to 0
|
||||||
DoubleNum = 0.0; // ...the number is reset to 0
|
|
||||||
Str[0] = '\0'; // ...and the string is reset to ""
|
|
||||||
}
|
|
||||||
Str_SetDecimalPointToLocal (); // Return to local system
|
Str_SetDecimalPointToLocal (); // Return to local system
|
||||||
|
|
||||||
|
/***** Free temporary string *****/
|
||||||
|
free (StrPoint);
|
||||||
|
|
||||||
return DoubleNum;
|
return DoubleNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ char Str_ConvertToLowerLetter (char Ch);
|
||||||
void Str_DoubleNumToStr (char **Str,double Number);
|
void Str_DoubleNumToStr (char **Str,double Number);
|
||||||
void Str_DoubleNumToStrFewDigits (char **Str,double Number);
|
void Str_DoubleNumToStrFewDigits (char **Str,double Number);
|
||||||
void Str_ConvertStrFloatCommaToStrFloatPoint (char *Str);
|
void Str_ConvertStrFloatCommaToStrFloatPoint (char *Str);
|
||||||
double Str_GetDoubleFromStr (char *Str);
|
double Str_GetDoubleFromStr (const char *Str);
|
||||||
void Str_SetDecimalPointToUS (void);
|
void Str_SetDecimalPointToUS (void);
|
||||||
void Str_SetDecimalPointToLocal (void);
|
void Str_SetDecimalPointToLocal (void);
|
||||||
|
|
||||||
|
|
343
swad_test.c
343
swad_test.c
|
@ -131,16 +131,24 @@ static void Tst_ResetAnswerTypes (struct Tst_AnswerTypes *AnswerTypes);
|
||||||
static void Tst_ShowFormRequestTest (const struct Tst_Tags *Tags,
|
static void Tst_ShowFormRequestTest (const struct Tst_Tags *Tags,
|
||||||
const struct Tst_AnswerTypes *AnswerTypes);
|
const struct Tst_AnswerTypes *AnswerTypes);
|
||||||
|
|
||||||
static void Tst_GetQuestionsAndAnswersFromForm (unsigned NumQsts);
|
static void Tst_GetQuestionsAndAnswersFromForm (unsigned NumQsts,
|
||||||
|
struct Tst_UsrAnswers *UsrAnswers);
|
||||||
static bool Tst_CheckIfNextTstAllowed (void);
|
static bool Tst_CheckIfNextTstAllowed (void);
|
||||||
static void Tst_SetTstStatus (unsigned NumTst,Tst_Status_t TstStatus);
|
static void Tst_SetTstStatus (unsigned NumTst,Tst_Status_t TstStatus);
|
||||||
static Tst_Status_t Tst_GetTstStatus (unsigned NumTst);
|
static Tst_Status_t Tst_GetTstStatus (unsigned NumTst);
|
||||||
static unsigned Tst_GetNumAccessesTst (void);
|
static unsigned Tst_GetNumAccessesTst (void);
|
||||||
static void Tst_ShowTestQuestionsWhenSeeing (unsigned NumQsts,MYSQL_RES *mysql_res);
|
static void Tst_ShowTestQuestionsWhenSeeing (unsigned NumQsts,
|
||||||
|
MYSQL_RES *mysql_res);
|
||||||
static void Tst_ShowOneTestQuestionWhenSeeing (unsigned NumQst,long QstCod);
|
static void Tst_ShowOneTestQuestionWhenSeeing (unsigned NumQst,long QstCod);
|
||||||
static void Tst_ShowTestResultAfterAssess (long TstCod,unsigned NumQsts,
|
static void Tst_ShowTestResultAfterAssess (long TstCod,
|
||||||
|
unsigned NumQsts,
|
||||||
unsigned *NumQstsNotBlank,
|
unsigned *NumQstsNotBlank,
|
||||||
|
const struct Tst_UsrAnswers *UsrAnswers,
|
||||||
double *TotalScore);
|
double *TotalScore);
|
||||||
|
static void Tst_WriteQstAndAnsTestToAnswer (unsigned NumQst,
|
||||||
|
long QstCod,
|
||||||
|
MYSQL_ROW row);
|
||||||
|
|
||||||
static void Tst_PutFormToEditQstMedia (const struct Media *Media,int NumMediaInForm,
|
static void Tst_PutFormToEditQstMedia (const struct Media *Media,int NumMediaInForm,
|
||||||
bool OptionsDisabled);
|
bool OptionsDisabled);
|
||||||
static void Tst_UpdateScoreQst (long QstCod,double ScoreThisQst,bool AnswerIsNotBlank);
|
static void Tst_UpdateScoreQst (long QstCod,double ScoreThisQst,bool AnswerIsNotBlank);
|
||||||
|
@ -209,6 +217,7 @@ static void Tst_GetParamGblAnswerTypes (struct Tst_AnswerTypes *AnswerTypesDst);
|
||||||
static void Tst_WriteAnswersTestToAnswer (unsigned NumQst,long QstCod,
|
static void Tst_WriteAnswersTestToAnswer (unsigned NumQst,long QstCod,
|
||||||
Tst_AnswerType_t AnswerType,bool Shuffle);
|
Tst_AnswerType_t AnswerType,bool Shuffle);
|
||||||
static void Tst_WriteAnswersTestResult (struct UsrData *UsrDat,
|
static void Tst_WriteAnswersTestResult (struct UsrData *UsrDat,
|
||||||
|
const struct Tst_UsrAnswers *UsrAnswers,
|
||||||
unsigned NumQst,long QstCod,
|
unsigned NumQst,long QstCod,
|
||||||
Tst_AnswerType_t AnswerType,
|
Tst_AnswerType_t AnswerType,
|
||||||
unsigned Visibility,
|
unsigned Visibility,
|
||||||
|
@ -216,6 +225,7 @@ static void Tst_WriteAnswersTestResult (struct UsrData *UsrDat,
|
||||||
|
|
||||||
static void Tst_WriteTFAnsViewTest (unsigned NumQst);
|
static void Tst_WriteTFAnsViewTest (unsigned NumQst);
|
||||||
static void Tst_WriteTFAnsAssessTest (struct UsrData *UsrDat,
|
static void Tst_WriteTFAnsAssessTest (struct UsrData *UsrDat,
|
||||||
|
const struct Tst_UsrAnswers *UsrAnswers,
|
||||||
unsigned NumQst,
|
unsigned NumQst,
|
||||||
const struct Tst_Question *Question,
|
const struct Tst_Question *Question,
|
||||||
MYSQL_RES *mysql_res,
|
MYSQL_RES *mysql_res,
|
||||||
|
@ -227,6 +237,7 @@ static void Tst_WriteChoiceAnsViewTest (unsigned NumQst,long QstCod,
|
||||||
Tst_AnswerType_t AnswerType,
|
Tst_AnswerType_t AnswerType,
|
||||||
bool Shuffle);
|
bool Shuffle);
|
||||||
static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat,
|
static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat,
|
||||||
|
const struct Tst_UsrAnswers *UsrAnswers,
|
||||||
unsigned NumQst,
|
unsigned NumQst,
|
||||||
struct Tst_Question *Question,
|
struct Tst_Question *Question,
|
||||||
MYSQL_RES *mysql_res,
|
MYSQL_RES *mysql_res,
|
||||||
|
@ -237,6 +248,7 @@ static void Tst_GetChoiceAns (MYSQL_RES *mysql_res,struct Tst_Question *Question
|
||||||
|
|
||||||
static void Tst_WriteTextAnsViewTest (unsigned NumQst);
|
static void Tst_WriteTextAnsViewTest (unsigned NumQst);
|
||||||
static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat,
|
static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat,
|
||||||
|
const struct Tst_UsrAnswers *UsrAnswers,
|
||||||
unsigned NumQst,
|
unsigned NumQst,
|
||||||
struct Tst_Question *Question,
|
struct Tst_Question *Question,
|
||||||
MYSQL_RES *mysql_res,
|
MYSQL_RES *mysql_res,
|
||||||
|
@ -246,6 +258,7 @@ static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat,
|
||||||
|
|
||||||
static void Tst_WriteIntAnsViewTest (unsigned NumQst);
|
static void Tst_WriteIntAnsViewTest (unsigned NumQst);
|
||||||
static void Tst_WriteIntAnsAssessTest (struct UsrData *UsrDat,
|
static void Tst_WriteIntAnsAssessTest (struct UsrData *UsrDat,
|
||||||
|
const struct Tst_UsrAnswers *UsrAnswers,
|
||||||
unsigned NumQst,
|
unsigned NumQst,
|
||||||
const struct Tst_Question *Question,
|
const struct Tst_Question *Question,
|
||||||
MYSQL_RES *mysql_res,
|
MYSQL_RES *mysql_res,
|
||||||
|
@ -255,6 +268,7 @@ static void Tst_WriteIntAnsAssessTest (struct UsrData *UsrDat,
|
||||||
|
|
||||||
static void Tst_WriteFloatAnsViewTest (unsigned NumQst);
|
static void Tst_WriteFloatAnsViewTest (unsigned NumQst);
|
||||||
static void Tst_WriteFloatAnsAssessTest (struct UsrData *UsrDat,
|
static void Tst_WriteFloatAnsAssessTest (struct UsrData *UsrDat,
|
||||||
|
const struct Tst_UsrAnswers *UsrAnswers,
|
||||||
unsigned NumQst,
|
unsigned NumQst,
|
||||||
const struct Tst_Question *Question,
|
const struct Tst_Question *Question,
|
||||||
MYSQL_RES *mysql_res,
|
MYSQL_RES *mysql_res,
|
||||||
|
@ -577,6 +591,7 @@ void Tst_AssessTest (void)
|
||||||
bool AllowTeachers; // Can teachers of this course see the test result?
|
bool AllowTeachers; // Can teachers of this course see the test result?
|
||||||
long TstCod = -1L; // Initialized to avoid warning
|
long TstCod = -1L; // Initialized to avoid warning
|
||||||
unsigned NumQstsNotBlank;
|
unsigned NumQstsNotBlank;
|
||||||
|
struct Tst_UsrAnswers UsrAnswers;
|
||||||
double TotalScore;
|
double TotalScore;
|
||||||
|
|
||||||
/***** Read test configuration from database *****/
|
/***** Read test configuration from database *****/
|
||||||
|
@ -597,7 +612,7 @@ void Tst_AssessTest (void)
|
||||||
AllowTeachers = Par_GetParToBool ("AllowTchs");
|
AllowTeachers = Par_GetParToBool ("AllowTchs");
|
||||||
|
|
||||||
/***** Get questions and answers from form to assess a test *****/
|
/***** Get questions and answers from form to assess a test *****/
|
||||||
Tst_GetQuestionsAndAnswersFromForm (NumQsts);
|
Tst_GetQuestionsAndAnswersFromForm (NumQsts,&UsrAnswers);
|
||||||
|
|
||||||
/***** Create new test in database to store the result *****/
|
/***** Create new test in database to store the result *****/
|
||||||
TstCod = TsR_CreateTestResultInDB (AllowTeachers,NumQsts);
|
TstCod = TsR_CreateTestResultInDB (AllowTeachers,NumQsts);
|
||||||
|
@ -620,7 +635,8 @@ void Tst_AssessTest (void)
|
||||||
|
|
||||||
/***** Write answers and solutions *****/
|
/***** Write answers and solutions *****/
|
||||||
HTM_TABLE_BeginWideMarginPadding (10);
|
HTM_TABLE_BeginWideMarginPadding (10);
|
||||||
Tst_ShowTestResultAfterAssess (TstCod,NumQsts,&NumQstsNotBlank,&TotalScore);
|
Tst_ShowTestResultAfterAssess (TstCod,NumQsts,&NumQstsNotBlank,
|
||||||
|
&UsrAnswers,&TotalScore);
|
||||||
HTM_TABLE_End ();
|
HTM_TABLE_End ();
|
||||||
|
|
||||||
/***** Write total score and grade *****/
|
/***** Write total score and grade *****/
|
||||||
|
@ -660,7 +676,8 @@ void Tst_AssessTest (void)
|
||||||
/*********** Get questions and answers from form to assess a test ************/
|
/*********** Get questions and answers from form to assess a test ************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static void Tst_GetQuestionsAndAnswersFromForm (unsigned NumQsts)
|
static void Tst_GetQuestionsAndAnswersFromForm (unsigned NumQsts,
|
||||||
|
struct Tst_UsrAnswers *UsrAnswers)
|
||||||
{
|
{
|
||||||
unsigned NumQst;
|
unsigned NumQst;
|
||||||
char StrQstIndOrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Qstxx...x", "Indxx...x" or "Ansxx...x"
|
char StrQstIndOrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Qstxx...x", "Indxx...x" or "Ansxx...x"
|
||||||
|
@ -674,21 +691,21 @@ static void Tst_GetQuestionsAndAnswersFromForm (unsigned NumQsts)
|
||||||
snprintf (StrQstIndOrAns,sizeof (StrQstIndOrAns),
|
snprintf (StrQstIndOrAns,sizeof (StrQstIndOrAns),
|
||||||
"Qst%03u",
|
"Qst%03u",
|
||||||
NumQst);
|
NumQst);
|
||||||
if ((Gbl.Test.QstCodes[NumQst] = Par_GetParToLong (StrQstIndOrAns)) <= 0)
|
if ((UsrAnswers->QstCodes[NumQst] = Par_GetParToLong (StrQstIndOrAns)) <= 0)
|
||||||
Lay_ShowErrorAndExit ("Code of question is missing.");
|
Lay_ShowErrorAndExit ("Code of question is missing.");
|
||||||
|
|
||||||
/* Get indexes for this question */
|
/* Get indexes for this question */
|
||||||
snprintf (StrQstIndOrAns,sizeof (StrQstIndOrAns),
|
snprintf (StrQstIndOrAns,sizeof (StrQstIndOrAns),
|
||||||
"Ind%03u",
|
"Ind%03u",
|
||||||
NumQst);
|
NumQst);
|
||||||
Par_GetParMultiToText (StrQstIndOrAns,Gbl.Test.StrIndexesOneQst[NumQst],
|
Par_GetParMultiToText (StrQstIndOrAns,UsrAnswers->StrIndexesOneQst[NumQst],
|
||||||
Tst_MAX_BYTES_INDEXES_ONE_QST); /* If choice ==> "0", "1", "2",... */
|
Tst_MAX_BYTES_INDEXES_ONE_QST); /* If choice ==> "0", "1", "2",... */
|
||||||
|
|
||||||
/* Get answers selected by user for this question */
|
/* Get answers selected by user for this question */
|
||||||
snprintf (StrQstIndOrAns,sizeof (StrQstIndOrAns),
|
snprintf (StrQstIndOrAns,sizeof (StrQstIndOrAns),
|
||||||
"Ans%03u",
|
"Ans%03u",
|
||||||
NumQst);
|
NumQst);
|
||||||
Par_GetParMultiToText (StrQstIndOrAns,Gbl.Test.StrAnswersOneQst[NumQst],
|
Par_GetParMultiToText (StrQstIndOrAns,UsrAnswers->StrAnswersOneQst[NumQst],
|
||||||
Tst_MAX_BYTES_ANSWERS_ONE_QST); /* If answer type == T/F ==> " ", "T", "F"; if choice ==> "0", "2",... */
|
Tst_MAX_BYTES_ANSWERS_ONE_QST); /* If answer type == T/F ==> " ", "T", "F"; if choice ==> "0", "2",... */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -905,7 +922,8 @@ static unsigned Tst_GetNumAccessesTst (void)
|
||||||
// NumRows must hold the number of rows of a MySQL query
|
// NumRows must hold the number of rows of a MySQL query
|
||||||
// In each row mysql_res holds: in the column 0 the code of a question, in the column 1 the type of answer, and in the column 2 the stem
|
// In each row mysql_res holds: in the column 0 the code of a question, in the column 1 the type of answer, and in the column 2 the stem
|
||||||
|
|
||||||
static void Tst_ShowTestQuestionsWhenSeeing (unsigned NumQsts,MYSQL_RES *mysql_res)
|
static void Tst_ShowTestQuestionsWhenSeeing (unsigned NumQsts,
|
||||||
|
MYSQL_RES *mysql_res)
|
||||||
{
|
{
|
||||||
unsigned NumQst;
|
unsigned NumQst;
|
||||||
long QstCod;
|
long QstCod;
|
||||||
|
@ -936,32 +954,12 @@ static void Tst_ShowOneTestQuestionWhenSeeing (unsigned NumQst,long QstCod)
|
||||||
{
|
{
|
||||||
MYSQL_RES *mysql_res;
|
MYSQL_RES *mysql_res;
|
||||||
MYSQL_ROW row;
|
MYSQL_ROW row;
|
||||||
double ScoreThisQst; // Not used here
|
|
||||||
bool AnswerIsNotBlank; // Not used here
|
|
||||||
|
|
||||||
if (Tst_GetOneQuestionByCod (QstCod,&mysql_res)) // Question exists
|
if (Tst_GetOneQuestionByCod (QstCod,&mysql_res)) // Question exists
|
||||||
{
|
{
|
||||||
/***** Get row of the result of the query *****/
|
/***** Get row of the result of the query *****/
|
||||||
row = mysql_fetch_row (mysql_res);
|
row = mysql_fetch_row (mysql_res);
|
||||||
/*
|
Tst_WriteQstAndAnsTestToAnswer (NumQst,QstCod,row);
|
||||||
row[0] UNIX_TIMESTAMP(EditTime)
|
|
||||||
row[1] AnsType
|
|
||||||
row[2] Shuffle
|
|
||||||
row[3] Stem
|
|
||||||
row[4] Feedback
|
|
||||||
row[5] MedCod
|
|
||||||
row[6] NumHits
|
|
||||||
row[7] NumHitsNotBlank
|
|
||||||
row[8] Score
|
|
||||||
*/
|
|
||||||
Tst_WriteQstAndAnsTest (Tst_SHOW_TEST_TO_ANSWER,
|
|
||||||
&Gbl.Usrs.Me.UsrDat,
|
|
||||||
NumQst,
|
|
||||||
QstCod,
|
|
||||||
row,
|
|
||||||
TsV_MAX_VISIBILITY, // All visible here
|
|
||||||
&ScoreThisQst, // Not used here
|
|
||||||
&AnswerIsNotBlank); // Not used here
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Lay_ShowErrorAndExit ("Wrong question.");
|
Lay_ShowErrorAndExit ("Wrong question.");
|
||||||
|
@ -1000,8 +998,10 @@ void Tst_ShowTagList (unsigned NumTags,MYSQL_RES *mysql_res)
|
||||||
/******************* Show the result of assessing a test *********************/
|
/******************* Show the result of assessing a test *********************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static void Tst_ShowTestResultAfterAssess (long TstCod,unsigned NumQsts,
|
static void Tst_ShowTestResultAfterAssess (long TstCod,
|
||||||
|
unsigned NumQsts,
|
||||||
unsigned *NumQstsNotBlank,
|
unsigned *NumQstsNotBlank,
|
||||||
|
const struct Tst_UsrAnswers *UsrAnswers,
|
||||||
double *TotalScore)
|
double *TotalScore)
|
||||||
{
|
{
|
||||||
extern const char *Txt_Question_removed;
|
extern const char *Txt_Question_removed;
|
||||||
|
@ -1022,33 +1022,19 @@ static void Tst_ShowTestResultAfterAssess (long TstCod,unsigned NumQsts,
|
||||||
Gbl.RowEvenOdd = NumQst % 2;
|
Gbl.RowEvenOdd = NumQst % 2;
|
||||||
|
|
||||||
/***** Query database *****/
|
/***** Query database *****/
|
||||||
if (Tst_GetOneQuestionByCod (Gbl.Test.QstCodes[NumQst],&mysql_res)) // Question exists
|
if (Tst_GetOneQuestionByCod (UsrAnswers->QstCodes[NumQst],&mysql_res)) // Question exists
|
||||||
{
|
{
|
||||||
/***** Get row of the result of the query *****/
|
|
||||||
row = mysql_fetch_row (mysql_res);
|
|
||||||
/*
|
|
||||||
row[0] UNIX_TIMESTAMP(EditTime)
|
|
||||||
row[1] AnsType
|
|
||||||
row[2] Shuffle
|
|
||||||
row[3] Stem
|
|
||||||
row[4] Feedback
|
|
||||||
row[5] MedCod
|
|
||||||
row[6] NumHits
|
|
||||||
row[7] NumHitsNotBlank
|
|
||||||
row[8] Score
|
|
||||||
*/
|
|
||||||
|
|
||||||
/***** Write question and answers *****/
|
/***** Write question and answers *****/
|
||||||
Tst_WriteQstAndAnsTest (Tst_SHOW_TEST_RESULT,
|
row = mysql_fetch_row (mysql_res);
|
||||||
&Gbl.Usrs.Me.UsrDat,
|
Tst_WriteQstAndAnsTestResult (&Gbl.Usrs.Me.UsrDat,
|
||||||
NumQst,
|
UsrAnswers,
|
||||||
Gbl.Test.QstCodes[NumQst],
|
NumQst,
|
||||||
row,
|
row,
|
||||||
TstCfg_GetConfigVisibility (),
|
TstCfg_GetConfigVisibility (),
|
||||||
&ScoreThisQst,&AnswerIsNotBlank);
|
&ScoreThisQst,&AnswerIsNotBlank);
|
||||||
|
|
||||||
/***** Store test result question in database *****/
|
/***** Store test result question in database *****/
|
||||||
TsR_StoreOneTestResultQstInDB (TstCod,Gbl.Test.QstCodes[NumQst],
|
TsR_StoreOneTestResultQstInDB (TstCod,UsrAnswers,
|
||||||
NumQst, // 0, 1, 2, 3...
|
NumQst, // 0, 1, 2, 3...
|
||||||
ScoreThisQst);
|
ScoreThisQst);
|
||||||
|
|
||||||
|
@ -1059,15 +1045,15 @@ static void Tst_ShowTestResultAfterAssess (long TstCod,unsigned NumQsts,
|
||||||
|
|
||||||
/***** Update the number of accesses and the score of this question *****/
|
/***** Update the number of accesses and the score of this question *****/
|
||||||
if (Gbl.Usrs.Me.Role.Logged == Rol_STD)
|
if (Gbl.Usrs.Me.Role.Logged == Rol_STD)
|
||||||
Tst_UpdateScoreQst (Gbl.Test.QstCodes[NumQst],ScoreThisQst,AnswerIsNotBlank);
|
Tst_UpdateScoreQst (UsrAnswers->QstCodes[NumQst],ScoreThisQst,AnswerIsNotBlank);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/***** Question does not exists *****/
|
/***** Question does not exists *****/
|
||||||
HTM_TR_Begin (NULL);
|
HTM_TR_Begin (NULL);
|
||||||
|
|
||||||
HTM_TD_Begin ("class=\"BIG_INDEX RT COLOR%u\"",Gbl.RowEvenOdd);
|
HTM_TD_Begin ("class=\"RT COLOR%u\"",Gbl.RowEvenOdd);
|
||||||
HTM_Unsigned (NumQst + 1);
|
Tst_WriteNumQst (NumQst + 1);
|
||||||
HTM_TD_End ();
|
HTM_TD_End ();
|
||||||
|
|
||||||
HTM_TD_Begin ("class=\"DAT_LIGHT LT COLOR%u\"",Gbl.RowEvenOdd);
|
HTM_TD_Begin ("class=\"DAT_LIGHT LT COLOR%u\"",Gbl.RowEvenOdd);
|
||||||
|
@ -1086,15 +1072,72 @@ static void Tst_ShowTestResultAfterAssess (long TstCod,unsigned NumQsts,
|
||||||
/********** Write a row of a test, with one question and its answer **********/
|
/********** Write a row of a test, with one question and its answer **********/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestions,
|
static void Tst_WriteQstAndAnsTestToAnswer (unsigned NumQst,
|
||||||
struct UsrData *UsrDat,
|
long QstCod,
|
||||||
unsigned NumQst,
|
MYSQL_ROW row)
|
||||||
long QstCod,
|
{
|
||||||
MYSQL_ROW row,
|
struct Tst_Question Question;
|
||||||
unsigned Visibility,
|
/*
|
||||||
double *ScoreThisQst,bool *AnswerIsNotBlank)
|
row[0] UNIX_TIMESTAMP(EditTime)
|
||||||
|
row[1] AnsType
|
||||||
|
row[2] Shuffle
|
||||||
|
row[3] Stem
|
||||||
|
row[4] Feedback
|
||||||
|
row[5] MedCod
|
||||||
|
row[6] NumHits
|
||||||
|
row[7] NumHitsNotBlank
|
||||||
|
row[8] Score
|
||||||
|
*/
|
||||||
|
|
||||||
|
/***** Create test question *****/
|
||||||
|
Tst_QstConstructor (&Question);
|
||||||
|
|
||||||
|
/***** Begin row *****/
|
||||||
|
HTM_TR_Begin (NULL);
|
||||||
|
|
||||||
|
/***** Number of question and answer type (row[1]) *****/
|
||||||
|
HTM_TD_Begin ("class=\"RT COLOR%u\"",Gbl.RowEvenOdd);
|
||||||
|
Tst_WriteNumQst (NumQst + 1);
|
||||||
|
Question.Answer.Type = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
|
||||||
|
Tst_WriteAnswerType (Question.Answer.Type);
|
||||||
|
HTM_TD_End ();
|
||||||
|
|
||||||
|
/***** Stem, media and answers *****/
|
||||||
|
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
|
||||||
|
|
||||||
|
/* Stem (row[3]) */
|
||||||
|
Tst_WriteQstStem (row[3],"TEST_EXA",true);
|
||||||
|
|
||||||
|
/* Media (row[5]) */
|
||||||
|
Question.Media.MedCod = Str_ConvertStrCodToLongCod (row[5]);
|
||||||
|
Med_GetMediaDataByCod (&Question.Media);
|
||||||
|
Med_ShowMedia (&Question.Media,
|
||||||
|
"TEST_MED_SHOW_CONT",
|
||||||
|
"TEST_MED_SHOW");
|
||||||
|
|
||||||
|
/* Answers depending on shuffle (row[2]) */
|
||||||
|
Tst_WriteAnswersTestToAnswer (NumQst,QstCod,Question.Answer.Type,(row[2][0] == 'Y'));
|
||||||
|
|
||||||
|
HTM_TD_End ();
|
||||||
|
|
||||||
|
/***** End row *****/
|
||||||
|
HTM_TR_End ();
|
||||||
|
|
||||||
|
/***** Destroy test question *****/
|
||||||
|
Tst_QstDestructor (&Question);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/********** Write a row of a test, with one question and its answer **********/
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
void Tst_WriteQstAndAnsTestResult (struct UsrData *UsrDat,
|
||||||
|
const struct Tst_UsrAnswers *UsrAnswers,
|
||||||
|
unsigned NumQst,
|
||||||
|
MYSQL_ROW row,
|
||||||
|
unsigned Visibility,
|
||||||
|
double *ScoreThisQst,bool *AnswerIsNotBlank)
|
||||||
{
|
{
|
||||||
extern const char *Txt_TST_STR_ANSWER_TYPES[Tst_NUM_ANS_TYPES];
|
|
||||||
struct Tst_Question Question;
|
struct Tst_Question Question;
|
||||||
bool IsVisibleQstAndAnsTxt = TsV_IsVisibleQstAndAnsTxt (Visibility);
|
bool IsVisibleQstAndAnsTxt = TsV_IsVisibleQstAndAnsTxt (Visibility);
|
||||||
/*
|
/*
|
||||||
|
@ -1108,30 +1151,27 @@ void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestio
|
||||||
row[7] NumHitsNotBlank
|
row[7] NumHitsNotBlank
|
||||||
row[8] Score
|
row[8] Score
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/***** Create test question *****/
|
/***** Create test question *****/
|
||||||
Tst_QstConstructor (&Question);
|
Tst_QstConstructor (&Question);
|
||||||
|
|
||||||
|
/***** Begin row *****/
|
||||||
HTM_TR_Begin (NULL);
|
HTM_TR_Begin (NULL);
|
||||||
|
|
||||||
|
/***** Number of question and answer type (row[1]) *****/
|
||||||
HTM_TD_Begin ("class=\"RT COLOR%u\"",Gbl.RowEvenOdd);
|
HTM_TD_Begin ("class=\"RT COLOR%u\"",Gbl.RowEvenOdd);
|
||||||
|
Tst_WriteNumQst (NumQst + 1);
|
||||||
/***** Write number of question *****/
|
|
||||||
HTM_DIV_Begin ("class=\"BIG_INDEX\"");
|
|
||||||
HTM_Unsigned (NumQst + 1);
|
|
||||||
HTM_DIV_End ();
|
|
||||||
|
|
||||||
/***** Write answer type (row[1]) *****/
|
|
||||||
Question.Answer.Type = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
|
Question.Answer.Type = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
|
||||||
HTM_DIV_Begin ("class=\"DAT_SMALL\"");
|
Tst_WriteAnswerType (Question.Answer.Type);
|
||||||
HTM_Txt (Txt_TST_STR_ANSWER_TYPES[Question.Answer.Type]);
|
|
||||||
HTM_DIV_End ();
|
|
||||||
|
|
||||||
HTM_TD_End ();
|
HTM_TD_End ();
|
||||||
|
|
||||||
/***** Write stem (row[3]) *****/
|
/***** Stem, media and answers *****/
|
||||||
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
|
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
|
||||||
|
|
||||||
|
/* Stem (row[3]) */
|
||||||
Tst_WriteQstStem (row[3],"TEST_EXA",IsVisibleQstAndAnsTxt);
|
Tst_WriteQstStem (row[3],"TEST_EXA",IsVisibleQstAndAnsTxt);
|
||||||
|
|
||||||
/***** Get and show media (row[5]) *****/
|
/* Media (row[5]) */
|
||||||
if (IsVisibleQstAndAnsTxt)
|
if (IsVisibleQstAndAnsTxt)
|
||||||
{
|
{
|
||||||
Question.Media.MedCod = Str_ConvertStrCodToLongCod (row[5]);
|
Question.Media.MedCod = Str_ConvertStrCodToLongCod (row[5]);
|
||||||
|
@ -1141,31 +1181,50 @@ void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestio
|
||||||
"TEST_MED_SHOW");
|
"TEST_MED_SHOW");
|
||||||
}
|
}
|
||||||
|
|
||||||
/***** Write answers depending on shuffle (row[2]) and feedback (row[4]) *****/
|
/* Answers */
|
||||||
switch (ActionToDoWithQuestions)
|
Tst_WriteAnswersTestResult (UsrDat,UsrAnswers,
|
||||||
{
|
NumQst,UsrAnswers->QstCodes[NumQst],Question.Answer.Type,
|
||||||
case Tst_SHOW_TEST_TO_ANSWER:
|
Visibility,
|
||||||
Tst_WriteAnswersTestToAnswer (NumQst,QstCod,Question.Answer.Type,(row[2][0] == 'Y'));
|
ScoreThisQst,AnswerIsNotBlank);
|
||||||
break;
|
|
||||||
case Tst_SHOW_TEST_RESULT:
|
/* Question feedback (row[4]) */
|
||||||
Tst_WriteAnswersTestResult (UsrDat,NumQst,QstCod,Question.Answer.Type,
|
if (TsV_IsVisibleFeedbackTxt (Visibility))
|
||||||
Visibility,
|
Tst_WriteQstFeedback (row[4],"TEST_EXA_LIGHT");
|
||||||
ScoreThisQst,AnswerIsNotBlank);
|
|
||||||
|
|
||||||
/* Write question feedback (row[4]) */
|
|
||||||
if (TsV_IsVisibleFeedbackTxt (Visibility))
|
|
||||||
Tst_WriteQstFeedback (row[4],"TEST_EXA_LIGHT");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
HTM_TD_End ();
|
HTM_TD_End ();
|
||||||
|
|
||||||
|
/***** End row *****/
|
||||||
HTM_TR_End ();
|
HTM_TR_End ();
|
||||||
|
|
||||||
/***** Destroy test question *****/
|
/***** Destroy test question *****/
|
||||||
Tst_QstDestructor (&Question);
|
Tst_QstDestructor (&Question);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/********************* Write the number of a test question *******************/
|
||||||
|
/*****************************************************************************/
|
||||||
|
// Number of question should be 1, 2, 3...
|
||||||
|
|
||||||
|
void Tst_WriteNumQst (unsigned NumQst)
|
||||||
|
{
|
||||||
|
HTM_DIV_Begin ("class=\"BIG_INDEX\"");
|
||||||
|
HTM_Unsigned (NumQst);
|
||||||
|
HTM_DIV_End ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/************************** Write the type of answer *************************/
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
void Tst_WriteAnswerType (Tst_AnswerType_t AnswerType)
|
||||||
|
{
|
||||||
|
extern const char *Txt_TST_STR_ANSWER_TYPES[Tst_NUM_ANS_TYPES];
|
||||||
|
|
||||||
|
HTM_DIV_Begin ("class=\"DAT_SMALL\"");
|
||||||
|
HTM_Txt (Txt_TST_STR_ANSWER_TYPES[AnswerType]);
|
||||||
|
HTM_DIV_End ();
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/********************* Write the stem of a test question *********************/
|
/********************* Write the stem of a test question *********************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@ -2852,7 +2911,6 @@ static void Tst_WriteQuestionRowForEdition (const struct Tst_Tags *Tags,
|
||||||
unsigned long NumRow,
|
unsigned long NumRow,
|
||||||
long QstCod)
|
long QstCod)
|
||||||
{
|
{
|
||||||
extern const char *Txt_TST_STR_ANSWER_TYPES[Tst_NUM_ANS_TYPES];
|
|
||||||
MYSQL_RES *mysql_res;
|
MYSQL_RES *mysql_res;
|
||||||
MYSQL_ROW row;
|
MYSQL_ROW row;
|
||||||
struct Tst_Question Question;
|
struct Tst_Question Question;
|
||||||
|
@ -2907,27 +2965,19 @@ static void Tst_WriteQuestionRowForEdition (const struct Tst_Tags *Tags,
|
||||||
|
|
||||||
HTM_TD_End ();
|
HTM_TD_End ();
|
||||||
|
|
||||||
|
/* Number of question and answer type (row[1]) */
|
||||||
HTM_TD_Begin ("class=\"RT COLOR%u\"",Gbl.RowEvenOdd);
|
HTM_TD_Begin ("class=\"RT COLOR%u\"",Gbl.RowEvenOdd);
|
||||||
|
Tst_WriteNumQst ((unsigned) NumRow + 1);
|
||||||
/* Write number of question */
|
|
||||||
HTM_DIV_Begin ("class=\"BIG_INDEX\"");
|
|
||||||
HTM_UnsignedLong (NumRow + 1);
|
|
||||||
HTM_DIV_End ();
|
|
||||||
|
|
||||||
/* Write answer type (row[1]) */
|
|
||||||
Question.Answer.Type = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
|
Question.Answer.Type = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
|
||||||
HTM_DIV_Begin ("class=\"DAT_SMALL\"");
|
Tst_WriteAnswerType (Question.Answer.Type);
|
||||||
HTM_Txt (Txt_TST_STR_ANSWER_TYPES[Question.Answer.Type]);
|
|
||||||
HTM_DIV_End ();
|
|
||||||
|
|
||||||
HTM_TD_End ();
|
HTM_TD_End ();
|
||||||
|
|
||||||
/* Write question code */
|
/* Question code */
|
||||||
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
|
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
|
||||||
HTM_TxtF ("%ld ",QstCod);
|
HTM_TxtF ("%ld ",QstCod);
|
||||||
HTM_TD_End ();
|
HTM_TD_End ();
|
||||||
|
|
||||||
/* Write the date (row[0] has the UTC date-time) */
|
/* Date (row[0] has the UTC date-time) */
|
||||||
TimeUTC = Dat_GetUNIXTimeFromStr (row[0]);
|
TimeUTC = Dat_GetUNIXTimeFromStr (row[0]);
|
||||||
if (asprintf (&Id,"tst_date_%u",++UniqueId) < 0)
|
if (asprintf (&Id,"tst_date_%u",++UniqueId) < 0)
|
||||||
Lay_NotEnoughMemoryExit ();
|
Lay_NotEnoughMemoryExit ();
|
||||||
|
@ -2939,12 +2989,12 @@ static void Tst_WriteQuestionRowForEdition (const struct Tst_Tags *Tags,
|
||||||
HTM_TD_End ();
|
HTM_TD_End ();
|
||||||
free (Id);
|
free (Id);
|
||||||
|
|
||||||
/* Write the question tags */
|
/* Question tags */
|
||||||
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
|
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
|
||||||
Tst_GetAndWriteTagsQst (QstCod);
|
Tst_GetAndWriteTagsQst (QstCod);
|
||||||
HTM_TD_End ();
|
HTM_TD_End ();
|
||||||
|
|
||||||
/* Write if shuffle is enabled (row[2]) */
|
/* Shuffle (row[2]) */
|
||||||
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
|
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
|
||||||
if (Question.Answer.Type == Tst_ANS_UNIQUE_CHOICE ||
|
if (Question.Answer.Type == Tst_ANS_UNIQUE_CHOICE ||
|
||||||
Question.Answer.Type == Tst_ANS_MULTIPLE_CHOICE)
|
Question.Answer.Type == Tst_ANS_MULTIPLE_CHOICE)
|
||||||
|
@ -2966,7 +3016,7 @@ static void Tst_WriteQuestionRowForEdition (const struct Tst_Tags *Tags,
|
||||||
}
|
}
|
||||||
HTM_TD_End ();
|
HTM_TD_End ();
|
||||||
|
|
||||||
/* Write stem (row[3]) */
|
/* Stem (row[3]) */
|
||||||
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
|
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
|
||||||
Tst_WriteQstStem (row[3],"TEST_EDI",
|
Tst_WriteQstStem (row[3],"TEST_EDI",
|
||||||
true); // Visible
|
true); // Visible
|
||||||
|
@ -2978,7 +3028,7 @@ static void Tst_WriteQuestionRowForEdition (const struct Tst_Tags *Tags,
|
||||||
"TEST_MED_EDIT_LIST_CONT",
|
"TEST_MED_EDIT_LIST_CONT",
|
||||||
"TEST_MED_EDIT_LIST");
|
"TEST_MED_EDIT_LIST");
|
||||||
|
|
||||||
/* Write feedback (row[4]) and answers */
|
/* Feedback (row[4]) and answers */
|
||||||
Tst_WriteQstFeedback (row[4],"TEST_EDI_LIGHT");
|
Tst_WriteQstFeedback (row[4],"TEST_EDI_LIGHT");
|
||||||
Tst_WriteAnswersEdit (QstCod,Question.Answer.Type);
|
Tst_WriteAnswersEdit (QstCod,Question.Answer.Type);
|
||||||
HTM_TD_End ();
|
HTM_TD_End ();
|
||||||
|
@ -3001,12 +3051,12 @@ static void Tst_WriteQuestionRowForEdition (const struct Tst_Tags *Tags,
|
||||||
Lay_ShowErrorAndExit ("Wrong score of a question.");
|
Lay_ShowErrorAndExit ("Wrong score of a question.");
|
||||||
Str_SetDecimalPointToLocal (); // Return to local system
|
Str_SetDecimalPointToLocal (); // Return to local system
|
||||||
|
|
||||||
/* Write number of times this question has been answered */
|
/* Number of times this question has been answered */
|
||||||
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
|
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
|
||||||
HTM_UnsignedLong (NumHitsThisQst);
|
HTM_UnsignedLong (NumHitsThisQst);
|
||||||
HTM_TD_End ();
|
HTM_TD_End ();
|
||||||
|
|
||||||
/* Write average score */
|
/* Average score */
|
||||||
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
|
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
|
||||||
if (NumHitsThisQst)
|
if (NumHitsThisQst)
|
||||||
HTM_Double2Decimals (TotalScoreThisQst /
|
HTM_Double2Decimals (TotalScoreThisQst /
|
||||||
|
@ -3015,12 +3065,12 @@ static void Tst_WriteQuestionRowForEdition (const struct Tst_Tags *Tags,
|
||||||
HTM_Txt ("N.A.");
|
HTM_Txt ("N.A.");
|
||||||
HTM_TD_End ();
|
HTM_TD_End ();
|
||||||
|
|
||||||
/* Write number of times this question has been answered (not blank) */
|
/* Number of times this question has been answered (not blank) */
|
||||||
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
|
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
|
||||||
HTM_UnsignedLong (NumHitsNotBlankThisQst);
|
HTM_UnsignedLong (NumHitsNotBlankThisQst);
|
||||||
HTM_TD_End ();
|
HTM_TD_End ();
|
||||||
|
|
||||||
/* Write average score (not blank) */
|
/* Average score (not blank) */
|
||||||
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
|
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
|
||||||
if (NumHitsNotBlankThisQst)
|
if (NumHitsNotBlankThisQst)
|
||||||
HTM_Double2Decimals (TotalScoreThisQst /
|
HTM_Double2Decimals (TotalScoreThisQst /
|
||||||
|
@ -3054,7 +3104,6 @@ static void Tst_ListOneOrMoreQuestionsForSelection (unsigned long NumRows,
|
||||||
extern const char *Txt_Date;
|
extern const char *Txt_Date;
|
||||||
extern const char *Txt_Tags;
|
extern const char *Txt_Tags;
|
||||||
extern const char *Txt_Type;
|
extern const char *Txt_Type;
|
||||||
extern const char *Txt_TST_STR_ANSWER_TYPES[Tst_NUM_ANS_TYPES];
|
|
||||||
extern const char *Txt_Shuffle;
|
extern const char *Txt_Shuffle;
|
||||||
extern const char *Txt_Question;
|
extern const char *Txt_Question;
|
||||||
extern const char *Txt_Add_questions;
|
extern const char *Txt_Add_questions;
|
||||||
|
@ -3578,6 +3627,7 @@ static void Tst_WriteAnswersTestToAnswer (unsigned NumQst,long QstCod,
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static void Tst_WriteAnswersTestResult (struct UsrData *UsrDat,
|
static void Tst_WriteAnswersTestResult (struct UsrData *UsrDat,
|
||||||
|
const struct Tst_UsrAnswers *UsrAnswers,
|
||||||
unsigned NumQst,long QstCod,
|
unsigned NumQst,long QstCod,
|
||||||
Tst_AnswerType_t AnswerType,
|
Tst_AnswerType_t AnswerType,
|
||||||
unsigned Visibility,
|
unsigned Visibility,
|
||||||
|
@ -3604,28 +3654,33 @@ static void Tst_WriteAnswersTestResult (struct UsrData *UsrDat,
|
||||||
switch (Question.Answer.Type)
|
switch (Question.Answer.Type)
|
||||||
{
|
{
|
||||||
case Tst_ANS_INT:
|
case Tst_ANS_INT:
|
||||||
Tst_WriteIntAnsAssessTest (UsrDat,NumQst,&Question,mysql_res,
|
Tst_WriteIntAnsAssessTest (UsrDat,UsrAnswers,
|
||||||
|
NumQst,&Question,mysql_res,
|
||||||
Visibility,
|
Visibility,
|
||||||
ScoreThisQst,AnswerIsNotBlank);
|
ScoreThisQst,AnswerIsNotBlank);
|
||||||
break;
|
break;
|
||||||
case Tst_ANS_FLOAT:
|
case Tst_ANS_FLOAT:
|
||||||
Tst_WriteFloatAnsAssessTest (UsrDat,NumQst,&Question,mysql_res,
|
Tst_WriteFloatAnsAssessTest (UsrDat,UsrAnswers,
|
||||||
|
NumQst,&Question,mysql_res,
|
||||||
Visibility,
|
Visibility,
|
||||||
ScoreThisQst,AnswerIsNotBlank);
|
ScoreThisQst,AnswerIsNotBlank);
|
||||||
break;
|
break;
|
||||||
case Tst_ANS_TRUE_FALSE:
|
case Tst_ANS_TRUE_FALSE:
|
||||||
Tst_WriteTFAnsAssessTest (UsrDat,NumQst,&Question,mysql_res,
|
Tst_WriteTFAnsAssessTest (UsrDat,UsrAnswers,
|
||||||
|
NumQst,&Question,mysql_res,
|
||||||
Visibility,
|
Visibility,
|
||||||
ScoreThisQst,AnswerIsNotBlank);
|
ScoreThisQst,AnswerIsNotBlank);
|
||||||
break;
|
break;
|
||||||
case Tst_ANS_UNIQUE_CHOICE:
|
case Tst_ANS_UNIQUE_CHOICE:
|
||||||
case Tst_ANS_MULTIPLE_CHOICE:
|
case Tst_ANS_MULTIPLE_CHOICE:
|
||||||
Tst_WriteChoiceAnsAssessTest (UsrDat,NumQst,&Question,mysql_res,
|
Tst_WriteChoiceAnsAssessTest (UsrDat,UsrAnswers,
|
||||||
|
NumQst,&Question,mysql_res,
|
||||||
Visibility,
|
Visibility,
|
||||||
ScoreThisQst,AnswerIsNotBlank);
|
ScoreThisQst,AnswerIsNotBlank);
|
||||||
break;
|
break;
|
||||||
case Tst_ANS_TEXT:
|
case Tst_ANS_TEXT:
|
||||||
Tst_WriteTextAnsAssessTest (UsrDat,NumQst,&Question,mysql_res,
|
Tst_WriteTextAnsAssessTest (UsrDat,UsrAnswers,
|
||||||
|
NumQst,&Question,mysql_res,
|
||||||
Visibility,
|
Visibility,
|
||||||
ScoreThisQst,AnswerIsNotBlank);
|
ScoreThisQst,AnswerIsNotBlank);
|
||||||
break;
|
break;
|
||||||
|
@ -3698,6 +3753,7 @@ void Tst_WriteAnsTF (char AnsTF)
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static void Tst_WriteTFAnsAssessTest (struct UsrData *UsrDat,
|
static void Tst_WriteTFAnsAssessTest (struct UsrData *UsrDat,
|
||||||
|
const struct Tst_UsrAnswers *UsrAnswers,
|
||||||
unsigned NumQst,
|
unsigned NumQst,
|
||||||
const struct Tst_Question *Question,
|
const struct Tst_Question *Question,
|
||||||
MYSQL_RES *mysql_res,
|
MYSQL_RES *mysql_res,
|
||||||
|
@ -3721,7 +3777,7 @@ static void Tst_WriteTFAnsAssessTest (struct UsrData *UsrDat,
|
||||||
row = mysql_fetch_row (mysql_res);
|
row = mysql_fetch_row (mysql_res);
|
||||||
|
|
||||||
/***** Compute the mark for this question *****/
|
/***** Compute the mark for this question *****/
|
||||||
AnsTF = Gbl.Test.StrAnswersOneQst[NumQst][0];
|
AnsTF = UsrAnswers->StrAnswersOneQst[NumQst][0];
|
||||||
if (AnsTF == '\0') // User has omitted the answer (the answer is blank)
|
if (AnsTF == '\0') // User has omitted the answer (the answer is blank)
|
||||||
{
|
{
|
||||||
*AnswerIsNotBlank = false;
|
*AnswerIsNotBlank = false;
|
||||||
|
@ -3919,6 +3975,7 @@ static void Tst_WriteChoiceAnsViewTest (unsigned NumQst,long QstCod,
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat,
|
static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat,
|
||||||
|
const struct Tst_UsrAnswers *UsrAnswers,
|
||||||
unsigned NumQst,
|
unsigned NumQst,
|
||||||
struct Tst_Question *Question,
|
struct Tst_Question *Question,
|
||||||
MYSQL_RES *mysql_res,
|
MYSQL_RES *mysql_res,
|
||||||
|
@ -3942,10 +3999,10 @@ static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat,
|
||||||
Tst_GetChoiceAns (mysql_res,Question);
|
Tst_GetChoiceAns (mysql_res,Question);
|
||||||
|
|
||||||
/***** Get indexes for this question from string *****/
|
/***** Get indexes for this question from string *****/
|
||||||
Tst_GetIndexesFromStr (Gbl.Test.StrIndexesOneQst[NumQst],Indexes);
|
Tst_GetIndexesFromStr (UsrAnswers->StrIndexesOneQst[NumQst],Indexes);
|
||||||
|
|
||||||
/***** Get the user's answers for this question from string *****/
|
/***** Get the user's answers for this question from string *****/
|
||||||
Tst_GetAnswersFromStr (Gbl.Test.StrAnswersOneQst[NumQst],AnswersUsr);
|
Tst_GetAnswersFromStr (UsrAnswers->StrAnswersOneQst[NumQst],AnswersUsr);
|
||||||
|
|
||||||
/***** Compute the total score of this question *****/
|
/***** Compute the total score of this question *****/
|
||||||
Tst_ComputeScoreQst (Question,Indexes,AnswersUsr,ScoreThisQst,AnswerIsNotBlank);
|
Tst_ComputeScoreQst (Question,Indexes,AnswersUsr,ScoreThisQst,AnswerIsNotBlank);
|
||||||
|
@ -4417,6 +4474,7 @@ static void Tst_WriteTextAnsViewTest (unsigned NumQst)
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat,
|
static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat,
|
||||||
|
const struct Tst_UsrAnswers *UsrAnswers,
|
||||||
unsigned NumQst,
|
unsigned NumQst,
|
||||||
struct Tst_Question *Question,
|
struct Tst_Question *Question,
|
||||||
MYSQL_RES *mysql_res,
|
MYSQL_RES *mysql_res,
|
||||||
|
@ -4481,10 +4539,10 @@ static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat,
|
||||||
HTM_TR_Begin (NULL);
|
HTM_TR_Begin (NULL);
|
||||||
|
|
||||||
/***** Write the user answer *****/
|
/***** Write the user answer *****/
|
||||||
if (Gbl.Test.StrAnswersOneQst[NumQst][0]) // If user has answered the question
|
if (UsrAnswers->StrAnswersOneQst[NumQst][0]) // If user has answered the question
|
||||||
{
|
{
|
||||||
/* Filter the user answer */
|
/* Filter the user answer */
|
||||||
Str_Copy (TextAnsUsr,Gbl.Test.StrAnswersOneQst[NumQst],
|
Str_Copy (TextAnsUsr,UsrAnswers->StrAnswersOneQst[NumQst],
|
||||||
Tst_MAX_BYTES_ANSWERS_ONE_QST);
|
Tst_MAX_BYTES_ANSWERS_ONE_QST);
|
||||||
|
|
||||||
/* In order to compare student answer to stored answer,
|
/* In order to compare student answer to stored answer,
|
||||||
|
@ -4514,7 +4572,7 @@ static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat,
|
||||||
(Correct ? "ANS_OK" :
|
(Correct ? "ANS_OK" :
|
||||||
"ANS_BAD") :
|
"ANS_BAD") :
|
||||||
"ANS_0");
|
"ANS_0");
|
||||||
HTM_Txt (Gbl.Test.StrAnswersOneQst[NumQst]);
|
HTM_Txt (UsrAnswers->StrAnswersOneQst[NumQst]);
|
||||||
}
|
}
|
||||||
else // If user has omitted the answer
|
else // If user has omitted the answer
|
||||||
HTM_TD_Begin (NULL);
|
HTM_TD_Begin (NULL);
|
||||||
|
@ -4571,7 +4629,7 @@ static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat,
|
||||||
HTM_TR_End ();
|
HTM_TR_End ();
|
||||||
|
|
||||||
/***** Compute the mark *****/
|
/***** Compute the mark *****/
|
||||||
if (!Gbl.Test.StrAnswersOneQst[NumQst][0]) // If user has omitted the answer
|
if (!UsrAnswers->StrAnswersOneQst[NumQst][0]) // If user has omitted the answer
|
||||||
{
|
{
|
||||||
*AnswerIsNotBlank = false;
|
*AnswerIsNotBlank = false;
|
||||||
*ScoreThisQst = 0.0;
|
*ScoreThisQst = 0.0;
|
||||||
|
@ -4589,7 +4647,7 @@ static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat,
|
||||||
if (TsV_IsVisibleEachQstScore (Visibility))
|
if (TsV_IsVisibleEachQstScore (Visibility))
|
||||||
{
|
{
|
||||||
Tst_WriteScoreStart (4);
|
Tst_WriteScoreStart (4);
|
||||||
if (!Gbl.Test.StrAnswersOneQst[NumQst][0]) // If user has omitted the answer
|
if (!UsrAnswers->StrAnswersOneQst[NumQst][0]) // If user has omitted the answer
|
||||||
{
|
{
|
||||||
HTM_SPAN_Begin ("class=\"ANS_0\"");
|
HTM_SPAN_Begin ("class=\"ANS_0\"");
|
||||||
HTM_Double2Decimals (0.0);
|
HTM_Double2Decimals (0.0);
|
||||||
|
@ -4632,6 +4690,7 @@ static void Tst_WriteIntAnsViewTest (unsigned NumQst)
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static void Tst_WriteIntAnsAssessTest (struct UsrData *UsrDat,
|
static void Tst_WriteIntAnsAssessTest (struct UsrData *UsrDat,
|
||||||
|
const struct Tst_UsrAnswers *UsrAnswers,
|
||||||
unsigned NumQst,
|
unsigned NumQst,
|
||||||
const struct Tst_Question *Question,
|
const struct Tst_Question *Question,
|
||||||
MYSQL_RES *mysql_res,
|
MYSQL_RES *mysql_res,
|
||||||
|
@ -4666,9 +4725,9 @@ static void Tst_WriteIntAnsAssessTest (struct UsrData *UsrDat,
|
||||||
HTM_TR_Begin (NULL);
|
HTM_TR_Begin (NULL);
|
||||||
|
|
||||||
/***** Write the user answer *****/
|
/***** Write the user answer *****/
|
||||||
if (Gbl.Test.StrAnswersOneQst[NumQst][0]) // If user has answered the question
|
if (UsrAnswers->StrAnswersOneQst[NumQst][0]) // If user has answered the question
|
||||||
{
|
{
|
||||||
if (sscanf (Gbl.Test.StrAnswersOneQst[NumQst],"%ld",&IntAnswerUsr) == 1)
|
if (sscanf (UsrAnswers->StrAnswersOneQst[NumQst],"%ld",&IntAnswerUsr) == 1)
|
||||||
{
|
{
|
||||||
HTM_TD_Begin ("class=\"%s CM\"",
|
HTM_TD_Begin ("class=\"%s CM\"",
|
||||||
TsV_IsVisibleCorrectAns (Visibility) ?
|
TsV_IsVisibleCorrectAns (Visibility) ?
|
||||||
|
@ -4680,7 +4739,6 @@ static void Tst_WriteIntAnsAssessTest (struct UsrData *UsrDat,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Gbl.Test.StrAnswersOneQst[NumQst][0] = '\0';
|
|
||||||
HTM_TD_Begin ("class=\"ANS_0 CM\"");
|
HTM_TD_Begin ("class=\"ANS_0 CM\"");
|
||||||
HTM_Txt ("?");
|
HTM_Txt ("?");
|
||||||
HTM_TD_End ();
|
HTM_TD_End ();
|
||||||
|
@ -4701,7 +4759,7 @@ static void Tst_WriteIntAnsAssessTest (struct UsrData *UsrDat,
|
||||||
HTM_TR_End ();
|
HTM_TR_End ();
|
||||||
|
|
||||||
/***** Compute the score *****/
|
/***** Compute the score *****/
|
||||||
if (!Gbl.Test.StrAnswersOneQst[NumQst][0]) // If user has omitted the answer
|
if (!UsrAnswers->StrAnswersOneQst[NumQst][0]) // If user has omitted the answer
|
||||||
{
|
{
|
||||||
*AnswerIsNotBlank = false;
|
*AnswerIsNotBlank = false;
|
||||||
*ScoreThisQst = 0.0;
|
*ScoreThisQst = 0.0;
|
||||||
|
@ -4719,7 +4777,7 @@ static void Tst_WriteIntAnsAssessTest (struct UsrData *UsrDat,
|
||||||
if (TsV_IsVisibleEachQstScore (Visibility))
|
if (TsV_IsVisibleEachQstScore (Visibility))
|
||||||
{
|
{
|
||||||
Tst_WriteScoreStart (2);
|
Tst_WriteScoreStart (2);
|
||||||
if (!Gbl.Test.StrAnswersOneQst[NumQst][0]) // If user has omitted the answer
|
if (!UsrAnswers->StrAnswersOneQst[NumQst][0]) // If user has omitted the answer
|
||||||
{
|
{
|
||||||
HTM_SPAN_Begin ("class=\"ANS_0\"");
|
HTM_SPAN_Begin ("class=\"ANS_0\"");
|
||||||
HTM_Double2Decimals (0.0);
|
HTM_Double2Decimals (0.0);
|
||||||
|
@ -4762,6 +4820,7 @@ static void Tst_WriteFloatAnsViewTest (unsigned NumQst)
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static void Tst_WriteFloatAnsAssessTest (struct UsrData *UsrDat,
|
static void Tst_WriteFloatAnsAssessTest (struct UsrData *UsrDat,
|
||||||
|
const struct Tst_UsrAnswers *UsrAnswers,
|
||||||
unsigned NumQst,
|
unsigned NumQst,
|
||||||
const struct Tst_Question *Question,
|
const struct Tst_Question *Question,
|
||||||
MYSQL_RES *mysql_res,
|
MYSQL_RES *mysql_res,
|
||||||
|
@ -4809,10 +4868,10 @@ static void Tst_WriteFloatAnsAssessTest (struct UsrData *UsrDat,
|
||||||
HTM_TR_Begin (NULL);
|
HTM_TR_Begin (NULL);
|
||||||
|
|
||||||
/***** Write the user answer *****/
|
/***** Write the user answer *****/
|
||||||
if (Gbl.Test.StrAnswersOneQst[NumQst][0]) // If user has answered the question
|
if (UsrAnswers->StrAnswersOneQst[NumQst][0]) // If user has answered the question
|
||||||
{
|
{
|
||||||
FloatAnsUsr = Str_GetDoubleFromStr (Gbl.Test.StrAnswersOneQst[NumQst]);
|
FloatAnsUsr = Str_GetDoubleFromStr (UsrAnswers->StrAnswersOneQst[NumQst]);
|
||||||
if (Gbl.Test.StrAnswersOneQst[NumQst][0]) // It's a correct floating point number
|
if (UsrAnswers->StrAnswersOneQst[NumQst][0]) // It's a correct floating point number
|
||||||
{
|
{
|
||||||
HTM_TD_Begin ("class=\"%s CM\"",
|
HTM_TD_Begin ("class=\"%s CM\"",
|
||||||
TsV_IsVisibleCorrectAns (Visibility) ?
|
TsV_IsVisibleCorrectAns (Visibility) ?
|
||||||
|
@ -4850,7 +4909,7 @@ static void Tst_WriteFloatAnsAssessTest (struct UsrData *UsrDat,
|
||||||
HTM_TR_End ();
|
HTM_TR_End ();
|
||||||
|
|
||||||
/***** Compute mark *****/
|
/***** Compute mark *****/
|
||||||
if (!Gbl.Test.StrAnswersOneQst[NumQst][0]) // If user has omitted the answer
|
if (!UsrAnswers->StrAnswersOneQst[NumQst][0]) // If user has omitted the answer
|
||||||
{
|
{
|
||||||
*AnswerIsNotBlank = false;
|
*AnswerIsNotBlank = false;
|
||||||
*ScoreThisQst = 0.0;
|
*ScoreThisQst = 0.0;
|
||||||
|
@ -4869,7 +4928,7 @@ static void Tst_WriteFloatAnsAssessTest (struct UsrData *UsrDat,
|
||||||
if (TsV_IsVisibleEachQstScore (Visibility))
|
if (TsV_IsVisibleEachQstScore (Visibility))
|
||||||
{
|
{
|
||||||
Tst_WriteScoreStart (2);
|
Tst_WriteScoreStart (2);
|
||||||
if (!Gbl.Test.StrAnswersOneQst[NumQst][0]) // If user has omitted the answer
|
if (!UsrAnswers->StrAnswersOneQst[NumQst][0]) // If user has omitted the answer
|
||||||
{
|
{
|
||||||
HTM_SPAN_Begin ("class=\"ANS_0\"");
|
HTM_SPAN_Begin ("class=\"ANS_0\"");
|
||||||
HTM_Double2Decimals (0.0);
|
HTM_Double2Decimals (0.0);
|
||||||
|
|
25
swad_test.h
25
swad_test.h
|
@ -41,10 +41,6 @@
|
||||||
#define Tst_MAX_CHARS_TAG (128 - 1) // 127
|
#define Tst_MAX_CHARS_TAG (128 - 1) // 127
|
||||||
#define Tst_MAX_BYTES_TAG ((Tst_MAX_CHARS_TAG + 1) * Str_MAX_BYTES_PER_CHAR - 1) // 2047
|
#define Tst_MAX_BYTES_TAG ((Tst_MAX_CHARS_TAG + 1) * Str_MAX_BYTES_PER_CHAR - 1) // 2047
|
||||||
|
|
||||||
#define Tst_MAX_OPTIONS_PER_QUESTION 10
|
|
||||||
#define Tst_MAX_BYTES_INDEXES_ONE_QST (Tst_MAX_OPTIONS_PER_QUESTION * (3 + 1))
|
|
||||||
#define Tst_MAX_BYTES_ANSWERS_ONE_QST (Tst_MAX_OPTIONS_PER_QUESTION * (3 + 1))
|
|
||||||
|
|
||||||
#define Tst_MAX_CHARS_ANSWER_OR_FEEDBACK (1024 - 1) // 1023
|
#define Tst_MAX_CHARS_ANSWER_OR_FEEDBACK (1024 - 1) // 1023
|
||||||
#define Tst_MAX_BYTES_ANSWER_OR_FEEDBACK ((Tst_MAX_CHARS_ANSWER_OR_FEEDBACK + 1) * Str_MAX_BYTES_PER_CHAR - 1) // 16383
|
#define Tst_MAX_BYTES_ANSWER_OR_FEEDBACK ((Tst_MAX_CHARS_ANSWER_OR_FEEDBACK + 1) * Str_MAX_BYTES_PER_CHAR - 1) // 16383
|
||||||
|
|
||||||
|
@ -97,11 +93,7 @@ struct Tst_Test
|
||||||
struct Tst_Tags Tags;
|
struct Tst_Tags Tags;
|
||||||
struct Tst_AnswerTypes AnswerTypes;
|
struct Tst_AnswerTypes AnswerTypes;
|
||||||
Tst_QuestionsOrder_t SelectedOrder;
|
Tst_QuestionsOrder_t SelectedOrder;
|
||||||
long QstCodes[TstCfg_MAX_QUESTIONS_PER_TEST]; // Codes of the sent/received questions in a test
|
// struct Tst_UsrAnswers UsrAnswers;
|
||||||
char StrIndexesOneQst[TstCfg_MAX_QUESTIONS_PER_TEST]
|
|
||||||
[Tst_MAX_BYTES_INDEXES_ONE_QST + 1]; // 0 1 2 3, 3 0 2 1, etc.
|
|
||||||
char StrAnswersOneQst[TstCfg_MAX_QUESTIONS_PER_TEST]
|
|
||||||
[Tst_MAX_BYTES_ANSWERS_ONE_QST + 1]; // Answers selected by user
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Tst_Question
|
struct Tst_Question
|
||||||
|
@ -165,13 +157,14 @@ void Tst_ShowGrade (double Grade,double MaxGrade);
|
||||||
|
|
||||||
void Tst_ShowTagList (unsigned NumTags,MYSQL_RES *mysql_res);
|
void Tst_ShowTagList (unsigned NumTags,MYSQL_RES *mysql_res);
|
||||||
|
|
||||||
void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestions,
|
void Tst_WriteQstAndAnsTestResult (struct UsrData *UsrDat,
|
||||||
struct UsrData *UsrDat,
|
const struct Tst_UsrAnswers *UsrAnswers,
|
||||||
unsigned NumQst,
|
unsigned NumQst,
|
||||||
long QstCod,
|
MYSQL_ROW row,
|
||||||
MYSQL_ROW row,
|
unsigned Visibility,
|
||||||
unsigned Visibility,
|
double *ScoreThisQst,bool *AnswerIsNotBlank);
|
||||||
double *ScoreThisQst,bool *AnswerIsNotBlank);
|
void Tst_WriteNumQst (unsigned NumQst);
|
||||||
|
void Tst_WriteAnswerType (Tst_AnswerType_t AnswerType);
|
||||||
void Tst_WriteQstStem (const char *Stem,const char *ClassStem,bool Visible);
|
void Tst_WriteQstStem (const char *Stem,const char *ClassStem,bool Visible);
|
||||||
void Tst_WriteQstFeedback (const char *Feedback,const char *ClassFeedback);
|
void Tst_WriteQstFeedback (const char *Feedback,const char *ClassFeedback);
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ static void TsR_GetTestResultDataByTstCod (long TstCod,
|
||||||
unsigned *NumQsts,
|
unsigned *NumQsts,
|
||||||
unsigned *NumQstsNotBlank,
|
unsigned *NumQstsNotBlank,
|
||||||
double *Score);
|
double *Score);
|
||||||
static unsigned TsR_GetTestResultQuestionsFromDB (long TstCod);
|
static unsigned TsR_GetTestResultQuestionsFromDB (long TstCod,struct Tst_UsrAnswers *UsrAnswers);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/************ Select users and dates to show their test results **************/
|
/************ Select users and dates to show their test results **************/
|
||||||
|
@ -606,6 +606,7 @@ void TsR_ShowOneTstResult (void)
|
||||||
time_t TstTimeUTC = 0; // Test result UTC date-time, initialized to avoid warning
|
time_t TstTimeUTC = 0; // Test result UTC date-time, initialized to avoid warning
|
||||||
unsigned NumQsts;
|
unsigned NumQsts;
|
||||||
unsigned NumQstsNotBlank;
|
unsigned NumQstsNotBlank;
|
||||||
|
struct Tst_UsrAnswers UsrAnswers;
|
||||||
double TotalScore;
|
double TotalScore;
|
||||||
bool ShowPhoto;
|
bool ShowPhoto;
|
||||||
char PhotoURL[PATH_MAX + 1];
|
char PhotoURL[PATH_MAX + 1];
|
||||||
|
@ -674,7 +675,7 @@ void TsR_ShowOneTstResult (void)
|
||||||
if (ICanViewTest) // I am allowed to view this test result
|
if (ICanViewTest) // I am allowed to view this test result
|
||||||
{
|
{
|
||||||
/***** Get questions and user's answers of the test result from database *****/
|
/***** Get questions and user's answers of the test result from database *****/
|
||||||
NumQsts = TsR_GetTestResultQuestionsFromDB (TstCod);
|
NumQsts = TsR_GetTestResultQuestionsFromDB (TstCod,&UsrAnswers);
|
||||||
|
|
||||||
/***** Begin box *****/
|
/***** Begin box *****/
|
||||||
Box_BoxBegin (NULL,Txt_Test_result,NULL,
|
Box_BoxBegin (NULL,Txt_Test_result,NULL,
|
||||||
|
@ -791,7 +792,9 @@ void TsR_ShowOneTstResult (void)
|
||||||
|
|
||||||
/***** Write answers and solutions *****/
|
/***** Write answers and solutions *****/
|
||||||
TsR_ShowTestResult (&Gbl.Usrs.Other.UsrDat,
|
TsR_ShowTestResult (&Gbl.Usrs.Other.UsrDat,
|
||||||
NumQsts,TstTimeUTC,
|
NumQsts,
|
||||||
|
&UsrAnswers,
|
||||||
|
TstTimeUTC,
|
||||||
TstCfg_GetConfigVisibility ());
|
TstCfg_GetConfigVisibility ());
|
||||||
|
|
||||||
/***** End table *****/
|
/***** End table *****/
|
||||||
|
@ -850,7 +853,9 @@ static void TsR_ShowTstTagsPresentInATestResult (long TstCod)
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
void TsR_ShowTestResult (struct UsrData *UsrDat,
|
void TsR_ShowTestResult (struct UsrData *UsrDat,
|
||||||
unsigned NumQsts,time_t TstTimeUTC,
|
unsigned NumQsts,
|
||||||
|
const struct Tst_UsrAnswers *UsrAnswers,
|
||||||
|
time_t TstTimeUTC,
|
||||||
unsigned Visibility)
|
unsigned Visibility)
|
||||||
{
|
{
|
||||||
extern const char *Txt_Question_modified;
|
extern const char *Txt_Question_modified;
|
||||||
|
@ -870,21 +875,10 @@ void TsR_ShowTestResult (struct UsrData *UsrDat,
|
||||||
Gbl.RowEvenOdd = NumQst % 2;
|
Gbl.RowEvenOdd = NumQst % 2;
|
||||||
|
|
||||||
/***** Query database *****/
|
/***** Query database *****/
|
||||||
if (Tst_GetOneQuestionByCod (Gbl.Test.QstCodes[NumQst],&mysql_res)) // Question exists
|
if (Tst_GetOneQuestionByCod (UsrAnswers->QstCodes[NumQst],&mysql_res)) // Question exists
|
||||||
{
|
{
|
||||||
/***** Get row of the result of the query *****/
|
/***** Get row of the result of the query *****/
|
||||||
row = mysql_fetch_row (mysql_res);
|
row = mysql_fetch_row (mysql_res);
|
||||||
/*
|
|
||||||
row[0] UNIX_TIMESTAMP(EditTime)
|
|
||||||
row[1] AnsType
|
|
||||||
row[2] Shuffle
|
|
||||||
row[3] Stem
|
|
||||||
row[4] Feedback
|
|
||||||
row[5] MedCod
|
|
||||||
row[6] NumHits
|
|
||||||
row[7] NumHitsNotBlank
|
|
||||||
row[8] Score
|
|
||||||
*/
|
|
||||||
|
|
||||||
/***** If this question has been edited later than test time
|
/***** If this question has been edited later than test time
|
||||||
==> don't show question ****/
|
==> don't show question ****/
|
||||||
|
@ -910,13 +904,13 @@ void TsR_ShowTestResult (struct UsrData *UsrDat,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/***** Write questions and answers *****/
|
/***** Write questions and answers *****/
|
||||||
Tst_WriteQstAndAnsTest (Tst_SHOW_TEST_RESULT,
|
Tst_WriteQstAndAnsTestResult (UsrDat,
|
||||||
UsrDat,
|
UsrAnswers,
|
||||||
NumQst,Gbl.Test.QstCodes[NumQst],
|
NumQst,
|
||||||
row,
|
row,
|
||||||
Visibility,
|
Visibility,
|
||||||
&ScoreThisQst, // Not used here
|
&ScoreThisQst, // Not used here
|
||||||
&AnswerIsNotBlank); // Not used here
|
&AnswerIsNotBlank); // Not used here
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1001,15 +995,17 @@ static void TsR_GetTestResultDataByTstCod (long TstCod,
|
||||||
/************ Store user's answers of an test result into database ***********/
|
/************ Store user's answers of an test result into database ***********/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
void TsR_StoreOneTestResultQstInDB (long TstCod,long QstCod,unsigned NumQst,double Score)
|
void TsR_StoreOneTestResultQstInDB (long TstCod,
|
||||||
|
const struct Tst_UsrAnswers *UsrAnswers,
|
||||||
|
unsigned NumQst,double Score)
|
||||||
{
|
{
|
||||||
char Indexes[Tst_MAX_BYTES_INDEXES_ONE_QST + 1];
|
char Indexes[Tst_MAX_BYTES_INDEXES_ONE_QST + 1];
|
||||||
char Answers[Tst_MAX_BYTES_ANSWERS_ONE_QST + 1];
|
char Answers[Tst_MAX_BYTES_ANSWERS_ONE_QST + 1];
|
||||||
|
|
||||||
/***** Replace each separator of multiple parameters by a comma *****/
|
/***** Replace each separator of multiple parameters by a comma *****/
|
||||||
/* In database commas are used as separators instead of special chars */
|
/* In database commas are used as separators instead of special chars */
|
||||||
Par_ReplaceSeparatorMultipleByComma (Gbl.Test.StrIndexesOneQst[NumQst],Indexes);
|
Par_ReplaceSeparatorMultipleByComma (UsrAnswers->StrIndexesOneQst[NumQst],Indexes);
|
||||||
Par_ReplaceSeparatorMultipleByComma (Gbl.Test.StrAnswersOneQst[NumQst],Answers);
|
Par_ReplaceSeparatorMultipleByComma (UsrAnswers->StrAnswersOneQst[NumQst],Answers);
|
||||||
|
|
||||||
/***** Insert question and user's answers into database *****/
|
/***** Insert question and user's answers into database *****/
|
||||||
Str_SetDecimalPointToUS (); // To print the floating point as a dot
|
Str_SetDecimalPointToUS (); // To print the floating point as a dot
|
||||||
|
@ -1018,7 +1014,7 @@ void TsR_StoreOneTestResultQstInDB (long TstCod,long QstCod,unsigned NumQst,doub
|
||||||
" (TstCod,QstCod,QstInd,Score,Indexes,Answers)"
|
" (TstCod,QstCod,QstInd,Score,Indexes,Answers)"
|
||||||
" VALUES"
|
" VALUES"
|
||||||
" (%ld,%ld,%u,'%.15lg','%s','%s')",
|
" (%ld,%ld,%u,'%.15lg','%s','%s')",
|
||||||
TstCod,QstCod,
|
TstCod,UsrAnswers->QstCodes[NumQst],
|
||||||
NumQst, // 0, 1, 2, 3...
|
NumQst, // 0, 1, 2, 3...
|
||||||
Score,
|
Score,
|
||||||
Indexes,
|
Indexes,
|
||||||
|
@ -1030,7 +1026,7 @@ void TsR_StoreOneTestResultQstInDB (long TstCod,long QstCod,unsigned NumQst,doub
|
||||||
/************ Get the questions of a test result from database ***************/
|
/************ Get the questions of a test result from database ***************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static unsigned TsR_GetTestResultQuestionsFromDB (long TstCod)
|
static unsigned TsR_GetTestResultQuestionsFromDB (long TstCod,struct Tst_UsrAnswers *UsrAnswers)
|
||||||
{
|
{
|
||||||
MYSQL_RES *mysql_res;
|
MYSQL_RES *mysql_res;
|
||||||
MYSQL_ROW row;
|
MYSQL_ROW row;
|
||||||
|
@ -1056,21 +1052,21 @@ static unsigned TsR_GetTestResultQuestionsFromDB (long TstCod)
|
||||||
row = mysql_fetch_row (mysql_res);
|
row = mysql_fetch_row (mysql_res);
|
||||||
|
|
||||||
/* Get question code */
|
/* Get question code */
|
||||||
if ((Gbl.Test.QstCodes[NumQst] = Str_ConvertStrCodToLongCod (row[0])) < 0)
|
if ((UsrAnswers->QstCodes[NumQst] = Str_ConvertStrCodToLongCod (row[0])) < 0)
|
||||||
Lay_ShowErrorAndExit ("Wrong code of question.");
|
Lay_ShowErrorAndExit ("Wrong code of question.");
|
||||||
|
|
||||||
/* Get indexes for this question (row[1]) */
|
/* Get indexes for this question (row[1]) */
|
||||||
Str_Copy (Gbl.Test.StrIndexesOneQst[NumQst],row[1],
|
Str_Copy (UsrAnswers->StrIndexesOneQst[NumQst],row[1],
|
||||||
Tst_MAX_BYTES_INDEXES_ONE_QST);
|
Tst_MAX_BYTES_INDEXES_ONE_QST);
|
||||||
|
|
||||||
/* Get answers selected by user for this question (row[2]) */
|
/* Get answers selected by user for this question (row[2]) */
|
||||||
Str_Copy (Gbl.Test.StrAnswersOneQst[NumQst],row[2],
|
Str_Copy (UsrAnswers->StrAnswersOneQst[NumQst],row[2],
|
||||||
Tst_MAX_BYTES_ANSWERS_ONE_QST);
|
Tst_MAX_BYTES_ANSWERS_ONE_QST);
|
||||||
|
|
||||||
/* Replace each comma by a separator of multiple parameters */
|
/* Replace each comma by a separator of multiple parameters */
|
||||||
/* In database commas are used as separators instead of special chars */
|
/* In database commas are used as separators instead of special chars */
|
||||||
Par_ReplaceCommaBySeparatorMultiple (Gbl.Test.StrIndexesOneQst[NumQst]);
|
Par_ReplaceCommaBySeparatorMultiple (UsrAnswers->StrIndexesOneQst[NumQst]);
|
||||||
Par_ReplaceCommaBySeparatorMultiple (Gbl.Test.StrAnswersOneQst[NumQst]);
|
Par_ReplaceCommaBySeparatorMultiple (UsrAnswers->StrAnswersOneQst[NumQst]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***** Free structure that stores the query result *****/
|
/***** Free structure that stores the query result *****/
|
||||||
|
|
|
@ -33,12 +33,25 @@
|
||||||
/***************************** Public constants ******************************/
|
/***************************** Public constants ******************************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#define Tst_MAX_OPTIONS_PER_QUESTION 10
|
||||||
|
#define Tst_MAX_BYTES_INDEXES_ONE_QST (Tst_MAX_OPTIONS_PER_QUESTION * (3 + 1))
|
||||||
|
#define Tst_MAX_BYTES_ANSWERS_ONE_QST (Tst_MAX_OPTIONS_PER_QUESTION * (3 + 1))
|
||||||
|
|
||||||
#define TsR_SCORE_MAX 10 // Maximum score of a test (10 in Spain). Must be unsigned! // TODO: Make this configurable by teachers
|
#define TsR_SCORE_MAX 10 // Maximum score of a test (10 in Spain). Must be unsigned! // TODO: Make this configurable by teachers
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/******************************* Public types ********************************/
|
/******************************* Public types ********************************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
struct Tst_UsrAnswers
|
||||||
|
{
|
||||||
|
long QstCodes[TstCfg_MAX_QUESTIONS_PER_TEST]; // Codes of the sent/received questions in a test
|
||||||
|
char StrIndexesOneQst[TstCfg_MAX_QUESTIONS_PER_TEST]
|
||||||
|
[Tst_MAX_BYTES_INDEXES_ONE_QST + 1]; // 0 1 2 3, 3 0 2 1, etc.
|
||||||
|
char StrAnswersOneQst[TstCfg_MAX_QUESTIONS_PER_TEST]
|
||||||
|
[Tst_MAX_BYTES_ANSWERS_ONE_QST + 1]; // Answers selected by user
|
||||||
|
};
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/***************************** Public prototypes *****************************/
|
/***************************** Public prototypes *****************************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@ -52,9 +65,13 @@ void TsR_StoreScoreOfTestResultInDB (long TstCod,
|
||||||
void TsR_GetUsrsAndShowTstResults (void);
|
void TsR_GetUsrsAndShowTstResults (void);
|
||||||
void TsR_ShowOneTstResult (void);
|
void TsR_ShowOneTstResult (void);
|
||||||
void TsR_ShowTestResult (struct UsrData *UsrDat,
|
void TsR_ShowTestResult (struct UsrData *UsrDat,
|
||||||
unsigned NumQsts,time_t TstTimeUTC,
|
unsigned NumQsts,
|
||||||
|
const struct Tst_UsrAnswers *UsrAnswers,
|
||||||
|
time_t TstTimeUTC,
|
||||||
unsigned Visibility);
|
unsigned Visibility);
|
||||||
void TsR_StoreOneTestResultQstInDB (long TstCod,long QstCod,unsigned NumQst,double Score);
|
void TsR_StoreOneTestResultQstInDB (long TstCod,
|
||||||
|
const struct Tst_UsrAnswers *UsrAnswers,
|
||||||
|
unsigned NumQst,double Score);
|
||||||
void TsR_RemoveTestResultsMadeByUsrInAllCrss (long UsrCod);
|
void TsR_RemoveTestResultsMadeByUsrInAllCrss (long UsrCod);
|
||||||
void TsR_RemoveTestResultsMadeByUsrInCrs (long UsrCod,long CrsCod);
|
void TsR_RemoveTestResultsMadeByUsrInCrs (long UsrCod,long CrsCod);
|
||||||
void TsR_RemoveCrsTestResults (long CrsCod);
|
void TsR_RemoveCrsTestResults (long CrsCod);
|
||||||
|
|
Loading…
Reference in New Issue