// swad_assignment.c: assignments /* SWAD (Shared Workspace At a Distance), is a web platform developed at the University of Granada (Spain), and used to support university teaching. This file is part of SWAD core. Copyright (C) 1999-2016 Antonio Caņas Vargas This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ /*****************************************************************************/ /********************************* Headers ***********************************/ /*****************************************************************************/ #include // For PATH_MAX #include // For NULL #include // For calloc #include // For string functions #include "swad_assignment.h" #include "swad_database.h" #include "swad_global.h" #include "swad_group.h" #include "swad_notification.h" #include "swad_pagination.h" #include "swad_parameter.h" #include "swad_photo.h" #include "swad_string.h" /*****************************************************************************/ /************** External global variables from others modules ****************/ /*****************************************************************************/ extern struct Globals Gbl; /*****************************************************************************/ /***************************** Private constants *****************************/ /*****************************************************************************/ /*****************************************************************************/ /******************************* Private types *******************************/ /*****************************************************************************/ /*****************************************************************************/ /***************************** Private variables *****************************/ /*****************************************************************************/ /*****************************************************************************/ /***************************** Private prototypes ****************************/ /*****************************************************************************/ static void Asg_ShowAllAssignments (void); static void Asg_PutFormToSelectWhichGroupsToShow (void); static void Asg_ShowOneAssignment (long AsgCod); static void Asg_WriteAsgAuthor (struct Assignment *Asg); static void Asg_WriteAssignmentFolder (struct Assignment *Asg); static void Asg_GetParamAsgOrderType (void); static void Asg_PutFormToCreateNewAsg (void); static void Asg_PutFormToCreateNewAsgParams (void); static void Asg_PutFormsToRemEditOneAsg (long AsgCod,bool Hidden); static void Asg_PutParams (void); static void Asg_GetDataOfAssignment (struct Assignment *Asg,const char *Query); static void Asg_GetAssignmentTxtFromDB (long AsgCod,char *Txt); static void Asg_PutParamAsgCod (long AsgCod); static bool Asg_CheckIfSimilarAssignmentExists (const char *Field,const char *Value,long AsgCod); static void Asg_ShowLstGrpsToEditAssignment (long AsgCod); static void Asg_UpdateNumUsrsNotifiedByEMailAboutAssignment (long AsgCod,unsigned NumUsrsToBeNotifiedByEMail); static void Asg_CreateAssignment (struct Assignment *Asg,const char *Txt); static void Asg_UpdateAssignment (struct Assignment *Asg,const char *Txt); static bool Asg_CheckIfAsgIsAssociatedToGrps (long AsgCod); static void Asg_RemoveAllTheGrpsAssociatedToAnAssignment (long AsgCod); static void Asg_CreateGrps (long AsgCod); static void Asg_GetAndWriteNamesOfGrpsAssociatedToAsg (struct Assignment *Asg); static bool Asg_CheckIfIBelongToCrsOrGrpsThisAssignment (long AsgCod); /*****************************************************************************/ /************************ List all the assignments ***************************/ /*****************************************************************************/ void Asg_SeeAssignments (void) { /***** Get parameters *****/ Asg_GetParamAsgOrderType (); Grp_GetParamWhichGrps (); Pag_GetParamPagNum (Pag_ASSIGNMENTS); /***** Put link (form) to create a bew assignment *****/ switch (Gbl.Usrs.Me.LoggedRole) { case Rol_TEACHER: case Rol_SYS_ADM: Asg_PutFormToCreateNewAsg (); break; default: break; } /***** Show all the assignments *****/ Asg_ShowAllAssignments (); } /*****************************************************************************/ /************************ Show all the assignments ***************************/ /*****************************************************************************/ static void Asg_ShowAllAssignments (void) { extern const char *Txt_Assignments; extern const char *Txt_ASG_ATT_OR_SVY_HELP_ORDER[2]; extern const char *Txt_ASG_ATT_OR_SVY_ORDER[2]; extern const char *Txt_Assignment; extern const char *Txt_Upload_files_QUESTION; extern const char *Txt_Folder; tAsgsOrderType Order; struct Pagination Pagination; unsigned NumAsg; /***** Get list of assignments *****/ Asg_GetListAssignments (); /***** Compute variables related to pagination *****/ Pagination.NumItems = Gbl.Asgs.Num; Pagination.CurrentPage = (int) Gbl.Pag.CurrentPage; Pag_CalculatePagination (&Pagination); Gbl.Pag.CurrentPage = (unsigned) Pagination.CurrentPage; /***** Write links to pages *****/ if (Pagination.MoreThanOnePage) Pag_WriteLinksToPagesCentered (Pag_ASSIGNMENTS,0,&Pagination); /***** Start table *****/ Lay_StartRoundFrameTable (NULL,2,Txt_Assignments); /***** Select whether show only my groups or all groups *****/ if (Gbl.CurrentCrs.Grps.NumGrps) { fprintf (Gbl.F.Out,"" ""); Asg_PutFormToSelectWhichGroupsToShow (); fprintf (Gbl.F.Out,"" ""); } /***** Table head *****/ fprintf (Gbl.F.Out,""); for (Order = Asg_ORDER_BY_START_DATE; Order <= Asg_ORDER_BY_END_DATE; Order++) { fprintf (Gbl.F.Out,""); Act_FormStart (ActSeeAsg); Grp_PutParamWhichGrps (); Pag_PutHiddenParamPagNum (Gbl.Pag.CurrentPage); Par_PutHiddenParamUnsigned ("Order",(unsigned) Order); Act_LinkFormSubmit (Txt_ASG_ATT_OR_SVY_HELP_ORDER[Order],"TIT_TBL"); if (Order == Gbl.Asgs.SelectedOrderType) fprintf (Gbl.F.Out,""); fprintf (Gbl.F.Out,"%s",Txt_ASG_ATT_OR_SVY_ORDER[Order]); if (Order == Gbl.Asgs.SelectedOrderType) fprintf (Gbl.F.Out,""); fprintf (Gbl.F.Out,""); Act_FormEnd (); fprintf (Gbl.F.Out,""); } fprintf (Gbl.F.Out,"" "%s" "" "" "%s" "" "" "%s" "" "", Txt_Assignment, Txt_Upload_files_QUESTION, Txt_Folder); /***** Write all the assignments *****/ for (NumAsg = Pagination.FirstItemVisible; NumAsg <= Pagination.LastItemVisible; NumAsg++) Asg_ShowOneAssignment (Gbl.Asgs.LstAsgCods[NumAsg-1]); /***** Table end *****/ Lay_EndRoundFrameTable (); /***** Write again links to pages *****/ if (Pagination.MoreThanOnePage) Pag_WriteLinksToPagesCentered (Pag_ASSIGNMENTS,0,&Pagination); /***** Free list of assignments *****/ Asg_FreeListAssignments (); } /*****************************************************************************/ /***************** Put form to select which groups to show *******************/ /*****************************************************************************/ static void Asg_PutFormToSelectWhichGroupsToShow (void) { Act_FormStart (ActSeeAsg); Asg_PutHiddenParamAsgOrderType (); Pag_PutHiddenParamPagNum (Gbl.Pag.CurrentPage); Grp_ShowSelectorWhichGrps (); Act_FormEnd (); } /*****************************************************************************/ /*************************** Show one assignment *****************************/ /*****************************************************************************/ static void Asg_ShowOneAssignment (long AsgCod) { extern const char *Txt_Today; extern const char *Txt_ASSIGNMENT_TYPES[Asg_NUM_TYPES_SEND_WORK]; extern const char *Txt_Yes; extern const char *Txt_No; static unsigned UniqueId = 0; struct Assignment Asg; char Txt[Cns_MAX_BYTES_TEXT+1]; /***** Get data of this assignment *****/ Asg.AsgCod = AsgCod; Asg_GetDataOfAssignmentByCod (&Asg); /***** Write first row of data of this assignment *****/ /* Start date/time */ UniqueId++; fprintf (Gbl.F.Out,"" "" "" "", UniqueId, Asg.Hidden ? (Asg.Open ? "DATE_GREEN_LIGHT" : "DATE_RED_LIGHT") : (Asg.Open ? "DATE_GREEN" : "DATE_RED"), Gbl.RowEvenOdd, UniqueId,Asg.TimeUTC[Asg_START_TIME],Txt_Today); /* End date/time */ UniqueId++; fprintf (Gbl.F.Out,"" "" "", UniqueId, Asg.Hidden ? (Asg.Open ? "DATE_GREEN_LIGHT" : "DATE_RED_LIGHT") : (Asg.Open ? "DATE_GREEN" : "DATE_RED"), Gbl.RowEvenOdd, UniqueId,Asg.TimeUTC[Asg_END_TIME],Txt_Today); /* Assignment title */ fprintf (Gbl.F.Out,"" "
%s
", Gbl.RowEvenOdd, Asg.Hidden ? "ASG_TITLE_LIGHT" : "ASG_TITLE", Asg.Title); fprintf (Gbl.F.Out,""); /* Send work? */ fprintf (Gbl.F.Out,"" "\"%s\"" "
%s" "", (Asg.SendWork == Asg_SEND_WORK) ? "DAT_N" : "DAT", Gbl.RowEvenOdd, Gbl.Prefs.IconsURL, (Asg.SendWork == Asg_SEND_WORK) ? "file_on" : "file_off", Txt_ASSIGNMENT_TYPES[Asg.SendWork], Txt_ASSIGNMENT_TYPES[Asg.SendWork], (Asg.SendWork == Asg_SEND_WORK) ? Txt_Yes : Txt_No); /* Assignment folder */ fprintf (Gbl.F.Out,"", Gbl.RowEvenOdd); Asg_WriteAssignmentFolder (&Asg); fprintf (Gbl.F.Out,"" ""); /***** Write second row of data of this assignment *****/ fprintf (Gbl.F.Out,"" "", Gbl.RowEvenOdd); /* Author of the assignment */ Asg_WriteAsgAuthor (&Asg); /* Forms to remove/edit this assignment */ switch (Gbl.Usrs.Me.LoggedRole) { case Rol_TEACHER: case Rol_SYS_ADM: Asg_PutFormsToRemEditOneAsg (Asg.AsgCod,Asg.Hidden); break; default: break; } fprintf (Gbl.F.Out,""); /* Text of the assignment */ Asg_GetAssignmentTxtFromDB (Asg.AsgCod,Txt); Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML, Txt,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to recpectful HTML Str_InsertLinks (Txt,Cns_MAX_BYTES_TEXT,60); // Insert links fprintf (Gbl.F.Out,"", Gbl.RowEvenOdd); if (Gbl.CurrentCrs.Grps.NumGrps) Asg_GetAndWriteNamesOfGrpsAssociatedToAsg (&Asg); fprintf (Gbl.F.Out,"

