Version19.152.3

This commit is contained in:
acanas 2020-03-23 21:40:17 +01:00
parent da9be54965
commit 71010415e1
8 changed files with 205 additions and 194 deletions

View File

@ -497,7 +497,7 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - *
En OpenSWAD:
ps2pdf source.ps destination.pdf
*/
#define Log_PLATFORM_VERSION "SWAD 19.152.1 (2020-03-23)"
#define Log_PLATFORM_VERSION "SWAD 19.152.3 (2020-03-23)"
#define CSS_FILE "swad19.146.css"
#define JS_FILE "swad19.91.1.js"
/*
@ -524,6 +524,8 @@ Param
// 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
Version 19.152.3: Mar 23, 2020 Code refactoring in tests. (283512 lines)
Version 19.152.2: Mar 23, 2020 Code refactoring in tests. (283513 lines)
Version 19.152.1: Mar 23, 2020 Code refactoring in tests. (283499 lines)
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)

View File

@ -222,7 +222,7 @@ static void Mch_GetNumPlayers (struct Match *Match);
static void Mch_RemoveMyAnswerToMatchQuestion (const struct Match *Match);
static double Mch_ComputeScore (const struct Tst_UsrAnswers *UsrAnswers);
static void Mch_ComputeScore (struct TsR_Result *Result);
static unsigned Mch_GetNumUsrsWhoHaveAnswerMch (long MchCod);
@ -3672,8 +3672,7 @@ void Mch_ReceiveQuestionAnswer (void)
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION];
struct Mch_UsrAnswer PreviousUsrAnswer;
struct Mch_UsrAnswer UsrAnswer;
struct Tst_UsrAnswers UsrAnswers;
double TotalScore;
struct TsR_Result Result;
/***** Get data of the match from database *****/
Match.MchCod = Gbl.Games.MchCodBeingPlayed;
@ -3729,8 +3728,8 @@ void Mch_ReceiveQuestionAnswer (void)
/***** Update student's match result *****/
McR_GetMatchResultQuestionsFromDB (Match.MchCod,Gbl.Usrs.Me.UsrDat.UsrCod,
&UsrAnswers);
TotalScore = Mch_ComputeScore (&UsrAnswers);
&Result);
Mch_ComputeScore (&Result);
Str_SetDecimalPointToUS (); // To print the floating point as a dot
if (DB_QueryCOUNT ("can not get if match result exists",
@ -3745,9 +3744,9 @@ void Mch_ReceiveQuestionAnswer (void)
"NumQstsNotBlank=%u,"
"Score='%.15lg'"
" WHERE MchCod=%ld AND UsrCod=%ld",
UsrAnswers.NumQsts,
UsrAnswers.NumQstsNotBlank,
TotalScore,
Result.NumQsts,
Result.NumQstsNotBlank,
Result.Score,
Match.MchCod,Gbl.Usrs.Me.UsrDat.UsrCod);
else // Result doesn't exist
/* Create result */
@ -3763,9 +3762,9 @@ void Mch_ReceiveQuestionAnswer (void)
"%u," // NumQstsNotBlank
"'%.15lg')", // Score
Match.MchCod,Gbl.Usrs.Me.UsrDat.UsrCod,
UsrAnswers.NumQsts,
UsrAnswers.NumQstsNotBlank,
TotalScore);
Result.NumQsts,
Result.NumQstsNotBlank,
Result.Score);
Str_SetDecimalPointToLocal (); // Return to local system
}
@ -3791,7 +3790,7 @@ static void Mch_RemoveMyAnswerToMatchQuestion (const struct Match *Match)
/******************** Compute match score for a student **********************/
/*****************************************************************************/
static double Mch_ComputeScore (const struct Tst_UsrAnswers *UsrAnswers)
static void Mch_ComputeScore (struct TsR_Result *Result)
{
unsigned NumQst;
struct Tst_Question Question;
@ -3799,37 +3798,35 @@ static double Mch_ComputeScore (const struct Tst_UsrAnswers *UsrAnswers)
bool AnswerIsNotBlank;
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION]; // Indexes of all answers of this question
bool AnswersUsr[Tst_MAX_OPTIONS_PER_QUESTION];
double TotalScore = 0.0;
/***** Create test question *****/
Tst_QstConstructor (&Question);
Question.Answer.Type = Tst_ANS_UNIQUE_CHOICE;
Result->Score = 0.0;
for (NumQst = 0;
NumQst < UsrAnswers->NumQsts;
NumQst < Result->NumQsts;
NumQst++)
{
/***** Get indexes for this question from string *****/
Tst_GetIndexesFromStr (UsrAnswers->StrIndexesOneQst[NumQst],Indexes);
Tst_GetIndexesFromStr (Result->StrIndexes[NumQst],Indexes);
/***** Get the user's answers for this question from string *****/
Tst_GetAnswersFromStr (UsrAnswers->StrAnswersOneQst[NumQst],AnswersUsr);
Tst_GetAnswersFromStr (Result->StrAnswers[NumQst],AnswersUsr);
/***** Get correct answers of test question from database *****/
Tst_GetCorrectAnswersFromDB (UsrAnswers->QstCodes[NumQst],&Question);
Tst_GetCorrectAnswersFromDB (Result->QstCodes[NumQst],&Question);
/***** Compute the total score of this question *****/
Tst_ComputeScoreQst (&Question,
Indexes,AnswersUsr,&ScoreThisQst,&AnswerIsNotBlank);
/***** Compute total score *****/
TotalScore += ScoreThisQst;
/***** Update total score *****/
Result->Score += ScoreThisQst;
}
/***** Destroy test question *****/
Tst_QstDestructor (&Question);
return TotalScore;
}
/*****************************************************************************/

View File

