From 5d92078a142af8e77e960595f3af5d8076b73726 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Ca=C3=B1as=20Vargas?= Date: Mon, 22 May 2017 20:37:46 +0200 Subject: [PATCH] Version 16.220.12 --- swad_changelog.h | 3 +- swad_report.c | 9 +++-- swad_role.c | 6 ++- swad_role_type.h | 2 +- swad_scope.c | 1 + swad_search.c | 4 +- swad_statistic.c | 95 ++++++++++++++++++++++++++++++++++++++++-------- swad_statistic.h | 25 +++++++------ swad_text.c | 41 +++++++++++++++++++++ swad_user.c | 79 +++++++++++++++++++++++++--------------- swad_user.h | 3 +- 11 files changed, 203 insertions(+), 65 deletions(-) diff --git a/swad_changelog.h b/swad_changelog.h index 4c6980c9..15c67c6e 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -233,13 +233,14 @@ /****************************** Public constants *****************************/ /*****************************************************************************/ -#define Log_PLATFORM_VERSION "SWAD 16.220.11 (2017-05-22)" +#define Log_PLATFORM_VERSION "SWAD 16.220.12 (2017-05-22)" #define CSS_FILE "swad16.209.3.css" #define JS_FILE "swad16.206.3.js" // Number of lines (includes comments but not blank lines) has been got with the following command: // nl swad*.c swad*.h css/swad*.css py/swad*.py js/swad*.js soap/swad*?.h sql/swad*.sql | tail -1 /* + Version 16.220.12:May 22, 2017 Changes related with new role. Not finished. (220155 lines) Version 16.220.11:May 22, 2017 Changes related with new role. Not finished. (220019 lines) Version 16.220.10:May 22, 2017 Changes related with new role. Not finished. (219775 lines) Version 16.220.9: May 22, 2017 Changes related with new role. Not finished. (219720 lines) diff --git a/swad_report.c b/swad_report.c index 08deba3d..47af0f12 100644 --- a/swad_report.c +++ b/swad_report.c @@ -927,7 +927,7 @@ static void Rep_GetMaxHitsPerYear (struct Rep_Report *Report) " GROUP BY Year" // ---------------------------------------------------------- " UNION " - // Clicks as student or teacher in courses ------------------ + // Clicks as student, non-editing teacher or teacher in courses "SELECT " "CrsCod," "YEAR(CONVERT_TZ(ClickTime,@@session.time_zone,'UTC')) AS Year," @@ -1171,8 +1171,11 @@ static void Rep_WriteRowCrsData (long CrsCod,Rol_Role_t Role, /***** Write number of teachers / students in course *****/ if (WriteNumUsrs) fprintf (Gbl.F.Rep," (%u %s / %u %s)", - Usr_GetNumUsrsInCrs (Rol_TCH,Crs.CrsCod),Txt_teachers_ABBREVIATION, - Usr_GetNumUsrsInCrs (Rol_STD,Crs.CrsCod),Txt_students_ABBREVIATION); + Usr_GetNumUsrsInCrs (Rol_NET,Crs.CrsCod) + + Usr_GetNumUsrsInCrs (Rol_TCH,Crs.CrsCod), + Txt_teachers_ABBREVIATION, + Usr_GetNumUsrsInCrs (Rol_STD,Crs.CrsCod), + Txt_students_ABBREVIATION); } else fprintf (Gbl.F.Rep,"(%s)",Txt_unknown_removed_course); diff --git a/swad_role.c b/swad_role.c index f6661a66..237521ea 100644 --- a/swad_role.c +++ b/swad_role.c @@ -86,7 +86,11 @@ Rol_Role_t Rol_GetMaxRoleInCrss (unsigned Roles) if (Roles & (1 << Rol_TCH)) return Rol_TCH; - /* Not a teacher. Check then if user is a student in any course */ + /* Not a teacher. Check then if user is a non-editing teacher in any course */ + if (Roles & (1 << Rol_NET)) + return Rol_NET; + + /* Not a non-editing teacher or a teacher. Check then if user is a student in any course */ if (Roles & (1 << Rol_STD)) return Rol_STD; diff --git a/swad_role_type.h b/swad_role_type.h index 65dc268c..81d776f9 100644 --- a/swad_role_type.h +++ b/swad_role_type.h @@ -36,7 +36,7 @@ Don't change these numbers! They are used for users' permissions and for user's types in database - Only Rol_STD and Rol_TCH are allowed + Only Rol_STD, Rol_NET and Rol_TCH are allowed as user permanent roles in courses, but a user may be logged temporarily as other roles */ diff --git a/swad_scope.c b/swad_scope.c index 2333ab73..be96a7cf 100644 --- a/swad_scope.c +++ b/swad_scope.c @@ -274,6 +274,7 @@ void Sco_SetScopesForListingStudents (void) switch (Gbl.Usrs.Me.LoggedRole) { case Rol_STD: + case Rol_NET: case Rol_TCH: Gbl.Scope.Allowed = 1 << Sco_SCOPE_CRS; break; diff --git a/swad_search.c b/swad_search.c index 31740493..268ec2d0 100644 --- a/swad_search.c +++ b/swad_search.c @@ -595,7 +595,7 @@ static void Sch_SearchInDB (void) NumResults += Sch_SearchCentresInDB (RangeQuery); NumResults += Sch_SearchDegreesInDB (RangeQuery); NumResults += Sch_SearchCoursesInDB (RangeQuery); - NumResults += Sch_SearchUsrsInDB (Rol_TCH); + NumResults += Sch_SearchUsrsInDB (Rol_TCH); // Non-editing teachers and teachers NumResults += Sch_SearchUsrsInDB (Rol_STD); NumResults += Sch_SearchUsrsInDB (Rol_GST); NumResults += Sch_SearchOpenDocumentsInDB (RangeQuery); @@ -621,7 +621,7 @@ static void Sch_SearchInDB (void) NumResults = Sch_SearchUsrsInDB (Rol_UNK); // Here Rol_UNK means any user break; case Sch_SEARCH_TEACHERS: - NumResults = Sch_SearchUsrsInDB (Rol_TCH); + NumResults = Sch_SearchUsrsInDB (Rol_TCH); // Non-editing teachers and teachers break; case Sch_SEARCH_STUDENTS: NumResults = Sch_SearchUsrsInDB (Rol_STD); diff --git a/swad_statistic.c b/swad_statistic.c index fb9ac286..a52f0663 100644 --- a/swad_statistic.c +++ b/swad_statistic.c @@ -133,10 +133,8 @@ static void Sta_WriteSelectorAction (void); static void Sta_ShowHits (Sta_GlobalOrCourseAccesses_t GlobalOrCourse); static void Sta_ShowDetailedAccessesList (unsigned long NumRows,MYSQL_RES *mysql_res); static void Sta_WriteLogComments (long LogCod); -static void Sta_ShowNumHitsPerUsr (unsigned long NumRows, - MYSQL_RES *mysql_res); -static void Sta_ShowNumHitsPerDays (unsigned long NumRows, - MYSQL_RES *mysql_res); +static void Sta_ShowNumHitsPerUsr (unsigned long NumRows,MYSQL_RES *mysql_res); +static void Sta_ShowNumHitsPerDays (unsigned long NumRows,MYSQL_RES *mysql_res); static void Sta_ShowDistrAccessesPerDaysAndHour (unsigned long NumRows,MYSQL_RES *mysql_res); static Sta_ColorType_t Sta_GetStatColorType (void); static void Sta_DrawBarColors (Sta_ColorType_t ColorType,float HitsMax); @@ -463,10 +461,12 @@ void Sta_AskShowCrsHits (void) Grp_GetParCodsSeveralGrpsToShowUsrs (); /***** Get and order the lists of users of this course *****/ - Usr_GetListUsrs (Rol_TCH,Sco_SCOPE_CRS); Usr_GetListUsrs (Rol_STD,Sco_SCOPE_CRS); - NumTotalUsrs = Gbl.Usrs.LstUsrs[Rol_TCH].NumUsrs + - Gbl.Usrs.LstUsrs[Rol_STD].NumUsrs; + Usr_GetListUsrs (Rol_NET,Sco_SCOPE_CRS); + Usr_GetListUsrs (Rol_TCH,Sco_SCOPE_CRS); + NumTotalUsrs = Gbl.Usrs.LstUsrs[Rol_STD].NumUsrs + + Gbl.Usrs.LstUsrs[Rol_NET].NumUsrs + + Gbl.Usrs.LstUsrs[Rol_TCH].NumUsrs; /***** Start frame *****/ sprintf (Gbl.Title,Txt_Statistics_of_visits_to_the_course_X, @@ -503,6 +503,7 @@ void Sta_AskShowCrsHits (void) The_ClassForm[Gbl.Prefs.Theme],Txt_Users, The_ClassForm[Gbl.Prefs.Theme]); Usr_ListUsersToSelect (Rol_TCH); + Usr_ListUsersToSelect (Rol_NET); Usr_ListUsersToSelect (Rol_STD); fprintf (Gbl.F.Out,"" "" @@ -608,6 +609,7 @@ void Sta_AskShowCrsHits (void) /***** Free memory used by the lists *****/ Usr_FreeUsrsList (Rol_TCH); + Usr_FreeUsrsList (Rol_NET); Usr_FreeUsrsList (Rol_STD); /***** Free memory for list of selected groups *****/ @@ -1248,6 +1250,10 @@ static void Sta_ShowHits (Sta_GlobalOrCourseAccesses_t GlobalOrCourse) sprintf (StrRole," AND %s.Role=%u", LogTable,(unsigned) Rol_TCH); break; + case Sta_NON_EDITING_TEACHERS: + sprintf (StrRole," AND %s.Role=%u", + LogTable,(unsigned) Rol_NET); + break; case Sta_STUDENTS: sprintf (StrRole," AND %s.Role=%u", LogTable,(unsigned) Rol_STD); @@ -1833,8 +1839,7 @@ static void Sta_WriteLogComments (long LogCod) /********* Show a listing of with the number of clicks of each user **********/ /*****************************************************************************/ -static void Sta_ShowNumHitsPerUsr (unsigned long NumRows, - MYSQL_RES *mysql_res) +static void Sta_ShowNumHitsPerUsr (unsigned long NumRows,MYSQL_RES *mysql_res) { extern const char *Txt_No_INDEX; extern const char *Txt_Photo; @@ -1949,8 +1954,8 @@ static void Sta_ShowNumHitsPerUsr (unsigned long NumRows, " style=\"width:%upx; height:18px;\" />" " ", Gbl.Prefs.IconsURL, - UsrDat.RoleInCurrentCrsDB == Rol_STD ? 'c' : - 'v', + UsrDat.RoleInCurrentCrsDB == Rol_STD ? 'c' : // Student + 'v', // Non-editing teacher or teacher BarWidth); Str_WriteFloatNum (Gbl.F.Out,Hits.Num); fprintf (Gbl.F.Out," " @@ -1965,8 +1970,7 @@ static void Sta_ShowNumHitsPerUsr (unsigned long NumRows, /********** Show a listing of with the number of clicks in each date *********/ /*****************************************************************************/ -static void Sta_ShowNumHitsPerDays (unsigned long NumRows, - MYSQL_RES *mysql_res) +static void Sta_ShowNumHitsPerDays (unsigned long NumRows,MYSQL_RES *mysql_res) { extern const char *Txt_Date; extern const char *Txt_Day; @@ -4070,8 +4074,9 @@ static void Sta_GetAndShowUsersStats (void) Txt_Average_number_of_courses_to_which_a_user_belongs, Txt_Average_number_of_users_belonging_to_a_course); Usr_GetAndShowNumUsrsInPlatform (Rol_STD); // Students + Usr_GetAndShowNumUsrsInPlatform (Rol_NET); // Non-editing teachers Usr_GetAndShowNumUsrsInPlatform (Rol_TCH); // Teachers - Usr_GetAndShowNumUsrsInPlatform (Rol_UNK); // Students and teachers + Usr_GetAndShowNumUsrsInPlatform (Rol_UNK); // Students, non-editing teachers and teachers fprintf (Gbl.F.Out,"" "" ""); @@ -4186,6 +4191,7 @@ static void Sta_WriteHeadDegsCrssInSWAD (void) extern const char *Txt_With_degrees; extern const char *Txt_With_courses; extern const char *Txt_With_teachers; + extern const char *Txt_With_non_editing_teachers; extern const char *Txt_With_students; fprintf (Gbl.F.Out,"" @@ -4211,6 +4217,9 @@ static void Sta_WriteHeadDegsCrssInSWAD (void) "" "%s" "" + "" + "%s" + "" "", Txt_Total, Txt_With_institutions, @@ -4218,6 +4227,7 @@ static void Sta_WriteHeadDegsCrssInSWAD (void) Txt_With_degrees, Txt_With_courses, Txt_With_teachers, + Txt_With_non_editing_teachers, Txt_With_students); } @@ -4235,6 +4245,7 @@ static void Sta_GetAndShowNumCtysInSWAD (void) unsigned NumCtysWithDegs = 0; unsigned NumCtysWithCrss = 0; unsigned NumCtysWithTchs = 0; + unsigned NumCtysWithNETs = 0; unsigned NumCtysWithStds = 0; /***** Get number of countries *****/ @@ -4247,6 +4258,7 @@ static void Sta_GetAndShowNumCtysInSWAD (void) NumCtysWithDegs = Cty_GetNumCtysWithDegs (""); NumCtysWithCrss = Cty_GetNumCtysWithCrss (""); NumCtysWithTchs = Cty_GetNumCtysWithUsrs (Rol_TCH,""); + NumCtysWithNETs = Cty_GetNumCtysWithUsrs (Rol_NET,""); NumCtysWithStds = Cty_GetNumCtysWithUsrs (Rol_STD,""); SubQuery[0] = '\0'; break; @@ -4259,6 +4271,7 @@ static void Sta_GetAndShowNumCtysInSWAD (void) NumCtysWithDegs = Cty_GetNumCtysWithDegs (SubQuery); NumCtysWithCrss = Cty_GetNumCtysWithCrss (SubQuery); NumCtysWithTchs = Cty_GetNumCtysWithUsrs (Rol_TCH,SubQuery); + NumCtysWithNETs = Cty_GetNumCtysWithUsrs (Rol_NET,SubQuery); NumCtysWithStds = Cty_GetNumCtysWithUsrs (Rol_STD,SubQuery); break; case Sco_SCOPE_INS: @@ -4270,6 +4283,7 @@ static void Sta_GetAndShowNumCtysInSWAD (void) NumCtysWithDegs = Cty_GetNumCtysWithDegs (SubQuery); NumCtysWithCrss = Cty_GetNumCtysWithCrss (SubQuery); NumCtysWithTchs = Cty_GetNumCtysWithUsrs (Rol_TCH,SubQuery); + NumCtysWithNETs = Cty_GetNumCtysWithUsrs (Rol_NET,SubQuery); NumCtysWithStds = Cty_GetNumCtysWithUsrs (Rol_STD,SubQuery); break; case Sco_SCOPE_CTR: @@ -4281,6 +4295,7 @@ static void Sta_GetAndShowNumCtysInSWAD (void) NumCtysWithDegs = Cty_GetNumCtysWithDegs (SubQuery); NumCtysWithCrss = Cty_GetNumCtysWithCrss (SubQuery); NumCtysWithTchs = Cty_GetNumCtysWithUsrs (Rol_TCH,SubQuery); + NumCtysWithNETs = Cty_GetNumCtysWithUsrs (Rol_NET,SubQuery); NumCtysWithStds = Cty_GetNumCtysWithUsrs (Rol_STD,SubQuery); break; case Sco_SCOPE_DEG: @@ -4292,6 +4307,7 @@ static void Sta_GetAndShowNumCtysInSWAD (void) Gbl.CurrentDeg.Deg.DegCod); NumCtysWithCrss = Cty_GetNumCtysWithCrss (SubQuery); NumCtysWithTchs = Cty_GetNumCtysWithUsrs (Rol_TCH,SubQuery); + NumCtysWithNETs = Cty_GetNumCtysWithUsrs (Rol_NET,SubQuery); NumCtysWithStds = Cty_GetNumCtysWithUsrs (Rol_STD,SubQuery); break; case Sco_SCOPE_CRS: @@ -4303,6 +4319,7 @@ static void Sta_GetAndShowNumCtysInSWAD (void) sprintf (SubQuery,"crs_usr.CrsCod=%ld AND ", Gbl.CurrentCrs.Crs.CrsCod); NumCtysWithTchs = Cty_GetNumCtysWithUsrs (Rol_TCH,SubQuery); + NumCtysWithNETs = Cty_GetNumCtysWithUsrs (Rol_NET,SubQuery); NumCtysWithStds = Cty_GetNumCtysWithUsrs (Rol_STD,SubQuery); break; default: @@ -4339,6 +4356,9 @@ static void Sta_GetAndShowNumCtysInSWAD (void) "" "%u" "" + "" + "%u" + "" "", Gbl.Prefs.IconsURL, Txt_Countries, @@ -4350,6 +4370,7 @@ static void Sta_GetAndShowNumCtysInSWAD (void) NumCtysWithDegs, NumCtysWithCrss, NumCtysWithTchs, + NumCtysWithNETs, NumCtysWithStds); } @@ -4366,6 +4387,7 @@ static void Sta_GetAndShowNumInssInSWAD (void) unsigned NumInssWithDegs = 0; unsigned NumInssWithCrss = 0; unsigned NumInssWithTchs = 0; + unsigned NumInssWithNETs = 0; unsigned NumInssWithStds = 0; /***** Get number of institutions *****/ @@ -4377,6 +4399,7 @@ static void Sta_GetAndShowNumInssInSWAD (void) NumInssWithDegs = Ins_GetNumInssWithDegs (""); NumInssWithCrss = Ins_GetNumInssWithCrss (""); NumInssWithTchs = Ins_GetNumInssWithUsrs (Rol_TCH,""); + NumInssWithNETs = Ins_GetNumInssWithUsrs (Rol_NET,""); NumInssWithStds = Ins_GetNumInssWithUsrs (Rol_STD,""); SubQuery[0] = '\0'; break; @@ -4388,6 +4411,7 @@ static void Sta_GetAndShowNumInssInSWAD (void) NumInssWithDegs = Ins_GetNumInssWithDegs (SubQuery); NumInssWithCrss = Ins_GetNumInssWithCrss (SubQuery); NumInssWithTchs = Ins_GetNumInssWithUsrs (Rol_TCH,SubQuery); + NumInssWithNETs = Ins_GetNumInssWithUsrs (Rol_NET,SubQuery); NumInssWithStds = Ins_GetNumInssWithUsrs (Rol_STD,SubQuery); break; case Sco_SCOPE_INS: @@ -4398,6 +4422,7 @@ static void Sta_GetAndShowNumInssInSWAD (void) NumInssWithDegs = Ins_GetNumInssWithDegs (SubQuery); NumInssWithCrss = Ins_GetNumInssWithCrss (SubQuery); NumInssWithTchs = Ins_GetNumInssWithUsrs (Rol_TCH,SubQuery); + NumInssWithNETs = Ins_GetNumInssWithUsrs (Rol_NET,SubQuery); NumInssWithStds = Ins_GetNumInssWithUsrs (Rol_STD,SubQuery); break; case Sco_SCOPE_CTR: @@ -4408,6 +4433,7 @@ static void Sta_GetAndShowNumInssInSWAD (void) NumInssWithDegs = Ins_GetNumInssWithDegs (SubQuery); NumInssWithCrss = Ins_GetNumInssWithCrss (SubQuery); NumInssWithTchs = Ins_GetNumInssWithUsrs (Rol_TCH,SubQuery); + NumInssWithNETs = Ins_GetNumInssWithUsrs (Rol_NET,SubQuery); NumInssWithStds = Ins_GetNumInssWithUsrs (Rol_STD,SubQuery); break; case Sco_SCOPE_DEG: @@ -4418,6 +4444,7 @@ static void Sta_GetAndShowNumInssInSWAD (void) Gbl.CurrentDeg.Deg.DegCod); NumInssWithCrss = Ins_GetNumInssWithCrss (SubQuery); NumInssWithTchs = Ins_GetNumInssWithUsrs (Rol_TCH,SubQuery); + NumInssWithNETs = Ins_GetNumInssWithUsrs (Rol_NET,SubQuery); NumInssWithStds = Ins_GetNumInssWithUsrs (Rol_STD,SubQuery); break; case Sco_SCOPE_CRS: @@ -4428,6 +4455,7 @@ static void Sta_GetAndShowNumInssInSWAD (void) sprintf (SubQuery,"crs_usr.CrsCod=%ld AND ", Gbl.CurrentCrs.Crs.CrsCod); NumInssWithTchs = Ins_GetNumInssWithUsrs (Rol_TCH,SubQuery); + NumInssWithNETs = Ins_GetNumInssWithUsrs (Rol_NET,SubQuery); NumInssWithStds = Ins_GetNumInssWithUsrs (Rol_STD,SubQuery); break; default: @@ -4462,6 +4490,9 @@ static void Sta_GetAndShowNumInssInSWAD (void) "" "%u" "" + "" + "%u" + "" "", Gbl.Prefs.IconsURL, Txt_Institutions, @@ -4472,6 +4503,7 @@ static void Sta_GetAndShowNumInssInSWAD (void) NumInssWithDegs, NumInssWithCrss, NumInssWithTchs, + NumInssWithNETs, NumInssWithStds); } @@ -4487,6 +4519,7 @@ static void Sta_GetAndShowNumCtrsInSWAD (void) unsigned NumCtrsWithDegs = 0; unsigned NumCtrsWithCrss = 0; unsigned NumCtrsWithTchs = 0; + unsigned NumCtrsWithNETs = 0; unsigned NumCtrsWithStds = 0; /***** Get number of centres *****/ @@ -4497,6 +4530,7 @@ static void Sta_GetAndShowNumCtrsInSWAD (void) NumCtrsWithDegs = Ctr_GetNumCtrsWithDegs (""); NumCtrsWithCrss = Ctr_GetNumCtrsWithCrss (""); NumCtrsWithTchs = Ctr_GetNumCtrsWithUsrs (Rol_TCH,""); + NumCtrsWithNETs = Ctr_GetNumCtrsWithUsrs (Rol_NET,""); NumCtrsWithStds = Ctr_GetNumCtrsWithUsrs (Rol_STD,""); SubQuery[0] = '\0'; break; @@ -4507,6 +4541,7 @@ static void Sta_GetAndShowNumCtrsInSWAD (void) NumCtrsWithDegs = Ctr_GetNumCtrsWithDegs (SubQuery); NumCtrsWithCrss = Ctr_GetNumCtrsWithCrss (SubQuery); NumCtrsWithTchs = Ctr_GetNumCtrsWithUsrs (Rol_TCH,SubQuery); + NumCtrsWithNETs = Ctr_GetNumCtrsWithUsrs (Rol_NET,SubQuery); NumCtrsWithStds = Ctr_GetNumCtrsWithUsrs (Rol_STD,SubQuery); break; case Sco_SCOPE_INS: @@ -4516,6 +4551,7 @@ static void Sta_GetAndShowNumCtrsInSWAD (void) NumCtrsWithDegs = Ctr_GetNumCtrsWithDegs (SubQuery); NumCtrsWithCrss = Ctr_GetNumCtrsWithCrss (SubQuery); NumCtrsWithTchs = Ctr_GetNumCtrsWithUsrs (Rol_TCH,SubQuery); + NumCtrsWithNETs = Ctr_GetNumCtrsWithUsrs (Rol_NET,SubQuery); NumCtrsWithStds = Ctr_GetNumCtrsWithUsrs (Rol_STD,SubQuery); break; case Sco_SCOPE_CTR: @@ -4525,6 +4561,7 @@ static void Sta_GetAndShowNumCtrsInSWAD (void) NumCtrsWithDegs = Ctr_GetNumCtrsWithDegs (SubQuery); NumCtrsWithCrss = Ctr_GetNumCtrsWithCrss (SubQuery); NumCtrsWithTchs = Ctr_GetNumCtrsWithUsrs (Rol_TCH,SubQuery); + NumCtrsWithNETs = Ctr_GetNumCtrsWithUsrs (Rol_NET,SubQuery); NumCtrsWithStds = Ctr_GetNumCtrsWithUsrs (Rol_STD,SubQuery); break; case Sco_SCOPE_DEG: @@ -4534,6 +4571,7 @@ static void Sta_GetAndShowNumCtrsInSWAD (void) Gbl.CurrentDeg.Deg.DegCod); NumCtrsWithCrss = Ctr_GetNumCtrsWithCrss (SubQuery); NumCtrsWithTchs = Ctr_GetNumCtrsWithUsrs (Rol_TCH,SubQuery); + NumCtrsWithNETs = Ctr_GetNumCtrsWithUsrs (Rol_NET,SubQuery); NumCtrsWithStds = Ctr_GetNumCtrsWithUsrs (Rol_STD,SubQuery); break; case Sco_SCOPE_CRS: @@ -4543,6 +4581,7 @@ static void Sta_GetAndShowNumCtrsInSWAD (void) sprintf (SubQuery,"crs_usr.CrsCod=%ld AND ", Gbl.CurrentCrs.Crs.CrsCod); NumCtrsWithTchs = Ctr_GetNumCtrsWithUsrs (Rol_TCH,SubQuery); + NumCtrsWithNETs = Ctr_GetNumCtrsWithUsrs (Rol_NET,SubQuery); NumCtrsWithStds = Ctr_GetNumCtrsWithUsrs (Rol_STD,SubQuery); break; default: @@ -4575,6 +4614,9 @@ static void Sta_GetAndShowNumCtrsInSWAD (void) "" "%u" "" + "" + "%u" + "" "", Gbl.Prefs.IconsURL, Txt_Centres, @@ -4584,6 +4626,7 @@ static void Sta_GetAndShowNumCtrsInSWAD (void) NumCtrsWithDegs, NumCtrsWithCrss, NumCtrsWithTchs, + NumCtrsWithNETs, NumCtrsWithStds); } @@ -4598,6 +4641,7 @@ static void Sta_GetAndShowNumDegsInSWAD (void) unsigned NumDegsTotal = 0; unsigned NumDegsWithCrss = 0; unsigned NumDegsWithTchs = 0; + unsigned NumDegsWithNETs = 0; unsigned NumDegsWithStds = 0; /***** Get number of degrees *****/ @@ -4607,6 +4651,7 @@ static void Sta_GetAndShowNumDegsInSWAD (void) NumDegsTotal = Deg_GetNumDegsTotal (); NumDegsWithCrss = Deg_GetNumDegsWithCrss (""); NumDegsWithTchs = Deg_GetNumDegsWithUsrs (Rol_TCH,""); + NumDegsWithNETs = Deg_GetNumDegsWithUsrs (Rol_NET,""); NumDegsWithStds = Deg_GetNumDegsWithUsrs (Rol_STD,""); SubQuery[0] = '\0'; break; @@ -4616,6 +4661,7 @@ static void Sta_GetAndShowNumDegsInSWAD (void) Gbl.CurrentCty.Cty.CtyCod); NumDegsWithCrss = Deg_GetNumDegsWithCrss (SubQuery); NumDegsWithTchs = Deg_GetNumDegsWithUsrs (Rol_TCH,SubQuery); + NumDegsWithNETs = Deg_GetNumDegsWithUsrs (Rol_NET,SubQuery); NumDegsWithStds = Deg_GetNumDegsWithUsrs (Rol_STD,SubQuery); break; case Sco_SCOPE_INS: @@ -4624,6 +4670,7 @@ static void Sta_GetAndShowNumDegsInSWAD (void) Gbl.CurrentIns.Ins.InsCod); NumDegsWithCrss = Deg_GetNumDegsWithCrss (SubQuery); NumDegsWithTchs = Deg_GetNumDegsWithUsrs (Rol_TCH,SubQuery); + NumDegsWithNETs = Deg_GetNumDegsWithUsrs (Rol_NET,SubQuery); NumDegsWithStds = Deg_GetNumDegsWithUsrs (Rol_STD,SubQuery); break; case Sco_SCOPE_CTR: @@ -4632,6 +4679,7 @@ static void Sta_GetAndShowNumDegsInSWAD (void) Gbl.CurrentCtr.Ctr.CtrCod); NumDegsWithCrss = Deg_GetNumDegsWithCrss (SubQuery); NumDegsWithTchs = Deg_GetNumDegsWithUsrs (Rol_TCH,SubQuery); + NumDegsWithNETs = Deg_GetNumDegsWithUsrs (Rol_NET,SubQuery); NumDegsWithStds = Deg_GetNumDegsWithUsrs (Rol_STD,SubQuery); break; case Sco_SCOPE_DEG: @@ -4640,6 +4688,7 @@ static void Sta_GetAndShowNumDegsInSWAD (void) Gbl.CurrentDeg.Deg.DegCod); NumDegsWithCrss = Deg_GetNumDegsWithCrss (SubQuery); NumDegsWithTchs = Deg_GetNumDegsWithUsrs (Rol_TCH,SubQuery); + NumDegsWithNETs = Deg_GetNumDegsWithUsrs (Rol_NET,SubQuery); NumDegsWithStds = Deg_GetNumDegsWithUsrs (Rol_STD,SubQuery); break; case Sco_SCOPE_CRS: @@ -4648,6 +4697,7 @@ static void Sta_GetAndShowNumDegsInSWAD (void) sprintf (SubQuery,"crs_usr.CrsCod=%ld AND ", Gbl.CurrentCrs.Crs.CrsCod); NumDegsWithTchs = Deg_GetNumDegsWithUsrs (Rol_TCH,SubQuery); + NumDegsWithNETs = Deg_GetNumDegsWithUsrs (Rol_NET,SubQuery); NumDegsWithStds = Deg_GetNumDegsWithUsrs (Rol_STD,SubQuery); break; default: @@ -4678,6 +4728,9 @@ static void Sta_GetAndShowNumDegsInSWAD (void) "" "%u" "" + "" + "%u" + "" "", Gbl.Prefs.IconsURL, Txt_Degrees, @@ -4686,6 +4739,7 @@ static void Sta_GetAndShowNumDegsInSWAD (void) NumDegsTotal, NumDegsWithCrss, NumDegsWithTchs, + NumDegsWithNETs, NumDegsWithStds); } @@ -4699,6 +4753,7 @@ static void Sta_GetAndShowNumCrssInSWAD (void) char SubQuery[128]; unsigned NumCrssTotal = 0; unsigned NumCrssWithTchs = 0; + unsigned NumCrssWithNETs = 0; unsigned NumCrssWithStds = 0; /***** Get number of courses *****/ @@ -4707,6 +4762,7 @@ static void Sta_GetAndShowNumCrssInSWAD (void) case Sco_SCOPE_SYS: NumCrssTotal = Crs_GetNumCrssTotal (); NumCrssWithTchs = Crs_GetNumCrssWithUsrs (Rol_TCH,""); + NumCrssWithNETs = Crs_GetNumCrssWithUsrs (Rol_NET,""); NumCrssWithStds = Crs_GetNumCrssWithUsrs (Rol_STD,""); SubQuery[0] = '\0'; break; @@ -4715,6 +4771,7 @@ static void Sta_GetAndShowNumCrssInSWAD (void) sprintf (SubQuery,"institutions.CtyCod=%ld AND ", Gbl.CurrentCty.Cty.CtyCod); NumCrssWithTchs = Crs_GetNumCrssWithUsrs (Rol_TCH,SubQuery); + NumCrssWithNETs = Crs_GetNumCrssWithUsrs (Rol_NET,SubQuery); NumCrssWithStds = Crs_GetNumCrssWithUsrs (Rol_STD,SubQuery); break; case Sco_SCOPE_INS: @@ -4722,6 +4779,7 @@ static void Sta_GetAndShowNumCrssInSWAD (void) sprintf (SubQuery,"centres.InsCod=%ld AND ", Gbl.CurrentIns.Ins.InsCod); NumCrssWithTchs = Crs_GetNumCrssWithUsrs (Rol_TCH,SubQuery); + NumCrssWithNETs = Crs_GetNumCrssWithUsrs (Rol_NET,SubQuery); NumCrssWithStds = Crs_GetNumCrssWithUsrs (Rol_STD,SubQuery); break; case Sco_SCOPE_CTR: @@ -4729,6 +4787,7 @@ static void Sta_GetAndShowNumCrssInSWAD (void) sprintf (SubQuery,"degrees.CtrCod=%ld AND ", Gbl.CurrentCtr.Ctr.CtrCod); NumCrssWithTchs = Crs_GetNumCrssWithUsrs (Rol_TCH,SubQuery); + NumCrssWithNETs = Crs_GetNumCrssWithUsrs (Rol_NET,SubQuery); NumCrssWithStds = Crs_GetNumCrssWithUsrs (Rol_STD,SubQuery); break; case Sco_SCOPE_DEG: @@ -4736,6 +4795,7 @@ static void Sta_GetAndShowNumCrssInSWAD (void) sprintf (SubQuery,"courses.DegCod=%ld AND ", Gbl.CurrentDeg.Deg.DegCod); NumCrssWithTchs = Crs_GetNumCrssWithUsrs (Rol_TCH,SubQuery); + NumCrssWithNETs = Crs_GetNumCrssWithUsrs (Rol_NET,SubQuery); NumCrssWithStds = Crs_GetNumCrssWithUsrs (Rol_STD,SubQuery); break; case Sco_SCOPE_CRS: @@ -4743,6 +4803,7 @@ static void Sta_GetAndShowNumCrssInSWAD (void) sprintf (SubQuery,"crs_usr.CrsCod=%ld AND ", Gbl.CurrentCrs.Crs.CrsCod); NumCrssWithTchs = Crs_GetNumCrssWithUsrs (Rol_TCH,SubQuery); + NumCrssWithNETs = Crs_GetNumCrssWithUsrs (Rol_NET,SubQuery); NumCrssWithStds = Crs_GetNumCrssWithUsrs (Rol_STD,SubQuery); break; default: @@ -4771,6 +4832,9 @@ static void Sta_GetAndShowNumCrssInSWAD (void) "" "%u" "" + "" + "%u" + "" "", Gbl.Prefs.IconsURL, Txt_Courses, @@ -4778,6 +4842,7 @@ static void Sta_GetAndShowNumCrssInSWAD (void) Txt_Courses, NumCrssTotal, NumCrssWithTchs, + NumCrssWithNETs, NumCrssWithStds); } @@ -5271,7 +5336,7 @@ static unsigned Sta_GetTotalNumberOfUsersInPlatform (void) /*****************************************************************************/ /******************* Get total number of users in courses ********************/ /*****************************************************************************/ -// Here Rol_UNK means "students or teachers" +// Here Rol_UNK means "students, non-editing teachers or teachers" unsigned Sta_GetTotalNumberOfUsersInCourses (Sco_Scope_t Scope,Rol_Role_t Role) { diff --git a/swad_statistic.h b/swad_statistic.h index b789c6e1..41b947a9 100644 --- a/swad_statistic.h +++ b/swad_statistic.h @@ -33,20 +33,21 @@ /************************** Public types and constants ***********************/ /*****************************************************************************/ -#define Sta_NUM_ROLES_STAT 11 +#define Sta_NUM_ROLES_STAT 12 typedef enum { - Sta_IDENTIFIED_USRS = 0, - Sta_ALL_USRS = 1, - Sta_INS_ADMINS = 2, - Sta_CTR_ADMINS = 3, - Sta_DEG_ADMINS = 4, - Sta_TEACHERS = 5, - Sta_STUDENTS = 6, - Sta_VISITORS = 7, - Sta_GUESTS = 8, - Sta_UNKNOWN_USRS = 9, - Sta_ME = 10, + Sta_IDENTIFIED_USRS = 0, + Sta_ALL_USRS = 1, + Sta_INS_ADMINS = 2, + Sta_CTR_ADMINS = 3, + Sta_DEG_ADMINS = 4, + Sta_TEACHERS = 5, + Sta_NON_EDITING_TEACHERS = 6, + Sta_STUDENTS = 7, + Sta_VISITORS = 8, + Sta_GUESTS = 9, + Sta_UNKNOWN_USRS = 10, + Sta_ME = 11, } Sta_Role_t; #define Sta_ROLE_DEFAULT Sta_IDENTIFIED_USRS diff --git a/swad_text.c b/swad_text.c index 6d4e3d93..ee1ddd7f 100644 --- a/swad_text.c +++ b/swad_text.c @@ -32007,6 +32007,26 @@ const char *Txt_ROLE_STATS[Sta_NUM_ROLES_STAT] = "nauczycieli" #elif L==9 "professores" +#endif + , // Sta_NON_EDITING_TEACHERS +#if L==1 + "professors no editors" +#elif L==2 + "nicht bearbeiteter Lehrkraft" +#elif L==3 + "non-editing teachers" +#elif L==4 + "profesores no editores" +#elif L==5 + "enseignants non-éditeurs" +#elif L==6 + "mbo'ehára no editores" // Okoteve traducción +#elif L==7 + "professori non-editing" +#elif L==8 + "nauczyciele nie edytujący" +#elif L==9 + "professores não editores" #endif , // Sta_STUDENTS #if L==1 @@ -51423,6 +51443,27 @@ const char *Txt_with_new_posts = "com novas posts"; #endif +const char *Txt_With_non_editing_teachers = +#if L==1 + "Amb professors no editors"; +#elif L==2 + "Mit nicht bearbeiteter Lehrkräften"; +#elif L==3 + "With non-editing teachers"; +#elif L==4 + "Con profesores no editores"; +#elif L==5 + "Avec enseignants non-éditeurs"; +#elif L==6 + "Con profesores no editores"; // Okoteve traducción +#elif L==7 + "Con professori non-editing"; +#elif L==8 + "Z nauczycielami nie edytujący"; +#elif L==9 + "Com professores não editores"; +#endif + const char *Txt_With_students = #if L==1 "Amb estudiants"; diff --git a/swad_user.c b/swad_user.c index 2227d78c..d6ea2056 100644 --- a/swad_user.c +++ b/swad_user.c @@ -961,12 +961,12 @@ unsigned Usr_GetNumUsrsInCrssOfAUsr (long UsrCod,Rol_Role_t UsrRole, switch (UsrRole) { case Rol_STD: // Student - sprintf (SubQueryRole,"Role=%u", + sprintf (SubQueryRole," AND Role=%u", (unsigned) Rol_STD); break; case Rol_NET: // Non-editing teacher case Rol_TCH: // or teacher - sprintf (SubQueryRole,"(Role=%u OR Role=%u)", + sprintf (SubQueryRole," AND (Role=%u OR Role=%u)", (unsigned) Rol_NET,(unsigned) Rol_TCH); break; default: @@ -978,7 +978,8 @@ unsigned Usr_GetNumUsrsInCrssOfAUsr (long UsrCod,Rol_Role_t UsrRole, " (CrsCod INT NOT NULL,UNIQUE INDEX (CrsCod))" " ENGINE=MEMORY" " SELECT CrsCod FROM crs_usr" - " WHERE UsrCod=%ld AND %s", + " WHERE UsrCod=%ld" + "%s", UsrCod,SubQueryRole); if (mysql_query (&Gbl.mysql,Query)) DB_ExitOnMySQLError ("can not create temporary table"); @@ -987,12 +988,12 @@ unsigned Usr_GetNumUsrsInCrssOfAUsr (long UsrCod,Rol_Role_t UsrRole, switch (OthersRole) { case Rol_STD: // Student - sprintf (SubQueryRole,"crs_usr.Role=%u", + sprintf (SubQueryRole," AND crs_usr.Role=%u", (unsigned) Rol_STD); break; case Rol_NET: // Non-editing teacher case Rol_TCH: // or teacher - sprintf (SubQueryRole,"(crs_usr.Role=%u OR crs_usr.Role=%u)", + sprintf (SubQueryRole," AND (crs_usr.Role=%u OR crs_usr.Role=%u)", (unsigned) Rol_NET,(unsigned) Rol_TCH); break; default: @@ -1002,7 +1003,8 @@ unsigned Usr_GetNumUsrsInCrssOfAUsr (long UsrCod,Rol_Role_t UsrRole, } sprintf (Query,"SELECT COUNT(DISTINCT crs_usr.UsrCod)" " FROM crs_usr,usr_courses_tmp" - " WHERE crs_usr.CrsCod=usr_courses_tmp.CrsCod AND %s", + " WHERE crs_usr.CrsCod=usr_courses_tmp.CrsCod" + "%s", SubQueryRole); NumUsrs = (unsigned) DB_QueryCOUNT (Query,"can not get the number of users"); @@ -4300,6 +4302,7 @@ void Usr_GetListUsrs (Rol_Role_t Role,Sco_Scope_t Scope) void Usr_SearchListUsrs (Rol_Role_t Role) { + char SubQueryRole[64]; char Query[Usr_MAX_BYTES_QUERY_GET_LIST_USRS + 1]; const char *QueryFields = "DISTINCT usr_data.UsrCod," @@ -4430,13 +4433,29 @@ void Usr_SearchListUsrs (Rol_Role_t Role) QueryFields, OrderQuery); break; - case Rol_STD: - case Rol_TCH: + case Rol_STD: // Student + case Rol_NET: // Non-editing teacher + case Rol_TCH: // Teacher /* To achieve maximum speed, it's important to do the things in this order: 1) Search for user's name (UsrQuery) getting candidate users 2) Filter the candidate users according to scope */ + switch (Role) + { + case Rol_STD: // Student + sprintf (SubQueryRole," AND crs_usr.Role=%u", + (unsigned) Rol_STD); + break; + case Rol_NET: // Non-editing teacher + case Rol_TCH: // or teacher + sprintf (SubQueryRole," AND (crs_usr.Role=%u OR crs_usr.Role=%u)", + (unsigned) Rol_NET,(unsigned) Rol_TCH); + break; + default: + SubQueryRole[0] = '\0'; + break; + } switch (Gbl.Scope.Current) { case Sco_SCOPE_SYS: @@ -4444,10 +4463,10 @@ void Usr_SearchListUsrs (Rol_Role_t Role) sprintf (Query,"SELECT %s" " FROM candidate_users,crs_usr,usr_data" " WHERE candidate_users.UsrCod=crs_usr.UsrCod" - " AND crs_usr.Role=%u" + "%s" " AND %s", QueryFields, - (unsigned) Role, + SubQueryRole, OrderQuery); break; case Sco_SCOPE_CTY: @@ -4455,7 +4474,7 @@ void Usr_SearchListUsrs (Rol_Role_t Role) sprintf (Query,"SELECT %s" " FROM candidate_users,crs_usr,courses,degrees,centres,institutions,usr_data" " WHERE candidate_users.UsrCod=crs_usr.UsrCod" - " AND crs_usr.Role=%u" + "%s" " AND crs_usr.CrsCod=courses.CrsCod" " AND courses.DegCod=degrees.DegCod" " AND degrees.CtrCod=centres.CtrCod" @@ -4463,7 +4482,7 @@ void Usr_SearchListUsrs (Rol_Role_t Role) " AND institutions.CtyCod=%ld" " AND %s", QueryFields, - (unsigned) Role, + SubQueryRole, Gbl.CurrentCty.Cty.CtyCod, OrderQuery); break; @@ -4472,14 +4491,14 @@ void Usr_SearchListUsrs (Rol_Role_t Role) sprintf (Query,"SELECT %s" " FROM candidate_users,crs_usr,courses,degrees,centres,usr_data" " WHERE candidate_users.UsrCod=crs_usr.UsrCod" - " AND crs_usr.Role=%u" + "%s" " AND crs_usr.CrsCod=courses.CrsCod" " AND courses.DegCod=degrees.DegCod" " AND degrees.CtrCod=centres.CtrCod" " AND centres.InsCod=%ld" " AND %s", QueryFields, - (unsigned) Role, + SubQueryRole, Gbl.CurrentIns.Ins.InsCod, OrderQuery); break; @@ -4488,13 +4507,13 @@ void Usr_SearchListUsrs (Rol_Role_t Role) sprintf (Query,"SELECT %s" " FROM candidate_users,crs_usr,courses,degrees,usr_data" " WHERE candidate_users.UsrCod=crs_usr.UsrCod" - " AND crs_usr.Role=%u" + "%s" " AND crs_usr.CrsCod=courses.CrsCod" " AND courses.DegCod=degrees.DegCod" " AND degrees.CtrCod=%ld" " AND %s", QueryFields, - (unsigned) Role, + SubQueryRole, Gbl.CurrentCtr.Ctr.CtrCod, OrderQuery); break; @@ -4503,12 +4522,12 @@ void Usr_SearchListUsrs (Rol_Role_t Role) sprintf (Query,"SELECT %s" " FROM candidate_users,crs_usr,courses,usr_data" " WHERE candidate_users.UsrCod=crs_usr.UsrCod" - " AND crs_usr.Role=%u" + "%s" " AND crs_usr.CrsCod=courses.CrsCod" " AND courses.DegCod=%ld" " AND %s", QueryFields, - (unsigned) Role, + SubQueryRole, Gbl.CurrentDeg.Deg.DegCod, OrderQuery); break; @@ -4517,11 +4536,11 @@ void Usr_SearchListUsrs (Rol_Role_t Role) sprintf (Query,"SELECT %s,crs_usr.Role,crs_usr.Accepted" " FROM candidate_users,crs_usr,usr_data" " WHERE candidate_users.UsrCod=crs_usr.UsrCod" - " AND crs_usr.Role=%u" + "%s" " AND crs_usr.CrsCod=%ld" " AND %s", QueryFields, - (unsigned) Role, + SubQueryRole, Gbl.CurrentCrs.Crs.CrsCod, OrderQuery); break; @@ -6570,7 +6589,8 @@ void Usr_ListAllDataTchs (void) /*****************************************************************************/ // Returns number of users found -unsigned Usr_ListUsrsFound (Rol_Role_t Role,const char SearchQuery[Sch_MAX_BYTES_SEARCH_QUERY]) +unsigned Usr_ListUsrsFound (Rol_Role_t Role, + const char SearchQuery[Sch_MAX_BYTES_SEARCH_QUERY]) { extern const char *Txt_user[Usr_NUM_SEXS]; extern const char *Txt_users[Usr_NUM_SEXS]; @@ -6598,10 +6618,11 @@ unsigned Usr_ListUsrsFound (Rol_Role_t Role,const char SearchQuery[Sch_MAX_BYTES /* Number of users found */ Sex = Usr_GetSexOfUsrsLst (Role); sprintf (Gbl.Title,"%u %s", - NumUsrs,(Role == Rol_UNK) ? ((NumUsrs == 1) ? Txt_user[Sex] : - Txt_users[Sex]) : - ((NumUsrs == 1) ? Txt_ROLES_SINGUL_abc[Role][Sex] : - Txt_ROLES_PLURAL_abc[Role][Sex])); + NumUsrs, + (Role == Rol_UNK) ? ((NumUsrs == 1) ? Txt_user[Sex] : + Txt_users[Sex]) : + ((NumUsrs == 1) ? Txt_ROLES_SINGUL_abc[Role][Sex] : + Txt_ROLES_PLURAL_abc[Role][Sex])); Lay_StartRoundFrameTable (NULL,Gbl.Title,NULL,NULL,2); /***** Heading row with column names *****/ @@ -8168,7 +8189,7 @@ void Usr_GetAndShowNumUsrsInPlatform (Rol_Role_t Role) float NumCrssPerUsr; float NumUsrsPerCrs; char *Class = (Role == Rol_UNK) ? "DAT_N_LINE_TOP RIGHT_BOTTOM" : - "DAT RIGHT_BOTTOM"; + "DAT RIGHT_BOTTOM"; /***** Get the number of users belonging to any course *****/ if (Role == Rol_GST) // Users not beloging to any course @@ -8178,11 +8199,11 @@ void Usr_GetAndShowNumUsrsInPlatform (Rol_Role_t Role) /***** Get average number of courses per user *****/ NumCrssPerUsr = (Role == Rol_GST) ? 0 : - Usr_GetNumCrssPerUsr (Role); + Usr_GetNumCrssPerUsr (Role); /***** Query the number of users per course *****/ NumUsrsPerCrs = (Role == Rol_GST) ? 0 : - Usr_GetNumUsrsPerCrs (Role); + Usr_GetNumUsrsPerCrs (Role); /***** Write the total number of users *****/ fprintf (Gbl.F.Out,"" @@ -8200,7 +8221,7 @@ void Usr_GetAndShowNumUsrsInPlatform (Rol_Role_t Role) "" "", Class,(Role == Rol_UNK) ? Txt_Total : - Txt_ROLES_PLURAL_Abc[Role][Usr_SEX_UNKNOWN], + Txt_ROLES_PLURAL_Abc[Role][Usr_SEX_UNKNOWN], Class,NumUsrs, Class,NumCrssPerUsr, Class,NumUsrsPerCrs); diff --git a/swad_user.h b/swad_user.h index a2070e1e..fb201be8 100644 --- a/swad_user.h +++ b/swad_user.h @@ -372,7 +372,8 @@ void Usr_ListAllDataGsts (void); void Usr_ListAllDataStds (void); void Usr_ListUsrsForSelection (Rol_Role_t Role); void Usr_ListAllDataTchs (void); -unsigned Usr_ListUsrsFound (Rol_Role_t Role,const char SearchQuery[Sch_MAX_BYTES_SEARCH_QUERY]); +unsigned Usr_ListUsrsFound (Rol_Role_t Role, + const char SearchQuery[Sch_MAX_BYTES_SEARCH_QUERY]); void Usr_ListDataAdms (void); void Usr_PutParamsPrefsAboutUsrList (void);