diff --git a/swad_changelog.h b/swad_changelog.h
index 93c3aa42..1fbdfe2a 100644
--- a/swad_changelog.h
+++ b/swad_changelog.h
@@ -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 20.95 (2021-07-08)"
+#define Log_PLATFORM_VERSION "SWAD 20.95.1 (2021-07-15)"
#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 20.95.1: Jul 15, 2021 Queries moved to module swad_exam_database. (314082 lines)
Version 20.95: Jul 08, 2021 New module swad_exam_database for database queries related to exams. (313981 lines)
Version 20.94.10: Jun 29, 2021 Code refactoring related to HTML output. (313860 lines)
Version 20.94.9: Jun 29, 2021 Query moved from module swad_menu to module swad_setting. (313848 lines)
diff --git a/swad_database.c b/swad_database.c
index 00e72ed6..190b33c3 100644
--- a/swad_database.c
+++ b/swad_database.c
@@ -3944,7 +3944,7 @@ Rol_Role_t DB_QuerySELECTRole (const char *MsgError,
}
/*****************************************************************************/
-/**** Make a SELECT query for a unique row with one double from database *****/
+/**** Make a SELECT query for a unique row with one string from database *****/
/*****************************************************************************/
// StrSize does not include the ending byte '\0'
diff --git a/swad_exam_database.c b/swad_exam_database.c
index 03adddd8..89451881 100644
--- a/swad_exam_database.c
+++ b/swad_exam_database.c
@@ -35,6 +35,7 @@
//#include "swad_error.h"
#include "swad_exam_database.h"
#include "swad_exam_log.h"
+#include "swad_exam_print.h"
#include "swad_global.h"
/*****************************************************************************/
@@ -59,11 +60,359 @@ extern struct Globals Gbl;
/***************************** Private prototypes ****************************/
/*****************************************************************************/
+/*****************************************************************************/
+/***************** Get sets of questions in a given exam *********************/
+/*****************************************************************************/
+
+unsigned Exa_DB_GetExamSets (MYSQL_RES **mysql_res,long ExaCod)
+ {
+ return (unsigned)
+ DB_QuerySELECT (mysql_res,"can not get sets of questions",
+ "SELECT SetCod," // row[0]
+ "NumQstsToPrint," // row[1]
+ "Title" // row[2]
+ " FROM exa_sets"
+ " WHERE ExaCod=%ld"
+ " ORDER BY SetInd",
+ ExaCod);
+ }
+
+/*****************************************************************************/
+/******************* Get some random questions from a set ********************/
+/*****************************************************************************/
+
+unsigned Exa_DB_GetSomeQstsFromSetToPrint (MYSQL_RES **mysql_res,
+ long SetCod,unsigned NumQstsToPrint)
+ {
+ return (unsigned)
+ DB_QuerySELECT (mysql_res,"can not get questions from set",
+ "SELECT QstCod," // row[0]
+ "AnsType," // row[1]
+ "Shuffle" // row[2]
+ " FROM exa_set_questions"
+ " WHERE SetCod=%ld"
+ " ORDER BY RAND()" // Don't use RAND(NOW()) because the same ordering will be repeated across sets
+ " LIMIT %u",
+ SetCod,
+ NumQstsToPrint);
+ }
+
+/*****************************************************************************/
+/************** Get answers text for a question in an exam set ***************/
+/*****************************************************************************/
+
+unsigned Exa_DB_GetQstAnswersTextFromSet (MYSQL_RES **mysql_res,long QstCod)
+ {
+ return (unsigned)
+ DB_QuerySELECT (mysql_res,"can not get text of answers of a question",
+ "SELECT Answer" // row[0]
+ " FROM exa_set_answers"
+ " WHERE QstCod=%ld",
+ QstCod);
+ }
+
+/*****************************************************************************/
+/********** Get answers correctness for a question in an exam set ************/
+/*****************************************************************************/
+
+unsigned Exa_DB_GetQstAnswersCorrFromSet (MYSQL_RES **mysql_res,long QstCod)
+ {
+ return (unsigned)
+ DB_QuerySELECT (mysql_res,"can not get correctness of answers of a question",
+ "SELECT Correct" // row[0]
+ " FROM exa_set_answers"
+ " WHERE QstCod=%ld"
+ " ORDER BY AnsInd",
+ QstCod);
+ }
+
+/*****************************************************************************/
+/***************** Create new blank exam print in database *******************/
+/*****************************************************************************/
+
+long Exa_DB_CreatePrint (const struct ExaPrn_Print *Print)
+ {
+ return
+ DB_QueryINSERTandReturnCode ("can not create new exam print",
+ "INSERT INTO exa_prints"
+ " (SesCod,UsrCod,StartTime,EndTime,"
+ "NumQsts,NumQstsNotBlank,Sent,Score)"
+ " VALUES"
+ " (%ld,%ld,NOW(),NOW(),"
+ "%u,0,'N',0)",
+ Print->SesCod,
+ Print->UsrCod,
+ Print->NumQsts.All);
+ }
+
+/*****************************************************************************/
+/********************** Update exam print in database ************************/
+/*****************************************************************************/
+
+void Exa_DB_UpdatePrint (const struct ExaPrn_Print *Print)
+ {
+ /***** Update exam print in database *****/
+ Str_SetDecimalPointToUS (); // To print the floating point as a dot
+ DB_QueryUPDATE ("can not update exam print",
+ "UPDATE exa_prints"
+ " SET EndTime=NOW(),"
+ "NumQstsNotBlank=%u,"
+ "Sent='%c',"
+ "Score='%.15lg'"
+ " WHERE PrnCod=%ld"
+ " AND SesCod=%ld"
+ " AND UsrCod=%ld", // Extra checks
+ Print->NumQsts.NotBlank,
+ Print->Sent ? 'Y' :
+ 'N',
+ Print->Score,
+ Print->PrnCod,
+ Print->SesCod,
+ Gbl.Usrs.Me.UsrDat.UsrCod);
+ Str_SetDecimalPointToLocal (); // Return to local system
+ }
+
+/*****************************************************************************/
+/**************** Get data of an exam print using print code *****************/
+/*****************************************************************************/
+
+unsigned Exa_DB_GetDataOfPrintByPrnCod (MYSQL_RES **mysql_res,long PrnCod)
+ {
+ return (unsigned)
+ DB_QuerySELECT (mysql_res,"can not get data of an exam print",
+ "SELECT PrnCod," // row[0]
+ "SesCod," // row[1]
+ "UsrCod," // row[2]
+ "UNIX_TIMESTAMP(StartTime)," // row[3]
+ "UNIX_TIMESTAMP(EndTime)," // row[4]
+ "NumQsts," // row[5]
+ "NumQstsNotBlank," // row[6]
+ "Sent," // row[7]
+ "Score" // row[8]
+ " FROM exa_prints"
+ " WHERE PrnCod=%ld",
+ PrnCod);
+ }
+
+/*****************************************************************************/
+/******** Get data of an exam print using session code and user code *********/
+/*****************************************************************************/
+
+unsigned Exa_DB_GetDataOfPrintBySesCodAndUsrCod (MYSQL_RES **mysql_res,
+ long SesCod,long UsrCod)
+ {
+ return (unsigned)
+ DB_QuerySELECT (mysql_res,"can not get data of an exam print",
+ "SELECT PrnCod," // row[0]
+ "SesCod," // row[1]
+ "UsrCod," // row[2]
+ "UNIX_TIMESTAMP(StartTime)," // row[3]
+ "UNIX_TIMESTAMP(EndTime)," // row[4]
+ "NumQsts," // row[5]
+ "NumQstsNotBlank," // row[6]
+ "Sent," // row[7]
+ "Score" // row[8]
+ " FROM exa_prints"
+ " WHERE SesCod=%ld"
+ " AND UsrCod=%ld",
+ SesCod,
+ UsrCod);
+ }
+
+/*****************************************************************************/
+/******************* Remove exam prints for a given user *********************/
+/*****************************************************************************/
+
+void Exa_DB_RemovePrintsMadeByUsrInAllCrss (long UsrCod)
+ {
+ DB_QueryDELETE ("can not remove exam prints made by a user",
+ "DELETE FROM exa_prints"
+ " WHERE UsrCod=%ld",
+ UsrCod);
+ }
+
+/*****************************************************************************/
+/*************** Remove exam prints made by a user in a course ***************/
+/*****************************************************************************/
+
+void Exa_DB_RemovePrintsMadeByUsrInCrs (long UsrCod,long CrsCod)
+ {
+ DB_QueryDELETE ("can not remove exams prints made by a user in a course",
+ "DELETE FROM exa_prints"
+ " USING exa_exams,"
+ "exa_sessions,"
+ "exa_prints"
+ " WHERE exa_exams.CrsCod=%ld"
+ " AND exa_exams.ExaCod=exa_sessions.ExaCod"
+ " AND exa_sessions.SesCod=exa_prints.SesCod"
+ " AND exa_prints.UsrCod=%ld",
+ CrsCod,
+ UsrCod);
+ }
+
+/*****************************************************************************/
+/******* Remove exams prints made by the given user in the given course ******/
+/*****************************************************************************/
+
+void Exa_DB_RemovePrintsInCrs (long CrsCod)
+ {
+ DB_QueryDELETE ("can not remove exams prints in a course",
+ "DELETE FROM exa_prints"
+ " USING exa_exams,"
+ "exa_sessions,"
+ "exa_prints"
+ " WHERE exa_exams.CrsCod=%ld"
+ " AND exa_exams.ExaCod=exa_sessions.ExaCod"
+ " AND exa_sessions.SesCod=exa_prints.SesCod",
+ CrsCod);
+ }
+
+/*****************************************************************************/
+/************* Store user's answers of an test exam into database ************/
+/*****************************************************************************/
+
+void Exa_DB_StoreOneQstOfPrint (const struct ExaPrn_Print *Print,
+ unsigned QstInd)
+ {
+ Str_SetDecimalPointToUS (); // To print the floating point as a dot
+ DB_QueryREPLACE ("can not update a question in an exam print",
+ "REPLACE INTO exa_print_questions"
+ " (PrnCod,QstCod,QstInd,SetCod,Score,Indexes,Answers)"
+ " VALUES"
+ " (%ld,%ld,%u,%ld,'%.15lg','%s','%s')",
+ Print->PrnCod,
+ Print->PrintedQuestions[QstInd].QstCod,
+ QstInd, // 0, 1, 2, 3...
+ Print->PrintedQuestions[QstInd].SetCod,
+ Print->PrintedQuestions[QstInd].Score,
+ Print->PrintedQuestions[QstInd].StrIndexes,
+ Print->PrintedQuestions[QstInd].StrAnswers);
+ Str_SetDecimalPointToLocal (); // Return to local system
+ }
+
+/*****************************************************************************/
+/************* Get the questions of an exam print from database **************/
+/*****************************************************************************/
+
+unsigned Exa_DB_GetPrintQuestions (MYSQL_RES **mysql_res,long PrnCod)
+ {
+ return (unsigned)
+ DB_QuerySELECT (mysql_res,"can not get questions of an exam print",
+ "SELECT QstCod," // row[0]
+ "SetCod," // row[1]
+ "Score," // row[2]
+ "Indexes," // row[3]
+ "Answers" // row[4]
+ " FROM exa_print_questions"
+ " WHERE PrnCod=%ld"
+ " ORDER BY QstInd",
+ PrnCod);
+ }
+
+/*****************************************************************************/
+/************** Get the answers of an exam print from database ***************/
+/*****************************************************************************/
+
+void Exa_DB_GetAnswersFromQstInPrint (long PrnCod,long QstCod,
+ char StrAnswers[Tst_MAX_BYTES_ANSWERS_ONE_QST + 1])
+ {
+ DB_QuerySELECTString (StrAnswers,Tst_MAX_BYTES_ANSWERS_ONE_QST,
+ "can not get answer in an exam print",
+ "SELECT Answers"
+ " FROM exa_print_questions"
+ " WHERE PrnCod=%ld"
+ " AND QstCod=%ld",
+ PrnCod,QstCod);
+ }
+
+/*****************************************************************************/
+/************ Get number of questions not blank in an exam print *************/
+/*****************************************************************************/
+
+unsigned Exa_DB_GetNumQstsNotBlankInPrint (long PrnCod)
+ {
+ return (unsigned)
+ DB_QueryCOUNT ("can not get number of questions not blank",
+ "SELECT COUNT(*)"
+ " FROM exa_print_questions"
+ " WHERE PrnCod=%ld"
+ " AND Answers<>''",
+ PrnCod);
+ }
+
+/*****************************************************************************/
+/************* Compute total score of questions of an exam print *************/
+/*****************************************************************************/
+
+double Exa_DB_ComputeTotalScoreOfPrint (long PrnCod)
+ {
+ return DB_QuerySELECTDouble ("can not get score of exam print",
+ "SELECT SUM(Score)"
+ " FROM exa_print_questions"
+ " WHERE PrnCod=%ld",
+ PrnCod);
+ }
+
+/*****************************************************************************/
+/*************** Remove exam prints questions for a given user ***************/
+/*****************************************************************************/
+
+void Exa_DB_RemovePrintQuestionsMadeByUsrInAllCrss (long UsrCod)
+ {
+ DB_QueryDELETE ("can not remove exam prints made by a user",
+ "DELETE FROM exa_print_questions"
+ " USING exa_prints,"
+ "exa_print_questions"
+ " WHERE exa_prints.UsrCod=%ld"
+ " AND exa_prints.PrnCod=exa_print_questions.PrnCod",
+ UsrCod);
+ }
+
+/*****************************************************************************/
+/* Remove questions of exams prints made by the given user in a given course */
+/*****************************************************************************/
+
+void Exa_DB_RemovePrintsQuestionsMadeByUsrInCrs (long UsrCod,long CrsCod)
+ {
+ DB_QueryDELETE ("can not remove exams prints made by a user in a course",
+ "DELETE FROM exa_print_questions"
+ " USING exa_exams,"
+ "exa_sessions,"
+ "exa_prints,"
+ "exa_print_questions"
+ " WHERE exa_exams.CrsCod=%ld"
+ " AND exa_exams.ExaCod=exa_sessions.ExaCod"
+ " AND exa_sessions.SesCod=exa_prints.SesCod"
+ " AND exa_prints.UsrCod=%ld"
+ " AND exa_prints.PrnCod=exa_print_questions.PrnCod",
+ CrsCod,
+ UsrCod);
+ }
+
+/*****************************************************************************/
+/* Remove questions of exams prints made by the given user in a given course */
+/*****************************************************************************/
+
+void Exa_DB_RemovePrintQuestionsInCrs (long CrsCod)
+ {
+ DB_QueryDELETE ("can not remove exams prints in a course",
+ "DELETE FROM exa_print_questions"
+ " USING exa_exams,"
+ "exa_sessions,"
+ "exa_prints,"
+ "exa_print_questions"
+ " WHERE exa_exams.CrsCod=%ld"
+ " AND exa_exams.ExaCod=exa_sessions.ExaCod"
+ " AND exa_sessions.SesCod=exa_prints.SesCod"
+ " AND exa_prints.PrnCod=exa_print_questions.PrnCod",
+ CrsCod);
+ }
+
/*****************************************************************************/
/******** Check if the current session id is the same as the last one ********/
/*****************************************************************************/
-bool ExaLog_DB_CheckIfSessionIsTheSameAsTheLast (long PrnCod)
+bool Exa_DB_CheckIfSessionIsTheSameAsTheLast (long PrnCod)
{
/***** Check if the current session id
is the same as the last one stored in database *****/
@@ -83,7 +432,7 @@ bool ExaLog_DB_CheckIfSessionIsTheSameAsTheLast (long PrnCod)
/******** Check if the current user agent is the same as the last one ********/
/*****************************************************************************/
-bool ExaLog_DB_CheckIfUserAgentIsTheSameAsTheLast (long PrnCod,const char *UserAgentDB)
+bool Exa_DB_CheckIfUserAgentIsTheSameAsTheLast (long PrnCod,const char *UserAgentDB)
{
/***** Get if the current user agent
is the same as the last stored in database *****/
@@ -103,7 +452,7 @@ bool ExaLog_DB_CheckIfUserAgentIsTheSameAsTheLast (long PrnCod,const char *UserA
/******************************** Log access *********************************/
/*****************************************************************************/
-void ExaLog_DB_LogAccess (long LogCod,long PrnCod,ExaLog_Action_t Action)
+void Exa_DB_LogAccess (long LogCod,long PrnCod,ExaLog_Action_t Action)
{
/* Log access in exam log.
Redundant data (also present in log table) are stored for speed */
@@ -126,7 +475,7 @@ void ExaLog_DB_LogAccess (long LogCod,long PrnCod,ExaLog_Action_t Action)
/*************************** Log session in database *************************/
/*****************************************************************************/
-void ExaLog_DB_LogSession (long LogCod,long PrnCod)
+void Exa_DB_LogSession (long LogCod,long PrnCod)
{
DB_QueryINSERT ("can not log session",
"INSERT INTO exa_log_sessions "
@@ -142,7 +491,7 @@ void ExaLog_DB_LogSession (long LogCod,long PrnCod)
/************************* Log user agent in database ************************/
/*****************************************************************************/
-void ExaLog_DB_LogUserAgent (long LogCod,long PrnCod,const char *UserAgentDB)
+void Exa_DB_LogUserAgent (long LogCod,long PrnCod,const char *UserAgentDB)
{
DB_QueryINSERT ("can not log user agent",
"INSERT INTO exa_log_user_agents "
@@ -153,3 +502,28 @@ void ExaLog_DB_LogUserAgent (long LogCod,long PrnCod,const char *UserAgentDB)
PrnCod,
UserAgentDB);
}
+
+/*****************************************************************************/
+/********************* Get exam print log from database **********************/
+/*****************************************************************************/
+
+unsigned Exa_DB_GetExamLog (MYSQL_RES **mysql_res,long PrnCod)
+ {
+ return (unsigned)
+ DB_QuerySELECT (mysql_res,"can not get exam print log",
+ "SELECT exa_log.ActCod," // row[0]
+ "exa_log.QstInd," // row[1]
+ "exa_log.CanAnswer," // row[2]
+ "UNIX_TIMESTAMP(exa_log.ClickTime)," // row[3]
+ "exa_log.IP," // row[4]
+ "exa_log_sessions.SessionId," // row[5]
+ "exa_log_user_agents.UserAgent" // row[6]
+ " FROM exa_log"
+ " LEFT JOIN exa_log_sessions"
+ " ON exa_log.LogCod=exa_log_sessions.LogCod"
+ " LEFT JOIN exa_log_user_agents"
+ " ON exa_log.LogCod=exa_log_user_agents.LogCod"
+ " WHERE exa_log.PrnCod=%ld"
+ " ORDER BY exa_log.LogCod",
+ PrnCod);
+ }
diff --git a/swad_exam_database.h b/swad_exam_database.h
index ae2b6f6c..947f7b3d 100644
--- a/swad_exam_database.h
+++ b/swad_exam_database.h
@@ -28,7 +28,8 @@
/*****************************************************************************/
#include "swad_exam_log.h"
-// #include "swad_exam_print.h"
+#include "swad_exam_print.h"
+#include "swad_test_type.h"
/*****************************************************************************/
/************************* Public types and constants ************************/
@@ -38,11 +39,39 @@
/***************************** Public prototypes *****************************/
/*****************************************************************************/
-bool ExaLog_DB_CheckIfSessionIsTheSameAsTheLast (long PrnCod);
-bool ExaLog_DB_CheckIfUserAgentIsTheSameAsTheLast (long PrnCod,const char *UserAgentDB);
+unsigned Exa_DB_GetExamSets (MYSQL_RES **mysql_res,long ExaCod);
+unsigned Exa_DB_GetSomeQstsFromSetToPrint (MYSQL_RES **mysql_res,
+ long SetCod,unsigned NumQstsToPrint);
+unsigned Exa_DB_GetQstAnswersTextFromSet (MYSQL_RES **mysql_res,long QstCod);
+unsigned Exa_DB_GetQstAnswersCorrFromSet (MYSQL_RES **mysql_res,long QstCod);
-void ExaLog_DB_LogAccess (long LogCod,long PrnCod,ExaLog_Action_t Action);
-void ExaLog_DB_LogSession (long LogCod,long PrnCod);
-void ExaLog_DB_LogUserAgent (long LogCod,long PrnCod,const char *UserAgentDB);
+long Exa_DB_CreatePrint (const struct ExaPrn_Print *Print);
+void Exa_DB_UpdatePrint (const struct ExaPrn_Print *Print);
+unsigned Exa_DB_GetDataOfPrintByPrnCod (MYSQL_RES **mysql_res,long PrnCod);
+unsigned Exa_DB_GetDataOfPrintBySesCodAndUsrCod (MYSQL_RES **mysql_res,
+ long SesCod,long UsrCod);
+void Exa_DB_RemovePrintsMadeByUsrInAllCrss (long UsrCod);
+void Exa_DB_RemovePrintsMadeByUsrInCrs (long UsrCod,long CrsCod);
+void Exa_DB_RemovePrintsInCrs (long CrsCod);
+
+void Exa_DB_StoreOneQstOfPrint (const struct ExaPrn_Print *Print,
+ unsigned QstInd);
+unsigned Exa_DB_GetPrintQuestions (MYSQL_RES **mysql_res,long PrnCod);
+void Exa_DB_GetAnswersFromQstInPrint (long PrnCod,long QstCod,
+ char StrAnswers[Tst_MAX_BYTES_ANSWERS_ONE_QST + 1]);
+unsigned Exa_DB_GetNumQstsNotBlankInPrint (long PrnCod);
+double Exa_DB_ComputeTotalScoreOfPrint (long PrnCod);
+void Exa_DB_RemovePrintQuestionsMadeByUsrInAllCrss (long UsrCod);
+void Exa_DB_RemovePrintsQuestionsMadeByUsrInCrs (long UsrCod,long CrsCod);
+void Exa_DB_RemovePrintQuestionsInCrs (long CrsCod);
+
+bool Exa_DB_CheckIfSessionIsTheSameAsTheLast (long PrnCod);
+bool Exa_DB_CheckIfUserAgentIsTheSameAsTheLast (long PrnCod,const char *UserAgentDB);
+
+void Exa_DB_LogAccess (long LogCod,long PrnCod,ExaLog_Action_t Action);
+void Exa_DB_LogSession (long LogCod,long PrnCod);
+void Exa_DB_LogUserAgent (long LogCod,long PrnCod,const char *UserAgentDB);
+
+unsigned Exa_DB_GetExamLog (MYSQL_RES **mysql_res,long PrnCod);
#endif
diff --git a/swad_exam_log.c b/swad_exam_log.c
index 8e38cda5..af083cd5 100644
--- a/swad_exam_log.c
+++ b/swad_exam_log.c
@@ -151,7 +151,7 @@ void ExaLog_LogAccess (long LogCod)
/***** Insert access into database *****/
/* Log access in exam log.
Redundant data (also present in log table) are stored for speed */
- ExaLog_DB_LogAccess (LogCod,PrnCod,Action);
+ Exa_DB_LogAccess (LogCod,PrnCod,Action);
/***** Log session and user agent *****/
ExaLog_LogSession (LogCod,PrnCod);
@@ -168,8 +168,8 @@ static void ExaLog_LogSession (long LogCod,long PrnCod)
{
/***** Insert session id into database
only if it's not the same as the last one stored *****/
- if (!ExaLog_DB_CheckIfSessionIsTheSameAsTheLast (PrnCod))
- ExaLog_DB_LogSession (LogCod,PrnCod);
+ if (!Exa_DB_CheckIfSessionIsTheSameAsTheLast (PrnCod))
+ Exa_DB_LogSession (LogCod,PrnCod);
}
/*****************************************************************************/
@@ -209,8 +209,8 @@ static void ExaLog_LogUsrAgent (long LogCod,long PrnCod)
/***** Insert user agent into database
only if it's not the same as the last one stored *****/
- if (!ExaLog_DB_CheckIfUserAgentIsTheSameAsTheLast (PrnCod,UserAgentDB))
- ExaLog_DB_LogUserAgent (LogCod,PrnCod,UserAgentDB);
+ if (!Exa_DB_CheckIfUserAgentIsTheSameAsTheLast (PrnCod,UserAgentDB))
+ Exa_DB_LogUserAgent (LogCod,PrnCod,UserAgentDB);
/***** Free user agent *****/
free (UserAgentDB);
@@ -251,25 +251,7 @@ void ExaLog_ShowExamLog (const struct ExaPrn_Print *Print)
const char *Class;
/***** Get print log from database *****/
- NumClicks = (unsigned)
- DB_QuerySELECT (&mysql_res,"can not get exam print log",
- "SELECT exa_log.ActCod," // row[0]
- "exa_log.QstInd," // row[1]
- "exa_log.CanAnswer," // row[2]
- "UNIX_TIMESTAMP(exa_log.ClickTime)," // row[3]
- "exa_log.IP," // row[4]
- "exa_log_sessions.SessionId," // row[5]
- "exa_log_user_agents.UserAgent" // row[6]
- " FROM exa_log"
- " LEFT JOIN exa_log_sessions"
- " ON exa_log.LogCod=exa_log_sessions.LogCod"
- " LEFT JOIN exa_log_user_agents"
- " ON exa_log.LogCod=exa_log_user_agents.LogCod"
- " WHERE exa_log.PrnCod=%ld"
- " ORDER BY exa_log.LogCod",
- Print->PrnCod);
-
- if (NumClicks)
+ if ((NumClicks = Exa_DB_GetExamLog (&mysql_res,Print->PrnCod)))
{
/***** Initialize last session id and last user agent ******/
SessionId[0] = '\0';
diff --git a/swad_exam_print.c b/swad_exam_print.c
index a0a65d76..bbabde23 100644
--- a/swad_exam_print.c
+++ b/swad_exam_print.c
@@ -35,6 +35,7 @@
#include "swad_database.h"
#include "swad_error.h"
#include "swad_exam.h"
+#include "swad_exam_database.h"
#include "swad_exam_log.h"
#include "swad_exam_print.h"
#include "swad_exam_result.h"
@@ -75,10 +76,10 @@ static void ExaPrn_GetDataOfPrint (struct ExaPrn_Print *Print,
static void ExaPrn_GetQuestionsForNewPrintFromDB (struct ExaPrn_Print *Print,long ExaCod);
static unsigned ExaPrn_GetSomeQstsFromSetToPrint (struct ExaPrn_Print *Print,
struct ExaSet_Set *Set,
- unsigned *NumQstInPrint);
+ unsigned *NumQstsInPrint);
static void ExaPrn_GenerateChoiceIndexes (struct TstPrn_PrintedQuestion *PrintedQuestion,
bool Shuffle);
-static void ExaPrn_CreatePrintInDB (struct ExaPrn_Print *Print);
+static void ExaPrn_CreatePrint (struct ExaPrn_Print *Print);
static void ExaPrn_ShowExamPrintToFillIt (struct Exa_Exams *Exams,
const struct Exa_Exam *Exam,
@@ -141,15 +142,6 @@ static void ExaPrn_GetCorrectChoAnswerFromDB (struct Tst_Question *Question);
static void ExaPrn_GetCorrectTxtAnswerFromDB (struct Tst_Question *Question);
//-----------------------------------------------------------------------------
-static void ExaPrn_GetAnswerFromDB (struct ExaPrn_Print *Print,long QstCod,
- char StrAnswers[Tst_MAX_BYTES_ANSWERS_ONE_QST + 1]);
-static void ExaPrn_StoreOneQstOfPrintInDB (const struct ExaPrn_Print *Print,
- unsigned QstInd);
-
-static unsigned Exa_DB_GetNumQstsNotBlankInPrint (long PrnCod);
-static double Exa_DB_ComputeTotalScoreOfPrint (long PrnCod);
-static void Exa_DB_UpdatePrint (const struct ExaPrn_Print *Print);
-
/*****************************************************************************/
/**************************** Reset exam print *******************************/
/*****************************************************************************/
@@ -216,7 +208,7 @@ void ExaPrn_ShowExamPrint (void)
if (Print.NumQsts.All)
{
/***** Create new exam print in database *****/
- ExaPrn_CreatePrintInDB (&Print);
+ ExaPrn_CreatePrint (&Print);
/***** Set log print code and action *****/
ExaLog_SetPrnCod (Print.PrnCod);
@@ -256,20 +248,7 @@ void ExaPrn_GetDataOfPrintByPrnCod (struct ExaPrn_Print *Print)
unsigned NumPrints;
/***** Make database query *****/
- NumPrints = (unsigned)
- DB_QuerySELECT (&mysql_res,"can not get data of an exam print",
- "SELECT PrnCod," // row[0]
- "SesCod," // row[1]
- "UsrCod," // row[2]
- "UNIX_TIMESTAMP(StartTime)," // row[3]
- "UNIX_TIMESTAMP(EndTime)," // row[4]
- "NumQsts," // row[5]
- "NumQstsNotBlank," // row[6]
- "Sent," // row[7]
- "Score" // row[8]
- " FROM exa_prints"
- " WHERE PrnCod=%ld",
- Print->PrnCod);
+ NumPrints = Exa_DB_GetDataOfPrintByPrnCod (&mysql_res,Print->PrnCod);
/***** Get data of print *****/
ExaPrn_GetDataOfPrint (Print,&mysql_res,NumPrints);
@@ -285,22 +264,9 @@ void ExaPrn_GetDataOfPrintBySesCodAndUsrCod (struct ExaPrn_Print *Print)
unsigned NumPrints;
/***** Make database query *****/
- NumPrints = (unsigned)
- DB_QuerySELECT (&mysql_res,"can not get data of an exam print",
- "SELECT PrnCod," // row[0]
- "SesCod," // row[1]
- "UsrCod," // row[2]
- "UNIX_TIMESTAMP(StartTime)," // row[3]
- "UNIX_TIMESTAMP(EndTime)," // row[4]
- "NumQsts," // row[5]
- "NumQstsNotBlank," // row[6]
- "Sent," // row[7]
- "Score" // row[8]
- " FROM exa_prints"
- " WHERE SesCod=%ld"
- " AND UsrCod=%ld",
- Print->SesCod,
- Print->UsrCod);
+ NumPrints = Exa_DB_GetDataOfPrintBySesCodAndUsrCod (&mysql_res,
+ Print->SesCod,
+ Print->UsrCod);
/***** Get data of print *****/
ExaPrn_GetDataOfPrint (Print,&mysql_res,NumPrints);
@@ -369,22 +335,11 @@ static void ExaPrn_GetQuestionsForNewPrintFromDB (struct ExaPrn_Print *Print,lon
unsigned NumSet;
struct ExaSet_Set Set;
unsigned NumQstsFromSet;
- unsigned NumQstInPrint = 0;
-
- /***** Get data of set of questions from database *****/
- NumSets = (unsigned)
- DB_QuerySELECT (&mysql_res,"can not get sets of questions",
- "SELECT SetCod," // row[0]
- "NumQstsToPrint," // row[1]
- "Title" // row[2]
- " FROM exa_sets"
- " WHERE ExaCod=%ld"
- " ORDER BY SetInd",
- ExaCod);
+ unsigned NumQstsInPrint = 0;
/***** Get questions from all sets *****/
Print->NumQsts.All = 0;
- if (NumSets)
+ if ((NumSets = Exa_DB_GetExamSets (&mysql_res,ExaCod)))
/***** For each set in exam... *****/
for (NumSet = 0;
NumSet < NumSets;
@@ -400,22 +355,21 @@ static void ExaPrn_GetQuestionsForNewPrintFromDB (struct ExaPrn_Print *Print,lon
row[1] NumQstsToPrint
row[2] Title
*/
- /* Get set code (row[0]) */
- Set.SetCod = Str_ConvertStrCodToLongCod (row[0]);
-
- /* Get set index (row[1]) */
+ /* Get set code (row[0])
+ and set index (row[1]) */
+ Set.SetCod = Str_ConvertStrCodToLongCod (row[0]);
Set.NumQstsToPrint = Str_ConvertStrToUnsigned (row[1]);
/* Get the title of the set (row[2]) */
Str_Copy (Set.Title,row[2],sizeof (Set.Title) - 1);
/***** Questions in this set *****/
- NumQstsFromSet = ExaPrn_GetSomeQstsFromSetToPrint (Print,&Set,&NumQstInPrint);
+ NumQstsFromSet = ExaPrn_GetSomeQstsFromSetToPrint (Print,&Set,&NumQstsInPrint);
Print->NumQsts.All += NumQstsFromSet;
}
/***** Check *****/
- if (Print->NumQsts.All != NumQstInPrint)
+ if (Print->NumQsts.All != NumQstsInPrint)
Err_ShowErrorAndExit ("Wrong number of questions.");
/***** Free structure that stores the query result *****/
@@ -423,12 +377,12 @@ static void ExaPrn_GetQuestionsForNewPrintFromDB (struct ExaPrn_Print *Print,lon
}
/*****************************************************************************/
-/************************ Show questions from a set **************************/
+/********************** Get some questions from a set ************************/
/*****************************************************************************/
static unsigned ExaPrn_GetSomeQstsFromSetToPrint (struct ExaPrn_Print *Print,
struct ExaSet_Set *Set,
- unsigned *NumQstInPrint)
+ unsigned *NumQstsInPrint)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
@@ -438,22 +392,14 @@ static unsigned ExaPrn_GetSomeQstsFromSetToPrint (struct ExaPrn_Print *Print,
bool Shuffle;
/***** Get questions from database *****/
- NumQstsInSet = (unsigned)
- DB_QuerySELECT (&mysql_res,"can not get questions from set",
- "SELECT QstCod," // row[0]
- "AnsType," // row[1]
- "Shuffle" // row[2]
- " FROM exa_set_questions"
- " WHERE SetCod=%ld"
- " ORDER BY RAND()" // Don't use RAND(NOW()) because the same ordering will be repeated across sets
- " LIMIT %u",
- Set->SetCod,
- Set->NumQstsToPrint);
+ NumQstsInSet = Exa_DB_GetSomeQstsFromSetToPrint (&mysql_res,
+ Set->SetCod,
+ Set->NumQstsToPrint);
/***** Questions in this set *****/
for (NumQstInSet = 0;
NumQstInSet < NumQstsInSet;
- NumQstInSet++, (*NumQstInPrint)++)
+ NumQstInSet++, (*NumQstsInPrint)++)
{
Gbl.RowEvenOdd = 1 - Gbl.RowEvenOdd;
@@ -466,10 +412,10 @@ static unsigned ExaPrn_GetSomeQstsFromSetToPrint (struct ExaPrn_Print *Print,
*/
/* Get question code (row[0]) */
- Print->PrintedQuestions[*NumQstInPrint].QstCod = Str_ConvertStrCodToLongCod (row[0]);
+ Print->PrintedQuestions[*NumQstsInPrint].QstCod = Str_ConvertStrCodToLongCod (row[0]);
/* Set set of questions */
- Print->PrintedQuestions[*NumQstInPrint].SetCod = Set->SetCod;
+ Print->PrintedQuestions[*NumQstsInPrint].SetCod = Set->SetCod;
/* Get answer type (row[1]) */
AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
@@ -484,13 +430,13 @@ static unsigned ExaPrn_GetSomeQstsFromSetToPrint (struct ExaPrn_Print *Print,
case Tst_ANS_FLOAT:
case Tst_ANS_TRUE_FALSE:
case Tst_ANS_TEXT:
- Print->PrintedQuestions[*NumQstInPrint].StrIndexes[0] = '\0';
+ Print->PrintedQuestions[*NumQstsInPrint].StrIndexes[0] = '\0';
break;
case Tst_ANS_UNIQUE_CHOICE:
case Tst_ANS_MULTIPLE_CHOICE:
/* If answer type is unique or multiple option,
generate indexes of answers depending on shuffle */
- ExaPrn_GenerateChoiceIndexes (&Print->PrintedQuestions[*NumQstInPrint],Shuffle);
+ ExaPrn_GenerateChoiceIndexes (&Print->PrintedQuestions[*NumQstsInPrint],Shuffle);
break;
default:
break;
@@ -500,10 +446,10 @@ static unsigned ExaPrn_GetSomeQstsFromSetToPrint (struct ExaPrn_Print *Print,
Initially user has not answered the question ==> initially all the answers will be blank.
If the user does not confirm the submission of their exam ==>
==> the exam may be half filled ==> the answers displayed will be those selected by the user. */
- Print->PrintedQuestions[*NumQstInPrint].StrAnswers[0] = '\0';
+ Print->PrintedQuestions[*NumQstsInPrint].StrAnswers[0] = '\0';
/* Reset score of this question in print */
- Print->PrintedQuestions[*NumQstInPrint].Score = 0.0;
+ Print->PrintedQuestions[*NumQstsInPrint].Score = 0.0;
}
return NumQstsInSet;
@@ -578,29 +524,19 @@ static void ExaPrn_GenerateChoiceIndexes (struct TstPrn_PrintedQuestion *Printed
/***************** Create new blank exam print in database *******************/
/*****************************************************************************/
-static void ExaPrn_CreatePrintInDB (struct ExaPrn_Print *Print)
+static void ExaPrn_CreatePrint (struct ExaPrn_Print *Print)
{
unsigned QstInd;
- /***** Insert new exam print into table *****/
- Print->PrnCod =
- DB_QueryINSERTandReturnCode ("can not create new exam print",
- "INSERT INTO exa_prints"
- " (SesCod,UsrCod,StartTime,EndTime,"
- "NumQsts,NumQstsNotBlank,Sent,Score)"
- " VALUES"
- " (%ld,%ld,NOW(),NOW(),"
- "%u,0,'N',0)",
- Print->SesCod,
- Print->UsrCod,
- Print->NumQsts.All);
+ /***** Insert new exam print into database *****/
+ Print->PrnCod = Exa_DB_CreatePrint (Print);
/***** Store all questions (with blank answers)
of this exam print just generated in database *****/
for (QstInd = 0;
QstInd < Print->NumQsts.All;
QstInd++)
- ExaPrn_StoreOneQstOfPrintInDB (Print,QstInd);
+ Exa_DB_StoreOneQstOfPrint (Print,QstInd);
}
/*****************************************************************************/
@@ -614,31 +550,18 @@ void ExaPrn_GetPrintQuestionsFromDB (struct ExaPrn_Print *Print)
unsigned QstInd;
/***** Get questions of an exam print from database *****/
- Print->NumQsts.All = (unsigned)
- DB_QuerySELECT (&mysql_res,"can not get questions of an exam print",
- "SELECT QstCod," // row[0]
- "SetCod," // row[1]
- "Score," // row[2]
- "Indexes," // row[3]
- "Answers" // row[4]
- " FROM exa_print_questions"
- " WHERE PrnCod=%ld"
- " ORDER BY QstInd",
- Print->PrnCod);
-
- /***** Get questions *****/
- if (Print->NumQsts.All <= ExaPrn_MAX_QUESTIONS_PER_EXAM_PRINT)
+ if ((Print->NumQsts.All = Exa_DB_GetPrintQuestions (&mysql_res,Print->PrnCod))
+ <= ExaPrn_MAX_QUESTIONS_PER_EXAM_PRINT)
for (QstInd = 0;
QstInd < Print->NumQsts.All;
QstInd++)
{
row = mysql_fetch_row (mysql_res);
- /* Get question code (row[0]) */
+ /* Get question code (row[0])
+ and set code (row[1]) */
if ((Print->PrintedQuestions[QstInd].QstCod = Str_ConvertStrCodToLongCod (row[0])) <= 0)
Err_WrongQuestionExit ();
-
- /* Get set code (row[1]) */
if ((Print->PrintedQuestions[QstInd].SetCod = Str_ConvertStrCodToLongCod (row[1])) <= 0)
Err_WrongSetExit ();
@@ -648,11 +571,10 @@ void ExaPrn_GetPrintQuestionsFromDB (struct ExaPrn_Print *Print)
Err_ShowErrorAndExit ("Wrong question score.");
Str_SetDecimalPointToLocal (); // Return to local system
- /* Get indexes for this question (row[3]) */
+ /* Get indexes for this question (row[3])
+ and answers selected by user for this question (row[4]) */
Str_Copy (Print->PrintedQuestions[QstInd].StrIndexes,row[3],
sizeof (Print->PrintedQuestions[QstInd].StrIndexes) - 1);
-
- /* Get answers selected by user for this question (row[4]) */
Str_Copy (Print->PrintedQuestions[QstInd].StrAnswers,row[4],
sizeof (Print->PrintedQuestions[QstInd].StrAnswers) - 1);
}
@@ -914,9 +836,9 @@ static void ExaPrn_WriteTF_AnsToFill (const struct ExaPrn_Print *Print,
HTM_TxtF ("");
- HTM_OPTION (HTM_Type_STRING,"" ,Print->PrintedQuestions[QstInd].StrAnswers[0] == '\0',false," ");
- HTM_OPTION (HTM_Type_STRING,"T",Print->PrintedQuestions[QstInd].StrAnswers[0] == 'T' ,false,"%s",Txt_TF_QST[0]);
- HTM_OPTION (HTM_Type_STRING,"F",Print->PrintedQuestions[QstInd].StrAnswers[0] == 'F' ,false,"%s",Txt_TF_QST[1]);
+ HTM_OPTION (HTM_Type_STRING,"" ,Print->PrintedQuestions[QstInd].StrAnswers[0] == '\0',false," ");
+ HTM_OPTION (HTM_Type_STRING,"T",Print->PrintedQuestions[QstInd].StrAnswers[0] == 'T' ,false,"%s",Txt_TF_QST[0]);
+ HTM_OPTION (HTM_Type_STRING,"F",Print->PrintedQuestions[QstInd].StrAnswers[0] == 'F' ,false,"%s",Txt_TF_QST[1]);
HTM_Txt ("");
}
@@ -953,37 +875,37 @@ static void ExaPrn_WriteChoAnsToFill (const struct ExaPrn_Print *Print,
or 3 1 0 2... (example) if shuffle *****/
HTM_TR_Begin (NULL);
- /***** Write selectors and letter of this option *****/
- /* Initially user has not answered the question ==> initially all the answers will be blank.
- If the user does not confirm the submission of their exam ==>
- ==> the exam may be half filled ==> the answers displayed will be those selected by the user. */
- HTM_TD_Begin ("class=\"LT\"");
- snprintf (Id,sizeof (Id),"Ans%010u",QstInd);
- HTM_TxtF ("Answer.Type == Tst_ANS_UNIQUE_CHOICE ? "radio" :
- "checkbox",
- Id,NumOpt,Indexes[NumOpt],
- UsrAnswers[Indexes[NumOpt]] ? " checked=\"checked\"" :
- "");
- ExaPrn_WriteJSToUpdateExamPrint (Print,QstInd,Id,(int) NumOpt);
- HTM_Txt (" />");
- HTM_TD_End ();
+ /***** Write selectors and letter of this option *****/
+ /* Initially user has not answered the question ==> initially all the answers will be blank.
+ If the user does not confirm the submission of their exam ==>
+ ==> the exam may be half filled ==> the answers displayed will be those selected by the user. */
+ HTM_TD_Begin ("class=\"LT\"");
+ snprintf (Id,sizeof (Id),"Ans%010u",QstInd);
+ HTM_TxtF ("Answer.Type == Tst_ANS_UNIQUE_CHOICE ? "radio" :
+ "checkbox",
+ Id,NumOpt,Indexes[NumOpt],
+ UsrAnswers[Indexes[NumOpt]] ? " checked=\"checked\"" :
+ "");
+ ExaPrn_WriteJSToUpdateExamPrint (Print,QstInd,Id,(int) NumOpt);
+ HTM_Txt (" />");
+ HTM_TD_End ();
- HTM_TD_Begin ("class=\"LT\"");
- HTM_LABEL_Begin ("for=\"Ans%010u_%u\" class=\"TEST_TXT\"",QstInd,NumOpt);
- HTM_TxtF ("%c) ",'a' + (char) NumOpt);
- HTM_LABEL_End ();
- HTM_TD_End ();
+ HTM_TD_Begin ("class=\"LT\"");
+ HTM_LABEL_Begin ("for=\"Ans%010u_%u\" class=\"TEST_TXT\"",QstInd,NumOpt);
+ HTM_TxtF ("%c) ",'a' + (char) NumOpt);
+ HTM_LABEL_End ();
+ HTM_TD_End ();
- /***** Write the option text *****/
- HTM_TD_Begin ("class=\"LT\"");
- HTM_LABEL_Begin ("for=\"Ans%010u_%u\" class=\"TEST_TXT\"",QstInd,NumOpt);
- HTM_Txt (Question->Answer.Options[Indexes[NumOpt]].Text);
- HTM_LABEL_End ();
- Med_ShowMedia (&Question->Answer.Options[Indexes[NumOpt]].Media,
- "TEST_MED_SHOW_CONT",
- "TEST_MED_SHOW");
- HTM_TD_End ();
+ /***** Write the option text *****/
+ HTM_TD_Begin ("class=\"LT\"");
+ HTM_LABEL_Begin ("for=\"Ans%010u_%u\" class=\"TEST_TXT\"",QstInd,NumOpt);
+ HTM_Txt (Question->Answer.Options[Indexes[NumOpt]].Text);
+ HTM_LABEL_End ();
+ Med_ShowMedia (&Question->Answer.Options[Indexes[NumOpt]].Media,
+ "TEST_MED_SHOW_CONT",
+ "TEST_MED_SHOW");
+ HTM_TD_End ();
HTM_TR_End ();
}
@@ -1009,7 +931,6 @@ static void ExaPrn_WriteTxtAnsToFill (const struct ExaPrn_Print *Print,
Id,Tst_MAX_CHARS_ANSWERS_ONE_QST,
Print->PrintedQuestions[QstInd].StrAnswers);
ExaPrn_WriteJSToUpdateExamPrint (Print,QstInd,Id,-1);
-
HTM_Txt (" />");
}
@@ -1174,8 +1095,8 @@ static void ExaPrn_ComputeScoreAndStoreQuestionOfPrint (struct ExaPrn_Print *Pri
==> uncheck it by deleting answer *****/
if (Question.Answer.Type == Tst_ANS_UNIQUE_CHOICE)
{
- ExaPrn_GetAnswerFromDB (Print,Print->PrintedQuestions[QstInd].QstCod,
- CurrentStrAnswersInDB);
+ Exa_DB_GetAnswersFromQstInPrint (Print->PrnCod,Print->PrintedQuestions[QstInd].QstCod,
+ CurrentStrAnswersInDB);
if (!strcmp (Print->PrintedQuestions[QstInd].StrAnswers,CurrentStrAnswersInDB))
{
/* The answer just clicked by user
@@ -1186,8 +1107,8 @@ static void ExaPrn_ComputeScoreAndStoreQuestionOfPrint (struct ExaPrn_Print *Pri
}
/***** Store test exam question in database *****/
- ExaPrn_StoreOneQstOfPrintInDB (Print,
- QstInd); // 0, 1, 2, 3...
+ Exa_DB_StoreOneQstOfPrint (Print,
+ QstInd); // 0, 1, 2, 3...
}
/*****************************************************************************/
@@ -1271,12 +1192,7 @@ static void ExaPrn_GetCorrectIntAnswerFromDB (struct Tst_Question *Question)
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 exa_set_answers"
- " WHERE QstCod=%ld",
- Question->QstCod);
+ Question->Answer.NumOptions = Exa_DB_GetQstAnswersTextFromSet (&mysql_res,Question->QstCod);
/***** Check if number of rows is correct *****/
Tst_CheckIfNumberOfAnswersIsOne (Question);
@@ -1298,12 +1214,7 @@ static void ExaPrn_GetCorrectFltAnswerFromDB (struct Tst_Question *Question)
double Tmp;
/***** Query database *****/
- Question->Answer.NumOptions = (unsigned)
- DB_QuerySELECT (&mysql_res,"can not get answers of a question",
- "SELECT Answer" // row[0]
- " FROM exa_set_answers"
- " WHERE QstCod=%ld",
- Question->QstCod);
+ Question->Answer.NumOptions = Exa_DB_GetQstAnswersTextFromSet (&mysql_res,Question->QstCod);
/***** Check if number of rows is correct *****/
if (Question->Answer.NumOptions != 2)
@@ -1336,12 +1247,7 @@ static void ExaPrn_GetCorrectTF_AnswerFromDB (struct Tst_Question *Question)
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 exa_set_answers"
- " WHERE QstCod=%ld",
- Question->QstCod);
+ Question->Answer.NumOptions = Exa_DB_GetQstAnswersTextFromSet (&mysql_res,Question->QstCod);
/***** Check if number of rows is correct *****/
Tst_CheckIfNumberOfAnswersIsOne (Question);
@@ -1361,13 +1267,7 @@ static void ExaPrn_GetCorrectChoAnswerFromDB (struct Tst_Question *Question)
unsigned NumOpt;
/***** Query database *****/
- Question->Answer.NumOptions = (unsigned)
- DB_QuerySELECT (&mysql_res,"can not get answers of a question",
- "SELECT Correct" // row[0]
- " FROM exa_set_answers"
- " WHERE QstCod=%ld"
- " ORDER BY AnsInd",
- Question->QstCod);
+ Question->Answer.NumOptions = Exa_DB_GetQstAnswersCorrFromSet (&mysql_res,Question->QstCod);
for (NumOpt = 0;
NumOpt < Question->Answer.NumOptions;
NumOpt++)
@@ -1390,12 +1290,7 @@ static void ExaPrn_GetCorrectTxtAnswerFromDB (struct Tst_Question *Question)
unsigned NumOpt;
/***** Query database *****/
- Question->Answer.NumOptions = (unsigned)
- DB_QuerySELECT (&mysql_res,"can not get answers of a question",
- "SELECT Answer" // row[0]
- " FROM exa_set_answers"
- " WHERE QstCod=%ld",
- Question->QstCod);
+ Question->Answer.NumOptions = Exa_DB_GetQstAnswersTextFromSet (&mysql_res,Question->QstCod);
/***** Get text and correctness of answers for this question from database (one row per answer) *****/
for (NumOpt = 0;
@@ -1422,115 +1317,6 @@ static void ExaPrn_GetCorrectTxtAnswerFromDB (struct Tst_Question *Question)
DB_FreeMySQLResult (&mysql_res);
}
-/*****************************************************************************/
-/************* Get the questions of an exam print from database **************/
-/*****************************************************************************/
-
-static void ExaPrn_GetAnswerFromDB (struct ExaPrn_Print *Print,long QstCod,
- char StrAnswers[Tst_MAX_BYTES_ANSWERS_ONE_QST + 1])
- {
- MYSQL_RES *mysql_res;
- MYSQL_ROW row;
-
- /***** Get questions of an exam print from database *****/
- if (DB_QuerySELECT (&mysql_res,"can not get answer in an exam print",
- "SELECT Answers" // row[0]
- " FROM exa_print_questions"
- " WHERE PrnCod=%ld"
- " AND QstCod=%ld",
- Print->PrnCod,QstCod))
- {
- row = mysql_fetch_row (mysql_res);
-
- /* Get answers selected by user for this question (row[0]) */
- Str_Copy (StrAnswers,row[0],strlen (StrAnswers) - 1);
- }
- else
- StrAnswers[0] = '\0';
-
- /***** Free structure that stores the query result *****/
- DB_FreeMySQLResult (&mysql_res);
- }
-
-/*****************************************************************************/
-/************* Store user's answers of an test exam into database ************/
-/*****************************************************************************/
-
-static void ExaPrn_StoreOneQstOfPrintInDB (const struct ExaPrn_Print *Print,
- unsigned QstInd)
- {
- /***** Insert question and user's answers into database *****/
- Str_SetDecimalPointToUS (); // To print the floating point as a dot
- DB_QueryREPLACE ("can not update a question in an exam print",
- "REPLACE INTO exa_print_questions"
- " (PrnCod,QstCod,QstInd,SetCod,Score,Indexes,Answers)"
- " VALUES"
- " (%ld,%ld,%u,%ld,'%.15lg','%s','%s')",
- Print->PrnCod,
- Print->PrintedQuestions[QstInd].QstCod,
- QstInd, // 0, 1, 2, 3...
- Print->PrintedQuestions[QstInd].SetCod,
- Print->PrintedQuestions[QstInd].Score,
- Print->PrintedQuestions[QstInd].StrIndexes,
- Print->PrintedQuestions[QstInd].StrAnswers);
- Str_SetDecimalPointToLocal (); // Return to local system
- }
-
-/*****************************************************************************/
-/************ Get number of questions not blank in an exam print *************/
-/*****************************************************************************/
-
-static unsigned Exa_DB_GetNumQstsNotBlankInPrint (long PrnCod)
- {
- return (unsigned)
- DB_QueryCOUNT ("can not get number of questions not blank",
- "SELECT COUNT(*)"
- " FROM exa_print_questions"
- " WHERE PrnCod=%ld"
- " AND Answers<>''",
- PrnCod);
- }
-
-/*****************************************************************************/
-/************* Compute total score of questions of an exam print *************/
-/*****************************************************************************/
-
-static double Exa_DB_ComputeTotalScoreOfPrint (long PrnCod)
- {
- return DB_QuerySELECTDouble ("can not get score of exam print",
- "SELECT SUM(Score)"
- " FROM exa_print_questions"
- " WHERE PrnCod=%ld",
- PrnCod);
- }
-
-/*****************************************************************************/
-/********************** Update exam print in database ************************/
-/*****************************************************************************/
-
-static void Exa_DB_UpdatePrint (const struct ExaPrn_Print *Print)
- {
- /***** Update exam print in database *****/
- Str_SetDecimalPointToUS (); // To print the floating point as a dot
- DB_QueryUPDATE ("can not update exam print",
- "UPDATE exa_prints"
- " SET EndTime=NOW(),"
- "NumQstsNotBlank=%u,"
- "Sent='%c',"
- "Score='%.15lg'"
- " WHERE PrnCod=%ld"
- " AND SesCod=%ld"
- " AND UsrCod=%ld", // Extra checks
- Print->NumQsts.NotBlank,
- Print->Sent ? 'Y' :
- 'N',
- Print->Score,
- Print->PrnCod,
- Print->SesCod,
- Gbl.Usrs.Me.UsrDat.UsrCod);
- Str_SetDecimalPointToLocal (); // Return to local system
- }
-
/*****************************************************************************/
/********************** Remove exam prints made by a user ********************/
/*****************************************************************************/
@@ -1538,19 +1324,10 @@ static void Exa_DB_UpdatePrint (const struct ExaPrn_Print *Print)
void ExaPrn_RemovePrintsMadeByUsrInAllCrss (long UsrCod)
{
/***** Remove exam prints questions for the given user *****/
- DB_QueryDELETE ("can not remove exam prints made by a user",
- "DELETE FROM exa_print_questions"
- " USING exa_prints,"
- "exa_print_questions"
- " WHERE exa_prints.UsrCod=%ld"
- " AND exa_prints.PrnCod=exa_print_questions.PrnCod",
- UsrCod);
+ Exa_DB_RemovePrintQuestionsMadeByUsrInAllCrss (UsrCod);
/***** Remove exam prints made by the given user *****/
- DB_QueryDELETE ("can not remove exam prints made by a user",
- "DELETE FROM exa_prints"
- " WHERE UsrCod=%ld",
- UsrCod);
+ Exa_DB_RemovePrintsMadeByUsrInAllCrss (UsrCod);
}
/*****************************************************************************/
@@ -1560,32 +1337,10 @@ void ExaPrn_RemovePrintsMadeByUsrInAllCrss (long UsrCod)
void ExaPrn_RemovePrintsMadeByUsrInCrs (long UsrCod,long CrsCod)
{
/***** Remove questions of exams prints made by the given user in the given course *****/
- DB_QueryDELETE ("can not remove exams prints made by a user in a course",
- "DELETE FROM exa_print_questions"
- " USING exa_exams,"
- "exa_sessions,"
- "exa_prints,"
- "exa_print_questions"
- " WHERE exa_exams.CrsCod=%ld"
- " AND exa_exams.ExaCod=exa_sessions.ExaCod"
- " AND exa_sessions.SesCod=exa_prints.SesCod"
- " AND exa_prints.UsrCod=%ld"
- " AND exa_prints.PrnCod=exa_print_questions.PrnCod",
- CrsCod,
- UsrCod);
+ Exa_DB_RemovePrintsQuestionsMadeByUsrInCrs (UsrCod,CrsCod);
/***** Remove exams prints made by the given user in the given course *****/
- DB_QueryDELETE ("can not remove exams prints made by a user in a course",
- "DELETE FROM exa_prints"
- " USING exa_exams,"
- "exa_sessions,"
- "exa_prints"
- " WHERE exa_exams.CrsCod=%ld"
- " AND exa_exams.ExaCod=exa_sessions.ExaCod"
- " AND exa_sessions.SesCod=exa_prints.SesCod"
- " AND exa_prints.UsrCod=%ld",
- CrsCod,
- UsrCod);
+ Exa_DB_RemovePrintsMadeByUsrInCrs (UsrCod,CrsCod);
}
/*****************************************************************************/
@@ -1595,26 +1350,8 @@ void ExaPrn_RemovePrintsMadeByUsrInCrs (long UsrCod,long CrsCod)
void ExaPrn_RemoveCrsPrints (long CrsCod)
{
/***** Remove questions of exams prints made by the given user in the given course *****/
- DB_QueryDELETE ("can not remove exams prints in a course",
- "DELETE FROM exa_print_questions"
- " USING exa_exams,"
- "exa_sessions,"
- "exa_prints,"
- "exa_print_questions"
- " WHERE exa_exams.CrsCod=%ld"
- " AND exa_exams.ExaCod=exa_sessions.ExaCod"
- " AND exa_sessions.SesCod=exa_prints.SesCod"
- " AND exa_prints.PrnCod=exa_print_questions.PrnCod",
- CrsCod);
+ Exa_DB_RemovePrintQuestionsInCrs (CrsCod);
/***** Remove exams prints made by the given user in the given course *****/
- DB_QueryDELETE ("can not remove exams prints in a course",
- "DELETE FROM exa_prints"
- " USING exa_exams,"
- "exa_sessions,"
- "exa_prints"
- " WHERE exa_exams.CrsCod=%ld"
- " AND exa_exams.ExaCod=exa_sessions.ExaCod"
- " AND exa_sessions.SesCod=exa_prints.SesCod",
- CrsCod);
+ Exa_DB_RemovePrintsInCrs (CrsCod);
}