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.
|
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 CSS_FILE "swad20.45.css"
|
||||||
#define JS_FILE "swad20.69.1.js"
|
#define JS_FILE "swad20.69.1.js"
|
||||||
/*
|
/*
|
||||||
TODO: Rename CENTRE to CENTER in help wiki.
|
TODO: Rename CENTRE to CENTER in help wiki.
|
||||||
TODO: Rename ASSESSMENT.Announcements to ASSESSMENT.Calls_for_exams
|
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.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.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)
|
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 ();
|
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 *****************/
|
/************** 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,
|
void Qst_WriteChoAnsBank (struct Qst_Question *Question,
|
||||||
const char *ClassTxt,
|
const char *ClassTxt,
|
||||||
const char *ClassFeedback);
|
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 ();
|
NumPrintsGeneratedByMe = TstPrn_GetNumPrintsGeneratedByMe ();
|
||||||
|
|
||||||
/***** Create new test print in database *****/
|
/***** Create new test print in database *****/
|
||||||
TstPrn_CreatePrintInDB (&Print);
|
Print.PrnCod = Tst_DB_CreatePrint (Print.NumQsts.All);
|
||||||
TstPrn_ComputeScoresAndStoreQuestionsOfPrint (&Print,
|
TstPrn_ComputeScoresAndStoreQuestionsOfPrint (&Print,
|
||||||
false); // Don't update question score
|
false); // Don't update question score
|
||||||
|
|
||||||
|
@ -298,7 +298,7 @@ void Tst_ReceiveTestDraft (void)
|
||||||
/***** Update test print in database *****/
|
/***** Update test print in database *****/
|
||||||
TstPrn_ComputeScoresAndStoreQuestionsOfPrint (&Print,
|
TstPrn_ComputeScoresAndStoreQuestionsOfPrint (&Print,
|
||||||
false); // Don't update question score
|
false); // Don't update question score
|
||||||
TstPrn_UpdatePrintInDB (&Print);
|
Tst_DB_UpdatePrint (&Print);
|
||||||
|
|
||||||
/***** Show question and button to send the test *****/
|
/***** Show question and button to send the test *****/
|
||||||
/* Begin alert */
|
/* Begin alert */
|
||||||
|
@ -358,7 +358,7 @@ void Tst_AssessTest (void)
|
||||||
/***** Update test print in database *****/
|
/***** Update test print in database *****/
|
||||||
TstPrn_ComputeScoresAndStoreQuestionsOfPrint (&Print,
|
TstPrn_ComputeScoresAndStoreQuestionsOfPrint (&Print,
|
||||||
Gbl.Usrs.Me.Role.Logged == Rol_STD); // Update question score?
|
Gbl.Usrs.Me.Role.Logged == Rol_STD); // Update question score?
|
||||||
TstPrn_UpdatePrintInDB (&Print);
|
Tst_DB_UpdatePrint (&Print);
|
||||||
|
|
||||||
/***** Begin box *****/
|
/***** Begin box *****/
|
||||||
Box_BoxBegin (NULL,Txt_Result,
|
Box_BoxBegin (NULL,Txt_Result,
|
||||||
|
|
|
@ -169,6 +169,32 @@ unsigned Tst_DB_GetNumPrintsGeneratedByMe (MYSQL_RES **mysql_res)
|
||||||
Gbl.Hierarchy.Crs.CrsCod);
|
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 ***************/
|
/************** Get questions for a new test from the database ***************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@ -344,3 +370,53 @@ void Tst_DB_RemoveTstConfig (long CrsCod)
|
||||||
" WHERE CrsCod=%ld",
|
" WHERE CrsCod=%ld",
|
||||||
CrsCod);
|
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);
|
unsigned Tst_DB_GetNumPrintsGeneratedByMe (MYSQL_RES **mysql_res);
|
||||||
|
|
||||||
//---------------------------- Test questions ---------------------------------
|
//---------------------------- Test questions ---------------------------------
|
||||||
|
void Tst_DB_UpdateQstScore (const struct TstPrn_PrintedQuestion *PrintedQuestion);
|
||||||
|
|
||||||
unsigned Tst_DB_GetQuestionsForNewTest (MYSQL_RES **mysql_res,
|
unsigned Tst_DB_GetQuestionsForNewTest (MYSQL_RES **mysql_res,
|
||||||
const struct Qst_Questions *Questions);
|
const struct Qst_Questions *Questions);
|
||||||
|
|
||||||
|
@ -67,4 +69,8 @@ unsigned Tst_DB_GetPluggableFromConfig (MYSQL_RES **mysql_res);
|
||||||
|
|
||||||
void Tst_DB_RemoveTstConfig (long CrsCod);
|
void Tst_DB_RemoveTstConfig (long CrsCod);
|
||||||
|
|
||||||
|
//------------------------------- Test prints ---------------------------------
|
||||||
|
long Tst_DB_CreatePrint (unsigned NumQsts);
|
||||||
|
void Tst_DB_UpdatePrint (const struct TstPrn_Print *Print);
|
||||||
|
|
||||||
#endif
|
#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_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,
|
void TstPrn_ShowTestPrintToFillIt (struct TstPrn_Print *Print,
|
||||||
unsigned NumPrintsGeneratedByMe,
|
unsigned NumPrintsGeneratedByMe,
|
||||||
|
|
Loading…
Reference in New Issue