// swad_country.c: countries /* SWAD (Shared Workspace At a Distance), is a web platform developed at the University of Granada (Spain), and used to support university teaching. This file is part of SWAD core. Copyright (C) 1999-2019 Antonio Caņas Vargas This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ /*****************************************************************************/ /********************************* Headers ***********************************/ /*****************************************************************************/ #define _GNU_SOURCE // For asprintf #include // For NULL #include // For log10, ceil, pow... #include // For asprintf #include // For calloc #include // For string functions #include "swad_box.h" #include "swad_constant.h" #include "swad_country.h" #include "swad_database.h" #include "swad_form.h" #include "swad_global.h" #include "swad_help.h" #include "swad_HTML.h" #include "swad_institution.h" #include "swad_language.h" #include "swad_QR.h" #include "swad_setting.h" /*****************************************************************************/ /************** External global variables from others modules ****************/ /*****************************************************************************/ extern struct Globals Gbl; /*****************************************************************************/ /***************************** Private constants *****************************/ /*****************************************************************************/ /*****************************************************************************/ /******************************* Private types *******************************/ /*****************************************************************************/ /*****************************************************************************/ /***************************** Private variables *****************************/ /*****************************************************************************/ static struct Country *Cty_EditingCty = NULL; // Static variable to keep the country being edited /*****************************************************************************/ /***************************** Private prototypes ****************************/ /*****************************************************************************/ static void Cty_Configuration (bool PrintView); static void Cty_PutIconToPrint (void); static void Cty_ShowNumUsrsInCrssOfCty (Rol_Role_t Role); static void Cty_PutHeadCountriesForSeeing (bool OrderSelectable); static void Cty_ListOneCountryForSeeing (struct Country *Cty,unsigned NumCty); static bool Cty_CheckIfICanEditCountries (void); static void Cty_PutIconsListingCountries (void); static void Cty_PutIconToEditCountries (void); static unsigned Cty_GetNumUsrsWhoClaimToBelongToCty (long CtyCod); static void Cty_GetParamCtyOrder (void); static void Cty_EditCountriesInternal (void); static void Cty_PutIconsEditingCountries (void); static void Cty_PutIconToViewCountries (void); static void Cty_GetMapAttribution (long CtyCod,char **MapAttribution); static void Cty_FreeMapAttribution (char **MapAttribution); static void Cty_ListCountriesForEdition (void); static void Cty_PutParamOtherCtyCod (long CtyCod); static long Cty_GetParamOtherCtyCod (void); static bool Cty_CheckIfNumericCountryCodeExists (long CtyCod); static bool Cty_CheckIfAlpha2CountryCodeExists (const char Alpha2[2 + 1]); static bool Cty_CheckIfCountryNameExists (Lan_Language_t Language,const char *Name,long CtyCod); static void Cty_UpdateCtyNameDB (long CtyCod,const char *FieldName,const char *NewCtyName); static void Cty_ShowAlertAndButtonToGoToCty (void); static void Cty_PutParamGoToCty (void); static void Cty_PutFormToCreateCountry (void); static void Cty_PutHeadCountriesForEdition (void); static void Cty_CreateCountry (void); static void Cty_EditingCountryConstructor (void); static void Cty_EditingCountryDestructor (void); /*****************************************************************************/ /***************** List countries with pending institutions ******************/ /*****************************************************************************/ void Cty_SeeCtyWithPendingInss (void) { extern const char *Hlp_SYSTEM_Hierarchy_pending; extern const char *Lan_STR_LANG_ID[1 + Lan_NUM_LANGUAGES]; extern const char *Txt_Countries_with_pending_institutions; extern const char *Txt_Country; extern const char *Txt_Institutions_ABBREVIATION; extern const char *Txt_There_are_no_countries_with_requests_for_institutions_to_be_confirmed; MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned NumCtys; unsigned NumCty; struct Country Cty; const char *BgColor; /***** Get countries with pending institutions *****/ switch (Gbl.Usrs.Me.Role.Logged) { case Rol_SYS_ADM: NumCtys = (unsigned) DB_QuerySELECT (&mysql_res,"can not get countries" "with pending institutions", "SELECT institutions.CtyCod,COUNT(*)" " FROM institutions,countries" " WHERE (institutions.Status & %u)<>0" " AND institutions.CtyCod=countries.CtyCod" " GROUP BY institutions.CtyCod" " ORDER BY countries.Name_%s", (unsigned) Ins_STATUS_BIT_PENDING, Lan_STR_LANG_ID[Gbl.Prefs.Language]); break; default: // Forbidden for other users return; } /***** Get countries *****/ if (NumCtys) { /***** Begin box and table *****/ Box_StartBoxTable (NULL,Txt_Countries_with_pending_institutions,NULL, Hlp_SYSTEM_Hierarchy_pending,Box_NOT_CLOSABLE,2); /***** Write heading *****/ HTM_TR_Begin (NULL); HTM_TH (1,1,"LM",Txt_Country); HTM_TH (1,1,"RM",Txt_Institutions_ABBREVIATION); HTM_TR_End (); /***** List the countries *****/ for (NumCty = 0; NumCty < NumCtys; NumCty++) { /* Get next country */ row = mysql_fetch_row (mysql_res); /* Get country code (row[0]) */ Cty.CtyCod = Str_ConvertStrCodToLongCod (row[0]); BgColor = (Cty.CtyCod == Gbl.Hierarchy.Cty.CtyCod) ? "LIGHT_BLUE" : Gbl.ColorRows[Gbl.RowEvenOdd]; /* Get data of country */ Cty_GetDataOfCountryByCod (&Cty,Cty_GET_BASIC_DATA); HTM_TR_Begin (NULL); /* Country map */ HTM_TD_Begin ("class=\"LM %s\"",BgColor); Cty_DrawCountryMapAndNameWithLink (&Cty,ActSeeIns, "COUNTRY_SMALL", "COUNTRY_MAP_SMALL", "DAT"); HTM_TD_End (); /* Number of pending institutions (row[1]) */ HTM_TD_Begin ("class=\"DAT RM %s\"",BgColor); fprintf (Gbl.F.Out,"%s",row[1]); HTM_TD_End (); HTM_TR_End (); Gbl.RowEvenOdd = 1 - Gbl.RowEvenOdd; } /***** End table and box *****/ Box_EndBoxTable (); } else Ale_ShowAlert (Ale_INFO,Txt_There_are_no_countries_with_requests_for_institutions_to_be_confirmed); /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); } /*****************************************************************************/ /***************** Show information of the current country *******************/ /*****************************************************************************/ void Cty_ShowConfiguration (void) { Cty_Configuration (false); /***** Show help to enrol me *****/ Hlp_ShowHelpWhatWouldYouLikeToDo (); } /*****************************************************************************/ /***************** Print information of the current country ******************/ /*****************************************************************************/ void Cty_PrintConfiguration (void) { Cty_Configuration (true); } /*****************************************************************************/ /******************** Information of the current country *********************/ /*****************************************************************************/ static void Cty_Configuration (bool PrintView) { extern const char *Hlp_COUNTRY_Information; extern const char *The_ClassFormInBox[The_NUM_THEMES]; extern const char *Txt_Country; extern const char *Txt_Shortcut; extern const char *Lan_STR_LANG_ID[1 + Lan_NUM_LANGUAGES]; extern const char *Txt_QR_code; extern const char *Txt_Institutions; extern const char *Txt_Institutions_of_COUNTRY_X; extern const char *Txt_Centres; extern const char *Txt_Degrees; extern const char *Txt_Courses; extern const char *Txt_Users_of_the_country; char *MapAttribution = NULL; bool PutLink; /***** Trivial check *****/ if (Gbl.Hierarchy.Cty.CtyCod <= 0) // No country selected return; /***** Begin box *****/ if (PrintView) Box_BoxBegin (NULL,NULL,NULL, NULL,Box_NOT_CLOSABLE); else Box_BoxBegin (NULL,NULL,Cty_PutIconToPrint, Hlp_COUNTRY_Information,Box_NOT_CLOSABLE); /***** Title *****/ PutLink = !PrintView && Gbl.Hierarchy.Cty.WWW[Gbl.Prefs.Language][0]; HTM_DIV_Begin ("class=\"FRAME_TITLE FRAME_TITLE_BIG\""); if (PutLink) HTM_A_Begin ("href=\"%s\" target=\"_blank\"" " class=\"FRAME_TITLE_BIG\" title=\"%s\"", Gbl.Hierarchy.Cty.WWW[Gbl.Prefs.Language], Gbl.Hierarchy.Cty.Name[Gbl.Prefs.Language]); fprintf (Gbl.F.Out,"%s",Gbl.Hierarchy.Cty.Name[Gbl.Prefs.Language]); if (PutLink) HTM_A_End (); HTM_DIV_End (); /***** Country map (and link to WWW if exists) *****/ if (Cty_CheckIfCountryMapExists (&Gbl.Hierarchy.Cty)) { /* Get map attribution */ Cty_GetMapAttribution (Gbl.Hierarchy.Cty.CtyCod,&MapAttribution); /* Map image */ HTM_DIV_Begin ("class=\"DAT_SMALL CM\""); if (PutLink) HTM_A_Begin ("href=\"%s\" target=\"_blank\"", Gbl.Hierarchy.Cty.WWW[Gbl.Prefs.Language]); Cty_DrawCountryMap (&Gbl.Hierarchy.Cty,PrintView ? "COUNTRY_MAP_PRINT" : "COUNTRY_MAP_SHOW"); if (PutLink) HTM_A_End (); HTM_DIV_End (); /* Map attribution */ if (!PrintView && Cty_CheckIfICanEditCountries ()) { HTM_DIV_Begin ("class=\"CM\""); Frm_StartForm (ActChgCtyMapAtt); HTM_TEXTAREA_Begin ("name=\"Attribution\" cols=\"50\" rows=\"2\"" " onchange=\"document.getElementById('%s').submit();return false;\"", Gbl.Form.Id); if (MapAttribution) fprintf (Gbl.F.Out,"%s",MapAttribution); HTM_TEXTAREA_End (); Frm_EndForm (); HTM_DIV_End (); } else if (MapAttribution) { HTM_DIV_Begin ("class=\"ATTRIBUTION\""); fprintf (Gbl.F.Out,"%s",MapAttribution); HTM_DIV_End (); } /* Free memory used for map attribution */ Cty_FreeMapAttribution (&MapAttribution); } /***** Begin table *****/ HTM_TABLE_BeginWidePadding (2); /***** Country name (an link to WWW if exists) *****/ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"%s RM\"",The_ClassFormInBox[Gbl.Prefs.Theme]); fprintf (Gbl.F.Out,"%s:",Txt_Country); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT_N LM\""); if (!PrintView && Gbl.Hierarchy.Cty.WWW[Gbl.Prefs.Language][0]) HTM_A_Begin ("href=\"%s\" target=\"_blank\" class=\"DAT_N\"", Gbl.Hierarchy.Cty.WWW[Gbl.Prefs.Language]); fprintf (Gbl.F.Out,"%s",Gbl.Hierarchy.Cty.Name[Gbl.Prefs.Language]); if (!PrintView && Gbl.Hierarchy.Cty.WWW[Gbl.Prefs.Language][0]) HTM_A_End (); HTM_TD_End (); HTM_TR_End (); /***** Link to the country inside platform *****/ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"%s RM\"",The_ClassFormInBox[Gbl.Prefs.Theme]); fprintf (Gbl.F.Out,"%s:",Txt_Shortcut); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT LM\""); HTM_A_Begin ("href=\"%s/%s?cty=%ld\" class=\"DAT\" target=\"_blank\"", Cfg_URL_SWAD_CGI, Lan_STR_LANG_ID[Gbl.Prefs.Language], Gbl.Hierarchy.Cty.CtyCod); fprintf (Gbl.F.Out,"%s/%s?cty=%ld", Cfg_URL_SWAD_CGI, Lan_STR_LANG_ID[Gbl.Prefs.Language], Gbl.Hierarchy.Cty.CtyCod); HTM_A_End (); HTM_TD_End (); HTM_TR_End (); if (PrintView) { /***** QR code with link to the country *****/ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"%s RM\"",The_ClassFormInBox[Gbl.Prefs.Theme]); fprintf (Gbl.F.Out,"%s:",Txt_QR_code); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT LM\""); QR_LinkTo (250,"cty",Gbl.Hierarchy.Cty.CtyCod); HTM_TD_End (); HTM_TR_End (); } else { /***** Number of users who claim to belong to this country *****/ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"%s RM\"",The_ClassFormInBox[Gbl.Prefs.Theme]); fprintf (Gbl.F.Out,"%s:",Txt_Users_of_the_country); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT LM\""); fprintf (Gbl.F.Out,"%u", Usr_GetNumUsrsWhoClaimToBelongToCty (Gbl.Hierarchy.Cty.CtyCod)); HTM_TD_End (); HTM_TR_End (); /***** Number of institutions *****/ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"%s RM\"",The_ClassFormInBox[Gbl.Prefs.Theme]); fprintf (Gbl.F.Out,"%s:",Txt_Institutions); HTM_TD_End (); /* Form to go to see institutions of this country */ HTM_TD_Begin ("class=\"LM\""); Frm_StartFormGoTo (ActSeeIns); Cty_PutParamCtyCod (Gbl.Hierarchy.Cty.CtyCod); snprintf (Gbl.Title,sizeof (Gbl.Title), Txt_Institutions_of_COUNTRY_X, Gbl.Hierarchy.Cty.Name[Gbl.Prefs.Language]); Frm_LinkFormSubmit (Gbl.Title,"DAT",NULL); fprintf (Gbl.F.Out,"%u",Ins_GetNumInssInCty (Gbl.Hierarchy.Cty.CtyCod)); Frm_LinkFormEnd (); Frm_EndForm (); HTM_TD_End (); HTM_TR_End (); /***** Number of centres *****/ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"%s RM\"",The_ClassFormInBox[Gbl.Prefs.Theme]); fprintf (Gbl.F.Out,"%s:",Txt_Centres); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT LM\""); fprintf (Gbl.F.Out,"%u",Ctr_GetNumCtrsInCty (Gbl.Hierarchy.Cty.CtyCod)); HTM_TD_End (); HTM_TR_End (); /***** Number of degrees *****/ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"%s RM\"",The_ClassFormInBox[Gbl.Prefs.Theme]); fprintf (Gbl.F.Out,"%s:", Txt_Degrees); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT LM\""); fprintf (Gbl.F.Out,"%u",Deg_GetNumDegsInCty (Gbl.Hierarchy.Cty.CtyCod)); HTM_TD_End (); HTM_TR_End (); /***** Number of courses *****/ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"%s RM\"",The_ClassFormInBox[Gbl.Prefs.Theme]); fprintf (Gbl.F.Out,"%s:",Txt_Courses); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT LM\""); fprintf (Gbl.F.Out,"%u",Crs_GetNumCrssInCty (Gbl.Hierarchy.Cty.CtyCod)); HTM_TD_End (); HTM_TR_End (); /***** Number of users in courses of this country *****/ Cty_ShowNumUsrsInCrssOfCty (Rol_TCH); Cty_ShowNumUsrsInCrssOfCty (Rol_NET); Cty_ShowNumUsrsInCrssOfCty (Rol_STD); Cty_ShowNumUsrsInCrssOfCty (Rol_UNK); } /***** End table *****/ HTM_TABLE_End (); /***** End box *****/ Box_BoxEnd (); } /*****************************************************************************/ /************* Put icon to print the configuration of a country **************/ /*****************************************************************************/ static void Cty_PutIconToPrint (void) { Ico_PutContextualIconToPrint (ActPrnCtyInf,NULL); } /*****************************************************************************/ /**************** Number of users in courses of this country *****************/ /*****************************************************************************/ static void Cty_ShowNumUsrsInCrssOfCty (Rol_Role_t Role) { extern const char *The_ClassFormInBox[The_NUM_THEMES]; extern const char *Txt_Users_in_courses; extern const char *Txt_ROLES_PLURAL_Abc[Rol_NUM_ROLES][Usr_NUM_SEXS]; HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"%s RM\"",The_ClassFormInBox[Gbl.Prefs.Theme]); fprintf (Gbl.F.Out,"%s:", (Role == Rol_UNK) ? Txt_Users_in_courses : Txt_ROLES_PLURAL_Abc[Role][Usr_SEX_UNKNOWN]); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT LM\""); fprintf (Gbl.F.Out,"%u", Usr_GetNumUsrsInCrssOfCty (Role,Gbl.Hierarchy.Cty.CtyCod)); HTM_TD_End (); HTM_TR_End (); } /*****************************************************************************/ /*************************** List all the countries **************************/ /*****************************************************************************/ void Cty_ListCountries (void) { Cty_ListCountries1 (); Cty_ListCountries2 (); } /*****************************************************************************/ /*************************** List all the countries **************************/ /*****************************************************************************/ void Cty_ListCountries1 (void) { /***** Get parameter with the type of order in the list of countries *****/ Cty_GetParamCtyOrder (); /***** Get list of countries *****/ Cty_GetListCountries (Cty_GET_EXTRA_DATA); } void Cty_ListCountries2 (void) { extern const char *Hlp_SYSTEM_Countries; extern const char *Txt_Countries; extern const char *Txt_Other_countries; extern const char *Txt_Country_unspecified; unsigned NumCty; /***** Write menu to select country *****/ Hie_WriteMenuHierarchy (); /***** Begin box and table *****/ Box_StartBoxTable (NULL,Txt_Countries,Cty_PutIconsListingCountries, Hlp_SYSTEM_Countries,Box_NOT_CLOSABLE,2); /***** Write heading *****/ Cty_PutHeadCountriesForSeeing (true); // Order selectable /***** Write all the countries and their number of users and institutions *****/ for (NumCty = 0; NumCty < Gbl.Hierarchy.Sys.Ctys.Num; NumCty++) Cty_ListOneCountryForSeeing (&Gbl.Hierarchy.Sys.Ctys.Lst[NumCty],NumCty + 1); /***** Separation row *****/ HTM_TR_Begin (NULL); HTM_TD_Begin ("colspan=\"8\" class=\"DAT CM\""); fprintf (Gbl.F.Out," "); HTM_TD_End (); HTM_TR_End (); /***** Write users and institutions in other countries *****/ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"DAT RM\""); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT LM\""); fprintf (Gbl.F.Out,"%s",Txt_Other_countries); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT RM\""); fprintf (Gbl.F.Out,"%u",Cty_GetNumUsrsWhoClaimToBelongToCty (0)); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT RM\""); fprintf (Gbl.F.Out,"%u",Ins_GetNumInssInCty (0)); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT RM\""); fprintf (Gbl.F.Out,"%u",Ctr_GetNumCtrsInCty (0)); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT RM\""); fprintf (Gbl.F.Out,"%u",Deg_GetNumDegsInCty (0)); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT RM\""); fprintf (Gbl.F.Out,"%u",Crs_GetNumCrssInCty (0)); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT RM\""); fprintf (Gbl.F.Out,"%u",Usr_GetNumUsrsInCrssOfCty (Rol_TCH,0)); HTM_TD_End (); HTM_TR_End (); /***** Write users and institutions with unknown country *****/ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"DAT RM\""); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT LM\""); fprintf (Gbl.F.Out,"%s",Txt_Country_unspecified); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT RM\""); fprintf (Gbl.F.Out,"%u",Cty_GetNumUsrsWhoClaimToBelongToCty (-1L)); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT RM\""); fprintf (Gbl.F.Out,"%u",Ins_GetNumInssInCty (-1L)); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT RM\""); fprintf (Gbl.F.Out,"%u",Ctr_GetNumCtrsInCty (-1L)); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT RM\""); fprintf (Gbl.F.Out,"%u",Deg_GetNumDegsInCty (-1L)); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT RM\""); fprintf (Gbl.F.Out,"%u",Crs_GetNumCrssInCty (-1L)); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT RM\""); fprintf (Gbl.F.Out,"0"); HTM_TD_End (); HTM_TR_End (); /***** End table and box *****/ Box_EndBoxTable (); /***** Div for Google Geochart *****/ if (Gbl.Action.Act == ActSeeCty) { HTM_DIV_Begin ("id=\"chart_div\""); HTM_DIV_End (); } /***** Free list of countries *****/ Cty_FreeListCountries (); } /*****************************************************************************/ /******************* Write header with fields of a country *******************/ /*****************************************************************************/ static void Cty_PutHeadCountriesForSeeing (bool OrderSelectable) { extern const char *Txt_COUNTRIES_HELP_ORDER[2]; extern const char *Txt_COUNTRIES_ORDER[2]; extern const char *Txt_Institutions_ABBREVIATION; extern const char *Txt_Centres_ABBREVIATION; extern const char *Txt_Degrees_ABBREVIATION; extern const char *Txt_Courses_ABBREVIATION; extern const char *Txt_ROLES_PLURAL_BRIEF_Abc[Rol_NUM_ROLES]; Cty_Order_t Order; HTM_TR_Begin (NULL); HTM_TH_Empty (1); for (Order = Cty_ORDER_BY_COUNTRY; Order <= Cty_ORDER_BY_NUM_USRS; Order++) { HTM_TH_Begin (1,1,Order == Cty_ORDER_BY_COUNTRY ? "LM" : "RM"); if (OrderSelectable) { Frm_StartForm (ActSeeCty); Par_PutHiddenParamUnsigned (NULL,"Order",(unsigned) Order); Frm_LinkFormSubmit (Txt_COUNTRIES_HELP_ORDER[Order],"TIT_TBL",NULL); if (Order == Gbl.Hierarchy.Sys.Ctys.SelectedOrder) fprintf (Gbl.F.Out,""); } fprintf (Gbl.F.Out,"%s",Txt_COUNTRIES_ORDER[Order]); if (OrderSelectable) { if (Order == Gbl.Hierarchy.Sys.Ctys.SelectedOrder) fprintf (Gbl.F.Out,""); Frm_LinkFormEnd (); Frm_EndForm (); } HTM_TH_End (); } HTM_TH (1,1,"RM",Txt_Institutions_ABBREVIATION); HTM_TH (1,1,"RM",Txt_Centres_ABBREVIATION); HTM_TH (1,1,"RM",Txt_Degrees_ABBREVIATION); HTM_TH (1,1,"RM",Txt_Courses_ABBREVIATION); HTM_TH_Begin (1,1,"RM"); fprintf (Gbl.F.Out,"%s+
%s", Txt_ROLES_PLURAL_BRIEF_Abc[Rol_TCH], Txt_ROLES_PLURAL_BRIEF_Abc[Rol_STD]); HTM_TH_End (); HTM_TR_End (); } /*****************************************************************************/ /************************ List one country for seeing ************************/ /*****************************************************************************/ static void Cty_ListOneCountryForSeeing (struct Country *Cty,unsigned NumCty) { const char *BgColor; BgColor = (Cty->CtyCod == Gbl.Hierarchy.Cty.CtyCod) ? "LIGHT_BLUE" : Gbl.ColorRows[Gbl.RowEvenOdd]; HTM_TR_Begin (NULL); /***** Number of country in this list *****/ HTM_TD_Begin ("class=\"DAT RM %s\"",BgColor); fprintf (Gbl.F.Out,"%u",NumCty); HTM_TD_End (); /***** Country map (and link to WWW if exists) *****/ HTM_TD_Begin ("class=\"LM %s\"",BgColor); Cty_DrawCountryMapAndNameWithLink (Cty,ActSeeIns, "COUNTRY_SMALL", "COUNTRY_MAP_SMALL", "DAT_N"); HTM_TD_End (); /* Write stats of this country */ HTM_TD_Begin ("class=\"DAT RM %s\"",BgColor); fprintf (Gbl.F.Out,"%u",Cty->NumUsrsWhoClaimToBelongToCty); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT RM %s\"",BgColor); fprintf (Gbl.F.Out,"%u",Cty->Inss.Num); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT RM %s\"",BgColor); fprintf (Gbl.F.Out,"%u",Cty->NumCtrs); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT RM %s\"",BgColor); fprintf (Gbl.F.Out,"%u",Cty->NumDegs); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT RM %s\"",BgColor); fprintf (Gbl.F.Out,"%u",Cty->NumCrss); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT RM %s\"",BgColor); fprintf (Gbl.F.Out,"%u",Cty->NumUsrs); HTM_TD_End (); HTM_TR_End (); Gbl.RowEvenOdd = 1 - Gbl.RowEvenOdd; } /*****************************************************************************/ /********************** Check if I can edit countries ************************/ /*****************************************************************************/ static bool Cty_CheckIfICanEditCountries (void) { return (bool) (Gbl.Usrs.Me.Role.Logged == Rol_SYS_ADM); } /*****************************************************************************/ /***************** Put contextual icons in list of countries *****************/ /*****************************************************************************/ static void Cty_PutIconsListingCountries (void) { /***** Put icon to edit countries *****/ if (Cty_CheckIfICanEditCountries ()) Cty_PutIconToEditCountries (); /***** Put icon to show a figure *****/ Gbl.Figures.FigureType = Fig_HIERARCHY; Fig_PutIconToShowFigure (); } /*****************************************************************************/ /************************ Put icon to edit countries *************************/ /*****************************************************************************/ static void Cty_PutIconToEditCountries (void) { Ico_PutContextualIconToEdit (ActEdiCty,NULL); } /*****************************************************************************/ /******** Get number of users who claim to belong to other countries *********/ /*****************************************************************************/ static unsigned Cty_GetNumUsrsWhoClaimToBelongToCty (long CtyCod) { /***** Get number of users from database *****/ return (unsigned) DB_QueryCOUNT ("can not get number of users" " who claim to belong to other countries", "SELECT COUNT(*) FROM usr_data" " WHERE CtyCod=%ld", CtyCod); } /*****************************************************************************/ /********************* Draw country map and name with link *******************/ /*****************************************************************************/ void Cty_DrawCountryMapAndNameWithLink (struct Country *Cty,Act_Action_t Action, const char *ClassContainer, const char *ClassMap, const char *ClassLink) { extern const char *Txt_Go_to_X; char CountryName[Cty_MAX_BYTES_NAME + 1]; /***** Begin form *****/ Frm_StartFormGoTo (Action); Cty_PutParamCtyCod (Cty->CtyCod); HTM_DIV_Begin ("class=\"%s\"",ClassContainer); /***** Link to action *****/ snprintf (Gbl.Title,sizeof (Gbl.Title), Txt_Go_to_X, Cty->Name[Gbl.Prefs.Language]); Frm_LinkFormSubmit (Gbl.Title,ClassLink,NULL); /***** Draw country map *****/ Cty_DrawCountryMap (Cty,ClassMap); /***** Write country name *****/ Str_Copy (CountryName,Cty->Name[Gbl.Prefs.Language], Cty_MAX_BYTES_NAME); fprintf (Gbl.F.Out," %s (%s)",CountryName,Cty->Alpha2); /***** End link *****/ Frm_LinkFormEnd (); /***** End form *****/ HTM_DIV_End (); Frm_EndForm (); } /*****************************************************************************/ /***************************** Draw country map ******************************/ /*****************************************************************************/ void Cty_DrawCountryMap (struct Country *Cty,const char *Class) { char *URL; char *Icon; /***** Draw country map *****/ if (Cty_CheckIfCountryMapExists (Cty)) { if (asprintf (&URL,"%s/%s", Cfg_URL_ICON_COUNTRIES_PUBLIC, Cty->Alpha2) < 0) Lay_NotEnoughMemoryExit (); if (asprintf (&Icon,"%s.png", Cty->Alpha2) < 0) Lay_NotEnoughMemoryExit (); HTM_IMG (URL,Icon,Cty->Name[Gbl.Prefs.Language], "class=\"%s\"",Class); free ((void *) Icon); free ((void *) URL); } else Ico_PutIcon ("tr16x16.gif",Cty->Name[Gbl.Prefs.Language],Class); } /*****************************************************************************/ /*********************** Check if country map exists *************************/ /*****************************************************************************/ bool Cty_CheckIfCountryMapExists (struct Country *Cty) { char PathMap[PATH_MAX + 1]; snprintf (PathMap,sizeof (PathMap), "%s/%s/%s.png", Cfg_PATH_ICON_COUNTRIES_PUBLIC, Cty->Alpha2, Cty->Alpha2); return Fil_CheckIfPathExists (PathMap); } /*****************************************************************************/ /********************** Write script for Google Geochart *********************/ /*****************************************************************************/ void Cty_WriteScriptGoogleGeochart (void) { extern const char *Txt_Country_NO_HTML; extern const char *Txt_Users_NO_HTML; extern const char *Txt_Institutions_NO_HTML; unsigned NumCty; unsigned MaxUsrsInCountry = 0; unsigned NumCtysWithUsrs = 0; /***** Write start of the script *****/ HTM_SCRIPT_Begin ("https://www.google.com/jsapi",NULL); HTM_SCRIPT_End (); HTM_SCRIPT_Begin (NULL,NULL); fprintf (Gbl.F.Out," google.load('visualization', '1', {'packages': ['geochart']});\n" " google.setOnLoadCallback(drawRegionsMap);\n" " function drawRegionsMap() {\n" " var data = new google.visualization.DataTable();\n" " data.addColumn('string', '%s');\n" " data.addColumn('number', '%s');\n" " data.addColumn('number', '%s');\n" " data.addRows([\n", Txt_Country_NO_HTML, Txt_Users_NO_HTML, Txt_Institutions_NO_HTML); /***** Write all the countries and their number of users and institutions *****/ for (NumCty = 0; NumCty < Gbl.Hierarchy.Sys.Ctys.Num; NumCty++) if (Gbl.Hierarchy.Sys.Ctys.Lst[NumCty].NumUsrsWhoClaimToBelongToCty) { /* Write data of this country */ fprintf (Gbl.F.Out," ['%s', %u, %u],\n", Gbl.Hierarchy.Sys.Ctys.Lst[NumCty].Alpha2, Gbl.Hierarchy.Sys.Ctys.Lst[NumCty].NumUsrsWhoClaimToBelongToCty, Gbl.Hierarchy.Sys.Ctys.Lst[NumCty].Inss.Num); if (Gbl.Hierarchy.Sys.Ctys.Lst[NumCty].NumUsrsWhoClaimToBelongToCty > MaxUsrsInCountry) MaxUsrsInCountry = Gbl.Hierarchy.Sys.Ctys.Lst[NumCty].NumUsrsWhoClaimToBelongToCty; NumCtysWithUsrs++; } /***** Write end of the script *****/ fprintf (Gbl.F.Out," ]);\n" " var options = {\n" " width:600,\n" " height:360,\n" " backgroundColor:'white',\n" " datalessRegionColor:'white',\n" " colorAxis:{colors:['#EAF1F4','#4D88A1'],minValue:0,maxValue:%u}};\n" " var chart = new google.visualization.GeoChart(document.getElementById('chart_div'));\n" " chart.draw(data, options);\n" " };\n", NumCtysWithUsrs ? MaxUsrsInCountry : 0); HTM_SCRIPT_End (); } /*****************************************************************************/ /******** Get parameter with the type or order in list of countries **********/ /*****************************************************************************/ static void Cty_GetParamCtyOrder (void) { Gbl.Hierarchy.Sys.Ctys.SelectedOrder = (Cty_Order_t) Par_GetParToUnsignedLong ("Order", 0, Cty_NUM_ORDERS - 1, (unsigned long) Cty_ORDER_DEFAULT); } /*****************************************************************************/ /******************** Put forms to edit institution types ********************/ /*****************************************************************************/ void Cty_EditCountries (void) { /***** Country constructor *****/ Cty_EditingCountryConstructor (); /***** Edit countries *****/ Cty_EditCountriesInternal (); /***** Country destructor *****/ Cty_EditingCountryDestructor (); } static void Cty_EditCountriesInternal (void) { extern const char *Hlp_SYSTEM_Countries; extern const char *Txt_Countries; /***** Get list of countries *****/ Gbl.Hierarchy.Sys.Ctys.SelectedOrder = Cty_ORDER_BY_COUNTRY; Cty_GetListCountries (Cty_GET_EXTRA_DATA); /***** Write menu to select country *****/ Hie_WriteMenuHierarchy (); /***** Begin box *****/ Box_BoxBegin (NULL,Txt_Countries,Cty_PutIconsEditingCountries, Hlp_SYSTEM_Countries,Box_NOT_CLOSABLE); /***** Put a form to create a new country *****/ Cty_PutFormToCreateCountry (); /***** Forms to edit current countries *****/ if (Gbl.Hierarchy.Sys.Ctys.Num) Cty_ListCountriesForEdition (); /***** End box *****/ Box_BoxEnd (); /***** Free list of countries *****/ Cty_FreeListCountries (); } /*****************************************************************************/ /*************** Put contextual icons in edition of countries ****************/ /*****************************************************************************/ static void Cty_PutIconsEditingCountries (void) { /***** Put icon to view countries *****/ Cty_PutIconToViewCountries (); /***** Put icon to show a figure *****/ Gbl.Figures.FigureType = Fig_HIERARCHY; Fig_PutIconToShowFigure (); } /*****************************************************************************/ /************************ Put icon to view countries *************************/ /*****************************************************************************/ static void Cty_PutIconToViewCountries (void) { extern const char *Txt_Countries; Lay_PutContextualLinkOnlyIcon (ActSeeCty,NULL,NULL, "globe.svg", Txt_Countries); } /*****************************************************************************/ /************************** List all the countries ***************************/ /*****************************************************************************/ #define Cty_MAX_BYTES_SUBQUERY_CTYS ((1 + Lan_NUM_LANGUAGES) * 32) void Cty_GetListCountries (Cty_GetExtraData_t GetExtraData) { extern const char *Lan_STR_LANG_ID[1 + Lan_NUM_LANGUAGES]; char StrField[32]; char SubQueryNam1[Cty_MAX_BYTES_SUBQUERY_CTYS + 1]; char SubQueryNam2[Cty_MAX_BYTES_SUBQUERY_CTYS + 1]; char SubQueryWWW1[Cty_MAX_BYTES_SUBQUERY_CTYS + 1]; char SubQueryWWW2[Cty_MAX_BYTES_SUBQUERY_CTYS + 1]; char *OrderBySubQuery = NULL; MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned long NumRows = 0; unsigned NumCty; struct Country *Cty; Lan_Language_t Lan; /***** Get countries from database *****/ switch (GetExtraData) { case Cty_GET_BASIC_DATA: NumRows = DB_QuerySELECT (&mysql_res,"can not get countries", "SELECT CtyCod,Alpha2,Name_%s" " FROM countries ORDER BY Name_%s", Lan_STR_LANG_ID[Gbl.Prefs.Language], Lan_STR_LANG_ID[Gbl.Prefs.Language]); break; case Cty_GET_EXTRA_DATA: SubQueryNam1[0] = '\0'; SubQueryNam2[0] = '\0'; SubQueryWWW1[0] = '\0'; SubQueryWWW2[0] = '\0'; for (Lan = (Lan_Language_t) 1; Lan <= Lan_NUM_LANGUAGES; Lan++) { snprintf (StrField,sizeof (StrField), "countries.Name_%s,", Lan_STR_LANG_ID[Lan]); Str_Concat (SubQueryNam1,StrField, Cty_MAX_BYTES_SUBQUERY_CTYS); snprintf (StrField,sizeof (StrField), "Name_%s,", Lan_STR_LANG_ID[Lan]); Str_Concat (SubQueryNam2,StrField, Cty_MAX_BYTES_SUBQUERY_CTYS); snprintf (StrField,sizeof (StrField), "countries.WWW_%s,", Lan_STR_LANG_ID[Lan]); Str_Concat (SubQueryWWW1,StrField, Cty_MAX_BYTES_SUBQUERY_CTYS); snprintf (StrField,sizeof (StrField), "WWW_%s,", Lan_STR_LANG_ID[Lan]); Str_Concat (SubQueryWWW2,StrField, Cty_MAX_BYTES_SUBQUERY_CTYS); } switch (Gbl.Hierarchy.Sys.Ctys.SelectedOrder) { case Cty_ORDER_BY_COUNTRY: if (asprintf (&OrderBySubQuery,"Name_%s", Lan_STR_LANG_ID[Gbl.Prefs.Language]) < 0) Lay_NotEnoughMemoryExit (); break; case Cty_ORDER_BY_NUM_USRS: if (asprintf (&OrderBySubQuery,"NumUsrs DESC,Name_%s", Lan_STR_LANG_ID[Gbl.Prefs.Language]) < 0) Lay_NotEnoughMemoryExit (); break; } NumRows = DB_QuerySELECT (&mysql_res,"can not get countries", "(SELECT countries.CtyCod,countries.Alpha2," "%s%sCOUNT(*) AS NumUsrs" " FROM countries,usr_data" " WHERE countries.CtyCod=usr_data.CtyCod" " GROUP BY countries.CtyCod)" " UNION " "(SELECT CtyCod,Alpha2,%s%s0 AS NumUsrs" " FROM countries" " WHERE CtyCod NOT IN" " (SELECT DISTINCT CtyCod FROM usr_data))" " ORDER BY %s", SubQueryNam1,SubQueryWWW1, SubQueryNam2,SubQueryWWW2,OrderBySubQuery); break; } /***** Free memory for subquery *****/ if (OrderBySubQuery) free ((void *) OrderBySubQuery); if (NumRows) // Countries found... { Gbl.Hierarchy.Sys.Ctys.Num = (unsigned) NumRows; /***** Create list with countries *****/ if ((Gbl.Hierarchy.Sys.Ctys.Lst = (struct Country *) calloc (NumRows,sizeof (struct Country))) == NULL) Lay_NotEnoughMemoryExit (); /***** Get the countries *****/ for (NumCty = 0; NumCty < Gbl.Hierarchy.Sys.Ctys.Num; NumCty++) { Cty = &(Gbl.Hierarchy.Sys.Ctys.Lst[NumCty]); /* Get next country */ row = mysql_fetch_row (mysql_res); /* Get numerical country code (row[0]) */ if ((Cty->CtyCod = Str_ConvertStrCodToLongCod (row[0])) < 0) Lay_ShowErrorAndExit ("Wrong code of country."); /* Get Alpha-2 country code (row[1]) */ Str_Copy (Cty->Alpha2,row[1], 2); switch (GetExtraData) { case Cty_GET_BASIC_DATA: for (Lan = (Lan_Language_t) 1; Lan <= Lan_NUM_LANGUAGES; Lan++) { Cty->Name[Lan][0] = '\0'; Cty->WWW[Lan][0] = '\0'; } Cty->NumUsrsWhoClaimToBelongToCty = 0; Cty->Inss.Num = Cty->NumCtrs = Cty->NumDegs = Cty->NumCrss = 0; Cty->NumUsrs = 0; /* Get the name of the country in current language */ Str_Copy (Cty->Name[Gbl.Prefs.Language],row[2], Cty_MAX_BYTES_NAME); break; case Cty_GET_EXTRA_DATA: /* Get the name of the country in several languages */ for (Lan = (Lan_Language_t) 1; Lan <= Lan_NUM_LANGUAGES; Lan++) { Str_Copy (Cty->Name[Lan],row[1 + Lan], Cty_MAX_BYTES_NAME); Str_Copy (Cty->WWW[Lan],row[1 + Lan_NUM_LANGUAGES + Lan], Cns_MAX_BYTES_WWW); } /* Get number of users who claim to belong to this country */ if (sscanf (row[1 + Lan_NUM_LANGUAGES * 2 + 1],"%u", &Cty->NumUsrsWhoClaimToBelongToCty) != 1) Cty->NumUsrsWhoClaimToBelongToCty = 0; /* Get number of institutions in this country */ Cty->Inss.Num = Ins_GetNumInssInCty (Cty->CtyCod); /* Get number of centres in this country */ Cty->NumCtrs = Ctr_GetNumCtrsInCty (Cty->CtyCod); /* Get number of degrees in this country */ Cty->NumDegs = Deg_GetNumDegsInCty (Cty->CtyCod); /* Get number of courses in this country */ Cty->NumCrss = Crs_GetNumCrssInCty (Cty->CtyCod); /* Get number of users in courses of this country */ Cty->NumUsrs = Usr_GetNumUsrsInCrssOfCty (Rol_UNK,Cty->CtyCod); // Here Rol_UNK means "all users" break; } } } else Gbl.Hierarchy.Sys.Ctys.Num = 0; /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); } /*****************************************************************************/ /************************** Write selector of country ************************/ /*****************************************************************************/ void Cty_WriteSelectorOfCountry (void) { extern const char *Txt_Country; extern const char *Lan_STR_LANG_ID[1 + Lan_NUM_LANGUAGES]; MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned NumCtys; unsigned NumCty; long CtyCod; /***** Begin form *****/ Frm_StartFormGoTo (ActSeeIns); fprintf (Gbl.F.Out,"