2014-12-01 23:55:08 +01:00
// swad_group.c: types of groups and groups
/*
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 .
2017-01-13 01:51:23 +01:00
Copyright ( C ) 1999 - 2017 Antonio Ca <EFBFBD> as Vargas
2014-12-01 23:55:08 +01:00
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 < http : //www.gnu.org/licenses/>.
*/
/*****************************************************************************/
/*********************************** Headers *********************************/
/*****************************************************************************/
# include <linux/stddef.h> // For NULL
# include <stdlib.h> // For exit, system, malloc, free, rand, etc.
# include <string.h> // For string functions
# include "swad_action.h"
# include "swad_database.h"
# include "swad_global.h"
# include "swad_group.h"
# include "swad_notification.h"
# include "swad_parameter.h"
/*****************************************************************************/
/*************************** Internal constants ******************************/
/*****************************************************************************/
2017-04-29 19:19:55 +02:00
# define Grp_SECTION_GROUP_TYPES "grp_types"
# define Grp_SECTION_NEW_GROUP_TYPE "new_grp_type"
# define Grp_SECTION_GROUPS "grps"
# define Grp_SECTION_NEW_GROUP "new_grp"
2017-04-29 15:29:58 +02:00
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/***************************** Internal types ********************************/
/*****************************************************************************/
/*****************************************************************************/
/************* External global variables from others modules *****************/
/*****************************************************************************/
extern struct Globals Gbl ;
/*****************************************************************************/
/************************* Internal global variables *************************/
/*****************************************************************************/
/*****************************************************************************/
/***************************** Internal prototypes ***************************/
/*****************************************************************************/
2017-04-29 20:42:10 +02:00
static void Grp_ReqEditGroupsInternal ( Lay_AlertType_t AlertTypeGroupTypes , const char * MessageGroupTypes ,
Lay_AlertType_t AlertTypeGroups , const char * MessageGroups ) ;
2017-04-29 02:20:34 +02:00
static void Grp_ReqEditGroupsInternal0 ( void ) ;
2017-04-29 20:42:10 +02:00
static void Grp_ReqEditGroupsInternal1 ( Lay_AlertType_t AlertTypeGroupTypes , const char * MessageGroupTypes ) ;
static void Grp_ReqEditGroupsInternal2 ( Lay_AlertType_t AlertTypeGroups , const char * MessageGroups ) ;
2017-04-28 18:03:30 +02:00
2014-12-01 23:55:08 +01:00
static void Grp_EditGroupTypes ( void ) ;
static void Grp_EditGroups ( void ) ;
2017-04-29 20:16:53 +02:00
static void Grp_PutIconsEditingGroups ( void ) ;
static void Grp_PutIconToCreateNewGroup ( void ) ;
2017-01-19 20:55:31 +01:00
2014-12-01 23:55:08 +01:00
static void Grp_ConstructorListGrpAlreadySelec ( struct ListGrpsAlreadySelec * * AlreadyExistsGroupOfType ) ;
static void Grp_DestructorListGrpAlreadySelec ( struct ListGrpsAlreadySelec * * AlreadyExistsGroupOfType ) ;
static void Grp_RemoveUsrFromGroup ( long UsrCod , long GrpCod ) ;
static void Grp_AddUsrToGroup ( struct UsrData * UsrDat , long GrpCod ) ;
2017-04-29 19:32:06 +02:00
2014-12-01 23:55:08 +01:00
static void Grp_ListGroupTypesForEdition ( void ) ;
2017-04-29 19:19:55 +02:00
static void Grp_PutIconsEditingGroupTypes ( void ) ;
static void Grp_PutIconToViewGroups ( void ) ;
static void Grp_PutIconToCreateNewGroupType ( void ) ;
2014-12-01 23:55:08 +01:00
static void Grp_WriteHeadingGroupTypes ( void ) ;
2017-04-29 19:32:06 +02:00
2014-12-01 23:55:08 +01:00
static void Grp_ListGroupsForEdition ( void ) ;
static void Grp_WriteHeadingGroups ( void ) ;
2016-03-16 22:40:35 +01:00
static void Grp_PutIconToEditGroups ( void ) ;
2014-12-01 23:55:08 +01:00
static void Grp_ShowWarningToStdsToChangeGrps ( void ) ;
static unsigned Grp_ListGrpsForChange ( struct GroupType * GrpTyp ) ;
static void Grp_ListGrpsToAddOrRemUsrs ( struct GroupType * GrpTyp , long UsrCod ) ;
static void Grp_ListGrpsForMultipleSelection ( struct GroupType * GrpTyp ) ;
static void Grp_WriteGrpHead ( struct GroupType * GrpTyp ) ;
static void Grp_WriteRowGrp ( struct Group * Grp , bool Highlight ) ;
static void Grp_PutFormToCreateGroupType ( void ) ;
static void Grp_PutFormToCreateGroup ( void ) ;
static unsigned Grp_CountNumGrpsInThisCrsOfType ( long GrpTypCod ) ;
static void Grp_GetDataOfGroupTypeByCod ( struct GroupType * GrpTyp ) ;
2017-03-30 11:20:06 +02:00
static bool Grp_GetMultipleEnrolmentOfAGroupType ( long GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
static long Grp_GetTypeOfGroupOfAGroup ( long GrpCod ) ;
static unsigned Grp_CountNumStdsInNoGrpsOfType ( long GrpTypCod ) ;
static long Grp_GetFirstCodGrpStdBelongsTo ( long GrpTypCod , long UsrCod ) ;
static bool Grp_GetIfGrpIsAvailable ( long GrpTypCod ) ;
static void Grp_GetLstCodGrpsUsrBelongs ( long CrsCod , long GrpTypCod , long UsrCod ,
struct ListCodGrps * LstGrps ) ;
static bool Grp_CheckIfGrpIsInList ( long GrpCod , struct ListCodGrps * LstGrps ) ;
2015-10-26 20:02:07 +01:00
static bool Grp_CheckIfOpenTimeInTheFuture ( time_t OpenTimeUTC ) ;
2014-12-01 23:55:08 +01:00
static bool Grp_CheckIfGroupTypeNameExists ( const char * GrpTypName , long GrpTypCod ) ;
static bool Grp_CheckIfGroupNameExists ( long GrpTypCod , const char * GrpName , long GrpCod ) ;
static void Grp_CreateGroupType ( void ) ;
static void Grp_CreateGroup ( void ) ;
2017-04-28 13:10:46 +02:00
2014-12-01 23:55:08 +01:00
static void Grp_AskConfirmRemGrpTypWithGrps ( unsigned NumGrps ) ;
2017-04-28 14:12:37 +02:00
static void Grp_PutParamRemGrpTyp ( void ) ;
2014-12-01 23:55:08 +01:00
static void Grp_AskConfirmRemGrp ( void ) ;
2017-04-28 13:10:46 +02:00
static void Grp_PutParamRemGrp ( void ) ;
2014-12-01 23:55:08 +01:00
static void Grp_RemoveGroupTypeCompletely ( void ) ;
static void Grp_RemoveGroupCompletely ( void ) ;
2017-04-28 13:10:46 +02:00
2014-12-01 23:55:08 +01:00
static void Grp_WriteMaxStdsGrp ( unsigned MaxStudents ) ;
static long Grp_GetParamGrpTypCod ( void ) ;
static long Grp_GetParamGrpCod ( void ) ;
static void Grp_PutParamGrpTypCod ( long GrpTypCod ) ;
/*****************************************************************************/
/******************* Write the names of the selected groups ******************/
/*****************************************************************************/
void Grp_WriteNamesOfSelectedGrps ( void )
{
extern const char * Txt_Group ;
extern const char * Txt_Groups ;
extern const char * Txt_students_with_no_group ;
extern const char * Txt_and ;
long GrpCod ;
unsigned NumGrpSel ;
struct GroupData GrpDat ;
/***** Show the selected groups *****/
fprintf ( Gbl . F . Out , " %s: " ,
( Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps = = 1 ) ?
Txt_Group :
Txt_Groups ) ;
for ( NumGrpSel = 0 ;
NumGrpSel < Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps ;
NumGrpSel + + )
{
2017-01-19 20:55:31 +01:00
if ( ( GrpCod = Gbl . CurrentCrs . Grps . LstGrpsSel . GrpCods [ NumGrpSel ] ) > = 0 )
2014-12-01 23:55:08 +01:00
{
GrpDat . GrpCod = GrpCod ;
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
fprintf ( Gbl . F . Out , " %s %s " ,
GrpDat . GrpTypName , GrpDat . GrpName ) ;
}
else // GrpCod < 0 ==> students not belonging to any group of type (-GrpCod)
{
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod = - GrpCod ;
Grp_GetDataOfGroupTypeByCod ( & Gbl . CurrentCrs . Grps . GrpTyp ) ;
fprintf ( Gbl . F . Out , " %s (%s) " ,
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName ,
Txt_students_with_no_group ) ;
}
if ( Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps > = 2 )
{
if ( NumGrpSel = = Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps - 2 )
fprintf ( Gbl . F . Out , " %s " , Txt_and ) ;
if ( Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps > = 3 )
if ( NumGrpSel < Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps - 2 )
fprintf ( Gbl . F . Out , " , " ) ;
}
}
}
/*****************************************************************************/
/************************** Put forms to edit groups *************************/
/*****************************************************************************/
void Grp_ReqEditGroups ( void )
2017-04-29 20:42:10 +02:00
{
Grp_ReqEditGroupsInternal ( Lay_INFO , NULL ,
Lay_INFO , NULL ) ;
}
static void Grp_ReqEditGroupsInternal ( Lay_AlertType_t AlertTypeGroupTypes , const char * MessageGroupTypes ,
Lay_AlertType_t AlertTypeGroups , const char * MessageGroups )
2017-04-28 18:03:30 +02:00
{
2017-04-29 02:20:34 +02:00
Grp_ReqEditGroupsInternal0 ( ) ;
2017-04-29 20:42:10 +02:00
Grp_ReqEditGroupsInternal1 ( AlertTypeGroupTypes , MessageGroupTypes ) ;
Grp_ReqEditGroupsInternal2 ( AlertTypeGroups , MessageGroups ) ;
2017-04-28 18:03:30 +02:00
}
2017-04-29 02:20:34 +02:00
static void Grp_ReqEditGroupsInternal0 ( void )
2017-04-29 00:23:48 +02:00
{
2017-04-29 02:20:34 +02:00
/***** Start groups types section *****/
2017-04-29 19:19:55 +02:00
fprintf ( Gbl . F . Out , " <section id= \" %s \" > " , Grp_SECTION_GROUP_TYPES ) ;
2017-04-29 00:23:48 +02:00
}
2017-04-29 20:42:10 +02:00
static void Grp_ReqEditGroupsInternal1 ( Lay_AlertType_t AlertTypeGroupTypes , const char * MessageGroupTypes )
2014-12-01 23:55:08 +01:00
{
/***** Get list of groups types and groups in this course *****/
Grp_GetListGrpTypesAndGrpsInThisCrs ( Grp_ALL_GROUP_TYPES ) ;
2017-04-29 02:20:34 +02:00
/***** Show optional alert *****/
2017-04-29 20:42:10 +02:00
if ( MessageGroupTypes )
if ( MessageGroupTypes [ 0 ] )
Lay_ShowAlert ( AlertTypeGroupTypes , MessageGroupTypes ) ;
2017-04-28 18:03:30 +02:00
2017-04-29 02:20:34 +02:00
/***** Put form to edit group types *****/
2014-12-01 23:55:08 +01:00
Grp_EditGroupTypes ( ) ;
2017-04-29 02:20:34 +02:00
/***** End groups types section *****/
2017-04-28 18:03:30 +02:00
fprintf ( Gbl . F . Out , " </section> " ) ;
2017-04-29 02:20:34 +02:00
/***** Start groups section *****/
2017-04-29 19:19:55 +02:00
fprintf ( Gbl . F . Out , " <section id= \" %s \" > " , Grp_SECTION_GROUPS ) ;
2017-04-29 00:23:48 +02:00
}
2017-04-28 18:03:30 +02:00
2017-04-29 20:42:10 +02:00
static void Grp_ReqEditGroupsInternal2 ( Lay_AlertType_t AlertTypeGroups , const char * MessageGroups )
2017-04-29 00:23:48 +02:00
{
2017-04-29 02:20:34 +02:00
/***** Show optional alert *****/
2017-04-29 20:42:10 +02:00
if ( MessageGroups )
if ( MessageGroups [ 0 ] )
Lay_ShowAlert ( AlertTypeGroups , MessageGroups ) ;
2017-04-29 02:20:34 +02:00
/***** Put form to edit groups *****/
2014-12-01 23:55:08 +01:00
if ( Gbl . CurrentCrs . Grps . GrpTypes . Num ) // If there are group types...
Grp_EditGroups ( ) ;
2017-04-29 02:20:34 +02:00
/***** End groups section *****/
2017-04-28 18:03:30 +02:00
fprintf ( Gbl . F . Out , " </section> " ) ;
2017-04-29 02:20:34 +02:00
/***** Free list of groups types and groups in this course *****/
Grp_FreeListGrpTypesAndGrps ( ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************************* Put forms to edit group types *********************/
/*****************************************************************************/
static void Grp_EditGroupTypes ( void )
{
2017-04-29 20:16:53 +02:00
extern const char * Hlp_USERS_Groups ;
extern const char * Txt_Types_of_group ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_There_are_no_types_of_group_in_the_course_X ;
2017-04-29 20:16:53 +02:00
/***** Start frame *****/
Lay_StartRoundFrame ( NULL , Txt_Types_of_group ,
Grp_PutIconsEditingGroupTypes ,
Hlp_USERS_Groups ) ;
2014-12-01 23:55:08 +01:00
/***** Forms to edit current group types *****/
if ( Gbl . CurrentCrs . Grps . GrpTypes . Num ) // Group types found...
Grp_ListGroupTypesForEdition ( ) ;
else // No group types found in this course
{
sprintf ( Gbl . Message , Txt_There_are_no_types_of_group_in_the_course_X ,
2016-10-28 10:03:37 +02:00
Gbl . CurrentCrs . Crs . ShrtName ) ;
2014-12-01 23:55:08 +01:00
Lay_ShowAlert ( Lay_INFO , Gbl . Message ) ;
}
/***** Put a form to create a new group type *****/
Grp_PutFormToCreateGroupType ( ) ;
2017-04-29 20:16:53 +02:00
/***** End frame *****/
Lay_EndRoundFrame ( ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/**************************** Put forms to edit groups ***********************/
/*****************************************************************************/
static void Grp_EditGroups ( void )
{
2017-04-29 20:16:53 +02:00
extern const char * Hlp_USERS_Groups ;
extern const char * Txt_Groups ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_No_groups_have_been_created_in_the_course_X ;
2017-04-29 20:16:53 +02:00
/***** Start frame *****/
Lay_StartRoundFrame ( NULL , Txt_Groups , Grp_PutIconsEditingGroups ,
Hlp_USERS_Groups ) ;
2014-12-01 23:55:08 +01:00
/***** Forms to edit current groups *****/
if ( Gbl . CurrentCrs . Grps . GrpTypes . NumGrpsTotal ) // If there are groups...
Grp_ListGroupsForEdition ( ) ;
else // There are group types, but there aren't groups
{
sprintf ( Gbl . Message , Txt_No_groups_have_been_created_in_the_course_X ,
2016-10-28 10:03:37 +02:00
Gbl . CurrentCrs . Crs . ShrtName ) ;
2014-12-01 23:55:08 +01:00
Lay_ShowAlert ( Lay_INFO , Gbl . Message ) ;
}
/***** Put a form to create a new group *****/
Grp_PutFormToCreateGroup ( ) ;
2017-04-29 20:16:53 +02:00
/***** End frame *****/
Lay_EndRoundFrame ( ) ;
}
/*****************************************************************************/
/**************** Put contextual icons in edition of groups ******************/
/*****************************************************************************/
static void Grp_PutIconsEditingGroups ( void )
{
/***** Put icon to view groups *****/
Grp_PutIconToViewGroups ( ) ;
/***** Put icon to create a new group *****/
Grp_PutIconToCreateNewGroup ( ) ;
}
static void Grp_PutIconToCreateNewGroup ( void )
{
extern const char * Txt_New_group ;
/***** Put form to create a new group *****/
Lay_PutContextualLink ( ActReqEdiGrp , Grp_SECTION_NEW_GROUP , NULL ,
" plus64x64.png " ,
Txt_New_group , NULL ,
NULL ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*************** Show form to select one or several groups *******************/
/*****************************************************************************/
2016-11-25 03:21:02 +01:00
void Grp_ShowFormToSelectSeveralGroups ( Act_Action_t NextAction )
2014-12-01 23:55:08 +01:00
{
2016-11-13 20:54:06 +01:00
extern const char * Hlp_USERS_Groups ;
2015-07-27 21:25:45 +02:00
extern const char * The_ClassForm [ The_NUM_THEMES ] ;
extern const char * The_ClassFormBold [ The_NUM_THEMES ] ;
2015-04-11 14:27:18 +02:00
extern const char * Txt_Groups ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_All_groups ;
extern const char * Txt_Update_students ;
extern const char * Txt_Update_students_according_to_selected_groups ;
unsigned NumGrpTyp ;
2016-11-25 03:21:02 +01:00
bool ICanEdit ;
2014-12-01 23:55:08 +01:00
2016-11-25 03:21:02 +01:00
if ( Gbl . CurrentCrs . Grps . NumGrps )
{
ICanEdit = ! Gbl . Form . Inside & &
( Gbl . Usrs . Me . LoggedRole = = Rol_TEACHER | |
Gbl . Usrs . Me . LoggedRole = = Rol_SYS_ADM ) ;
/***** Start frame *****/
Lay_StartRoundFrame ( NULL , Txt_Groups ,
ICanEdit ? Grp_PutIconToEditGroups :
NULL ,
Hlp_USERS_Groups ) ;
/***** Start form to update the students listed
depending on the groups selected * * * * */
Act_FormStart ( NextAction ) ;
2017-02-01 11:23:48 +01:00
Usr_PutParamsPrefsAboutUsrList ( ) ;
2016-11-25 03:21:02 +01:00
/***** Put parameters needed depending on the action *****/
Usr_PutExtraParamsUsrList ( NextAction ) ;
/***** Select all groups *****/
2016-12-23 22:19:03 +01:00
fprintf ( Gbl . F . Out , " <div class= \" CONTEXT_OPT \" > "
" <label class= \" %s \" > "
2016-12-20 14:03:46 +01:00
" <input type= \" checkbox \" "
" id= \" AllGroups \" name= \" AllGroups \" value= \" Y \" " ,
2016-11-25 03:21:02 +01:00
The_ClassForm [ Gbl . Prefs . Theme ] ) ;
if ( Gbl . Usrs . ClassPhoto . AllGroups )
fprintf ( Gbl . F . Out , " checked= \" checked \" " ) ;
fprintf ( Gbl . F . Out , " onclick= \" togglecheckChildren(this,'GrpCods') \" /> "
2016-12-20 14:03:46 +01:00
" %s "
" </label> "
2016-11-25 03:21:02 +01:00
" </div> " ,
Txt_All_groups ) ;
/***** Get list of groups types and groups in this course *****/
Grp_GetListGrpTypesAndGrpsInThisCrs ( Grp_ONLY_GROUP_TYPES_WITH_GROUPS ) ;
/***** List the groups for each group type *****/
2017-05-01 10:22:16 +02:00
Lay_StartTableWide ( 2 ) ;
2016-11-25 03:21:02 +01:00
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
if ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps )
Grp_ListGrpsForMultipleSelection ( & Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ) ;
2017-05-01 10:22:16 +02:00
Lay_EndTable ( ) ;
2016-11-25 03:21:02 +01:00
/***** Free list of groups types and groups in this course *****/
Grp_FreeListGrpTypesAndGrps ( ) ;
/***** Submit button *****/
fprintf ( Gbl . F . Out , " <div class= \" CENTER_MIDDLE \" "
" style= \" padding-top:12px; \" > " ) ;
Act_LinkFormSubmitAnimated ( Txt_Update_students_according_to_selected_groups ,
The_ClassFormBold [ Gbl . Prefs . Theme ] ,
" CopyMessageToHiddenFields() " ) ;
Lay_PutCalculateIconWithText ( Txt_Update_students_according_to_selected_groups ,
Txt_Update_students ) ;
fprintf ( Gbl . F . Out , " </div> " ) ;
/***** End form *****/
Act_FormEnd ( ) ;
/***** End frame *****/
Lay_EndRoundFrame ( ) ;
}
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************ Put parameters with the groups of students selected ************/
/*****************************************************************************/
void Grp_PutParamsCodGrps ( void )
{
unsigned NumGrpSel ;
/***** Write the boolean parameter that indicates if all the groups must be listed *****/
Par_PutHiddenParamChar ( " AllGroups " ,
Gbl . Usrs . ClassPhoto . AllGroups ? ' Y ' :
' N ' ) ;
/***** Write the parameter with the list of group codes to show *****/
if ( ! Gbl . Usrs . ClassPhoto . AllGroups & &
Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps )
{
fprintf ( Gbl . F . Out , " <input type= \" hidden \" name= \" GrpCods \" value= \" " ) ;
for ( NumGrpSel = 0 ;
NumGrpSel < Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps ;
NumGrpSel + + )
{
if ( NumGrpSel )
fprintf ( Gbl . F . Out , " %c " , Par_SEPARATOR_PARAM_MULTIPLE ) ;
2017-01-19 20:55:31 +01:00
fprintf ( Gbl . F . Out , " %ld " , Gbl . CurrentCrs . Grps . LstGrpsSel . GrpCods [ NumGrpSel ] ) ;
2014-12-01 23:55:08 +01:00
}
fprintf ( Gbl . F . Out , " \" /> " ) ;
}
}
/*****************************************************************************/
/**************** Get parameters related to groups selected ******************/
/*****************************************************************************/
void Grp_GetParCodsSeveralGrpsToShowUsrs ( void )
{
struct ListCodGrps LstGrpsIBelong ;
unsigned NumGrp ;
if ( + + Gbl . CurrentCrs . Grps . LstGrpsSel . NestedCalls > 1 ) // If list is created yet, there's nothing to do
return ;
/***** Get boolean parameter that indicates if all groups must be listed *****/
2017-01-28 20:32:50 +01:00
Gbl . Usrs . ClassPhoto . AllGroups = Par_GetParToBool ( " AllGroups " ) ;
2014-12-01 23:55:08 +01:00
2017-01-19 20:55:31 +01:00
/***** Get parameter with list of groups selected *****/
Grp_GetParCodsSeveralGrps ( ) ;
2014-12-01 23:55:08 +01:00
2017-01-19 20:55:31 +01:00
if ( Gbl . CurrentCrs . Grps . NumGrps & & // This course has groups and...
! Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps ) // ...I haven't selected any group
{
/***** I I haven't selected any group, show by default the groups I belong to *****/
/* Get list of groups of all types in current course I belong to */
Grp_GetLstCodGrpsUsrBelongs ( Gbl . CurrentCrs . Crs . CrsCod , - 1L ,
Gbl . Usrs . Me . UsrDat . UsrCod , & LstGrpsIBelong ) ;
2014-12-01 23:55:08 +01:00
2017-01-19 20:55:31 +01:00
if ( LstGrpsIBelong . NumGrps )
{
/* Allocate space for list of selected groups */
if ( ( Gbl . CurrentCrs . Grps . LstGrpsSel . GrpCods = ( long * ) calloc ( LstGrpsIBelong . NumGrps , sizeof ( long ) ) ) = = NULL )
Lay_ShowErrorAndExit ( " Not enough memory to store the codes of the selected groups. " ) ;
/* Fill list of selected groups with list of groups I belong to */
for ( NumGrp = 0 ;
NumGrp < LstGrpsIBelong . NumGrps ;
NumGrp + + )
Gbl . CurrentCrs . Grps . LstGrpsSel . GrpCods [ NumGrp ] = LstGrpsIBelong . GrpCods [ NumGrp ] ;
Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps = LstGrpsIBelong . NumGrps ;
}
2014-12-01 23:55:08 +01:00
2017-01-19 20:55:31 +01:00
/* Free list of groups I belong to */
Grp_FreeListCodGrp ( & LstGrpsIBelong ) ;
2014-12-01 23:55:08 +01:00
}
/***** If no groups selected ==> show all groups *****/
if ( ! Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps )
Gbl . Usrs . ClassPhoto . AllGroups = true ;
}
/*****************************************************************************/
2017-01-19 20:55:31 +01:00
/**************** Get parameter with list of groups selected *****************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2017-01-19 20:55:31 +01:00
void Grp_GetParCodsSeveralGrps ( void )
2014-12-01 23:55:08 +01:00
{
2017-01-19 20:55:31 +01:00
char * ParamLstCodGrps ;
2014-12-01 23:55:08 +01:00
const char * Ptr ;
2017-01-19 20:55:31 +01:00
char LongStr [ 1 + 10 + 1 ] ;
2014-12-01 23:55:08 +01:00
unsigned NumGrp ;
2017-01-19 20:55:31 +01:00
unsigned long MaxSizeLstGrpCods = ( ( 1 + 10 + 1 ) * Gbl . CurrentCrs . Grps . NumGrps ) - 1 ;
2014-12-01 23:55:08 +01:00
2017-01-19 20:55:31 +01:00
/***** Reset number of groups selected *****/
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps = 0 ;
2017-01-19 20:55:31 +01:00
if ( Gbl . CurrentCrs . Grps . NumGrps ) // If course has groups
2014-12-01 23:55:08 +01:00
{
2017-01-19 20:55:31 +01:00
/***** Allocate memory for the list of group codes selected *****/
if ( ( ParamLstCodGrps = ( char * ) malloc ( MaxSizeLstGrpCods + 1 ) ) = = NULL )
Lay_ShowErrorAndExit ( " Not enough memory to store the codes of the selected groups. " ) ;
2014-12-01 23:55:08 +01:00
/***** Get parameter with list of groups to list *****/
2017-01-19 20:55:31 +01:00
Par_GetParMultiToText ( " GrpCods " , ParamLstCodGrps , MaxSizeLstGrpCods ) ;
2014-12-01 23:55:08 +01:00
2017-01-19 20:55:31 +01:00
if ( ParamLstCodGrps [ 0 ] )
{
/***** Count number of groups selected from LstCodGrps *****/
for ( Ptr = ParamLstCodGrps , NumGrp = 0 ;
* Ptr ;
NumGrp + + )
2017-01-28 15:58:46 +01:00
Par_GetNextStrUntilSeparParamMult ( & Ptr , LongStr , 1 + 10 ) ;
2017-01-19 20:55:31 +01:00
Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps = NumGrp ;
if ( Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps ) // If I have selected groups...
{
/***** Create a list of groups selected from LstCodGrps *****/
if ( ( Gbl . CurrentCrs . Grps . LstGrpsSel . GrpCods = ( long * ) calloc ( Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps , sizeof ( long ) ) ) = = NULL )
Lay_ShowErrorAndExit ( " Not enough memory to store the codes of the selected groups. " ) ;
for ( Ptr = ParamLstCodGrps , NumGrp = 0 ;
* Ptr ;
NumGrp + + )
{
2017-01-28 15:58:46 +01:00
Par_GetNextStrUntilSeparParamMult ( & Ptr , LongStr , 1 + 10 ) ;
2017-01-19 20:55:31 +01:00
Gbl . CurrentCrs . Grps . LstGrpsSel . GrpCods [ NumGrp ] = Str_ConvertStrCodToLongCod ( LongStr ) ;
}
}
}
2014-12-01 23:55:08 +01:00
/***** Free memory used for the list of groups to show *****/
2017-01-19 20:55:31 +01:00
free ( ( void * ) ParamLstCodGrps ) ;
2014-12-01 23:55:08 +01:00
}
}
/*****************************************************************************/
/********* Free memory used for the list of group codes selected *************/
/*****************************************************************************/
void Grp_FreeListCodSelectedGrps ( void )
{
if ( Gbl . CurrentCrs . Grps . LstGrpsSel . NestedCalls > 0 )
if ( - - Gbl . CurrentCrs . Grps . LstGrpsSel . NestedCalls = = 0 )
2017-01-19 20:55:31 +01:00
if ( Gbl . CurrentCrs . Grps . LstGrpsSel . GrpCods )
2014-12-01 23:55:08 +01:00
{
2017-01-19 20:55:31 +01:00
free ( ( void * ) Gbl . CurrentCrs . Grps . LstGrpsSel . GrpCods ) ;
Gbl . CurrentCrs . Grps . LstGrpsSel . GrpCods = NULL ;
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps = 0 ;
}
}
/*****************************************************************************/
/******************* Change my groups and show form again ********************/
/*****************************************************************************/
void Grp_ChangeMyGrpsAndShowChanges ( void )
{
/***** Change my groups *****/
Grp_ChangeMyGrps ( ) ;
/***** Show again the table of selection of groups with the changes already made *****/
Grp_ReqRegisterInGrps ( ) ;
}
/*****************************************************************************/
/****************************** Change my groups *****************************/
/*****************************************************************************/
void Grp_ChangeMyGrps ( void )
{
extern const char * Txt_The_requested_group_changes_were_successful ;
extern const char * Txt_There_has_been_no_change_in_groups ;
2017-03-30 11:20:06 +02:00
extern const char * Txt_In_a_type_of_group_with_single_enrolment_students_can_not_be_registered_in_more_than_one_group ;
2014-12-01 23:55:08 +01:00
struct ListCodGrps LstGrpsIWant ;
bool MySelectionIsValid = true ;
/***** Get list of groups types and groups in this course *****/
Grp_GetListGrpTypesAndGrpsInThisCrs ( Grp_ONLY_GROUP_TYPES_WITH_GROUPS ) ;
/***** Get the group codes which I want to join to *****/
2017-01-19 20:55:31 +01:00
LstGrpsIWant . GrpCods = NULL ; // Initialized to avoid bug reported by Coverity
2016-12-29 22:19:46 +01:00
LstGrpsIWant . NumGrps = 0 ; // Initialized to avoid bug reported by Coverity
2014-12-01 23:55:08 +01:00
Grp_GetLstCodsGrpWanted ( & LstGrpsIWant ) ;
2017-03-30 11:20:06 +02:00
/***** A student can not be enroled in more than one group
if the type of group is of single enrolment * * * * */
// As the form to register in groups of single enrolment...
2014-12-01 23:55:08 +01:00
// ...is a radio-based form and not a checkbox-based form...
// ...this check is made only to avoid problems...
// ...if the student manipulates the form
2015-04-07 21:44:24 +02:00
if ( Gbl . Usrs . Me . LoggedRole = = Rol_STUDENT & &
2014-12-01 23:55:08 +01:00
LstGrpsIWant . NumGrps > = 2 )
MySelectionIsValid = Grp_CheckIfSelectionGrpsIsValid ( & LstGrpsIWant ) ;
/***** Free list of groups types and groups in this course *****/
// The lists of group types and groups need to be freed here...
// ...in order to get them again when changing my groups atomically
Grp_FreeListGrpTypesAndGrps ( ) ;
/***** Change my groups *****/
if ( MySelectionIsValid )
{
if ( Grp_ChangeMyGrpsAtomically ( & LstGrpsIWant ) )
Lay_ShowAlert ( Lay_SUCCESS , Txt_The_requested_group_changes_were_successful ) ;
else
Lay_ShowAlert ( Lay_WARNING , Txt_There_has_been_no_change_in_groups ) ;
}
else
2017-03-30 11:20:06 +02:00
Lay_ShowAlert ( Lay_WARNING , Txt_In_a_type_of_group_with_single_enrolment_students_can_not_be_registered_in_more_than_one_group ) ;
2014-12-01 23:55:08 +01:00
/***** Free memory with the list of groups which I want to belong to *****/
Grp_FreeListCodGrp ( & LstGrpsIWant ) ;
}
/*****************************************************************************/
/********************** Change groups of another user ************************/
/*****************************************************************************/
void Grp_ChangeOtherUsrGrps ( void )
{
extern const char * Txt_The_requested_group_changes_were_successful ;
extern const char * Txt_There_has_been_no_change_in_groups ;
2017-03-30 11:20:06 +02:00
extern const char * Txt_In_a_type_of_group_with_single_enrolment_students_can_not_be_registered_in_more_than_one_group ;
2014-12-01 23:55:08 +01:00
struct ListCodGrps LstGrpsUsrWants ;
bool SelectionIsValid = true ;
/***** Get list of groups types and groups in current course *****/
Grp_GetListGrpTypesAndGrpsInThisCrs ( Grp_ONLY_GROUP_TYPES_WITH_GROUPS ) ;
/***** Get the list of groups to which register this user *****/
2017-01-19 20:55:31 +01:00
LstGrpsUsrWants . GrpCods = NULL ; // Initialized to avoid bug reported by Coverity
2016-12-29 22:42:57 +01:00
LstGrpsUsrWants . NumGrps = 0 ; // Initialized to avoid bug reported by Coverity
2014-12-01 23:55:08 +01:00
Grp_GetLstCodsGrpWanted ( & LstGrpsUsrWants ) ;
2017-03-30 11:20:06 +02:00
/***** A student can not be enroled in more than one group
if the type of group is of single enrolment * * * * */
2015-04-07 21:44:24 +02:00
if ( Gbl . Usrs . Other . UsrDat . RoleInCurrentCrsDB = = Rol_STUDENT & &
2014-12-01 23:55:08 +01:00
LstGrpsUsrWants . NumGrps > = 2 )
SelectionIsValid = Grp_CheckIfSelectionGrpsIsValid ( & LstGrpsUsrWants ) ;
/***** Free list of groups types and groups in this course *****/
// The lists of group types and groups need to be freed here...
// ...in order to get them again when changing groups atomically
Grp_FreeListGrpTypesAndGrps ( ) ;
/***** Register user in the selected groups *****/
if ( SelectionIsValid )
{
if ( Grp_ChangeGrpsOtherUsrAtomically ( & LstGrpsUsrWants ) )
Lay_ShowAlert ( Lay_SUCCESS , Txt_The_requested_group_changes_were_successful ) ;
else
Lay_ShowAlert ( Lay_WARNING , Txt_There_has_been_no_change_in_groups ) ;
}
else
2017-03-30 11:20:06 +02:00
Lay_ShowAlert ( Lay_WARNING , Txt_In_a_type_of_group_with_single_enrolment_students_can_not_be_registered_in_more_than_one_group ) ;
2014-12-01 23:55:08 +01:00
/***** Free memory with the list of groups to/from which register/remove users *****/
Grp_FreeListCodGrp ( & LstGrpsUsrWants ) ;
}
/*****************************************************************************/
/********************** Change my groups atomically **************************/
/*****************************************************************************/
// Return true if desired changes are made
bool Grp_ChangeMyGrpsAtomically ( struct ListCodGrps * LstGrpsIWant )
{
struct ListCodGrps LstGrpsIBelong ;
unsigned NumGrpTyp ;
unsigned NumGrpIBelong ;
unsigned NumGrpIWant ;
unsigned NumGrpThisType ;
struct GroupType * GrpTyp ;
bool ITryToLeaveAClosedGroup = false ;
bool ITryToRegisterInAClosedGroup = false ;
bool ITryToRegisterInFullGroup = false ;
bool RemoveMeFromThisGrp ;
bool RegisterMeInThisGrp ;
bool ChangesMade = false ;
/***** Lock tables to make the inscription atomic *****/
DB_Query ( " LOCK TABLES crs_grp_types WRITE,crs_grp WRITE, "
" crs_grp_usr WRITE,crs_usr READ " ,
" Can not lock tables to change user's groups " ) ;
Gbl . DB . LockedTables = true ;
/***** Get list of groups types and groups in this course *****/
Grp_GetListGrpTypesAndGrpsInThisCrs ( Grp_ONLY_GROUP_TYPES_WITH_GROUPS ) ;
/***** Query in the database the group codes which I belong to *****/
Grp_GetLstCodGrpsUsrBelongs ( Gbl . CurrentCrs . Crs . CrsCod , - 1L ,
Gbl . Usrs . Me . UsrDat . UsrCod , & LstGrpsIBelong ) ;
2015-04-07 21:44:24 +02:00
if ( Gbl . Usrs . Me . LoggedRole = = Rol_STUDENT )
2014-12-01 23:55:08 +01:00
{
/***** Go across the list of groups which I belong to and check if I try to leave a closed group *****/
for ( NumGrpIBelong = 0 ;
NumGrpIBelong < LstGrpsIBelong . NumGrps & & ! ITryToLeaveAClosedGroup ;
NumGrpIBelong + + )
{
for ( NumGrpIWant = 0 , RemoveMeFromThisGrp = true ;
NumGrpIWant < LstGrpsIWant - > NumGrps & & RemoveMeFromThisGrp ;
NumGrpIWant + + )
2017-01-19 20:55:31 +01:00
if ( LstGrpsIBelong . GrpCods [ NumGrpIBelong ] = = LstGrpsIWant - > GrpCods [ NumGrpIWant ] )
2014-12-01 23:55:08 +01:00
RemoveMeFromThisGrp = false ;
if ( RemoveMeFromThisGrp )
/* Check if the group is closed */
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num & & ! ITryToLeaveAClosedGroup ;
NumGrpTyp + + )
{
GrpTyp = & Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ;
for ( NumGrpThisType = 0 ;
NumGrpThisType < GrpTyp - > NumGrps & & ! ITryToLeaveAClosedGroup ;
NumGrpThisType + + )
2017-01-19 20:55:31 +01:00
if ( ( GrpTyp - > LstGrps [ NumGrpThisType ] ) . GrpCod = = LstGrpsIBelong . GrpCods [ NumGrpIBelong ] )
2014-12-01 23:55:08 +01:00
if ( ! ( ( GrpTyp - > LstGrps [ NumGrpThisType ] ) . Open ) )
ITryToLeaveAClosedGroup = true ;
}
}
if ( ! ITryToLeaveAClosedGroup )
/***** Go across the list of groups which I want to belong
and check that they are not closed or full * * * * */
for ( NumGrpIWant = 0 ;
NumGrpIWant < LstGrpsIWant - > NumGrps & &
! ITryToRegisterInAClosedGroup & &
! ITryToRegisterInFullGroup ;
NumGrpIWant + + )
{
for ( NumGrpIBelong = 0 , RegisterMeInThisGrp = true ;
NumGrpIBelong < LstGrpsIBelong . NumGrps & & RegisterMeInThisGrp ;
NumGrpIBelong + + )
2017-01-19 20:55:31 +01:00
if ( LstGrpsIWant - > GrpCods [ NumGrpIWant ] = = LstGrpsIBelong . GrpCods [ NumGrpIBelong ] )
2014-12-01 23:55:08 +01:00
RegisterMeInThisGrp = false ;
if ( RegisterMeInThisGrp )
/* Check if the group is closed or full */
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num & &
! ITryToRegisterInAClosedGroup & &
! ITryToRegisterInFullGroup ;
NumGrpTyp + + )
{
GrpTyp = & Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ;
for ( NumGrpThisType = 0 ;
NumGrpThisType < GrpTyp - > NumGrps & &
! ITryToRegisterInAClosedGroup & &
! ITryToRegisterInFullGroup ;
NumGrpThisType + + )
2017-01-19 20:55:31 +01:00
if ( ( GrpTyp - > LstGrps [ NumGrpThisType ] ) . GrpCod = = LstGrpsIWant - > GrpCods [ NumGrpIWant ] )
2014-12-01 23:55:08 +01:00
{
/* Check if the group is closed */
if ( ! ( ( GrpTyp - > LstGrps [ NumGrpThisType ] ) . Open ) )
ITryToRegisterInAClosedGroup = true ;
/* Check if the group is full */
else if ( ( GrpTyp - > LstGrps [ NumGrpThisType ] ) . NumStudents > =
( GrpTyp - > LstGrps [ NumGrpThisType ] ) . MaxStudents )
ITryToRegisterInFullGroup = true ;
}
}
}
}
if ( ! ITryToLeaveAClosedGroup & &
! ITryToRegisterInAClosedGroup & &
! ITryToRegisterInFullGroup )
{
/***** Go across the list of groups I belong to, removing those groups that are not present in the list of groups I want to belong to *****/
for ( NumGrpIBelong = 0 ;
NumGrpIBelong < LstGrpsIBelong . NumGrps ;
NumGrpIBelong + + )
{
for ( NumGrpIWant = 0 , RemoveMeFromThisGrp = true ;
NumGrpIWant < LstGrpsIWant - > NumGrps & & RemoveMeFromThisGrp ;
NumGrpIWant + + )
2017-01-19 20:55:31 +01:00
if ( LstGrpsIBelong . GrpCods [ NumGrpIBelong ] = = LstGrpsIWant - > GrpCods [ NumGrpIWant ] )
2014-12-01 23:55:08 +01:00
RemoveMeFromThisGrp = false ;
if ( RemoveMeFromThisGrp )
2017-01-19 20:55:31 +01:00
Grp_RemoveUsrFromGroup ( Gbl . Usrs . Me . UsrDat . UsrCod , LstGrpsIBelong . GrpCods [ NumGrpIBelong ] ) ;
2014-12-01 23:55:08 +01:00
}
/***** Go across the list of groups that I want to register in, adding those groups that are not present in the list of groups I belong to *****/
for ( NumGrpIWant = 0 ;
NumGrpIWant < LstGrpsIWant - > NumGrps ;
NumGrpIWant + + )
{
for ( NumGrpIBelong = 0 , RegisterMeInThisGrp = true ;
NumGrpIBelong < LstGrpsIBelong . NumGrps & & RegisterMeInThisGrp ;
NumGrpIBelong + + )
2017-01-19 20:55:31 +01:00
if ( LstGrpsIWant - > GrpCods [ NumGrpIWant ] = = LstGrpsIBelong . GrpCods [ NumGrpIBelong ] )
2014-12-01 23:55:08 +01:00
RegisterMeInThisGrp = false ;
if ( RegisterMeInThisGrp )
2017-01-19 20:55:31 +01:00
Grp_AddUsrToGroup ( & Gbl . Usrs . Me . UsrDat , LstGrpsIWant - > GrpCods [ NumGrpIWant ] ) ;
2014-12-01 23:55:08 +01:00
}
ChangesMade = true ;
}
/***** Free memory with the list of groups which I belonged to *****/
Grp_FreeListCodGrp ( & LstGrpsIBelong ) ;
/***** Unlock tables after changes in my groups *****/
Gbl . DB . LockedTables = false ; // Set to false before the following unlock...
// ...to not retry the unlock if error in unlocking
DB_Query ( " UNLOCK TABLES " ,
" Can not unlock tables after changes in user's groups " ) ;
/***** Free list of groups types and groups in this course *****/
Grp_FreeListGrpTypesAndGrps ( ) ;
return ChangesMade ;
}
/*****************************************************************************/
/********************** Change my groups atomically **************************/
/*****************************************************************************/
// Return true if desired changes are made
bool Grp_ChangeGrpsOtherUsrAtomically ( struct ListCodGrps * LstGrpsUsrWants )
{
struct ListCodGrps LstGrpsUsrBelongs ;
unsigned NumGrpUsrBelongs ;
unsigned NumGrpUsrWants ;
bool RemoveUsrFromThisGrp ;
bool RegisterUsrInThisGrp ;
bool ChangesMade = false ;
2015-04-07 21:44:24 +02:00
if ( Gbl . Usrs . Other . UsrDat . RoleInCurrentCrsDB = = Rol_STUDENT )
2014-12-01 23:55:08 +01:00
{
/***** Lock tables to make the inscription atomic *****/
DB_Query ( " LOCK TABLES crs_grp_types WRITE,crs_grp WRITE, "
" crs_grp_usr WRITE,crs_usr READ " ,
" Can not lock tables to change user's groups " ) ;
Gbl . DB . LockedTables = true ;
}
/***** Get list of groups types and groups in this course *****/
Grp_GetListGrpTypesAndGrpsInThisCrs ( Grp_ONLY_GROUP_TYPES_WITH_GROUPS ) ;
/***** Query in the database the group codes which user belongs to *****/
Grp_GetLstCodGrpsUsrBelongs ( Gbl . CurrentCrs . Crs . CrsCod , - 1L ,
Gbl . Usrs . Other . UsrDat . UsrCod , & LstGrpsUsrBelongs ) ;
/***** Go across the list of groups user belongs to, removing those groups that are not present in the list of groups user wants to belong to *****/
for ( NumGrpUsrBelongs = 0 ;
NumGrpUsrBelongs < LstGrpsUsrBelongs . NumGrps ;
NumGrpUsrBelongs + + )
{
for ( NumGrpUsrWants = 0 , RemoveUsrFromThisGrp = true ;
NumGrpUsrWants < LstGrpsUsrWants - > NumGrps & & RemoveUsrFromThisGrp ;
NumGrpUsrWants + + )
2017-01-19 20:55:31 +01:00
if ( LstGrpsUsrBelongs . GrpCods [ NumGrpUsrBelongs ] = = LstGrpsUsrWants - > GrpCods [ NumGrpUsrWants ] )
2014-12-01 23:55:08 +01:00
RemoveUsrFromThisGrp = false ;
if ( RemoveUsrFromThisGrp )
2017-01-19 20:55:31 +01:00
Grp_RemoveUsrFromGroup ( Gbl . Usrs . Other . UsrDat . UsrCod , LstGrpsUsrBelongs . GrpCods [ NumGrpUsrBelongs ] ) ;
2014-12-01 23:55:08 +01:00
}
/***** Go across the list of groups that user wants to register in, adding those groups that are not present in the list of groups user belongs to *****/
for ( NumGrpUsrWants = 0 ;
NumGrpUsrWants < LstGrpsUsrWants - > NumGrps ;
NumGrpUsrWants + + )
{
for ( NumGrpUsrBelongs = 0 , RegisterUsrInThisGrp = true ;
NumGrpUsrBelongs < LstGrpsUsrBelongs . NumGrps & & RegisterUsrInThisGrp ;
NumGrpUsrBelongs + + )
2017-01-19 20:55:31 +01:00
if ( LstGrpsUsrWants - > GrpCods [ NumGrpUsrWants ] = = LstGrpsUsrBelongs . GrpCods [ NumGrpUsrBelongs ] )
2014-12-01 23:55:08 +01:00
RegisterUsrInThisGrp = false ;
if ( RegisterUsrInThisGrp )
2017-01-19 20:55:31 +01:00
Grp_AddUsrToGroup ( & Gbl . Usrs . Other . UsrDat , LstGrpsUsrWants - > GrpCods [ NumGrpUsrWants ] ) ;
2014-12-01 23:55:08 +01:00
}
ChangesMade = true ;
/***** Free memory with the list of groups which I belonged to *****/
Grp_FreeListCodGrp ( & LstGrpsUsrBelongs ) ;
/***** Unlock tables after changes in my groups *****/
2015-04-07 21:44:24 +02:00
if ( Gbl . Usrs . Other . UsrDat . RoleInCurrentCrsDB = = Rol_STUDENT )
2014-12-01 23:55:08 +01:00
{
Gbl . DB . LockedTables = false ; // Set to false before the following unlock...
// ...to not retry the unlock if error in unlocking
DB_Query ( " UNLOCK TABLES " ,
" Can not unlock tables after changes in user's groups " ) ;
}
/***** Free list of groups types and groups in this course *****/
Grp_FreeListGrpTypesAndGrps ( ) ;
return ChangesMade ;
}
/*****************************************************************************/
2017-03-30 11:20:06 +02:00
/***** Check if no se ha selected m<> s of a group of single enrolment ********/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
bool Grp_CheckIfSelectionGrpsIsValid ( struct ListCodGrps * LstGrps )
{
struct ListGrpsAlreadySelec * AlreadyExistsGroupOfType ;
unsigned NumCodGrp ;
unsigned NumGrpTyp ;
long GrpTypCod ;
bool SelectionValid = true ;
/***** Create and initialize list of groups already selected *****/
Grp_ConstructorListGrpAlreadySelec ( & AlreadyExistsGroupOfType ) ;
/***** Go across the list of groups selected checking if a group of the same type
is already selected * * * * */
for ( NumCodGrp = 0 ;
SelectionValid & & NumCodGrp < LstGrps - > NumGrps ;
NumCodGrp + + )
{
2017-01-19 20:55:31 +01:00
GrpTypCod = Grp_GetTypeOfGroupOfAGroup ( LstGrps - > GrpCods [ NumCodGrp ] ) ;
2017-03-30 11:20:06 +02:00
if ( ! Grp_GetMultipleEnrolmentOfAGroupType ( GrpTypCod ) )
2014-12-01 23:55:08 +01:00
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
if ( GrpTypCod = = AlreadyExistsGroupOfType [ NumGrpTyp ] . GrpTypCod )
{
if ( AlreadyExistsGroupOfType [ NumGrpTyp ] . AlreadySelected )
SelectionValid = false ;
else
AlreadyExistsGroupOfType [ NumGrpTyp ] . AlreadySelected = true ;
break ;
}
}
/***** Free memory of the list of booleanos that indicates
if a group of each type has been selected * * * * */
Grp_DestructorListGrpAlreadySelec ( & AlreadyExistsGroupOfType ) ;
return SelectionValid ; // Return true if the selection of groups is correct
}
/*****************************************************************************/
/*********** Create e inicializar list of groups already selected ************/
/*****************************************************************************/
static void Grp_ConstructorListGrpAlreadySelec ( struct ListGrpsAlreadySelec * * AlreadyExistsGroupOfType )
{
unsigned NumGrpTyp ;
/***** Allocate memory to a list of booleanos that indica if already se ha selected a group of cada type *****/
if ( ( * AlreadyExistsGroupOfType = ( struct ListGrpsAlreadySelec * ) calloc ( Gbl . CurrentCrs . Grps . GrpTypes . Num , sizeof ( struct ListGrpsAlreadySelec ) ) ) = = NULL )
Lay_ShowErrorAndExit ( " Not enough memory to store type of group. " ) ;
/***** Initialize the list *****/
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
{
( * AlreadyExistsGroupOfType ) [ NumGrpTyp ] . GrpTypCod = Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ;
( * AlreadyExistsGroupOfType ) [ NumGrpTyp ] . AlreadySelected = false ;
}
}
/*****************************************************************************/
/***************** Liberar list of groups already selected *******************/
/*****************************************************************************/
static void Grp_DestructorListGrpAlreadySelec ( struct ListGrpsAlreadySelec * * AlreadyExistsGroupOfType )
{
free ( ( void * ) * AlreadyExistsGroupOfType ) ;
* AlreadyExistsGroupOfType = NULL ;
}
/*****************************************************************************/
/******************* Register user in the groups of a list *******************/
/*****************************************************************************/
void Grp_RegisterUsrIntoGroups ( struct UsrData * UsrDat , struct ListCodGrps * LstGrps )
{
extern const char * Txt_THE_USER_X_has_been_removed_from_the_group_of_type_Y_to_which_it_belonged ;
2017-03-30 11:20:06 +02:00
extern const char * Txt_THE_USER_X_has_been_enroled_in_the_group_of_type_Y_Z ;
2014-12-01 23:55:08 +01:00
struct ListCodGrps LstGrpsHeBelongs ;
2016-12-29 22:19:46 +01:00
unsigned NumGrpTyp ;
unsigned NumGrpSel ;
unsigned NumGrpThisType ;
unsigned NumGrpHeBelongs ;
2017-03-30 11:20:06 +02:00
bool MultipleEnrolment ;
2014-12-01 23:55:08 +01:00
bool AlreadyRegisteredInGrp ;
/***** For each existing type of group in the course... *****/
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
{
2017-03-30 11:20:06 +02:00
MultipleEnrolment = Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MultipleEnrolment ;
2014-12-01 23:55:08 +01:00
/***** Query in the database the group codes of any group of this type the student belongs to *****/
2016-12-29 22:42:57 +01:00
LstGrpsHeBelongs . NumGrps = 0 ; // Initialized to avoid bug reported by Coverity
2017-01-19 20:55:31 +01:00
LstGrpsHeBelongs . GrpCods = NULL ; // Initialized to avoid bug reported by Coverity
2014-12-01 23:55:08 +01:00
Grp_GetLstCodGrpsUsrBelongs ( Gbl . CurrentCrs . Crs . CrsCod , Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ,
UsrDat - > UsrCod , & LstGrpsHeBelongs ) ;
/***** For each group selected by me... *****/
for ( NumGrpSel = 0 ;
NumGrpSel < LstGrps - > NumGrps ;
NumGrpSel + + )
{
/* Check if the selected group is of this type */
for ( NumGrpThisType = 0 ;
NumGrpThisType < Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps ;
NumGrpThisType + + )
2017-01-19 20:55:31 +01:00
if ( LstGrps - > GrpCods [ NumGrpSel ] = = Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . LstGrps [ NumGrpThisType ] . GrpCod )
2014-12-01 23:55:08 +01:00
{ // The selected group is of this type
AlreadyRegisteredInGrp = false ;
/* For each group of this type to which the user belongs... */
for ( NumGrpHeBelongs = 0 ;
NumGrpHeBelongs < LstGrpsHeBelongs . NumGrps ;
NumGrpHeBelongs + + )
2017-01-19 20:55:31 +01:00
if ( LstGrps - > GrpCods [ NumGrpSel ] = = LstGrpsHeBelongs . GrpCods [ NumGrpHeBelongs ] )
2014-12-01 23:55:08 +01:00
AlreadyRegisteredInGrp = true ;
2017-03-30 11:20:06 +02:00
else if ( ! MultipleEnrolment ) // If the type of group is of single enrolment
2014-12-01 23:55:08 +01:00
{
2017-03-30 11:20:06 +02:00
/* If the enrolment is single and the group to which the user belongs is different from the selected ==>
2014-12-01 23:55:08 +01:00
remove user from the group to which he belongs */
2017-01-19 20:55:31 +01:00
Grp_RemoveUsrFromGroup ( UsrDat - > UsrCod , LstGrpsHeBelongs . GrpCods [ NumGrpHeBelongs ] ) ;
2014-12-01 23:55:08 +01:00
sprintf ( Gbl . Message , Txt_THE_USER_X_has_been_removed_from_the_group_of_type_Y_to_which_it_belonged ,
UsrDat - > FullName , Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypName ) ;
Lay_ShowAlert ( Lay_SUCCESS , Gbl . Message ) ;
}
if ( ! AlreadyRegisteredInGrp ) // If the user does not belong to the selected group
{
2017-01-19 20:55:31 +01:00
Grp_AddUsrToGroup ( UsrDat , LstGrps - > GrpCods [ NumGrpSel ] ) ;
2017-03-30 11:20:06 +02:00
sprintf ( Gbl . Message , Txt_THE_USER_X_has_been_enroled_in_the_group_of_type_Y_Z ,
2014-12-01 23:55:08 +01:00
UsrDat - > FullName , Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypName ,
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . LstGrps [ NumGrpThisType ] . GrpName ) ;
Lay_ShowAlert ( Lay_SUCCESS , Gbl . Message ) ;
}
break ; // Once we know the type of a selected group, it's not necessary to check the rest of types
}
}
/***** Free the list of groups of this type to which the user belonged *****/
Grp_FreeListCodGrp ( & LstGrpsHeBelongs ) ;
}
}
/*****************************************************************************/
/**************** Remove user of the groups indicados in a list **************/
/*****************************************************************************/
// Returns NumGrpsHeIsRemoved
unsigned Grp_RemoveUsrFromGroups ( struct UsrData * UsrDat , struct ListCodGrps * LstGrps )
{
extern const char * Txt_THE_USER_X_has_not_been_removed_from_any_group ;
extern const char * Txt_THE_USER_X_has_been_removed_from_one_group ;
extern const char * Txt_THE_USER_X_has_been_removed_from_Y_groups ;
struct ListCodGrps LstGrpsHeBelongs ;
unsigned NumGrpSel , NumGrpHeBelongs , NumGrpsHeIsRemoved = 0 ;
/***** Query in the database the group codes of any group the user belongs to *****/
Grp_GetLstCodGrpsUsrBelongs ( Gbl . CurrentCrs . Crs . CrsCod , - 1L ,
UsrDat - > UsrCod , & LstGrpsHeBelongs ) ;
/***** For each group selected by me... *****/
for ( NumGrpSel = 0 ;
NumGrpSel < LstGrps - > NumGrps ;
NumGrpSel + + )
/* For each group to which the user belongs... */
for ( NumGrpHeBelongs = 0 ;
NumGrpHeBelongs < LstGrpsHeBelongs . NumGrps ;
NumGrpHeBelongs + + )
/* If the user belongs to a selected group from which he must be removed */
2017-01-19 20:55:31 +01:00
if ( LstGrpsHeBelongs . GrpCods [ NumGrpHeBelongs ] = = LstGrps - > GrpCods [ NumGrpSel ] )
2014-12-01 23:55:08 +01:00
{
2017-01-19 20:55:31 +01:00
Grp_RemoveUsrFromGroup ( UsrDat - > UsrCod , LstGrpsHeBelongs . GrpCods [ NumGrpHeBelongs ] ) ;
2014-12-01 23:55:08 +01:00
NumGrpsHeIsRemoved + + ;
}
/***** Write message to inform about how many groups the student has been removed from *****/
if ( NumGrpsHeIsRemoved = = 0 )
sprintf ( Gbl . Message , Txt_THE_USER_X_has_not_been_removed_from_any_group ,
UsrDat - > FullName ) ;
else if ( NumGrpsHeIsRemoved = = 1 )
sprintf ( Gbl . Message , Txt_THE_USER_X_has_been_removed_from_one_group ,
UsrDat - > FullName ) ;
else // NumGrpsHeIsRemoved > 1
sprintf ( Gbl . Message , Txt_THE_USER_X_has_been_removed_from_Y_groups ,
UsrDat - > FullName , NumGrpsHeIsRemoved ) ;
Lay_ShowAlert ( Lay_SUCCESS , Gbl . Message ) ;
/***** Free the list of groups of this type to which the user belonged *****/
Grp_FreeListCodGrp ( & LstGrpsHeBelongs ) ;
return NumGrpsHeIsRemoved ;
}
/*****************************************************************************/
/*************** Remove a user of all the groups of a course *****************/
/*****************************************************************************/
void Grp_RemUsrFromAllGrpsInCrs ( struct UsrData * UsrDat , struct Course * Crs , Cns_QuietOrVerbose_t QuietOrVerbose )
{
extern const char * Txt_THE_USER_X_has_been_removed_from_all_groups_of_the_course_Y ;
2017-03-11 00:47:23 +01:00
char Query [ 512 ] ;
2014-12-01 23:55:08 +01:00
/***** Remove user from all the groups of the course *****/
sprintf ( Query , " DELETE FROM crs_grp_usr "
2017-03-24 01:09:27 +01:00
" WHERE UsrCod=%ld AND GrpCod IN "
2014-12-01 23:55:08 +01:00
" (SELECT crs_grp.GrpCod FROM crs_grp_types,crs_grp "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp_types.CrsCod=%ld "
2017-03-11 00:47:23 +01:00
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod) " ,
2014-12-01 23:55:08 +01:00
UsrDat - > UsrCod , Crs - > CrsCod ) ;
DB_QueryDELETE ( Query , " can not remove a user from all groups of a course " ) ;
/***** Write message to show the change made *****/
if ( QuietOrVerbose = = Cns_VERBOSE )
{
sprintf ( Gbl . Message , Txt_THE_USER_X_has_been_removed_from_all_groups_of_the_course_Y ,
UsrDat - > FullName , Crs - > FullName ) ;
Lay_ShowAlert ( Lay_SUCCESS , Gbl . Message ) ;
}
}
/*****************************************************************************/
/******* Remove a user from all the groups of all the user's courses *********/
/*****************************************************************************/
void Grp_RemUsrFromAllGrps ( struct UsrData * UsrDat , Cns_QuietOrVerbose_t QuietOrVerbose )
{
extern const char * Txt_THE_USER_X_has_been_removed_from_all_groups_in_all_courses ;
2017-03-11 00:47:23 +01:00
char Query [ 128 ] ;
2014-12-01 23:55:08 +01:00
/***** Remove user from all groups *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " DELETE FROM crs_grp_usr WHERE UsrCod=%ld " ,
2014-12-01 23:55:08 +01:00
UsrDat - > UsrCod ) ;
DB_QueryDELETE ( Query , " can not remove a user from the groups he/she belongs to " ) ;
/***** Write message to show the change made *****/
if ( QuietOrVerbose = = Cns_VERBOSE )
{
sprintf ( Gbl . Message , Txt_THE_USER_X_has_been_removed_from_all_groups_in_all_courses ,
UsrDat - > FullName ) ;
Lay_ShowAlert ( Lay_SUCCESS , Gbl . Message ) ;
}
}
/*****************************************************************************/
/************************* Remove a user from a group ************************/
/*****************************************************************************/
static void Grp_RemoveUsrFromGroup ( long UsrCod , long GrpCod )
{
2017-03-11 00:47:23 +01:00
char Query [ 256 ] ;
2014-12-01 23:55:08 +01:00
/***** Remove user from group *****/
sprintf ( Query , " DELETE FROM crs_grp_usr "
2017-03-24 01:09:27 +01:00
" WHERE GrpCod=%ld AND UsrCod=%ld " ,
2014-12-01 23:55:08 +01:00
GrpCod , UsrCod ) ;
DB_QueryDELETE ( Query , " can not remove a user from a group " ) ;
}
/*****************************************************************************/
/*********************** Register a user in a group **************************/
/*****************************************************************************/
static void Grp_AddUsrToGroup ( struct UsrData * UsrDat , long GrpCod )
{
2017-03-11 00:47:23 +01:00
char Query [ 256 ] ;
2014-12-01 23:55:08 +01:00
/***** Register in group *****/
2017-03-13 13:17:53 +01:00
sprintf ( Query , " INSERT INTO crs_grp_usr "
" (GrpCod,UsrCod) "
" VALUES "
2017-03-24 01:09:27 +01:00
" (%ld,%ld) " ,
2014-12-01 23:55:08 +01:00
GrpCod , UsrDat - > UsrCod ) ;
DB_QueryINSERT ( Query , " can not add a user to a group " ) ;
}
/*****************************************************************************/
/******************** List current group types for edition *******************/
/*****************************************************************************/
static void Grp_ListGroupTypesForEdition ( void )
{
2017-04-29 20:16:53 +02:00
2014-12-01 23:55:08 +01:00
extern const char * Txt_It_is_optional_to_choose_a_group ;
extern const char * Txt_It_is_mandatory_to_choose_a_group ;
extern const char * Txt_A_student_can_belong_to_several_groups ;
extern const char * Txt_A_student_can_only_belong_to_one_group ;
extern const char * Txt_The_groups_will_automatically_open ;
extern const char * Txt_The_groups_will_not_automatically_open ;
unsigned NumGrpTyp ;
2015-10-26 20:02:07 +01:00
unsigned UniqueId ;
char Id [ 32 ] ;
2014-12-01 23:55:08 +01:00
/***** Write heading *****/
2017-05-01 10:22:16 +02:00
Lay_StartTableWide ( 2 ) ;
2014-12-01 23:55:08 +01:00
Grp_WriteHeadingGroupTypes ( ) ;
/***** List group types with forms for edition *****/
2015-10-26 20:02:07 +01:00
for ( NumGrpTyp = 0 , UniqueId = 1 ;
2014-12-01 23:55:08 +01:00
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
2015-10-26 20:02:07 +01:00
NumGrpTyp + + , UniqueId + + )
2014-12-01 23:55:08 +01:00
{
/* Put icon to remove group type */
fprintf ( Gbl . F . Out , " <tr> "
" <td class= \" BM \" > " ) ;
2017-04-29 15:29:58 +02:00
Act_FormStartAnchor ( ActReqRemGrpTyp , Grp_SECTION_GROUP_TYPES ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpTypCod ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
2015-07-22 19:59:28 +02:00
Lay_PutIconRemove ( ) ;
2015-03-13 00:16:02 +01:00
Act_FormEnd ( ) ;
fprintf ( Gbl . F . Out , " </td> " ) ;
2014-12-01 23:55:08 +01:00
/* Name of group type */
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" LEFT_MIDDLE \" > " ) ;
2017-04-29 15:29:58 +02:00
Act_FormStartAnchor ( ActRenGrpTyp , Grp_SECTION_GROUP_TYPES ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpTypCod ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
2015-10-22 14:49:48 +02:00
fprintf ( Gbl . F . Out , " <input type= \" text \" name= \" GrpTypName \" "
2016-03-19 00:40:20 +01:00
" size= \" 12 \" maxlength= \" %u \" value= \" %s \" "
2015-10-22 14:49:48 +02:00
" onchange= \" document.getElementById('%s').submit(); \" /> " ,
2017-03-07 11:03:05 +01:00
Grp_MAX_CHARS_GROUP_TYPE_NAME ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypName ,
2016-01-14 10:31:09 +01:00
Gbl . Form . Id ) ;
2015-03-13 00:16:02 +01:00
Act_FormEnd ( ) ;
fprintf ( Gbl . F . Out , " </td> " ) ;
2014-12-01 23:55:08 +01:00
/* Is it mandatory to register in any group? */
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" CENTER_MIDDLE \" > " ) ;
2017-04-29 15:29:58 +02:00
Act_FormStartAnchor ( ActChgMdtGrpTyp , Grp_SECTION_GROUP_TYPES ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpTypCod ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
2017-03-30 11:20:06 +02:00
fprintf ( Gbl . F . Out , " <select name= \" MandatoryEnrolment \" "
2015-09-28 18:28:29 +02:00
" style= \" width:150px; \" "
2015-10-22 14:49:48 +02:00
" onchange= \" document.getElementById('%s').submit(); \" > "
2014-12-01 23:55:08 +01:00
" <option value= \" N \" " ,
2016-01-14 10:31:09 +01:00
Gbl . Form . Id ) ;
2017-03-30 11:20:06 +02:00
if ( ! Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MandatoryEnrolment )
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " selected= \" selected \" " ) ;
fprintf ( Gbl . F . Out , " >%s</option> "
" <option value= \" Y \" " ,
Txt_It_is_optional_to_choose_a_group ) ;
2017-03-30 11:20:06 +02:00
if ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MandatoryEnrolment )
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " selected= \" selected \" " ) ;
fprintf ( Gbl . F . Out , " >%s</option> "
2015-03-13 00:16:02 +01:00
" </select> " ,
2014-12-01 23:55:08 +01:00
Txt_It_is_mandatory_to_choose_a_group ) ;
2015-03-13 00:16:02 +01:00
Act_FormEnd ( ) ;
fprintf ( Gbl . F . Out , " </td> " ) ;
2014-12-01 23:55:08 +01:00
/* Is it possible to register in multiple groups? */
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" CENTER_MIDDLE \" > " ) ;
2017-04-29 15:29:58 +02:00
Act_FormStartAnchor ( ActChgMulGrpTyp , Grp_SECTION_GROUP_TYPES ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpTypCod ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
2017-03-30 11:20:06 +02:00
fprintf ( Gbl . F . Out , " <select name= \" MultipleEnrolment \" "
2015-09-28 18:28:29 +02:00
" style= \" width:150px; \" "
2015-10-22 14:49:48 +02:00
" onchange= \" document.getElementById('%s').submit(); \" > "
2014-12-01 23:55:08 +01:00
" <option value= \" N \" " ,
2016-01-14 10:31:09 +01:00
Gbl . Form . Id ) ;
2017-03-30 11:20:06 +02:00
if ( ! Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MultipleEnrolment )
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " selected= \" selected \" " ) ;
fprintf ( Gbl . F . Out , " >%s</option> "
" <option value= \" Y \" " ,
Txt_A_student_can_only_belong_to_one_group ) ;
2017-03-30 11:20:06 +02:00
if ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MultipleEnrolment )
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " selected= \" selected \" " ) ;
fprintf ( Gbl . F . Out , " >%s</option> "
2015-03-13 00:16:02 +01:00
" </select> " ,
2014-12-01 23:55:08 +01:00
Txt_A_student_can_belong_to_several_groups ) ;
2015-03-13 00:16:02 +01:00
Act_FormEnd ( ) ;
fprintf ( Gbl . F . Out , " </td> " ) ;
2014-12-01 23:55:08 +01:00
/* Open time */
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" LEFT_MIDDLE \" > " ) ;
2017-04-29 15:29:58 +02:00
Act_FormStartAnchor ( ActChgTimGrpTyp , Grp_SECTION_GROUP_TYPES ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpTypCod ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
2017-05-01 12:36:24 +02:00
Lay_StartTableCenter ( 2 ) ;
fprintf ( Gbl . F . Out , " <tr> "
2015-09-28 18:28:29 +02:00
" <td class= \" LEFT_MIDDLE \" style= \" width:20px; \" > "
2015-07-22 11:18:11 +02:00
" <img src= \" %s/%s16x16.gif \" "
" alt= \" %s \" title= \" %s \" "
2016-11-14 10:05:41 +01:00
" class= \" ICO20x20 \" /> "
2014-12-01 23:55:08 +01:00
" </td> "
2015-08-03 20:22:41 +02:00
" <td class= \" LEFT_MIDDLE \" > " ,
2014-12-01 23:55:08 +01:00
Gbl . Prefs . IconsURL ,
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MustBeOpened ? " time " :
" time-off " ,
2015-07-22 11:18:11 +02:00
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MustBeOpened ? Txt_The_groups_will_automatically_open :
Txt_The_groups_will_not_automatically_open ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MustBeOpened ? Txt_The_groups_will_automatically_open :
Txt_The_groups_will_not_automatically_open ) ;
2015-10-26 20:02:07 +01:00
sprintf ( Id , " open_time_%u " , UniqueId ) ;
Dat_WriteFormClientLocalDateTimeFromTimeUTC ( Id ,
" Open " ,
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . OpenTimeUTC ,
Gbl . Now . Date . Year ,
Gbl . Now . Date . Year + 1 ,
2016-12-03 20:08:01 +01:00
Dat_FORM_SECONDS_ON ,
2017-02-26 20:09:21 +01:00
Dat_HMS_DO_NOT_SET , // Don't set hour, minute and second
true ) ; // Submit on change
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " </td> "
2017-05-01 12:36:24 +02:00
" </tr> " ) ;
Lay_EndTable ( ) ;
2015-03-13 00:16:02 +01:00
Act_FormEnd ( ) ;
fprintf ( Gbl . F . Out , " </td> " ) ;
2014-12-01 23:55:08 +01:00
/* Number of groups of this type */
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" DAT CENTER_MIDDLE \" > "
2014-12-22 23:18:56 +01:00
" %u "
" </td> "
2014-12-01 23:55:08 +01:00
" </tr> " ,
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps ) ;
}
2017-04-29 20:16:53 +02:00
/***** End table *****/
2017-05-01 10:22:16 +02:00
Lay_EndTable ( ) ;
2014-12-01 23:55:08 +01:00
}
2017-04-29 19:19:55 +02:00
/*****************************************************************************/
/************ Put contextual icons in edition of types of group **************/
/*****************************************************************************/
static void Grp_PutIconsEditingGroupTypes ( void )
{
/***** Put icon to view groups *****/
Grp_PutIconToViewGroups ( ) ;
/***** Put icon to create a new type of group *****/
Grp_PutIconToCreateNewGroupType ( ) ;
}
static void Grp_PutIconToViewGroups ( void )
{
2017-04-30 23:48:48 +02:00
Lay_PutContextualIconToView ( ActReqSelGrp , NULL ) ;
2017-04-29 19:19:55 +02:00
}
static void Grp_PutIconToCreateNewGroupType ( void )
{
extern const char * Txt_New_type_of_group ;
/***** Put form to create a new type of group *****/
Lay_PutContextualLink ( ActReqEdiGrp , Grp_SECTION_NEW_GROUP_TYPE , NULL ,
" plus64x64.png " ,
Txt_New_type_of_group , NULL ,
NULL ) ;
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/*********************** Write heading of group types ************************/
/*****************************************************************************/
static void Grp_WriteHeadingGroupTypes ( void )
{
extern const char * Txt_Type_of_group ;
extern const char * Txt_eg_Lectures_Practicals ;
2017-03-30 11:20:06 +02:00
extern const char * Txt_Mandatory_enrolment ;
extern const char * Txt_Multiple_enrolment ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_Opening_of_groups ;
extern const char * Txt_No_of_BR_groups ;
fprintf ( Gbl . F . Out , " <tr> "
" <th class= \" BM \" ></th> "
2015-09-06 20:02:14 +02:00
" <th class= \" CENTER_MIDDLE \" > "
2014-12-26 22:11:03 +01:00
" %s<br />(%s) "
" </th> "
2015-09-06 20:02:14 +02:00
" <th class= \" CENTER_MIDDLE \" > "
2014-12-26 22:11:03 +01:00
" %s "
" </th> "
2015-09-06 20:02:14 +02:00
" <th class= \" CENTER_MIDDLE \" > "
2014-12-26 22:11:03 +01:00
" %s "
" </th> "
2015-09-06 20:02:14 +02:00
" <th class= \" CENTER_MIDDLE \" > "
2014-12-26 22:11:03 +01:00
" %s "
" </th> "
2015-09-06 20:02:14 +02:00
" <th class= \" CENTER_MIDDLE \" > "
2014-12-26 22:11:03 +01:00
" %s "
" </th> "
2014-12-01 23:55:08 +01:00
" </tr> " ,
Txt_Type_of_group , Txt_eg_Lectures_Practicals ,
2017-03-30 11:20:06 +02:00
Txt_Mandatory_enrolment ,
Txt_Multiple_enrolment ,
2014-12-01 23:55:08 +01:00
Txt_Opening_of_groups ,
Txt_No_of_BR_groups ) ;
}
/*****************************************************************************/
/********************** List current groups for edition **********************/
/*****************************************************************************/
static void Grp_ListGroupsForEdition ( void )
{
extern const char * Txt_Group_X_open_click_to_close_it ;
extern const char * Txt_Group_X_closed_click_to_open_it ;
extern const char * Txt_File_zones_of_the_group_X_enabled_click_to_disable_them ;
extern const char * Txt_File_zones_of_the_group_X_disabled_click_to_enable_them ;
unsigned NumGrpTyp ;
unsigned NumTipGrpAux ;
unsigned NumGrpThisType ;
struct GroupType * GrpTyp ;
struct GroupType * GrpTypAux ;
struct Group * Grp ;
/***** Write heading *****/
2017-05-01 10:22:16 +02:00
Lay_StartTableWide ( 2 ) ;
2014-12-01 23:55:08 +01:00
Grp_WriteHeadingGroups ( ) ;
/***** List the groups *****/
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
{
GrpTyp = & Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ;
for ( NumGrpThisType = 0 ;
NumGrpThisType < GrpTyp - > NumGrps ;
NumGrpThisType + + )
{
Grp = & ( GrpTyp - > LstGrps [ NumGrpThisType ] ) ;
/* Write icon to remove group */
fprintf ( Gbl . F . Out , " <tr> "
" <td class= \" BM \" > " ) ;
2017-04-29 15:29:58 +02:00
Act_FormStartAnchor ( ActReqRemGrp , Grp_SECTION_GROUPS ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpCod ( Grp - > GrpCod ) ;
2015-07-22 19:59:28 +02:00
Lay_PutIconRemove ( ) ;
2015-03-13 00:16:02 +01:00
Act_FormEnd ( ) ;
fprintf ( Gbl . F . Out , " </td> " ) ;
2014-12-01 23:55:08 +01:00
/* Write icon to open/close group */
fprintf ( Gbl . F . Out , " <td class= \" BM \" > " ) ;
2017-04-29 01:12:35 +02:00
Act_FormStartAnchor ( Grp - > Open ? ActCloGrp :
ActOpeGrp ,
2017-04-29 15:29:58 +02:00
Grp_SECTION_GROUPS ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpCod ( Grp - > GrpCod ) ;
sprintf ( Gbl . Title ,
Grp - > Open ? Txt_Group_X_open_click_to_close_it :
Txt_Group_X_closed_click_to_open_it ,
Grp - > GrpName ) ;
2016-12-05 01:54:03 +01:00
fprintf ( Gbl . F . Out , " <input type= \" image \" src= \" %s/%s-on64x64.png \" "
2015-09-05 12:04:30 +02:00
" alt= \" %s \" title= \" %s \" "
2016-11-14 10:05:41 +01:00
" class= \" ICO20x20 \" /> " ,
2014-12-01 23:55:08 +01:00
Gbl . Prefs . IconsURL ,
2016-12-05 01:54:03 +01:00
Grp - > Open ? " unlock " :
" lock " ,
2014-12-01 23:55:08 +01:00
Gbl . Title ,
Gbl . Title ) ;
2015-03-13 00:16:02 +01:00
Act_FormEnd ( ) ;
fprintf ( Gbl . F . Out , " </td> " ) ;
2014-12-01 23:55:08 +01:00
/* Write icon to activate file zones for this group */
fprintf ( Gbl . F . Out , " <td class= \" BM \" > " ) ;
2017-04-29 01:12:35 +02:00
Act_FormStartAnchor ( Grp - > FileZones ? ActDisFilZonGrp :
ActEnaFilZonGrp ,
2017-04-29 15:29:58 +02:00
Grp_SECTION_GROUPS ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpCod ( Grp - > GrpCod ) ;
sprintf ( Gbl . Title ,
Grp - > FileZones ? Txt_File_zones_of_the_group_X_enabled_click_to_disable_them :
Txt_File_zones_of_the_group_X_disabled_click_to_enable_them ,
Grp - > GrpName ) ;
fprintf ( Gbl . F . Out , " <input type= \" image \" src= \" %s/%s16x16.gif \" "
2015-09-05 12:04:30 +02:00
" alt= \" %s \" title= \" %s \" "
2016-11-14 10:05:41 +01:00
" class= \" ICO20x20 \" /> " ,
2014-12-01 23:55:08 +01:00
Gbl . Prefs . IconsURL ,
Grp - > FileZones ? " folder-yes " :
" folder-no " ,
Gbl . Title ,
Gbl . Title ) ;
2015-03-13 00:16:02 +01:00
Act_FormEnd ( ) ;
fprintf ( Gbl . F . Out , " </td> " ) ;
2014-12-01 23:55:08 +01:00
/* Group type */
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" CENTER_MIDDLE \" > " ) ;
2017-04-29 15:29:58 +02:00
Act_FormStartAnchor ( ActChgGrpTyp , Grp_SECTION_GROUPS ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpCod ( Grp - > GrpCod ) ;
2017-03-11 00:47:23 +01:00
fprintf ( Gbl . F . Out , " <select name= \" GrpTypCod \" style= \" width:150px; \" "
2015-10-22 14:49:48 +02:00
" onchange= \" document.getElementById('%s').submit(); \" > " ,
2016-01-14 10:31:09 +01:00
Gbl . Form . Id ) ;
2014-12-01 23:55:08 +01:00
for ( NumTipGrpAux = 0 ;
NumTipGrpAux < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumTipGrpAux + + )
{
GrpTypAux = & Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumTipGrpAux ] ;
fprintf ( Gbl . F . Out , " <option value= \" %ld \" " , GrpTypAux - > GrpTypCod ) ;
if ( GrpTypAux - > GrpTypCod = = GrpTyp - > GrpTypCod )
fprintf ( Gbl . F . Out , " selected= \" selected \" " ) ;
fprintf ( Gbl . F . Out , " >%s</option> " , GrpTypAux - > GrpTypName ) ;
}
2015-03-13 00:16:02 +01:00
fprintf ( Gbl . F . Out , " </select> " ) ;
Act_FormEnd ( ) ;
fprintf ( Gbl . F . Out , " </td> " ) ;
2014-12-01 23:55:08 +01:00
/* Group name */
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" CENTER_MIDDLE \" > " ) ;
2017-04-29 15:29:58 +02:00
Act_FormStartAnchor ( ActRenGrp , Grp_SECTION_GROUPS ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpCod ( Grp - > GrpCod ) ;
2015-10-22 14:49:48 +02:00
fprintf ( Gbl . F . Out , " <input type= \" text \" name= \" GrpName \" "
" size= \" 40 \" maxlength= \" %u \" value= \" %s \" "
2015-11-09 20:22:41 +01:00
" onchange= \" document.getElementById('%s').submit(); \" /> " ,
2017-03-07 11:03:05 +01:00
Grp_MAX_CHARS_GROUP_NAME , Grp - > GrpName , Gbl . Form . Id ) ;
2015-03-13 00:16:02 +01:00
Act_FormEnd ( ) ;
fprintf ( Gbl . F . Out , " </td> " ) ;
2014-12-01 23:55:08 +01:00
/* Maximum number of students of the group (row[3]) */
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" CENTER_MIDDLE \" > " ) ;
2017-04-29 15:29:58 +02:00
Act_FormStartAnchor ( ActChgMaxStdGrp , Grp_SECTION_GROUPS ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpCod ( Grp - > GrpCod ) ;
2015-10-22 14:49:48 +02:00
fprintf ( Gbl . F . Out , " <input type= \" text \" name= \" MaxStudents \" "
" size= \" 3 \" maxlength= \" 10 \" value= \" " ) ;
2014-12-01 23:55:08 +01:00
Grp_WriteMaxStdsGrp ( Grp - > MaxStudents ) ;
2015-10-22 14:49:48 +02:00
fprintf ( Gbl . F . Out , " \" onchange= \" document.getElementById('%s').submit(); \" /> " ,
2016-01-14 10:31:09 +01:00
Gbl . Form . Id ) ;
2015-03-13 00:16:02 +01:00
Act_FormEnd ( ) ;
fprintf ( Gbl . F . Out , " </td> " ) ;
2014-12-01 23:55:08 +01:00
/* Current number of students in this group */
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" DAT CENTER_MIDDLE \" > "
2014-12-22 23:18:56 +01:00
" %d "
" </td> "
2014-12-01 23:55:08 +01:00
" </tr> " ,
Grp - > NumStudents ) ;
}
}
2016-11-14 10:05:41 +01:00
/***** End table *****/
2017-05-01 10:22:16 +02:00
Lay_EndTable ( ) ;
2017-04-29 19:32:06 +02:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/************************** Write heading of groups **************************/
/*****************************************************************************/
static void Grp_WriteHeadingGroups ( void )
{
extern const char * Txt_Type_BR_of_group ;
extern const char * Txt_Group_name ;
extern const char * Txt_eg_A_B ;
extern const char * Txt_Max_BR_students ;
extern const char * Txt_Students_ABBREVIATION ;
fprintf ( Gbl . F . Out , " <tr> "
" <th class= \" BM \" ></th> "
" <th class= \" BM \" ></th> "
" <th class= \" BM \" ></th> "
2015-09-06 20:02:14 +02:00
" <th class= \" CENTER_MIDDLE \" > "
2014-12-26 22:11:03 +01:00
" %s "
" </th> "
2015-09-06 20:02:14 +02:00
" <th class= \" CENTER_MIDDLE \" > "
2014-12-26 22:11:03 +01:00
" %s<br />(%s) "
" </th> "
2015-09-06 20:02:14 +02:00
" <th class= \" CENTER_MIDDLE \" > "
2014-12-26 22:11:03 +01:00
" %s "
" </th> "
2015-09-06 20:02:14 +02:00
" <th class= \" CENTER_MIDDLE \" > "
2014-12-26 22:11:03 +01:00
" %s "
" </th> "
2014-12-01 23:55:08 +01:00
" </tr> " ,
Txt_Type_BR_of_group ,
Txt_Group_name , Txt_eg_A_B ,
Txt_Max_BR_students ,
Txt_Students_ABBREVIATION ) ;
}
/*****************************************************************************/
/* List groups of a type to edit assignments, attendance events, or surveys **/
/*****************************************************************************/
void Grp_ListGrpsToEditAsgAttOrSvy ( struct GroupType * GrpTyp , long Cod , Grp_AsgOrSvy_t Grp_AsgAttOrSvy )
{
struct ListCodGrps LstGrpsIBelong ;
unsigned NumGrpThisType ;
bool IBelongToThisGroup ;
struct Group * Grp ;
bool AssociatedToGrp = false ;
/***** Write heading *****/
Grp_WriteGrpHead ( GrpTyp ) ;
/***** Query from the database the groups of this type which I belong to *****/
Grp_GetLstCodGrpsUsrBelongs ( Gbl . CurrentCrs . Crs . CrsCod , GrpTyp - > GrpTypCod ,
Gbl . Usrs . Me . UsrDat . UsrCod , & LstGrpsIBelong ) ;
/***** List the groups *****/
for ( NumGrpThisType = 0 ;
NumGrpThisType < GrpTyp - > NumGrps ;
NumGrpThisType + + )
{
Grp = & ( GrpTyp - > LstGrps [ NumGrpThisType ] ) ;
IBelongToThisGroup = Grp_CheckIfGrpIsInList ( Grp - > GrpCod , & LstGrpsIBelong ) ;
/* Put checkbox to select the group */
fprintf ( Gbl . F . Out , " <tr> "
2015-09-04 19:26:08 +02:00
" <td class= \" LEFT_MIDDLE " ) ;
2014-12-01 23:55:08 +01:00
if ( IBelongToThisGroup )
2015-09-04 19:26:08 +02:00
fprintf ( Gbl . F . Out , " LIGHT_BLUE " ) ;
fprintf ( Gbl . F . Out , " \" > "
2016-12-20 14:03:46 +01:00
" <input type= \" checkbox \" "
" id= \" Grp%ld \" name= \" GrpCods \" value= \" %ld \" " ,
Grp - > GrpCod ,
2014-12-01 23:55:08 +01:00
Grp - > GrpCod ) ;
if ( Cod > 0 ) // Cod == -1L means new assignment or survey
{
switch ( Grp_AsgAttOrSvy )
{
case Grp_ASSIGNMENT :
AssociatedToGrp = Asg_CheckIfAsgIsAssociatedToGrp ( Cod , Grp - > GrpCod ) ;
break ;
case Grp_ATT_EVENT :
AssociatedToGrp = Att_CheckIfAttEventIsAssociatedToGrp ( Cod , Grp - > GrpCod ) ;
break ;
case Grp_SURVEY :
AssociatedToGrp = Svy_CheckIfSvyIsAssociatedToGrp ( Cod , Grp - > GrpCod ) ;
break ;
}
if ( AssociatedToGrp )
fprintf ( Gbl . F . Out , " checked= \" checked \" " ) ;
}
if ( ! ( IBelongToThisGroup | |
2015-04-07 21:44:24 +02:00
Gbl . Usrs . Me . LoggedRole = = Rol_SYS_ADM ) )
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " disabled= \" disabled \" " ) ;
2016-12-20 14:03:46 +01:00
fprintf ( Gbl . F . Out , " onclick= \" uncheckParent(this,'WholeCrs') \" /> "
" </td> " ) ;
2014-12-01 23:55:08 +01:00
Grp_WriteRowGrp ( Grp , IBelongToThisGroup ) ;
fprintf ( Gbl . F . Out , " </tr> " ) ;
}
/***** Free memory with the list of groups which I belongs to *****/
Grp_FreeListCodGrp ( & LstGrpsIBelong ) ;
}
/*****************************************************************************/
/***************** Show list of groups to register/remove me *****************/
/*****************************************************************************/
void Grp_ReqRegisterInGrps ( void )
{
2016-03-28 01:02:34 +02:00
/***** Show list of groups to register/remove me *****/
Grp_ShowLstGrpsToChgMyGrps ( ( Gbl . Usrs . Me . LoggedRole = = Rol_STUDENT ) ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/***************** Show list of groups to register/remove me *****************/
/*****************************************************************************/
2016-03-16 15:00:47 +01:00
void Grp_ShowLstGrpsToChgMyGrps ( bool ShowWarningsToStudents )
2014-12-01 23:55:08 +01:00
{
2016-11-13 20:54:06 +01:00
extern const char * Hlp_USERS_Groups ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_My_groups ;
2016-03-16 15:00:47 +01:00
extern const char * Txt_Change_my_groups ;
2017-03-30 11:20:06 +02:00
extern const char * Txt_Enrol_in_groups ;
2016-03-28 01:02:34 +02:00
extern const char * Txt_No_groups_have_been_created_in_the_course_X ;
2017-03-01 17:06:24 +01:00
extern const char * Txt_Create_group ;
2014-12-01 23:55:08 +01:00
unsigned NumGrpTyp ;
unsigned NumGrpsIBelong = 0 ;
2016-03-16 15:00:47 +01:00
bool PutFormToChangeGrps = ! Gbl . Form . Inside ; // Not inside another form (record card)
bool ICanEdit = ! Gbl . Form . Inside & &
( Gbl . Usrs . Me . LoggedRole = = Rol_TEACHER | |
Gbl . Usrs . Me . LoggedRole = = Rol_SYS_ADM ) ;
2014-12-01 23:55:08 +01:00
2016-03-28 01:02:34 +02:00
if ( Gbl . CurrentCrs . Grps . NumGrps ) // This course has groups
{
/***** Get list of groups types and groups in this course *****/
Grp_GetListGrpTypesAndGrpsInThisCrs ( Grp_ONLY_GROUP_TYPES_WITH_GROUPS ) ;
2014-12-01 23:55:08 +01:00
2016-03-28 01:02:34 +02:00
/***** Show warnings to students *****/
2017-03-30 11:20:06 +02:00
// Students are required to join groups with mandatory enrolment; teachers don't
2016-03-28 01:02:34 +02:00
if ( ShowWarningsToStudents )
Grp_ShowWarningToStdsToChangeGrps ( ) ;
}
2014-12-01 23:55:08 +01:00
2016-03-16 15:00:47 +01:00
/***** Start frame *****/
Lay_StartRoundFrame ( NULL , Txt_My_groups ,
2016-03-16 22:40:35 +01:00
ICanEdit ? Grp_PutIconToEditGroups :
2016-11-12 22:00:50 +01:00
NULL ,
2016-11-13 20:54:06 +01:00
Hlp_USERS_Groups ) ;
2016-03-16 15:00:47 +01:00
2016-03-28 01:02:34 +02:00
if ( Gbl . CurrentCrs . Grps . NumGrps ) // This course has groups
2016-03-16 15:00:47 +01:00
{
2016-03-28 01:02:34 +02:00
/***** Start form *****/
if ( PutFormToChangeGrps )
Act_FormStart ( ActChgGrp ) ;
/***** List the groups the user belongs to for change *****/
2017-05-01 10:22:16 +02:00
Lay_StartTableWide ( 2 ) ;
2016-03-28 01:02:34 +02:00
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
if ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps ) // If there are groups of this type
NumGrpsIBelong + = Grp_ListGrpsForChange ( & Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ) ;
2017-05-01 10:22:16 +02:00
Lay_EndTable ( ) ;
2016-03-28 01:02:34 +02:00
/***** End form *****/
if ( PutFormToChangeGrps )
{
Lay_PutConfirmButton ( NumGrpsIBelong ? Txt_Change_my_groups :
2017-03-30 11:20:06 +02:00
Txt_Enrol_in_groups ) ;
2016-03-28 01:02:34 +02:00
Act_FormEnd ( ) ;
}
}
else // This course has no groups
{
sprintf ( Gbl . Message , Txt_No_groups_have_been_created_in_the_course_X ,
Gbl . CurrentCrs . Crs . FullName ) ;
Lay_ShowAlert ( Lay_INFO , Gbl . Message ) ;
2017-03-01 17:06:24 +01:00
/***** Button to create group *****/
if ( ICanEdit )
{
Act_FormStart ( ActReqEdiGrp ) ;
Lay_PutConfirmButton ( Txt_Create_group ) ;
Act_FormEnd ( ) ;
}
2016-03-16 15:00:47 +01:00
}
/***** End frame *****/
Lay_EndRoundFrame ( ) ;
2014-12-01 23:55:08 +01:00
2016-03-28 01:02:34 +02:00
if ( Gbl . CurrentCrs . Grps . NumGrps ) // This course has groups
/***** Free list of groups types and groups in this course *****/
Grp_FreeListGrpTypesAndGrps ( ) ;
2016-03-16 15:00:47 +01:00
}
/*****************************************************************************/
/*************************** Put icon to edit groups *************************/
/*****************************************************************************/
2016-03-16 22:40:35 +01:00
static void Grp_PutIconToEditGroups ( void )
2016-03-16 15:00:47 +01:00
{
2017-04-30 23:48:48 +02:00
Lay_PutContextualIconToEdit ( ActReqEdiGrp , NULL ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********** Show warnings to students before form to change groups **********/
/*****************************************************************************/
static void Grp_ShowWarningToStdsToChangeGrps ( void )
{
extern const char * Txt_You_have_to_register_compulsorily_at_least_in_one_group_of_type_X ;
extern const char * Txt_You_have_to_register_compulsorily_in_one_group_of_type_X ;
extern const char * Txt_You_can_register_voluntarily_in_one_or_more_groups_of_type_X ;
extern const char * Txt_You_can_register_voluntarily_in_one_group_of_type_X ;
unsigned NumGrpTyp ;
struct GroupType * GrpTyp ;
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
{
GrpTyp = & Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ;
if ( GrpTyp - > NumGrps ) // If there are groups of this type
if ( Grp_GetFirstCodGrpStdBelongsTo ( GrpTyp - > GrpTypCod , Gbl . Usrs . Me . UsrDat . UsrCod ) < 0 ) // If the student does not belong to any group
if ( Grp_GetIfGrpIsAvailable ( GrpTyp - > GrpTypCod ) ) // If there is any group of this type available
{
2017-03-30 11:20:06 +02:00
if ( GrpTyp - > MandatoryEnrolment )
2014-12-01 23:55:08 +01:00
{
sprintf ( Gbl . Message ,
2017-03-30 11:20:06 +02:00
GrpTyp - > MultipleEnrolment ? Txt_You_have_to_register_compulsorily_at_least_in_one_group_of_type_X :
Txt_You_have_to_register_compulsorily_in_one_group_of_type_X ,
2014-12-01 23:55:08 +01:00
GrpTyp - > GrpTypName ) ;
Lay_ShowAlert ( Lay_WARNING , Gbl . Message ) ;
}
else
{
sprintf ( Gbl . Message ,
2017-03-30 11:20:06 +02:00
GrpTyp - > MultipleEnrolment ? Txt_You_can_register_voluntarily_in_one_or_more_groups_of_type_X :
Txt_You_can_register_voluntarily_in_one_group_of_type_X ,
2014-12-01 23:55:08 +01:00
GrpTyp - > GrpTypName ) ;
Lay_ShowAlert ( Lay_INFO , Gbl . Message ) ;
}
}
}
}
/*****************************************************************************/
/*************** List the groups of a type to register in ********************/
/*****************************************************************************/
// Returns the number of groups of this type I belong to
static unsigned Grp_ListGrpsForChange ( struct GroupType * GrpTyp )
{
struct ListCodGrps LstGrpsIBelong ;
unsigned NumGrpThisType ;
struct Group * Grp ;
bool IBelongToThisGroup ;
unsigned NumGrpsIBelong ;
/***** Write heading *****/
Grp_WriteGrpHead ( GrpTyp ) ;
/***** Query in the database the group of this type that I belong to *****/
Grp_GetLstCodGrpsUsrBelongs ( Gbl . CurrentCrs . Crs . CrsCod , GrpTyp - > GrpTypCod ,
Gbl . Usrs . Me . UsrDat . UsrCod , & LstGrpsIBelong ) ;
NumGrpsIBelong = LstGrpsIBelong . NumGrps ;
/***** List the groups *****/
for ( NumGrpThisType = 0 ;
NumGrpThisType < GrpTyp - > NumGrps ;
NumGrpThisType + + )
{
Grp = & ( GrpTyp - > LstGrps [ NumGrpThisType ] ) ;
IBelongToThisGroup = Grp_CheckIfGrpIsInList ( Grp - > GrpCod , & LstGrpsIBelong ) ;
/* Put icon to select the group */
fprintf ( Gbl . F . Out , " <tr> "
2015-09-04 19:26:08 +02:00
" <td class= \" LEFT_MIDDLE " ) ;
2014-12-01 23:55:08 +01:00
if ( IBelongToThisGroup )
2015-09-04 19:26:08 +02:00
fprintf ( Gbl . F . Out , " LIGHT_BLUE " ) ;
fprintf ( Gbl . F . Out , " \" > "
2014-12-22 23:18:56 +01:00
" <input type= \" " ) ;
2014-12-01 23:55:08 +01:00
2017-03-30 11:20:06 +02:00
// If user is a student and the enrolment is single
2014-12-01 23:55:08 +01:00
// and there are more than a group, put a radio item
2015-04-07 21:44:24 +02:00
if ( Gbl . Usrs . Me . LoggedRole = = Rol_STUDENT & &
2017-03-30 11:20:06 +02:00
! GrpTyp - > MultipleEnrolment & &
2014-12-01 23:55:08 +01:00
GrpTyp - > NumGrps > 1 )
{
2016-12-20 14:03:46 +01:00
fprintf ( Gbl . F . Out , " radio \" id= \" Grp%ld \" name= \" GrpCod%ld \" "
" value= \" %ld \" " ,
Grp - > GrpCod , GrpTyp - > GrpTypCod ,
Grp - > GrpCod ) ;
2017-03-30 11:20:06 +02:00
if ( ! GrpTyp - > MandatoryEnrolment ) // If the enrolment is not mandatory, I can select no groups
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " onclick= \" selectUnselectRadio(this,this.form.GrpCod%ld,%u) \" " ,
GrpTyp - > GrpTypCod , GrpTyp - > NumGrps ) ;
}
else // Put a checkbox item
2016-12-20 14:03:46 +01:00
fprintf ( Gbl . F . Out , " checkbox \" id= \" Grp%ld \" name= \" GrpCod%ld \" "
" value= \" %ld \" " ,
Grp - > GrpCod , GrpTyp - > GrpTypCod ,
Grp - > GrpCod ) ;
2014-12-01 23:55:08 +01:00
if ( IBelongToThisGroup )
fprintf ( Gbl . F . Out , " checked= \" checked \" " ) ;
2015-04-07 21:44:24 +02:00
else if ( ( Gbl . Usrs . Me . LoggedRole = = Rol_STUDENT ) & &
2014-12-01 23:55:08 +01:00
( ( ! Grp - > Open ) | | ( Grp - > NumStudents > = Grp - > MaxStudents ) ) )
fprintf ( Gbl . F . Out , " disabled= \" disabled \" " ) ;
fprintf ( Gbl . F . Out , " /></td> " ) ;
Grp_WriteRowGrp ( Grp , IBelongToThisGroup ) ;
fprintf ( Gbl . F . Out , " </tr> " ) ;
}
/***** Free memory with the list of groups a the that belongs the user *****/
Grp_FreeListCodGrp ( & LstGrpsIBelong ) ;
return NumGrpsIBelong ;
}
/*****************************************************************************/
/*************** Show list of groups to register/remove users ****************/
/*****************************************************************************/
// If UsrCod > 0 ==> mark her/his groups as checked
// If UsrCod <= 0 ==> do not mark any group as checked
void Grp_ShowLstGrpsToChgOtherUsrsGrps ( long UsrCod )
{
2016-11-13 20:54:06 +01:00
extern const char * Hlp_USERS_Groups ;
2015-02-08 18:39:58 +01:00
extern const char * Txt_Groups ;
2014-12-01 23:55:08 +01:00
unsigned NumGrpTyp ;
/***** Get list of groups types and groups in current course *****/
Grp_GetListGrpTypesAndGrpsInThisCrs ( Grp_ONLY_GROUP_TYPES_WITH_GROUPS ) ;
/***** Start table *****/
2016-11-14 10:05:41 +01:00
Lay_StartRoundFrameTable ( NULL , Txt_Groups , NULL , Hlp_USERS_Groups , 0 ) ;
2014-12-01 23:55:08 +01:00
/***** List to select the groups the user belongs to *****/
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
if ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps )
Grp_ListGrpsToAddOrRemUsrs ( & Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] , UsrCod ) ;
/***** End table *****/
2015-04-12 18:01:06 +02:00
Lay_EndRoundFrameTable ( ) ;
2014-12-01 23:55:08 +01:00
/***** Free list of groups types and groups in current course *****/
Grp_FreeListGrpTypesAndGrps ( ) ;
}
/*****************************************************************************/
/*************** List groups of a type to add or remove users ****************/
/*****************************************************************************/
// If UsrCod > 0 ==> mark her/his groups as checked
// If UsrCod <= 0 ==> do not mark any group as checked
static void Grp_ListGrpsToAddOrRemUsrs ( struct GroupType * GrpTyp , long UsrCod )
{
struct ListCodGrps LstGrpsIBelong ;
struct ListCodGrps LstGrpsUsrBelongs ;
unsigned NumGrpThisType ;
bool IBelongToThisGroup ;
bool UsrBelongsToThisGroup ;
struct Group * Grp ;
/***** Write heading *****/
Grp_WriteGrpHead ( GrpTyp ) ;
/***** Query from the database the groups of this type which I belong to *****/
Grp_GetLstCodGrpsUsrBelongs ( Gbl . CurrentCrs . Crs . CrsCod , GrpTyp - > GrpTypCod ,
Gbl . Usrs . Me . UsrDat . UsrCod , & LstGrpsIBelong ) ;
/***** Query from the database the groups of this type which I belong to *****/
if ( UsrCod > 0 )
Grp_GetLstCodGrpsUsrBelongs ( Gbl . CurrentCrs . Crs . CrsCod , GrpTyp - > GrpTypCod ,
Gbl . Usrs . Other . UsrDat . UsrCod , & LstGrpsUsrBelongs ) ;
/***** List the groups *****/
for ( NumGrpThisType = 0 ;
NumGrpThisType < GrpTyp - > NumGrps ;
NumGrpThisType + + )
{
Grp = & ( GrpTyp - > LstGrps [ NumGrpThisType ] ) ;
IBelongToThisGroup = Grp_CheckIfGrpIsInList ( Grp - > GrpCod , & LstGrpsIBelong ) ;
UsrBelongsToThisGroup = ( UsrCod > 0 ) ? Grp_CheckIfGrpIsInList ( Grp - > GrpCod , & LstGrpsUsrBelongs ) :
false ;
/* Put checkbox to select the group */
fprintf ( Gbl . F . Out , " <tr> "
2015-09-04 19:26:08 +02:00
" <td class= \" LEFT_MIDDLE " ) ;
2014-12-01 23:55:08 +01:00
if ( UsrBelongsToThisGroup )
2015-09-04 19:26:08 +02:00
fprintf ( Gbl . F . Out , " LIGHT_BLUE " ) ;
fprintf ( Gbl . F . Out , " \" > "
2016-12-20 14:03:46 +01:00
" <input type= \" checkbox \" "
" id= \" Grp%ld \" name= \" GrpCod%ld \" value= \" %ld \" " ,
Grp - > GrpCod , GrpTyp - > GrpTypCod ,
Grp - > GrpCod ) ;
2014-12-01 23:55:08 +01:00
if ( UsrBelongsToThisGroup )
fprintf ( Gbl . F . Out , " checked= \" checked \" " ) ;
if ( ! ( IBelongToThisGroup | |
2015-04-07 21:44:24 +02:00
Gbl . Usrs . Me . LoggedRole = = Rol_SYS_ADM ) )
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " disabled= \" disabled \" " ) ;
fprintf ( Gbl . F . Out , " /></td> " ) ;
Grp_WriteRowGrp ( Grp , UsrBelongsToThisGroup ) ;
fprintf ( Gbl . F . Out , " </tr> " ) ;
}
/***** Free memory with the lists of groups *****/
if ( UsrCod > 0 )
Grp_FreeListCodGrp ( & LstGrpsUsrBelongs ) ;
Grp_FreeListCodGrp ( & LstGrpsIBelong ) ;
}
/*****************************************************************************/
/******* Write a list of groups as checkbox form for unique selection ********/
/*****************************************************************************/
static void Grp_ListGrpsForMultipleSelection ( struct GroupType * GrpTyp )
{
extern const char * Txt_students_with_no_group ;
unsigned NumGrpThisType ;
unsigned NumGrpSel ;
struct ListCodGrps LstGrpsIBelong ;
bool IBelongToThisGroup ;
struct Group * Grp ;
/***** Write heading *****/
Grp_WriteGrpHead ( GrpTyp ) ;
/***** Query from the database the groups of this type which I belong to *****/
Grp_GetLstCodGrpsUsrBelongs ( Gbl . CurrentCrs . Crs . CrsCod , GrpTyp - > GrpTypCod ,
Gbl . Usrs . Me . UsrDat . UsrCod , & LstGrpsIBelong ) ;
/***** List the groups *****/
for ( NumGrpThisType = 0 ;
NumGrpThisType < GrpTyp - > NumGrps ;
NumGrpThisType + + )
{
Grp = & ( GrpTyp - > LstGrps [ NumGrpThisType ] ) ;
IBelongToThisGroup = Grp_CheckIfGrpIsInList ( Grp - > GrpCod , & LstGrpsIBelong ) ;
/* Put checkbox to select the group */
fprintf ( Gbl . F . Out , " <tr> "
2015-09-04 19:26:08 +02:00
" <td class= \" LEFT_MIDDLE " ) ;
2014-12-01 23:55:08 +01:00
if ( IBelongToThisGroup )
2015-09-04 19:26:08 +02:00
fprintf ( Gbl . F . Out , " LIGHT_BLUE " ) ;
fprintf ( Gbl . F . Out , " \" > "
2016-12-20 14:03:46 +01:00
" <input type= \" checkbox \" "
" id= \" Grp%ld \" name= \" GrpCods \" value= \" %ld \" " ,
Grp - > GrpCod ,
2014-12-01 23:55:08 +01:00
Grp - > GrpCod ) ;
if ( Gbl . Usrs . ClassPhoto . AllGroups )
fprintf ( Gbl . F . Out , " checked= \" checked \" " ) ;
else
for ( NumGrpSel = 0 ;
NumGrpSel < Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps ;
NumGrpSel + + )
2017-01-19 20:55:31 +01:00
if ( Gbl . CurrentCrs . Grps . LstGrpsSel . GrpCods [ NumGrpSel ] = = Grp - > GrpCod )
2014-12-01 23:55:08 +01:00
{
fprintf ( Gbl . F . Out , " checked= \" checked \" " ) ;
break ;
}
fprintf ( Gbl . F . Out , " onclick= \" checkParent(this,'AllGroups') \" /></td> " ) ;
Grp_WriteRowGrp ( Grp , IBelongToThisGroup ) ;
fprintf ( Gbl . F . Out , " </tr> " ) ;
}
/***** Free memory with the list of groups which I belongs to *****/
Grp_FreeListCodGrp ( & LstGrpsIBelong ) ;
/***** Write rows to select the students who don't belong to any group *****/
/* To get the students who don't belong to a type of group, use group code -(GrpTyp->GrpTypCod) */
/* Write checkbox to select the group */
fprintf ( Gbl . F . Out , " <tr> "
2015-08-03 20:22:41 +02:00
" <td class= \" LEFT_MIDDLE \" > "
2016-12-20 14:03:46 +01:00
" <input type= \" checkbox \" id= \" Grp%ld \" name= \" GrpCods \" "
" value= \" %ld \" " ,
- ( GrpTyp - > GrpTypCod ) ,
2014-12-01 23:55:08 +01:00
- ( GrpTyp - > GrpTypCod ) ) ;
if ( Gbl . Usrs . ClassPhoto . AllGroups )
fprintf ( Gbl . F . Out , " checked= \" checked \" " ) ;
else
for ( NumGrpSel = 0 ;
NumGrpSel < Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps ;
NumGrpSel + + )
2017-01-19 20:55:31 +01:00
if ( Gbl . CurrentCrs . Grps . LstGrpsSel . GrpCods [ NumGrpSel ] = = - ( GrpTyp - > GrpTypCod ) )
2014-12-01 23:55:08 +01:00
{
fprintf ( Gbl . F . Out , " checked= \" checked \" " ) ;
break ;
}
2016-12-20 14:03:46 +01:00
fprintf ( Gbl . F . Out , " onclick= \" checkParent(this,'AllGroups') \" /> "
" </td> " ) ;
2014-12-01 23:55:08 +01:00
/* Column closed/open */
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" LEFT_MIDDLE \" > "
2014-12-22 23:18:56 +01:00
" </td> " ) ;
2014-12-01 23:55:08 +01:00
/* Group name = students with no group */
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td colspan= \" 2 \" class= \" DAT LEFT_MIDDLE \" > "
2016-12-20 14:03:46 +01:00
" <label for= \" Grp%ld \" >%s</label> "
2014-12-22 23:18:56 +01:00
" </td> " ,
2016-12-20 14:03:46 +01:00
- ( GrpTyp - > GrpTypCod ) , Txt_students_with_no_group ) ;
2014-12-01 23:55:08 +01:00
/* Number of students who don't belong to any group of this type */
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" DAT CENTER_MIDDLE \" > "
2014-12-22 23:18:56 +01:00
" %u "
" </td> " ,
2014-12-01 23:55:08 +01:00
Grp_CountNumStdsInNoGrpsOfType ( GrpTyp - > GrpTypCod ) ) ;
/* Last column */
2014-12-22 23:18:56 +01:00
fprintf ( Gbl . F . Out , " <td></td> "
2014-12-01 23:55:08 +01:00
" </tr> " ) ;
}
/*****************************************************************************/
/************** Write a row with the head for list of groups *****************/
/*****************************************************************************/
static void Grp_WriteGrpHead ( struct GroupType * GrpTyp )
{
extern const char * Txt_Opening_of_groups ;
2015-12-29 11:35:01 +01:00
extern const char * Txt_Today ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_Group ;
extern const char * Txt_Max_BR_students ;
extern const char * Txt_Students_ABBREVIATION ;
extern const char * Txt_Vacants ;
2015-10-26 20:02:07 +01:00
static unsigned UniqueId = 0 ;
2014-12-01 23:55:08 +01:00
/***** Name of group type *****/
fprintf ( Gbl . F . Out , " <tr> "
2015-08-03 20:22:41 +02:00
" <td colspan= \" 6 \" class= \" GRP_TITLE LEFT_MIDDLE \" > "
2014-12-22 23:18:56 +01:00
" <br />%s " ,
2014-12-01 23:55:08 +01:00
GrpTyp - > GrpTypName ) ;
if ( GrpTyp - > MustBeOpened )
{
2015-10-26 20:02:07 +01:00
UniqueId + + ;
fprintf ( Gbl . F . Out , " <br />%s: "
" <span id= \" open_time_%u \" ></span> "
" <script type= \" text/javascript \" > "
2017-05-04 17:06:26 +02:00
" writeLocalDateHMSFromUTC('open_time_%u',%ld, "
2017-05-05 09:41:56 +02:00
" %u,', ','%s',true,true,0x7); "
2015-10-26 20:02:07 +01:00
" </script> " ,
Txt_Opening_of_groups ,
UniqueId ,
2017-05-04 17:06:26 +02:00
UniqueId , ( long ) GrpTyp - > OpenTimeUTC ,
( unsigned ) Gbl . Prefs . DateFormat , Txt_Today ) ;
2014-12-01 23:55:08 +01:00
}
fprintf ( Gbl . F . Out , " </td> "
" </tr> " ) ;
/***** Head row with title of each column *****/
fprintf ( Gbl . F . Out , " <tr> "
2015-09-05 19:19:39 +02:00
" <th colspan= \" 2 \" ></th> "
2015-09-06 20:02:14 +02:00
" <th class= \" LEFT_MIDDLE \" > "
2014-12-22 23:18:56 +01:00
" %s "
2015-09-05 19:19:39 +02:00
" </th> "
2015-09-06 20:02:14 +02:00
" <th class= \" CENTER_MIDDLE \" > "
2014-12-22 23:18:56 +01:00
" %s "
2015-09-05 19:19:39 +02:00
" </th> "
2015-09-06 20:02:14 +02:00
" <th class= \" CENTER_MIDDLE \" > "
2014-12-22 23:18:56 +01:00
" %s "
2015-09-05 19:19:39 +02:00
" </th> "
2015-09-06 20:02:14 +02:00
" <th class= \" CENTER_MIDDLE \" > "
2014-12-22 23:18:56 +01:00
" %s "
2015-09-05 19:19:39 +02:00
" </th> "
2014-12-01 23:55:08 +01:00
" </tr> " ,
Txt_Group ,
Txt_Max_BR_students ,
Txt_Students_ABBREVIATION ,
Txt_Vacants ) ;
}
/*****************************************************************************/
/****************** Write a row with the data of a group *********************/
/*****************************************************************************/
static void Grp_WriteRowGrp ( struct Group * Grp , bool Highlight )
{
extern const char * Txt_Group_X_open ;
extern const char * Txt_Group_X_closed ;
int Vacant ;
/***** Write icon to show if group is open or closed *****/
2015-07-22 11:18:11 +02:00
sprintf ( Gbl . Title , Grp - > Open ? Txt_Group_X_open :
Txt_Group_X_closed ,
Grp - > GrpName ) ;
2015-09-04 19:32:07 +02:00
fprintf ( Gbl . F . Out , " <td class= \" LEFT_MIDDLE " ) ;
2014-12-01 23:55:08 +01:00
if ( Highlight )
2015-09-04 19:26:08 +02:00
fprintf ( Gbl . F . Out , " LIGHT_BLUE " ) ;
2015-09-28 18:28:29 +02:00
fprintf ( Gbl . F . Out , " \" style= \" width:15px; \" > "
2016-12-05 01:54:03 +01:00
" <img src= \" %s/%s-off64x64.png \" "
2015-07-22 11:18:11 +02:00
" alt= \" %s \" title= \" %s \" "
2016-11-14 10:05:41 +01:00
" class= \" ICO20x20 \" /> "
2015-07-22 11:18:11 +02:00
" </td> " ,
2014-12-01 23:55:08 +01:00
Gbl . Prefs . IconsURL ,
2016-12-05 01:54:03 +01:00
Grp - > Open ? " unlock " :
" lock " ,
2015-07-22 11:18:11 +02:00
Gbl . Title , Gbl . Title ) ;
2014-12-01 23:55:08 +01:00
/***** Group name *****/
2016-12-23 22:19:03 +01:00
fprintf ( Gbl . F . Out , " <td class= \" LEFT_MIDDLE " ) ;
2014-12-01 23:55:08 +01:00
if ( Highlight )
2015-09-04 19:26:08 +02:00
fprintf ( Gbl . F . Out , " LIGHT_BLUE " ) ;
fprintf ( Gbl . F . Out , " \" > "
2016-12-23 22:19:03 +01:00
" <label for= \" Grp%ld \" class= \" DAT \" > "
2016-12-20 14:03:46 +01:00
" %s "
" </label> "
2014-12-22 23:18:56 +01:00
" </td> " ,
2016-12-20 14:03:46 +01:00
Grp - > GrpCod ,
2014-12-22 23:18:56 +01:00
Grp - > GrpName ) ;
2014-12-01 23:55:08 +01:00
/***** Max. number of students in this group *****/
2015-09-04 19:32:07 +02:00
fprintf ( Gbl . F . Out , " <td class= \" DAT CENTER_MIDDLE " ) ;
2014-12-01 23:55:08 +01:00
if ( Highlight )
2015-09-04 19:26:08 +02:00
fprintf ( Gbl . F . Out , " LIGHT_BLUE " ) ;
fprintf ( Gbl . F . Out , " \" > " ) ;
2014-12-01 23:55:08 +01:00
Grp_WriteMaxStdsGrp ( Grp - > MaxStudents ) ;
2014-12-22 23:18:56 +01:00
fprintf ( Gbl . F . Out , " "
" </td> " ) ;
2014-12-01 23:55:08 +01:00
/***** Current number of students in this group *****/
2015-09-04 19:26:08 +02:00
fprintf ( Gbl . F . Out , " <td class= \" DAT CENTER_MIDDLE " ) ;
2014-12-01 23:55:08 +01:00
if ( Highlight )
2015-09-04 19:26:08 +02:00
fprintf ( Gbl . F . Out , " LIGHT_BLUE " ) ;
fprintf ( Gbl . F . Out , " \" > "
2014-12-22 23:18:56 +01:00
" %d "
" </td> " ,
Grp - > NumStudents ) ;
2014-12-01 23:55:08 +01:00
/***** Vacants in this group *****/
2015-09-04 19:26:08 +02:00
fprintf ( Gbl . F . Out , " <td class= \" DAT CENTER_MIDDLE " ) ;
2014-12-01 23:55:08 +01:00
if ( Highlight )
2015-09-04 19:26:08 +02:00
fprintf ( Gbl . F . Out , " LIGHT_BLUE " ) ;
fprintf ( Gbl . F . Out , " \" > " ) ;
2014-12-01 23:55:08 +01:00
if ( Grp - > MaxStudents > Grp_MAX_STUDENTS_IN_A_GROUP )
fprintf ( Gbl . F . Out , " - " ) ;
else
{
Vacant = ( int ) Grp - > MaxStudents - ( int ) Grp - > NumStudents ;
fprintf ( Gbl . F . Out , " %u " ,
Vacant > 0 ? ( unsigned ) Vacant :
0 ) ;
}
fprintf ( Gbl . F . Out , " </td> " ) ;
}
/*****************************************************************************/
/********************* Put a form to create a new group type *****************/
/*****************************************************************************/
static void Grp_PutFormToCreateGroupType ( void )
{
extern const char * Txt_New_type_of_group ;
extern const char * Txt_It_is_optional_to_choose_a_group ;
extern const char * Txt_It_is_mandatory_to_choose_a_group ;
extern const char * Txt_A_student_can_belong_to_several_groups ;
extern const char * Txt_A_student_can_only_belong_to_one_group ;
extern const char * Txt_The_groups_will_automatically_open ;
extern const char * Txt_The_groups_will_not_automatically_open ;
extern const char * Txt_Create_type_of_group ;
/***** Start form *****/
2017-04-29 19:19:55 +02:00
fprintf ( Gbl . F . Out , " <section id= \" %s \" > " , Grp_SECTION_NEW_GROUP_TYPE ) ;
2017-04-29 15:29:58 +02:00
Act_FormStartAnchor ( ActNewGrpTyp , Grp_SECTION_GROUP_TYPES ) ;
2014-12-01 23:55:08 +01:00
/***** Start of frame *****/
2016-11-14 10:05:41 +01:00
Lay_StartRoundFrameTable ( NULL , Txt_New_type_of_group ,
2017-04-29 20:16:53 +02:00
NULL , NULL , 2 ) ;
2014-12-01 23:55:08 +01:00
/***** Write heading *****/
Grp_WriteHeadingGroupTypes ( ) ;
2017-04-29 20:16:53 +02:00
/***** Column to remove group type, disabled here *****/
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " <tr> "
2017-04-29 20:16:53 +02:00
" <td class= \" BM \" ></td> " ) ;
2014-12-01 23:55:08 +01:00
/***** Name of group type *****/
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" LEFT_MIDDLE \" > "
2015-10-23 01:31:08 +02:00
" <input type= \" text \" name= \" GrpTypName \" "
2016-11-19 14:03:07 +01:00
" size= \" 12 \" maxlength= \" %u \" value= \" %s \" "
" required= \" required \" /> "
2014-12-01 23:55:08 +01:00
" </td> " ,
2017-03-07 11:03:05 +01:00
Grp_MAX_CHARS_GROUP_TYPE_NAME , Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName ) ;
2014-12-01 23:55:08 +01:00
/***** Is it mandatory to register in any groups of this type? *****/
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" CENTER_MIDDLE \" > "
2017-03-30 11:20:06 +02:00
" <select name= \" MandatoryEnrolment \" "
2015-09-28 18:28:29 +02:00
" style= \" width:150px; \" > "
2014-12-01 23:55:08 +01:00
" <option value= \" N \" " ) ;
2017-03-30 11:20:06 +02:00
if ( ! Gbl . CurrentCrs . Grps . GrpTyp . MandatoryEnrolment )
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " selected= \" selected \" " ) ;
fprintf ( Gbl . F . Out , " >%s</option> "
" <option value= \" Y \" " ,
Txt_It_is_optional_to_choose_a_group ) ;
2017-03-30 11:20:06 +02:00
if ( Gbl . CurrentCrs . Grps . GrpTyp . MandatoryEnrolment )
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " selected= \" selected \" " ) ;
fprintf ( Gbl . F . Out , " >%s</option> "
" </select> "
" </td> " ,
Txt_It_is_mandatory_to_choose_a_group ) ;
/***** Is it possible to register in multiple groups of this type? *****/
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" CENTER_MIDDLE \" > "
2017-03-30 11:20:06 +02:00
" <select name= \" MultipleEnrolment \" "
2015-09-28 18:28:29 +02:00
" style= \" width:150px; \" > "
2014-12-01 23:55:08 +01:00
" <option value= \" N \" " ) ;
2017-03-30 11:20:06 +02:00
if ( ! Gbl . CurrentCrs . Grps . GrpTyp . MultipleEnrolment )
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " selected= \" selected \" " ) ;
fprintf ( Gbl . F . Out , " >%s</option> "
" <option value= \" Y \" " ,
Txt_A_student_can_only_belong_to_one_group ) ;
2017-03-30 11:20:06 +02:00
if ( Gbl . CurrentCrs . Grps . GrpTyp . MultipleEnrolment )
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " selected= \" selected \" " ) ;
fprintf ( Gbl . F . Out , " >%s</option> "
" </select> "
" </td> " ,
Txt_A_student_can_belong_to_several_groups ) ;
/***** Open time *****/
2017-05-01 21:17:38 +02:00
fprintf ( Gbl . F . Out , " <td class= \" LEFT_MIDDLE \" > " ) ;
Lay_StartTable ( 2 ) ;
fprintf ( Gbl . F . Out , " <tr> "
2015-10-26 20:02:07 +01:00
" <td class= \" LEFT_MIDDLE \" style= \" width:20px; \" > "
2015-07-22 11:18:11 +02:00
" <img src= \" %s/%s16x16.gif \" "
" alt= \" %s \" title= \" %s \" "
2016-11-14 10:05:41 +01:00
" class= \" ICO20x20 \" /> "
2014-12-01 23:55:08 +01:00
" </td> "
2015-10-26 20:02:07 +01:00
" <td class= \" LEFT_MIDDLE \" > " ,
2014-12-01 23:55:08 +01:00
Gbl . Prefs . IconsURL ,
Gbl . CurrentCrs . Grps . GrpTyp . MustBeOpened ? " time " :
" time-off " ,
2015-07-22 11:18:11 +02:00
Gbl . CurrentCrs . Grps . GrpTyp . MustBeOpened ? Txt_The_groups_will_automatically_open :
Txt_The_groups_will_not_automatically_open ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . MustBeOpened ? Txt_The_groups_will_automatically_open :
Txt_The_groups_will_not_automatically_open ) ;
2015-10-26 20:02:07 +01:00
Dat_WriteFormClientLocalDateTimeFromTimeUTC ( " open_time " ,
" Open " ,
Gbl . CurrentCrs . Grps . GrpTyp . OpenTimeUTC ,
Gbl . Now . Date . Year ,
Gbl . Now . Date . Year + 1 ,
2016-12-03 20:08:01 +01:00
Dat_FORM_SECONDS_ON ,
2017-02-26 20:09:21 +01:00
Dat_HMS_DO_NOT_SET , // Don't set hour, minute and second
false ) ; // Don't submit on change
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " </td> "
2017-05-01 21:17:38 +02:00
" </tr> " ) ;
Lay_EndTable ( ) ;
fprintf ( Gbl . F . Out , " </td> " ) ;
2014-12-01 23:55:08 +01:00
/***** Number of groups of this type *****/
2017-04-29 20:16:53 +02:00
fprintf ( Gbl . F . Out , " <td class= \" DAT CENTER_MIDDLE \" > "
" 0 " // It's a new group type ==> 0 groups
" </td> "
" </tr> " ) ;
2014-12-01 23:55:08 +01:00
2015-04-11 23:46:21 +02:00
/***** Send button and end frame *****/
2015-04-12 18:01:06 +02:00
Lay_EndRoundFrameTableWithButton ( Lay_CREATE_BUTTON , Txt_Create_type_of_group ) ;
2014-12-01 23:55:08 +01:00
2015-04-11 23:46:21 +02:00
/***** End form *****/
2015-03-13 00:16:02 +01:00
Act_FormEnd ( ) ;
2017-04-29 19:19:55 +02:00
fprintf ( Gbl . F . Out , " </section> " ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********************** Put a form to create a new group ********************/
/*****************************************************************************/
static void Grp_PutFormToCreateGroup ( void )
{
extern const char * Txt_New_group ;
2015-07-22 11:18:11 +02:00
extern const char * Txt_Group_closed ;
extern const char * Txt_File_zones_disabled ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_Create_group ;
unsigned NumGrpTyp ;
/***** Start form *****/
2017-04-29 19:32:06 +02:00
fprintf ( Gbl . F . Out , " <section id= \" %s \" > " , Grp_SECTION_NEW_GROUP ) ;
2017-04-29 15:29:58 +02:00
Act_FormStartAnchor ( ActNewGrp , Grp_SECTION_GROUPS ) ;
2014-12-01 23:55:08 +01:00
/***** Start of frame *****/
2017-04-29 20:27:58 +02:00
Lay_StartRoundFrameTable ( NULL , Txt_New_group , NULL , NULL , 2 ) ;
2014-12-01 23:55:08 +01:00
/***** Write heading *****/
Grp_WriteHeadingGroups ( ) ;
2017-04-29 20:16:53 +02:00
/***** Put disabled icons to open group and archive zone *****/
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " <tr> "
2017-04-29 20:16:53 +02:00
" <td class= \" BM \" ></td> "
2014-12-01 23:55:08 +01:00
" <td class= \" BM \" > "
2016-12-05 01:54:03 +01:00
" <img src= \" %s/lock-off64x64.png \" "
2015-07-22 11:18:11 +02:00
" alt= \" %s \" title= \" %s \" "
2016-11-14 10:05:41 +01:00
" class= \" ICO20x20 \" /> "
2014-12-01 23:55:08 +01:00
" </td> "
" <td class= \" BM \" > "
" <img src= \" %s/folder-no_off16x16.gif \" "
2015-07-22 11:18:11 +02:00
" alt= \" %s \" title= \" %s \" "
2016-11-14 10:05:41 +01:00
" class= \" ICO20x20 \" /> "
2014-12-01 23:55:08 +01:00
" </td> " ,
Gbl . Prefs . IconsURL ,
2015-07-22 19:20:30 +02:00
Txt_Group_closed ,
Txt_Group_closed ,
2014-12-01 23:55:08 +01:00
Gbl . Prefs . IconsURL ,
2015-07-22 19:20:30 +02:00
Txt_File_zones_disabled ,
Txt_File_zones_disabled ) ;
2014-12-01 23:55:08 +01:00
/***** Group type *****/
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" CENTER_MIDDLE \" > "
2017-03-11 00:47:23 +01:00
" <select name= \" GrpTypCod \" style= \" width:150px; \" > " ) ;
2014-12-01 23:55:08 +01:00
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
{
fprintf ( Gbl . F . Out , " <option value= \" %ld \" " ,
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
if ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod = = Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod )
fprintf ( Gbl . F . Out , " selected= \" selected \" " ) ;
fprintf ( Gbl . F . Out , " >%s</option> " ,
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypName ) ;
}
fprintf ( Gbl . F . Out , " </select> "
" </td> " ) ;
/***** Group name *****/
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" CENTER_MIDDLE \" > "
2015-10-23 01:31:08 +02:00
" <input type= \" text \" name= \" GrpName \" "
2016-11-19 14:03:07 +01:00
" size= \" 40 \" maxlength= \" %u \" value= \" %s \" "
" required= \" required \" /> "
" </td> " ,
2017-03-07 11:03:05 +01:00
Grp_MAX_CHARS_GROUP_NAME , Gbl . CurrentCrs . Grps . GrpName ) ;
2014-12-01 23:55:08 +01:00
/***** Maximum number of students *****/
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" CENTER_MIDDLE \" > "
2015-10-23 01:31:08 +02:00
" <input type= \" text \" name= \" MaxStudents \" "
" size= \" 3 \" maxlength= \" 10 \" value= \" " ) ;
2014-12-01 23:55:08 +01:00
Grp_WriteMaxStdsGrp ( Gbl . CurrentCrs . Grps . MaxStudents ) ;
2016-12-23 22:19:03 +01:00
fprintf ( Gbl . F . Out , " \" /> "
" </td> " ) ;
2014-12-01 23:55:08 +01:00
/***** Current number of students in this group *****/
2017-04-29 20:16:53 +02:00
fprintf ( Gbl . F . Out , " <td class= \" DAT CENTER_MIDDLE \" > "
" 0 " // It's a new group ==> 0 students
" </td> "
2014-12-01 23:55:08 +01:00
" </tr> " ) ;
2015-04-11 23:46:21 +02:00
/***** Send button and end frame *****/
2015-04-12 18:01:06 +02:00
Lay_EndRoundFrameTableWithButton ( Lay_CREATE_BUTTON , Txt_Create_group ) ;
2014-12-01 23:55:08 +01:00
/***** End of form *****/
2015-03-13 00:16:02 +01:00
Act_FormEnd ( ) ;
2017-04-29 19:32:06 +02:00
fprintf ( Gbl . F . Out , " </section> " ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********** Create a list with current group types in this course ***********/
/*****************************************************************************/
void Grp_GetListGrpTypesInThisCrs ( Grp_WhichGroupTypes_t WhichGroupTypes )
{
char Query [ 1024 ] ;
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
unsigned long NumRow ;
if ( + + Gbl . CurrentCrs . Grps . GrpTypes . NestedCalls > 1 ) // If list is created yet, there's nothing to do
return ;
/***** Open groups of this course that must be opened
if open time is in the past * * * * */
Grp_OpenGroupsAutomatically ( ) ;
/***** Get group types with groups + groups types without groups from database *****/
// The tables in the second part of the UNION requires ALIAS in order to LOCK TABLES when registering in groups
switch ( WhichGroupTypes )
{
case Grp_ONLY_GROUP_TYPES_WITH_GROUPS :
sprintf ( Query , " SELECT crs_grp_types.GrpTypCod,crs_grp_types.GrpTypName, "
" crs_grp_types.Mandatory,crs_grp_types.Multiple, "
" crs_grp_types.MustBeOpened, "
2015-10-26 20:02:07 +01:00
" UNIX_TIMESTAMP(crs_grp_types.OpenTime), "
2014-12-01 23:55:08 +01:00
" COUNT(crs_grp.GrpCod) "
" FROM crs_grp_types,crs_grp "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp_types.CrsCod=%ld "
2014-12-01 23:55:08 +01:00
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
" GROUP BY crs_grp_types.GrpTypCod "
" ORDER BY crs_grp_types.GrpTypName " ,
Gbl . CurrentCrs . Crs . CrsCod ) ;
break ;
case Grp_ALL_GROUP_TYPES :
sprintf ( Query , " (SELECT crs_grp_types.GrpTypCod,crs_grp_types.GrpTypName AS GrpTypName, "
" crs_grp_types.Mandatory,crs_grp_types.Multiple, "
" crs_grp_types.MustBeOpened, "
2015-10-26 20:02:07 +01:00
" UNIX_TIMESTAMP(crs_grp_types.OpenTime), "
2014-12-01 23:55:08 +01:00
" COUNT(crs_grp.GrpCod) "
" FROM crs_grp_types,crs_grp "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp_types.CrsCod=%ld "
2014-12-01 23:55:08 +01:00
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
" GROUP BY crs_grp_types.GrpTypCod) "
" UNION "
" (SELECT GrpTypCod,GrpTypName, "
" Mandatory,Multiple, "
2015-10-26 20:02:07 +01:00
" MustBeOpened, "
" UNIX_TIMESTAMP(OpenTime), "
2017-03-24 01:09:27 +01:00
" 0 "
" FROM crs_grp_types WHERE CrsCod=%ld "
2014-12-01 23:55:08 +01:00
" AND GrpTypCod NOT IN (SELECT GrpTypCod FROM crs_grp)) "
" ORDER BY GrpTypName " ,
Gbl . CurrentCrs . Crs . CrsCod ,
Gbl . CurrentCrs . Crs . CrsCod ) ;
break ;
}
Gbl . CurrentCrs . Grps . GrpTypes . Num = ( unsigned ) DB_QuerySELECT ( Query , & mysql_res , " can not get types of group of a course " ) ;
/***** Get group types *****/
Gbl . CurrentCrs . Grps . GrpTypes . NumGrpsTotal = 0 ;
if ( Gbl . CurrentCrs . Grps . GrpTypes . Num )
{
/***** Create a list of group types *****/
if ( ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes = ( struct GroupType * ) calloc ( Gbl . CurrentCrs . Grps . GrpTypes . Num , sizeof ( struct GroupType ) ) ) = = NULL )
Lay_ShowErrorAndExit ( " Not enough memory to store types of group. " ) ;
/***** Get group types *****/
for ( NumRow = 0 ;
NumRow < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumRow + + )
{
/* Get next group type */
row = mysql_fetch_row ( mysql_res ) ;
/* Get group type code (row[0]) */
if ( ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumRow ] . GrpTypCod = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) < 0 )
Lay_ShowErrorAndExit ( " Wrong type of group. " ) ;
/* Get group type name (row[1]) */
2017-01-15 18:02:52 +01:00
Str_Copy ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumRow ] . GrpTypName , row [ 1 ] ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_TYPE_NAME ) ;
2014-12-01 23:55:08 +01:00
/* Is it mandatory to register in any groups of this type? (row[2]) */
2017-03-30 11:20:06 +02:00
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumRow ] . MandatoryEnrolment = ( row [ 2 ] [ 0 ] = = ' Y ' ) ;
2014-12-01 23:55:08 +01:00
/* Is it possible to register in multiple groups of this type? (row[3]) */
2017-03-30 11:20:06 +02:00
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumRow ] . MultipleEnrolment = ( row [ 3 ] [ 0 ] = = ' Y ' ) ;
2014-12-01 23:55:08 +01:00
/* Groups of this type must be opened? (row[4]) */
2016-09-07 18:48:10 +02:00
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumRow ] . MustBeOpened = ( row [ 4 ] [ 0 ] = = ' Y ' ) ;
2014-12-01 23:55:08 +01:00
2015-10-26 20:02:07 +01:00
/* Get open time (row[5] holds the open time UTC) */
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumRow ] . OpenTimeUTC = Dat_GetUNIXTimeFromStr ( row [ 5 ] ) ;
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumRow ] . MustBeOpened & = Grp_CheckIfOpenTimeInTheFuture ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumRow ] . OpenTimeUTC ) ;
2014-12-01 23:55:08 +01:00
/* Number of groups of this type (row[6]) */
if ( sscanf ( row [ 6 ] , " %u " , & Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumRow ] . NumGrps ) ! = 1 )
Lay_ShowErrorAndExit ( " Wrong number of groups of a type. " ) ;
/* Add number of groups to total number of groups */
Gbl . CurrentCrs . Grps . GrpTypes . NumGrpsTotal + = Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumRow ] . NumGrps ;
/* Initialize pointer to the list of groups of this type */
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumRow ] . LstGrps = NULL ;
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
}
/*****************************************************************************/
/***************** Open automatically groups in this course ******************/
/*****************************************************************************/
void Grp_OpenGroupsAutomatically ( void )
{
char Query [ 512 ] ;
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
unsigned NumGrpTypes ;
unsigned NumGrpTyp ;
long GrpTypCod ;
/***** Find group types to be opened *****/
sprintf ( Query , " SELECT GrpTypCod FROM crs_grp_types "
2017-03-24 01:09:27 +01:00
" WHERE CrsCod=%ld AND MustBeOpened='Y' "
2015-11-11 03:00:22 +01:00
" AND OpenTime<=NOW() " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Crs . CrsCod ) ;
NumGrpTypes = ( unsigned ) DB_QuerySELECT ( Query , & mysql_res ,
" can not get the types of group to be opened " ) ;
for ( NumGrpTyp = 0 ;
NumGrpTyp < NumGrpTypes ;
NumGrpTyp + + )
{
/* Get next group TYPE */
row = mysql_fetch_row ( mysql_res ) ;
if ( ( GrpTypCod = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) > 0 )
{
/***** Open all the closed groups in this course the must be opened
and with open time in the past * * * */
sprintf ( Query , " UPDATE crs_grp SET Open='Y' "
2017-03-24 01:09:27 +01:00
" WHERE GrpTypCod=%ld AND Open='N' " ,
2014-12-01 23:55:08 +01:00
GrpTypCod ) ;
DB_QueryUPDATE ( Query , " can not open groups " ) ;
/***** To not try to open groups again, set MustBeOpened to false *****/
sprintf ( Query , " UPDATE crs_grp_types SET MustBeOpened='N' "
2017-03-24 01:09:27 +01:00
" WHERE GrpTypCod=%ld " ,
2014-12-01 23:55:08 +01:00
GrpTypCod ) ;
DB_QueryUPDATE ( Query , " can not update the opening of a type of group " ) ;
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
}
/*****************************************************************************/
/********* Create a list with group types and groups in this course **********/
/*****************************************************************************/
void Grp_GetListGrpTypesAndGrpsInThisCrs ( Grp_WhichGroupTypes_t WhichGroupTypes )
{
unsigned NumGrpTyp ;
unsigned NumGrp ;
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
unsigned long NumRows ;
struct GroupType * GrpTyp ;
struct Group * Grp ;
/***** First we get the list of group types *****/
Grp_GetListGrpTypesInThisCrs ( WhichGroupTypes ) ;
/***** Then we get the list of groups for each group type *****/
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
{
GrpTyp = & Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ;
if ( GrpTyp - > NumGrps ) // If there are groups of this type...
{
/***** Query database *****/
if ( ( NumRows = Grp_GetGrpsOfType ( GrpTyp - > GrpTypCod , & mysql_res ) ) > 0 ) // Groups found...
{
// NumRows should be equal to GrpTyp->NumGrps
GrpTyp - > NumGrps = ( unsigned ) NumRows ;
/***** Create list with groups of this type *****/
if ( ( GrpTyp - > LstGrps = ( struct Group * ) calloc ( GrpTyp - > NumGrps , sizeof ( struct Group ) ) ) = = NULL )
Lay_ShowErrorAndExit ( " Not enough memory to store groups of a type. " ) ;
/***** Get the groups of this type *****/
for ( NumGrp = 0 ;
NumGrp < GrpTyp - > NumGrps ;
NumGrp + + )
{
Grp = & ( GrpTyp - > LstGrps [ NumGrp ] ) ;
/* Get next group */
row = mysql_fetch_row ( mysql_res ) ;
/* Get group code (row[0]) */
if ( ( Grp - > GrpCod = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) < 0 )
Lay_ShowErrorAndExit ( " Wrong code of group. " ) ;
/* Get group name (row[1]) */
2017-01-17 03:10:43 +01:00
Str_Copy ( Grp - > GrpName , row [ 1 ] ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_NAME ) ;
2014-12-01 23:55:08 +01:00
/* Get max number of students of group (row[2]) and number of current students */
Grp - > MaxStudents = Grp_ConvertToNumMaxStdsGrp ( row [ 2 ] ) ;
Grp - > NumStudents = Grp_CountNumStdsInGrp ( Grp - > GrpCod ) ;
/* Get whether group is open ('Y') or closed ('N') (row[3]) */
2016-09-07 18:48:10 +02:00
Grp - > Open = ( row [ 3 ] [ 0 ] = = ' Y ' ) ;
2014-12-01 23:55:08 +01:00
/* Get whether group have file zones ('Y') or not ('N') (row[4]) */
2016-09-07 18:48:10 +02:00
Grp - > FileZones = ( row [ 4 ] [ 0 ] = = ' Y ' ) ;
2014-12-01 23:55:08 +01:00
}
}
else // Error: groups should be found, but really they haven't be found. This never should happen.
GrpTyp - > NumGrps = 0 ;
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
}
}
}
/*****************************************************************************/
/********* Free list of groups types and list of groups of each type *********/
/*****************************************************************************/
void Grp_FreeListGrpTypesAndGrps ( void )
{
unsigned NumGrpTyp ;
struct GroupType * GrpTyp ;
if ( Gbl . CurrentCrs . Grps . GrpTypes . NestedCalls > 0 )
if ( - - Gbl . CurrentCrs . Grps . GrpTypes . NestedCalls = = 0 )
if ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes )
{
/***** Free memory used for each list of groups (one list for each group type) *****/
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
{
GrpTyp = & Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ;
if ( GrpTyp - > LstGrps )
{
free ( ( void * ) GrpTyp - > LstGrps ) ;
GrpTyp - > LstGrps = NULL ;
GrpTyp - > NumGrps = 0 ;
}
}
/***** Free memory used by the list of group types *****/
free ( ( void * ) Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes ) ;
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes = NULL ;
Gbl . CurrentCrs . Grps . GrpTypes . Num = 0 ;
}
}
/*****************************************************************************/
/*********** Query the number of groups that hay in this course **************/
/*****************************************************************************/
unsigned Grp_CountNumGrpsInCurrentCrs ( void )
{
char Query [ 512 ] ;
/***** Get number of group in current course from database *****/
sprintf ( Query , " SELECT COUNT(*) FROM crs_grp_types,crs_grp "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp_types.CrsCod=%ld "
2014-12-01 23:55:08 +01:00
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod " ,
Gbl . CurrentCrs . Crs . CrsCod ) ;
return ( unsigned ) DB_QueryCOUNT ( Query , " can not get number of groups in this course " ) ;
}
/*****************************************************************************/
/****************** Count number of groups in a group type *******************/
/*****************************************************************************/
static unsigned Grp_CountNumGrpsInThisCrsOfType ( long GrpTypCod )
{
2017-03-11 00:47:23 +01:00
char Query [ 128 ] ;
2014-12-01 23:55:08 +01:00
/***** Get number of groups of a type from database *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " SELECT COUNT(*) FROM crs_grp WHERE GrpTypCod=%ld " ,
2014-12-01 23:55:08 +01:00
GrpTypCod ) ;
return ( unsigned ) DB_QueryCOUNT ( Query , " can not get number of groups of a type " ) ;
}
/*****************************************************************************/
/***************** Get current groups of a type in this course ***************/
/*****************************************************************************/
unsigned long Grp_GetGrpsOfType ( long GrpTypCod , MYSQL_RES * * mysql_res )
{
char Query [ 512 ] ;
/***** Get groups of a type from database *****/
sprintf ( Query , " SELECT GrpCod,GrpName,MaxStudents,Open,FileZones "
2015-01-27 20:50:44 +01:00
" FROM crs_grp "
2017-03-24 01:09:27 +01:00
" WHERE GrpTypCod=%ld "
2015-01-27 20:50:44 +01:00
" ORDER BY GrpName " ,
GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
return DB_QuerySELECT ( Query , mysql_res , " can not get groups of a type " ) ;
}
/*****************************************************************************/
/******************* Get data of a group type from its code ******************/
/*****************************************************************************/
// GrpTyp->GrpTypCod must have the code of the type of group
static void Grp_GetDataOfGroupTypeByCod ( struct GroupType * GrpTyp )
{
char Query [ 512 ] ;
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
unsigned long NumRows ;
/***** Get data of a type of group from database *****/
2015-10-26 20:02:07 +01:00
sprintf ( Query , " SELECT GrpTypName,Mandatory,Multiple,MustBeOpened,UNIX_TIMESTAMP(OpenTime) "
2014-12-01 23:55:08 +01:00
" FROM crs_grp_types "
2017-03-24 01:09:27 +01:00
" WHERE CrsCod=%ld AND GrpTypCod=%ld " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Crs . CrsCod , GrpTyp - > GrpTypCod ) ;
NumRows = DB_QuerySELECT ( Query , & mysql_res , " can not get type of group " ) ;
/***** Count number of rows in result *****/
if ( NumRows ! = 1 )
Lay_ShowErrorAndExit ( " Error when getting type of group. " ) ;
/***** Get some data of group type *****/
row = mysql_fetch_row ( mysql_res ) ;
2017-01-17 03:10:43 +01:00
Str_Copy ( GrpTyp - > GrpTypName , row [ 0 ] ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_TYPE_NAME ) ;
2017-03-30 11:20:06 +02:00
GrpTyp - > MandatoryEnrolment = ( row [ 1 ] [ 0 ] = = ' Y ' ) ;
GrpTyp - > MultipleEnrolment = ( row [ 2 ] [ 0 ] = = ' Y ' ) ;
GrpTyp - > MustBeOpened = ( row [ 3 ] [ 0 ] = = ' Y ' ) ;
2015-10-26 20:02:07 +01:00
GrpTyp - > OpenTimeUTC = Dat_GetUNIXTimeFromStr ( row [ 4 ] ) ;
2014-12-01 23:55:08 +01:00
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
}
/*****************************************************************************/
2017-03-30 11:20:06 +02:00
/************* Check if a group type has multiple enrolment *****************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2017-03-30 11:20:06 +02:00
static bool Grp_GetMultipleEnrolmentOfAGroupType ( long GrpTypCod )
2014-12-01 23:55:08 +01:00
{
2017-03-11 00:47:23 +01:00
char Query [ 128 ] ;
2014-12-01 23:55:08 +01:00
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
2017-03-30 11:20:06 +02:00
bool MultipleEnrolment ;
2014-12-01 23:55:08 +01:00
/***** Get data of a type of group from database *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " SELECT Multiple FROM crs_grp_types WHERE GrpTypCod=%ld " ,
2014-12-01 23:55:08 +01:00
GrpTypCod ) ;
2017-03-30 11:20:06 +02:00
if ( DB_QuerySELECT ( Query , & mysql_res , " can not get if type of group has multiple enrolment " ) ! = 1 )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Error when getting type of group. " ) ;
2017-03-30 11:20:06 +02:00
/***** Get multiple enrolment *****/
2014-12-01 23:55:08 +01:00
row = mysql_fetch_row ( mysql_res ) ;
2017-03-30 11:20:06 +02:00
MultipleEnrolment = ( row [ 0 ] [ 0 ] = = ' Y ' ) ;
2014-12-01 23:55:08 +01:00
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
2017-03-30 11:20:06 +02:00
return MultipleEnrolment ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/********************** Get data of a group from its code ********************/
/*****************************************************************************/
void Grp_GetDataOfGroupByCod ( struct GroupData * GrpDat )
{
char Query [ 512 ] ;
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
unsigned long NumRows ;
2016-12-28 02:40:15 +01:00
/***** Reset values *****/
GrpDat - > GrpTypCod = - 1L ;
GrpDat - > CrsCod = - 1L ;
GrpDat - > GrpTypName [ 0 ] = ' \0 ' ;
GrpDat - > GrpName [ 0 ] = ' \0 ' ;
GrpDat - > MaxStudents = 0 ;
GrpDat - > Vacant = 0 ;
2017-03-30 11:20:06 +02:00
GrpDat - > Open = false ;
GrpDat - > FileZones = false ;
GrpDat - > MultipleEnrolment = false ;
2016-12-28 02:40:15 +01:00
if ( GrpDat - > GrpCod > 0 )
{
/***** Get data of a group from database *****/
sprintf ( Query , " SELECT crs_grp_types.GrpTypCod,crs_grp_types.CrsCod, "
" crs_grp_types.GrpTypName,crs_grp_types.Multiple, "
" crs_grp.GrpName,crs_grp.MaxStudents, "
" crs_grp.Open,crs_grp.FileZones "
" FROM crs_grp,crs_grp_types "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp.GrpCod=%ld "
2016-12-28 02:40:15 +01:00
" AND crs_grp.GrpTypCod=crs_grp_types.GrpTypCod " ,
GrpDat - > GrpCod ) ;
NumRows = DB_QuerySELECT ( Query , & mysql_res , " can not get data of a group " ) ;
if ( NumRows = = 1 )
{
/***** Get data of group *****/
row = mysql_fetch_row ( mysql_res ) ;
2015-01-24 19:30:44 +01:00
2016-12-28 02:40:15 +01:00
/* Get the code of the group type (row[0]) */
if ( ( GrpDat - > GrpTypCod = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) < = 0 )
Lay_ShowErrorAndExit ( " Wrong code of type of group. " ) ;
2015-01-24 19:30:44 +01:00
2016-12-28 02:40:15 +01:00
/* Get the code of the course (row[1]) */
if ( ( GrpDat - > CrsCod = Str_ConvertStrCodToLongCod ( row [ 1 ] ) ) < = 0 )
Lay_ShowErrorAndExit ( " Wrong code of course. " ) ;
2015-01-24 19:30:44 +01:00
2016-12-28 02:40:15 +01:00
/* Get the name of the group type (row[2]) */
2017-01-17 03:10:43 +01:00
Str_Copy ( GrpDat - > GrpTypName , row [ 2 ] ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_TYPE_NAME ) ;
2015-01-24 19:30:44 +01:00
2016-12-28 02:40:15 +01:00
/* Get whether a student may be in one or multiple groups (row[3]) */
2017-03-30 11:20:06 +02:00
GrpDat - > MultipleEnrolment = ( row [ 3 ] [ 0 ] = = ' Y ' ) ;
2015-01-24 19:30:44 +01:00
2016-12-28 02:40:15 +01:00
/* Get the name of the group (row[4]) */
2017-01-17 03:10:43 +01:00
Str_Copy ( GrpDat - > GrpName , row [ 4 ] ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_NAME ) ;
2015-01-24 19:30:44 +01:00
2016-12-28 02:40:15 +01:00
/* Get maximum number of students (row[5]) */
GrpDat - > MaxStudents = Grp_ConvertToNumMaxStdsGrp ( row [ 5 ] ) ;
2015-01-24 19:30:44 +01:00
2016-12-28 02:40:15 +01:00
/* Get whether group is open or closed (row[6]) */
GrpDat - > Open = ( row [ 6 ] [ 0 ] = = ' Y ' ) ;
2015-01-24 19:30:44 +01:00
2016-12-28 02:40:15 +01:00
/* Get whether group has file zones (row[7]) */
GrpDat - > FileZones = ( row [ 7 ] [ 0 ] = = ' Y ' ) ;
}
2014-12-01 23:55:08 +01:00
2016-12-28 02:40:15 +01:00
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
}
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/********************** Get the type of group of a group *********************/
/*****************************************************************************/
static long Grp_GetTypeOfGroupOfAGroup ( long GrpCod )
{
2017-03-11 00:47:23 +01:00
char Query [ 128 ] ;
2014-12-01 23:55:08 +01:00
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
long GrpTypCod ;
/***** Get data of a group from database *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " SELECT GrpTypCod FROM crs_grp WHERE GrpCod=%ld " ,
2014-12-01 23:55:08 +01:00
GrpCod ) ;
if ( DB_QuerySELECT ( Query , & mysql_res , " can not get the type of a group " ) ! = 1 )
Lay_ShowErrorAndExit ( " Error when getting group. " ) ;
/***** Get data of group *****/
row = mysql_fetch_row ( mysql_res ) ;
/* Get the code of the group type (row[0]) */
if ( ( GrpTypCod = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) < 0 )
Lay_ShowErrorAndExit ( " Wrong code of type of group. " ) ;
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
return GrpTypCod ;
}
/*****************************************************************************/
/******************** Check if a group exists in database ********************/
/*****************************************************************************/
bool Grp_CheckIfGroupExists ( long GrpCod )
{
char Query [ 128 ] ;
/***** Get if a group exists from database *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " SELECT COUNT(*) FROM crs_grp WHERE GrpCod=%ld " , GrpCod ) ;
2014-12-01 23:55:08 +01:00
return ( DB_QueryCOUNT ( Query , " can not check if a group exists " ) ! = 0 ) ;
}
/*****************************************************************************/
/******************* Check if a group belongs to a course ********************/
/*****************************************************************************/
bool Grp_CheckIfGroupBelongsToCourse ( long GrpCod , long CrsCod )
{
2016-04-12 22:28:15 +02:00
char Query [ 256 ] ;
2014-12-01 23:55:08 +01:00
/***** Get if a group exists from database *****/
sprintf ( Query , " SELECT COUNT(*) FROM crs_grp,crs_grp_types "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp.GrpCod=%ld "
2014-12-01 23:55:08 +01:00
" AND crs_grp.GrpTypCod=crs_grp_types.GrpTypCod "
2017-03-24 01:09:27 +01:00
" AND crs_grp_types.CrsCod=%ld " ,
2014-12-01 23:55:08 +01:00
GrpCod , CrsCod ) ;
return ( DB_QueryCOUNT ( Query , " can not check if a group belongs to a course " ) ! = 0 ) ;
}
/*****************************************************************************/
/******************** Count number of students in a group ********************/
/*****************************************************************************/
unsigned Grp_CountNumStdsInGrp ( long GrpCod )
{
char Query [ 512 ] ;
/***** Get number of students in a group from database *****/
sprintf ( Query , " SELECT COUNT(*) "
" FROM crs_grp_usr,crs_grp,crs_grp_types,crs_usr "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp_usr.GrpCod=%ld "
2014-12-01 23:55:08 +01:00
" AND crs_grp_usr.GrpCod=crs_grp.GrpCod "
" AND crs_grp.GrpTypCod=crs_grp_types.GrpTypCod "
" AND crs_grp_types.CrsCod=crs_usr.CrsCod "
" AND crs_grp_usr.UsrCod=crs_usr.UsrCod "
2017-03-24 01:09:27 +01:00
" AND crs_usr.Role=%u " ,
2015-04-07 21:44:24 +02:00
GrpCod , ( unsigned ) Rol_STUDENT ) ;
2014-12-01 23:55:08 +01:00
return ( unsigned ) DB_QueryCOUNT ( Query ,
" can not get number of students in a group " ) ;
}
/*****************************************************************************/
/** Count # of students of current course not belonging to groups of a type **/
/*****************************************************************************/
static unsigned Grp_CountNumStdsInNoGrpsOfType ( long GrpTypCod )
{
char Query [ 512 ] ;
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
unsigned NumStds ;
/***** Get number of students not belonging to groups of a type from database ******/
sprintf ( Query , " SELECT COUNT(UsrCod) FROM crs_usr "
2017-03-24 01:09:27 +01:00
" WHERE CrsCod=%ld AND Role=%u "
2017-03-11 00:47:23 +01:00
" AND UsrCod NOT IN "
" (SELECT DISTINCT crs_grp_usr.UsrCod "
" FROM crs_grp,crs_grp_usr "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp.GrpTypCod=%ld "
2017-03-11 00:47:23 +01:00
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod) " ,
2015-04-07 21:44:24 +02:00
Gbl . CurrentCrs . Crs . CrsCod , ( unsigned ) Rol_STUDENT , GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
DB_QuerySELECT ( Query , & mysql_res , " can not get the number of students not belonging to groups of a type " ) ;
/***** Get the number of students (row[0]) *****/
row = mysql_fetch_row ( mysql_res ) ;
if ( sscanf ( row [ 0 ] , " %u " , & NumStds ) ! = 1 )
Lay_ShowErrorAndExit ( " Error when getting the number of students not belonging to groups of a type. " ) ;
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
return NumStds ;
}
/*****************************************************************************/
/**** Get the first code of group of cierto type al that pert. a student *****/
/*****************************************************************************/
// Return -GrpTypCod if the student does not belongs to any group of type GrpTypCod
static long Grp_GetFirstCodGrpStdBelongsTo ( long GrpTypCod , long UsrCod )
{
2017-03-11 00:47:23 +01:00
char Query [ 512 ] ;
2014-12-01 23:55:08 +01:00
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
unsigned long NumRows ;
long CodGrpIBelong ;
/***** Get a group which a user belong to from database *****/
2017-03-11 00:47:23 +01:00
sprintf ( Query , " SELECT crs_grp.GrpCod FROM crs_grp,crs_grp_usr "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp.GrpTypCod=%ld "
2017-03-11 00:47:23 +01:00
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod "
2017-03-24 01:09:27 +01:00
" AND crs_grp_usr.UsrCod=%ld " ,
2014-12-01 23:55:08 +01:00
GrpTypCod , UsrCod ) ;
NumRows = DB_QuerySELECT ( Query , & mysql_res , " can not get the group which a user belongs to " ) ;
/***** Get the group *****/
if ( NumRows = = 0 )
CodGrpIBelong = - GrpTypCod ;
else // If there are more than a group, only get the first one
{
row = mysql_fetch_row ( mysql_res ) ;
/* Get the code of group (row[0]) */
if ( ( CodGrpIBelong = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) < 0 )
Lay_ShowErrorAndExit ( " Wrong code of group. " ) ;
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
return CodGrpIBelong ;
}
/*****************************************************************************/
/********************* Check if a user belongs to a group ********************/
/*****************************************************************************/
// Return true if the user identificado belongs al group with c<> digo GrpCod
bool Grp_GetIfIBelongToGrp ( long GrpCod )
{
char Query [ 256 ] ;
/***** Get if I belong to a group from database *****/
sprintf ( Query , " SELECT COUNT(*) FROM crs_grp_usr "
2017-03-24 01:09:27 +01:00
" WHERE GrpCod=%ld AND UsrCod=%ld " ,
2014-12-01 23:55:08 +01:00
GrpCod , Gbl . Usrs . Me . UsrDat . UsrCod ) ;
return ( DB_QueryCOUNT ( Query , " can not check if you belong to a group " ) ! = 0 ) ;
}
/*****************************************************************************/
2017-03-30 11:20:06 +02:00
/**** Get the number of types of group with mandatory enrolment *****/
2014-12-01 23:55:08 +01:00
/**** that have any group open and with any vacant *****/
/**** and I don't belong to any of these groups as student *****/
/*****************************************************************************/
unsigned Grp_NumGrpTypesMandatIDontBelong ( void )
{
char Query [ 4096 ] ;
unsigned NumGrpTypes ;
2017-03-30 11:20:06 +02:00
/***** Get the number of types of groups with mandatory enrolment which I don't belong to, from database *****/
2014-12-01 23:55:08 +01:00
sprintf ( Query , " SELECT COUNT(DISTINCT GrpTypCod) FROM "
2017-03-11 00:47:23 +01:00
" (SELECT crs_grp_types.GrpTypCod AS GrpTypCod, "
" COUNT(*) AS NumStudents, "
" crs_grp.MaxStudents as MaxStudents "
2014-12-01 23:55:08 +01:00
" FROM crs_grp_types,crs_grp,crs_grp_usr,crs_usr "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp_types.CrsCod=%ld "
2017-03-11 00:47:23 +01:00
" AND crs_grp_types.Mandatory='Y' "
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
" AND crs_grp.Open='Y' "
2014-12-01 23:55:08 +01:00
" AND crs_grp_types.CrsCod=crs_usr.CrsCod "
2017-03-11 00:47:23 +01:00
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod "
" AND crs_grp_usr.UsrCod=crs_usr.UsrCod "
2017-03-24 01:09:27 +01:00
" AND crs_usr.Role=%u "
2017-03-11 00:47:23 +01:00
" GROUP BY crs_grp.GrpCod "
" HAVING NumStudents<MaxStudents) AS grp_types_open_not_full "
2014-12-01 23:55:08 +01:00
" WHERE GrpTypCod NOT IN "
2017-03-11 00:47:23 +01:00
" (SELECT DISTINCT crs_grp_types.GrpTypCod "
" FROM crs_grp_types,crs_grp,crs_grp_usr "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp_types.CrsCod=%ld "
2017-03-11 00:47:23 +01:00
" AND crs_grp_types.Mandatory='Y' "
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod "
2017-03-24 01:09:27 +01:00
" AND crs_grp_usr.UsrCod=%ld) " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Crs . CrsCod ,
2015-04-07 21:44:24 +02:00
( unsigned ) Rol_STUDENT ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Crs . CrsCod ,
Gbl . Usrs . Me . UsrDat . UsrCod ) ;
NumGrpTypes = DB_QueryCOUNT ( Query , " can not get the number of types of group of mandatory registration to which you don't belong to " ) ;
return NumGrpTypes ;
}
/*****************************************************************************/
/********** Query if any group of a type is open and has vacants *************/
/*****************************************************************************/
static bool Grp_GetIfGrpIsAvailable ( long GrpTypCod )
{
char Query [ 2048 ] ;
unsigned NumGrpTypes ;
/***** Get the number of types of group (0 or 1) of a type
with one or more open groups with vacants , from database * * * * */
sprintf ( Query , " SELECT COUNT(DISTINCT GrpTypCod) FROM "
2017-03-11 00:47:23 +01:00
" (SELECT crs_grp_types.GrpTypCod AS GrpTypCod, "
" COUNT(*) AS NumStudents, "
" crs_grp.MaxStudents as MaxStudents "
2014-12-01 23:55:08 +01:00
" FROM crs_grp_types,crs_grp,crs_grp_usr,crs_usr "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp_types.GrpTypCod=%ld "
2017-03-11 00:47:23 +01:00
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
" AND crs_grp.Open='Y' "
" AND crs_grp_types.CrsCod=crs_usr.CrsCod "
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod "
" AND crs_grp_usr.UsrCod=crs_usr.UsrCod "
2017-03-24 01:09:27 +01:00
" AND crs_usr.Role=%u "
2017-03-11 00:47:23 +01:00
" GROUP BY crs_grp.GrpCod "
" HAVING NumStudents<MaxStudents) AS available_grp_types " ,
2015-04-07 21:44:24 +02:00
GrpTypCod , ( unsigned ) Rol_STUDENT ) ;
2014-12-01 23:55:08 +01:00
NumGrpTypes = DB_QueryCOUNT ( Query , " can not check if a type of group has available groups " ) ;
return ( NumGrpTypes ! = 0 ) ;
}
/*****************************************************************************/
/****** Query list of group codes of a type to which a user belongs to *******/
/*****************************************************************************/
// If CrsCod < 0 ==> get the groups from all the user's courses
// If GrpTypCod < 0 ==> get the groups of any type
static void Grp_GetLstCodGrpsUsrBelongs ( long CrsCod , long GrpTypCod ,
long UsrCod , struct ListCodGrps * LstGrps )
{
char Query [ 1024 ] ;
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
unsigned NumGrp ;
/***** Get groups which a user belong to from database *****/
if ( CrsCod < 0 ) // Query the groups from all the user's courses
2017-03-11 00:47:23 +01:00
sprintf ( Query , " SELECT GrpCod "
" FROM crs_grp_usr "
2017-03-24 01:09:27 +01:00
" WHERE UsrCod=%ld " , // Groups will be unordered
2015-01-27 20:50:44 +01:00
UsrCod ) ;
2014-12-01 23:55:08 +01:00
else if ( GrpTypCod < 0 ) // Query the groups of any type in the course
2017-03-11 00:47:23 +01:00
sprintf ( Query , " SELECT crs_grp.GrpCod "
" FROM crs_grp_types,crs_grp,crs_grp_usr "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp_types.CrsCod=%ld "
2017-03-11 00:47:23 +01:00
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod "
2017-03-24 01:09:27 +01:00
" AND crs_grp_usr.UsrCod=%ld "
2014-12-01 23:55:08 +01:00
" ORDER BY crs_grp_types.GrpTypName,crs_grp.GrpName " ,
Gbl . CurrentCrs . Crs . CrsCod , UsrCod ) ;
else // Query only the groups of specified type in the course
2017-03-11 00:47:23 +01:00
sprintf ( Query , " SELECT crs_grp.GrpCod "
" FROM crs_grp_types,crs_grp,crs_grp_usr "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp_types.CrsCod=%ld "
" AND crs_grp_types.GrpTypCod=%ld "
2017-03-11 00:47:23 +01:00
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod "
2017-03-24 01:09:27 +01:00
" AND crs_grp_usr.UsrCod=%ld "
2014-12-01 23:55:08 +01:00
" ORDER BY crs_grp.GrpName " ,
Gbl . CurrentCrs . Crs . CrsCod , GrpTypCod , UsrCod ) ;
LstGrps - > NumGrps = ( unsigned ) DB_QuerySELECT ( Query , & mysql_res , " can not get the groups which a user belongs to " ) ;
/***** Get the groups *****/
if ( LstGrps - > NumGrps )
{
/***** Create a list of groups the user belongs to *****/
2017-01-19 20:55:31 +01:00
if ( ( LstGrps - > GrpCods = ( long * ) calloc ( LstGrps - > NumGrps , sizeof ( long ) ) ) = = NULL )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Not enough memory to store codes of groups a user belongs to. " ) ;
for ( NumGrp = 0 ;
NumGrp < LstGrps - > NumGrps ;
NumGrp + + )
{
row = mysql_fetch_row ( mysql_res ) ;
/* Get the code of group (row[0]) */
2017-01-19 20:55:31 +01:00
if ( ( LstGrps - > GrpCods [ NumGrp ] = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) < 0 )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Wrong code of group. " ) ;
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
}
/*****************************************************************************/
/********** Query list of group codes with file zones I belong to ************/
/*****************************************************************************/
void Grp_GetLstCodGrpsWithFileZonesIBelong ( struct ListCodGrps * LstGrps )
{
char Query [ 1024 ] ;
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
unsigned NumGrp ;
/***** Get groups which I belong to from database *****/
2017-03-11 00:47:23 +01:00
sprintf ( Query , " SELECT crs_grp.GrpCod "
" FROM crs_grp_types,crs_grp,crs_grp_usr "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp_types.CrsCod=%ld "
2015-10-26 20:02:07 +01:00
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
2014-12-01 23:55:08 +01:00
" AND crs_grp.FileZones='Y' "
2015-10-26 20:02:07 +01:00
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod "
2017-03-24 01:09:27 +01:00
" AND crs_grp_usr.UsrCod=%ld "
2014-12-01 23:55:08 +01:00
" ORDER BY crs_grp_types.GrpTypName,crs_grp.GrpName " ,
Gbl . CurrentCrs . Crs . CrsCod , Gbl . Usrs . Me . UsrDat . UsrCod ) ;
LstGrps - > NumGrps = ( unsigned ) DB_QuerySELECT ( Query , & mysql_res , " can not get the groups which I belong to " ) ;
/***** Get the groups *****/
if ( LstGrps - > NumGrps )
{
/***** Create a list of groups I belong to *****/
2017-01-19 20:55:31 +01:00
if ( ( LstGrps - > GrpCods = ( long * ) calloc ( LstGrps - > NumGrps , sizeof ( long ) ) ) = = NULL )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Not enough memory to store codes of groups I belongs to. " ) ;
for ( NumGrp = 0 ;
NumGrp < LstGrps - > NumGrps ;
NumGrp + + )
{
row = mysql_fetch_row ( mysql_res ) ;
/* Get the code of group (row[0]) */
2017-01-19 20:55:31 +01:00
if ( ( LstGrps - > GrpCods [ NumGrp ] = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) < 0 )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Wrong code of group. " ) ;
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
}
/*****************************************************************************/
/******** Check if a group is in a list of groups which I belong to **********/
/*****************************************************************************/
static bool Grp_CheckIfGrpIsInList ( long GrpCod , struct ListCodGrps * LstGrps )
{
unsigned NumGrp ;
for ( NumGrp = 0 ;
NumGrp < LstGrps - > NumGrps ;
NumGrp + + )
2017-01-19 20:55:31 +01:00
if ( GrpCod = = LstGrps - > GrpCods [ NumGrp ] )
2014-12-01 23:55:08 +01:00
return true ;
return false ;
}
/*****************************************************************************/
/********** Query names of groups of a type which user belongs to ************/
/*****************************************************************************/
void Grp_GetNamesGrpsStdBelongsTo ( long GrpTypCod , long UsrCod , char * GroupNames )
{
char Query [ 512 ] ;
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
2017-01-16 01:51:01 +01:00
unsigned long NumRow ;
unsigned long NumRows ;
2017-03-07 11:03:05 +01:00
size_t MaxLength = ( Grp_MAX_BYTES_GROUP_NAME + 2 ) * Gbl . CurrentCrs . Grps . GrpTypes . NumGrpsTotal ;
2014-12-01 23:55:08 +01:00
/***** Get the names of groups which a user belongs to, from database *****/
sprintf ( Query , " SELECT crs_grp.GrpName FROM crs_grp,crs_grp_usr "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp.GrpTypCod=%ld "
2015-10-26 20:02:07 +01:00
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod "
2017-03-24 01:09:27 +01:00
" AND crs_grp_usr.UsrCod=%ld "
2015-10-26 20:02:07 +01:00
" ORDER BY crs_grp.GrpName " ,
GrpTypCod , UsrCod ) ;
2014-12-01 23:55:08 +01:00
NumRows = DB_QuerySELECT ( Query , & mysql_res , " can not get the names of groups a user belongs to " ) ;
/***** Get the groups *****/
GroupNames [ 0 ] = ' \0 ' ;
for ( NumRow = 0 ;
NumRow < NumRows ;
NumRow + + )
{
/* Get next group */
row = mysql_fetch_row ( mysql_res ) ;
/* El group name in row[0] */
if ( NumRow )
2017-01-17 03:33:05 +01:00
Str_Concat ( GroupNames , " , " ,
MaxLength ) ;
Str_Concat ( GroupNames , row [ 0 ] ,
MaxLength ) ;
2014-12-01 23:55:08 +01:00
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
}
/*****************************************************************************/
/****************** Receive form to create a new group type ******************/
/*****************************************************************************/
void Grp_RecFormNewGrpTyp ( void )
{
extern const char * Txt_The_type_of_group_X_already_exists ;
2017-04-29 02:20:34 +02:00
extern const char * Txt_Created_new_type_of_group_X ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_You_must_specify_the_name_of_the_new_type_of_group ;
2017-04-29 02:20:34 +02:00
Lay_AlertType_t AlertType ;
2014-12-01 23:55:08 +01:00
/***** Get parameters from form *****/
/* Get the name of group type */
2017-01-29 12:42:19 +01:00
Par_GetParToText ( " GrpTypName " , Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_TYPE_NAME ) ;
2014-12-01 23:55:08 +01:00
/* Get whether it is mandatory to regisrer in any group of this type */
2017-03-30 11:20:06 +02:00
Gbl . CurrentCrs . Grps . GrpTyp . MandatoryEnrolment = Par_GetParToBool ( " MandatoryEnrolment " ) ;
2014-12-01 23:55:08 +01:00
/* Get whether it is possible to register in multiple groups of this type */
2017-03-30 11:20:06 +02:00
Gbl . CurrentCrs . Grps . GrpTyp . MultipleEnrolment = Par_GetParToBool ( " MultipleEnrolment " ) ;
2014-12-01 23:55:08 +01:00
/* Get open time */
2015-10-26 20:02:07 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . OpenTimeUTC = Dat_GetTimeUTCFromForm ( " OpenTimeUTC " ) ;
Gbl . CurrentCrs . Grps . GrpTyp . MustBeOpened = Grp_CheckIfOpenTimeInTheFuture ( Gbl . CurrentCrs . Grps . GrpTyp . OpenTimeUTC ) ;
2014-12-01 23:55:08 +01:00
if ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName [ 0 ] ) // If there's a group type name
{
/***** If name of group type was in database... *****/
if ( Grp_CheckIfGroupTypeNameExists ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName , - 1L ) )
{
2017-04-29 02:20:34 +02:00
AlertType = Lay_WARNING ;
2014-12-01 23:55:08 +01:00
sprintf ( Gbl . Message , Txt_The_type_of_group_X_already_exists ,
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName ) ;
}
else // Add new group type to database
2017-04-29 02:20:34 +02:00
{
2014-12-01 23:55:08 +01:00
Grp_CreateGroupType ( ) ;
2017-04-29 02:20:34 +02:00
AlertType = Lay_SUCCESS ;
sprintf ( Gbl . Message , Txt_Created_new_type_of_group_X ,
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName ) ;
}
2014-12-01 23:55:08 +01:00
}
else // If there is not a group type name
{
2017-04-29 02:20:34 +02:00
AlertType = Lay_WARNING ;
2014-12-01 23:55:08 +01:00
sprintf ( Gbl . Message , " %s " , Txt_You_must_specify_the_name_of_the_new_type_of_group ) ;
}
/***** Show the form again *****/
2017-04-29 20:42:10 +02:00
Grp_ReqEditGroupsInternal ( AlertType , Gbl . Message ,
Lay_INFO , NULL ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/**************** Check if the open time if in the future ********************/
/*****************************************************************************/
2015-10-26 20:02:07 +01:00
static bool Grp_CheckIfOpenTimeInTheFuture ( time_t OpenTimeUTC )
2014-12-01 23:55:08 +01:00
{
2015-10-26 20:02:07 +01:00
/***** If open time is 0 ==> groups must no be opened *****/
if ( OpenTimeUTC = = ( time_t ) 0 )
2014-12-01 23:55:08 +01:00
return false ;
/***** Is open time in the future? *****/
2015-10-27 19:00:21 +01:00
return ( OpenTimeUTC > Gbl . StartExecutionTimeUTC ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************** Receive form to create a new group *********************/
/*****************************************************************************/
void Grp_RecFormNewGrp ( void )
{
extern const char * Txt_The_group_X_already_exists ;
2017-04-28 18:03:30 +02:00
extern const char * Txt_Created_new_group_X ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_You_must_specify_the_name_of_the_new_group ;
2017-04-28 18:03:30 +02:00
Lay_AlertType_t AlertType ;
2014-12-01 23:55:08 +01:00
/***** Get parameters from form *****/
if ( ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) > 0 ) // Group type valid
{
/* Get group name */
2017-01-29 12:42:19 +01:00
Par_GetParToText ( " GrpName " , Gbl . CurrentCrs . Grps . GrpName ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_NAME ) ;
2014-12-01 23:55:08 +01:00
/* Get maximum number of students */
2017-01-29 21:41:08 +01:00
Gbl . CurrentCrs . Grps . MaxStudents = ( unsigned )
Par_GetParToUnsignedLong ( " MaxStudents " ,
0 ,
Grp_MAX_STUDENTS_IN_A_GROUP ,
Grp_NUM_STUDENTS_NOT_LIMITED ) ;
2014-12-01 23:55:08 +01:00
if ( Gbl . CurrentCrs . Grps . GrpName [ 0 ] ) // If there's a group name
{
/***** If name of group was in database... *****/
if ( Grp_CheckIfGroupNameExists ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod , Gbl . CurrentCrs . Grps . GrpName , - 1L ) )
{
2017-04-28 18:03:30 +02:00
AlertType = Lay_WARNING ;
2014-12-01 23:55:08 +01:00
sprintf ( Gbl . Message , Txt_The_group_X_already_exists ,
Gbl . CurrentCrs . Grps . GrpName ) ;
}
else // Add new group to database
2017-04-28 18:03:30 +02:00
{
2014-12-01 23:55:08 +01:00
Grp_CreateGroup ( ) ;
2017-04-28 18:03:30 +02:00
/* Write success message */
AlertType = Lay_SUCCESS ;
sprintf ( Gbl . Message , Txt_Created_new_group_X ,
Gbl . CurrentCrs . Grps . GrpName ) ;
}
2014-12-01 23:55:08 +01:00
}
else // If there is not a group name
{
2017-04-28 18:03:30 +02:00
AlertType = Lay_ERROR ;
2014-12-01 23:55:08 +01:00
sprintf ( Gbl . Message , " %s " , Txt_You_must_specify_the_name_of_the_new_group ) ;
}
}
else // Invalid group type
2017-04-28 18:03:30 +02:00
{
AlertType = Lay_ERROR ;
sprintf ( Gbl . Message , " %s " , " Wrong type of group. " ) ;
}
2014-12-01 23:55:08 +01:00
/***** Show the form again *****/
2017-04-29 20:42:10 +02:00
Grp_ReqEditGroupsInternal ( Lay_INFO , NULL ,
AlertType , Gbl . Message ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************* Check if name of group type exists **********************/
/*****************************************************************************/
static bool Grp_CheckIfGroupTypeNameExists ( const char * GrpTypName , long GrpTypCod )
{
2017-03-11 00:47:23 +01:00
char Query [ 256 + Grp_MAX_BYTES_GROUP_TYPE_NAME ] ;
2014-12-01 23:55:08 +01:00
/***** Get number of group types with a name from database *****/
sprintf ( Query , " SELECT COUNT(*) FROM crs_grp_types "
2017-03-24 01:09:27 +01:00
" WHERE CrsCod=%ld AND GrpTypName='%s' "
" AND GrpTypCod<>%ld " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Crs . CrsCod , GrpTypName , GrpTypCod ) ;
return ( DB_QueryCOUNT ( Query , " can not check if the name of type of group already existed " ) ! = 0 ) ;
}
/*****************************************************************************/
/************************ Check if name of group exists **********************/
/*****************************************************************************/
static bool Grp_CheckIfGroupNameExists ( long GrpTypCod , const char * GrpName , long GrpCod )
{
2017-03-11 00:47:23 +01:00
char Query [ 256 + Grp_MAX_BYTES_GROUP_NAME ] ;
2014-12-01 23:55:08 +01:00
/***** Get number of groups with a type and a name from database *****/
sprintf ( Query , " SELECT COUNT(*) FROM crs_grp "
2017-03-24 01:09:27 +01:00
" WHERE GrpTypCod=%ld AND GrpName='%s' AND GrpCod<>%ld " ,
2014-12-01 23:55:08 +01:00
GrpTypCod , GrpName , GrpCod ) ;
return ( DB_QueryCOUNT ( Query , " can not check if the name of group already existed " ) ! = 0 ) ;
}
/*****************************************************************************/
/************************** Create a new group type **************************/
/*****************************************************************************/
static void Grp_CreateGroupType ( void )
{
char Query [ 1024 ] ;
/***** Create a new group type *****/
2016-04-30 17:16:41 +02:00
sprintf ( Query , " INSERT INTO crs_grp_types "
" (CrsCod,GrpTypName,Mandatory,Multiple,MustBeOpened,OpenTime) "
2017-03-13 13:17:53 +01:00
" VALUES "
2017-03-24 01:09:27 +01:00
" (%ld,'%s','%c','%c','%c',FROM_UNIXTIME(%ld)) " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Crs . CrsCod , Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName ,
2017-03-30 11:20:06 +02:00
Gbl . CurrentCrs . Grps . GrpTyp . MandatoryEnrolment ? ' Y ' :
2014-12-01 23:55:08 +01:00
' N ' ,
2017-03-30 11:20:06 +02:00
Gbl . CurrentCrs . Grps . GrpTyp . MultipleEnrolment ? ' Y ' :
' N ' ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . MustBeOpened ? ' Y ' :
' N ' ,
2015-10-26 20:02:07 +01:00
( long ) Gbl . CurrentCrs . Grps . GrpTyp . OpenTimeUTC ) ;
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod = DB_QueryINSERTandReturnCode ( Query , " can not create type of group " ) ;
}
/*****************************************************************************/
/***************************** Create a new group ****************************/
/*****************************************************************************/
static void Grp_CreateGroup ( void )
{
2017-04-28 18:03:30 +02:00
char Query [ 256 + Grp_MAX_BYTES_GROUP_NAME ] ;
2014-12-01 23:55:08 +01:00
2017-04-28 18:03:30 +02:00
/***** Create a new group *****/
2017-03-13 13:17:53 +01:00
sprintf ( Query , " INSERT INTO crs_grp "
" (GrpTypCod,GrpName,MaxStudents,Open,FileZones) "
" VALUES "
2017-03-24 01:09:27 +01:00
" (%ld,'%s',%u,'N','N') " ,
2017-01-29 12:42:19 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ,
Gbl . CurrentCrs . Grps . GrpName ,
Gbl . CurrentCrs . Grps . MaxStudents ) ;
2014-12-01 23:55:08 +01:00
DB_QueryINSERT ( Query , " can not create group " ) ;
}
/*****************************************************************************/
/********************* Request removing of a group type **********************/
/*****************************************************************************/
void Grp_ReqRemGroupType ( void )
{
unsigned NumGrps ;
/***** Get the code of the group type *****/
if ( ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) < 0 )
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/***** Check if this group type has groups *****/
if ( ( NumGrps = Grp_CountNumGrpsInThisCrsOfType ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ) ) // Group type has groups ==> Ask for confirmation
Grp_AskConfirmRemGrpTypWithGrps ( NumGrps ) ;
else // Group type has no groups ==> remove directly
Grp_RemoveGroupTypeCompletely ( ) ;
}
/*****************************************************************************/
/************************* Request removal of a group ************************/
/*****************************************************************************/
void Grp_ReqRemGroup ( void )
{
/***** Get group code *****/
if ( ( Gbl . CurrentCrs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1L )
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/***** Confirm removing *****/
Grp_AskConfirmRemGrp ( ) ;
}
/*****************************************************************************/
/********** Ask for confirmation to remove a group type with groups **********/
/*****************************************************************************/
static void Grp_AskConfirmRemGrpTypWithGrps ( unsigned NumGrps )
{
extern const char * Txt_Do_you_really_want_to_remove_the_type_of_group_X_1_group_ ;
extern const char * Txt_Do_you_really_want_to_remove_the_type_of_group_X_Y_groups_ ;
extern const char * Txt_Remove_type_of_group ;
/***** Get data of the group type from database *****/
Grp_GetDataOfGroupTypeByCod ( & Gbl . CurrentCrs . Grps . GrpTyp ) ;
2017-04-29 02:20:34 +02:00
/***** Start section to edit group types *****/
Grp_ReqEditGroupsInternal0 ( ) ;
2017-04-28 14:12:37 +02:00
/***** Show question and button to remove type of group *****/
/* Start alert */
2014-12-01 23:55:08 +01:00
if ( NumGrps = = 1 )
sprintf ( Gbl . Message , Txt_Do_you_really_want_to_remove_the_type_of_group_X_1_group_ ,
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName ) ;
else
sprintf ( Gbl . Message , Txt_Do_you_really_want_to_remove_the_type_of_group_X_Y_groups_ ,
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName , NumGrps ) ;
2017-04-28 14:12:37 +02:00
Lay_ShowAlertAndButton1 ( Lay_QUESTION , Gbl . Message ) ;
2014-12-01 23:55:08 +01:00
2017-04-28 14:12:37 +02:00
/* End alert */
2017-04-29 15:29:58 +02:00
Lay_ShowAlertAndButton2 ( ActRemGrpTyp , Grp_SECTION_GROUP_TYPES ,
Grp_PutParamRemGrpTyp ,
2017-04-28 14:12:37 +02:00
Lay_REMOVE_BUTTON , Txt_Remove_type_of_group ) ;
2017-04-29 02:20:34 +02:00
/***** Show the form to edit group types and groups again *****/
Grp_ReqEditGroupsInternal1 ( Lay_INFO , NULL ) ;
Grp_ReqEditGroupsInternal2 ( Lay_INFO , NULL ) ;
2017-04-28 14:12:37 +02:00
}
/*****************************************************************************/
/**************** Put parameter to remove a type of group ********************/
/*****************************************************************************/
static void Grp_PutParamRemGrpTyp ( void )
{
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpTypCod ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
}
/*****************************************************************************/
/******************* Ask for confirmation to remove a group ******************/
/*****************************************************************************/
static void Grp_AskConfirmRemGrp ( void )
{
extern const char * Txt_Do_you_really_want_to_remove_the_group_X ;
extern const char * Txt_Do_you_really_want_to_remove_the_group_X_1_student_ ;
extern const char * Txt_Do_you_really_want_to_remove_the_group_X_Y_students_ ;
extern const char * Txt_Remove_group ;
struct GroupData GrpDat ;
unsigned NumStds ;
2017-04-28 13:10:46 +02:00
/***** Get name of the group from database *****/
2014-12-01 23:55:08 +01:00
GrpDat . GrpCod = Gbl . CurrentCrs . Grps . GrpCod ;
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
2017-04-28 13:10:46 +02:00
/***** Count number of students in group *****/
2014-12-01 23:55:08 +01:00
NumStds = Grp_CountNumStdsInGrp ( Gbl . CurrentCrs . Grps . GrpCod ) ;
2017-04-29 02:20:34 +02:00
/***** Show the form to edit group types again *****/
Grp_ReqEditGroupsInternal0 ( ) ;
Grp_ReqEditGroupsInternal1 ( Lay_INFO , NULL ) ;
2017-04-28 13:10:46 +02:00
/***** Show question and button to remove group *****/
/* Start alert */
2014-12-01 23:55:08 +01:00
if ( NumStds = = 0 )
sprintf ( Gbl . Message , Txt_Do_you_really_want_to_remove_the_group_X ,
GrpDat . GrpName ) ;
else if ( NumStds = = 1 )
sprintf ( Gbl . Message , Txt_Do_you_really_want_to_remove_the_group_X_1_student_ ,
GrpDat . GrpName ) ;
else
sprintf ( Gbl . Message , Txt_Do_you_really_want_to_remove_the_group_X_Y_students_ ,
GrpDat . GrpName , NumStds ) ;
2017-04-28 13:10:46 +02:00
Lay_ShowAlertAndButton1 ( Lay_QUESTION , Gbl . Message ) ;
2014-12-01 23:55:08 +01:00
2017-04-28 13:10:46 +02:00
/* End alert */
2017-04-29 15:29:58 +02:00
Lay_ShowAlertAndButton2 ( ActRemGrp , Grp_SECTION_GROUPS , Grp_PutParamRemGrp ,
2017-04-28 13:10:46 +02:00
Lay_REMOVE_BUTTON , Txt_Remove_group ) ;
2017-04-29 02:20:34 +02:00
/***** Show the form to edit groups again *****/
Grp_ReqEditGroupsInternal2 ( Lay_INFO , NULL ) ;
2017-04-28 13:10:46 +02:00
}
/*****************************************************************************/
/*********************** Put parameter to remove a group *********************/
/*****************************************************************************/
static void Grp_PutParamRemGrp ( void )
{
Grp_PutParamGrpCod ( Gbl . CurrentCrs . Grps . GrpCod ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2017-04-28 13:10:46 +02:00
/**************************** Remove a group type ****************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
void Grp_RemoveGroupType ( void )
{
/***** Get param with code of group type *****/
if ( ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) < 0 )
Lay_ShowErrorAndExit ( " Code of type of group is missing. " ) ;
/***** Remove group type and its groups *****/
Grp_RemoveGroupTypeCompletely ( ) ;
}
/*****************************************************************************/
/******************************* Remove a group ******************************/
/*****************************************************************************/
void Grp_RemoveGroup ( void )
{
/***** Get param with group code *****/
if ( ( Gbl . CurrentCrs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1L )
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/***** Remove group *****/
Grp_RemoveGroupCompletely ( ) ;
}
/*****************************************************************************/
2017-04-29 02:20:34 +02:00
/********************* Remove a group type from database *********************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
static void Grp_RemoveGroupTypeCompletely ( void )
{
extern const char * Txt_Type_of_group_X_removed ;
char Query [ 512 ] ;
/***** Get name and type of the group from database *****/
Grp_GetDataOfGroupTypeByCod ( & Gbl . CurrentCrs . Grps . GrpTyp ) ;
/***** Remove file zones of all the groups of this type *****/
Brw_RemoveZonesOfGroupsOfType ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
/***** Remove the associations of assignments to groups of this type *****/
Asg_RemoveGroupsOfType ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
/***** Remove the associations of attendance events to groups of this type *****/
Att_RemoveGroupsOfType ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
/***** Remove the associations of surveys to groups of this type *****/
Svy_RemoveGroupsOfType ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
/***** Change all groups of this type in course timetable *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " UPDATE timetable_crs SET GrpCod=-1 "
2015-01-27 20:50:44 +01:00
" WHERE GrpCod IN "
2017-03-24 01:09:27 +01:00
" (SELECT GrpCod FROM crs_grp WHERE GrpTypCod=%ld) " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
DB_QueryUPDATE ( Query , " can not update all groups of a type in course timetable " ) ;
/***** Remove all the students in groups of this type *****/
sprintf ( Query , " DELETE FROM crs_grp_usr WHERE GrpCod IN "
2017-03-24 01:09:27 +01:00
" (SELECT GrpCod FROM crs_grp WHERE GrpTypCod=%ld) " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
DB_QueryDELETE ( Query , " can not remove users from all groups of a type " ) ;
/***** Remove all the groups of this type *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " DELETE FROM crs_grp WHERE GrpTypCod=%ld " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
DB_QueryDELETE ( Query , " can not remove groups of a type " ) ;
/***** Remove the group type *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " DELETE FROM crs_grp_types WHERE GrpTypCod=%ld " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
DB_QueryDELETE ( Query , " can not remove a type of group " ) ;
/***** Write message to show the change made *****/
sprintf ( Gbl . Message , Txt_Type_of_group_X_removed ,
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName ) ;
/***** Show the form again *****/
2017-04-29 20:42:10 +02:00
Grp_ReqEditGroupsInternal ( Lay_SUCCESS , Gbl . Message ,
Lay_INFO , NULL ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******* Remove a group from data base and remove group common zone **********/
/*****************************************************************************/
static void Grp_RemoveGroupCompletely ( void )
{
extern const char * Txt_Group_X_removed ;
struct GroupData GrpDat ;
char Query [ 512 ] ;
/***** Get name and type of the group from database *****/
GrpDat . GrpCod = Gbl . CurrentCrs . Grps . GrpCod ;
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
/***** Remove file zones of this group *****/
2017-04-29 20:16:53 +02:00
Brw_RemoveGrpZones ( Gbl . CurrentCrs . Crs . CrsCod , GrpDat . GrpCod ) ;
2014-12-01 23:55:08 +01:00
/***** Remove this group from all the assignments *****/
Asg_RemoveGroup ( GrpDat . GrpCod ) ;
/***** Remove this group from all the attendance events *****/
Att_RemoveGroup ( GrpDat . GrpCod ) ;
/***** Remove this group from all the surveys *****/
Svy_RemoveGroup ( GrpDat . GrpCod ) ;
/***** Change this group in course timetable *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " UPDATE timetable_crs SET GrpCod=-1 WHERE GrpCod=%ld " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpCod ) ;
DB_QueryUPDATE ( Query , " can not update a group in course timetable " ) ;
/***** Remove all the students in this group *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " DELETE FROM crs_grp_usr WHERE GrpCod=%ld " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpCod ) ;
DB_QueryDELETE ( Query , " can not remove users from a group " ) ;
/***** Remove the group *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " DELETE FROM crs_grp WHERE GrpCod=%ld " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpCod ) ;
DB_QueryDELETE ( Query , " can not remove a group " ) ;
/***** Write message to show the change made *****/
2017-04-29 02:20:34 +02:00
sprintf ( Gbl . Message , Txt_Group_X_removed , GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
/***** Show the form again *****/
2017-04-29 20:42:10 +02:00
Grp_ReqEditGroupsInternal ( Lay_INFO , NULL ,
Lay_SUCCESS , Gbl . Message ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************************* Open a group ********************************/
/*****************************************************************************/
void Grp_OpenGroup ( void )
{
extern const char * Txt_The_group_X_is_now_open ;
struct GroupData GrpDat ;
char Query [ 512 ] ;
/***** Get group code *****/
if ( ( Gbl . CurrentCrs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1 )
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/***** Get group data from database *****/
GrpDat . GrpCod = Gbl . CurrentCrs . Grps . GrpCod ;
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
/***** Update the table of groups changing open/close status *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " UPDATE crs_grp SET Open='Y' WHERE GrpCod=%ld " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpCod ) ;
DB_QueryUPDATE ( Query , " can not open a group " ) ;
/***** Write message to show the change made *****/
2017-04-29 01:12:35 +02:00
sprintf ( Gbl . Message , Txt_The_group_X_is_now_open , GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
/***** Show the form again *****/
Gbl . CurrentCrs . Grps . Open = true ;
2017-04-29 20:42:10 +02:00
Grp_ReqEditGroupsInternal ( Lay_INFO , NULL ,
Lay_SUCCESS , Gbl . Message ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************************* Close a group *******************************/
/*****************************************************************************/
void Grp_CloseGroup ( void )
{
extern const char * Txt_The_group_X_is_now_closed ;
struct GroupData GrpDat ;
char Query [ 512 ] ;
/***** Get group code *****/
if ( ( Gbl . CurrentCrs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1 )
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/***** Get group data from database *****/
GrpDat . GrpCod = Gbl . CurrentCrs . Grps . GrpCod ;
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
/***** Update the table of groups changing open/close status *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " UPDATE crs_grp SET Open='N' WHERE GrpCod=%ld " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpCod ) ;
DB_QueryUPDATE ( Query , " can not close a group " ) ;
/***** Write message to show the change made *****/
2017-04-29 01:12:35 +02:00
sprintf ( Gbl . Message , Txt_The_group_X_is_now_closed , GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
/***** Show the form again *****/
Gbl . CurrentCrs . Grps . Open = false ;
2017-04-29 20:42:10 +02:00
Grp_ReqEditGroupsInternal ( Lay_INFO , NULL ,
Lay_SUCCESS , Gbl . Message ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************************ Enable file zones of a group ***********************/
/*****************************************************************************/
void Grp_EnableFileZonesGrp ( void )
{
extern const char * Txt_File_zones_of_the_group_X_are_now_enabled ;
struct GroupData GrpDat ;
char Query [ 512 ] ;
/***** Get group code *****/
if ( ( Gbl . CurrentCrs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1 )
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/***** Get group data from database *****/
GrpDat . GrpCod = Gbl . CurrentCrs . Grps . GrpCod ;
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
/***** Update the table of groups changing file zones status *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " UPDATE crs_grp SET FileZones='Y' WHERE GrpCod=%ld " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpCod ) ;
DB_QueryUPDATE ( Query , " can not enable file zones of a group " ) ;
/***** Write message to show the change made *****/
sprintf ( Gbl . Message , Txt_File_zones_of_the_group_X_are_now_enabled ,
GrpDat . GrpName ) ;
/***** Show the form again *****/
Gbl . CurrentCrs . Grps . FileZones = true ;
2017-04-29 20:42:10 +02:00
Grp_ReqEditGroupsInternal ( Lay_INFO , NULL ,
Lay_SUCCESS , Gbl . Message ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********************** Disable file zones of a group ***********************/
/*****************************************************************************/
void Grp_DisableFileZonesGrp ( void )
{
extern const char * Txt_File_zones_of_the_group_X_are_now_disabled ;
struct GroupData GrpDat ;
char Query [ 512 ] ;
/***** Get group code *****/
if ( ( Gbl . CurrentCrs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1 )
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/***** Get group data from database *****/
GrpDat . GrpCod = Gbl . CurrentCrs . Grps . GrpCod ;
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
/***** Update the table of groups changing file zones status *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " UPDATE crs_grp SET FileZones='N' WHERE GrpCod=%ld " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpCod ) ;
DB_QueryUPDATE ( Query , " can not disable file zones of a group " ) ;
/***** Write message to show the change made *****/
sprintf ( Gbl . Message , Txt_File_zones_of_the_group_X_are_now_disabled ,
GrpDat . GrpName ) ;
/***** Show the form again *****/
Gbl . CurrentCrs . Grps . FileZones = false ;
2017-04-29 20:42:10 +02:00
Grp_ReqEditGroupsInternal ( Lay_INFO , NULL ,
Lay_SUCCESS , Gbl . Message ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********************** Change the group type of a group ********************/
/*****************************************************************************/
void Grp_ChangeGroupType ( void )
{
extern const char * Txt_The_group_X_already_exists ;
extern const char * Txt_The_type_of_group_of_the_group_X_has_changed ;
long NewGrpTypCod ;
struct GroupData GrpDat ;
char Query [ 512 ] ;
2017-04-29 01:12:35 +02:00
Lay_AlertType_t AlertType ;
2014-12-01 23:55:08 +01:00
/***** Get parameters from form *****/
/* Get group code */
if ( ( Gbl . CurrentCrs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1L )
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/* Get the new group type */
NewGrpTypCod = Grp_GetParamGrpTypCod ( ) ;
/* Get from the database the type and the name of the group */
GrpDat . GrpCod = Gbl . CurrentCrs . Grps . GrpCod ;
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
/***** If group was in database... *****/
if ( Grp_CheckIfGroupNameExists ( NewGrpTypCod , GrpDat . GrpName , - 1L ) )
{
2017-04-29 01:12:35 +02:00
AlertType = Lay_WARNING ;
sprintf ( Gbl . Message , Txt_The_group_X_already_exists , GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
}
else
{
/* Update the table of groups changing old type by new type */
2017-03-24 01:09:27 +01:00
sprintf ( Query , " UPDATE crs_grp SET GrpTypCod=%ld WHERE GrpCod=%ld " ,
2014-12-01 23:55:08 +01:00
NewGrpTypCod , Gbl . CurrentCrs . Grps . GrpCod ) ;
DB_QueryUPDATE ( Query , " can not update the type of a group " ) ;
/***** Write message to show the change made *****/
2017-04-29 01:12:35 +02:00
AlertType = Lay_SUCCESS ;
2014-12-01 23:55:08 +01:00
sprintf ( Gbl . Message , Txt_The_type_of_group_of_the_group_X_has_changed ,
GrpDat . GrpName ) ;
}
/***** Show the form again *****/
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod = NewGrpTypCod ;
2017-04-29 20:42:10 +02:00
Grp_ReqEditGroupsInternal ( Lay_INFO , NULL ,
AlertType , Gbl . Message ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************ Change mandatory registration to a group of a type *************/
/*****************************************************************************/
void Grp_ChangeMandatGrpTyp ( void )
{
2017-03-30 11:20:06 +02:00
extern const char * Txt_The_type_of_enrolment_of_the_type_of_group_X_has_not_changed ;
extern const char * Txt_The_enrolment_of_students_into_groups_of_type_X_is_now_mandatory ;
extern const char * Txt_The_enrolment_of_students_into_groups_of_type_X_is_now_voluntary ;
2014-12-01 23:55:08 +01:00
char Query [ 1024 ] ;
2017-03-30 11:20:06 +02:00
bool NewMandatoryEnrolment ;
2017-04-29 02:20:34 +02:00
Lay_AlertType_t AlertType ;
2014-12-01 23:55:08 +01:00
/***** Get parameters of the form *****/
/* Get the c<> digo of type of group */
if ( ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) < 0 )
Lay_ShowErrorAndExit ( " Code of type of group is missing. " ) ;
2017-03-30 11:20:06 +02:00
/* Get the new type of enrolment (mandatory or voluntaria) of this type of group */
NewMandatoryEnrolment = Par_GetParToBool ( " MandatoryEnrolment " ) ;
2014-12-01 23:55:08 +01:00
2017-03-30 11:20:06 +02:00
/* Get from the database the name of the type and the old type of enrolment */
2014-12-01 23:55:08 +01:00
Grp_GetDataOfGroupTypeByCod ( & Gbl . CurrentCrs . Grps . GrpTyp ) ;
2017-03-30 11:20:06 +02:00
/***** Check if the old type of enrolment match the new
2014-12-01 23:55:08 +01:00
( this happens when return is pressed without changes in the form ) * * * * */
2017-03-30 11:20:06 +02:00
if ( Gbl . CurrentCrs . Grps . GrpTyp . MandatoryEnrolment = = NewMandatoryEnrolment )
2014-12-01 23:55:08 +01:00
{
2017-04-29 02:20:34 +02:00
AlertType = Lay_INFO ;
2017-03-30 11:20:06 +02:00
sprintf ( Gbl . Message , Txt_The_type_of_enrolment_of_the_type_of_group_X_has_not_changed ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName ) ;
}
else
{
2017-03-30 11:20:06 +02:00
/***** Update of the table of types of group changing the old type of enrolment by the new *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " UPDATE crs_grp_types SET Mandatory='%c' WHERE GrpTypCod=%ld " ,
2017-03-30 11:20:06 +02:00
NewMandatoryEnrolment ? ' Y ' :
2014-12-01 23:55:08 +01:00
' N ' ,
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
2017-03-30 11:20:06 +02:00
DB_QueryUPDATE ( Query , " can not update enrolment type of a type of group " ) ;
2014-12-01 23:55:08 +01:00
/***** Write message to show the change made *****/
2017-04-29 02:20:34 +02:00
AlertType = Lay_SUCCESS ;
2014-12-01 23:55:08 +01:00
sprintf ( Gbl . Message ,
2017-03-30 11:20:06 +02:00
NewMandatoryEnrolment ? Txt_The_enrolment_of_students_into_groups_of_type_X_is_now_mandatory :
Txt_The_enrolment_of_students_into_groups_of_type_X_is_now_voluntary ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName ) ;
}
/***** Show the form again *****/
2017-03-30 11:20:06 +02:00
Gbl . CurrentCrs . Grps . GrpTyp . MandatoryEnrolment = NewMandatoryEnrolment ;
2017-04-29 20:42:10 +02:00
Grp_ReqEditGroupsInternal ( AlertType , Gbl . Message ,
Lay_INFO , NULL ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2017-03-30 11:20:06 +02:00
/******** Change multiple enrolment to one or more groups of a type *********/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
void Grp_ChangeMultiGrpTyp ( void )
{
2017-03-30 11:20:06 +02:00
extern const char * Txt_The_type_of_enrolment_of_the_type_of_group_X_has_not_changed ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_Now_each_student_can_belong_to_multiple_groups_of_type_X ;
extern const char * Txt_Now_each_student_can_only_belong_to_a_group_of_type_X ;
char Query [ 1024 ] ;
2017-03-30 11:20:06 +02:00
bool NewMultipleEnrolment ;
2017-04-29 02:20:34 +02:00
Lay_AlertType_t AlertType ;
2014-12-01 23:55:08 +01:00
/***** Get parameters from the form *****/
/* Get the code of type of group */
if ( ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) < 0 )
Lay_ShowErrorAndExit ( " Code of type of group is missing. " ) ;
2017-03-30 11:20:06 +02:00
/* Get the new type of enrolment (single or multiple) of this type of group */
NewMultipleEnrolment = Par_GetParToBool ( " MultipleEnrolment " ) ;
2014-12-01 23:55:08 +01:00
2017-03-30 11:20:06 +02:00
/* Get from the database the name of the type and the old type of enrolment */
2014-12-01 23:55:08 +01:00
Grp_GetDataOfGroupTypeByCod ( & Gbl . CurrentCrs . Grps . GrpTyp ) ;
2017-03-30 11:20:06 +02:00
/***** Check if the old type of enrolment match the new one
2014-12-01 23:55:08 +01:00
( this happends when return is pressed without changes ) * * * * */
2017-03-30 11:20:06 +02:00
if ( Gbl . CurrentCrs . Grps . GrpTyp . MultipleEnrolment = = NewMultipleEnrolment )
2014-12-01 23:55:08 +01:00
{
2017-04-29 02:20:34 +02:00
AlertType = Lay_INFO ;
2017-03-30 11:20:06 +02:00
sprintf ( Gbl . Message , Txt_The_type_of_enrolment_of_the_type_of_group_X_has_not_changed ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName ) ;
}
else
{
2017-03-30 11:20:06 +02:00
/***** Update of the table of types of group changing the old type of enrolment by the new *****/
2014-12-01 23:55:08 +01:00
sprintf ( Query , " UPDATE crs_grp_types SET Multiple='%c' "
2017-03-24 01:09:27 +01:00
" WHERE GrpTypCod=%ld " ,
2017-03-30 11:20:06 +02:00
NewMultipleEnrolment ? ' Y ' :
' N ' ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
2017-03-30 11:20:06 +02:00
DB_QueryUPDATE ( Query , " can not update enrolment type of a type of group " ) ;
2014-12-01 23:55:08 +01:00
/***** Write message to show the change made *****/
2017-04-29 02:20:34 +02:00
AlertType = Lay_SUCCESS ;
2014-12-01 23:55:08 +01:00
sprintf ( Gbl . Message ,
2017-03-30 11:20:06 +02:00
NewMultipleEnrolment ? Txt_Now_each_student_can_belong_to_multiple_groups_of_type_X :
Txt_Now_each_student_can_only_belong_to_a_group_of_type_X ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName ) ;
}
/***** Show the form again *****/
2017-03-30 11:20:06 +02:00
Gbl . CurrentCrs . Grps . GrpTyp . MultipleEnrolment = NewMultipleEnrolment ;
2017-04-29 20:42:10 +02:00
Grp_ReqEditGroupsInternal ( AlertType , Gbl . Message ,
Lay_INFO , NULL ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/****************** Change open time for a type of group *********************/
/*****************************************************************************/
void Grp_ChangeOpenTimeGrpTyp ( void )
{
extern const char * Txt_The_date_time_of_opening_of_groups_has_changed ;
char Query [ 512 ] ;
/***** Get the code of type of group *****/
if ( ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) < 0 )
Lay_ShowErrorAndExit ( " Code of type of group is missing. " ) ;
/***** Get from the database the data of this type of group *****/
Grp_GetDataOfGroupTypeByCod ( & Gbl . CurrentCrs . Grps . GrpTyp ) ;
/***** Get open time *****/
2015-10-26 20:02:07 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . OpenTimeUTC = Dat_GetTimeUTCFromForm ( " OpenTimeUTC " ) ;
Gbl . CurrentCrs . Grps . GrpTyp . MustBeOpened = Grp_CheckIfOpenTimeInTheFuture ( Gbl . CurrentCrs . Grps . GrpTyp . OpenTimeUTC ) ;
2014-12-01 23:55:08 +01:00
2016-04-30 17:16:41 +02:00
/***** Update the table of types of group
2017-03-30 11:20:06 +02:00
changing the old open time of enrolment by the new * * * * */
2016-04-30 17:16:41 +02:00
sprintf ( Query , " UPDATE crs_grp_types "
2017-03-24 01:09:27 +01:00
" SET MustBeOpened='%c',OpenTime=FROM_UNIXTIME(%ld) "
" WHERE GrpTypCod=%ld " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . MustBeOpened ? ' Y ' :
' N ' ,
2015-10-26 20:02:07 +01:00
( long ) Gbl . CurrentCrs . Grps . GrpTyp . OpenTimeUTC ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
2017-03-30 11:20:06 +02:00
DB_QueryUPDATE ( Query , " can not update enrolment type of a type of group " ) ;
2014-12-01 23:55:08 +01:00
/***** Write message to show the change made *****/
2017-04-29 02:20:34 +02:00
sprintf ( Gbl . Message , " %s " , Txt_The_date_time_of_opening_of_groups_has_changed ) ;
2014-12-01 23:55:08 +01:00
/***** Show the form again *****/
2017-04-29 20:42:10 +02:00
Grp_ReqEditGroupsInternal ( Lay_SUCCESS , Gbl . Message ,
Lay_INFO , NULL ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/***************** Change maximum of students in a group *********************/
/*****************************************************************************/
void Grp_ChangeMaxStdsGrp ( void )
{
extern const char * Txt_The_maximum_number_of_students_in_the_group_X_has_not_changed ;
extern const char * Txt_The_group_X_now_has_no_limit_of_students ;
extern const char * Txt_The_maximum_number_of_students_in_the_group_X_is_now_Y ;
struct GroupData GrpDat ;
char Query [ 1024 ] ;
unsigned NewMaxStds ;
2017-04-29 01:12:35 +02:00
Lay_AlertType_t AlertType ;
2014-12-01 23:55:08 +01:00
/***** Get parameters of the form *****/
/* Get group code */
if ( ( Gbl . CurrentCrs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1 )
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/* Get the new maximum number of students of the group */
2017-01-29 21:41:08 +01:00
NewMaxStds = ( unsigned )
Par_GetParToUnsignedLong ( " MaxStudents " ,
0 ,
Grp_MAX_STUDENTS_IN_A_GROUP ,
Grp_NUM_STUDENTS_NOT_LIMITED ) ;
2014-12-01 23:55:08 +01:00
/* Get from the database the type, name, and antiguo maximum of students of the group */
GrpDat . GrpCod = Gbl . CurrentCrs . Grps . GrpCod ;
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
/***** Check if the old maximum of students equals the new one (this happens when user press return without change the form) *****/
if ( GrpDat . MaxStudents = = NewMaxStds )
{
2017-04-29 01:12:35 +02:00
AlertType = Lay_INFO ;
2014-12-01 23:55:08 +01:00
sprintf ( Gbl . Message , Txt_The_maximum_number_of_students_in_the_group_X_has_not_changed ,
GrpDat . GrpName ) ;
}
else
{
/***** Update the table of groups changing the old maximum of students to the new *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " UPDATE crs_grp SET MaxStudents=%u WHERE GrpCod=%ld " ,
2014-12-01 23:55:08 +01:00
NewMaxStds , Gbl . CurrentCrs . Grps . GrpCod ) ;
DB_QueryUPDATE ( Query , " can not update the maximum number of students in a group " ) ;
/***** Write message to show the change made *****/
2017-04-29 01:12:35 +02:00
AlertType = Lay_SUCCESS ;
2017-01-29 12:42:19 +01:00
if ( NewMaxStds > Grp_MAX_STUDENTS_IN_A_GROUP )
2014-12-01 23:55:08 +01:00
sprintf ( Gbl . Message , Txt_The_group_X_now_has_no_limit_of_students ,
GrpDat . GrpName ) ;
else
sprintf ( Gbl . Message , Txt_The_maximum_number_of_students_in_the_group_X_is_now_Y ,
GrpDat . GrpName , NewMaxStds ) ;
}
/***** Show the form again *****/
Gbl . CurrentCrs . Grps . MaxStudents = NewMaxStds ;
2017-04-29 20:42:10 +02:00
Grp_ReqEditGroupsInternal ( Lay_INFO , NULL ,
AlertType , Gbl . Message ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************ Write the number maximum of students in a group ***************/
/*****************************************************************************/
static void Grp_WriteMaxStdsGrp ( unsigned MaxStudents )
{
if ( MaxStudents > Grp_MAX_STUDENTS_IN_A_GROUP )
fprintf ( Gbl . F . Out , " - " ) ;
else
fprintf ( Gbl . F . Out , " %u " , MaxStudents ) ;
}
/*****************************************************************************/
/********* Convert string to maximum number of students in a group ***********/
/*****************************************************************************/
unsigned Grp_ConvertToNumMaxStdsGrp ( const char * StrMaxStudents )
{
unsigned MaxStudents ;
if ( sscanf ( StrMaxStudents , " %u " , & MaxStudents ) ! = 1 )
2017-01-29 12:42:19 +01:00
return Grp_NUM_STUDENTS_NOT_LIMITED ;
2014-12-01 23:55:08 +01:00
else if ( MaxStudents > Grp_MAX_STUDENTS_IN_A_GROUP )
2017-01-29 12:42:19 +01:00
return Grp_NUM_STUDENTS_NOT_LIMITED ;
2014-12-01 23:55:08 +01:00
return MaxStudents ;
}
/*****************************************************************************/
/***************************** Rename a group type ***************************/
/*****************************************************************************/
void Grp_RenameGroupType ( void )
{
extern const char * Txt_You_can_not_leave_the_name_of_the_type_of_group_X_empty ;
extern const char * Txt_The_type_of_group_X_already_exists ;
extern const char * Txt_The_type_of_group_X_has_been_renamed_as_Y ;
extern const char * Txt_The_name_of_the_type_of_group_X_has_not_changed ;
2017-03-11 00:47:23 +01:00
char Query [ 128 + Grp_MAX_BYTES_GROUP_TYPE_NAME ] ;
2017-03-07 11:03:05 +01:00
char NewNameGrpTyp [ Grp_MAX_BYTES_GROUP_TYPE_NAME + 1 ] ;
2017-04-29 02:20:34 +02:00
Lay_AlertType_t AlertType ;
2014-12-01 23:55:08 +01:00
/***** Get parameters from form *****/
/* Get the code of the group type */
if ( ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) < 0 )
Lay_ShowErrorAndExit ( " Code of type of group is missing. " ) ;
/* Get the new name for the group type */
2017-03-07 11:03:05 +01:00
Par_GetParToText ( " GrpTypName " , NewNameGrpTyp , Grp_MAX_BYTES_GROUP_TYPE_NAME ) ;
2014-12-01 23:55:08 +01:00
/***** Get from the database the old name of the group type *****/
Grp_GetDataOfGroupTypeByCod ( & Gbl . CurrentCrs . Grps . GrpTyp ) ;
/***** Check if new name is empty *****/
if ( ! NewNameGrpTyp [ 0 ] )
{
2017-04-29 02:20:34 +02:00
AlertType = Lay_WARNING ;
2014-12-01 23:55:08 +01:00
sprintf ( Gbl . Message , Txt_You_can_not_leave_the_name_of_the_type_of_group_X_empty ,
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName ) ;
}
else
{
/***** Check if old and new names are the same (this happens when user press enter with no changes in the form) *****/
if ( strcmp ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName , NewNameGrpTyp ) ) // Different names
{
/***** If group type was in database... *****/
if ( Grp_CheckIfGroupTypeNameExists ( NewNameGrpTyp , Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) )
{
2017-04-29 02:20:34 +02:00
AlertType = Lay_WARNING ;
2014-12-01 23:55:08 +01:00
sprintf ( Gbl . Message , Txt_The_type_of_group_X_already_exists ,
NewNameGrpTyp ) ;
}
else
{
/* Update the table changing old name by new name */
2017-03-11 00:47:23 +01:00
sprintf ( Query , " UPDATE crs_grp_types SET GrpTypName='%s' "
2017-03-24 01:09:27 +01:00
" WHERE GrpTypCod=%ld " ,
2016-04-30 17:16:41 +02:00
NewNameGrpTyp ,
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
DB_QueryUPDATE ( Query , " can not update the type of a group " ) ;
/***** Write message to show the change made *****/
2017-04-29 02:20:34 +02:00
AlertType = Lay_SUCCESS ;
2014-12-01 23:55:08 +01:00
sprintf ( Gbl . Message , Txt_The_type_of_group_X_has_been_renamed_as_Y ,
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName , NewNameGrpTyp ) ;
}
}
else // The same name
{
2017-04-29 02:20:34 +02:00
AlertType = Lay_INFO ;
2014-12-01 23:55:08 +01:00
sprintf ( Gbl . Message , Txt_The_name_of_the_type_of_group_X_has_not_changed ,
NewNameGrpTyp ) ;
}
}
/***** Show the form again *****/
2017-01-15 18:02:52 +01:00
Str_Copy ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName , NewNameGrpTyp ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_TYPE_NAME ) ;
2017-04-29 20:42:10 +02:00
Grp_ReqEditGroupsInternal ( AlertType , Gbl . Message ,
Lay_INFO , NULL ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************************* Rename a group ******************************/
/*****************************************************************************/
void Grp_RenameGroup ( void )
{
extern const char * Txt_You_can_not_leave_the_name_of_the_group_X_empty ;
extern const char * Txt_The_group_X_already_exists ;
extern const char * Txt_The_group_X_has_been_renamed_as_Y ;
extern const char * Txt_The_name_of_the_group_X_has_not_changed ;
struct GroupData GrpDat ;
2017-03-11 00:47:23 +01:00
char Query [ 128 + Grp_MAX_BYTES_GROUP_NAME ] ;
2017-03-07 11:03:05 +01:00
char NewNameGrp [ Grp_MAX_BYTES_GROUP_NAME + 1 ] ;
2017-04-29 01:12:35 +02:00
Lay_AlertType_t AlertType ;
2014-12-01 23:55:08 +01:00
/***** Get parameters from form *****/
/* Get the code of the group */
if ( ( Gbl . CurrentCrs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1L )
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/* Get the new name for the group */
2017-03-07 11:03:05 +01:00
Par_GetParToText ( " GrpName " , NewNameGrp , Grp_MAX_BYTES_GROUP_NAME ) ;
2014-12-01 23:55:08 +01:00
/***** Get from the database the type and the old name of the group *****/
GrpDat . GrpCod = Gbl . CurrentCrs . Grps . GrpCod ;
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
/***** Check if new name is empty *****/
if ( ! NewNameGrp [ 0 ] )
{
2017-04-29 01:12:35 +02:00
AlertType = Lay_WARNING ;
2014-12-01 23:55:08 +01:00
sprintf ( Gbl . Message , Txt_You_can_not_leave_the_name_of_the_group_X_empty ,
GrpDat . GrpName ) ;
}
else
{
/***** Check if old and new names are the same (this happens when user press enter with no changes in the form) *****/
if ( strcmp ( GrpDat . GrpName , NewNameGrp ) ) // Different names
{
/***** If group was in database... *****/
if ( Grp_CheckIfGroupNameExists ( GrpDat . GrpTypCod , NewNameGrp , Gbl . CurrentCrs . Grps . GrpCod ) )
{
2017-04-29 01:12:35 +02:00
AlertType = Lay_WARNING ;
sprintf ( Gbl . Message , Txt_The_group_X_already_exists , NewNameGrp ) ;
2014-12-01 23:55:08 +01:00
}
else
{
/* Update the table changing old name by new name */
2017-03-24 01:09:27 +01:00
sprintf ( Query , " UPDATE crs_grp SET GrpName='%s' WHERE GrpCod=%ld " ,
2014-12-01 23:55:08 +01:00
NewNameGrp , Gbl . CurrentCrs . Grps . GrpCod ) ;
DB_QueryUPDATE ( Query , " can not update the name of a group " ) ;
/***** Write message to show the change made *****/
2017-04-29 01:12:35 +02:00
AlertType = Lay_SUCCESS ;
2014-12-01 23:55:08 +01:00
sprintf ( Gbl . Message , Txt_The_group_X_has_been_renamed_as_Y ,
GrpDat . GrpName , NewNameGrp ) ;
}
}
else // The same name
{
2017-04-29 01:12:35 +02:00
AlertType = Lay_INFO ;
2014-12-01 23:55:08 +01:00
sprintf ( Gbl . Message , Txt_The_name_of_the_group_X_has_not_changed ,
NewNameGrp ) ;
}
}
/***** Show the form again *****/
2017-01-17 03:10:43 +01:00
Str_Copy ( Gbl . CurrentCrs . Grps . GrpName , NewNameGrp ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_NAME ) ;
2017-04-29 20:42:10 +02:00
Grp_ReqEditGroupsInternal ( Lay_INFO , NULL ,
AlertType , Gbl . Message ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************* Get parameter with code of group type *******************/
/*****************************************************************************/
static long Grp_GetParamGrpTypCod ( void )
{
2017-01-28 20:32:50 +01:00
/***** Get code of group type *****/
return Par_GetParToLong ( " GrpTypCod " ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********************** Get parameter with group code ***********************/
/*****************************************************************************/
static long Grp_GetParamGrpCod ( void )
{
2017-01-28 20:32:50 +01:00
/***** Get group code *****/
return Par_GetParToLong ( " GrpCod " ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/****************** Write parameter with code of group type ******************/
/*****************************************************************************/
static void Grp_PutParamGrpTypCod ( long GrpTypCod )
{
Par_PutHiddenParamLong ( " GrpTypCod " , GrpTypCod ) ;
}
/*****************************************************************************/
/********************* Write parameter with code of group ********************/
/*****************************************************************************/
void Grp_PutParamGrpCod ( long GrpCod )
{
Par_PutHiddenParamLong ( " GrpCod " , GrpCod ) ;
}
/*****************************************************************************/
/************************ Get list of group codes selected *******************/
/*****************************************************************************/
void Grp_GetLstCodsGrpWanted ( struct ListCodGrps * LstGrpsWanted )
{
unsigned NumGrpTyp ;
2017-01-28 15:58:46 +01:00
char Param [ 8 + 10 + 1 ] ;
char LongStr [ 1 + 10 + 1 ] ;
2014-12-01 23:55:08 +01:00
char * * LstStrCodGrps ;
const char * Ptr ;
unsigned NumGrpWanted ;
/***** Allocate memory for the strings with group codes in each type *****/
if ( ( LstStrCodGrps = ( char * * ) calloc ( Gbl . CurrentCrs . Grps . GrpTypes . Num , sizeof ( char * ) ) ) = = NULL )
2017-03-30 11:20:06 +02:00
Lay_ShowErrorAndExit ( " Not enough memory to store codes of groups in which a user wants to be enroled. " ) ;
2014-12-01 23:55:08 +01:00
/***** Get lists with the groups that I want in each type
in order to count the total number of groups selected * * * * */
for ( NumGrpTyp = 0 , LstGrpsWanted - > NumGrps = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
{
/***** Allocate memory for the list of group codes of this type *****/
2017-01-28 15:58:46 +01:00
if ( ( LstStrCodGrps [ NumGrpTyp ] = ( char * ) malloc ( ( size_t ) ( ( 1 + 10 + 1 ) *
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps ) ) ) = = NULL )
2017-03-30 11:20:06 +02:00
Lay_ShowErrorAndExit ( " Not enough memory to store codes of groups in which a user wants to be enroled. " ) ;
2014-12-01 23:55:08 +01:00
/***** Get the multiple parameter code of group of this type *****/
sprintf ( Param , " GrpCod%ld " , Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
2017-01-28 15:58:46 +01:00
Par_GetParMultiToText ( Param , LstStrCodGrps [ NumGrpTyp ] ,
( ( 1 + 10 + 1 ) * Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps ) - 1 ) ;
2014-12-01 23:55:08 +01:00
if ( LstStrCodGrps [ NumGrpTyp ] [ 0 ] )
{
/***** Count the number of groups selected of this type of LstCodGrps[NumGrpTyp] *****/
for ( Ptr = LstStrCodGrps [ NumGrpTyp ] , NumGrpWanted = 0 ;
* Ptr ;
NumGrpWanted + + )
2017-01-28 15:58:46 +01:00
Par_GetNextStrUntilSeparParamMult ( & Ptr , LongStr , 1 + 10 ) ;
2014-12-01 23:55:08 +01:00
/***** Add the number of groups selected of this type to the number of groups selected total *****/
LstGrpsWanted - > NumGrps + = NumGrpWanted ;
}
}
/***** Create the list (argument passed to this function)
with all the groups selected ( of all the types ) * * * * */
if ( LstGrpsWanted - > NumGrps )
{
2017-01-19 20:55:31 +01:00
if ( ( LstGrpsWanted - > GrpCods = ( long * ) calloc ( LstGrpsWanted - > NumGrps , sizeof ( long ) ) ) = = NULL )
2017-03-30 11:20:06 +02:00
Lay_ShowErrorAndExit ( " Not enoguh memory to store codes of groups in which a user wants to be enroled. " ) ;
2014-12-01 23:55:08 +01:00
/***** Get the groups *****/
for ( NumGrpTyp = 0 , NumGrpWanted = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
{
/* Add the groups selected of this type to the complete list of groups selected */
for ( Ptr = LstStrCodGrps [ NumGrpTyp ] ;
* Ptr ;
NumGrpWanted + + )
{
2017-01-28 15:58:46 +01:00
Par_GetNextStrUntilSeparParamMult ( & Ptr , LongStr , 1 + 10 ) ;
2017-01-19 20:55:31 +01:00
LstGrpsWanted - > GrpCods [ NumGrpWanted ] = Str_ConvertStrCodToLongCod ( LongStr ) ;
2014-12-01 23:55:08 +01:00
}
/* Free memory used by the list of group codes of this type */
free ( ( void * ) LstStrCodGrps [ NumGrpTyp ] ) ;
}
}
/***** Free memory used by the lists of group codes of each type *****/
free ( ( void * ) LstStrCodGrps ) ;
}
/*****************************************************************************/
2016-12-29 22:19:46 +01:00
/************************** Free list of group codes *************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
void Grp_FreeListCodGrp ( struct ListCodGrps * LstGrps )
{
2017-01-19 20:55:31 +01:00
if ( LstGrps - > NumGrps & & LstGrps - > GrpCods )
free ( ( void * ) LstGrps - > GrpCods ) ;
LstGrps - > GrpCods = NULL ;
2016-12-29 22:19:46 +01:00
LstGrps - > NumGrps = 0 ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********** Put parameter that indicates all groups selected ****************/
/*****************************************************************************/
void Grp_PutParamAllGroups ( void )
{
Par_PutHiddenParamChar ( " AllGroups " , ' Y ' ) ;
}
/*****************************************************************************/
/****** Parameter to show only my groups or all groups or in timetable *******/
/*****************************************************************************/
void Grp_PutParamWhichGrps ( void )
{
Grp_GetParamWhichGrps ( ) ;
Par_PutHiddenParamUnsigned ( " WhichGrps " , ( unsigned ) Gbl . CurrentCrs . Grps . WhichGrps ) ;
}
2016-12-04 20:12:56 +01:00
void Grp_PutParamWhichGrpsOnlyMyGrps ( void )
{
Par_PutHiddenParamUnsigned ( " WhichGrps " , ( unsigned ) Grp_ONLY_MY_GROUPS ) ;
}
void Grp_PutParamWhichGrpsAllGrps ( void )
{
Par_PutHiddenParamUnsigned ( " WhichGrps " , ( unsigned ) Grp_ALL_GROUPS ) ;
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2016-12-05 01:54:03 +01:00
/***** Show form to choice whether to show only my groups or all groups ******/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2016-12-04 23:09:28 +01:00
void Grp_ShowFormToSelWhichGrps ( Act_Action_t Action , void ( * FuncParams ) ( ) )
{
2017-03-21 00:57:11 +01:00
extern const char * Txt_GROUP_WHICH_GROUPS [ 2 ] ;
2016-12-04 23:09:28 +01:00
Grp_WhichGroups_t WhichGrps ;
2016-12-23 22:19:03 +01:00
fprintf ( Gbl . F . Out , " <div class= \" PREF_CONTAINER \" > " ) ;
2016-12-04 23:09:28 +01:00
for ( WhichGrps = Grp_ONLY_MY_GROUPS ;
WhichGrps < = Grp_ALL_GROUPS ;
WhichGrps + + )
{
2016-12-23 22:19:03 +01:00
fprintf ( Gbl . F . Out , " <div class= \" %s \" > " ,
2016-12-04 23:09:28 +01:00
WhichGrps = = Gbl . CurrentCrs . Grps . WhichGrps ? " PREF_ON " :
" PREF_OFF " ) ;
Act_FormStart ( Action ) ;
Par_PutHiddenParamUnsigned ( " WhichGrps " , ( unsigned ) WhichGrps ) ;
if ( FuncParams ) // Extra parameters depending on the action
FuncParams ( ) ;
fprintf ( Gbl . F . Out , " <input type= \" image \" src= \" %s/%s \" "
" alt= \" %s \" title= \" %s \" class= \" ICO25x25 \" "
" style= \" margin:0 auto; \" /> " ,
Gbl . Prefs . IconsURL ,
WhichGrps = = Grp_ONLY_MY_GROUPS ? " myhierarchy64x64.png " :
" hierarchy64x64.png " ,
2017-03-21 00:57:11 +01:00
Txt_GROUP_WHICH_GROUPS [ WhichGrps ] ,
Txt_GROUP_WHICH_GROUPS [ WhichGrps ] ) ;
2016-12-04 23:09:28 +01:00
Act_FormEnd ( ) ;
fprintf ( Gbl . F . Out , " </div> " ) ;
}
fprintf ( Gbl . F . Out , " </div> " ) ;
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2016-12-03 23:13:49 +01:00
/************* Get whether to show only my groups or all groups **************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
void Grp_GetParamWhichGrps ( void )
{
2017-04-14 00:27:38 +02:00
static bool AlreadyGot = false ;
2017-01-29 12:42:19 +01:00
Grp_WhichGroups_t WhichGroupsDefault ;
2014-12-01 23:55:08 +01:00
2017-04-14 00:27:38 +02:00
if ( ! AlreadyGot )
2014-12-01 23:55:08 +01:00
{
2016-12-03 23:13:49 +01:00
/***** Get which grous (my groups or all groups) *****/
2017-01-29 12:42:19 +01:00
/* Set default */
switch ( Gbl . Action . Act )
{
case ActSeeCrsTT :
case ActPrnCrsTT :
case ActChgCrsTT1stDay :
case ActSeeAsg :
case ActSeeAllSvy :
2017-04-27 10:15:07 +02:00
case ActSeeAtt :
2017-01-29 12:42:19 +01:00
WhichGroupsDefault = Gbl . Usrs . Me . IBelongToCurrentCrs ? Grp_ONLY_MY_GROUPS : // If I belong to this course ==> see only my groups
Grp_ALL_GROUPS ; // If I don't belong to this course ==> see all groups
break ;
case ActSeeMyTT :
case ActPrnMyTT :
case ActChgMyTT1stDay :
WhichGroupsDefault = Grp_ONLY_MY_GROUPS ; // By default, see only my groups
break ;
default : // Control never should enter here
WhichGroupsDefault = Grp_WHICH_GROUPS_DEFAULT ;
break ;
}
/* Get parameter */
Gbl . CurrentCrs . Grps . WhichGrps = ( Grp_WhichGroups_t )
2017-01-29 21:41:08 +01:00
Par_GetParToUnsignedLong ( " WhichGrps " ,
0 ,
Grp_NUM_WHICH_GROUPS - 1 ,
( unsigned long ) WhichGroupsDefault ) ;
2017-04-14 00:27:38 +02:00
AlreadyGot = true ;
2014-12-01 23:55:08 +01:00
}
}