" "%s" "

" "" "", Asg.Hidden ? "DAT_LIGHT" : "DAT", Txt); Gbl.RowEvenOdd = 1 - Gbl.RowEvenOdd; /***** Mark possible notification as seen *****/ Ntf_MarkNotifAsSeen (Ntf_EVENT_ASSIGNMENT, AsgCod,Gbl.CurrentCrs.Crs.CrsCod, Gbl.Usrs.Me.UsrDat.UsrCod); } /*****************************************************************************/ /********************* Write the author of an assignment *********************/ /*****************************************************************************/ static void Asg_WriteAsgAuthor (struct Assignment *Asg) { bool ShowPhoto = false; char PhotoURL[PATH_MAX+1]; char FirstName[Usr_MAX_BYTES_NAME+1]; char Surnames[2*(Usr_MAX_BYTES_NAME+1)]; struct UsrData UsrDat; /***** Initialize structure with user's data *****/ Usr_UsrDataConstructor (&UsrDat); /***** Get data of author *****/ UsrDat.UsrCod = Asg->UsrCod; if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat)) ShowPhoto = Pho_ShowUsrPhotoIsAllowed (&UsrDat,PhotoURL); /***** Show photo *****/ Pho_ShowUsrPhoto (&UsrDat,ShowPhoto ? PhotoURL : NULL, "PHOTO15x20",Pho_ZOOM,false); /***** Write name *****/ strcpy (FirstName,UsrDat.FirstName); strcpy (Surnames,UsrDat.Surname1); if (UsrDat.Surname2[0]) { strcat (Surnames," "); strcat (Surnames,UsrDat.Surname2); } Str_LimitLengthHTMLStr (FirstName,9); Str_LimitLengthHTMLStr (Surnames,9); fprintf (Gbl.F.Out,"%s %s", Asg->Hidden ? "MSG_AUT_LIGHT" : "MSG_AUT", FirstName,Surnames); /***** Free memory used for user's data *****/ Usr_UsrDataDestructor (&UsrDat); } /*****************************************************************************/ /********************* Write the folder of an assignment *********************/ /*****************************************************************************/ static void Asg_WriteAssignmentFolder (struct Assignment *Asg) { extern const char *Txt_Upload_file_or_create_folder_in_FOLDER; extern const char *Txt_Folder; if (Asg->SendWork == Asg_SEND_WORK) { /***** Folder icon *****/ if (Gbl.Usrs.Me.LoggedRole == Rol_STUDENT && Asg->Open && Asg->IBelongToCrsOrGrps) // I can send files to this assignment folder { /* Form to create a new file or folder */ Act_FormStart (ActFrmCreAsgUsr); Brw_PutParamsPathAndFile (Brw_IS_FOLDER,Brw_INTERNAL_NAME_ROOT_FOLDER_ASSIGNMENTS,Asg->Folder); sprintf (Gbl.Title,Txt_Upload_file_or_create_folder_in_FOLDER, Asg->Folder); fprintf (Gbl.F.Out,"", Gbl.Prefs.IconsURL, Gbl.Title, Gbl.Title); Act_FormEnd (); } else // I can't send files to this assignment folder fprintf (Gbl.F.Out,"\"%s\"", Gbl.Prefs.IconsURL, Txt_Folder,Txt_Folder); /***** Folder name *****/ fprintf (Gbl.F.Out,"%s",Asg->Folder); } } /*****************************************************************************/ /******* Get parameter with the type or order in list of assignments *********/ /*****************************************************************************/ static void Asg_GetParamAsgOrderType (void) { char UnsignedStr[10+1]; unsigned UnsignedNum; Par_GetParToText ("Order",UnsignedStr,10); if (sscanf (UnsignedStr,"%u",&UnsignedNum) == 1) Gbl.Asgs.SelectedOrderType = (tAsgsOrderType) UnsignedNum; else Gbl.Asgs.SelectedOrderType = Asg_DEFAULT_ORDER_TYPE; } /*****************************************************************************/ /*** Put a hidden parameter with the type of order in list of assignments ****/ /*****************************************************************************/ void Asg_PutHiddenParamAsgOrderType (void) { Par_PutHiddenParamUnsigned ("Order",(unsigned) Gbl.Asgs.SelectedOrderType); } /*****************************************************************************/ /************** Put a link (form) to create a new assignment *****************/ /*****************************************************************************/ static void Asg_PutFormToCreateNewAsg (void) { extern const char *Txt_New_assignment; /***** Put form to create a new assignment *****/ fprintf (Gbl.F.Out,"
"); Lay_PutContextualLink (ActFrmNewAsg,Asg_PutFormToCreateNewAsgParams, "plus64x64.png", Txt_New_assignment,Txt_New_assignment); fprintf (Gbl.F.Out,"
"); } static void Asg_PutFormToCreateNewAsgParams (void) { Asg_PutHiddenParamAsgOrderType (); Grp_PutParamWhichGrps (); Pag_PutHiddenParamPagNum (Gbl.Pag.CurrentPage); } /*****************************************************************************/ /***************** Put a link (form) to edit one assignment ******************/ /*****************************************************************************/ static void Asg_PutFormsToRemEditOneAsg (long AsgCod,bool Hidden) { extern const char *Txt_Remove; extern const char *Txt_Show; extern const char *Txt_Hide; extern const char *Txt_Edit; fprintf (Gbl.F.Out,"
"); Gbl.Asgs.AsgCodToEdit = AsgCod; // Used as parameter in contextual links /***** Put form to remove assignment *****/ Lay_PutContextualLink (ActReqRemAsg,Asg_PutParams,"remove-on64x64.png", Txt_Remove,NULL); /***** Put form to hide/show assignment *****/ if (Hidden) Lay_PutContextualLink (ActShoAsg,Asg_PutParams,"eye-slash-on64x64.png", Txt_Show,NULL); else Lay_PutContextualLink (ActHidAsg,Asg_PutParams,"eye-on64x64.png", Txt_Hide,NULL); /***** Put form to edit assignment *****/ Lay_PutContextualLink (ActEdiOneAsg,Asg_PutParams,"edit64x64.png", Txt_Edit,NULL); fprintf (Gbl.F.Out,"
"); } /*****************************************************************************/ /******************** Params used to edit an assignment **********************/ /*****************************************************************************/ static void Asg_PutParams (void) { Asg_PutParamAsgCod (Gbl.Asgs.AsgCodToEdit); Asg_PutHiddenParamAsgOrderType (); Grp_PutParamWhichGrps (); Pag_PutHiddenParamPagNum (Gbl.Pag.CurrentPage); } /*****************************************************************************/ /************************ List all the assignments ***************************/ /*****************************************************************************/ void Asg_GetListAssignments (void) { char HiddenSubQuery[256]; char OrderBySubQuery[256]; char Query[2048]; MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned long NumRows; unsigned NumAsg; if (Gbl.Asgs.LstIsRead) Asg_FreeListAssignments (); /***** Get list of assignments from database *****/ switch (Gbl.Usrs.Me.LoggedRole) { case Rol_TEACHER: case Rol_SYS_ADM: HiddenSubQuery[0] = '\0'; break; default: sprintf (HiddenSubQuery,"AND Hidden='N'"); break; } switch (Gbl.Asgs.SelectedOrderType) { case Asg_ORDER_BY_START_DATE: sprintf (OrderBySubQuery,"StartTime DESC,EndTime DESC,Title DESC"); break; case Asg_ORDER_BY_END_DATE: sprintf (OrderBySubQuery,"EndTime DESC,StartTime DESC,Title DESC"); break; } if (Gbl.CurrentCrs.Grps.WhichGrps == Grp_ONLY_MY_GROUPS) sprintf (Query,"SELECT AsgCod" " FROM assignments" " WHERE CrsCod='%ld'%s" " AND (AsgCod NOT IN (SELECT AsgCod FROM asg_grp) OR" " AsgCod IN (SELECT asg_grp.AsgCod FROM asg_grp,crs_grp_usr" " WHERE crs_grp_usr.UsrCod='%ld' AND asg_grp.GrpCod=crs_grp_usr.GrpCod))" " ORDER BY %s", Gbl.CurrentCrs.Crs.CrsCod, HiddenSubQuery, Gbl.Usrs.Me.UsrDat.UsrCod, OrderBySubQuery); else // Gbl.CurrentCrs.Grps.WhichGrps == Grp_ALL_GROUPS sprintf (Query,"SELECT AsgCod" " FROM assignments" " WHERE CrsCod='%ld'%s" " ORDER BY %s", Gbl.CurrentCrs.Crs.CrsCod,HiddenSubQuery,OrderBySubQuery); NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get assignments"); if (NumRows) // Assignments found... { Gbl.Asgs.Num = (unsigned) NumRows; /***** Create list of assignments *****/ if ((Gbl.Asgs.LstAsgCods = (long *) calloc (NumRows,sizeof (long))) == NULL) Lay_ShowErrorAndExit ("Not enough memory to store list of assignments."); /***** Get the assignments codes *****/ for (NumAsg = 0; NumAsg < Gbl.Asgs.Num; NumAsg++) { /* Get next assignment code */ row = mysql_fetch_row (mysql_res); if ((Gbl.Asgs.LstAsgCods[NumAsg] = Str_ConvertStrCodToLongCod (row[0])) < 0) Lay_ShowErrorAndExit ("Error: wrong assignment code."); } } else Gbl.Asgs.Num = 0; /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); Gbl.Asgs.LstIsRead = true; } /*****************************************************************************/ /******************* Get assignment data using its code **********************/ /*****************************************************************************/ void Asg_GetDataOfAssignmentByCod (struct Assignment *Asg) { char Query[1024]; /***** Build query *****/ sprintf (Query,"SELECT AsgCod,Hidden,UsrCod," "UNIX_TIMESTAMP(StartTime)," "UNIX_TIMESTAMP(EndTime)," "NOW() BETWEEN StartTime AND EndTime," "Title,Folder" " FROM assignments" " WHERE AsgCod='%ld' AND CrsCod='%ld'", Asg->AsgCod,Gbl.CurrentCrs.Crs.CrsCod); /***** Get data of assignment *****/ Asg_GetDataOfAssignment (Asg,Query); } /*****************************************************************************/ /*************** Get assignment data using its folder name *******************/ /*****************************************************************************/ void Asg_GetDataOfAssignmentByFolder (struct Assignment *Asg) { char Query[1024]; /***** Query database *****/ sprintf (Query,"SELECT AsgCod,Hidden,UsrCod," "UNIX_TIMESTAMP(StartTime)," "UNIX_TIMESTAMP(EndTime)," "NOW() BETWEEN StartTime AND EndTime," "Title,Folder" " FROM assignments" " WHERE CrsCod='%ld' AND Folder='%s'", Gbl.CurrentCrs.Crs.CrsCod,Asg->Folder); /***** Get data of assignment *****/ Asg_GetDataOfAssignment (Asg,Query); } /*****************************************************************************/ /************************* Get assignment data *******************************/ /*****************************************************************************/ static void Asg_GetDataOfAssignment (struct Assignment *Asg,const char *Query) { MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned long NumRows; /***** Clear data *****/ Asg->TimeUTC[Asg_START_TIME] = Asg->TimeUTC[Asg_END_TIME ] = (time_t) 0; Asg->Title[0] = '\0'; /***** Get data of assignment from database *****/ NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get assignment data"); if (NumRows) // Assignment found... { /* Get row */ row = mysql_fetch_row (mysql_res); /* Get code of the assignment (row[0]) */ Asg->AsgCod = Str_ConvertStrCodToLongCod (row[0]); /* Get wether the assignment is hidden or not (row[1]) */ Asg->Hidden = (Str_ConvertToUpperLetter (row[1][0]) == 'Y'); /* Get author of the assignment (row[2]) */ Asg->UsrCod = Str_ConvertStrCodToLongCod (row[2]); /* Get start date (row[3] holds the start UTC time) */ Asg->TimeUTC[Asg_START_TIME] = Dat_GetUNIXTimeFromStr (row[3]); /* Get end date (row[4] holds the end UTC time) */ Asg->TimeUTC[Asg_END_TIME ] = Dat_GetUNIXTimeFromStr (row[4]); /* Get whether the assignment is open or closed (row(5)) */ Asg->Open = (row[5][0] == '1'); /* Get the title of the assignment (row[6]) */ strcpy (Asg->Title,row[6]); /* Get the folder for the assignment files (row[7]) */ strcpy (Asg->Folder,row[7]); Asg->SendWork = (Asg->Folder[0] != '\0'); /* Can I do this assignment? */ Asg->IBelongToCrsOrGrps = Asg_CheckIfIBelongToCrsOrGrpsThisAssignment (Asg->AsgCod); } else { /* Initialize to empty assignment */ Asg->AsgCod = -1L; Asg->Hidden = false; Asg->Open = false; Asg->Title[0] = '\0'; Asg->SendWork = false; Asg->Folder[0] = '\0'; Asg->IBelongToCrsOrGrps = false; } /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); } /*****************************************************************************/ /************************* Free list of assignments **************************/ /*****************************************************************************/ void Asg_FreeListAssignments (void) { if (Gbl.Asgs.LstIsRead && Gbl.Asgs.LstAsgCods) { /***** Free memory used by the list of assignments *****/ free ((void *) Gbl.Asgs.LstAsgCods); Gbl.Asgs.LstAsgCods = NULL; Gbl.Asgs.Num = 0; Gbl.Asgs.LstIsRead = false; } } /*****************************************************************************/ /******************** Get assignment text from database **********************/ /*****************************************************************************/ static void Asg_GetAssignmentTxtFromDB (long AsgCod,char *Txt) { char Query[512]; MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned long NumRows; /***** Get text of assignment from database *****/ sprintf (Query,"SELECT Txt FROM assignments" " WHERE AsgCod='%ld' AND CrsCod='%ld'", AsgCod,Gbl.CurrentCrs.Crs.CrsCod); NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get assignment text"); /***** The result of the query must have one row or none *****/ if (NumRows == 1) { /* Get info text */ row = mysql_fetch_row (mysql_res); strcpy (Txt,row[0]); } else Txt[0] = '\0'; /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); if (NumRows > 1) Lay_ShowErrorAndExit ("Error when getting assignment text."); } /*****************************************************************************/ /***************** Get summary and content of an assignment *****************/ /*****************************************************************************/ // This function may be called inside a web service void Asg_GetNotifAssignment (char *SummaryStr,char **ContentStr, long AsgCod,unsigned MaxChars,bool GetContent) { char Query[512]; MYSQL_RES *mysql_res; MYSQL_ROW row; SummaryStr[0] = '\0'; // Return nothing on error /***** Build query *****/ sprintf (Query,"SELECT Title,Txt FROM assignments WHERE AsgCod='%ld'", AsgCod); if (!mysql_query (&Gbl.mysql,Query)) if ((mysql_res = mysql_store_result (&Gbl.mysql)) != NULL) { /***** Result should have a unique row *****/ if (mysql_num_rows (mysql_res) == 1) { /***** Get row *****/ row = mysql_fetch_row (mysql_res); /***** Get summary *****/ strcpy (SummaryStr,row[0]); if (MaxChars) Str_LimitLengthHTMLStr (SummaryStr,MaxChars); /***** Get content *****/ if (GetContent) { if ((*ContentStr = (char *) malloc (512+Cns_MAX_BYTES_TEXT)) == NULL) Lay_ShowErrorAndExit ("Error allocating memory for notification content."); strcpy (*ContentStr,row[1]); } } mysql_free_result (mysql_res); } } /*****************************************************************************/ /***************** Write parameter with code of assignment *******************/ /*****************************************************************************/ static void Asg_PutParamAsgCod (long AsgCod) { Par_PutHiddenParamLong ("AsgCod",AsgCod); } /*****************************************************************************/ /****************** Get parameter with code of assignment ********************/ /*****************************************************************************/ long Asg_GetParamAsgCod (void) { char LongStr[1+10+1]; /***** Get parameter with code of assignment *****/ Par_GetParToText ("AsgCod",LongStr,1+10); return Str_ConvertStrCodToLongCod (LongStr); } /*****************************************************************************/ /************ Ask for confirmation of removing of an assignment **************/ /*****************************************************************************/ void Asg_AskRemAssignment (void) { extern const char *Txt_Do_you_really_want_to_remove_the_assignment_X; extern const char *Txt_Remove_assignment; struct Assignment Asg; /***** Get parameters *****/ Asg_GetParamAsgOrderType (); Grp_GetParamWhichGrps (); Pag_GetParamPagNum (Pag_ASSIGNMENTS); /***** Get assignment code *****/ if ((Asg.AsgCod = Asg_GetParamAsgCod ()) == -1L) Lay_ShowErrorAndExit ("Code of assignment is missing."); /***** Get data of the assignment from database *****/ Asg_GetDataOfAssignmentByCod (&Asg); /***** Button of confirmation of removing *****/ Act_FormStart (ActRemAsg); Asg_PutParamAsgCod (Asg.AsgCod); Asg_PutHiddenParamAsgOrderType (); Grp_PutParamWhichGrps (); Pag_PutHiddenParamPagNum (Gbl.Pag.CurrentPage); /***** Ask for confirmation of removing *****/ sprintf (Gbl.Message,Txt_Do_you_really_want_to_remove_the_assignment_X, Asg.Title); Lay_ShowAlert (Lay_WARNING,Gbl.Message); Lay_PutRemoveButton (Txt_Remove_assignment); Act_FormEnd (); /***** Show assignments again *****/ Asg_SeeAssignments (); } /*****************************************************************************/ /*************************** Remove an assignment ****************************/ /*****************************************************************************/ void Asg_RemoveAssignment (void) { extern const char *Txt_Assignment_X_removed; char Query[512]; struct Assignment Asg; /***** Get assignment code *****/ if ((Asg.AsgCod = Asg_GetParamAsgCod ()) == -1L) Lay_ShowErrorAndExit ("Code of assignment is missing."); /***** Get data of the assignment from database *****/ Asg_GetDataOfAssignmentByCod (&Asg); // Inside this function, the course is checked to be the current one /***** Remove all the folders associated to this assignment *****/ if (Asg.Folder[0]) Brw_RemoveFoldersAssignmentsIfExistForAllUsrs (Asg.Folder); /***** Remove all the groups of this assignment *****/ Asg_RemoveAllTheGrpsAssociatedToAnAssignment (Asg.AsgCod); /***** Remove assignment *****/ sprintf (Query,"DELETE FROM assignments" " WHERE AsgCod='%ld' AND CrsCod='%ld'", Asg.AsgCod,Gbl.CurrentCrs.Crs.CrsCod); DB_QueryDELETE (Query,"can not remove assignment"); /***** Mark possible notifications as removed *****/ Ntf_MarkNotifAsRemoved (Ntf_EVENT_ASSIGNMENT,Asg.AsgCod); /***** Write message to show the change made *****/ sprintf (Gbl.Message,Txt_Assignment_X_removed, Asg.Title); Lay_ShowAlert (Lay_SUCCESS,Gbl.Message); /***** Show assignments again *****/ Asg_SeeAssignments (); } /*****************************************************************************/ /**************************** Hide an assignment *****************************/ /*****************************************************************************/ void Asg_HideAssignment (void) { extern const char *Txt_Assignment_X_is_now_hidden; char Query[512]; struct Assignment Asg; /***** Get assignment code *****/ if ((Asg.AsgCod = Asg_GetParamAsgCod ()) == -1L) Lay_ShowErrorAndExit ("Code of assignment is missing."); /***** Get data of the assignment from database *****/ Asg_GetDataOfAssignmentByCod (&Asg); /***** Hide assignment *****/ sprintf (Query,"UPDATE assignments SET Hidden='Y'" " WHERE AsgCod='%ld' AND CrsCod='%ld'", Asg.AsgCod,Gbl.CurrentCrs.Crs.CrsCod); DB_QueryUPDATE (Query,"can not hide assignment"); /***** Write message to show the change made *****/ sprintf (Gbl.Message,Txt_Assignment_X_is_now_hidden, Asg.Title); Lay_ShowAlert (Lay_SUCCESS,Gbl.Message); /***** Show assignments again *****/ Asg_SeeAssignments (); } /*****************************************************************************/ /**************************** Show an assignment *****************************/ /*****************************************************************************/ void Asg_ShowAssignment (void) { extern const char *Txt_Assignment_X_is_now_visible; char Query[512]; struct Assignment Asg; /***** Get assignment code *****/ if ((Asg.AsgCod = Asg_GetParamAsgCod ()) == -1L) Lay_ShowErrorAndExit ("Code of assignment is missing."); /***** Get data of the assignment from database *****/ Asg_GetDataOfAssignmentByCod (&Asg); /***** Hide assignment *****/ sprintf (Query,"UPDATE assignments SET Hidden='N'" " WHERE AsgCod='%ld' AND CrsCod='%ld'", Asg.AsgCod,Gbl.CurrentCrs.Crs.CrsCod); DB_QueryUPDATE (Query,"can not show assignment"); /***** Write message to show the change made *****/ sprintf (Gbl.Message,Txt_Assignment_X_is_now_visible, Asg.Title); Lay_ShowAlert (Lay_SUCCESS,Gbl.Message); /***** Show assignments again *****/ Asg_SeeAssignments (); } /*****************************************************************************/ /******** Check if the title or the folder of an assignment exists ***********/ /*****************************************************************************/ static bool Asg_CheckIfSimilarAssignmentExists (const char *Field,const char *Value,long AsgCod) { char Query[512]; /***** Get number of assignments with a field value from database *****/ sprintf (Query,"SELECT COUNT(*) FROM assignments" " WHERE CrsCod='%ld' AND %s='%s' AND AsgCod<>'%ld'", Gbl.CurrentCrs.Crs.CrsCod,Field,Value,AsgCod); return (DB_QueryCOUNT (Query,"can not get similar assignments") != 0); } /*****************************************************************************/ /****************** Put a form to create a new assignment ********************/ /*****************************************************************************/ void Asg_RequestCreatOrEditAsg (void) { extern const char *The_ClassForm[The_NUM_THEMES]; extern const char *Txt_New_assignment; extern const char *Txt_Edit_assignment; extern const char *Txt_Title; extern const char *Txt_Upload_files_QUESTION; extern const char *Txt_Folder; extern const char *Txt_Description; extern const char *Txt_Create_assignment; extern const char *Txt_Save; struct Assignment Asg; bool ItsANewAssignment; char Txt[Cns_MAX_BYTES_TEXT+1]; /***** Get parameters *****/ Asg_GetParamAsgOrderType (); Grp_GetParamWhichGrps (); Pag_GetParamPagNum (Pag_ASSIGNMENTS); /***** Get the code of the assignment *****/ ItsANewAssignment = ((Asg.AsgCod = Asg_GetParamAsgCod ()) == -1L); /***** Get from the database the data of the assignment *****/ if (ItsANewAssignment) { /* Initialize to empty assignment */ Asg.AsgCod = -1L; Asg.TimeUTC[Asg_START_TIME] = Gbl.StartExecutionTimeUTC; Asg.TimeUTC[Asg_END_TIME ] = Gbl.StartExecutionTimeUTC + (2 * 60 * 60); // +2 hours Asg.Open = true; Asg.Title[0] = '\0'; Asg.SendWork = false; Asg.Folder[0] = '\0'; Asg.IBelongToCrsOrGrps = false; } else { /* Get data of the assignment from database */ Asg_GetDataOfAssignmentByCod (&Asg); /* Get text of the assignment from database */ Asg_GetAssignmentTxtFromDB (Asg.AsgCod,Txt); } /***** Start form *****/ if (ItsANewAssignment) Act_FormStart (ActNewAsg); else { Act_FormStart (ActChgAsg); Asg_PutParamAsgCod (Asg.AsgCod); } Asg_PutHiddenParamAsgOrderType (); Grp_PutParamWhichGrps (); Pag_PutHiddenParamPagNum (Gbl.Pag.CurrentPage); /***** Table start *****/ Lay_StartRoundFrameTable (NULL,2,ItsANewAssignment ? Txt_New_assignment : Txt_Edit_assignment); /***** Assignment title *****/ fprintf (Gbl.F.Out,"" "" "%s:" "" "" "" "" "", The_ClassForm[Gbl.Prefs.Theme], Txt_Title, Asg_MAX_LENGTH_ASSIGNMENT_TITLE,Asg.Title); /***** Assignment start and end dates *****/ Dat_PutFormStartEndClientLocalDateTimes (Asg.TimeUTC); /***** Send work? *****/ fprintf (Gbl.F.Out,"" "" "%s:" "" "" "%s: " "" "" "", The_ClassForm[Gbl.Prefs.Theme], Txt_Upload_files_QUESTION, Txt_Folder, Asg_MAX_LENGTH_FOLDER,Asg_MAX_LENGTH_FOLDER,Asg.Folder); /***** Assignment text *****/ fprintf (Gbl.F.Out,"" "" "%s:" "" "" "" "" ""); /***** Groups *****/ Asg_ShowLstGrpsToEditAssignment (Asg.AsgCod); /***** New assignment *****/ if (ItsANewAssignment) Lay_EndRoundFrameTableWithButton (Lay_CREATE_BUTTON,Txt_Create_assignment); else Lay_EndRoundFrameTableWithButton (Lay_CONFIRM_BUTTON,Txt_Save); Act_FormEnd (); /***** Show current assignments *****/ Asg_ShowAllAssignments (); } /*****************************************************************************/ /**************** Show list of groups to edit and assignment *****************/ /*****************************************************************************/ static void Asg_ShowLstGrpsToEditAssignment (long AsgCod) { extern const char *The_ClassForm[The_NUM_THEMES]; extern const char *Txt_Groups; extern const char *Txt_The_whole_course; unsigned NumGrpTyp; /***** Get list of groups types and groups in this course *****/ Grp_GetListGrpTypesAndGrpsInThisCrs (Grp_ONLY_GROUP_TYPES_WITH_GROUPS); if (Gbl.CurrentCrs.Grps.GrpTypes.Num) { /***** Start table *****/ fprintf (Gbl.F.Out,"" "" "%s:" "" "", The_ClassForm[Gbl.Prefs.Theme], Txt_Groups); Lay_StartRoundFrameTable ("100%",0,NULL); /***** First row: checkbox to select the whole course *****/ fprintf (Gbl.F.Out,"" "" "%s %s" "", Txt_The_whole_course,Gbl.CurrentCrs.Crs.ShortName); /***** List the groups for each group type *****/ for (NumGrpTyp = 0; NumGrpTyp < Gbl.CurrentCrs.Grps.GrpTypes.Num; NumGrpTyp++) if (Gbl.CurrentCrs.Grps.GrpTypes.LstGrpTypes[NumGrpTyp].NumGrps) Grp_ListGrpsToEditAsgAttOrSvy (&Gbl.CurrentCrs.Grps.GrpTypes.LstGrpTypes[NumGrpTyp],AsgCod,Grp_ASSIGNMENT); /***** End table *****/ Lay_EndRoundFrameTable (); fprintf (Gbl.F.Out,"" ""); } /***** Free list of groups types and groups in this course *****/ Grp_FreeListGrpTypesAndGrps (); } /*****************************************************************************/ /****************** Receive form to create a new assignment ******************/ /*****************************************************************************/ void Asg_RecFormAssignment (void) { extern const char *Txt_Already_existed_an_assignment_with_the_title_X; extern const char *Txt_Already_existed_an_assignment_with_the_folder_X; extern const char *Txt_You_must_specify_the_title_of_the_assignment; extern const char *Txt_Created_new_assignment_X; extern const char *Txt_The_assignment_has_been_modified; extern const char *Txt_You_can_not_disable_file_uploading_once_folders_have_been_created; struct Assignment OldAsg; struct Assignment NewAsg; bool ItsANewAssignment; bool NewAssignmentIsCorrect = true; unsigned NumUsrsToBeNotifiedByEMail; char Txt[Cns_MAX_BYTES_TEXT+1]; /***** Get the code of the assignment *****/ ItsANewAssignment = ((NewAsg.AsgCod = Asg_GetParamAsgCod ()) == -1L); if (!ItsANewAssignment) { /* Get data of the old (current) assignment from database */ OldAsg.AsgCod = NewAsg.AsgCod; Asg_GetDataOfAssignmentByCod (&OldAsg); } /***** Get start/end date-times *****/ NewAsg.TimeUTC[Asg_START_TIME] = Dat_GetTimeUTCFromForm ("StartTimeUTC"); NewAsg.TimeUTC[Asg_END_TIME ] = Dat_GetTimeUTCFromForm ("EndTimeUTC" ); /***** Get assignment title *****/ Par_GetParToText ("Title",NewAsg.Title,Asg_MAX_LENGTH_ASSIGNMENT_TITLE); /***** Get folder name where to send works of the assignment *****/ Par_GetParToText ("Folder",NewAsg.Folder,Asg_MAX_LENGTH_FOLDER); NewAsg.SendWork = (NewAsg.Folder[0]) ? Asg_SEND_WORK : Asg_DO_NOT_SEND_WORK; /***** Get assignment text *****/ Par_GetParToHTML ("Txt",Txt,Cns_MAX_BYTES_TEXT); // Store in HTML format (not rigorous) /***** Adjust dates *****/ if (NewAsg.TimeUTC[Asg_START_TIME] == 0) NewAsg.TimeUTC[Asg_START_TIME] = Gbl.StartExecutionTimeUTC; if (NewAsg.TimeUTC[Asg_END_TIME] == 0) NewAsg.TimeUTC[Asg_END_TIME] = NewAsg.TimeUTC[Asg_START_TIME] + 2*60*60; // +2 hours /***** Check if title is correct *****/ if (NewAsg.Title[0]) // If there's an assignment title { /* If title of assignment was in database... */ if (Asg_CheckIfSimilarAssignmentExists ("Title",NewAsg.Title,NewAsg.AsgCod)) { NewAssignmentIsCorrect = false; sprintf (Gbl.Message,Txt_Already_existed_an_assignment_with_the_title_X, NewAsg.Title); Lay_ShowAlert (Lay_WARNING,Gbl.Message); } else // Title is correct { if (NewAsg.SendWork == Asg_SEND_WORK) { if (Str_ConvertFilFolLnkNameToValid (NewAsg.Folder)) // If folder name is valid... { if (Asg_CheckIfSimilarAssignmentExists ("Folder",NewAsg.Folder,NewAsg.AsgCod)) // If folder of assignment was in database... { NewAssignmentIsCorrect = false; sprintf (Gbl.Message,Txt_Already_existed_an_assignment_with_the_folder_X, NewAsg.Folder); Lay_ShowAlert (Lay_WARNING,Gbl.Message); } } else // Folder name not valid { NewAssignmentIsCorrect = false; Lay_ShowAlert (Lay_WARNING,Gbl.Message); } } else // NewAsg.SendWork == Asg_DO_NOT_SEND_WORK { if (OldAsg.SendWork == Asg_SEND_WORK) { if (Brw_CheckIfExistsFolderAssigmentForAnyUsr (OldAsg.Folder)) { NewAssignmentIsCorrect = false; Lay_ShowAlert (Lay_WARNING,Txt_You_can_not_disable_file_uploading_once_folders_have_been_created); } } } } } else // If there is not an assignment title { NewAssignmentIsCorrect = false; Lay_ShowAlert (Lay_WARNING,Txt_You_must_specify_the_title_of_the_assignment); } /***** Create a new assignment or update an existing one *****/ if (NewAssignmentIsCorrect) { /* Get groups for this assignments */ Grp_GetParCodsSeveralGrpsToEditAsgAttOrSvy (); if (ItsANewAssignment) { Asg_CreateAssignment (&NewAsg,Txt); // Add new assignment to database /***** Write success message *****/ sprintf (Gbl.Message,Txt_Created_new_assignment_X,NewAsg.Title); Lay_ShowAlert (Lay_SUCCESS,Gbl.Message); } else { if (OldAsg.Folder[0] && NewAsg.Folder[0]) if (strcmp (OldAsg.Folder,NewAsg.Folder)) // Folder name has changed NewAssignmentIsCorrect = Brw_UpdateFoldersAssigmentsIfExistForAllUsrs (OldAsg.Folder,NewAsg.Folder); if (NewAssignmentIsCorrect) { Asg_UpdateAssignment (&NewAsg,Txt); /***** Write success message *****/ Lay_ShowAlert (Lay_SUCCESS,Txt_The_assignment_has_been_modified); } } /* Free memory for list of selected groups */ Grp_FreeListCodSelectedGrps (); } else // TODO: The form should be filled with partial data, now is always empty Asg_RequestCreatOrEditAsg (); /***** Notify by e-mail about the new assignment *****/ if ((NumUsrsToBeNotifiedByEMail = Ntf_StoreNotifyEventsToAllUsrs (Ntf_EVENT_ASSIGNMENT,NewAsg.AsgCod))) Asg_UpdateNumUsrsNotifiedByEMailAboutAssignment (NewAsg.AsgCod,NumUsrsToBeNotifiedByEMail); Ntf_ShowAlertNumUsrsToBeNotifiedByEMail (NumUsrsToBeNotifiedByEMail); /***** Show assignments again *****/ Asg_SeeAssignments (); } /*****************************************************************************/ /******** Update number of users notified in table of assignments ************/ /*****************************************************************************/ static void Asg_UpdateNumUsrsNotifiedByEMailAboutAssignment (long AsgCod,unsigned NumUsrsToBeNotifiedByEMail) { char Query[512]; /***** Update number of users notified *****/ sprintf (Query,"UPDATE assignments SET NumNotif=NumNotif+'%u'" " WHERE AsgCod='%ld'", NumUsrsToBeNotifiedByEMail,AsgCod); DB_QueryUPDATE (Query,"can not update the number of notifications of an assignment"); } /*****************************************************************************/ /************************ Create a new assignment ****************************/ /*****************************************************************************/ static void Asg_CreateAssignment (struct Assignment *Asg,const char *Txt) { char Query[1024+Cns_MAX_BYTES_TEXT]; /***** Create a new assignment *****/ sprintf (Query,"INSERT INTO assignments" " (CrsCod,UsrCod,StartTime,EndTime,Title,Folder,Txt)" " VALUES" " ('%ld','%ld',FROM_UNIXTIME('%ld'),FROM_UNIXTIME('%ld')," "'%s','%s','%s')", Gbl.CurrentCrs.Crs.CrsCod, Gbl.Usrs.Me.UsrDat.UsrCod, Asg->TimeUTC[Asg_START_TIME], Asg->TimeUTC[Asg_END_TIME ], Asg->Title, Asg->Folder, Txt); Asg->AsgCod = DB_QueryINSERTandReturnCode (Query,"can not create new assignment"); /***** Create groups *****/ if (Gbl.CurrentCrs.Grps.LstGrpsSel.NumGrps) Asg_CreateGrps (Asg->AsgCod); } /*****************************************************************************/ /********************* Update an existing assignment *************************/ /*****************************************************************************/ static void Asg_UpdateAssignment (struct Assignment *Asg,const char *Txt) { char Query[1024+Cns_MAX_BYTES_TEXT]; /***** Update the data of the assignment *****/ sprintf (Query,"UPDATE assignments SET " "StartTime=FROM_UNIXTIME('%ld')," "EndTime=FROM_UNIXTIME('%ld')," "Title='%s',Folder='%s',Txt='%s'" " WHERE AsgCod='%ld' AND CrsCod='%ld'", Asg->TimeUTC[Asg_START_TIME], Asg->TimeUTC[Asg_END_TIME ], Asg->Title, Asg->Folder, Txt, Asg->AsgCod,Gbl.CurrentCrs.Crs.CrsCod); DB_QueryUPDATE (Query,"can not update assignment"); /***** Update groups *****/ /* Remove old groups */ Asg_RemoveAllTheGrpsAssociatedToAnAssignment (Asg->AsgCod); /* Create new groups */ if (Gbl.CurrentCrs.Grps.LstGrpsSel.NumGrps) Asg_CreateGrps (Asg->AsgCod); } /*****************************************************************************/ /*********** Check if an assignment is associated to any group ***************/ /*****************************************************************************/ static bool Asg_CheckIfAsgIsAssociatedToGrps (long AsgCod) { char Query[256]; /***** Get if an assignment is associated to a group from database *****/ sprintf (Query,"SELECT COUNT(*) FROM asg_grp WHERE AsgCod='%ld'", AsgCod); return (DB_QueryCOUNT (Query,"can not check if an assignment is associated to groups") != 0); } /*****************************************************************************/ /************ Check if an assignment is associated to a group ****************/ /*****************************************************************************/ bool Asg_CheckIfAsgIsAssociatedToGrp (long AsgCod,long GrpCod) { char Query[512]; /***** Get if an assignment is associated to a group from database *****/ sprintf (Query,"SELECT COUNT(*) FROM asg_grp WHERE AsgCod='%ld' AND GrpCod='%ld'", AsgCod,GrpCod); return (DB_QueryCOUNT (Query,"can not check if an assignment is associated to a group") != 0); } /*****************************************************************************/ /********************* Remove groups of an assignment ************************/ /*****************************************************************************/ static void Asg_RemoveAllTheGrpsAssociatedToAnAssignment (long AsgCod) { char Query[256]; /***** Remove groups of the assignment *****/ sprintf (Query,"DELETE FROM asg_grp WHERE AsgCod='%ld'",AsgCod); DB_QueryDELETE (Query,"can not remove the groups associated to an assignment"); } /*****************************************************************************/ /**************** Remove one group from all the assignments ******************/ /*****************************************************************************/ void Asg_RemoveGroup (long GrpCod) { char Query[256]; /***** Remove group from all the assignments *****/ sprintf (Query,"DELETE FROM asg_grp WHERE GrpCod='%ld'",GrpCod); DB_QueryDELETE (Query,"can not remove group from the associations between assignments and groups"); } /*****************************************************************************/ /*********** Remove groups of one type from all the assignments **************/ /*****************************************************************************/ void Asg_RemoveGroupsOfType (long GrpTypCod) { char Query[256]; /***** Remove group from all the assignments *****/ sprintf (Query,"DELETE FROM asg_grp USING crs_grp,asg_grp" " WHERE crs_grp.GrpTypCod='%ld' AND crs_grp.GrpCod=asg_grp.GrpCod", GrpTypCod); DB_QueryDELETE (Query,"can not remove groups of a type from the associations between assignments and groups"); } /*****************************************************************************/ /********************* Create groups of an assignment ************************/ /*****************************************************************************/ static void Asg_CreateGrps (long AsgCod) { unsigned NumGrpSel; char Query[256]; /***** Create groups of the assignment *****/ for (NumGrpSel = 0; NumGrpSel < Gbl.CurrentCrs.Grps.LstGrpsSel.NumGrps; NumGrpSel++) { /* Create group */ sprintf (Query,"INSERT INTO asg_grp (AsgCod,GrpCod) VALUES ('%ld','%ld')", AsgCod,Gbl.CurrentCrs.Grps.LstGrpsSel.GrpCod[NumGrpSel]); DB_QueryINSERT (Query,"can not associate a group to an assignment"); } } /*****************************************************************************/ /********* Get and write the names of the groups of an assignment ************/ /*****************************************************************************/ static void Asg_GetAndWriteNamesOfGrpsAssociatedToAsg (struct Assignment *Asg) { extern const char *Txt_Group; extern const char *Txt_Groups; extern const char *Txt_and; extern const char *Txt_The_whole_course; char Query[512]; MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned long NumRow; unsigned long NumRows; /***** Get groups associated to an assignment from database *****/ sprintf (Query,"SELECT crs_grp_types.GrpTypName,crs_grp.GrpName" " FROM asg_grp,crs_grp,crs_grp_types" " WHERE asg_grp.AsgCod='%ld' AND asg_grp.GrpCod=crs_grp.GrpCod" " AND crs_grp.GrpTypCod=crs_grp_types.GrpTypCod" " ORDER BY crs_grp_types.GrpTypName,crs_grp.GrpName", Asg->AsgCod); NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get groups of an assignment"); /***** Write heading *****/ fprintf (Gbl.F.Out,"
%s: ", Asg->Hidden ? "ASG_GRP_LIGHT" : "ASG_GRP", (NumRows == 1) ? Txt_Group : Txt_Groups); /***** Write groups *****/ if (NumRows) // Groups found... { /* Get and write the group types and names */ for (NumRow = 0; NumRow < NumRows; NumRow++) { /* Get next group */ row = mysql_fetch_row (mysql_res); /* Write group type name and group name */ fprintf (Gbl.F.Out,"%s %s",row[0],row[1]); if (NumRows >= 2) { if (NumRow == NumRows-2) fprintf (Gbl.F.Out," %s ",Txt_and); if (NumRows >= 3) if (NumRow < NumRows-2) fprintf (Gbl.F.Out,", "); } } } else fprintf (Gbl.F.Out,"%s %s", Txt_The_whole_course,Gbl.CurrentCrs.Crs.ShortName); fprintf (Gbl.F.Out,"
"); /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); } /*****************************************************************************/ /****************** Remove all the assignments of a course *******************/ /*****************************************************************************/ void Asg_RemoveCrsAssignments (long CrsCod) { char Query[512]; /***** Remove groups *****/ sprintf (Query,"DELETE FROM asg_grp USING assignments,asg_grp" " WHERE assignments.CrsCod='%ld' AND assignments.AsgCod=asg_grp.AsgCod", CrsCod); DB_QueryDELETE (Query,"can not remove all the groups associated to assignments of a course"); /***** Remove assignments *****/ sprintf (Query,"DELETE FROM assignments WHERE CrsCod='%ld'",CrsCod); DB_QueryDELETE (Query,"can not remove all the assignments of a course"); } /*****************************************************************************/ /********* Check if I belong to any of the groups of an assignment ***********/ /*****************************************************************************/ static bool Asg_CheckIfIBelongToCrsOrGrpsThisAssignment (long AsgCod) { char Query[512]; if (Gbl.Usrs.Me.LoggedRole == Rol_STUDENT || Gbl.Usrs.Me.LoggedRole == Rol_TEACHER) { // Students and teachers can edit assignments depending on groups /***** Get if I can edit an assignment from database *****/ sprintf (Query,"SELECT COUNT(*) FROM assignments" " WHERE AsgCod='%ld'" " AND " "(" "AsgCod NOT IN (SELECT AsgCod FROM asg_grp)" // Assignment is for the whole course " OR " "AsgCod IN" // Assignment is for specific groups " (SELECT asg_grp.AsgCod FROM asg_grp,crs_grp_usr" " WHERE crs_grp_usr.UsrCod='%ld'" " AND asg_grp.GrpCod=crs_grp_usr.GrpCod)" ")", AsgCod,Gbl.Usrs.Me.UsrDat.UsrCod); return (DB_QueryCOUNT (Query,"can not check if I can do an assignment") != 0); } else return (Gbl.Usrs.Me.LoggedRole > Rol_TEACHER); // Admins can edit assignments } /*****************************************************************************/ /****************** Get number of assignments in a course ********************/ /*****************************************************************************/ unsigned Asg_GetNumAssignmentsInCrs (long CrsCod) { char Query[256]; /***** Get number of assignments in a course from database *****/ sprintf (Query,"SELECT COUNT(*) FROM assignments WHERE CrsCod='%ld'", CrsCod); return (unsigned) DB_QueryCOUNT (Query,"can not get number of assignments in course"); } /*****************************************************************************/ /****************** Get number of courses with assignments *******************/ /*****************************************************************************/ // Returns the number of courses with assignments // in this location (all the platform, current degree or current course) unsigned Asg_GetNumCoursesWithAssignments (Sco_Scope_t Scope) { char Query[1024]; MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned NumCourses; /***** Get number of courses with assignments from database *****/ switch (Scope) { case Sco_SCOPE_SYS: sprintf (Query,"SELECT COUNT(DISTINCT (CrsCod))" " FROM assignments" " WHERE CrsCod>'0'"); break; case Sco_SCOPE_CTY: sprintf (Query,"SELECT COUNT(DISTINCT (assignments.CrsCod))" " FROM institutions,centres,degrees,courses,assignments" " WHERE institutions.CtyCod='%ld'" " AND institutions.InsCod=centres.InsCod" " AND centres.CtrCod=degrees.CtrCod" " AND degrees.DegCod=courses.DegCod" " AND courses.Status=0" " AND courses.CrsCod=assignments.CrsCod", Gbl.CurrentCty.Cty.CtyCod); break; case Sco_SCOPE_INS: sprintf (Query,"SELECT COUNT(DISTINCT (assignments.CrsCod))" " FROM centres,degrees,courses,assignments" " WHERE centres.InsCod='%ld'" " AND centres.CtrCod=degrees.CtrCod" " AND degrees.DegCod=courses.DegCod" " AND courses.Status=0" " AND courses.CrsCod=assignments.CrsCod", Gbl.CurrentIns.Ins.InsCod); break; case Sco_SCOPE_CTR: sprintf (Query,"SELECT COUNT(DISTINCT (assignments.CrsCod))" " FROM degrees,courses,assignments" " WHERE degrees.CtrCod='%ld'" " AND degrees.DegCod=courses.DegCod" " AND courses.Status=0" " AND courses.CrsCod=assignments.CrsCod", Gbl.CurrentCtr.Ctr.CtrCod); break; case Sco_SCOPE_DEG: sprintf (Query,"SELECT COUNT(DISTINCT (assignments.CrsCod))" " FROM courses,assignments" " WHERE courses.DegCod='%ld'" " AND courses.Status=0" " AND courses.CrsCod=assignments.CrsCod", Gbl.CurrentDeg.Deg.DegCod); break; case Sco_SCOPE_CRS: sprintf (Query,"SELECT COUNT(DISTINCT (CrsCod))" " FROM assignments" " WHERE CrsCod='%ld'", Gbl.CurrentCrs.Crs.CrsCod); break; default: Lay_ShowErrorAndExit ("Wrong scope."); break; } DB_QuerySELECT (Query,&mysql_res,"can not get number of courses with assignments"); /***** Get number of courses *****/ row = mysql_fetch_row (mysql_res); if (sscanf (row[0],"%u",&NumCourses) != 1) Lay_ShowErrorAndExit ("Error when getting number of courses with assignments."); /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); return NumCourses; } /*****************************************************************************/ /************************ Get number of assignments **************************/ /*****************************************************************************/ // Returns the number of assignments // in this location (all the platform, current degree or current course) unsigned Asg_GetNumAssignments (Sco_Scope_t Scope,unsigned *NumNotif) { char Query[1024]; MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned NumAssignments; /***** Get number of assignments from database *****/ switch (Scope) { case Sco_SCOPE_SYS: sprintf (Query,"SELECT COUNT(*),SUM(NumNotif)" " FROM assignments" " WHERE CrsCod>'0'"); break; case Sco_SCOPE_CTY: sprintf (Query,"SELECT COUNT(*),SUM(assignments.NumNotif)" " FROM institutions,centres,degrees,courses,assignments" " WHERE institutions.CtyCod='%ld'" " AND institutions.InsCod=centres.InsCod" " AND centres.CtrCod=degrees.CtrCod" " AND degrees.DegCod=courses.DegCod" " AND courses.CrsCod=assignments.CrsCod", Gbl.CurrentCty.Cty.CtyCod); break; case Sco_SCOPE_INS: sprintf (Query,"SELECT COUNT(*),SUM(assignments.NumNotif)" " FROM centres,degrees,courses,assignments" " WHERE centres.InsCod='%ld'" " AND centres.CtrCod=degrees.CtrCod" " AND degrees.DegCod=courses.DegCod" " AND courses.CrsCod=assignments.CrsCod", Gbl.CurrentIns.Ins.InsCod); break; case Sco_SCOPE_CTR: sprintf (Query,"SELECT COUNT(*),SUM(assignments.NumNotif)" " FROM degrees,courses,assignments" " WHERE degrees.CtrCod='%ld'" " AND degrees.DegCod=courses.DegCod" " AND courses.CrsCod=assignments.CrsCod", Gbl.CurrentCtr.Ctr.CtrCod); break; case Sco_SCOPE_DEG: sprintf (Query,"SELECT COUNT(*),SUM(assignments.NumNotif)" " FROM courses,assignments" " WHERE courses.DegCod='%ld'" " AND courses.CrsCod=assignments.CrsCod", Gbl.CurrentDeg.Deg.DegCod); break; case Sco_SCOPE_CRS: sprintf (Query,"SELECT COUNT(*),SUM(NumNotif)" " FROM assignments" " WHERE CrsCod='%ld'", Gbl.CurrentCrs.Crs.CrsCod); break; default: Lay_ShowErrorAndExit ("Wrong scope."); break; } DB_QuerySELECT (Query,&mysql_res,"can not get number of assignments"); /***** Get number of assignments *****/ row = mysql_fetch_row (mysql_res); if (sscanf (row[0],"%u",&NumAssignments) != 1) Lay_ShowErrorAndExit ("Error when getting number of assignments."); /***** Get number of notifications by e-mail *****/ if (row[1]) { if (sscanf (row[1],"%u",NumNotif) != 1) Lay_ShowErrorAndExit ("Error when getting number of notifications of assignments."); } else *NumNotif = 0; /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); return NumAssignments; }