mirror of https://github.com/acanas/swad-core.git
Version 21.46.4: Oct 27, 2021 Code refactoring in test prints.
This commit is contained in:
parent
352b95589c
commit
a07872fdb6
|
@ -602,13 +602,14 @@ TODO: FIX BUG, URGENT! En las fechas como par
|
|||
|
||||
TODO: En las encuestas, que los estudiantes no puedan ver los resultados hasta que no finalice el plazo.
|
||||
*/
|
||||
#define Log_PLATFORM_VERSION "SWAD 21.46.3 (2021-10-27)"
|
||||
#define Log_PLATFORM_VERSION "SWAD 21.46.4 (2021-10-27)"
|
||||
#define CSS_FILE "swad20.45.css"
|
||||
#define JS_FILE "swad20.69.1.js"
|
||||
/*
|
||||
TODO: Rename CENTRE to CENTER in help wiki.
|
||||
TODO: Rename ASSESSMENT.Announcements to ASSESSMENT.Calls_for_exams
|
||||
|
||||
Version 21.46.4: Oct 27, 2021 Code refactoring in test prints. (? lines)
|
||||
Version 21.46.3: Oct 27, 2021 Queries moved to module swad_test_database. (321054 lines)
|
||||
Version 21.46.2: Oct 26, 2021 Queries moved to module swad_test_database. (321062 lines)
|
||||
Version 21.46.1: Oct 26, 2021 Queries moved to module swad_test_database. (321058 lines)
|
||||
|
|
161
swad_question.c
161
swad_question.c
|
@ -1590,6 +1590,167 @@ void Qst_WriteChoAnsBank (struct Qst_Question *Question,
|
|||
HTM_TABLE_End ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**************** Get correct answer for each type of answer *****************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void Qst_GetCorrectIntAnswerFromDB (struct Qst_Question *Question)
|
||||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
|
||||
/***** Query database *****/
|
||||
Question->Answer.NumOptions = (unsigned)
|
||||
DB_QuerySELECT (&mysql_res,"can not get answers of a question",
|
||||
"SELECT Answer" // row[0]
|
||||
" FROM tst_answers"
|
||||
" WHERE QstCod=%ld",
|
||||
Question->QstCod);
|
||||
|
||||
/***** Check if number of rows is correct *****/
|
||||
Qst_CheckIfNumberOfAnswersIsOne (Question);
|
||||
|
||||
/***** Get correct answer *****/
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
if (sscanf (row[0],"%ld",&Question->Answer.Integer) != 1)
|
||||
Err_WrongAnswerExit ();
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
}
|
||||
|
||||
void Qst_GetCorrectFltAnswerFromDB (struct Qst_Question *Question)
|
||||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
unsigned NumOpt;
|
||||
double Tmp;
|
||||
|
||||
/***** Query database *****/
|
||||
Question->Answer.NumOptions = (unsigned)
|
||||
DB_QuerySELECT (&mysql_res,"can not get answers of a question",
|
||||
"SELECT Answer" // row[0]
|
||||
" FROM tst_answers"
|
||||
" WHERE QstCod=%ld",
|
||||
Question->QstCod);
|
||||
|
||||
/***** Check if number of rows is correct *****/
|
||||
if (Question->Answer.NumOptions != 2)
|
||||
Err_WrongAnswerExit ();
|
||||
|
||||
/***** Get float range *****/
|
||||
for (NumOpt = 0;
|
||||
NumOpt < 2;
|
||||
NumOpt++)
|
||||
{
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
Question->Answer.FloatingPoint[NumOpt] = Str_GetDoubleFromStr (row[0]);
|
||||
}
|
||||
if (Question->Answer.FloatingPoint[0] >
|
||||
Question->Answer.FloatingPoint[1]) // The maximum and the minimum are swapped
|
||||
{
|
||||
/* Swap maximum and minimum */
|
||||
Tmp = Question->Answer.FloatingPoint[0];
|
||||
Question->Answer.FloatingPoint[0] = Question->Answer.FloatingPoint[1];
|
||||
Question->Answer.FloatingPoint[1] = Tmp;
|
||||
}
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
}
|
||||
|
||||
void Qst_GetCorrectTF_AnswerFromDB (struct Qst_Question *Question)
|
||||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
|
||||
/***** Query database *****/
|
||||
Question->Answer.NumOptions = (unsigned)
|
||||
DB_QuerySELECT (&mysql_res,"can not get answers of a question",
|
||||
"SELECT Answer" // row[0]
|
||||
" FROM tst_answers"
|
||||
" WHERE QstCod=%ld",
|
||||
Question->QstCod);
|
||||
|
||||
/***** Check if number of rows is correct *****/
|
||||
Qst_CheckIfNumberOfAnswersIsOne (Question);
|
||||
|
||||
/***** Get answer *****/
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
Question->Answer.TF = row[0][0];
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
}
|
||||
|
||||
void Qst_GetCorrectChoAnswerFromDB (struct Qst_Question *Question)
|
||||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
unsigned NumOpt;
|
||||
|
||||
/***** Query database *****/
|
||||
Question->Answer.NumOptions = (unsigned)
|
||||
DB_QuerySELECT (&mysql_res,"can not get answers of a question",
|
||||
"SELECT Correct" // row[0]
|
||||
" FROM tst_answers"
|
||||
" WHERE QstCod=%ld"
|
||||
" ORDER BY AnsInd",
|
||||
Question->QstCod);
|
||||
for (NumOpt = 0;
|
||||
NumOpt < Question->Answer.NumOptions;
|
||||
NumOpt++)
|
||||
{
|
||||
/* Get next answer */
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
|
||||
/* Assign correctness (row[0]) of this answer (this option) */
|
||||
Question->Answer.Options[NumOpt].Correct = (row[0][0] == 'Y');
|
||||
}
|
||||
|
||||
/* Free structure that stores the query result */
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
}
|
||||
|
||||
void Qst_GetCorrectTxtAnswerFromDB (struct Qst_Question *Question)
|
||||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
unsigned NumOpt;
|
||||
|
||||
/***** Query database *****/
|
||||
Question->Answer.NumOptions = (unsigned)
|
||||
DB_QuerySELECT (&mysql_res,"can not get answers of a question",
|
||||
"SELECT Answer" // row[0]
|
||||
" FROM tst_answers"
|
||||
" WHERE QstCod=%ld",
|
||||
Question->QstCod);
|
||||
|
||||
/***** Get text and correctness of answers for this question from database (one row per answer) *****/
|
||||
for (NumOpt = 0;
|
||||
NumOpt < Question->Answer.NumOptions;
|
||||
NumOpt++)
|
||||
{
|
||||
/***** Get next answer *****/
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
|
||||
/***** Allocate memory for text in this choice answer *****/
|
||||
if (!Qst_AllocateTextChoiceAnswer (Question,NumOpt))
|
||||
/* Abort on error */
|
||||
Ale_ShowAlertsAndExit ();
|
||||
|
||||
/***** Copy answer text (row[0]) ******/
|
||||
Str_Copy (Question->Answer.Options[NumOpt].Text,row[0],
|
||||
Qst_MAX_BYTES_ANSWER_OR_FEEDBACK);
|
||||
}
|
||||
|
||||
/***** Change format of answers text *****/
|
||||
Qst_ChangeFormatAnswersText (Question);
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/************** Write false / true answer when seeing a test *****************/
|
||||
/*****************************************************************************/
|
||||
|
|
|
@ -202,6 +202,13 @@ void Qst_WriteTF_AnsBank (struct Qst_Question *Question,
|
|||
void Qst_WriteChoAnsBank (struct Qst_Question *Question,
|
||||
const char *ClassTxt,
|
||||
const char *ClassFeedback);
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void Qst_GetCorrectIntAnswerFromDB (struct Qst_Question *Question);
|
||||
void Qst_GetCorrectFltAnswerFromDB (struct Qst_Question *Question);
|
||||
void Qst_GetCorrectTF_AnswerFromDB (struct Qst_Question *Question);
|
||||
void Qst_GetCorrectChoAnswerFromDB (struct Qst_Question *Question);
|
||||
void Qst_GetCorrectTxtAnswerFromDB (struct Qst_Question *Question);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -232,7 +232,7 @@ void Tst_ShowNewTest (void)
|
|||
NumPrintsGeneratedByMe = TstPrn_GetNumPrintsGeneratedByMe ();
|
||||
|
||||
/***** Create new test print in database *****/
|
||||
TstPrn_CreatePrintInDB (&Print);
|
||||
Print.PrnCod = Tst_DB_CreatePrint (Print.NumQsts.All);
|
||||
TstPrn_ComputeScoresAndStoreQuestionsOfPrint (&Print,
|
||||
false); // Don't update question score
|
||||
|
||||
|
@ -298,7 +298,7 @@ void Tst_ReceiveTestDraft (void)
|
|||
/***** Update test print in database *****/
|
||||
TstPrn_ComputeScoresAndStoreQuestionsOfPrint (&Print,
|
||||
false); // Don't update question score
|
||||
TstPrn_UpdatePrintInDB (&Print);
|
||||
Tst_DB_UpdatePrint (&Print);
|
||||
|
||||
/***** Show question and button to send the test *****/
|
||||
/* Begin alert */
|
||||
|
@ -358,7 +358,7 @@ void Tst_AssessTest (void)
|
|||
/***** Update test print in database *****/
|
||||
TstPrn_ComputeScoresAndStoreQuestionsOfPrint (&Print,
|
||||
Gbl.Usrs.Me.Role.Logged == Rol_STD); // Update question score?
|
||||
TstPrn_UpdatePrintInDB (&Print);
|
||||
Tst_DB_UpdatePrint (&Print);
|
||||
|
||||
/***** Begin box *****/
|
||||
Box_BoxBegin (NULL,Txt_Result,
|
||||
|
|
|
@ -169,6 +169,32 @@ unsigned Tst_DB_GetNumPrintsGeneratedByMe (MYSQL_RES **mysql_res)
|
|||
Gbl.Hierarchy.Crs.CrsCod);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*********************** Update the score of a question **********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void Tst_DB_UpdateQstScore (const struct TstPrn_PrintedQuestion *PrintedQuestion)
|
||||
{
|
||||
/***** Update number of clicks and score of the question *****/
|
||||
Str_SetDecimalPointToUS (); // To print the floating point as a dot
|
||||
if (PrintedQuestion->StrAnswers[0]) // User's answer is not blank
|
||||
DB_QueryUPDATE ("can not update the score of a question",
|
||||
"UPDATE tst_questions"
|
||||
" SET NumHits=NumHits+1,"
|
||||
"NumHitsNotBlank=NumHitsNotBlank+1,"
|
||||
"Score=Score+(%.15lg)"
|
||||
" WHERE QstCod=%ld",
|
||||
PrintedQuestion->Score,
|
||||
PrintedQuestion->QstCod);
|
||||
else // User's answer is blank
|
||||
DB_QueryUPDATE ("can not update the score of a question",
|
||||
"UPDATE tst_questions"
|
||||
" SET NumHits=NumHits+1"
|
||||
" WHERE QstCod=%ld",
|
||||
PrintedQuestion->QstCod);
|
||||
Str_SetDecimalPointToLocal (); // Return to local system
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/************** Get questions for a new test from the database ***************/
|
||||
/*****************************************************************************/
|
||||
|
@ -344,3 +370,53 @@ void Tst_DB_RemoveTstConfig (long CrsCod)
|
|||
" WHERE CrsCod=%ld",
|
||||
CrsCod);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**************** Create new blank test print in database ********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
long Tst_DB_CreatePrint (unsigned NumQsts)
|
||||
{
|
||||
return
|
||||
DB_QueryINSERTandReturnCode ("can not create new test print",
|
||||
"INSERT INTO tst_exams"
|
||||
" (CrsCod,UsrCod,StartTime,EndTime,"
|
||||
"NumQsts,NumQstsNotBlank,"
|
||||
"Sent,AllowTeachers,Score)"
|
||||
" VALUES"
|
||||
" (%ld,%ld,NOW(),NOW(),"
|
||||
"%u,0,"
|
||||
"'N','N',0)",
|
||||
Gbl.Hierarchy.Crs.CrsCod,
|
||||
Gbl.Usrs.Me.UsrDat.UsrCod,
|
||||
NumQsts);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*********************** Update test print in database ***********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void Tst_DB_UpdatePrint (const struct TstPrn_Print *Print)
|
||||
{
|
||||
Str_SetDecimalPointToUS (); // To print the floating point as a dot
|
||||
DB_QueryUPDATE ("can not update test",
|
||||
"UPDATE tst_exams"
|
||||
" SET EndTime=NOW(),"
|
||||
"NumQstsNotBlank=%u,"
|
||||
"Sent='%c',"
|
||||
"AllowTeachers='%c',"
|
||||
"Score='%.15lg'"
|
||||
" WHERE ExaCod=%ld"
|
||||
" AND CrsCod=%ld" // Extra check
|
||||
" AND UsrCod=%ld", // Extra check
|
||||
Print->NumQsts.NotBlank,
|
||||
Print->Sent ? 'Y' :
|
||||
'N',
|
||||
Print->AllowTeachers ? 'Y' :
|
||||
'N',
|
||||
Print->Score,
|
||||
Print->PrnCod,
|
||||
Gbl.Hierarchy.Crs.CrsCod,
|
||||
Gbl.Usrs.Me.UsrDat.UsrCod);
|
||||
Str_SetDecimalPointToLocal (); // Return to local system
|
||||
}
|
||||
|
|
|
@ -57,6 +57,8 @@ unsigned Tst_DB_GetDateNextTstAllowed (MYSQL_RES **mysql_res);
|
|||
unsigned Tst_DB_GetNumPrintsGeneratedByMe (MYSQL_RES **mysql_res);
|
||||
|
||||
//---------------------------- Test questions ---------------------------------
|
||||
void Tst_DB_UpdateQstScore (const struct TstPrn_PrintedQuestion *PrintedQuestion);
|
||||
|
||||
unsigned Tst_DB_GetQuestionsForNewTest (MYSQL_RES **mysql_res,
|
||||
const struct Qst_Questions *Questions);
|
||||
|
||||
|
@ -67,4 +69,8 @@ unsigned Tst_DB_GetPluggableFromConfig (MYSQL_RES **mysql_res);
|
|||
|
||||
void Tst_DB_RemoveTstConfig (long CrsCod);
|
||||
|
||||
//------------------------------- Test prints ---------------------------------
|
||||
long Tst_DB_CreatePrint (unsigned NumQsts);
|
||||
void Tst_DB_UpdatePrint (const struct TstPrn_Print *Print);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -116,8 +116,6 @@ static void TstPrn_WriteQstAndAnsExam (struct UsrData *UsrDat,
|
|||
bool QuestionExists,
|
||||
unsigned Visibility);
|
||||
|
||||
static void TstPrn_UpdateQstScoreInDB (struct TstPrn_PrintedQuestion *PrintedQuestion);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void TstPrn_GetCorrectAndComputeIntAnsScore (struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
struct Qst_Question *Question);
|
||||
|
@ -130,12 +128,6 @@ static void TstPrn_GetCorrectAndComputeChoAnsScore (struct TstPrn_PrintedQuestio
|
|||
static void TstPrn_GetCorrectAndComputeTxtAnsScore (struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
struct Qst_Question *Question);
|
||||
//-----------------------------------------------------------------------------
|
||||
static void TstPrn_GetCorrectIntAnswerFromDB (struct Qst_Question *Question);
|
||||
static void TstPrn_GetCorrectFltAnswerFromDB (struct Qst_Question *Question);
|
||||
static void TstPrn_GetCorrectTF_AnswerFromDB (struct Qst_Question *Question);
|
||||
static void TstPrn_GetCorrectChoAnswerFromDB (struct Qst_Question *Question);
|
||||
static void TstPrn_GetCorrectTxtAnswerFromDB (struct Qst_Question *Question);
|
||||
//-----------------------------------------------------------------------------
|
||||
static void TstPrn_WriteIntAnsPrint (struct UsrData *UsrDat,
|
||||
const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
struct Qst_Question *Question,
|
||||
|
@ -170,7 +162,7 @@ static void TstPrn_WriteTxtAnsPrint (struct UsrData *UsrDat,
|
|||
|
||||
static void TstPrn_WriteHeadUserCorrect (struct UsrData *UsrDat);
|
||||
|
||||
static void TstPrn_StoreOneQstOfPrintInDB (const struct TstPrn_Print *Print,
|
||||
static void Tst_DB_StoreOneQstOfPrint (const struct TstPrn_Print *Print,
|
||||
unsigned QstInd);
|
||||
|
||||
static void TstPrn_PutFormToSelectUsrsToViewUsrsPrints (__attribute__((unused)) void *Args);
|
||||
|
@ -210,58 +202,6 @@ static void TstPrn_ResetPrintExceptPrnCod (struct TstPrn_Print *Print)
|
|||
Print->Score = 0.0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**************** Create new blank test print in database ********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void TstPrn_CreatePrintInDB (struct TstPrn_Print *Print)
|
||||
{
|
||||
/***** Insert new test print into table *****/
|
||||
Print->PrnCod =
|
||||
DB_QueryINSERTandReturnCode ("can not create new test print",
|
||||
"INSERT INTO tst_exams"
|
||||
" (CrsCod,UsrCod,StartTime,EndTime,"
|
||||
"NumQsts,NumQstsNotBlank,"
|
||||
"Sent,AllowTeachers,Score)"
|
||||
" VALUES"
|
||||
" (%ld,%ld,NOW(),NOW(),"
|
||||
"%u,0,"
|
||||
"'N','N',0)",
|
||||
Gbl.Hierarchy.Crs.CrsCod,
|
||||
Gbl.Usrs.Me.UsrDat.UsrCod,
|
||||
Print->NumQsts.All);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*********************** Update test print in database ***********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void TstPrn_UpdatePrintInDB (const struct TstPrn_Print *Print)
|
||||
{
|
||||
/***** Update test print in database *****/
|
||||
Str_SetDecimalPointToUS (); // To print the floating point as a dot
|
||||
DB_QueryUPDATE ("can not update test",
|
||||
"UPDATE tst_exams"
|
||||
" SET EndTime=NOW(),"
|
||||
"NumQstsNotBlank=%u,"
|
||||
"Sent='%c',"
|
||||
"AllowTeachers='%c',"
|
||||
"Score='%.15lg'"
|
||||
" WHERE ExaCod=%ld"
|
||||
" AND CrsCod=%ld" // Extra check
|
||||
" AND UsrCod=%ld", // Extra check
|
||||
Print->NumQsts.NotBlank,
|
||||
Print->Sent ? 'Y' :
|
||||
'N',
|
||||
Print->AllowTeachers ? 'Y' :
|
||||
'N',
|
||||
Print->Score,
|
||||
Print->PrnCod,
|
||||
Gbl.Hierarchy.Crs.CrsCod,
|
||||
Gbl.Usrs.Me.UsrDat.UsrCod);
|
||||
Str_SetDecimalPointToLocal (); // Return to local system
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/********************* Show a test print to be answered **********************/
|
||||
/*****************************************************************************/
|
||||
|
@ -628,7 +568,7 @@ void TstPrn_ShowPrintAfterAssess (struct TstPrn_Print *Print)
|
|||
TstCfg_GetConfigVisibility ());
|
||||
|
||||
/***** Store test question in database *****/
|
||||
TstPrn_StoreOneQstOfPrintInDB (Print,QstInd);
|
||||
Tst_DB_StoreOneQstOfPrint (Print,QstInd);
|
||||
|
||||
/***** Compute total score *****/
|
||||
Print->Score += Print->PrintedQuestions[QstInd].Score;
|
||||
|
@ -637,7 +577,7 @@ void TstPrn_ShowPrintAfterAssess (struct TstPrn_Print *Print)
|
|||
|
||||
/***** Update the number of accesses and the score of this question *****/
|
||||
if (Gbl.Usrs.Me.Role.Logged == Rol_STD)
|
||||
TstPrn_UpdateQstScoreInDB (&Print->PrintedQuestions[QstInd]);
|
||||
Tst_DB_UpdateQstScore (&Print->PrintedQuestions[QstInd]);
|
||||
|
||||
/***** Destroy test question *****/
|
||||
Qst_QstDestructor (&Question);
|
||||
|
@ -811,7 +751,7 @@ void TstPrn_ComputeScoresAndStoreQuestionsOfPrint (struct TstPrn_Print *Print,
|
|||
Qst_QstDestructor (&Question);
|
||||
|
||||
/* Store test question in database */
|
||||
TstPrn_StoreOneQstOfPrintInDB (Print,
|
||||
Tst_DB_StoreOneQstOfPrint (Print,
|
||||
QstInd); // 0, 1, 2, 3...
|
||||
|
||||
/* Accumulate total score */
|
||||
|
@ -821,7 +761,7 @@ void TstPrn_ComputeScoresAndStoreQuestionsOfPrint (struct TstPrn_Print *Print,
|
|||
|
||||
/* Update the number of hits and the score of this question in tests database */
|
||||
if (UpdateQstScore)
|
||||
TstPrn_UpdateQstScoreInDB (&Print->PrintedQuestions[QstInd]);
|
||||
Tst_DB_UpdateQstScore (&Print->PrintedQuestions[QstInd]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -847,32 +787,6 @@ void TstPrn_ComputeAnswerScore (struct TstPrn_PrintedQuestion *PrintedQuestion,
|
|||
TstPrn_GetCorrectAndComputeAnsScore[Question->Answer.Type] (PrintedQuestion,Question);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*********************** Update the score of a question **********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void TstPrn_UpdateQstScoreInDB (struct TstPrn_PrintedQuestion *PrintedQuestion)
|
||||
{
|
||||
/***** Update number of clicks and score of the question *****/
|
||||
Str_SetDecimalPointToUS (); // To print the floating point as a dot
|
||||
if (PrintedQuestion->StrAnswers[0]) // User's answer is not blank
|
||||
DB_QueryUPDATE ("can not update the score of a question",
|
||||
"UPDATE tst_questions"
|
||||
" SET NumHits=NumHits+1,"
|
||||
"NumHitsNotBlank=NumHitsNotBlank+1,"
|
||||
"Score=Score+(%.15lg)"
|
||||
" WHERE QstCod=%ld",
|
||||
PrintedQuestion->Score,
|
||||
PrintedQuestion->QstCod);
|
||||
else // User's answer is blank
|
||||
DB_QueryUPDATE ("can not update the score of a question",
|
||||
"UPDATE tst_questions"
|
||||
" SET NumHits=NumHits+1"
|
||||
" WHERE QstCod=%ld",
|
||||
PrintedQuestion->QstCod);
|
||||
Str_SetDecimalPointToLocal (); // Return to local system
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******* Get correct answer and compute score for each type of answer ********/
|
||||
/*****************************************************************************/
|
||||
|
@ -882,7 +796,7 @@ static void TstPrn_GetCorrectAndComputeIntAnsScore (struct TstPrn_PrintedQuestio
|
|||
{
|
||||
/***** Get the numerical value of the correct answer,
|
||||
and compute score *****/
|
||||
TstPrn_GetCorrectIntAnswerFromDB (Question);
|
||||
Qst_GetCorrectIntAnswerFromDB (Question);
|
||||
TstPrn_ComputeIntAnsScore (PrintedQuestion,Question);
|
||||
}
|
||||
|
||||
|
@ -891,7 +805,7 @@ static void TstPrn_GetCorrectAndComputeFltAnsScore (struct TstPrn_PrintedQuestio
|
|||
{
|
||||
/***** Get the numerical value of the minimum and maximum correct answers,
|
||||
and compute score *****/
|
||||
TstPrn_GetCorrectFltAnswerFromDB (Question);
|
||||
Qst_GetCorrectFltAnswerFromDB (Question);
|
||||
TstPrn_ComputeFltAnsScore (PrintedQuestion,Question);
|
||||
}
|
||||
|
||||
|
@ -900,7 +814,7 @@ static void TstPrn_GetCorrectAndComputeTF_AnsScore (struct TstPrn_PrintedQuestio
|
|||
{
|
||||
/***** Get answer true or false,
|
||||
and compute score *****/
|
||||
TstPrn_GetCorrectTF_AnswerFromDB (Question);
|
||||
Qst_GetCorrectTF_AnswerFromDB (Question);
|
||||
TstPrn_ComputeTF_AnsScore (PrintedQuestion,Question);
|
||||
}
|
||||
|
||||
|
@ -909,7 +823,7 @@ static void TstPrn_GetCorrectAndComputeChoAnsScore (struct TstPrn_PrintedQuestio
|
|||
{
|
||||
/***** Get correct options of test question from database,
|
||||
and compute score *****/
|
||||
TstPrn_GetCorrectChoAnswerFromDB (Question);
|
||||
Qst_GetCorrectChoAnswerFromDB (Question);
|
||||
TstPrn_ComputeChoAnsScore (PrintedQuestion,Question);
|
||||
}
|
||||
|
||||
|
@ -918,171 +832,10 @@ static void TstPrn_GetCorrectAndComputeTxtAnsScore (struct TstPrn_PrintedQuestio
|
|||
{
|
||||
/***** Get correct text answers for this question from database,
|
||||
and compute score *****/
|
||||
TstPrn_GetCorrectTxtAnswerFromDB (Question);
|
||||
Qst_GetCorrectTxtAnswerFromDB (Question);
|
||||
TstPrn_ComputeTxtAnsScore (PrintedQuestion,Question);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**************** Get correct answer for each type of answer *****************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void TstPrn_GetCorrectIntAnswerFromDB (struct Qst_Question *Question)
|
||||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
|
||||
/***** Query database *****/
|
||||
Question->Answer.NumOptions = (unsigned)
|
||||
DB_QuerySELECT (&mysql_res,"can not get answers of a question",
|
||||
"SELECT Answer" // row[0]
|
||||
" FROM tst_answers"
|
||||
" WHERE QstCod=%ld",
|
||||
Question->QstCod);
|
||||
|
||||
/***** Check if number of rows is correct *****/
|
||||
Qst_CheckIfNumberOfAnswersIsOne (Question);
|
||||
|
||||
/***** Get correct answer *****/
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
if (sscanf (row[0],"%ld",&Question->Answer.Integer) != 1)
|
||||
Err_WrongAnswerExit ();
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
}
|
||||
|
||||
static void TstPrn_GetCorrectFltAnswerFromDB (struct Qst_Question *Question)
|
||||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
unsigned NumOpt;
|
||||
double Tmp;
|
||||
|
||||
/***** Query database *****/
|
||||
Question->Answer.NumOptions = (unsigned)
|
||||
DB_QuerySELECT (&mysql_res,"can not get answers of a question",
|
||||
"SELECT Answer" // row[0]
|
||||
" FROM tst_answers"
|
||||
" WHERE QstCod=%ld",
|
||||
Question->QstCod);
|
||||
|
||||
/***** Check if number of rows is correct *****/
|
||||
if (Question->Answer.NumOptions != 2)
|
||||
Err_WrongAnswerExit ();
|
||||
|
||||
/***** Get float range *****/
|
||||
for (NumOpt = 0;
|
||||
NumOpt < 2;
|
||||
NumOpt++)
|
||||
{
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
Question->Answer.FloatingPoint[NumOpt] = Str_GetDoubleFromStr (row[0]);
|
||||
}
|
||||
if (Question->Answer.FloatingPoint[0] >
|
||||
Question->Answer.FloatingPoint[1]) // The maximum and the minimum are swapped
|
||||
{
|
||||
/* Swap maximum and minimum */
|
||||
Tmp = Question->Answer.FloatingPoint[0];
|
||||
Question->Answer.FloatingPoint[0] = Question->Answer.FloatingPoint[1];
|
||||
Question->Answer.FloatingPoint[1] = Tmp;
|
||||
}
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
}
|
||||
|
||||
static void TstPrn_GetCorrectTF_AnswerFromDB (struct Qst_Question *Question)
|
||||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
|
||||
/***** Query database *****/
|
||||
Question->Answer.NumOptions = (unsigned)
|
||||
DB_QuerySELECT (&mysql_res,"can not get answers of a question",
|
||||
"SELECT Answer" // row[0]
|
||||
" FROM tst_answers"
|
||||
" WHERE QstCod=%ld",
|
||||
Question->QstCod);
|
||||
|
||||
/***** Check if number of rows is correct *****/
|
||||
Qst_CheckIfNumberOfAnswersIsOne (Question);
|
||||
|
||||
/***** Get answer *****/
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
Question->Answer.TF = row[0][0];
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
}
|
||||
|
||||
static void TstPrn_GetCorrectChoAnswerFromDB (struct Qst_Question *Question)
|
||||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
unsigned NumOpt;
|
||||
|
||||
/***** Query database *****/
|
||||
Question->Answer.NumOptions = (unsigned)
|
||||
DB_QuerySELECT (&mysql_res,"can not get answers of a question",
|
||||
"SELECT Correct" // row[0]
|
||||
" FROM tst_answers"
|
||||
" WHERE QstCod=%ld"
|
||||
" ORDER BY AnsInd",
|
||||
Question->QstCod);
|
||||
for (NumOpt = 0;
|
||||
NumOpt < Question->Answer.NumOptions;
|
||||
NumOpt++)
|
||||
{
|
||||
/* Get next answer */
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
|
||||
/* Assign correctness (row[0]) of this answer (this option) */
|
||||
Question->Answer.Options[NumOpt].Correct = (row[0][0] == 'Y');
|
||||
}
|
||||
|
||||
/* Free structure that stores the query result */
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
}
|
||||
|
||||
static void TstPrn_GetCorrectTxtAnswerFromDB (struct Qst_Question *Question)
|
||||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
unsigned NumOpt;
|
||||
|
||||
/***** Query database *****/
|
||||
Question->Answer.NumOptions = (unsigned)
|
||||
DB_QuerySELECT (&mysql_res,"can not get answers of a question",
|
||||
"SELECT Answer" // row[0]
|
||||
" FROM tst_answers"
|
||||
" WHERE QstCod=%ld",
|
||||
Question->QstCod);
|
||||
|
||||
/***** Get text and correctness of answers for this question from database (one row per answer) *****/
|
||||
for (NumOpt = 0;
|
||||
NumOpt < Question->Answer.NumOptions;
|
||||
NumOpt++)
|
||||
{
|
||||
/***** Get next answer *****/
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
|
||||
/***** Allocate memory for text in this choice answer *****/
|
||||
if (!Qst_AllocateTextChoiceAnswer (Question,NumOpt))
|
||||
/* Abort on error */
|
||||
Ale_ShowAlertsAndExit ();
|
||||
|
||||
/***** Copy answer text (row[0]) ******/
|
||||
Str_Copy (Question->Answer.Options[NumOpt].Text,row[0],
|
||||
Qst_MAX_BYTES_ANSWER_OR_FEEDBACK);
|
||||
}
|
||||
|
||||
/***** Change format of answers text *****/
|
||||
Qst_ChangeFormatAnswersText (Question);
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/************** Compute answer score for each type of answer *****************/
|
||||
/*****************************************************************************/
|
||||
|
@ -1449,8 +1202,10 @@ static void TstPrn_WriteIntAnsPrint (struct UsrData *UsrDat,
|
|||
/***** Check if number of rows is correct *****/
|
||||
Qst_CheckIfNumberOfAnswersIsOne (Question);
|
||||
|
||||
/***** Header with the title of each column *****/
|
||||
/***** Begin table *****/
|
||||
HTM_TABLE_BeginPadding (2);
|
||||
|
||||
/***** Header with the title of each column *****/
|
||||
HTM_TR_Begin (NULL);
|
||||
TstPrn_WriteHeadUserCorrect (UsrDat);
|
||||
HTM_TR_End ();
|
||||
|
@ -1510,8 +1265,10 @@ static void TstPrn_WriteFltAnsPrint (struct UsrData *UsrDat,
|
|||
if (Question->Answer.NumOptions != 2)
|
||||
Err_WrongAnswerExit ();
|
||||
|
||||
/***** Header with the title of each column *****/
|
||||
/***** Begin table *****/
|
||||
HTM_TABLE_BeginPadding (2);
|
||||
|
||||
/***** Header with the title of each column *****/
|
||||
HTM_TR_Begin (NULL);
|
||||
TstPrn_WriteHeadUserCorrect (UsrDat);
|
||||
HTM_TR_End ();
|
||||
|
@ -1573,8 +1330,10 @@ static void TstPrn_WriteTF_AnsPrint (struct UsrData *UsrDat,
|
|||
/***** Get answer true or false *****/
|
||||
AnsTFUsr = PrintedQuestion->StrAnswers[0];
|
||||
|
||||
/***** Header with the title of each column *****/
|
||||
/***** Begin table *****/
|
||||
HTM_TABLE_BeginPadding (2);
|
||||
|
||||
/***** Header with the title of each column *****/
|
||||
HTM_TR_Begin (NULL);
|
||||
TstPrn_WriteHeadUserCorrect (UsrDat);
|
||||
HTM_TR_End ();
|
||||
|
@ -1640,6 +1399,7 @@ static void TstPrn_WriteChoAnsPrint (struct UsrData *UsrDat,
|
|||
|
||||
/***** Begin table *****/
|
||||
HTM_TABLE_BeginPadding (2);
|
||||
|
||||
HTM_TR_Begin (NULL);
|
||||
TstPrn_WriteHeadUserCorrect (UsrDat);
|
||||
HTM_TD_Empty (2);
|
||||
|
@ -1763,8 +1523,10 @@ static void TstPrn_WriteTxtAnsPrint (struct UsrData *UsrDat,
|
|||
if (ICanView[TstVis_VISIBLE_FEEDBACK_TXT])
|
||||
Qst_ChangeFormatAnswersFeedback (Question);
|
||||
|
||||
/***** Header with the title of each column *****/
|
||||
/***** Begin table *****/
|
||||
HTM_TABLE_BeginPadding (2);
|
||||
|
||||
/***** Header with the title of each column *****/
|
||||
HTM_TR_Begin (NULL);
|
||||
TstPrn_WriteHeadUserCorrect (UsrDat);
|
||||
HTM_TR_End ();
|
||||
|
@ -1883,7 +1645,7 @@ static void TstPrn_WriteHeadUserCorrect (struct UsrData *UsrDat)
|
|||
/************ Store user's answers of an test print into database ************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void TstPrn_StoreOneQstOfPrintInDB (const struct TstPrn_Print *Print,
|
||||
static void Tst_DB_StoreOneQstOfPrint (const struct TstPrn_Print *Print,
|
||||
unsigned QstInd)
|
||||
{
|
||||
/***** Insert question and user's answers into database *****/
|
||||
|
@ -1948,6 +1710,7 @@ void TstPrn_SelDatesToSeeMyPrints (void)
|
|||
Box_BoxTableBegin (NULL,Txt_Results,
|
||||
NULL,NULL,
|
||||
Hlp_ASSESSMENT_Tests_results,Box_NOT_CLOSABLE,2);
|
||||
|
||||
Dat_PutFormStartEndClientLocalDateTimesWithYesterdayToday (SetHMS);
|
||||
|
||||
/***** End table, send button and end box *****/
|
||||
|
@ -2142,6 +1905,7 @@ static void TstPrn_ShowUsrPrints (struct UsrData *UsrDat)
|
|||
|
||||
/***** Show user's data *****/
|
||||
HTM_TR_Begin (NULL);
|
||||
|
||||
Usr_ShowTableCellWithUsrData (UsrDat,NumPrints);
|
||||
|
||||
/***** Get and print tests *****/
|
||||
|
@ -2271,6 +2035,7 @@ static void TstPrn_ShowUsrPrints (struct UsrData *UsrDat)
|
|||
else
|
||||
Ico_PutIconNotVisible ();
|
||||
HTM_TD_End ();
|
||||
|
||||
HTM_TR_End ();
|
||||
|
||||
if (Print.AllowTeachers)
|
||||
|
@ -2577,6 +2342,8 @@ void TstPrn_ShowOnePrint (void)
|
|||
Ico_PutIconNotVisible ();
|
||||
HTM_TD_End ();
|
||||
|
||||
HTM_TR_End ();
|
||||
|
||||
/***** Grade *****/
|
||||
HTM_TR_Begin (NULL);
|
||||
|
||||
|
|
|
@ -91,8 +91,6 @@ typedef enum
|
|||
/*****************************************************************************/
|
||||
|
||||
void TstPrn_ResetPrint (struct TstPrn_Print *Print);
|
||||
void TstPrn_CreatePrintInDB (struct TstPrn_Print *Print);
|
||||
void TstPrn_UpdatePrintInDB (const struct TstPrn_Print *Print);
|
||||
|
||||
void TstPrn_ShowTestPrintToFillIt (struct TstPrn_Print *Print,
|
||||
unsigned NumPrintsGeneratedByMe,
|
||||
|
|
Loading…
Reference in New Issue