diff --git a/swad_changelog.h b/swad_changelog.h index 79b70561..acccf19e 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 21.38 (2021-10-20)" +#define Log_PLATFORM_VERSION "SWAD 21.38.1 (2021-10-20)" #define CSS_FILE "swad20.45.css" #define JS_FILE "swad20.69.1.js" /* TODO: Rename CENTRE to CENTER in help wiki. TODO: Rename ASSESSMENT.Announcements to ASSESSMENT.Calls_for_exams + Version 21.38.1: Oct 20, 2021 Queries moved to module swad_survey_database. (320522 lines) Version 21.38: Oct 20, 2021 New module swad_survey_database for database queries related to surveys. (320457 lines) Version 21.37.1: Oct 20, 2021 Code refactoring in attendance. (320361 lines) Version 21.37: Oct 19, 2021 New module swad_statistic_database for database queries related to statistics of accesses to platform. (320363 lines) diff --git a/swad_figure.c b/swad_figure.c index 08b9ee34..b941aa38 100644 --- a/swad_figure.c +++ b/swad_figure.c @@ -66,6 +66,7 @@ #include "swad_project_database.h" #include "swad_role.h" #include "swad_survey.h" +#include "swad_survey_database.h" #include "swad_test.h" #include "swad_timeline.h" #include "swad_timeline_database.h" @@ -3223,7 +3224,7 @@ static void Fig_GetAndShowSurveysStats (void) /***** Get the number of surveys and the average number of questions per survey from this location *****/ if ((NumSurveys = Svy_GetNumCrsSurveys (Gbl.Scope.Current,&NumNotif))) { - if ((NumCoursesWithSurveys = Svy_DB_GetNumCrssWithCrsSvys (Gbl.Scope.Current)) != 0) + if ((NumCoursesWithSurveys = Svy_DB_GetNumCrssWithCrsSurveys (Gbl.Scope.Current)) != 0) NumSurveysPerCourse = (double) NumSurveys / (double) NumCoursesWithSurveys; NumQstsPerSurvey = Svy_DB_GetNumQstsPerCrsSurvey (Gbl.Scope.Current); diff --git a/swad_group.c b/swad_group.c index 2f6ae397..aa5cb603 100644 --- a/swad_group.c +++ b/swad_group.c @@ -51,6 +51,7 @@ #include "swad_project.h" #include "swad_setting.h" #include "swad_survey.h" +#include "swad_survey_database.h" #include "swad_timetable.h" /*****************************************************************************/ diff --git a/swad_survey.c b/swad_survey.c index 986e7b21..487f5cd7 100644 --- a/swad_survey.c +++ b/swad_survey.c @@ -124,25 +124,19 @@ static void Svy_GetListSurveys (struct Svy_Surveys *Surveys); static void Svy_SetAllowedAndHiddenScopes (unsigned *ScopesAllowed, unsigned *HiddenAllowed); -static void Svy_DB_GetSurveyTxt (long SvyCod,char Txt[Cns_MAX_BYTES_TEXT + 1]); static void Svy_PutParamSvyCod (long SvyCod); static long Svy_GetParamSvyCod (void); static void Svy_PutButtonToResetSurvey (struct Svy_Surveys *Surveys); -static bool Svy_DB_CheckIfSimilarSurveyExists (const struct Svy_Survey *Svy); static void Svy_SetDefaultAndAllowedScope (struct Svy_Survey *Svy); static void Svy_ShowLstGrpsToEditSurvey (long SvyCod); -static void Svy_DB_UpdateNumUsrsNotifiedByEMailAboutSurvey (long SvyCod, - unsigned NumUsrsToBeNotifiedByEMail); static void Svy_CreateSurvey (struct Svy_Survey *Svy,const char *Txt); static void Svy_UpdateSurvey (struct Svy_Survey *Svy,const char *Txt); -static void Svy_DB_RemoveAllGrpsAssociatedToSurvey (long SvyCod); static void Svy_CreateGrps (long SvyCod); static void Svy_GetAndWriteNamesOfGrpsAssociatedToSvy (struct Svy_Survey *Svy); static bool Svy_CheckIfICanDoThisSurveyBasedOnGrps (long SvyCod); -static unsigned Svy_DB_GetNumQstsSvy (long SvyCod); static void Svy_ShowFormEditOneQst (struct Svy_Surveys *Surveys, long SvyCod,struct Svy_Question *SvyQst, char Txt[Cns_MAX_BYTES_TEXT + 1]); @@ -151,13 +145,10 @@ static void Svy_PutParamQstCod (long QstCod); static long Svy_GetParamQstCod (void); static void Svy_DB_RemAnswersOfAQuestion (long QstCod); static Svy_AnswerType_t Svy_ConvertFromStrAnsTypDBToAnsTyp (const char *StrAnsTypeBD); -static bool Svy_DB_CheckIfAnswerExists (long QstCod,unsigned AnsInd); -static unsigned Svy_DB_GetAnswersQst (MYSQL_RES **mysql_res,long QstCod); static bool Svy_AllocateTextChoiceAnswer (struct Svy_Question *SvyQst,unsigned NumAns); static void Svy_FreeTextChoiceAnswers (struct Svy_Question *SvyQst,unsigned NumAnswers); static void Svy_FreeTextChoiceAnswer (struct Svy_Question *SvyQst,unsigned NumAns); -static unsigned Svy_DB_GetQstIndFromQstCod (long QstCod); static unsigned Svy_GetNextQuestionIndexInSvy (long SvyCod); static void Svy_ListSvyQuestions (struct Svy_Surveys *Surveys, struct Svy_Survey *Svy); @@ -174,10 +165,6 @@ static void Svy_PutIconToRemoveOneQst (void *Surveys); static void Svy_PutParamsRemoveOneQst (void *Surveys); static void Svy_ReceiveAndStoreUserAnswersToASurvey (long SvyCod); -static void Svy_DB_IncreaseAnswer (long QstCod,unsigned AnsInd); -static void Svy_DB_RegisterIHaveAnsweredSvy (long SvyCod); -static bool Svy_DB_CheckIfIHaveAnsweredSvy (long SvyCod); -static unsigned Svy_DB_GetNumUsrsWhoHaveAnsweredSvy (long SvyCod); /*****************************************************************************/ /*************************** Reset surveys context ***************************/ @@ -934,24 +921,10 @@ static void Svy_PutParams (void *Surveys) static void Svy_GetListSurveys (struct Svy_Surveys *Surveys) { - char *SubQuery[HieLvl_NUM_LEVELS]; - static const char *OrderBySubQuery[Dat_NUM_START_END_TIME] = - { - [Dat_STR_TIME] = "StartTime DESC," - "EndTime DESC," - "Title DESC", - [Dat_END_TIME] = "EndTime DESC," - "StartTime DESC," - "Title DESC", - }; MYSQL_RES *mysql_res; - unsigned long NumRows; unsigned NumSvy; unsigned ScopesAllowed = 0; unsigned HiddenAllowed = 0; - long Cods[HieLvl_NUM_LEVELS]; - HieLvl_Level_t Scope; - bool SubQueryFilled = false; /***** Free list of surveys *****/ if (Surveys->LstIsRead) @@ -961,112 +934,13 @@ static void Svy_GetListSurveys (struct Svy_Surveys *Surveys) Svy_SetAllowedAndHiddenScopes (&ScopesAllowed,&HiddenAllowed); /***** Get list of surveys from database *****/ - Cods[HieLvl_SYS] = -1L; // System - Cods[HieLvl_CTY] = Gbl.Hierarchy.Cty.CtyCod; // Country - Cods[HieLvl_INS] = Gbl.Hierarchy.Ins.InsCod; // Institution - Cods[HieLvl_CTR] = Gbl.Hierarchy.Ctr.CtrCod; // Center - Cods[HieLvl_DEG] = Gbl.Hierarchy.Deg.DegCod; // Degree - Cods[HieLvl_CRS] = Gbl.Hierarchy.Crs.CrsCod; // Course - - /* Fill subqueries for system, country, institution, center and degree */ - for (Scope = HieLvl_SYS; - Scope <= HieLvl_DEG; - Scope++) - if (ScopesAllowed & 1 << Scope) - { - if (asprintf (&SubQuery[Scope],"%s(Scope='%s' AND Cod=%ld%s)", - SubQueryFilled ? " OR " : - "", - Sco_GetDBStrFromScope (Scope),Cods[Scope], - (HiddenAllowed & 1 << Scope) ? "" : - " AND Hidden='N'") < 0) - Err_NotEnoughMemoryExit (); - SubQueryFilled = true; - } - else - { - if (asprintf (&SubQuery[Scope],"%s","") < 0) - Err_NotEnoughMemoryExit (); - } - - /* Fill subquery for course */ - if (ScopesAllowed & 1 << HieLvl_CRS) + if ((Surveys->Num = Svy_DB_GetListSurveys (&mysql_res, + ScopesAllowed, + HiddenAllowed, + Surveys->SelectedOrder))) // Surveys found... { - if (Gbl.Crs.Grps.WhichGrps == Grp_MY_GROUPS) - { - if (asprintf (&SubQuery[HieLvl_CRS],"%s(" - "Scope='%s'" - " AND Cod=%ld%s" - " AND " - "(SvyCod NOT IN" - " (SELECT SvyCod" - " FROM svy_groups)" - " OR" - " SvyCod IN" - " (SELECT svy_groups.SvyCod" - " FROM grp_users," - "svy_groups" - " WHERE grp_users.UsrCod=%ld" - " AND grp_users.GrpCod=svy_groups.GrpCod))" - ")", - SubQueryFilled ? " OR " : - "", - Sco_GetDBStrFromScope (HieLvl_CRS),Cods[HieLvl_CRS], - (HiddenAllowed & 1 << HieLvl_CRS) ? "" : - " AND Hidden='N'", - Gbl.Usrs.Me.UsrDat.UsrCod) < 0) - Err_NotEnoughMemoryExit (); - } - else // Gbl.Crs.Grps.WhichGrps == Grp_ALL_GROUPS - { - if (asprintf (&SubQuery[HieLvl_CRS],"%s(Scope='%s' AND Cod=%ld%s)", - SubQueryFilled ? " OR " : - "", - Sco_GetDBStrFromScope (HieLvl_CRS),Cods[HieLvl_CRS], - (HiddenAllowed & 1 << HieLvl_CRS) ? "" : - " AND Hidden='N'") < 0) - Err_NotEnoughMemoryExit (); - } - SubQueryFilled = true; - } - else - { - if (asprintf (&SubQuery[HieLvl_CRS],"%s","") < 0) - Err_NotEnoughMemoryExit (); - } - - /* Make query */ - if (SubQueryFilled) - NumRows = DB_QuerySELECT (&mysql_res,"can not get surveys", - "SELECT SvyCod" - " FROM svy_surveys" - " WHERE %s%s%s%s%s%s" - " ORDER BY %s", - SubQuery[HieLvl_SYS], - SubQuery[HieLvl_CTY], - SubQuery[HieLvl_INS], - SubQuery[HieLvl_CTR], - SubQuery[HieLvl_DEG], - SubQuery[HieLvl_CRS], - OrderBySubQuery[Surveys->SelectedOrder]); - else - { - Err_ShowErrorAndExit ("Can not get list of surveys."); - NumRows = 0; // Not reached. Initialized to avoid warning - } - - /* Free allocated memory for subqueries */ - for (Scope = HieLvl_SYS; - Scope <= HieLvl_CRS; - Scope++) - free (SubQuery[Scope]); - - if (NumRows) // Surveys found... - { - Surveys->Num = (unsigned) NumRows; - /***** Create list of surveys *****/ - if ((Surveys->LstSvyCods = calloc (NumRows, + if ((Surveys->LstSvyCods = calloc ((size_t) Surveys->Num, sizeof (*Surveys->LstSvyCods))) == NULL) Err_NotEnoughMemoryExit (); @@ -1078,8 +952,6 @@ static void Svy_GetListSurveys (struct Svy_Surveys *Surveys) if ((Surveys->LstSvyCods[NumSvy] = DB_GetNextCode (mysql_res)) < 0) Err_WrongSurveyExit (); } - else - Surveys->Num = 0; /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); @@ -1485,20 +1357,6 @@ void Svy_FreeListSurveys (struct Svy_Surveys *Surveys) } } -/*****************************************************************************/ -/********************** Get survey text from database ************************/ -/*****************************************************************************/ - -static void Svy_DB_GetSurveyTxt (long SvyCod,char Txt[Cns_MAX_BYTES_TEXT + 1]) - { - /***** Get text of survey from database *****/ - DB_QuerySELECTString (Txt,Cns_MAX_BYTES_TEXT,"can not get survey text", - "SELECT Txt" - " FROM svy_surveys" - " WHERE SvyCod=%ld", - SvyCod); - } - /*****************************************************************************/ /******************** Get summary and content of a survey *******************/ /*****************************************************************************/ @@ -1845,26 +1703,6 @@ void Svy_UnhideSurvey (void) Svy_ListAllSurveys (&Surveys); } -/*****************************************************************************/ -/******************* Check if the title of a survey exists *******************/ -/*****************************************************************************/ - -static bool Svy_DB_CheckIfSimilarSurveyExists (const struct Svy_Survey *Svy) - { - /***** Get number of surveys with a field value from database *****/ - return (DB_QueryCOUNT ("can not get similar surveys", - "SELECT COUNT(*)" - " FROM svy_surveys" - " WHERE Scope='%s'" - " AND Cod=%ld" - " AND Title='%s'" - " AND SvyCod<>%ld", - Sco_GetDBStrFromScope (Svy->Scope), - Svy->Cod, - Svy->Title, - Svy->SvyCod) != 0); - } - /*****************************************************************************/ /********************* Put a form to create a new survey *********************/ /*****************************************************************************/ @@ -2338,22 +2176,6 @@ void Svy_ReceiveFormSurvey (void) Svy_ListAllSurveys (&Surveys); } -/*****************************************************************************/ -/*********** Update number of users notified in table of surveys *************/ -/*****************************************************************************/ - -static void Svy_DB_UpdateNumUsrsNotifiedByEMailAboutSurvey (long SvyCod, - unsigned NumUsrsToBeNotifiedByEMail) - { - /***** Update number of users notified *****/ - DB_QueryUPDATE ("can not update the number of notifications of a survey", - "UPDATE svy_surveys" - " SET NumNotif=NumNotif+%u" - " WHERE SvyCod=%ld", - NumUsrsToBeNotifiedByEMail, - SvyCod); - } - /*****************************************************************************/ /*************************** Create a new survey *****************************/ /*****************************************************************************/ @@ -2431,50 +2253,6 @@ static void Svy_UpdateSurvey (struct Svy_Survey *Svy,const char *Txt) Ale_ShowAlert (Ale_SUCCESS,Txt_The_survey_has_been_modified); } -/*****************************************************************************/ -/************************* Remove groups of a survey *************************/ -/*****************************************************************************/ - -static void Svy_DB_RemoveAllGrpsAssociatedToSurvey (long SvyCod) - { - /***** Remove groups of the survey *****/ - DB_QueryDELETE ("can not remove the groups associated to a survey", - "DELETE FROM svy_groups" - " WHERE SvyCod=%ld", - SvyCod); - } - -/*****************************************************************************/ -/*************** Remove groups of one type from all the surveys **************/ -/*****************************************************************************/ - -void Svy_DB_RemoveGroupsOfType (long GrpTypCod) - { - /***** Remove group from all the surveys *****/ - DB_QueryDELETE ("can not remove groups of a type" - " from the associations between surveys and groups", - "DELETE FROM svy_groups" - " USING grp_groups," - "svy_groups" - " WHERE grp_groups.GrpTypCod=%ld" - " AND grp_groups.GrpCod=svy_groups.GrpCod", - GrpTypCod); - } - -/*****************************************************************************/ -/******************* Remove one group from all the surveys *******************/ -/*****************************************************************************/ - -void Svy_DB_RemoveGroup (long GrpCod) - { - /***** Remove group from all the surveys *****/ - DB_QueryDELETE ("can not remove group from the associations" - " between surveys and groups", - "DELETE FROM svy_groups" - " WHERE GrpCod=%ld", - GrpCod); - } - /*****************************************************************************/ /************************ Create groups of a survey **************************/ /*****************************************************************************/ @@ -2656,21 +2434,6 @@ static bool Svy_CheckIfICanDoThisSurveyBasedOnGrps (long SvyCod) SvyCod,Gbl.Usrs.Me.UsrDat.UsrCod) != 0); } -/*****************************************************************************/ -/******************* Get number of questions of a survey *********************/ -/*****************************************************************************/ - -static unsigned Svy_DB_GetNumQstsSvy (long SvyCod) - { - /***** Get data of questions from database *****/ - return (unsigned) - DB_QueryCOUNT ("can not get number of questions of a survey", - "SELECT COUNT(*)" - " FROM svy_questions" - " WHERE SvyCod=%ld", - SvyCod); - } - /*****************************************************************************/ /*********** Put a form to edit/create a question in survey *****************/ /*****************************************************************************/ @@ -2976,45 +2739,6 @@ static Svy_AnswerType_t Svy_ConvertFromStrAnsTypDBToAnsTyp (const char *StrAnsTy return (Svy_AnswerType_t) 0; } -/*****************************************************************************/ -/*********** Check if an answer of a question exists in database *************/ -/*****************************************************************************/ - -static bool Svy_DB_CheckIfAnswerExists (long QstCod,unsigned AnsInd) - { - /***** Get answers of a question from database *****/ - return (DB_QueryCOUNT ("can not check if an answer exists", - "SELECT COUNT(*)" - " FROM svy_answers" - " WHERE QstCod=%ld" - " AND AnsInd=%u", - QstCod,AnsInd) != 0); - } - -/*****************************************************************************/ -/************** Get answers of a survey question from database ***************/ -/*****************************************************************************/ - -static unsigned Svy_DB_GetAnswersQst (MYSQL_RES **mysql_res,long QstCod) - { - unsigned NumAnswers; - - /***** Get answers of a question from database *****/ - NumAnswers = (unsigned) - DB_QuerySELECT (mysql_res,"can not get answers of a question", - "SELECT AnsInd," // row[0] - "NumUsrs," // row[1] - "Answer" // row[2] - " FROM svy_answers" - " WHERE QstCod=%ld" - " ORDER BY AnsInd", - QstCod); - if (!NumAnswers) - Err_WrongAnswerExit (); - - return NumAnswers; - } - /*****************************************************************************/ /******************* Allocate memory for a choice answer *********************/ /*****************************************************************************/ @@ -3239,20 +2963,6 @@ void Svy_ReceiveQst (void) Svy_ShowOneSurvey (&Surveys,SvyCod,true); } -/*****************************************************************************/ -/************ Get question index from question code in a survey **************/ -/*****************************************************************************/ - -static unsigned Svy_DB_GetQstIndFromQstCod (long QstCod) - { - /***** Get question index from database *****/ - return DB_QuerySELECTUnsigned ("can not get question index", - "SELECT QstInd" - " FROM svy_questions" - " WHERE QstCod=%ld", - QstCod); - } - /*****************************************************************************/ /******************* Get next question index in a survey *********************/ /*****************************************************************************/ @@ -3310,18 +3020,6 @@ static void Svy_ListSvyQuestions (struct Svy_Surveys *Surveys, Gbl.Action.Act == ActRcvSvyQst); bool PutFormAnswerSurvey = Svy->Status.ICanAnswer && !Editing; - /***** Get data of questions from database *****/ - NumQsts = (unsigned) - DB_QuerySELECT (&mysql_res,"can not get data of a question", - "SELECT QstCod," // row[0] - "QstInd," // row[1] - "AnsType," // row[2] - "Stem" // row[3] - " FROM svy_questions" - " WHERE SvyCod=%ld" - " ORDER BY QstInd", - Svy->SvyCod); - /***** Begin box *****/ Surveys->SvyCod = Svy->SvyCod; if (Svy->Status.ICanEdit) @@ -3333,7 +3031,8 @@ static void Svy_ListSvyQuestions (struct Svy_Surveys *Surveys, NULL,NULL, Hlp_ASSESSMENT_Surveys_questions,Box_NOT_CLOSABLE); - if (NumQsts) + /***** Get data of questions from database *****/ + if ((NumQsts = Svy_DB_GetSurveyQsts (&mysql_res,Svy->SvyCod))) { if (PutFormAnswerSurvey) { @@ -3476,7 +3175,7 @@ static void Svy_PutButtonToCreateNewQuestion (struct Svy_Surveys *Surveys) Frm_BeginForm (ActEdiOneSvyQst); Svy_PutParams (Surveys); - Btn_PutConfirmButton (Txt_New_question); + Btn_PutConfirmButton (Txt_New_question); Frm_EndForm (); } @@ -3756,19 +3455,10 @@ void Svy_RemoveQst (void) Svy_DB_RemAnswersOfAQuestion (SvyQst.QstCod); /* Remove the question itself */ - DB_QueryDELETE ("can not remove a question", - "DELETE FROM svy_questions" - " WHERE QstCod=%ld", - SvyQst.QstCod); + Svy_DB_RemoveQst (SvyQst.QstCod); /* Change index of questions greater than this */ - DB_QueryUPDATE ("can not update indexes of questions", - "UPDATE svy_questions" - " SET QstInd=QstInd-1" - " WHERE SvyCod=%ld" - " AND QstInd>%u", - SvyCod, - SvyQst.QstInd); + Svy_DB_ChangeIndexesQsts (SvyCod,SvyQst.QstInd); /***** Write message *****/ Ale_ShowAlert (Ale_SUCCESS,Txt_Question_removed); @@ -3829,14 +3519,7 @@ static void Svy_ReceiveAndStoreUserAnswersToASurvey (long SvyCod) unsigned AnsInd; /***** Get questions of this survey from database *****/ - NumQsts = (unsigned) DB_QuerySELECT (&mysql_res,"can not get questions" - " of a survey", - "SELECT QstCod" - " FROM svy_questions" - " WHERE SvyCod=%ld" - " ORDER BY QstCod", - SvyCod); - if (NumQsts) + if ((NumQsts = Svy_DB_GetSurveyQstsCodes (&mysql_res,SvyCod))) { // This survey has questions /***** Get questions *****/ @@ -3874,156 +3557,6 @@ static void Svy_ReceiveAndStoreUserAnswersToASurvey (long SvyCod) Svy_DB_RegisterIHaveAnsweredSvy (SvyCod); } -/*****************************************************************************/ -/************ Increase number of users who have marked one answer ************/ -/*****************************************************************************/ - -static void Svy_DB_IncreaseAnswer (long QstCod,unsigned AnsInd) - { - /***** Increase number of users who have selected the answer AnsInd in the question QstCod *****/ - DB_QueryUPDATE ("can not register your answer to the survey", - "UPDATE svy_answers" - " SET NumUsrs=NumUsrs+1" - " WHERE QstCod=%ld" - " AND AnsInd=%u", - QstCod, - AnsInd); - } - -/*****************************************************************************/ -/***************** Register that I have answered this survey *****************/ -/*****************************************************************************/ - -static void Svy_DB_RegisterIHaveAnsweredSvy (long SvyCod) - { - DB_QueryINSERT ("can not register that you have answered the survey", - "INSERT INTO svy_users" - " (SvyCod,UsrCod)" - " VALUES" - " (%ld,%ld)", - SvyCod, - Gbl.Usrs.Me.UsrDat.UsrCod); - } - -/*****************************************************************************/ -/************** Register that you have answered this survey ******************/ -/*****************************************************************************/ - -static bool Svy_DB_CheckIfIHaveAnsweredSvy (long SvyCod) - { - /***** Get number of surveys with a field value from database *****/ - return (DB_QueryCOUNT ("can not check if you have answered a survey", - "SELECT COUNT(*)" - " FROM svy_users" - " WHERE SvyCod=%ld" - " AND UsrCod=%ld", - SvyCod, - Gbl.Usrs.Me.UsrDat.UsrCod) != 0); - } - -/*****************************************************************************/ -/*************** Register that you have answered this survey *****************/ -/*****************************************************************************/ - -static unsigned Svy_DB_GetNumUsrsWhoHaveAnsweredSvy (long SvyCod) - { - /***** Get number of surveys with a field value from database *****/ - return (unsigned) - DB_QueryCOUNT ("can not get number of users who have answered a survey", - "SELECT COUNT(*)" - " FROM svy_users" - " WHERE SvyCod=%ld", - SvyCod); - } - -/*****************************************************************************/ -/******************** Get number of courses with surveys *********************/ -/*****************************************************************************/ -// Returns the number of courses with surveys for courses -// in this location (all the platform, current degree or current course) - -unsigned Svy_DB_GetNumCrssWithCrsSvys (HieLvl_Level_t Scope) - { - /***** Get number of courses with surveys from database *****/ - switch (Scope) - { - case HieLvl_SYS: - return (unsigned) - DB_QueryCOUNT ("can not get number of courses with surveys", - "SELECT COUNT(DISTINCT Cod)" - " FROM svy_surveys" - " WHERE Scope='%s'", - Sco_GetDBStrFromScope (HieLvl_CRS)); - case HieLvl_CTY: - return (unsigned) - DB_QueryCOUNT ("can not get number of courses with surveys", - "SELECT COUNT(DISTINCT svy_surveys.Cod)" - " FROM ins_instits," - "ctr_centers," - "deg_degrees," - "crs_courses," - "svy_surveys" - " 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=svy_surveys.Cod" - " AND svy_surveys.Scope='%s'", - Gbl.Hierarchy.Ins.InsCod, - Sco_GetDBStrFromScope (HieLvl_CRS)); - case HieLvl_INS: - return (unsigned) - DB_QueryCOUNT ("can not get number of courses with surveys", - "SELECT COUNT(DISTINCT svy_surveys.Cod)" - " FROM ctr_centers," - "deg_degrees," - "crs_courses," - "svy_surveys" - " WHERE ctr_centers.InsCod=%ld" - " AND ctr_centers.CtrCod=deg_degrees.CtrCod" - " AND deg_degrees.DegCod=crs_courses.DegCod" - " AND crs_courses.CrsCod=svy_surveys.Cod" - " AND svy_surveys.Scope='%s'", - Gbl.Hierarchy.Ins.InsCod, - Sco_GetDBStrFromScope (HieLvl_CRS)); - case HieLvl_CTR: - return (unsigned) - DB_QueryCOUNT ("can not get number of courses with surveys", - "SELECT COUNT(DISTINCT svy_surveys.Cod)" - " FROM deg_degrees," - "crs_courses," - "svy_surveys" - " WHERE deg_degrees.CtrCod=%ld" - " AND deg_degrees.DegCod=crs_courses.DegCod" - " AND crs_courses.CrsCod=svy_surveys.Cod" - " AND svy_surveys.Scope='%s'", - Gbl.Hierarchy.Ctr.CtrCod, - Sco_GetDBStrFromScope (HieLvl_CRS)); - case HieLvl_DEG: - return (unsigned) - DB_QueryCOUNT ("can not get number of courses with surveys", - "SELECT COUNT(DISTINCT svy_surveys.Cod)" - " FROM crs_courses," - "svy_surveys" - " WHERE crs_courses.DegCod=%ld" - " AND crs_courses.CrsCod=svy_surveys.Cod" - " AND svy_surveys.Scope='%s'", - Gbl.Hierarchy.Deg.DegCod, - Sco_GetDBStrFromScope (HieLvl_CRS)); - case HieLvl_CRS: - return (unsigned) - DB_QueryCOUNT ("can not get number of courses with surveys", - "SELECT COUNT(DISTINCT Cod)" - " FROM svy_surveys" - " WHERE Scope='%s'" - " AND Cod=%ld", - Sco_GetDBStrFromScope (HieLvl_CRS), - Gbl.Hierarchy.Crs.CrsCod); - default: - return 0; - } - } - /*****************************************************************************/ /******************** Get number of surveys for courses **********************/ /*****************************************************************************/ @@ -4037,211 +3570,27 @@ unsigned Svy_GetNumCrsSurveys (HieLvl_Level_t Scope,unsigned *NumNotif) unsigned NumSurveys; /***** Get number of surveys from database *****/ - switch (Scope) + if (Svy_DB_GetNumCrsSurveys (&mysql_res,Scope)) { - case HieLvl_SYS: - DB_QuerySELECT (&mysql_res,"can not get number of surveys", - "SELECT COUNT(*)," // row[0] - "SUM(NumNotif)" // row[1] - " FROM svy_surveys" - " WHERE Scope='%s'", - Sco_GetDBStrFromScope (HieLvl_CRS)); - break; - case HieLvl_CTY: - DB_QuerySELECT (&mysql_res,"can not get number of surveys", - "SELECT COUNT(*)," // row[0] - "SUM(svy_surveys.NumNotif)" // row[1] - " FROM ins_instits," - "ctr_centers," - "deg_degrees," - "crs_courses," - "svy_surveys" - " 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=svy_surveys.Cod" - " AND svy_surveys.Scope='%s'", - Gbl.Hierarchy.Cty.CtyCod, - Sco_GetDBStrFromScope (HieLvl_CRS)); - break; - case HieLvl_INS: - DB_QuerySELECT (&mysql_res,"can not get number of surveys", - "SELECT COUNT(*)," // row[0] - "SUM(svy_surveys.NumNotif)" // row[1] - " FROM ctr_centers," - "deg_degrees," - "crs_courses," - "svy_surveys" - " WHERE ctr_centers.InsCod=%ld" - " AND ctr_centers.CtrCod=deg_degrees.CtrCod" - " AND deg_degrees.DegCod=crs_courses.DegCod" - " AND crs_courses.CrsCod=svy_surveys.Cod" - " AND svy_surveys.Scope='%s'", - Gbl.Hierarchy.Ins.InsCod, - Sco_GetDBStrFromScope (HieLvl_CRS)); - break; - case HieLvl_CTR: - DB_QuerySELECT (&mysql_res,"can not get number of surveys", - "SELECT COUNT(*)," // row[0] - "SUM(svy_surveys.NumNotif)" // row[1] - " FROM deg_degrees," - "crs_courses," - "svy_surveys" - " WHERE deg_degrees.CtrCod=%ld" - " AND deg_degrees.DegCod=crs_courses.DegCod" - " AND crs_courses.CrsCod=svy_surveys.Cod" - " AND svy_surveys.Scope='%s'", - Gbl.Hierarchy.Ctr.CtrCod, - Sco_GetDBStrFromScope (HieLvl_CRS)); - break; - case HieLvl_DEG: - DB_QuerySELECT (&mysql_res,"can not get number of surveys", - "SELECT COUNT(*)," // row[0] - "SUM(svy_surveys.NumNotif)" // row[1] - " FROM crs_courses," - "svy_surveys" - " WHERE crs_courses.DegCod=%ld" - " AND crs_courses.CrsCod=svy_surveys.Cod" - " AND svy_surveys.Scope='%s'", - Gbl.Hierarchy.Deg.DegCod, - Sco_GetDBStrFromScope (HieLvl_CRS)); - break; - case HieLvl_CRS: - DB_QuerySELECT (&mysql_res,"can not get number of surveys", - "SELECT COUNT(*)," // row[0] - "SUM(NumNotif)" // row[1] - " FROM svy_surveys" - " WHERE svy_surveys.Scope='%s'" - " AND CrsCod=%ld", - Sco_GetDBStrFromScope (HieLvl_CRS), - Gbl.Hierarchy.Crs.CrsCod); - break; - default: - Err_WrongScopeExit (); - break; - } + /***** Get number of surveys *****/ + row = mysql_fetch_row (mysql_res); + if (sscanf (row[0],"%u",&NumSurveys) != 1) + Err_ShowErrorAndExit ("Error when getting number of surveys."); - /***** Get number of surveys *****/ - row = mysql_fetch_row (mysql_res); - if (sscanf (row[0],"%u",&NumSurveys) != 1) - Err_ShowErrorAndExit ("Error when getting number of surveys."); - - /***** Get number of notifications by email *****/ - if (row[1]) - { - if (sscanf (row[1],"%u",NumNotif) != 1) - Err_ShowErrorAndExit ("Error when getting number of notifications of surveys."); + /***** Get number of notifications by email *****/ + if (row[1]) + { + if (sscanf (row[1],"%u",NumNotif) != 1) + Err_ShowErrorAndExit ("Error when getting number of notifications of surveys."); + } + else + *NumNotif = 0; } else - *NumNotif = 0; + NumSurveys = 0; /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); return NumSurveys; } - -/*****************************************************************************/ -/************ Get average number of questions per course survey **************/ -/*****************************************************************************/ - -double Svy_DB_GetNumQstsPerCrsSurvey (HieLvl_Level_t Scope) - { - /***** Get number of questions per survey from database *****/ - switch (Scope) - { - case HieLvl_SYS: - return DB_QuerySELECTDouble ("can not get number of questions per survey", - "SELECT AVG(NumQsts)" - " FROM (SELECT COUNT(svy_questions.QstCod) AS NumQsts" - " FROM svy_surveys," - "svy_questions" - " WHERE svy_surveys.Scope='%s'" - " AND svy_surveys.SvyCod=svy_questions.SvyCod" - " GROUP BY svy_questions.SvyCod) AS NumQstsTable", - Sco_GetDBStrFromScope (HieLvl_CRS)); - case HieLvl_CTY: - return DB_QuerySELECTDouble ("can not get number of questions per survey", - "SELECT AVG(NumQsts)" - " FROM (SELECT COUNT(svy_questions.QstCod) AS NumQsts" - " FROM ins_instits," - "ctr_centers," - "deg_degrees," - "crs_courses," - "svy_surveys," - "svy_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=svy_surveys.Cod" - " AND svy_surveys.Scope='%s'" - " AND svy_surveys.SvyCod=svy_questions.SvyCod" - " GROUP BY svy_questions.SvyCod) AS NumQstsTable", - Gbl.Hierarchy.Cty.CtyCod, - Sco_GetDBStrFromScope (HieLvl_CRS)); - case HieLvl_INS: - return DB_QuerySELECTDouble ("can not get number of questions per survey", - "SELECT AVG(NumQsts)" - " FROM (SELECT COUNT(svy_questions.QstCod) AS NumQsts" - " FROM ctr_centers," - "deg_degrees," - "crs_courses," - "svy_surveys," - "svy_questions" - " WHERE ctr_centers.InsCod=%ld" - " AND ctr_centers.CtrCod=deg_degrees.CtrCod" - " AND deg_degrees.DegCod=crs_courses.DegCod" - " AND crs_courses.CrsCod=svy_surveys.Cod" - " AND svy_surveys.Scope='%s'" - " AND svy_surveys.SvyCod=svy_questions.SvyCod" - " GROUP BY svy_questions.SvyCod) AS NumQstsTable", - Gbl.Hierarchy.Ins.InsCod, - Sco_GetDBStrFromScope (HieLvl_CRS)); - case HieLvl_CTR: - return DB_QuerySELECTDouble ("can not get number of questions per survey", - "SELECT AVG(NumQsts)" - " FROM (SELECT COUNT(svy_questions.QstCod) AS NumQsts" - " FROM deg_degrees," - "crs_courses," - "svy_surveys," - "svy_questions" - " WHERE deg_degrees.CtrCod=%ld" - " AND deg_degrees.DegCod=crs_courses.DegCod" - " AND crs_courses.CrsCod=svy_surveys.Cod" - " AND svy_surveys.Scope='%s'" - " AND svy_surveys.SvyCod=svy_questions.SvyCod" - " GROUP BY svy_questions.SvyCod) AS NumQstsTable", - Gbl.Hierarchy.Ctr.CtrCod, - Sco_GetDBStrFromScope (HieLvl_CRS)); - case HieLvl_DEG: - return DB_QuerySELECTDouble ("can not get number of questions per survey", - "SELECT AVG(NumQsts)" - " FROM (SELECT COUNT(svy_questions.QstCod) AS NumQsts" - " FROM crs_courses," - "svy_surveys," - "svy_questions" - " WHERE crs_courses.DegCod=%ld" - " AND crs_courses.CrsCod=svy_surveys.Cod" - " AND svy_surveys.Scope='%s'" - " AND svy_surveys.SvyCod=svy_questions.SvyCod" - " GROUP BY svy_questions.SvyCod) AS NumQstsTable", - Gbl.Hierarchy.Deg.DegCod, - Sco_GetDBStrFromScope (HieLvl_CRS)); - case HieLvl_CRS: - return DB_QuerySELECTDouble ("can not get number of questions per survey", - "SELECT AVG(NumQsts)" - " FROM (SELECT COUNT(svy_questions.QstCod) AS NumQsts" - " FROM svy_surveys," - "svy_questions" - " WHERE svy_surveys.Scope='%s'" - " AND svy_surveys.Cod=%ld" - " AND svy_surveys.SvyCod=svy_questions.SvyCod" - " GROUP BY svy_questions.SvyCod) AS NumQstsTable", - Sco_GetDBStrFromScope (HieLvl_CRS),Gbl.Hierarchy.Crs.CrsCod); - default: - Err_WrongScopeExit (); - return 0.0; // Not reached - } - } diff --git a/swad_survey.h b/swad_survey.h index 7df5fd57..a1cb849c 100644 --- a/swad_survey.h +++ b/swad_survey.h @@ -108,8 +108,6 @@ void Svy_ResetSurvey (void); void Svy_HideSurvey (void); void Svy_UnhideSurvey (void); void Svy_ReceiveFormSurvey (void); -void Svy_DB_RemoveGroupsOfType (long GrpTypCod); -void Svy_DB_RemoveGroup (long GrpCod); void Svy_RemoveSurveys (HieLvl_Level_t Scope,long Cod); void Svy_RequestEditQuestion (void); @@ -120,8 +118,6 @@ void Svy_RemoveQst (void); void Svy_ReceiveSurveyAnswers (void); -unsigned Svy_DB_GetNumCrssWithCrsSvys (HieLvl_Level_t Scope); unsigned Svy_GetNumCrsSurveys (HieLvl_Level_t Scope,unsigned *NumNotif); -double Svy_DB_GetNumQstsPerCrsSurvey (HieLvl_Level_t Scope); #endif diff --git a/swad_survey_database.c b/swad_survey_database.c index b6a69e9b..769d0f83 100644 --- a/swad_survey_database.c +++ b/swad_survey_database.c @@ -25,17 +25,17 @@ /********************************* Headers ***********************************/ /*****************************************************************************/ -// #define _GNU_SOURCE // For asprintf +#define _GNU_SOURCE // For asprintf // #include // For PATH_MAX // #include // For NULL -// #include // For asprintf +#include // For asprintf // #include // For calloc // #include // For string functions // #include "swad_attendance.h" // #include "swad_box.h" #include "swad_database.h" -// #include "swad_error.h" +#include "swad_error.h" // #include "swad_figure.h" // #include "swad_form.h" #include "swad_global.h" @@ -48,7 +48,7 @@ // #include "swad_parameter.h" // #include "swad_role.h" // #include "swad_setting.h" -// #include "swad_survey.h" +#include "swad_survey.h" #include "swad_survey_database.h" /*****************************************************************************/ @@ -73,6 +73,471 @@ extern struct Globals Gbl; /***************************** Private prototypes ****************************/ /*****************************************************************************/ +/*****************************************************************************/ +/*********** Update number of users notified in table of surveys *************/ +/*****************************************************************************/ + +void Svy_DB_UpdateNumUsrsNotifiedByEMailAboutSurvey (long SvyCod, + unsigned NumUsrsToBeNotifiedByEMail) + { + DB_QueryUPDATE ("can not update the number of notifications of a survey", + "UPDATE svy_surveys" + " SET NumNotif=NumNotif+%u" + " WHERE SvyCod=%ld", + NumUsrsToBeNotifiedByEMail, + SvyCod); + } + +/*****************************************************************************/ +/*********************** Get list of all the surveys *************************/ +/*****************************************************************************/ + +unsigned Svy_DB_GetListSurveys (MYSQL_RES **mysql_res, + unsigned ScopesAllowed, + unsigned HiddenAllowed, + Dat_StartEndTime_t SelectedOrder) + { + char *SubQuery[HieLvl_NUM_LEVELS]; + static const char *OrderBySubQuery[Dat_NUM_START_END_TIME] = + { + [Dat_STR_TIME] = "StartTime DESC," + "EndTime DESC," + "Title DESC", + [Dat_END_TIME] = "EndTime DESC," + "StartTime DESC," + "Title DESC", + }; + unsigned NumSvys; + long Cods[HieLvl_NUM_LEVELS]; + HieLvl_Level_t Scope; + bool SubQueryFilled = false; + + /***** Set hierarchy codes *****/ + Cods[HieLvl_SYS] = -1L; // System + Cods[HieLvl_CTY] = Gbl.Hierarchy.Cty.CtyCod; // Country + Cods[HieLvl_INS] = Gbl.Hierarchy.Ins.InsCod; // Institution + Cods[HieLvl_CTR] = Gbl.Hierarchy.Ctr.CtrCod; // Center + Cods[HieLvl_DEG] = Gbl.Hierarchy.Deg.DegCod; // Degree + Cods[HieLvl_CRS] = Gbl.Hierarchy.Crs.CrsCod; // Course + + /***** Fill subqueries for system, country, institution, center and degree *****/ + for (Scope = HieLvl_SYS; + Scope <= HieLvl_DEG; + Scope++) + if (ScopesAllowed & 1 << Scope) + { + if (asprintf (&SubQuery[Scope],"%s(Scope='%s' AND Cod=%ld%s)", + SubQueryFilled ? " OR " : + "", + Sco_GetDBStrFromScope (Scope),Cods[Scope], + (HiddenAllowed & 1 << Scope) ? "" : + " AND Hidden='N'") < 0) + Err_NotEnoughMemoryExit (); + SubQueryFilled = true; + } + else + { + if (asprintf (&SubQuery[Scope],"%s","") < 0) + Err_NotEnoughMemoryExit (); + } + + /***** Fill subquery for course *****/ + if (ScopesAllowed & 1 << HieLvl_CRS) + { + if (Gbl.Crs.Grps.WhichGrps == Grp_MY_GROUPS) + { + if (asprintf (&SubQuery[HieLvl_CRS],"%s(" + "Scope='%s'" + " AND Cod=%ld%s" + " AND " + "(SvyCod NOT IN" + " (SELECT SvyCod" + " FROM svy_groups)" + " OR" + " SvyCod IN" + " (SELECT svy_groups.SvyCod" + " FROM grp_users," + "svy_groups" + " WHERE grp_users.UsrCod=%ld" + " AND grp_users.GrpCod=svy_groups.GrpCod))" + ")", + SubQueryFilled ? " OR " : + "", + Sco_GetDBStrFromScope (HieLvl_CRS),Cods[HieLvl_CRS], + (HiddenAllowed & 1 << HieLvl_CRS) ? "" : + " AND Hidden='N'", + Gbl.Usrs.Me.UsrDat.UsrCod) < 0) + Err_NotEnoughMemoryExit (); + } + else // Gbl.Crs.Grps.WhichGrps == Grp_ALL_GROUPS + { + if (asprintf (&SubQuery[HieLvl_CRS],"%s(Scope='%s' AND Cod=%ld%s)", + SubQueryFilled ? " OR " : + "", + Sco_GetDBStrFromScope (HieLvl_CRS),Cods[HieLvl_CRS], + (HiddenAllowed & 1 << HieLvl_CRS) ? "" : + " AND Hidden='N'") < 0) + Err_NotEnoughMemoryExit (); + } + SubQueryFilled = true; + } + else + { + if (asprintf (&SubQuery[HieLvl_CRS],"%s","") < 0) + Err_NotEnoughMemoryExit (); + } + + /***** Make query *****/ + if (SubQueryFilled) + NumSvys = (unsigned) + DB_QuerySELECT (mysql_res,"can not get surveys", + "SELECT SvyCod" + " FROM svy_surveys" + " WHERE %s%s%s%s%s%s" + " ORDER BY %s", + SubQuery[HieLvl_SYS], + SubQuery[HieLvl_CTY], + SubQuery[HieLvl_INS], + SubQuery[HieLvl_CTR], + SubQuery[HieLvl_DEG], + SubQuery[HieLvl_CRS], + OrderBySubQuery[SelectedOrder]); + else + { + Err_ShowErrorAndExit ("Can not get list of surveys."); + NumSvys = 0; // Not reached. Initialized to avoid warning + } + + /***** Free allocated memory for subqueries *****/ + for (Scope = HieLvl_SYS; + Scope <= HieLvl_CRS; + Scope++) + free (SubQuery[Scope]); + + return NumSvys; + } + +/*****************************************************************************/ +/********************** Get survey text from database ************************/ +/*****************************************************************************/ + +void Svy_DB_GetSurveyTxt (long SvyCod,char Txt[Cns_MAX_BYTES_TEXT + 1]) + { + DB_QuerySELECTString (Txt,Cns_MAX_BYTES_TEXT,"can not get survey text", + "SELECT Txt" + " FROM svy_surveys" + " WHERE SvyCod=%ld", + SvyCod); + } + +/*****************************************************************************/ +/******************* Check if the title of a survey exists *******************/ +/*****************************************************************************/ + +bool Svy_DB_CheckIfSimilarSurveyExists (const struct Svy_Survey *Svy) + { + /***** Get number of surveys with a field value from database *****/ + return (DB_QueryCOUNT ("can not get similar surveys", + "SELECT COUNT(*)" + " FROM svy_surveys" + " WHERE Scope='%s'" + " AND Cod=%ld" + " AND Title='%s'" + " AND SvyCod<>%ld", + Sco_GetDBStrFromScope (Svy->Scope), + Svy->Cod, + Svy->Title, + Svy->SvyCod) != 0); + } + +/*****************************************************************************/ +/******************** Get number of courses with surveys *********************/ +/*****************************************************************************/ +// Returns the number of courses with surveys for courses +// in this location (all the platform, current degree or current course) + +unsigned Svy_DB_GetNumCrssWithCrsSurveys (HieLvl_Level_t Scope) + { + /***** Get number of courses with surveys from database *****/ + switch (Scope) + { + case HieLvl_SYS: + return (unsigned) + DB_QueryCOUNT ("can not get number of courses with surveys", + "SELECT COUNT(DISTINCT Cod)" + " FROM svy_surveys" + " WHERE Scope='%s'", + Sco_GetDBStrFromScope (HieLvl_CRS)); + case HieLvl_CTY: + return (unsigned) + DB_QueryCOUNT ("can not get number of courses with surveys", + "SELECT COUNT(DISTINCT svy_surveys.Cod)" + " FROM ins_instits," + "ctr_centers," + "deg_degrees," + "crs_courses," + "svy_surveys" + " 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=svy_surveys.Cod" + " AND svy_surveys.Scope='%s'", + Gbl.Hierarchy.Ins.InsCod, + Sco_GetDBStrFromScope (HieLvl_CRS)); + case HieLvl_INS: + return (unsigned) + DB_QueryCOUNT ("can not get number of courses with surveys", + "SELECT COUNT(DISTINCT svy_surveys.Cod)" + " FROM ctr_centers," + "deg_degrees," + "crs_courses," + "svy_surveys" + " WHERE ctr_centers.InsCod=%ld" + " AND ctr_centers.CtrCod=deg_degrees.CtrCod" + " AND deg_degrees.DegCod=crs_courses.DegCod" + " AND crs_courses.CrsCod=svy_surveys.Cod" + " AND svy_surveys.Scope='%s'", + Gbl.Hierarchy.Ins.InsCod, + Sco_GetDBStrFromScope (HieLvl_CRS)); + case HieLvl_CTR: + return (unsigned) + DB_QueryCOUNT ("can not get number of courses with surveys", + "SELECT COUNT(DISTINCT svy_surveys.Cod)" + " FROM deg_degrees," + "crs_courses," + "svy_surveys" + " WHERE deg_degrees.CtrCod=%ld" + " AND deg_degrees.DegCod=crs_courses.DegCod" + " AND crs_courses.CrsCod=svy_surveys.Cod" + " AND svy_surveys.Scope='%s'", + Gbl.Hierarchy.Ctr.CtrCod, + Sco_GetDBStrFromScope (HieLvl_CRS)); + case HieLvl_DEG: + return (unsigned) + DB_QueryCOUNT ("can not get number of courses with surveys", + "SELECT COUNT(DISTINCT svy_surveys.Cod)" + " FROM crs_courses," + "svy_surveys" + " WHERE crs_courses.DegCod=%ld" + " AND crs_courses.CrsCod=svy_surveys.Cod" + " AND svy_surveys.Scope='%s'", + Gbl.Hierarchy.Deg.DegCod, + Sco_GetDBStrFromScope (HieLvl_CRS)); + case HieLvl_CRS: + return (unsigned) + DB_QueryCOUNT ("can not get number of courses with surveys", + "SELECT COUNT(DISTINCT Cod)" + " FROM svy_surveys" + " WHERE Scope='%s'" + " AND Cod=%ld", + Sco_GetDBStrFromScope (HieLvl_CRS), + Gbl.Hierarchy.Crs.CrsCod); + default: + Err_WrongScopeExit (); + return 0; // Not reached + } + } + +/*****************************************************************************/ +/******************** Get number of surveys for courses **********************/ +/*****************************************************************************/ +// Returns the number of surveys for courses +// in this location (all the platform, current degree or current course) + +unsigned Svy_DB_GetNumCrsSurveys (MYSQL_RES **mysql_res,HieLvl_Level_t Scope) + { + /***** Get number of surveys from database *****/ + switch (Scope) + { + case HieLvl_SYS: + return (unsigned) + DB_QuerySELECT (mysql_res,"can not get number of surveys", + "SELECT COUNT(*)," // row[0] + "SUM(NumNotif)" // row[1] + " FROM svy_surveys" + " WHERE Scope='%s'", + Sco_GetDBStrFromScope (HieLvl_CRS)); + case HieLvl_CTY: + return (unsigned) + DB_QuerySELECT (mysql_res,"can not get number of surveys", + "SELECT COUNT(*)," // row[0] + "SUM(svy_surveys.NumNotif)" // row[1] + " FROM ins_instits," + "ctr_centers," + "deg_degrees," + "crs_courses," + "svy_surveys" + " 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=svy_surveys.Cod" + " AND svy_surveys.Scope='%s'", + Gbl.Hierarchy.Cty.CtyCod, + Sco_GetDBStrFromScope (HieLvl_CRS)); + case HieLvl_INS: + return (unsigned) + DB_QuerySELECT (mysql_res,"can not get number of surveys", + "SELECT COUNT(*)," // row[0] + "SUM(svy_surveys.NumNotif)" // row[1] + " FROM ctr_centers," + "deg_degrees," + "crs_courses," + "svy_surveys" + " WHERE ctr_centers.InsCod=%ld" + " AND ctr_centers.CtrCod=deg_degrees.CtrCod" + " AND deg_degrees.DegCod=crs_courses.DegCod" + " AND crs_courses.CrsCod=svy_surveys.Cod" + " AND svy_surveys.Scope='%s'", + Gbl.Hierarchy.Ins.InsCod, + Sco_GetDBStrFromScope (HieLvl_CRS)); + case HieLvl_CTR: + return (unsigned) + DB_QuerySELECT (mysql_res,"can not get number of surveys", + "SELECT COUNT(*)," // row[0] + "SUM(svy_surveys.NumNotif)" // row[1] + " FROM deg_degrees," + "crs_courses," + "svy_surveys" + " WHERE deg_degrees.CtrCod=%ld" + " AND deg_degrees.DegCod=crs_courses.DegCod" + " AND crs_courses.CrsCod=svy_surveys.Cod" + " AND svy_surveys.Scope='%s'", + Gbl.Hierarchy.Ctr.CtrCod, + Sco_GetDBStrFromScope (HieLvl_CRS)); + case HieLvl_DEG: + return (unsigned) + DB_QuerySELECT (mysql_res,"can not get number of surveys", + "SELECT COUNT(*)," // row[0] + "SUM(svy_surveys.NumNotif)" // row[1] + " FROM crs_courses," + "svy_surveys" + " WHERE crs_courses.DegCod=%ld" + " AND crs_courses.CrsCod=svy_surveys.Cod" + " AND svy_surveys.Scope='%s'", + Gbl.Hierarchy.Deg.DegCod, + Sco_GetDBStrFromScope (HieLvl_CRS)); + case HieLvl_CRS: + return (unsigned) + DB_QuerySELECT (mysql_res,"can not get number of surveys", + "SELECT COUNT(*)," // row[0] + "SUM(NumNotif)" // row[1] + " FROM svy_surveys" + " WHERE svy_surveys.Scope='%s'" + " AND CrsCod=%ld", + Sco_GetDBStrFromScope (HieLvl_CRS), + Gbl.Hierarchy.Crs.CrsCod); + default: + Err_WrongScopeExit (); + return 0; // Not reached + } + } + +/*****************************************************************************/ +/************ Get average number of questions per course survey **************/ +/*****************************************************************************/ + +double Svy_DB_GetNumQstsPerCrsSurvey (HieLvl_Level_t Scope) + { + /***** Get number of questions per survey from database *****/ + switch (Scope) + { + case HieLvl_SYS: + return DB_QuerySELECTDouble ("can not get number of questions per survey", + "SELECT AVG(NumQsts)" + " FROM (SELECT COUNT(svy_questions.QstCod) AS NumQsts" + " FROM svy_surveys," + "svy_questions" + " WHERE svy_surveys.Scope='%s'" + " AND svy_surveys.SvyCod=svy_questions.SvyCod" + " GROUP BY svy_questions.SvyCod) AS NumQstsTable", + Sco_GetDBStrFromScope (HieLvl_CRS)); + case HieLvl_CTY: + return DB_QuerySELECTDouble ("can not get number of questions per survey", + "SELECT AVG(NumQsts)" + " FROM (SELECT COUNT(svy_questions.QstCod) AS NumQsts" + " FROM ins_instits," + "ctr_centers," + "deg_degrees," + "crs_courses," + "svy_surveys," + "svy_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=svy_surveys.Cod" + " AND svy_surveys.Scope='%s'" + " AND svy_surveys.SvyCod=svy_questions.SvyCod" + " GROUP BY svy_questions.SvyCod) AS NumQstsTable", + Gbl.Hierarchy.Cty.CtyCod, + Sco_GetDBStrFromScope (HieLvl_CRS)); + case HieLvl_INS: + return DB_QuerySELECTDouble ("can not get number of questions per survey", + "SELECT AVG(NumQsts)" + " FROM (SELECT COUNT(svy_questions.QstCod) AS NumQsts" + " FROM ctr_centers," + "deg_degrees," + "crs_courses," + "svy_surveys," + "svy_questions" + " WHERE ctr_centers.InsCod=%ld" + " AND ctr_centers.CtrCod=deg_degrees.CtrCod" + " AND deg_degrees.DegCod=crs_courses.DegCod" + " AND crs_courses.CrsCod=svy_surveys.Cod" + " AND svy_surveys.Scope='%s'" + " AND svy_surveys.SvyCod=svy_questions.SvyCod" + " GROUP BY svy_questions.SvyCod) AS NumQstsTable", + Gbl.Hierarchy.Ins.InsCod, + Sco_GetDBStrFromScope (HieLvl_CRS)); + case HieLvl_CTR: + return DB_QuerySELECTDouble ("can not get number of questions per survey", + "SELECT AVG(NumQsts)" + " FROM (SELECT COUNT(svy_questions.QstCod) AS NumQsts" + " FROM deg_degrees," + "crs_courses," + "svy_surveys," + "svy_questions" + " WHERE deg_degrees.CtrCod=%ld" + " AND deg_degrees.DegCod=crs_courses.DegCod" + " AND crs_courses.CrsCod=svy_surveys.Cod" + " AND svy_surveys.Scope='%s'" + " AND svy_surveys.SvyCod=svy_questions.SvyCod" + " GROUP BY svy_questions.SvyCod) AS NumQstsTable", + Gbl.Hierarchy.Ctr.CtrCod, + Sco_GetDBStrFromScope (HieLvl_CRS)); + case HieLvl_DEG: + return DB_QuerySELECTDouble ("can not get number of questions per survey", + "SELECT AVG(NumQsts)" + " FROM (SELECT COUNT(svy_questions.QstCod) AS NumQsts" + " FROM crs_courses," + "svy_surveys," + "svy_questions" + " WHERE crs_courses.DegCod=%ld" + " AND crs_courses.CrsCod=svy_surveys.Cod" + " AND svy_surveys.Scope='%s'" + " AND svy_surveys.SvyCod=svy_questions.SvyCod" + " GROUP BY svy_questions.SvyCod) AS NumQstsTable", + Gbl.Hierarchy.Deg.DegCod, + Sco_GetDBStrFromScope (HieLvl_CRS)); + case HieLvl_CRS: + return DB_QuerySELECTDouble ("can not get number of questions per survey", + "SELECT AVG(NumQsts)" + " FROM (SELECT COUNT(svy_questions.QstCod) AS NumQsts" + " FROM svy_surveys," + "svy_questions" + " WHERE svy_surveys.Scope='%s'" + " AND svy_surveys.Cod=%ld" + " AND svy_surveys.SvyCod=svy_questions.SvyCod" + " GROUP BY svy_questions.SvyCod) AS NumQstsTable", + Sco_GetDBStrFromScope (HieLvl_CRS),Gbl.Hierarchy.Crs.CrsCod); + default: + Err_WrongScopeExit (); + return 0.0; // Not reached + } + } + /*****************************************************************************/ /************ Get all user codes belonging to a survey, except me ************/ /*****************************************************************************/ @@ -118,3 +583,233 @@ unsigned Svy_DB_GetUsrsFromSurveyExceptMe (MYSQL_RES **mysql_res,long SvyCod) Gbl.Usrs.Me.UsrDat.UsrCod, Sco_GetDBStrFromScope (HieLvl_CRS)); } + +/*****************************************************************************/ +/************************* Remove groups of a survey *************************/ +/*****************************************************************************/ + +void Svy_DB_RemoveAllGrpsAssociatedToSurvey (long SvyCod) + { + DB_QueryDELETE ("can not remove the groups associated to a survey", + "DELETE FROM svy_groups" + " WHERE SvyCod=%ld", + SvyCod); + } + +/*****************************************************************************/ +/*************** Remove groups of one type from all the surveys **************/ +/*****************************************************************************/ + +void Svy_DB_RemoveGroupsOfType (long GrpTypCod) + { + /***** Remove group from all the surveys *****/ + DB_QueryDELETE ("can not remove groups of a type" + " from the associations between surveys and groups", + "DELETE FROM svy_groups" + " USING grp_groups," + "svy_groups" + " WHERE grp_groups.GrpTypCod=%ld" + " AND grp_groups.GrpCod=svy_groups.GrpCod", + GrpTypCod); + } + +/*****************************************************************************/ +/******************* Remove one group from all the surveys *******************/ +/*****************************************************************************/ + +void Svy_DB_RemoveGroup (long GrpCod) + { + /***** Remove group from all the surveys *****/ + DB_QueryDELETE ("can not remove group from the associations" + " between surveys and groups", + "DELETE FROM svy_groups" + " WHERE GrpCod=%ld", + GrpCod); + } + +/*****************************************************************************/ +/*********** Change indexes of questions greater than a given one ************/ +/*****************************************************************************/ + +void Svy_DB_ChangeIndexesQsts (long SvyCod,unsigned QstInd) + { + DB_QueryUPDATE ("can not update indexes of questions", + "UPDATE svy_questions" + " SET QstInd=QstInd-1" + " WHERE SvyCod=%ld" + " AND QstInd>%u", + SvyCod, + QstInd); + } + +/*****************************************************************************/ +/******************* Get number of questions of a survey *********************/ +/*****************************************************************************/ + +unsigned Svy_DB_GetNumQstsSvy (long SvyCod) + { + return (unsigned) + DB_QueryCOUNT ("can not get number of questions of a survey", + "SELECT COUNT(*)" + " FROM svy_questions" + " WHERE SvyCod=%ld", + SvyCod); + } + +/*****************************************************************************/ +/***************** Get questions of a survey from database *******************/ +/*****************************************************************************/ + +unsigned Svy_DB_GetSurveyQstsCodes (MYSQL_RES **mysql_res,long SvyCod) + { + return (unsigned) + DB_QuerySELECT (mysql_res,"can not get questions of a survey", + "SELECT QstCod" + " FROM svy_questions" + " WHERE SvyCod=%ld" + " ORDER BY QstCod", + SvyCod); + } + +/*****************************************************************************/ +/***************** Get questions of a survey from database *******************/ +/*****************************************************************************/ + +unsigned Svy_DB_GetSurveyQsts (MYSQL_RES **mysql_res,long SvyCod) + { + return (unsigned) + DB_QuerySELECT (mysql_res,"can not get data of questions of a survey", + "SELECT QstCod," // row[0] + "QstInd," // row[1] + "AnsType," // row[2] + "Stem" // row[3] + " FROM svy_questions" + " WHERE SvyCod=%ld" + " ORDER BY QstInd", + SvyCod); + } + +/*****************************************************************************/ +/************ Get question index from question code in a survey **************/ +/*****************************************************************************/ + +unsigned Svy_DB_GetQstIndFromQstCod (long QstCod) + { + return DB_QuerySELECTUnsigned ("can not get question index", + "SELECT QstInd" + " FROM svy_questions" + " WHERE QstCod=%ld", + QstCod); + } + +/*****************************************************************************/ +/****************************** Remove a question ****************************/ +/*****************************************************************************/ + +void Svy_DB_RemoveQst (long QstCod) + { + DB_QueryDELETE ("can not remove a question", + "DELETE FROM svy_questions" + " WHERE QstCod=%ld", + QstCod); + } + +/*****************************************************************************/ +/************ Increase number of users who have marked one answer ************/ +/*****************************************************************************/ + +void Svy_DB_IncreaseAnswer (long QstCod,unsigned AnsInd) + { + /***** Increase number of users who have selected + the answer AnsInd in the question QstCod *****/ + DB_QueryUPDATE ("can not register your answer to the survey", + "UPDATE svy_answers" + " SET NumUsrs=NumUsrs+1" + " WHERE QstCod=%ld" + " AND AnsInd=%u", + QstCod, + AnsInd); + } + +/*****************************************************************************/ +/*********** Check if an answer of a question exists in database *************/ +/*****************************************************************************/ + +bool Svy_DB_CheckIfAnswerExists (long QstCod,unsigned AnsInd) + { + return (DB_QueryCOUNT ("can not check if an answer exists", + "SELECT COUNT(*)" + " FROM svy_answers" + " WHERE QstCod=%ld" + " AND AnsInd=%u", + QstCod, + AnsInd) != 0); + } + +/*****************************************************************************/ +/************** Get answers of a survey question from database ***************/ +/*****************************************************************************/ + +unsigned Svy_DB_GetAnswersQst (MYSQL_RES **mysql_res,long QstCod) + { + unsigned NumAnswers; + + /***** Get answers of a question from database *****/ + NumAnswers = (unsigned) + DB_QuerySELECT (mysql_res,"can not get answers of a question", + "SELECT AnsInd," // row[0] + "NumUsrs," // row[1] + "Answer" // row[2] + " FROM svy_answers" + " WHERE QstCod=%ld" + " ORDER BY AnsInd", + QstCod); + if (!NumAnswers) + Err_WrongAnswerExit (); + + return NumAnswers; + } + +/*****************************************************************************/ +/***************** Register that I have answered this survey *****************/ +/*****************************************************************************/ + +void Svy_DB_RegisterIHaveAnsweredSvy (long SvyCod) + { + DB_QueryINSERT ("can not register that you have answered the survey", + "INSERT INTO svy_users" + " (SvyCod,UsrCod)" + " VALUES" + " (%ld,%ld)", + SvyCod, + Gbl.Usrs.Me.UsrDat.UsrCod); + } + +/*****************************************************************************/ +/**************** Check if I have answered a given survey ********************/ +/*****************************************************************************/ + +bool Svy_DB_CheckIfIHaveAnsweredSvy (long SvyCod) + { + return (DB_QueryCOUNT ("can not check if you have answered a survey", + "SELECT COUNT(*)" + " FROM svy_users" + " WHERE SvyCod=%ld" + " AND UsrCod=%ld", + SvyCod, + Gbl.Usrs.Me.UsrDat.UsrCod) != 0); + } + +/*****************************************************************************/ +/************** Get number of users who have answered a survey ***************/ +/*****************************************************************************/ + +unsigned Svy_DB_GetNumUsrsWhoHaveAnsweredSvy (long SvyCod) + { + return (unsigned) + DB_QueryCOUNT ("can not get number of users who have answered a survey", + "SELECT COUNT(*)" + " FROM svy_users" + " WHERE SvyCod=%ld", + SvyCod); + } diff --git a/swad_survey_database.h b/swad_survey_database.h index bc7157a6..e8d4f0a5 100644 --- a/swad_survey_database.h +++ b/swad_survey_database.h @@ -29,7 +29,8 @@ #include // To access MySQL databases -// #include "swad_date.h" +#include "swad_constant.h" +#include "swad_date.h" /*****************************************************************************/ /************************** Public types and constants ***********************/ @@ -39,6 +40,45 @@ /***************************** Public prototypes *****************************/ /*****************************************************************************/ +//-------------------------------- Surveys ------------------------------------ +void Svy_DB_UpdateNumUsrsNotifiedByEMailAboutSurvey (long SvyCod, + unsigned NumUsrsToBeNotifiedByEMail); +unsigned Svy_DB_GetListSurveys (MYSQL_RES **mysql_res, + unsigned ScopesAllowed, + unsigned HiddenAllowed, + Dat_StartEndTime_t SelectedOrder); +void Svy_DB_GetSurveyTxt (long SvyCod,char Txt[Cns_MAX_BYTES_TEXT + 1]); +bool Svy_DB_CheckIfSimilarSurveyExists (const struct Svy_Survey *Svy); +unsigned Svy_DB_GetNumCrssWithCrsSurveys (HieLvl_Level_t Scope); +unsigned Svy_DB_GetNumCrsSurveys (MYSQL_RES **mysql_res,HieLvl_Level_t Scope); +double Svy_DB_GetNumQstsPerCrsSurvey (HieLvl_Level_t Scope); unsigned Svy_DB_GetUsrsFromSurveyExceptMe (MYSQL_RES **mysql_res,long SvyCod); +//---------------------------- Surveys groups --------------------------------- +void Svy_DB_RemoveAllGrpsAssociatedToSurvey (long SvyCod); +void Svy_DB_RemoveGroupsOfType (long GrpTypCod); +void Svy_DB_RemoveGroup (long GrpCod); + +//--------------------------- Surveys questions ------------------------------- +void Svy_DB_ChangeIndexesQsts (long SvyCod,unsigned QstInd); + +unsigned Svy_DB_GetNumQstsSvy (long SvyCod); +unsigned Svy_DB_GetSurveyQstsCodes (MYSQL_RES **mysql_res,long SvyCod); +unsigned Svy_DB_GetSurveyQsts (MYSQL_RES **mysql_res,long SvyCod); +unsigned Svy_DB_GetQstIndFromQstCod (long QstCod); + +void Svy_DB_RemoveQst (long QstCod); + +//---------------------------- Surveys answers -------------------------------- +void Svy_DB_IncreaseAnswer (long QstCod,unsigned AnsInd); + +bool Svy_DB_CheckIfAnswerExists (long QstCod,unsigned AnsInd); +unsigned Svy_DB_GetAnswersQst (MYSQL_RES **mysql_res,long QstCod); + +//--------------------- Users who have answered surveys ----------------------- +void Svy_DB_RegisterIHaveAnsweredSvy (long SvyCod); + +bool Svy_DB_CheckIfIHaveAnsweredSvy (long SvyCod); +unsigned Svy_DB_GetNumUsrsWhoHaveAnsweredSvy (long SvyCod); + #endif