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
|
||||
|
|
1693
swad_test_print.c
1693
swad_test_print.c
File diff suppressed because it is too large
Load Diff
|
@ -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