From 1f178d96cbae9828f12a9cdac0b0ec7312fe9e11 Mon Sep 17 00:00:00 2001 From: acanas Date: Thu, 9 Sep 2021 18:11:46 +0200 Subject: [PATCH] Version 20.96.7: Sep 09, 2021 Queries moved to module swad_exam_database. --- swad_changelog.h | 3 +- swad_exam.c | 382 +++--------------------------------------- swad_exam.h | 4 - swad_exam_database.c | 390 +++++++++++++++++++++++++++++++++++++++++++ swad_exam_database.h | 21 +++ 5 files changed, 434 insertions(+), 366 deletions(-) diff --git a/swad_changelog.h b/swad_changelog.h index d451db4d..2a65ccb8 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.96.6 (2021-09-09)" +#define Log_PLATFORM_VERSION "SWAD 20.96.7 (2021-09-09)" #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.96.7: Sep 09, 2021 Queries moved to module swad_exam_database. (314527 lines) Version 20.96.6: Sep 09, 2021 Queries moved to module swad_exam_database. (314471 lines) Version 20.96.5: Sep 09, 2021 Queries moved to module swad_exam_database. (314448 lines) Version 20.96.4: Sep 08, 2021 Queries moved to module swad_exam_database. (314414 lines) diff --git a/swad_exam.c b/swad_exam.c index 911cab11..74158867 100644 --- a/swad_exam.c +++ b/swad_exam.c @@ -142,7 +142,7 @@ static void Exa_RemoveAllMedFilesFromStemOfAllQstsFromCrs (long CrsCod); static void Exa_RemoveAllMedFilesFromAnsOfAllQstsFromExam (long ExaCod); static void Exa_RemoveAllMedFilesFromAnsOfAllQstsFromCrs (long CrsCod); -static bool Exa_DB_CheckIfSimilarExamExists (const struct Exa_Exam *Exam); +static void Exa_HideUnhideExam (bool Hide); static void Exa_ReceiveExamFieldsFromForm (struct Exa_Exam *Exam, char Txt[Cns_MAX_BYTES_TEXT + 1]); @@ -1142,15 +1142,8 @@ static void Exa_RemoveAllMedFilesFromStemOfAllQstsFromExam (long ExaCod) MYSQL_RES *mysql_res; unsigned NumMedia; - /***** Get media codes associated to stems of an exam questions from database *****/ - NumMedia = (unsigned) - DB_QuerySELECT (&mysql_res,"can not get media", - "SELECT exa_set_questions.MedCod" - " FROM exa_sets," - "exa_set_questions" - " WHERE exa_sets.ExaCod=%ld" - " AND exa_sets.SetCod=exa_set_questions.SetCod", - ExaCod); + /***** Get media codes associated to stems of an exam questions *****/ + NumMedia = Exa_DB_GetAllMediaFomStemOfAllQstsFromExam (&mysql_res,ExaCod); /***** Go over result removing media files *****/ Med_RemoveMediaFromAllRows (NumMedia,mysql_res); @@ -1169,16 +1162,7 @@ static void Exa_RemoveAllMedFilesFromStemOfAllQstsFromCrs (long CrsCod) unsigned NumMedia; /***** Get media codes associated to stems of exam questions from database *****/ - NumMedia = (unsigned) - DB_QuerySELECT (&mysql_res,"can not get media", - "SELECT exa_set_questions.MedCod" - " FROM exa_exams," - "exa_sets," - "exa_set_questions" - " WHERE exa_exams.CrsCod=%ld" - " AND exa_exams.ExaCod=exa_sets.ExaCod" - " AND exa_sets.SetCod=exa_set_questions.SetCod", - CrsCod); + NumMedia = Exa_DB_GetAllMediaFomStemOfAllQstsFromCrs (&mysql_res,CrsCod); /***** Go over result removing media files *****/ Med_RemoveMediaFromAllRows (NumMedia,mysql_res); @@ -1197,16 +1181,7 @@ static void Exa_RemoveAllMedFilesFromAnsOfAllQstsFromExam (long ExaCod) unsigned NumMedia; /***** Get names of media files associated to answers of exam questions from database *****/ - NumMedia = (unsigned) - DB_QuerySELECT (&mysql_res,"can not get media", - "SELECT exa_set_answers.MedCod" - " FROM exa_sets," - "exa_set_questions," - "exa_set_answers" - " WHERE exa_sets.ExaCod=%ld" - " AND exa_sets.SetCod=exa_set_questions.SetCod" - " AND exa_set_questions.QstCod=exa_set_answers.QstCod", - ExaCod); + NumMedia = Exa_DB_GetAllMediaFromAnsOfAllQstsFromExam (&mysql_res,ExaCod); /***** Go over result removing media files *****/ Med_RemoveMediaFromAllRows (NumMedia,mysql_res); @@ -1225,18 +1200,7 @@ static void Exa_RemoveAllMedFilesFromAnsOfAllQstsFromCrs (long CrsCod) unsigned NumMedia; /***** Get names of media files associated to answers of exam questions from database *****/ - NumMedia = (unsigned) - DB_QuerySELECT (&mysql_res,"can not get media", - "SELECT exa_set_answers.MedCod" - " FROM exa_exams," - "exa_sets," - "exa_set_questions," - "exa_set_answers" - " WHERE exa_exams.CrsCod=%ld" - " AND exa_exams.ExaCod=exa_sets.ExaCod" - " AND exa_sets.SetCod=exa_set_questions.SetCod" - " AND exa_set_questions.QstCod=exa_set_answers.QstCod", - CrsCod); + NumMedia = Exa_DB_GetAllMediaFromAnsOfAllQstsFromCrs (&mysql_res,CrsCod); /***** Go over result removing media files *****/ Med_RemoveMediaFromAllRows (NumMedia,mysql_res); @@ -1251,36 +1215,7 @@ static void Exa_RemoveAllMedFilesFromAnsOfAllQstsFromCrs (long CrsCod) void Exa_HideExam (void) { - struct Exa_Exams Exams; - struct Exa_Exam Exam; - - /***** Check if I can edit exams *****/ - if (!Exa_CheckIfICanEditExams ()) - Err_NoPermissionExit (); - - /***** Reset exams context *****/ - Exa_ResetExams (&Exams); - Exa_ResetExam (&Exam); - - /***** Get parameters *****/ - Exa_GetParams (&Exams); - if (Exams.ExaCod <= 0) - Err_WrongExamExit (); - Exam.ExaCod = Exams.ExaCod; - - /***** Get data of the exam from database *****/ - Exa_GetDataOfExamByCod (&Exam); - Exams.ExaCod = Exam.ExaCod; - - /***** Hide exam *****/ - DB_QueryUPDATE ("can not hide exam", - "UPDATE exa_exams" - " SET Hidden='Y'" - " WHERE ExaCod=%ld", - Exam.ExaCod); - - /***** Show exams again *****/ - Exa_ListAllExams (&Exams); + Exa_HideUnhideExam (true); } /*****************************************************************************/ @@ -1288,6 +1223,15 @@ void Exa_HideExam (void) /*****************************************************************************/ void Exa_UnhideExam (void) + { + Exa_HideUnhideExam (false); + } + +/*****************************************************************************/ +/******************************* Unhide an exam ******************************/ +/*****************************************************************************/ + +static void Exa_HideUnhideExam (bool Hide) { struct Exa_Exams Exams; struct Exa_Exam Exam; @@ -1311,34 +1255,12 @@ void Exa_UnhideExam (void) Exams.ExaCod = Exam.ExaCod; /***** Unhide exam *****/ - DB_QueryUPDATE ("can not unhide exam", - "UPDATE exa_exams" - " SET Hidden='N'" - " WHERE ExaCod=%ld", - Exam.ExaCod); + Exa_DB_HideUnhideExam (Exam.ExaCod,Hide); /***** Show exams again *****/ Exa_ListAllExams (&Exams); } -/*****************************************************************************/ -/******************* Check if the title of an exam exists *******************/ -/*****************************************************************************/ - -static bool Exa_DB_CheckIfSimilarExamExists (const struct Exa_Exam *Exam) - { - /***** Get number of exams with a field value from database *****/ - return (DB_QueryCOUNT ("can not get similar exams", - "SELECT COUNT(*)" - " FROM exa_exams" - " WHERE CrsCod=%ld" - " AND Title='%s'" - " AND ExaCod<>%ld", - Gbl.Hierarchy.Crs.CrsCod, - Exam->Title, - Exam->ExaCod) != 0); - } - /*****************************************************************************/ /**************** Request the creation or edition of an exam ******************/ /*****************************************************************************/ @@ -1603,7 +1525,8 @@ static bool Exa_CheckExamFieldsReceivedFromForm (const struct Exa_Exam *Exam) if (Exam->Title[0]) // If there's an exam title { /* If title of exam was in database... */ - if (Exa_DB_CheckIfSimilarExamExists (Exam)) + if (Exa_DB_CheckIfSimilarExamExists (Gbl.Hierarchy.Crs.CrsCod, + Exam->ExaCod,Exam->Title)) { NewExamIsCorrect = false; Ale_ShowAlert (Ale_WARNING,Txt_Already_existed_an_exam_with_the_title_X, @@ -1628,22 +1551,7 @@ static void Exa_CreateExam (struct Exa_Exam *Exam,const char *Txt) extern const char *Txt_Created_new_exam_X; /***** Create a new exam *****/ - Str_SetDecimalPointToUS (); // To write the decimal point as a dot - Exam->ExaCod = - DB_QueryINSERTandReturnCode ("can not create new exam", - "INSERT INTO exa_exams" - " (CrsCod,Hidden,UsrCod,MaxGrade,Visibility," - "Title,Txt)" - " VALUES" - " (%ld,'N',%ld,%.15lg,%u," - "'%s','%s')", - Gbl.Hierarchy.Crs.CrsCod, - Gbl.Usrs.Me.UsrDat.UsrCod, - Exam->MaxGrade, - Exam->Visibility, - Exam->Title, - Txt); - Str_SetDecimalPointToLocal (); // Return to local system + Exam->ExaCod = Exa_DB_CreateExam (Exam,Txt); /***** Write success message *****/ Ale_ShowAlert (Ale_SUCCESS,Txt_Created_new_exam_X, @@ -1659,22 +1567,7 @@ static void Exa_UpdateExam (struct Exa_Exam *Exam,const char *Txt) extern const char *Txt_The_exam_has_been_modified; /***** Update the data of the exam *****/ - Str_SetDecimalPointToUS (); // To write the decimal point as a dot - DB_QueryUPDATE ("can not update exam", - "UPDATE exa_exams" - " SET CrsCod=%ld," - "MaxGrade=%.15lg," - "Visibility=%u," - "Title='%s'," - "Txt='%s'" - " WHERE ExaCod=%ld", - Gbl.Hierarchy.Crs.CrsCod, - Exam->MaxGrade, - Exam->Visibility, - Exam->Title, - Txt, - Exam->ExaCod); - Str_SetDecimalPointToLocal (); // Return to local system + Exa_DB_UpdateExam (Exam,Txt); /***** Write success message *****/ Ale_ShowAlert (Ale_SUCCESS,Txt_The_exam_has_been_modified); @@ -1693,236 +1586,3 @@ bool Exa_CheckIfEditable (const struct Exa_Exam *Exam) else return false; // Questions are not editable } - -/*****************************************************************************/ -/********************* Get number of courses with exams **********************/ -/*****************************************************************************/ -// Returns the number of courses with exams in this location - -unsigned Exa_DB_GetNumCoursesWithExams (HieLvl_Level_t Scope) - { - /***** Get number of courses with exams from database *****/ - switch (Scope) - { - case HieLvl_SYS: - return DB_QueryCOUNT ("can not get number of courses with exams", - "SELECT COUNT(DISTINCT CrsCod)" - " FROM exa_exams"); - case HieLvl_CTY: - return DB_QueryCOUNT ("can not get number of courses with exams", - "SELECT COUNT(DISTINCT exa_exams.CrsCod)" - " FROM ins_instits," - "ctr_centers," - "deg_degrees," - "crs_courses," - "exa_exams" - " WHERE ins_instits.CtyCod=%ld" - " AND ins_instits.InsCod=ctr_centers.InsCod" - " AND ctr_centers.CtrCod=deg_degrees.CtrCod" - " AND deg_degrees.DegCod=crs_courses.DegCod" - " AND crs_courses.CrsCod=exa_exams.CrsCod", - Gbl.Hierarchy.Ins.InsCod); - case HieLvl_INS: - return DB_QueryCOUNT ("can not get number of courses with exams", - "SELECT COUNT(DISTINCT exa_exams.CrsCod)" - " FROM ctr_centers," - "deg_degrees," - "crs_courses," - "exa_exams" - " WHERE ctr_centers.InsCod=%ld" - " AND ctr_centers.CtrCod=deg_degrees.CtrCod" - " AND deg_degrees.DegCod=crs_courses.DegCod" - " AND crs_courses.CrsCod=exa_exams.CrsCod", - Gbl.Hierarchy.Ins.InsCod); - case HieLvl_CTR: - return DB_QueryCOUNT ("can not get number of courses with exams", - "SELECT COUNT(DISTINCT exa_exams.CrsCod)" - " FROM deg_degrees," - "crs_courses," - "exa_exams" - " WHERE deg_degrees.CtrCod=%ld" - " AND deg_degrees.DegCod=crs_courses.DegCod" - " AND crs_courses.CrsCod=exa_exams.CrsCod", - Gbl.Hierarchy.Ctr.CtrCod); - case HieLvl_DEG: - return DB_QueryCOUNT ("can not get number of courses with exams", - "SELECT COUNT(DISTINCT exa_exams.CrsCod)" - " FROM crs_courses," - "exa_exams" - " WHERE crs_courses.DegCod=%ld" - " AND crs_courses.CrsCod=exa_exams.CrsCod", - Gbl.Hierarchy.Deg.DegCod); - case HieLvl_CRS: - return DB_QueryCOUNT ("can not get number of courses with exams", - "SELECT COUNT(DISTINCT CrsCod)" - " FROM exa_exams" - " WHERE CrsCod=%ld", - Gbl.Hierarchy.Crs.CrsCod); - default: - Err_WrongScopeExit (); - return 0; // Not reached - } - } - -/*****************************************************************************/ -/**************************** Get number of exams ****************************/ -/*****************************************************************************/ -// Returns the number of exams in this location - -unsigned Exa_DB_GetNumExams (HieLvl_Level_t Scope) - { - /***** Get number of exams from database *****/ - switch (Scope) - { - case HieLvl_SYS: - return DB_QueryCOUNT ("can not get number of exams", - "SELECT COUNT(*)" - " FROM exa_exams"); - case HieLvl_CTY: - return DB_QueryCOUNT ("can not get number of exams", - "SELECT COUNT(*)" - " FROM ins_instits," - "ctr_centers," - "deg_degrees," - "crs_courses," - "exa_exams" - " WHERE ins_instits.CtyCod=%ld" - " AND ins_instits.InsCod=ctr_centers.InsCod" - " AND ctr_centers.CtrCod=deg_degrees.CtrCod" - " AND deg_degrees.DegCod=crs_courses.DegCod" - " AND crs_courses.CrsCod=exa_exams.CrsCod", - Gbl.Hierarchy.Cty.CtyCod); - case HieLvl_INS: - return DB_QueryCOUNT ("can not get number of exams", - "SELECT COUNT(*)" - " FROM ctr_centers," - "deg_degrees," - "crs_courses," - "exa_exams" - " WHERE ctr_centers.InsCod=%ld" - " AND ctr_centers.CtrCod=deg_degrees.CtrCod" - " AND deg_degrees.DegCod=crs_courses.DegCod" - " AND crs_courses.CrsCod=exa_exams.CrsCod", - Gbl.Hierarchy.Ins.InsCod); - case HieLvl_CTR: - return DB_QueryCOUNT ("can not get number of exams", - "SELECT COUNT(*)" - " FROM deg_degrees," - "crs_courses," - "exa_exams" - " WHERE deg_degrees.CtrCod=%ld" - " AND deg_degrees.DegCod=crs_courses.DegCod" - " AND crs_courses.CrsCod=exa_exams.CrsCod", - Gbl.Hierarchy.Ctr.CtrCod); - case HieLvl_DEG: - return DB_QueryCOUNT ("can not get number of exams", - "SELECT COUNT(*)" - " FROM crs_courses," - "exa_exams" - " WHERE crs_courses.DegCod=%ld" - " AND crs_courses.CrsCod=exa_exams.CrsCod", - Gbl.Hierarchy.Deg.DegCod); - case HieLvl_CRS: - return DB_QueryCOUNT ("can not get number of exams", - "SELECT COUNT(*)" - " FROM exa_exams" - " WHERE CrsCod=%ld", - Gbl.Hierarchy.Crs.CrsCod); - default: - Err_WrongScopeExit (); - return 0; // Not reached - } - } - -/*****************************************************************************/ -/************* Get average number of questions per course exam ***************/ -/*****************************************************************************/ - -double Exa_DB_GetNumQstsPerCrsExam (HieLvl_Level_t Scope) - { - /***** Get number of questions per exam from database *****/ - switch (Scope) - { - case HieLvl_SYS: - return DB_QuerySELECTDouble ("can not get number of questions per exam", - "SELECT AVG(NumQsts)" - " FROM (SELECT COUNT(exa_set_questions.QstCod) AS NumQsts" - " FROM exa_exams," - "exa_set_questions" - " WHERE exa_exams.ExaCod=exa_set_questions.ExaCod" - " GROUP BY exa_set_questions.ExaCod) AS NumQstsTable"); - case HieLvl_CTY: - return DB_QuerySELECTDouble ("can not get number of questions per exam", - "SELECT AVG(NumQsts)" - " FROM (SELECT COUNT(exa_set_questions.QstCod) AS NumQsts" - " FROM ins_instits," - "ctr_centers," - "deg_degrees," - "crs_courses," - "exa_exams," - "exa_set_questions" - " WHERE ins_instits.CtyCod=%ld" - " AND ins_instits.InsCod=ctr_centers.InsCod" - " AND ctr_centers.CtrCod=deg_degrees.CtrCod" - " AND deg_degrees.DegCod=crs_courses.DegCod" - " AND crs_courses.CrsCod=exa_exams.CrsCod" - " AND exa_exams.ExaCod=exa_set_questions.ExaCod" - " GROUP BY exa_set_questions.ExaCod) AS NumQstsTable", - Gbl.Hierarchy.Cty.CtyCod); - case HieLvl_INS: - return DB_QuerySELECTDouble ("can not get number of questions per exam", - "SELECT AVG(NumQsts)" - " FROM (SELECT COUNT(exa_set_questions.QstCod) AS NumQsts" - " FROM ctr_centers," - "deg_degrees," - "crs_courses," - "exa_exams," - "exa_set_questions" - " WHERE ctr_centers.InsCod=%ld" - " AND ctr_centers.CtrCod=deg_degrees.CtrCod" - " AND deg_degrees.DegCod=crs_courses.DegCod" - " AND crs_courses.CrsCod=exa_exams.CrsCod" - " AND exa_exams.ExaCod=exa_set_questions.ExaCod" - " GROUP BY exa_set_questions.ExaCod) AS NumQstsTable", - Gbl.Hierarchy.Ins.InsCod); - case HieLvl_CTR: - return DB_QuerySELECTDouble ("can not get number of questions per exam", - "SELECT AVG(NumQsts)" - " FROM (SELECT COUNT(exa_set_questions.QstCod) AS NumQsts" - " FROM deg_degrees," - "crs_courses," - "exa_exams," - "exa_set_questions" - " WHERE deg_degrees.CtrCod=%ld" - " AND deg_degrees.DegCod=crs_courses.DegCod" - " AND crs_courses.CrsCod=exa_exams.CrsCod" - " AND exa_exams.ExaCod=exa_set_questions.ExaCod" - " GROUP BY exa_set_questions.ExaCod) AS NumQstsTable", - Gbl.Hierarchy.Ctr.CtrCod); - case HieLvl_DEG: - return DB_QuerySELECTDouble ("can not get number of questions per exam", - "SELECT AVG(NumQsts)" - " FROM (SELECT COUNT(exa_set_questions.QstCod) AS NumQsts" - " FROM crs_courses," - "exa_exams," - "exa_set_questions" - " WHERE crs_courses.DegCod=%ld" - " AND crs_courses.CrsCod=exa_exams.CrsCod" - " AND exa_exams.ExaCod=exa_set_questions.ExaCod" - " GROUP BY exa_set_questions.ExaCod) AS NumQstsTable", - Gbl.Hierarchy.Deg.DegCod); - case HieLvl_CRS: - return DB_QuerySELECTDouble ("can not get number of questions per exam", - "SELECT AVG(NumQsts)" - " FROM (SELECT COUNT(exa_set_questions.QstCod) AS NumQsts" - " FROM exa_exams," - "exa_set_questions" - " WHERE exa_exams.Cod=%ld" - " AND exa_exams.ExaCod=exa_set_questions.ExaCod" - " GROUP BY exa_set_questions.ExaCod) AS NumQstsTable", - Gbl.Hierarchy.Crs.CrsCod); - default: - Err_WrongScopeExit (); - return 0.0; // Not reached - } - } diff --git a/swad_exam.h b/swad_exam.h index 90cdffb7..ffccc86e 100644 --- a/swad_exam.h +++ b/swad_exam.h @@ -89,8 +89,4 @@ void Exa_ReceiveFormExam (void); bool Exa_CheckIfEditable (const struct Exa_Exam *Exam); -unsigned Exa_DB_GetNumCoursesWithExams (HieLvl_Level_t Scope); -unsigned Exa_DB_GetNumExams (HieLvl_Level_t Scope); -double Exa_DB_GetNumQstsPerCrsExam (HieLvl_Level_t Scope); - #endif diff --git a/swad_exam_database.c b/swad_exam_database.c index b9a37960..9040d3e1 100644 --- a/swad_exam_database.c +++ b/swad_exam_database.c @@ -60,6 +60,74 @@ extern struct Globals Gbl; static void Exa_DB_RemoveUsrSesResultsInCrs (long UsrCod,long CrsCod,const char *TableName); + +/*****************************************************************************/ +/**************************** Create a new exam ******************************/ +/*****************************************************************************/ + +long Exa_DB_CreateExam (const struct Exa_Exam *Exam,const char *Txt) + { + long ExaCod; + + Str_SetDecimalPointToUS (); // To write the decimal point as a dot + ExaCod = + DB_QueryINSERTandReturnCode ("can not create new exam", + "INSERT INTO exa_exams" + " (CrsCod,Hidden,UsrCod,MaxGrade,Visibility," + "Title,Txt)" + " VALUES" + " (%ld,'N',%ld,%.15lg,%u," + "'%s','%s')", + Gbl.Hierarchy.Crs.CrsCod, + Gbl.Usrs.Me.UsrDat.UsrCod, + Exam->MaxGrade, + Exam->Visibility, + Exam->Title, + Txt); + Str_SetDecimalPointToLocal (); // Return to local system + + return ExaCod; + } + +/*****************************************************************************/ +/************************* Update an existing exam *************************/ +/*****************************************************************************/ + +void Exa_DB_UpdateExam (const struct Exa_Exam *Exam,const char *Txt) + { + Str_SetDecimalPointToUS (); // To write the decimal point as a dot + DB_QueryUPDATE ("can not update exam", + "UPDATE exa_exams" + " SET CrsCod=%ld," + "MaxGrade=%.15lg," + "Visibility=%u," + "Title='%s'," + "Txt='%s'" + " WHERE ExaCod=%ld", + Gbl.Hierarchy.Crs.CrsCod, + Exam->MaxGrade, + Exam->Visibility, + Exam->Title, + Txt, + Exam->ExaCod); + Str_SetDecimalPointToLocal (); // Return to local system + } + +/*****************************************************************************/ +/***************************** Hide/unhide exam ******************************/ +/*****************************************************************************/ + +void Exa_DB_HideUnhideExam (long ExaCod,bool Hide) + { + DB_QueryUPDATE ("can not hide exam", + "UPDATE exa_exams" + " SET Hidden='%c'" + " WHERE ExaCod=%ld", + Hide ? 'Y' : + 'N', + ExaCod); + } + /*****************************************************************************/ /*********************** Get list of all the exams *************************/ /*****************************************************************************/ @@ -168,6 +236,256 @@ void Exa_DB_GetExamTxt (long ExaCod,char Txt[Cns_MAX_BYTES_TEXT + 1]) ExaCod); } +/*****************************************************************************/ +/******************* Check if the title of an exam exists ********************/ +/*****************************************************************************/ + +bool Exa_DB_CheckIfSimilarExamExists (long CrsCod,long ExaCod,const char *Title) + { + return (DB_QueryCOUNT ("can not get similar exams", + "SELECT COUNT(*)" + " FROM exa_exams" + " WHERE CrsCod=%ld" + " AND Title='%s'" + " AND ExaCod<>%ld", + CrsCod, + Title, + ExaCod) != 0); + } + +/*****************************************************************************/ +/********************* Get number of courses with exams **********************/ +/*****************************************************************************/ +// Returns the number of courses with exams in this location + +unsigned Exa_DB_GetNumCoursesWithExams (HieLvl_Level_t Scope) + { + /***** Get number of courses with exams from database *****/ + switch (Scope) + { + case HieLvl_SYS: + return DB_QueryCOUNT ("can not get number of courses with exams", + "SELECT COUNT(DISTINCT CrsCod)" + " FROM exa_exams"); + case HieLvl_CTY: + return DB_QueryCOUNT ("can not get number of courses with exams", + "SELECT COUNT(DISTINCT exa_exams.CrsCod)" + " FROM ins_instits," + "ctr_centers," + "deg_degrees," + "crs_courses," + "exa_exams" + " WHERE ins_instits.CtyCod=%ld" + " AND ins_instits.InsCod=ctr_centers.InsCod" + " AND ctr_centers.CtrCod=deg_degrees.CtrCod" + " AND deg_degrees.DegCod=crs_courses.DegCod" + " AND crs_courses.CrsCod=exa_exams.CrsCod", + Gbl.Hierarchy.Ins.InsCod); + case HieLvl_INS: + return DB_QueryCOUNT ("can not get number of courses with exams", + "SELECT COUNT(DISTINCT exa_exams.CrsCod)" + " FROM ctr_centers," + "deg_degrees," + "crs_courses," + "exa_exams" + " WHERE ctr_centers.InsCod=%ld" + " AND ctr_centers.CtrCod=deg_degrees.CtrCod" + " AND deg_degrees.DegCod=crs_courses.DegCod" + " AND crs_courses.CrsCod=exa_exams.CrsCod", + Gbl.Hierarchy.Ins.InsCod); + case HieLvl_CTR: + return DB_QueryCOUNT ("can not get number of courses with exams", + "SELECT COUNT(DISTINCT exa_exams.CrsCod)" + " FROM deg_degrees," + "crs_courses," + "exa_exams" + " WHERE deg_degrees.CtrCod=%ld" + " AND deg_degrees.DegCod=crs_courses.DegCod" + " AND crs_courses.CrsCod=exa_exams.CrsCod", + Gbl.Hierarchy.Ctr.CtrCod); + case HieLvl_DEG: + return DB_QueryCOUNT ("can not get number of courses with exams", + "SELECT COUNT(DISTINCT exa_exams.CrsCod)" + " FROM crs_courses," + "exa_exams" + " WHERE crs_courses.DegCod=%ld" + " AND crs_courses.CrsCod=exa_exams.CrsCod", + Gbl.Hierarchy.Deg.DegCod); + case HieLvl_CRS: + return DB_QueryCOUNT ("can not get number of courses with exams", + "SELECT COUNT(DISTINCT CrsCod)" + " FROM exa_exams" + " WHERE CrsCod=%ld", + Gbl.Hierarchy.Crs.CrsCod); + default: + Err_WrongScopeExit (); + return 0; // Not reached + } + } + +/*****************************************************************************/ +/**************************** Get number of exams ****************************/ +/*****************************************************************************/ +// Returns the number of exams in this location + +unsigned Exa_DB_GetNumExams (HieLvl_Level_t Scope) + { + /***** Get number of exams from database *****/ + switch (Scope) + { + case HieLvl_SYS: + return DB_QueryCOUNT ("can not get number of exams", + "SELECT COUNT(*)" + " FROM exa_exams"); + case HieLvl_CTY: + return DB_QueryCOUNT ("can not get number of exams", + "SELECT COUNT(*)" + " FROM ins_instits," + "ctr_centers," + "deg_degrees," + "crs_courses," + "exa_exams" + " WHERE ins_instits.CtyCod=%ld" + " AND ins_instits.InsCod=ctr_centers.InsCod" + " AND ctr_centers.CtrCod=deg_degrees.CtrCod" + " AND deg_degrees.DegCod=crs_courses.DegCod" + " AND crs_courses.CrsCod=exa_exams.CrsCod", + Gbl.Hierarchy.Cty.CtyCod); + case HieLvl_INS: + return DB_QueryCOUNT ("can not get number of exams", + "SELECT COUNT(*)" + " FROM ctr_centers," + "deg_degrees," + "crs_courses," + "exa_exams" + " WHERE ctr_centers.InsCod=%ld" + " AND ctr_centers.CtrCod=deg_degrees.CtrCod" + " AND deg_degrees.DegCod=crs_courses.DegCod" + " AND crs_courses.CrsCod=exa_exams.CrsCod", + Gbl.Hierarchy.Ins.InsCod); + case HieLvl_CTR: + return DB_QueryCOUNT ("can not get number of exams", + "SELECT COUNT(*)" + " FROM deg_degrees," + "crs_courses," + "exa_exams" + " WHERE deg_degrees.CtrCod=%ld" + " AND deg_degrees.DegCod=crs_courses.DegCod" + " AND crs_courses.CrsCod=exa_exams.CrsCod", + Gbl.Hierarchy.Ctr.CtrCod); + case HieLvl_DEG: + return DB_QueryCOUNT ("can not get number of exams", + "SELECT COUNT(*)" + " FROM crs_courses," + "exa_exams" + " WHERE crs_courses.DegCod=%ld" + " AND crs_courses.CrsCod=exa_exams.CrsCod", + Gbl.Hierarchy.Deg.DegCod); + case HieLvl_CRS: + return DB_QueryCOUNT ("can not get number of exams", + "SELECT COUNT(*)" + " FROM exa_exams" + " WHERE CrsCod=%ld", + Gbl.Hierarchy.Crs.CrsCod); + default: + Err_WrongScopeExit (); + return 0; // Not reached + } + } + +/*****************************************************************************/ +/************* Get average number of questions per course exam ***************/ +/*****************************************************************************/ + +double Exa_DB_GetNumQstsPerCrsExam (HieLvl_Level_t Scope) + { + /***** Get number of questions per exam from database *****/ + switch (Scope) + { + case HieLvl_SYS: + return DB_QuerySELECTDouble ("can not get number of questions per exam", + "SELECT AVG(NumQsts)" + " FROM (SELECT COUNT(exa_set_questions.QstCod) AS NumQsts" + " FROM exa_exams," + "exa_set_questions" + " WHERE exa_exams.ExaCod=exa_set_questions.ExaCod" + " GROUP BY exa_set_questions.ExaCod) AS NumQstsTable"); + case HieLvl_CTY: + return DB_QuerySELECTDouble ("can not get number of questions per exam", + "SELECT AVG(NumQsts)" + " FROM (SELECT COUNT(exa_set_questions.QstCod) AS NumQsts" + " FROM ins_instits," + "ctr_centers," + "deg_degrees," + "crs_courses," + "exa_exams," + "exa_set_questions" + " WHERE ins_instits.CtyCod=%ld" + " AND ins_instits.InsCod=ctr_centers.InsCod" + " AND ctr_centers.CtrCod=deg_degrees.CtrCod" + " AND deg_degrees.DegCod=crs_courses.DegCod" + " AND crs_courses.CrsCod=exa_exams.CrsCod" + " AND exa_exams.ExaCod=exa_set_questions.ExaCod" + " GROUP BY exa_set_questions.ExaCod) AS NumQstsTable", + Gbl.Hierarchy.Cty.CtyCod); + case HieLvl_INS: + return DB_QuerySELECTDouble ("can not get number of questions per exam", + "SELECT AVG(NumQsts)" + " FROM (SELECT COUNT(exa_set_questions.QstCod) AS NumQsts" + " FROM ctr_centers," + "deg_degrees," + "crs_courses," + "exa_exams," + "exa_set_questions" + " WHERE ctr_centers.InsCod=%ld" + " AND ctr_centers.CtrCod=deg_degrees.CtrCod" + " AND deg_degrees.DegCod=crs_courses.DegCod" + " AND crs_courses.CrsCod=exa_exams.CrsCod" + " AND exa_exams.ExaCod=exa_set_questions.ExaCod" + " GROUP BY exa_set_questions.ExaCod) AS NumQstsTable", + Gbl.Hierarchy.Ins.InsCod); + case HieLvl_CTR: + return DB_QuerySELECTDouble ("can not get number of questions per exam", + "SELECT AVG(NumQsts)" + " FROM (SELECT COUNT(exa_set_questions.QstCod) AS NumQsts" + " FROM deg_degrees," + "crs_courses," + "exa_exams," + "exa_set_questions" + " WHERE deg_degrees.CtrCod=%ld" + " AND deg_degrees.DegCod=crs_courses.DegCod" + " AND crs_courses.CrsCod=exa_exams.CrsCod" + " AND exa_exams.ExaCod=exa_set_questions.ExaCod" + " GROUP BY exa_set_questions.ExaCod) AS NumQstsTable", + Gbl.Hierarchy.Ctr.CtrCod); + case HieLvl_DEG: + return DB_QuerySELECTDouble ("can not get number of questions per exam", + "SELECT AVG(NumQsts)" + " FROM (SELECT COUNT(exa_set_questions.QstCod) AS NumQsts" + " FROM crs_courses," + "exa_exams," + "exa_set_questions" + " WHERE crs_courses.DegCod=%ld" + " AND crs_courses.CrsCod=exa_exams.CrsCod" + " AND exa_exams.ExaCod=exa_set_questions.ExaCod" + " GROUP BY exa_set_questions.ExaCod) AS NumQstsTable", + Gbl.Hierarchy.Deg.DegCod); + case HieLvl_CRS: + return DB_QuerySELECTDouble ("can not get number of questions per exam", + "SELECT AVG(NumQsts)" + " FROM (SELECT COUNT(exa_set_questions.QstCod) AS NumQsts" + " FROM exa_exams," + "exa_set_questions" + " WHERE exa_exams.Cod=%ld" + " AND exa_exams.ExaCod=exa_set_questions.ExaCod" + " GROUP BY exa_set_questions.ExaCod) AS NumQstsTable", + Gbl.Hierarchy.Crs.CrsCod); + default: + Err_WrongScopeExit (); + return 0.0; // Not reached + } + } + /*****************************************************************************/ /********************************* Remove exam *******************************/ /*****************************************************************************/ @@ -713,6 +1031,40 @@ unsigned Exa_DB_GetMediaFromStemOfQst (MYSQL_RES **mysql_res,long QstCod,long Se SetCod); } +/*****************************************************************************/ +/********* Get media codes associated to stems of an exam questions **********/ +/*****************************************************************************/ + +unsigned Exa_DB_GetAllMediaFomStemOfAllQstsFromExam (MYSQL_RES **mysql_res,long ExaCod) + { + return (unsigned) + DB_QuerySELECT (mysql_res,"can not get media", + "SELECT exa_set_questions.MedCod" + " FROM exa_sets," + "exa_set_questions" + " WHERE exa_sets.ExaCod=%ld" + " AND exa_sets.SetCod=exa_set_questions.SetCod", + ExaCod); + } + +/*****************************************************************************/ +/*** Get media codes associated to stems of all exam questions in a course ***/ +/*****************************************************************************/ + +unsigned Exa_DB_GetAllMediaFomStemOfAllQstsFromCrs (MYSQL_RES **mysql_res,long CrsCod) + { + return (unsigned) + DB_QuerySELECT (mysql_res,"can not get media", + "SELECT exa_set_questions.MedCod" + " FROM exa_exams," + "exa_sets," + "exa_set_questions" + " WHERE exa_exams.CrsCod=%ld" + " AND exa_exams.ExaCod=exa_sets.ExaCod" + " AND exa_sets.SetCod=exa_set_questions.SetCod", + CrsCod); + } + /*****************************************************************************/ /**************** Remove a question from a set of questions ******************/ /*****************************************************************************/ @@ -874,6 +1226,44 @@ unsigned Exa_DB_GetMediaFromAllAnsOfQst (MYSQL_RES **mysql_res,long QstCod,long SetCod); } +/*****************************************************************************/ +/********** Get media codes associated to answers of exam questions **********/ +/*****************************************************************************/ + +unsigned Exa_DB_GetAllMediaFromAnsOfAllQstsFromExam (MYSQL_RES **mysql_res,long ExaCod) + { + return (unsigned) + DB_QuerySELECT (mysql_res,"can not get media", + "SELECT exa_set_answers.MedCod" + " FROM exa_sets," + "exa_set_questions," + "exa_set_answers" + " WHERE exa_sets.ExaCod=%ld" + " AND exa_sets.SetCod=exa_set_questions.SetCod" + " AND exa_set_questions.QstCod=exa_set_answers.QstCod", + ExaCod); + } + +/*****************************************************************************/ +/***** Get media codes associated to answers of exam questions ********/ +/*****************************************************************************/ + +unsigned Exa_DB_GetAllMediaFromAnsOfAllQstsFromCrs (MYSQL_RES **mysql_res,long CrsCod) + { + return (unsigned) + DB_QuerySELECT (mysql_res,"can not get media", + "SELECT exa_set_answers.MedCod" + " FROM exa_exams," + "exa_sets," + "exa_set_questions," + "exa_set_answers" + " WHERE exa_exams.CrsCod=%ld" + " AND exa_exams.ExaCod=exa_sets.ExaCod" + " AND exa_sets.SetCod=exa_set_questions.SetCod" + " AND exa_set_questions.QstCod=exa_set_answers.QstCod", + CrsCod); + } + /*****************************************************************************/ /********** Remove the answers in sets of questions from an exam *************/ /*****************************************************************************/ diff --git a/swad_exam_database.h b/swad_exam_database.h index 6c61b40d..2876d28f 100644 --- a/swad_exam_database.h +++ b/swad_exam_database.h @@ -41,13 +41,22 @@ /***************************** Public prototypes *****************************/ /*****************************************************************************/ +//---------------------------- Exams ------------------------------------------ +long Exa_DB_CreateExam (const struct Exa_Exam *Exam,const char *Txt); +void Exa_DB_UpdateExam (const struct Exa_Exam *Exam,const char *Txt); +void Exa_DB_HideUnhideExam (long ExaCod,bool Hide); unsigned Exa_DB_GetListExams (MYSQL_RES **mysql_res,Exa_Order_t SelectedOrder); unsigned Exa_DB_GetDataOfExamByCod (MYSQL_RES **mysql_res,long ExaCod); unsigned Exa_DB_GetExamStartEnd (MYSQL_RES **mysql_res,long ExaCod); void Exa_DB_GetExamTxt (long ExaCod,char Txt[Cns_MAX_BYTES_TEXT + 1]); +bool Exa_DB_CheckIfSimilarExamExists (long CrsCod,long ExaCod,const char *Title); +unsigned Exa_DB_GetNumCoursesWithExams (HieLvl_Level_t Scope); +unsigned Exa_DB_GetNumExams (HieLvl_Level_t Scope); +double Exa_DB_GetNumQstsPerCrsExam (HieLvl_Level_t Scope); void Exa_DB_RemoveExam (long ExaCod); void Exa_DB_RemoveAllExamsFromCrs (long CrsCod); +//--------------------------------- Sets -------------------------------------- long Exa_DB_CreateSet (const struct ExaSet_Set *Set,unsigned SetInd); void Exa_DB_UpdateSet (const struct ExaSet_Set *Set); void Exa_DB_UpdateSetTitle (long SetCod,long ExaCod, @@ -72,6 +81,7 @@ void Exa_DB_RemoveSetFromExam (long SetCod,long ExaCod); void Exa_DB_RemoveAllSetsFromExam (long ExaCod); void Exa_DB_RemoveAllSetsFromCrs (long CrsCod); +//------------------------------ Set questions -------------------------------- long Exa_DB_AddQuestionToSet (long SetCod,const struct Tst_Question *Question,long MedCod); void Exa_DB_ChangeValidityQst (long QstCod,long SetCod,long ExaCod,long CrsCod, Tst_Validity_t Validity); @@ -83,11 +93,14 @@ unsigned Exa_DB_GetQstDataByCod (MYSQL_RES **mysql_res,long QstCod); unsigned Exa_DB_GetValidityAndAnswerType (MYSQL_RES **mysql_res,long QstCod); unsigned Exa_DB_GetAnswerType (MYSQL_RES **mysql_res,long QstCod); unsigned Exa_DB_GetMediaFromStemOfQst (MYSQL_RES **mysql_res,long QstCod,long SetCod); +unsigned Exa_DB_GetAllMediaFomStemOfAllQstsFromExam (MYSQL_RES **mysql_res,long ExaCod); +unsigned Exa_DB_GetAllMediaFomStemOfAllQstsFromCrs (MYSQL_RES **mysql_res,long CrsCod); void Exa_DB_RemoveSetQuestion (long QstCod,long SetCod); void Exa_DB_RemoveAllSetQuestionsFromSet (long SetCod,long ExaCod); void Exa_DB_RemoveAllSetQuestionsFromExam (long ExaCod); void Exa_DB_RemoveAllSetQuestionsFromCrs (long CrsCod); +//--------------------------- Set question answers ---------------------------- void Exa_DB_AddAnsToQstInSet (long QstCod,unsigned AnsInd, const char *Answer,const char *Feedback, long MedCod,bool Correct); @@ -95,9 +108,12 @@ unsigned Exa_DB_GetQstAnswersFromSet (MYSQL_RES **mysql_res,long QstCod,bool Shu unsigned Exa_DB_GetQstAnswersTextFromSet (MYSQL_RES **mysql_res,long QstCod); unsigned Exa_DB_GetQstAnswersCorrFromSet (MYSQL_RES **mysql_res,long QstCod); unsigned Exa_DB_GetMediaFromAllAnsOfQst (MYSQL_RES **mysql_res,long QstCod,long SetCod); +unsigned Exa_DB_GetAllMediaFromAnsOfAllQstsFromExam (MYSQL_RES **mysql_res,long ExaCod); +unsigned Exa_DB_GetAllMediaFromAnsOfAllQstsFromCrs (MYSQL_RES **mysql_res,long CrsCod); void Exa_DB_RemoveAllSetAnswersFromExam (long ExaCod); void Exa_DB_RemoveAllSetAnswersFromCrs (long CrsCod); +//-------------------------------- Sessions ----------------------------------- long Exa_DB_CreateSession (const struct ExaSes_Session *Session); void Exa_DB_UpdateSession (const struct ExaSes_Session *Session); unsigned Exa_DB_GetNumSessionsInExam (long ExaCod); @@ -111,6 +127,7 @@ void Exa_DB_RemoveAllSessionsFromExam (long ExaCod); void Exa_DB_RemoveAllSessionsFromCrs (long CrsCod); void Exa_DB_RemoveUsrFromSessionTablesInCrs (long UsrCod,long CrsCod); +//--------------------------------- Groups ------------------------------------ void Exa_DB_CreateGrpAssociatedToSes (long SesCod,long GrpCod); unsigned Exa_DB_GetGrpsAssociatedToSes (MYSQL_RES **mysql_res,long SesCod); bool Exa_DB_CheckIfICanListThisSessionBasedOnGrps (long SesCod); @@ -120,6 +137,7 @@ void Exa_DB_RemoveAllGrpsFromSes (long SesCod); void Exa_DB_RemoveAllGrpsOfType (long GrpTypCod); void Exa_DB_RemoveGrpAssociatedToExamSess (long GrpCod); +//---------------------------------- Prints ----------------------------------- 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); @@ -131,6 +149,7 @@ void Exa_DB_RemoveAllPrintsFromSes (long SesCod); void Exa_DB_RemoveAllPrintsFromExa (long ExaCod); void Exa_DB_RemoveAllPrintsFromCrs (long CrsCod); +//------------------------------- Print questions ----------------------------- void Exa_DB_StoreOneQstOfPrint (const struct ExaPrn_Print *Print, unsigned QstInd); unsigned Exa_DB_GetPrintQuestions (MYSQL_RES **mysql_res,long PrnCod); @@ -144,6 +163,7 @@ void Exa_DB_RemovePrintQstsFromSes (long SesCod); void Exa_DB_RemovePrintQstsFromExa (long ExaCod); void Exa_DB_RemovePrintQstsFromCrs (long CrsCod); +//---------------------------------- Logs ------------------------------------- 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); @@ -151,6 +171,7 @@ 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); +//--------------------------------- Results ----------------------------------- unsigned Exa_DB_GetAllUsrsWhoHaveMadeExam (MYSQL_RES **mysql_res,long ExaCod); unsigned Exa_DB_GetAllUsrsWhoHaveMadeSession (MYSQL_RES **mysql_res,long SesCod); unsigned Exa_DB_GetResults (MYSQL_RES **mysql_res,