@ -96,8 +96,7 @@ static void McR_ShowMchResultsSummaryRow (unsigned NumResults,
double TotalGrade);
static void McR_GetMatchResultDataByMchCod (long MchCod,long UsrCod,
time_t TimeUTC[Dat_NUM_START_END_TIME],
struct Tst_UsrAnswers *UsrAnswers,
double *Score);
struct TsR_Result *Result);
static bool McR_CheckIfICanSeeMatchResult (struct Match *Match,long UsrCod);
static bool McR_CheckIfICanViewScore (bool ICanViewResult,unsigned Visibility);
@ -1004,8 +1003,7 @@ void McR_ShowOneMchResult (void)
time_t TimeUTC[Dat_NUM_START_END_TIME]; // Match result UTC date-time
Dat_StartEndTime_t StartEndTime;
char *Id;
struct Tst_UsrAnswers UsrAnswers;
double TotalScore;
struct TsR_Result Result;
bool ShowPhoto;
char PhotoURL[PATH_MAX + 1];
bool ICanViewResult;
@ -1032,8 +1030,7 @@ void McR_ShowOneMchResult (void)
/***** Get match result data *****/
McR_GetMatchResultDataByMchCod (Match.MchCod,UsrDat->UsrCod,
TimeUTC,
&UsrAnswers,
&TotalScore);
&Result);
/***** Check if I can view this match result *****/
switch (Gbl.Usrs.Me.Role.Logged)
@ -1064,7 +1061,7 @@ void McR_ShowOneMchResult (void)
{
/***** Get questions and user's answers of the match result from database *****/
McR_GetMatchResultQuestionsFromDB (Match.MchCod,UsrDat->UsrCod,
&UsrAnswers);
&Result);
/***** Begin box *****/
Box_BoxBegin (NULL,Match.Title,NULL,
@ -1139,8 +1136,8 @@ void McR_ShowOneMchResult (void)
HTM_TD_Begin ("class=\"DAT LT\"");
HTM_TxtF ("%u (%u %s)",
UsrAnswers.NumQsts,
UsrAnswers.NumQstsNotBlank,Txt_non_blank_QUESTIONS);
Result.NumQsts,
Result.NumQstsNotBlank,Txt_non_blank_QUESTIONS);
HTM_TD_End ();
HTM_TR_End ();
@ -1154,7 +1151,7 @@ void McR_ShowOneMchResult (void)
HTM_TD_Begin ("class=\"DAT LT\"");
if (ICanViewScore)
HTM_Double2Decimals (TotalScore);
HTM_Double2Decimals (Result.Score);
else
Ico_PutIconNotVisible ();
HTM_TD_End ();
@ -1170,7 +1167,9 @@ void McR_ShowOneMchResult (void)
HTM_TD_Begin ("class=\"DAT LT\"");
if (ICanViewScore)
Tst_ComputeAndShowGrade (UsrAnswers.NumQsts,TotalScore,Game.MaxGrade);
Tst_ComputeAndShowGrade (Result.NumQsts,
Result.Score,
Game.MaxGrade);
else
Ico_PutIconNotVisible ();
HTM_TD_End ();
@ -1191,7 +1190,7 @@ void McR_ShowOneMchResult (void)
HTM_TR_End ();
/***** Write answers and solutions *****/
TsR_ShowTestResult (UsrDat,&UsrAnswers,TimeUTC[Dat_START_TIME],
TsR_ShowTestResult (UsrDat,&Result,TimeUTC[Dat_START_TIME],
Game.Visibility);
/***** End table *****/
@ -1202,10 +1201,10 @@ void McR_ShowOneMchResult (void)
{
HTM_DIV_Begin ("class=\"DAT_N_BOLD CM\"");
HTM_TxtColonNBSP (Txt_Score);
HTM_Double2Decimals (TotalScore);
HTM_Double2Decimals (Result.Score);
HTM_BR ();
HTM_TxtColonNBSP (Txt_Grade);
Tst_ComputeAndShowGrade (UsrAnswers.NumQsts,TotalScore,Game.MaxGrade);
Tst_ComputeAndShowGrade (Result.NumQsts,Result.Score,Game.MaxGrade);
HTM_DIV_End ();
}
@ -1221,7 +1220,7 @@ void McR_ShowOneMchResult (void)
/*****************************************************************************/
void McR_GetMatchResultQuestionsFromDB (long MchCod,long UsrCod,
struct Tst_UsrAnswers *UsrAnswers)
struct TsR_Result *Result)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
@ -1231,27 +1230,27 @@ void McR_GetMatchResultQuestionsFromDB (long MchCod,long UsrCod,
struct Mch_UsrAnswer UsrAnswer;
/***** Get questions and answers of a match result *****/
UsrAnswers->NumQsts = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get questions and answers"
" of a match result",
"SELECT gam_questions.QstCod," // row[0]
"gam_questions.QstInd," // row[1]
"mch_indexes.Indexes" // row[2]
" FROM mch_matches,gam_questions,mch_indexes"
" WHERE mch_matches.MchCod=%ld"
" AND mch_matches.GamCod=gam_questions.GamCod"
" AND mch_matches.MchCod=mch_indexes.MchCod"
" AND gam_questions.QstInd=mch_indexes.QstInd"
" ORDER BY gam_questions.QstInd",
MchCod);
for (NumQst = 0, UsrAnswers->NumQstsNotBlank = 0;
NumQst < UsrAnswers->NumQsts;
Result->NumQsts = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get questions and answers"
" of a match result",
"SELECT gam_questions.QstCod," // row[0]
"gam_questions.QstInd," // row[1]
"mch_indexes.Indexes" // row[2]
" FROM mch_matches,gam_questions,mch_indexes"
" WHERE mch_matches.MchCod=%ld"
" AND mch_matches.GamCod=gam_questions.GamCod"
" AND mch_matches.MchCod=mch_indexes.MchCod"
" AND gam_questions.QstInd=mch_indexes.QstInd"
" ORDER BY gam_questions.QstInd",
MchCod);
for (NumQst = 0, Result->NumQstsNotBlank = 0;
NumQst < Result->NumQsts;
NumQst++)
{
row = mysql_fetch_row (mysql_res);
/* Get question code (row[0]) */
if ((UsrAnswers->QstCodes[NumQst] = Str_ConvertStrCodToLongCod (row[0])) < 0)
if ((Result->QstCodes[NumQst] = Str_ConvertStrCodToLongCod (row[0])) < 0)
Lay_ShowErrorAndExit ("Wrong code of question.");
/* Get question index (row[1]) */
@ -1260,24 +1259,24 @@ void McR_GetMatchResultQuestionsFromDB (long MchCod,long UsrCod,
QstInd = (unsigned) LongNum;
/* Get indexes for this question (row[2]) */
Str_Copy (UsrAnswers->StrIndexesOneQst[NumQst],row[2],
Str_Copy (Result->StrIndexes[NumQst],row[2],
Tst_MAX_BYTES_INDEXES_ONE_QST);
/* Get answers selected by user for this question */
Mch_GetQstAnsFromDB (MchCod,UsrCod,QstInd,&UsrAnswer);
if (UsrAnswer.AnsInd >= 0) // UsrAnswer.AnsInd >= 0 ==> answer selected
{
snprintf (UsrAnswers->StrAnswersOneQst[NumQst],Tst_MAX_BYTES_ANSWERS_ONE_QST + 1,
snprintf (Result->StrAnswers[NumQst],Tst_MAX_BYTES_ANSWERS_ONE_QST + 1,
"%d",UsrAnswer.AnsInd);
UsrAnswers->NumQstsNotBlank++;
Result->NumQstsNotBlank++;
}
else // UsrAnswer.AnsInd < 0 ==> no answer selected
UsrAnswers->StrAnswersOneQst[NumQst][0] = '\0'; // Empty answer
Result->StrAnswers[NumQst][0] = '\0'; // Empty answer
/* Replace each comma by a separator of multiple parameters */
/* In database commas are used as separators instead of special chars */
Par_ReplaceCommaBySeparatorMultiple (UsrAnswers->StrIndexesOneQst[NumQst]);
Par_ReplaceCommaBySeparatorMultiple (UsrAnswers->StrAnswersOneQst[NumQst]);
Par_ReplaceCommaBySeparatorMultiple (Result->StrIndexes[NumQst]);
Par_ReplaceCommaBySeparatorMultiple (Result->StrAnswers[NumQst]);
}
/***** Free structure that stores the query result *****/
@ -1290,8 +1289,7 @@ void McR_GetMatchResultQuestionsFromDB (long MchCod,long UsrCod,
static void McR_GetMatchResultDataByMchCod (long MchCod,long UsrCod,
time_t TimeUTC[Dat_NUM_START_END_TIME],
struct Tst_UsrAnswers *UsrAnswers,
double *Score)
struct TsR_Result *Result)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
@ -1323,19 +1321,25 @@ static void McR_GetMatchResultDataByMchCod (long MchCod,long UsrCod,
TimeUTC[StartEndTime] = Dat_GetUNIXTimeFromStr (row[StartEndTime]);
/* Get number of questions (row[2]) */
if (sscanf (row[2],"%u",&UsrAnswers->NumQsts) != 1)
UsrAnswers->NumQsts = 0;
if (sscanf (row[2],"%u",&Result->NumQsts) != 1)
Result->NumQsts = 0;
/* Get number of questions not blank (row[3]) */
if (sscanf (row[3],"%u",&UsrAnswers->NumQstsNotBlank) != 1)
UsrAnswers->NumQstsNotBlank = 0;
if (sscanf (row[3],"%u",&Result->NumQstsNotBlank) != 1)
Result->NumQstsNotBlank = 0;
/* Get score (row[4]) */
Str_SetDecimalPointToUS (); // To get the decimal point as a dot
if (sscanf (row[4],"%lf",Score) != 1)
*Score = 0.0;
if (sscanf (row[4],"%lf",&Result->Score) != 1)
Result->Score = 0.0;
Str_SetDecimalPointToLocal (); // Return to local system
}
else
{
Result->NumQsts = 0;
Result->NumQstsNotBlank = 0;
Result->Score = 0.0;
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);

View File

@ -50,6 +50,6 @@ void McR_ShowAllMchResultsInMch (void);
void McR_ShowOneMchResult (void);
void McR_GetMatchResultQuestionsFromDB (long MchCod,long UsrCod,
struct Tst_UsrAnswers *UsrAnswers);
struct TsR_Result *Result);
#endif

View File

@ -131,7 +131,7 @@ static void Tst_ResetAnswerTypes (struct Tst_AnswerTypes *AnswerTypes);
static void Tst_ShowFormRequestTest (const struct Tst_Tags *Tags,
const struct Tst_AnswerTypes *AnswerTypes);
static void Tst_GetQuestionsAndAnswersFromForm (struct Tst_UsrAnswers *UsrAnswers);
static void Tst_GetQuestionsAndAnswersFromForm (struct TsR_Result *Result);
static bool Tst_CheckIfNextTstAllowed (void);
static void Tst_SetTstStatus (unsigned NumTst,Tst_Status_t TstStatus);
static Tst_Status_t Tst_GetTstStatus (unsigned NumTst);
@ -140,8 +140,7 @@ static void Tst_ShowTestQuestionsWhenSeeing (unsigned NumQsts,
MYSQL_RES *mysql_res);
static void Tst_ShowOneTestQuestionWhenSeeing (unsigned NumQst,long QstCod);
static void Tst_ShowTestResultAfterAssess (long TstCod,
struct Tst_UsrAnswers *UsrAnswers,
double *TotalScore);
struct TsR_Result *Result);
static void Tst_WriteQstAndAnsTestToAnswer (unsigned NumQst,
long QstCod,
MYSQL_ROW row);
@ -214,7 +213,7 @@ static void Tst_GetParamGblAnswerTypes (struct Tst_AnswerTypes *AnswerTypesDst);
static void Tst_WriteAnswersTestToAnswer (unsigned NumQst,long QstCod,
Tst_AnswerType_t AnswerType,bool Shuffle);
static void Tst_WriteAnswersTestResult (struct UsrData *UsrDat,
const struct Tst_UsrAnswers *UsrAnswers,
const struct TsR_Result *Result,
unsigned NumQst,long QstCod,
Tst_AnswerType_t AnswerType,
unsigned Visibility,
@ -222,7 +221,7 @@ static void Tst_WriteAnswersTestResult (struct UsrData *UsrDat,
static void Tst_WriteTFAnsViewTest (unsigned NumQst);
static void Tst_WriteTFAnsAssessTest (struct UsrData *UsrDat,
const struct Tst_UsrAnswers *UsrAnswers,
const struct TsR_Result *Result,
unsigned NumQst,
const struct Tst_Question *Question,
MYSQL_RES *mysql_res,
@ -234,7 +233,7 @@ static void Tst_WriteChoiceAnsViewTest (unsigned NumQst,long QstCod,
Tst_AnswerType_t AnswerType,
bool Shuffle);
static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat,
const struct Tst_UsrAnswers *UsrAnswers,
const struct TsR_Result *Result,
unsigned NumQst,
struct Tst_Question *Question,
MYSQL_RES *mysql_res,
@ -245,7 +244,7 @@ static void Tst_GetChoiceAns (MYSQL_RES *mysql_res,struct Tst_Question *Question
static void Tst_WriteTextAnsViewTest (unsigned NumQst);
static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat,
const struct Tst_UsrAnswers *UsrAnswers,
const struct TsR_Result *Result,
unsigned NumQst,
struct Tst_Question *Question,
MYSQL_RES *mysql_res,
@ -255,7 +254,7 @@ static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat,
static void Tst_WriteIntAnsViewTest (unsigned NumQst);
static void Tst_WriteIntAnsAssessTest (struct UsrData *UsrDat,
const struct Tst_UsrAnswers *UsrAnswers,
const struct TsR_Result *Result,
unsigned NumQst,
const struct Tst_Question *Question,
MYSQL_RES *mysql_res,
@ -265,7 +264,7 @@ static void Tst_WriteIntAnsAssessTest (struct UsrData *UsrDat,
static void Tst_WriteFloatAnsViewTest (unsigned NumQst);
static void Tst_WriteFloatAnsAssessTest (struct UsrData *UsrDat,
const struct Tst_UsrAnswers *UsrAnswers,
const struct TsR_Result *Result,
unsigned NumQst,
const struct Tst_Question *Question,
MYSQL_RES *mysql_res,
@ -586,8 +585,7 @@ void Tst_AssessTest (void)
unsigned NumTst;
bool AllowTeachers; // Can teachers of this course see the test result?
long TstCod = -1L; // Initialized to avoid warning
struct Tst_UsrAnswers UsrAnswers;
double TotalScore;
struct TsR_Result Result;
/***** Read test configuration from database *****/
TstCfg_GetConfigFromDB ();
@ -601,16 +599,16 @@ void Tst_AssessTest (void)
case Tst_STATUS_SHOWN_BUT_NOT_ASSESSED:
/***** Get the parameters of the form *****/
/* Get number of questions */
UsrAnswers.NumQsts = Tst_GetParamNumQsts ();
Result.NumQsts = Tst_GetParamNumQsts ();
/***** Get if test will be visible by teachers *****/
AllowTeachers = Par_GetParToBool ("AllowTchs");
/***** Get questions and answers from form to assess a test *****/
Tst_GetQuestionsAndAnswersFromForm (&UsrAnswers);
Tst_GetQuestionsAndAnswersFromForm (&Result);
/***** Create new test in database to store the result *****/
TstCod = TsR_CreateTestResultInDB (AllowTeachers,UsrAnswers.NumQsts);
TstCod = TsR_CreateTestResultInDB (AllowTeachers,Result.NumQsts);
/***** Begin box *****/
Box_BoxBegin (NULL,Txt_Test_result,NULL,
@ -630,7 +628,7 @@ void Tst_AssessTest (void)
/***** Write answers and solutions *****/
HTM_TABLE_BeginWideMarginPadding (10);
Tst_ShowTestResultAfterAssess (TstCod,&UsrAnswers,&TotalScore);
Tst_ShowTestResultAfterAssess (TstCod,&Result);
HTM_TABLE_End ();
/***** Write total score and grade *****/
@ -638,10 +636,12 @@ void Tst_AssessTest (void)
{
HTM_DIV_Begin ("class=\"DAT_N_BOLD CM\"");
HTM_TxtColonNBSP (Txt_Score);
HTM_Double2Decimals (TotalScore);
HTM_Double2Decimals (Result.Score);
HTM_BR ();
HTM_TxtColonNBSP (Txt_Grade);
Tst_ComputeAndShowGrade (UsrAnswers.NumQsts,TotalScore,TsR_SCORE_MAX);
Tst_ComputeAndShowGrade (Result.NumQsts,
Result.Score,
TsR_SCORE_MAX);
HTM_DIV_End ();
}
@ -649,8 +649,7 @@ void Tst_AssessTest (void)
Box_BoxEnd ();
/***** Store test result in database *****/
TsR_StoreScoreOfTestResultInDB (TstCod,
&UsrAnswers,TotalScore);
TsR_StoreScoreOfTestResultInDB (TstCod,&Result);
/***** Set test status *****/
Tst_SetTstStatus (NumTst,Tst_STATUS_ASSESSED);
@ -670,35 +669,35 @@ void Tst_AssessTest (void)
/*********** Get questions and answers from form to assess a test ************/
/*****************************************************************************/
static void Tst_GetQuestionsAndAnswersFromForm (struct Tst_UsrAnswers *UsrAnswers)
static void Tst_GetQuestionsAndAnswersFromForm (struct TsR_Result *Result)
{
unsigned NumQst;
char StrQstIndOrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Qstxx...x", "Indxx...x" or "Ansxx...x"
/***** Get questions and answers *****/
for (NumQst = 0;
NumQst < UsrAnswers->NumQsts;
NumQst < Result->NumQsts;
NumQst++)
{
/* Get question code */
snprintf (StrQstIndOrAns,sizeof (StrQstIndOrAns),
"Qst%03u",
NumQst);
if ((UsrAnswers->QstCodes[NumQst] = Par_GetParToLong (StrQstIndOrAns)) <= 0)
if ((Result->QstCodes[NumQst] = Par_GetParToLong (StrQstIndOrAns)) <= 0)
Lay_ShowErrorAndExit ("Code of question is missing.");
/* Get indexes for this question */
snprintf (StrQstIndOrAns,sizeof (StrQstIndOrAns),
"Ind%03u",
NumQst);
Par_GetParMultiToText (StrQstIndOrAns,UsrAnswers->StrIndexesOneQst[NumQst],
Par_GetParMultiToText (StrQstIndOrAns,Result->StrIndexes[NumQst],
Tst_MAX_BYTES_INDEXES_ONE_QST); /* If choice ==> "0", "1", "2",... */
/* Get answers selected by user for this question */
snprintf (StrQstIndOrAns,sizeof (StrQstIndOrAns),
"Ans%03u",
NumQst);
Par_GetParMultiToText (StrQstIndOrAns,UsrAnswers->StrAnswersOneQst[NumQst],
Par_GetParMultiToText (StrQstIndOrAns,Result->StrAnswers[NumQst],
Tst_MAX_BYTES_ANSWERS_ONE_QST); /* If answer type == T/F ==> " ", "T", "F"; if choice ==> "0", "2",... */
}
}
@ -992,8 +991,7 @@ void Tst_ShowTagList (unsigned NumTags,MYSQL_RES *mysql_res)
/*****************************************************************************/
static void Tst_ShowTestResultAfterAssess (long TstCod,
struct Tst_UsrAnswers *UsrAnswers,
double *TotalScore)
struct TsR_Result *Result)
{
extern const char *Txt_Question_removed;
MYSQL_RES *mysql_res;
@ -1003,40 +1001,40 @@ static void Tst_ShowTestResultAfterAssess (long TstCod,
bool AnswerIsNotBlank;
/***** Initialize score and number of questions not blank *****/
*TotalScore = 0.0;
UsrAnswers->NumQstsNotBlank = 0;
Result->NumQstsNotBlank = 0;
Result->Score = 0.0;
for (NumQst = 0;
NumQst < UsrAnswers->NumQsts;
NumQst < Result->NumQsts;
NumQst++)
{
Gbl.RowEvenOdd = NumQst % 2;
/***** Query database *****/
if (Tst_GetOneQuestionByCod (UsrAnswers->QstCodes[NumQst],&mysql_res)) // Question exists
if (Tst_GetOneQuestionByCod (Result->QstCodes[NumQst],&mysql_res)) // Question exists
{
/***** Write question and answers *****/
row = mysql_fetch_row (mysql_res);
Tst_WriteQstAndAnsTestResult (&Gbl.Usrs.Me.UsrDat,
UsrAnswers,
Result,
NumQst,
row,
TstCfg_GetConfigVisibility (),
&ScoreThisQst,&AnswerIsNotBlank);
/***** Store test result question in database *****/
TsR_StoreOneTestResultQstInDB (TstCod,UsrAnswers,
TsR_StoreOneTestResultQstInDB (TstCod,Result,
NumQst, // 0, 1, 2, 3...
ScoreThisQst);
/***** Compute total score *****/
*TotalScore += ScoreThisQst;
Result->Score += ScoreThisQst;
if (AnswerIsNotBlank)
UsrAnswers->NumQstsNotBlank++;
Result->NumQstsNotBlank++;
/***** Update the number of accesses and the score of this question *****/
if (Gbl.Usrs.Me.Role.Logged == Rol_STD)
Tst_UpdateScoreQst (UsrAnswers->QstCodes[NumQst],ScoreThisQst,AnswerIsNotBlank);
Tst_UpdateScoreQst (Result->QstCodes[NumQst],ScoreThisQst,AnswerIsNotBlank);
}
else
{
@ -1123,7 +1121,7 @@ static void Tst_WriteQstAndAnsTestToAnswer (unsigned NumQst,
/*****************************************************************************/
void Tst_WriteQstAndAnsTestResult (struct UsrData *UsrDat,
const struct Tst_UsrAnswers *UsrAnswers,
const struct TsR_Result *Result,
unsigned NumQst,
MYSQL_ROW row,
unsigned Visibility,
@ -1173,8 +1171,8 @@ void Tst_WriteQstAndAnsTestResult (struct UsrData *UsrDat,
}
/* Answers */
Tst_WriteAnswersTestResult (UsrDat,UsrAnswers,
NumQst,UsrAnswers->QstCodes[NumQst],Question.Answer.Type,
Tst_WriteAnswersTestResult (UsrDat,Result,
NumQst,Result->QstCodes[NumQst],Question.Answer.Type,
Visibility,
ScoreThisQst,AnswerIsNotBlank);
@ -3618,7 +3616,7 @@ static void Tst_WriteAnswersTestToAnswer (unsigned NumQst,long QstCod,
/*****************************************************************************/
static void Tst_WriteAnswersTestResult (struct UsrData *UsrDat,
const struct Tst_UsrAnswers *UsrAnswers,
const struct TsR_Result *Result,
unsigned NumQst,long QstCod,
Tst_AnswerType_t AnswerType,
unsigned Visibility,
@ -3645,32 +3643,32 @@ static void Tst_WriteAnswersTestResult (struct UsrData *UsrDat,
switch (Question.Answer.Type)
{
case Tst_ANS_INT:
Tst_WriteIntAnsAssessTest (UsrDat,UsrAnswers,
Tst_WriteIntAnsAssessTest (UsrDat,Result,
NumQst,&Question,mysql_res,
Visibility,
ScoreThisQst,AnswerIsNotBlank);
break;
case Tst_ANS_FLOAT:
Tst_WriteFloatAnsAssessTest (UsrDat,UsrAnswers,
Tst_WriteFloatAnsAssessTest (UsrDat,Result,
NumQst,&Question,mysql_res,
Visibility,
ScoreThisQst,AnswerIsNotBlank);
break;
case Tst_ANS_TRUE_FALSE:
Tst_WriteTFAnsAssessTest (UsrDat,UsrAnswers,
Tst_WriteTFAnsAssessTest (UsrDat,Result,
NumQst,&Question,mysql_res,
Visibility,
ScoreThisQst,AnswerIsNotBlank);
break;
case Tst_ANS_UNIQUE_CHOICE:
case Tst_ANS_MULTIPLE_CHOICE:
Tst_WriteChoiceAnsAssessTest (UsrDat,UsrAnswers,
Tst_WriteChoiceAnsAssessTest (UsrDat,Result,
NumQst,&Question,mysql_res,
Visibility,
ScoreThisQst,AnswerIsNotBlank);
break;
case Tst_ANS_TEXT:
Tst_WriteTextAnsAssessTest (UsrDat,UsrAnswers,
Tst_WriteTextAnsAssessTest (UsrDat,Result,
NumQst,&Question,mysql_res,
Visibility,
ScoreThisQst,AnswerIsNotBlank);
@ -3744,7 +3742,7 @@ void Tst_WriteAnsTF (char AnsTF)
/*****************************************************************************/
static void Tst_WriteTFAnsAssessTest (struct UsrData *UsrDat,
const struct Tst_UsrAnswers *UsrAnswers,
const struct TsR_Result *Result,
unsigned NumQst,
const struct Tst_Question *Question,
MYSQL_RES *mysql_res,
@ -3768,7 +3766,7 @@ static void Tst_WriteTFAnsAssessTest (struct UsrData *UsrDat,
row = mysql_fetch_row (mysql_res);
/***** Compute the mark for this question *****/
AnsTF = UsrAnswers->StrAnswersOneQst[NumQst][0];
AnsTF = Result->StrAnswers[NumQst][0];
if (AnsTF == '\0') // User has omitted the answer (the answer is blank)
{
*AnswerIsNotBlank = false;
@ -3966,7 +3964,7 @@ static void Tst_WriteChoiceAnsViewTest (unsigned NumQst,long QstCod,
/*****************************************************************************/
static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat,
const struct Tst_UsrAnswers *UsrAnswers,
const struct TsR_Result *Result,
unsigned NumQst,
struct Tst_Question *Question,
MYSQL_RES *mysql_res,
@ -3990,10 +3988,10 @@ static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat,
Tst_GetChoiceAns (mysql_res,Question);
/***** Get indexes for this question from string *****/
Tst_GetIndexesFromStr (UsrAnswers->StrIndexesOneQst[NumQst],Indexes);
Tst_GetIndexesFromStr (Result->StrIndexes[NumQst],Indexes);
/***** Get the user's answers for this question from string *****/
Tst_GetAnswersFromStr (UsrAnswers->StrAnswersOneQst[NumQst],AnswersUsr);
Tst_GetAnswersFromStr (Result->StrAnswers[NumQst],AnswersUsr);
/***** Compute the total score of this question *****/
Tst_ComputeScoreQst (Question,Indexes,AnswersUsr,ScoreThisQst,AnswerIsNotBlank);
@ -4465,7 +4463,7 @@ static void Tst_WriteTextAnsViewTest (unsigned NumQst)
/*****************************************************************************/
static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat,
const struct Tst_UsrAnswers *UsrAnswers,
const struct TsR_Result *Result,
unsigned NumQst,
struct Tst_Question *Question,
MYSQL_RES *mysql_res,
@ -4530,10 +4528,10 @@ static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat,
HTM_TR_Begin (NULL);
/***** Write the user answer *****/
if (UsrAnswers->StrAnswersOneQst[NumQst][0]) // If user has answered the question
if (Result->StrAnswers[NumQst][0]) // If user has answered the question
{
/* Filter the user answer */
Str_Copy (TextAnsUsr,UsrAnswers->StrAnswersOneQst[NumQst],
Str_Copy (TextAnsUsr,Result->StrAnswers[NumQst],
Tst_MAX_BYTES_ANSWERS_ONE_QST);
/* In order to compare student answer to stored answer,
@ -4563,7 +4561,7 @@ static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat,
(Correct ? "ANS_OK" :
"ANS_BAD") :
"ANS_0");
HTM_Txt (UsrAnswers->StrAnswersOneQst[NumQst]);
HTM_Txt (Result->StrAnswers[NumQst]);
}
else // If user has omitted the answer
HTM_TD_Begin (NULL);
@ -4620,7 +4618,7 @@ static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat,
HTM_TR_End ();
/***** Compute the mark *****/
if (!UsrAnswers->StrAnswersOneQst[NumQst][0]) // If user has omitted the answer
if (!Result->StrAnswers[NumQst][0]) // If user has omitted the answer
{
*AnswerIsNotBlank = false;
*ScoreThisQst = 0.0;
@ -4638,7 +4636,7 @@ static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat,
if (TsV_IsVisibleEachQstScore (Visibility))
{
Tst_WriteScoreStart (4);
if (!UsrAnswers->StrAnswersOneQst[NumQst][0]) // If user has omitted the answer
if (!Result->StrAnswers[NumQst][0]) // If user has omitted the answer
{
HTM_SPAN_Begin ("class=\"ANS_0\"");
HTM_Double2Decimals (0.0);
@ -4681,7 +4679,7 @@ static void Tst_WriteIntAnsViewTest (unsigned NumQst)
/*****************************************************************************/
static void Tst_WriteIntAnsAssessTest (struct UsrData *UsrDat,
const struct Tst_UsrAnswers *UsrAnswers,
const struct TsR_Result *Result,
unsigned NumQst,
const struct Tst_Question *Question,
MYSQL_RES *mysql_res,
@ -4716,9 +4714,9 @@ static void Tst_WriteIntAnsAssessTest (struct UsrData *UsrDat,
HTM_TR_Begin (NULL);
/***** Write the user answer *****/
if (UsrAnswers->StrAnswersOneQst[NumQst][0]) // If user has answered the question
if (Result->StrAnswers[NumQst][0]) // If user has answered the question
{
if (sscanf (UsrAnswers->StrAnswersOneQst[NumQst],"%ld",&IntAnswerUsr) == 1)
if (sscanf (Result->StrAnswers[NumQst],"%ld",&IntAnswerUsr) == 1)
{
HTM_TD_Begin ("class=\"%s CM\"",
TsV_IsVisibleCorrectAns (Visibility) ?
@ -4750,7 +4748,7 @@ static void Tst_WriteIntAnsAssessTest (struct UsrData *UsrDat,
HTM_TR_End ();
/***** Compute the score *****/
if (!UsrAnswers->StrAnswersOneQst[NumQst][0]) // If user has omitted the answer
if (!Result->StrAnswers[NumQst][0]) // If user has omitted the answer
{
*AnswerIsNotBlank = false;
*ScoreThisQst = 0.0;
@ -4768,7 +4766,7 @@ static void Tst_WriteIntAnsAssessTest (struct UsrData *UsrDat,
if (TsV_IsVisibleEachQstScore (Visibility))
{
Tst_WriteScoreStart (2);
if (!UsrAnswers->StrAnswersOneQst[NumQst][0]) // If user has omitted the answer
if (!Result->StrAnswers[NumQst][0]) // If user has omitted the answer
{
HTM_SPAN_Begin ("class=\"ANS_0\"");
HTM_Double2Decimals (0.0);
@ -4811,7 +4809,7 @@ static void Tst_WriteFloatAnsViewTest (unsigned NumQst)
/*****************************************************************************/
static void Tst_WriteFloatAnsAssessTest (struct UsrData *UsrDat,
const struct Tst_UsrAnswers *UsrAnswers,
const struct TsR_Result *Result,
unsigned NumQst,
const struct Tst_Question *Question,
MYSQL_RES *mysql_res,
@ -4859,10 +4857,10 @@ static void Tst_WriteFloatAnsAssessTest (struct UsrData *UsrDat,
HTM_TR_Begin (NULL);
/***** Write the user answer *****/
if (UsrAnswers->StrAnswersOneQst[NumQst][0]) // If user has answered the question
if (Result->StrAnswers[NumQst][0]) // If user has answered the question
{
FloatAnsUsr = Str_GetDoubleFromStr (UsrAnswers->StrAnswersOneQst[NumQst]);
if (UsrAnswers->StrAnswersOneQst[NumQst][0]) // It's a correct floating point number
FloatAnsUsr = Str_GetDoubleFromStr (Result->StrAnswers[NumQst]);
if (Result->StrAnswers[NumQst][0]) // It's a correct floating point number
{
HTM_TD_Begin ("class=\"%s CM\"",
TsV_IsVisibleCorrectAns (Visibility) ?
@ -4900,7 +4898,7 @@ static void Tst_WriteFloatAnsAssessTest (struct UsrData *UsrDat,
HTM_TR_End ();
/***** Compute mark *****/
if (!UsrAnswers->StrAnswersOneQst[NumQst][0]) // If user has omitted the answer
if (!Result->StrAnswers[NumQst][0]) // If user has omitted the answer
{
*AnswerIsNotBlank = false;
*ScoreThisQst = 0.0;
@ -4919,7 +4917,7 @@ static void Tst_WriteFloatAnsAssessTest (struct UsrData *UsrDat,
if (TsV_IsVisibleEachQstScore (Visibility))
{
Tst_WriteScoreStart (2);
if (!UsrAnswers->StrAnswersOneQst[NumQst][0]) // If user has omitted the answer
if (!Result->StrAnswers[NumQst][0]) // If user has omitted the answer
{
HTM_SPAN_Begin ("class=\"ANS_0\"");
HTM_Double2Decimals (0.0);

View File

@ -93,7 +93,7 @@ struct Tst_Test
struct Tst_Tags Tags;
struct Tst_AnswerTypes AnswerTypes;
Tst_QuestionsOrder_t SelectedOrder;
// struct Tst_UsrAnswers UsrAnswers;
// struct Tst_Result Result;
};
struct Tst_Question
@ -158,7 +158,7 @@ void Tst_ShowGrade (double Grade,double MaxGrade);
void Tst_ShowTagList (unsigned NumTags,MYSQL_RES *mysql_res);
void Tst_WriteQstAndAnsTestResult (struct UsrData *UsrDat,
const struct Tst_UsrAnswers *UsrAnswers,
const struct TsR_Result *Result,
unsigned NumQst,
MYSQL_ROW row,
unsigned Visibility,

View File

@ -89,9 +89,8 @@ static void TsR_ShowTstTagsPresentInATestResult (long TstCod);
static void TsR_GetTestResultDataByTstCod (long TstCod,
bool *AllowTeachers,
time_t *TstTimeUTC,
struct Tst_UsrAnswers *UsrAnswers,
double *Score);
static unsigned TsR_GetTestResultQuestionsFromDB (long TstCod,struct Tst_UsrAnswers *UsrAnswers);
struct TsR_Result *Result);
static void TsR_GetTestResultQuestionsFromDB (long TstCod,struct TsR_Result *Result);
/*****************************************************************************/
/************ Select users and dates to show their test results **************/
@ -193,15 +192,17 @@ long TsR_CreateTestResultInDB (bool AllowTeachers,unsigned NumQsts)
/*****************************************************************************/
void TsR_StoreScoreOfTestResultInDB (long TstCod,
const struct Tst_UsrAnswers *UsrAnswers,double Score)
const struct TsR_Result *Result)
{
/***** Update score in test result *****/
Str_SetDecimalPointToUS (); // To print the floating point as a dot
DB_QueryUPDATE ("can not update result of test result",
"UPDATE tst_exams"
" SET NumQstsNotBlank=%u,Score='%.15lg'"
" SET NumQstsNotBlank=%u,"
"Score='%.15lg'"
" WHERE TstCod=%ld",
UsrAnswers->NumQstsNotBlank,Score,
Result->NumQstsNotBlank,
Result->Score,
TstCod);
Str_SetDecimalPointToLocal (); // Return to local system
}
@ -445,7 +446,9 @@ static void TsR_ShowTstResults (struct UsrData *UsrDat)
/* Write grade */
HTM_TD_Begin ("class=\"%s RT COLOR%u\"",ClassDat,Gbl.RowEvenOdd);
if (ICanViewScore)
Tst_ComputeAndShowGrade (NumQstsInThisTest,ScoreInThisTest,TsR_SCORE_MAX);
Tst_ComputeAndShowGrade (NumQstsInThisTest,
ScoreInThisTest,
TsR_SCORE_MAX);
HTM_TD_End ();
/* Link to show this result */
@ -573,7 +576,9 @@ static void TsR_ShowTestResultsSummaryRow (bool ItsMe,
/***** Write score over Tst_SCORE_MAX *****/
HTM_TD_Begin ("class=\"DAT_N_LINE_TOP RM COLOR%u\"",Gbl.RowEvenOdd);
if (ICanViewTotalScore)
Tst_ComputeAndShowGrade (NumTotalQsts,TotalScoreOfAllTests,TsR_SCORE_MAX);
Tst_ComputeAndShowGrade (NumTotalQsts,
TotalScoreOfAllTests,
TsR_SCORE_MAX);
HTM_TD_End ();
/***** Last cell *****/
@ -603,8 +608,7 @@ void TsR_ShowOneTstResult (void)
long TstCod;
bool AllowTeachers = false; // Initialized to avoid warning
time_t TstTimeUTC = 0; // Test result UTC date-time, initialized to avoid warning
struct Tst_UsrAnswers UsrAnswers;
double TotalScore;
struct TsR_Result Result;
bool ShowPhoto;
char PhotoURL[PATH_MAX + 1];
bool ItsMe;
@ -619,8 +623,7 @@ void TsR_ShowOneTstResult (void)
TsR_GetTestResultDataByTstCod (TstCod,
&AllowTeachers,
&TstTimeUTC,
&UsrAnswers,
&TotalScore);
&Result);
TstCfg_SetConfigVisibility (TsV_MAX_VISIBILITY);
/***** Check if I can view this test result *****/
@ -671,7 +674,7 @@ void TsR_ShowOneTstResult (void)
if (ICanViewTest) // I am allowed to view this test result
{
/***** Get questions and user's answers of the test result from database *****/
UsrAnswers.NumQsts = TsR_GetTestResultQuestionsFromDB (TstCod,&UsrAnswers);
TsR_GetTestResultQuestionsFromDB (TstCod,&Result);
/***** Begin box *****/
Box_BoxBegin (NULL,Txt_Test_result,NULL,
@ -738,8 +741,8 @@ void TsR_ShowOneTstResult (void)
HTM_TD_Begin ("class=\"DAT LT\"");
HTM_TxtF ("%u (%u %s)",
UsrAnswers.NumQsts,
UsrAnswers.NumQstsNotBlank,Txt_non_blank_QUESTIONS);
Result.NumQsts,
Result.NumQstsNotBlank,Txt_non_blank_QUESTIONS);
HTM_TD_End ();
HTM_TR_End ();
@ -753,7 +756,7 @@ void TsR_ShowOneTstResult (void)
HTM_TD_Begin ("class=\"DAT LT\"");
if (ICanViewScore)
HTM_Double2Decimals (TotalScore);
HTM_Double2Decimals (Result.Score);
else
Ico_PutIconNotVisible ();
HTM_TD_End ();
@ -767,7 +770,9 @@ void TsR_ShowOneTstResult (void)
HTM_TD_Begin ("class=\"DAT LT\"");
if (ICanViewScore)
Tst_ComputeAndShowGrade (UsrAnswers.NumQsts,TotalScore,TsR_SCORE_MAX);
Tst_ComputeAndShowGrade (Result.NumQsts,
Result.Score,
TsR_SCORE_MAX);
else
Ico_PutIconNotVisible ();
HTM_TD_End ();
@ -789,7 +794,7 @@ void TsR_ShowOneTstResult (void)
/***** Write answers and solutions *****/
TsR_ShowTestResult (&Gbl.Usrs.Other.UsrDat,
&UsrAnswers,
&Result,
TstTimeUTC,
TstCfg_GetConfigVisibility ());
@ -801,10 +806,12 @@ void TsR_ShowOneTstResult (void)
{
HTM_DIV_Begin ("class=\"DAT_N_BOLD CM\"");
HTM_TxtColonNBSP (Txt_Score);
HTM_Double2Decimals (TotalScore);
HTM_Double2Decimals (Result.Score);
HTM_BR ();
HTM_TxtColonNBSP (Txt_Grade);
Tst_ComputeAndShowGrade (UsrAnswers.NumQsts,TotalScore,TsR_SCORE_MAX);
Tst_ComputeAndShowGrade (Result.NumQsts,
Result.Score,
TsR_SCORE_MAX);
HTM_DIV_End ();
}
@ -849,7 +856,7 @@ static void TsR_ShowTstTagsPresentInATestResult (long TstCod)
/*****************************************************************************/
void TsR_ShowTestResult (struct UsrData *UsrDat,
const struct Tst_UsrAnswers *UsrAnswers,
const struct TsR_Result *Result,
time_t TstTimeUTC,
unsigned Visibility)
{
@ -864,13 +871,13 @@ void TsR_ShowTestResult (struct UsrData *UsrDat,
time_t EditTimeUTC;
for (NumQst = 0;
NumQst < UsrAnswers->NumQsts;
NumQst < Result->NumQsts;
NumQst++)
{
Gbl.RowEvenOdd = NumQst % 2;
/***** Query database *****/
if (Tst_GetOneQuestionByCod (UsrAnswers->QstCodes[NumQst],&mysql_res)) // Question exists
if (Tst_GetOneQuestionByCod (Result->QstCodes[NumQst],&mysql_res)) // Question exists
{
/***** Get row of the result of the query *****/
row = mysql_fetch_row (mysql_res);
@ -900,7 +907,7 @@ void TsR_ShowTestResult (struct UsrData *UsrDat,
else
/***** Write questions and answers *****/
Tst_WriteQstAndAnsTestResult (UsrDat,
UsrAnswers,
Result,
NumQst,
row,
Visibility,
@ -935,8 +942,7 @@ void TsR_ShowTestResult (struct UsrData *UsrDat,
static void TsR_GetTestResultDataByTstCod (long TstCod,
bool *AllowTeachers,
time_t *TstTimeUTC,
struct Tst_UsrAnswers *UsrAnswers,
double *Score)
struct TsR_Result *Result)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
@ -967,19 +973,25 @@ static void TsR_GetTestResultDataByTstCod (long TstCod,
*TstTimeUTC = Dat_GetUNIXTimeFromStr (row[2]);
/* Get number of questions (row[3]) */
if (sscanf (row[3],"%u",&UsrAnswers->NumQsts) != 1)
UsrAnswers->NumQsts = 0;
if (sscanf (row[3],"%u",&Result->NumQsts) != 1)
Result->NumQsts = 0;
/* Get number of questions not blank (row[4]) */
if (sscanf (row[4],"%u",&UsrAnswers->NumQstsNotBlank) != 1)
UsrAnswers->NumQstsNotBlank = 0;
if (sscanf (row[4],"%u",&Result->NumQstsNotBlank) != 1)
Result->NumQstsNotBlank = 0;
/* Get score (row[5]) */
Str_SetDecimalPointToUS (); // To get the decimal point as a dot
if (sscanf (row[5],"%lf",Score) != 1)
*Score = 0.0;
if (sscanf (row[5],"%lf",&Result->Score) != 1)
Result->Score = 0.0;
Str_SetDecimalPointToLocal (); // Return to local system
}
else
{
Result->NumQsts = 0;
Result->NumQstsNotBlank = 0;
Result->Score = 0.0;
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
@ -990,16 +1002,16 @@ static void TsR_GetTestResultDataByTstCod (long TstCod,
/*****************************************************************************/
void TsR_StoreOneTestResultQstInDB (long TstCod,
const struct Tst_UsrAnswers *UsrAnswers,
unsigned NumQst,double Score)
const struct TsR_Result *Result,
unsigned NumQst,double ScoreThisQst)
{
char Indexes[Tst_MAX_BYTES_INDEXES_ONE_QST + 1];
char Answers[Tst_MAX_BYTES_ANSWERS_ONE_QST + 1];
/***** Replace each separator of multiple parameters by a comma *****/
/* In database commas are used as separators instead of special chars */
Par_ReplaceSeparatorMultipleByComma (UsrAnswers->StrIndexesOneQst[NumQst],Indexes);
Par_ReplaceSeparatorMultipleByComma (UsrAnswers->StrAnswersOneQst[NumQst],Answers);
Par_ReplaceSeparatorMultipleByComma (Result->StrIndexes[NumQst],Indexes);
Par_ReplaceSeparatorMultipleByComma (Result->StrAnswers[NumQst],Answers);
/***** Insert question and user's answers into database *****/
Str_SetDecimalPointToUS (); // To print the floating point as a dot
@ -1008,9 +1020,9 @@ void TsR_StoreOneTestResultQstInDB (long TstCod,
" (TstCod,QstCod,QstInd,Score,Indexes,Answers)"
" VALUES"
" (%ld,%ld,%u,'%.15lg','%s','%s')",
TstCod,UsrAnswers->QstCodes[NumQst],
TstCod,Result->QstCodes[NumQst],
NumQst, // 0, 1, 2, 3...
Score,
ScoreThisQst,
Indexes,
Answers);
Str_SetDecimalPointToLocal (); // Return to local system
@ -1020,15 +1032,14 @@ void TsR_StoreOneTestResultQstInDB (long TstCod,
/************ Get the questions of a test result from database ***************/
/*****************************************************************************/
static unsigned TsR_GetTestResultQuestionsFromDB (long TstCod,struct Tst_UsrAnswers *UsrAnswers)
static void TsR_GetTestResultQuestionsFromDB (long TstCod,struct TsR_Result *Result)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumQsts;
unsigned NumQst;
/***** Get questions of a test result from database *****/
NumQsts =
Result->NumQsts =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get questions"
" of a test result",
"SELECT QstCod," // row[0]
@ -1040,33 +1051,31 @@ static unsigned TsR_GetTestResultQuestionsFromDB (long TstCod,struct Tst_UsrAnsw
/***** Get questions codes *****/
for (NumQst = 0;
NumQst < NumQsts;
NumQst < Result->NumQsts;
NumQst++)
{
row = mysql_fetch_row (mysql_res);
/* Get question code */
if ((UsrAnswers->QstCodes[NumQst] = Str_ConvertStrCodToLongCod (row[0])) < 0)
if ((Result->QstCodes[NumQst] = Str_ConvertStrCodToLongCod (row[0])) < 0)
Lay_ShowErrorAndExit ("Wrong code of question.");
/* Get indexes for this question (row[1]) */
Str_Copy (UsrAnswers->StrIndexesOneQst[NumQst],row[1],
Str_Copy (Result->StrIndexes[NumQst],row[1],
Tst_MAX_BYTES_INDEXES_ONE_QST);
/* Get answers selected by user for this question (row[2]) */
Str_Copy (UsrAnswers->StrAnswersOneQst[NumQst],row[2],
Str_Copy (Result->StrAnswers[NumQst],row[2],
Tst_MAX_BYTES_ANSWERS_ONE_QST);
/* Replace each comma by a separator of multiple parameters */
/* In database commas are used as separators instead of special chars */
Par_ReplaceCommaBySeparatorMultiple (UsrAnswers->StrIndexesOneQst[NumQst]);
Par_ReplaceCommaBySeparatorMultiple (UsrAnswers->StrAnswersOneQst[NumQst]);
Par_ReplaceCommaBySeparatorMultiple (Result->StrIndexes[NumQst]);
Par_ReplaceCommaBySeparatorMultiple (Result->StrAnswers[NumQst]);
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return NumQsts;
}
/*****************************************************************************/

View File

@ -43,15 +43,16 @@
/******************************* Public types ********************************/
/*****************************************************************************/
struct Tst_UsrAnswers
struct TsR_Result
{
unsigned NumQsts;
unsigned NumQstsNotBlank;
double Score;
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
char StrIndexes[TstCfg_MAX_QUESTIONS_PER_TEST]
[Tst_MAX_BYTES_INDEXES_ONE_QST + 1]; // 0 1 2 3, 3 0 2 1, etc.
char StrAnswers[TstCfg_MAX_QUESTIONS_PER_TEST]
[Tst_MAX_BYTES_ANSWERS_ONE_QST + 1]; // Answers selected by user
};
/*****************************************************************************/
@ -63,16 +64,16 @@ void TsR_SelDatesToSeeMyTstResults (void);
void TsR_ShowMyTstResults (void);
long TsR_CreateTestResultInDB (bool AllowTeachers,unsigned NumQsts);
void TsR_StoreScoreOfTestResultInDB (long TstCod,
const struct Tst_UsrAnswers *UsrAnswers,double Score);
const struct TsR_Result *Result);
void TsR_GetUsrsAndShowTstResults (void);
void TsR_ShowOneTstResult (void);
void TsR_ShowTestResult (struct UsrData *UsrDat,
const struct Tst_UsrAnswers *UsrAnswers,
const struct TsR_Result *Result,
time_t TstTimeUTC,
unsigned Visibility);
void TsR_StoreOneTestResultQstInDB (long TstCod,
const struct Tst_UsrAnswers *UsrAnswers,
unsigned NumQst,double Score);
const struct TsR_Result *Result,
unsigned NumQst,double ScoreThisQst);
void TsR_RemoveTestResultsMadeByUsrInAllCrss (long UsrCod);
void TsR_RemoveTestResultsMadeByUsrInCrs (long UsrCod,long CrsCod);
void TsR_RemoveCrsTestResults (long CrsCod);