// swad_figure.c: figures (global stats)

/*
    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 <http://www.gnu.org/licenses/>.
*/
/*****************************************************************************/
/********************************* Headers ***********************************/
/*****************************************************************************/

#define _GNU_SOURCE 		// For asprintf
#include <stdio.h>		// For asprintf
#include <stdlib.h>		// For system, getenv, etc.
#include <string.h>		// For string functions

#include "swad_action.h"
#include "swad_box.h"
#include "swad_database.h"
#include "swad_figure.h"
#include "swad_file_browser.h"
#include "swad_follow.h"
#include "swad_form.h"
#include "swad_forum.h"
#include "swad_global.h"
#include "swad_hierarchy.h"
#include "swad_institution.h"
#include "swad_logo.h"
#include "swad_network.h"
#include "swad_notice.h"
#include "swad_privacy.h"
#include "swad_profile.h"
#include "swad_role.h"
#include "swad_table.h"

/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/

extern struct Globals Gbl;

/*****************************************************************************/
/***************************** Private constants *****************************/
/*****************************************************************************/

/*****************************************************************************/
/******************************* Private types *******************************/
/*****************************************************************************/

struct Fig_SizeOfFileZones
  {
   int NumCrss;	// -1 stands for not aplicable
   int NumGrps;	// -1 stands for not aplicable
   int NumUsrs;	// -1 stands for not aplicable
   unsigned MaxLevels;
   unsigned long NumFolders;
   unsigned long NumFiles;
   unsigned long long int Size;	// Total size in bytes
  };

struct Fig_FiguresForum
  {
   unsigned NumForums;
   unsigned NumThreads;
   unsigned NumPosts;
   unsigned NumUsrsToBeNotifiedByEMail;
  };

/*****************************************************************************/
/***************************** Internal prototypes ***************************/
/*****************************************************************************/

static void Fig_PutParamsToShowFigure (void);
static void Fig_PutHiddenParamFigureType (void);
static void Fig_PutHiddenParamScopeFig (void);

static void Fig_GetAndShowHierarchyStats (void);
static void Fig_WriteHeadHierarchy (void);
static void Fig_GetAndShowHierarchyWithInss (void);
static void Fig_GetAndShowHierarchyWithCtrs (void);
static void Fig_GetAndShowHierarchyWithDegs (void);
static void Fig_GetAndShowHierarchyWithCrss (void);
static void Fig_GetAndShowHierarchyWithUsrs (Rol_Role_t Role);
static void Fig_GetAndShowHierarchyTotal (void);
static void Fig_ShowHierarchyRow (const char *Text1,const char *Text2,
				  const char *ClassTxt,
				  int NumCtys,	// < 0 ==> do not show number
				  int NumInss,	// < 0 ==> do not show number
				  int NumCtrs,	// < 0 ==> do not show number
				  int NumDegs,	// < 0 ==> do not show number
				  int NumCrss);	// < 0 ==> do not show number
static void Fig_ShowHierarchyCell (const char *ClassTxt,int Num);

static void Fig_GetAndShowInstitutionsStats (void);
static void Fig_GetAndShowInssOrderedByNumCtrs (void);
static void Fig_GetAndShowInssOrderedByNumDegs (void);
static void Fig_GetAndShowInssOrderedByNumCrss (void);
static void Fig_GetAndShowInssOrderedByNumUsrsInCrss (void);
static void Fig_GetAndShowInssOrderedByNumUsrsWhoClaimToBelongToThem (void);
static void Fig_ShowInss (MYSQL_RES **mysql_res,unsigned NumInss,
		          const char *TxtFigure);
static unsigned Fig_GetInsAndStat (struct Instit *Ins,MYSQL_RES *mysql_res);

static void Fig_GetAndShowDegreeTypesStats (void);

static void Fig_GetAndShowUsersStats (void);
static void Fig_GetAndShowNumUsrsInCrss (Rol_Role_t Role);
static void Fig_GetAndShowNumUsrsNotBelongingToAnyCrs (void);

static void Fig_GetAndShowUsersRanking (void);

static void Fig_GetAndShowFileBrowsersStats (void);
static void Fig_GetSizeOfFileZoneFromDB (Hie_Level_t Scope,
                                         Brw_FileBrowser_t FileBrowser,
                                         struct Fig_SizeOfFileZones *SizeOfFileZones);
static void Fig_WriteStatsExpTreesTableHead1 (void);
static void Fig_WriteStatsExpTreesTableHead2 (void);
static void Fig_WriteStatsExpTreesTableHead3 (void);
static void Fig_WriteRowStatsFileBrowsers1 (const char *NameOfFileZones,
					    Brw_FileBrowser_t FileZone,
                                            struct Fig_SizeOfFileZones *SizeOfFileZones);
static void Fig_WriteRowStatsFileBrowsers2 (const char *NameOfFileZones,
					    Brw_FileBrowser_t FileZone,
                                            struct Fig_SizeOfFileZones *SizeOfFileZones);
static void Fig_WriteRowStatsFileBrowsers3 (const char *NameOfFileZones,
					    Brw_FileBrowser_t FileZone,
                                            struct Fig_SizeOfFileZones *SizeOfFileZones);

static void Fig_GetAndShowOERsStats (void);
static void Fig_GetNumberOfOERsFromDB (Hie_Level_t Scope,Brw_License_t License,unsigned long NumFiles[2]);

static void Fig_GetAndShowAssignmentsStats (void);
static void Fig_GetAndShowProjectsStats (void);
static void Fig_GetAndShowTestsStats (void);
static void Fig_GetAndShowGamesStats (void);

static void Fig_GetAndShowSocialActivityStats (void);
static void Fig_GetAndShowFollowStats (void);

static void Fig_GetAndShowForumStats (void);
static void Fig_ShowStatOfAForumType (For_ForumType_t ForumType,
                                      long CtyCod,long InsCod,long CtrCod,long DegCod,long CrsCod,
                                      struct Fig_FiguresForum *FiguresForum);
static void Fig_WriteForumTitleAndStats (For_ForumType_t ForumType,
                                         long CtyCod,long InsCod,long CtrCod,long DegCod,long CrsCod,
                                         const char *Icon,struct Fig_FiguresForum *FiguresForum,
                                         const char *ForumName1,const char *ForumName2);
static void Fig_WriteForumTotalStats (struct Fig_FiguresForum *FiguresForum);

static void Fig_GetAndShowNumUsrsPerNotifyEvent (void);
static void Fig_GetAndShowNoticesStats (void);
static void Fig_GetAndShowMsgsStats (void);

static void Fig_GetAndShowSurveysStats (void);
static void Fig_GetAndShowNumUsrsPerPrivacy (void);
static void Fig_GetAndShowNumUsrsPerPrivacyForAnObject (const char *TxtObject,
                                                        const char *FieldName,
                                                        unsigned MaskAllowedVisibility);
static void Fig_GetAndShowNumUsrsPerCookies (void);
static void Fig_GetAndShowNumUsrsPerLanguage (void);
static void Fig_GetAndShowNumUsrsPerFirstDayOfWeek (void);
static void Fig_GetAndShowNumUsrsPerDateFormat (void);
static void Fig_GetAndShowNumUsrsPerIconSet (void);
static void Fig_GetAndShowNumUsrsPerMenu (void);
static void Fig_GetAndShowNumUsrsPerTheme (void);
static void Fig_GetAndShowNumUsrsPerSideColumns (void);
unsigned Fig_GetNumUsrsWhoChoseAnOption (const char *SubQuery);

/*****************************************************************************/
/************************** Show use of the platform *************************/
/*****************************************************************************/

void Fig_ReqShowFigures (void)
  {
   extern const char *Hlp_ANALYTICS_Figures;
   extern const char *The_ClassFormInBox[The_NUM_THEMES];
   extern const char *Txt_Figures;
   extern const char *Txt_Scope;
   extern const char *Txt_Statistic;
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   extern const char *Txt_Show_statistic;
   Fig_FigureType_t FigureType;

   /***** Form to show statistic *****/
   Frm_StartForm (ActSeeUseGbl);

   /***** Start box *****/
   Box_StartBox (NULL,Txt_Figures,NULL,
                 Hlp_ANALYTICS_Figures,Box_NOT_CLOSABLE);

   /***** Compute stats for anywhere, degree or course? *****/
   fprintf (Gbl.F.Out,"<label class=\"%s\">%s:&nbsp;",
            The_ClassFormInBox[Gbl.Prefs.Theme],Txt_Scope);
   Gbl.Scope.Allowed = 1 << Hie_SYS |
	               1 << Hie_CTY |
	               1 << Hie_INS |
		       1 << Hie_CTR |
		       1 << Hie_DEG |
		       1 << Hie_CRS;
   Gbl.Scope.Default = Hie_SYS;
   Sco_GetScope ("ScopeFig");
   Sco_PutSelectorScope ("ScopeFig",false);
   fprintf (Gbl.F.Out,"</label><br />");

   /***** Type of statistic *****/
   fprintf (Gbl.F.Out,"<label class=\"%s\">%s:&nbsp;"
	              "<select name=\"FigureType\">",
	    The_ClassFormInBox[Gbl.Prefs.Theme],Txt_Statistic);
   for (FigureType = (Fig_FigureType_t) 0;
	FigureType < Fig_NUM_FIGURES;
	FigureType++)
     {
      fprintf (Gbl.F.Out,"<option value=\"%u\"",
               (unsigned) FigureType);
      if (FigureType == Gbl.Figures.FigureType)
         fprintf (Gbl.F.Out," selected=\"selected\"");
      fprintf (Gbl.F.Out," />"
	                 "%s"
	                 "</option>",
               Txt_FIGURE_TYPES[FigureType]);
     }
   fprintf (Gbl.F.Out,"</select>"
	              "</label>");

   /***** Send button and end box *****/
   Box_EndBoxWithButton (Btn_CONFIRM_BUTTON,Txt_Show_statistic);

   /***** End form *****/
   Frm_EndForm ();
  }

/*****************************************************************************/
/************************* Put icon to show a figure *************************/
/*****************************************************************************/
// Gbl.Figures.FigureType must be set to the desired figure before calling this function

void Fig_PutIconToShowFigure (void)
  {
   extern const char *Txt_Show_statistic;

   Lay_PutContextualLinkOnlyIcon (ActSeeUseGbl,NULL,Fig_PutParamsToShowFigure,
				  "chart-pie.svg",
				  Txt_Show_statistic);
  }

/*****************************************************************************/
/************* Put hidden parameters for figures (statistics) ****************/
/*****************************************************************************/
// Gbl.Figures.FigureType must be set to the desired figure before calling this function

static void Fig_PutParamsToShowFigure (void)
  {
   /***** Set default scope (used only if Gbl.Scope.Current is unknown) *****/
   Gbl.Scope.Default = Hie_CRS;
   Sco_AdjustScope ();

   Fig_PutHiddenParamFigures ();
  }

/*****************************************************************************/
/************* Put hidden parameters for figures (statistics) ****************/
/*****************************************************************************/

void Fig_PutHiddenParamFigures (void)
  {
   Fig_PutHiddenParamScopeFig ();
   Fig_PutHiddenParamFigureType ();
  }

/*****************************************************************************/
/********* Put hidden parameter for the type of figure (statistic) ***********/
/*****************************************************************************/

static void Fig_PutHiddenParamFigureType (void)
  {
   Par_PutHiddenParamUnsigned ("FigureType",(unsigned) Gbl.Figures.FigureType);
  }

/*****************************************************************************/
/********* Put hidden parameter for the type of figure (statistic) ***********/
/*****************************************************************************/

static void Fig_PutHiddenParamScopeFig (void)
  {
   Sco_PutParamScope ("ScopeFig",Gbl.Scope.Current);
  }

/*****************************************************************************/
/************************** Show use of the platform *************************/
/*****************************************************************************/

void Fig_ShowFigures (void)
  {
   static void (*Fig_Function[Fig_NUM_FIGURES])(void) =	// Array of pointers to functions
     {
      Fig_GetAndShowUsersStats,			// Fig_USERS
      Fig_GetAndShowUsersRanking,		// Fig_USERS_RANKING
      Fig_GetAndShowHierarchyStats,		// Fig_HIERARCHY
      Fig_GetAndShowInstitutionsStats,		// Fig_INSTITS
      Fig_GetAndShowDegreeTypesStats,		// Fig_DEGREE_TYPES
      Fig_GetAndShowFileBrowsersStats,		// Fig_FOLDERS_AND_FILES
      Fig_GetAndShowOERsStats,			// Fig_OER
      Fig_GetAndShowAssignmentsStats,		// Fig_ASSIGNMENTS
      Fig_GetAndShowProjectsStats,		// Fig_PROJECTS
      Fig_GetAndShowTestsStats,			// Fig_TESTS
      Fig_GetAndShowGamesStats,			// Fig_GAMES
      Fig_GetAndShowSurveysStats,		// Fig_SURVEYS
      Fig_GetAndShowSocialActivityStats,	// Fig_SOCIAL_ACTIVITY
      Fig_GetAndShowFollowStats,		// Fig_FOLLOW
      Fig_GetAndShowForumStats,			// Fig_FORUMS
      Fig_GetAndShowNumUsrsPerNotifyEvent,	// Fig_NOTIFY_EVENTS
      Fig_GetAndShowNoticesStats,		// Fig_NOTICES
      Fig_GetAndShowMsgsStats,			// Fig_MESSAGES
      Net_ShowWebAndSocialNetworksStats,	// Fig_SOCIAL_NETWORKS
      Fig_GetAndShowNumUsrsPerLanguage,		// Fig_LANGUAGES
      Fig_GetAndShowNumUsrsPerFirstDayOfWeek,	// Fig_FIRST_DAY_OF_WEEK
      Fig_GetAndShowNumUsrsPerDateFormat,	// Fig_DATE_FORMAT
      Fig_GetAndShowNumUsrsPerIconSet,		// Fig_ICON_SETS
      Fig_GetAndShowNumUsrsPerMenu,		// Fig_MENUS
      Fig_GetAndShowNumUsrsPerTheme,		// Fig_THEMES
      Fig_GetAndShowNumUsrsPerSideColumns,	// Fig_SIDE_COLUMNS
      Fig_GetAndShowNumUsrsPerPrivacy,		// Fig_PRIVACY
      Fig_GetAndShowNumUsrsPerCookies,		// Fig_COOKIES
     };

   /***** Get the type of figure ******/
   Gbl.Figures.FigureType = (Fig_FigureType_t)
	                 Par_GetParToUnsignedLong ("FigureType",
	                                           0,
	                                           Fig_NUM_FIGURES - 1,
	                                           (unsigned long) Fig_FIGURE_TYPE_DEF);

   /***** Show again the form to see use of the platform *****/
   Fig_ReqShowFigures ();

   /***** Show the stat of use selected by user *****/
   Fig_Function[Gbl.Figures.FigureType] ();
  }

/*****************************************************************************/
/********************** Show stats about number of users *********************/
/*****************************************************************************/

static void Fig_GetAndShowUsersStats (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_users;
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   extern const char *Txt_Users;
   extern const char *Txt_No_of_users;
   extern const char *Txt_Average_number_of_courses_to_which_a_user_belongs;
   extern const char *Txt_Average_number_of_users_belonging_to_a_course;

   /***** Start box and table *****/
   Box_StartBoxTable (NULL,Txt_FIGURE_TYPES[Fig_USERS],NULL,
                      Hlp_ANALYTICS_Figures_users,Box_NOT_CLOSABLE,2);

   /***** Write heading *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "</tr>",
            Txt_Users,
            Txt_No_of_users,
            Txt_Average_number_of_courses_to_which_a_user_belongs,
            Txt_Average_number_of_users_belonging_to_a_course);

   Fig_GetAndShowNumUsrsInCrss (Rol_STD);		// Students
   Fig_GetAndShowNumUsrsInCrss (Rol_NET);		// Non-editing teachers
   Fig_GetAndShowNumUsrsInCrss (Rol_TCH);		// Teachers
   Fig_GetAndShowNumUsrsInCrss (Rol_UNK);		// Any user in courses
   fprintf (Gbl.F.Out,"<tr>"
                      "<th colspan=\"4\" style=\"height:10px;\">"
                      "</tr>");
   Fig_GetAndShowNumUsrsNotBelongingToAnyCrs ();	// Users not beloging to any course

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/**************** Get and show number of users in courses ********************/
/*****************************************************************************/
// Rol_UNK means any role in courses

static void Fig_GetAndShowNumUsrsInCrss (Rol_Role_t Role)
  {
   extern const char *Txt_Total;
   extern const char *Txt_ROLES_PLURAL_Abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
   unsigned NumUsrs;
   float NumCrssPerUsr;
   float NumUsrsPerCrs;
   char *Class = (Role == Rol_UNK) ? "DAT_N_LINE_TOP RIGHT_BOTTOM" :
	                             "DAT RIGHT_BOTTOM";
   unsigned Roles = (Role == Rol_UNK) ? ((1 << Rol_STD) |
	                                 (1 << Rol_NET) |
	                                 (1 << Rol_TCH)) :
	                                (1 << Role);

   /***** Get the number of users belonging to any course *****/
   NumUsrs = Usr_GetTotalNumberOfUsersInCourses (Gbl.Scope.Current,
						 Roles);

   /***** Get average number of courses per user *****/
   NumCrssPerUsr = Usr_GetNumCrssPerUsr (Role);

   /***** Query the number of users per course *****/
   NumUsrsPerCrs = Usr_GetNumUsrsPerCrs (Role);

   /***** Write the total number of users *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<td class=\"%s\">"
                      "%s"
                      "</td>"
                      "<td class=\"%s\">"
                      "%u"
                      "</td>"
                      "<td class=\"%s\">"
                      "%.2f"
                      "</td>"
                      "<td class=\"%s\">"
                      "%.2f"
                      "</td>"
                      "</tr>",
            Class,(Role == Rol_UNK) ? Txt_Total :
        	                      Txt_ROLES_PLURAL_Abc[Role][Usr_SEX_UNKNOWN],
            Class,NumUsrs,
            Class,NumCrssPerUsr,
            Class,NumUsrsPerCrs);
  }

/*****************************************************************************/
/**************** Get and show number of users in courses ********************/
/*****************************************************************************/

static void Fig_GetAndShowNumUsrsNotBelongingToAnyCrs (void)
  {
   extern const char *Txt_ROLES_PLURAL_Abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
   char *Class = "DAT RIGHT_BOTTOM";

   /***** Write the total number of users not belonging to any course *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<td class=\"%s\">"
                      "%s"
                      "</td>"
                      "<td class=\"%s\">"
                      "%u"
                      "</td>"
                      "<td class=\"%s\">"
                      "%.2f"
                      "</td>"
                      "<td class=\"%s\">"
                      "%.2f"
                      "</td>"
                      "</tr>",
            Class,Txt_ROLES_PLURAL_Abc[Rol_GST][Usr_SEX_UNKNOWN],
            Class,Usr_GetNumUsrsNotBelongingToAnyCrs (),
            Class,0.0,
            Class,0.0);
  }

/*****************************************************************************/
/****************************** Show users' ranking **************************/
/*****************************************************************************/

static void Fig_GetAndShowUsersRanking (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_ranking;
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   extern const char *Txt_Clicks;
   extern const char *Txt_Clicks_per_day;
   extern const char *Txt_Timeline;
   extern const char *Txt_Downloads;
   extern const char *Txt_Forums;
   extern const char *Txt_Messages;
   extern const char *Txt_Followers;

   /***** Start box and table *****/
   Box_StartBoxTable (NULL,Txt_FIGURE_TYPES[Fig_USERS_RANKING],NULL,
                      Hlp_ANALYTICS_Figures_ranking,Box_NOT_CLOSABLE,2);

   /***** Write heading *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"CENTER_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"CENTER_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"CENTER_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"CENTER_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"CENTER_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"CENTER_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"CENTER_MIDDLE\">"
                      "%s"
                      "</th>"
                      "</tr>",
            Txt_Clicks,
            Txt_Clicks_per_day,
            Txt_Timeline,
            Txt_Followers,
            Txt_Downloads,
            Txt_Forums,
            Txt_Messages);

   /***** Rankings *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<td class=\"DAT LEFT_TOP\">");
   Prf_GetAndShowRankingClicks ();
   fprintf (Gbl.F.Out,"</td>"
                      "<td class=\"DAT LEFT_TOP\">");
   Prf_GetAndShowRankingClicksPerDay ();
   fprintf (Gbl.F.Out,"</td>"
                      "<td class=\"DAT LEFT_TOP\">");
   Prf_GetAndShowRankingSocPub ();
   fprintf (Gbl.F.Out,"</td>"
                      "<td class=\"DAT LEFT_TOP\">");
   Fol_GetAndShowRankingFollowers ();
   fprintf (Gbl.F.Out,"</td>"
                      "<td class=\"DAT LEFT_TOP\">");
   Prf_GetAndShowRankingFileViews ();
   fprintf (Gbl.F.Out,"</td>"
                      "<td class=\"DAT LEFT_TOP\">");
   Prf_GetAndShowRankingForPst ();
   fprintf (Gbl.F.Out,"</td>"
                      "<td class=\"DAT LEFT_TOP\">");
   Prf_GetAndShowRankingMsgSnt ();
   fprintf (Gbl.F.Out,"</td>"
	              "</tr>");

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/*********            Get and show stats about hierarchy           ***********/
/********* (countries, institutions, centres, degrees and courses) ***********/
/*****************************************************************************/

static void Fig_GetAndShowHierarchyStats (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_hierarchy;
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   Rol_Role_t Role;

   /***** Start box and table *****/
   Box_StartBoxTable (NULL,Txt_FIGURE_TYPES[Fig_HIERARCHY],NULL,
                      Hlp_ANALYTICS_Figures_hierarchy,Box_NOT_CLOSABLE,2);

   Fig_WriteHeadHierarchy ();
   Fig_GetAndShowHierarchyWithInss ();
   Fig_GetAndShowHierarchyWithCtrs ();
   Fig_GetAndShowHierarchyWithDegs ();
   Fig_GetAndShowHierarchyWithCrss ();
   for (Role =  Rol_TCH;
	Role >= Rol_STD;
	Role--)
      Fig_GetAndShowHierarchyWithUsrs (Role);
   Fig_GetAndShowHierarchyTotal ();

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/************************ Write head of hierarchy table **********************/
/*****************************************************************************/

static void Fig_WriteHeadHierarchy (void)
  {
   extern const char *Txt_Countries;
   extern const char *Txt_Institutions;
   extern const char *Txt_Centres;
   extern const char *Txt_Degrees;
   extern const char *Txt_Courses;

   fprintf (Gbl.F.Out,"<tr>"
                      "<th></th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "<img src=\"%s/globe.svg\""
                      " alt=\"%s\" title=\"%s\""
                      " class=\"CONTEXT_ICO_x16\" />"
                      "<br />"
                      "%s"
		      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "<img src=\"%s/university.svg\""
                      " alt=\"%s\" title=\"%s\""
                      " class=\"CONTEXT_ICO_x16\" />"
                      "<br />"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "<img src=\"%s/building.svg\""
                      " alt=\"%s\" title=\"%s\""
                      " class=\"CONTEXT_ICO_x16\" />"
                      "<br />"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "<img src=\"%s/graduation-cap.svg\""
                      " alt=\"%s\" title=\"%s\""
                      " class=\"CONTEXT_ICO_x16\" />"
                      "<br />"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "<img src=\"%s/list-ol.svg\""
                      " alt=\"%s\" title=\"%s\""
                      " class=\"CONTEXT_ICO_x16\" />"
                      "<br />"
                      "%s"
                      "</th>"
                      "</tr>",
            Cfg_URL_ICON_PUBLIC,Txt_Countries   ,Txt_Countries   ,Txt_Countries,
            Cfg_URL_ICON_PUBLIC,Txt_Institutions,Txt_Institutions,Txt_Institutions,
            Cfg_URL_ICON_PUBLIC,Txt_Centres     ,Txt_Centres     ,Txt_Centres,
            Cfg_URL_ICON_PUBLIC,Txt_Degrees     ,Txt_Degrees     ,Txt_Degrees,
            Cfg_URL_ICON_PUBLIC,Txt_Courses     ,Txt_Courses     ,Txt_Courses);
  }

/*****************************************************************************/
/****** Get and show number of elements in hierarchy with institutions *******/
/*****************************************************************************/

static void Fig_GetAndShowHierarchyWithInss (void)
  {
   extern const char *Txt_With_;
   extern const char *Txt_institutions;
   unsigned NumCtysWithInss = 1;

   /***** Get number of elements with institutions *****/
   switch (Gbl.Scope.Current)
     {
      case Hie_SYS:
         NumCtysWithInss = Cty_GetNumCtysWithInss ("");
         break;
      case Hie_CTY:
      case Hie_INS:
      case Hie_CTR:
      case Hie_DEG:
      case Hie_CRS:
	 break;
      default:
	 Lay_WrongScopeExit ();
	 break;
     }

   /***** Write number of elements with institutions *****/
   Fig_ShowHierarchyRow (Txt_With_,Txt_institutions,
			 "DAT",
                         (int) NumCtysWithInss,
                         -1,		// < 0 ==> do not show number
                         -1,		// < 0 ==> do not show number
                         -1,		// < 0 ==> do not show number
			 -1);		// < 0 ==> do not show number
  }

/*****************************************************************************/
/******** Get and show number of elements in hierarchy with centres **********/
/*****************************************************************************/

static void Fig_GetAndShowHierarchyWithCtrs (void)
  {
   extern const char *Txt_With_;
   extern const char *Txt_centres;
   char SubQuery[128];
   unsigned NumCtysWithCtrs = 1;
   unsigned NumInssWithCtrs = 1;

   /***** Get number of elements with centres *****/
   switch (Gbl.Scope.Current)
     {
      case Hie_SYS:
         NumCtysWithCtrs = Cty_GetNumCtysWithCtrs ("");
         NumInssWithCtrs = Ins_GetNumInssWithCtrs ("");
         break;
      case Hie_CTY:
         sprintf (SubQuery,"institutions.CtyCod=%ld AND ",
                  Gbl.Hierarchy.Cty.CtyCod);
         NumInssWithCtrs = Ins_GetNumInssWithCtrs (SubQuery);
         break;
      case Hie_INS:
      case Hie_CTR:
      case Hie_DEG:
      case Hie_CRS:
	 break;
      default:
	 Lay_WrongScopeExit ();
	 break;
     }

   /***** Write number of elements with centres *****/
   Fig_ShowHierarchyRow (Txt_With_,Txt_centres,
			 "DAT",
                         (int) NumCtysWithCtrs,
                         (int) NumInssWithCtrs,
                         -1,		// < 0 ==> do not show number
                         -1,		// < 0 ==> do not show number
			 -1);		// < 0 ==> do not show number
  }

/*****************************************************************************/
/******** Get and show number of elements in hierarchy with degrees **********/
/*****************************************************************************/

static void Fig_GetAndShowHierarchyWithDegs (void)
  {
   extern const char *Txt_With_;
   extern const char *Txt_degrees;
   char SubQuery[128];
   unsigned NumCtysWithDegs = 1;
   unsigned NumInssWithDegs = 1;
   unsigned NumCtrsWithDegs = 1;

   /***** Get number of elements with degrees *****/
   switch (Gbl.Scope.Current)
     {
      case Hie_SYS:
         NumCtysWithDegs = Cty_GetNumCtysWithDegs ("");
         NumInssWithDegs = Ins_GetNumInssWithDegs ("");
	 NumCtrsWithDegs = Ctr_GetNumCtrsWithDegs ("");
         break;
      case Hie_CTY:
         sprintf (SubQuery,"institutions.CtyCod=%ld AND ",
                  Gbl.Hierarchy.Cty.CtyCod);
         NumInssWithDegs = Ins_GetNumInssWithDegs (SubQuery);
	 NumCtrsWithDegs = Ctr_GetNumCtrsWithDegs (SubQuery);
         break;
      case Hie_INS:
         sprintf (SubQuery,"centres.InsCod=%ld AND ",
                  Gbl.Hierarchy.Ins.InsCod);
	 NumCtrsWithDegs = Ctr_GetNumCtrsWithDegs (SubQuery);
         break;
      case Hie_CTR:
      case Hie_DEG:
      case Hie_CRS:
	 break;
      default:
	 Lay_WrongScopeExit ();
	 break;
     }

   /***** Write number of elements with degrees *****/
   Fig_ShowHierarchyRow (Txt_With_,Txt_degrees,
			 "DAT",
                         (int) NumCtysWithDegs,
                         (int) NumInssWithDegs,
                         (int) NumCtrsWithDegs,
                         -1,		// < 0 ==> do not show number
			 -1);		// < 0 ==> do not show number
  }

/*****************************************************************************/
/******** Get and show number of elements in hierarchy with courses **********/
/*****************************************************************************/

static void Fig_GetAndShowHierarchyWithCrss (void)
  {
   extern const char *Txt_With_;
   extern const char *Txt_courses;
   char SubQuery[128];
   unsigned NumCtysWithCrss = 1;
   unsigned NumInssWithCrss = 1;
   unsigned NumCtrsWithCrss = 1;
   unsigned NumDegsWithCrss = 1;

   /***** Get number of elements with courses *****/
   switch (Gbl.Scope.Current)
     {
      case Hie_SYS:
         NumCtysWithCrss = Cty_GetNumCtysWithCrss ("");
         NumInssWithCrss = Ins_GetNumInssWithCrss ("");
	 NumCtrsWithCrss = Ctr_GetNumCtrsWithCrss ("");
	 NumDegsWithCrss = Deg_GetNumDegsWithCrss ("");
         break;
      case Hie_CTY:
         sprintf (SubQuery,"institutions.CtyCod=%ld AND ",
                  Gbl.Hierarchy.Cty.CtyCod);
         NumInssWithCrss = Ins_GetNumInssWithCrss (SubQuery);
	 NumCtrsWithCrss = Ctr_GetNumCtrsWithCrss (SubQuery);
	 NumDegsWithCrss = Deg_GetNumDegsWithCrss (SubQuery);
         break;
      case Hie_INS:
         sprintf (SubQuery,"centres.InsCod=%ld AND ",
                  Gbl.Hierarchy.Ins.InsCod);
	 NumCtrsWithCrss = Ctr_GetNumCtrsWithCrss (SubQuery);
	 NumDegsWithCrss = Deg_GetNumDegsWithCrss (SubQuery);
         break;
      case Hie_CTR:
         sprintf (SubQuery,"degrees.CtrCod=%ld AND ",
                  Gbl.Hierarchy.Ctr.CtrCod);
	 NumDegsWithCrss = Deg_GetNumDegsWithCrss (SubQuery);
	 break;
      case Hie_DEG:
      case Hie_CRS:
	 break;
      default:
	 Lay_WrongScopeExit ();
	 break;
     }

   /***** Write number of elements with courses *****/
   Fig_ShowHierarchyRow (Txt_With_,Txt_courses,
			 "DAT",
                         (int) NumCtysWithCrss,
                         (int) NumInssWithCrss,
                         (int) NumCtrsWithCrss,
                         (int) NumDegsWithCrss,
			 -1);		// < 0 ==> do not show number
  }

/*****************************************************************************/
/********** Get and show number of elements in hierarchy with users **********/
/*****************************************************************************/

static void Fig_GetAndShowHierarchyWithUsrs (Rol_Role_t Role)
  {
   extern const char *Txt_With_;
   extern const char *Txt_ROLES_PLURAL_abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
   char SubQuery[128];
   unsigned NumCtysWithUsrs = 0;
   unsigned NumInssWithUsrs = 0;
   unsigned NumCtrsWithUsrs = 0;
   unsigned NumDegsWithUsrs = 0;
   unsigned NumCrssWithUsrs = 0;

   /***** Get number of elements with students *****/
   switch (Gbl.Scope.Current)
     {
      case Hie_SYS:
         NumCtysWithUsrs = Cty_GetNumCtysWithUsrs (Role,"");
         NumInssWithUsrs = Ins_GetNumInssWithUsrs (Role,"");
	 NumCtrsWithUsrs = Ctr_GetNumCtrsWithUsrs (Role,"");
	 NumDegsWithUsrs = Deg_GetNumDegsWithUsrs (Role,"");
	 NumCrssWithUsrs = Crs_GetNumCrssWithUsrs (Role,"");
         break;
      case Hie_CTY:
         sprintf (SubQuery,"institutions.CtyCod=%ld AND ",
                  Gbl.Hierarchy.Cty.CtyCod);
         NumCtysWithUsrs = Cty_GetNumCtysWithUsrs (Role,SubQuery);
         NumInssWithUsrs = Ins_GetNumInssWithUsrs (Role,SubQuery);
	 NumCtrsWithUsrs = Ctr_GetNumCtrsWithUsrs (Role,SubQuery);
	 NumDegsWithUsrs = Deg_GetNumDegsWithUsrs (Role,SubQuery);
	 NumCrssWithUsrs = Crs_GetNumCrssWithUsrs (Role,SubQuery);
         break;
      case Hie_INS:
         sprintf (SubQuery,"centres.InsCod=%ld AND ",
                  Gbl.Hierarchy.Ins.InsCod);
         NumCtysWithUsrs = Cty_GetNumCtysWithUsrs (Role,SubQuery);
         NumInssWithUsrs = Ins_GetNumInssWithUsrs (Role,SubQuery);
	 NumCtrsWithUsrs = Ctr_GetNumCtrsWithUsrs (Role,SubQuery);
	 NumDegsWithUsrs = Deg_GetNumDegsWithUsrs (Role,SubQuery);
	 NumCrssWithUsrs = Crs_GetNumCrssWithUsrs (Role,SubQuery);
         break;
      case Hie_CTR:
         sprintf (SubQuery,"degrees.CtrCod=%ld AND ",
                  Gbl.Hierarchy.Ctr.CtrCod);
         NumCtysWithUsrs = Cty_GetNumCtysWithUsrs (Role,SubQuery);
         NumInssWithUsrs = Ins_GetNumInssWithUsrs (Role,SubQuery);
	 NumCtrsWithUsrs = Ctr_GetNumCtrsWithUsrs (Role,SubQuery);
	 NumDegsWithUsrs = Deg_GetNumDegsWithUsrs (Role,SubQuery);
	 NumCrssWithUsrs = Crs_GetNumCrssWithUsrs (Role,SubQuery);
	 break;
      case Hie_DEG:
         sprintf (SubQuery,"courses.DegCod=%ld AND ",
                  Gbl.Hierarchy.Deg.DegCod);
         NumCtysWithUsrs = Cty_GetNumCtysWithUsrs (Role,SubQuery);
         NumInssWithUsrs = Ins_GetNumInssWithUsrs (Role,SubQuery);
	 NumCtrsWithUsrs = Ctr_GetNumCtrsWithUsrs (Role,SubQuery);
	 NumDegsWithUsrs = Deg_GetNumDegsWithUsrs (Role,SubQuery);
	 NumCrssWithUsrs = Crs_GetNumCrssWithUsrs (Role,SubQuery);
	 break;
     case Hie_CRS:
         sprintf (SubQuery,"crs_usr.CrsCod=%ld AND ",
                  Gbl.Hierarchy.Crs.CrsCod);
         NumCtysWithUsrs = Cty_GetNumCtysWithUsrs (Role,SubQuery);
         NumInssWithUsrs = Ins_GetNumInssWithUsrs (Role,SubQuery);
	 NumCtrsWithUsrs = Ctr_GetNumCtrsWithUsrs (Role,SubQuery);
	 NumDegsWithUsrs = Deg_GetNumDegsWithUsrs (Role,SubQuery);
	 NumCrssWithUsrs = Crs_GetNumCrssWithUsrs (Role,SubQuery);
	 break;
      default:
	 Lay_WrongScopeExit ();
	 break;
     }

   /***** Write number of elements with students *****/
   Fig_ShowHierarchyRow (Txt_With_,Txt_ROLES_PLURAL_abc[Role][Usr_SEX_UNKNOWN],
			 "DAT",
                         (int) NumCtysWithUsrs,
                         (int) NumInssWithUsrs,
                         (int) NumCtrsWithUsrs,
                         (int) NumDegsWithUsrs,
			 (int) NumCrssWithUsrs);
  }

/*****************************************************************************/
/************ Get and show total number of elements in hierarchy *************/
/*****************************************************************************/

static void Fig_GetAndShowHierarchyTotal (void)
  {
   extern const char *Txt_Total;
   unsigned NumCtysTotal = 1;
   unsigned NumInssTotal = 1;
   unsigned NumCtrsTotal = 1;
   unsigned NumDegsTotal = 1;
   unsigned NumCrssTotal = 1;

   /***** Get total number of elements *****/
   switch (Gbl.Scope.Current)
     {
      case Hie_SYS:
	 NumCtysTotal = Cty_GetNumCtysTotal ();
	 NumInssTotal = Ins_GetNumInssTotal ();
	 NumCtrsTotal = Ctr_GetNumCtrsTotal ();
	 NumDegsTotal = Deg_GetNumDegsTotal ();
	 NumCrssTotal = Crs_GetNumCrssTotal ();
         break;
      case Hie_CTY:
	 NumInssTotal = Ins_GetNumInssInCty (Gbl.Hierarchy.Cty.CtyCod);
	 NumCtrsTotal = Ctr_GetNumCtrsInCty (Gbl.Hierarchy.Cty.CtyCod);
	 NumDegsTotal = Deg_GetNumDegsInCty (Gbl.Hierarchy.Cty.CtyCod);
	 NumCrssTotal = Crs_GetNumCrssInCty (Gbl.Hierarchy.Cty.CtyCod);
         break;
      case Hie_INS:
	 NumCtrsTotal = Ctr_GetNumCtrsInIns (Gbl.Hierarchy.Ins.InsCod);
	 NumDegsTotal = Deg_GetNumDegsInIns (Gbl.Hierarchy.Ins.InsCod);
	 NumCrssTotal = Crs_GetNumCrssInIns (Gbl.Hierarchy.Ins.InsCod);
         break;
      case Hie_CTR:
	 NumDegsTotal = Deg_GetNumDegsInCtr (Gbl.Hierarchy.Ctr.CtrCod);
	 NumCrssTotal = Crs_GetNumCrssInCtr (Gbl.Hierarchy.Ctr.CtrCod);
	 break;
      case Hie_DEG:
	 NumCrssTotal = Crs_GetNumCrssInDeg (Gbl.Hierarchy.Deg.DegCod);
	 break;
     case Hie_CRS:
	 break;
      default:
	 Lay_WrongScopeExit ();
	 break;
     }

   /***** Write total number of elements *****/
   Fig_ShowHierarchyRow ("",Txt_Total,
			 "DAT_N_LINE_TOP",
                         (int) NumCtysTotal,
                         (int) NumInssTotal,
                         (int) NumCtrsTotal,
                         (int) NumDegsTotal,
			 (int) NumCrssTotal);
  }

/*****************************************************************************/
/************** Show row with number of elements in hierarchy ****************/
/*****************************************************************************/

static void Fig_ShowHierarchyRow (const char *Text1,const char *Text2,
				  const char *ClassTxt,
				  int NumCtys,	// < 0 ==> do not show number
				  int NumInss,	// < 0 ==> do not show number
				  int NumCtrs,	// < 0 ==> do not show number
				  int NumDegs,	// < 0 ==> do not show number
				  int NumCrss)	// < 0 ==> do not show number
  {
   /***** Start row and write text *****/
   fprintf (Gbl.F.Out,"<tr>"
	              "<td class=\"%s RIGHT_MIDDLE\">"
		      "%s%s"
		      "</td>",
	    ClassTxt,Text1,Text2);

   /***** Write number of countries *****/
   Fig_ShowHierarchyCell (ClassTxt,NumCtys);
   Fig_ShowHierarchyCell (ClassTxt,NumInss);
   Fig_ShowHierarchyCell (ClassTxt,NumCtrs);
   Fig_ShowHierarchyCell (ClassTxt,NumDegs);
   Fig_ShowHierarchyCell (ClassTxt,NumCrss);

   /***** End row *****/
   fprintf (Gbl.F.Out,"</tr>");
  }

static void Fig_ShowHierarchyCell (const char *ClassTxt,int Num)
  {
   /***** Write number *****/
   fprintf (Gbl.F.Out,"<td class=\"%s RIGHT_MIDDLE\">",ClassTxt);
   if (Num >= 0)
      fprintf (Gbl.F.Out,"%d",Num);
   else		// < 0 ==> do not show number
      fprintf (Gbl.F.Out,"-");
   fprintf (Gbl.F.Out,"</td>");
  }

/*****************************************************************************/
/****************** Get and show stats about institutions ********************/
/*****************************************************************************/

static void Fig_GetAndShowInstitutionsStats (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_institutions;
   extern const char *Txt_Institutions;

   /***** Start box *****/
   Box_StartBox (NULL,Txt_Institutions,NULL,
                 Hlp_ANALYTICS_Figures_institutions,Box_NOT_CLOSABLE);

   /***** Form to select type of list used to display degree photos *****/
   Usr_GetAndUpdatePrefsAboutUsrList ();
   Usr_ShowFormsToSelectUsrListType (Fig_PutHiddenParamFigures);

   /***** Institutions ordered by number of centres *****/
   Fig_GetAndShowInssOrderedByNumCtrs ();

   /***** Institutions ordered by number of degrees *****/
   Fig_GetAndShowInssOrderedByNumDegs ();

   /***** Institutions ordered by number of courses *****/
   Fig_GetAndShowInssOrderedByNumCrss ();

   /***** Institutions ordered by number of users in courses *****/
   Fig_GetAndShowInssOrderedByNumUsrsInCrss ();

   /***** Institutions ordered by number of users who claim to belong to them *****/
   Fig_GetAndShowInssOrderedByNumUsrsWhoClaimToBelongToThem ();

   /***** End box *****/
   Box_EndBox ();
  }

/*****************************************************************************/
/**** Get and show stats about institutions ordered by number of centres *****/
/*****************************************************************************/

static void Fig_GetAndShowInssOrderedByNumCtrs (void)
  {
   extern const char *Txt_Institutions_by_number_of_centres;
   extern const char *Txt_Centres;
   MYSQL_RES *mysql_res;
   unsigned NumInss = 0;

   /***** Start box and table *****/
   Box_StartBoxTable ("100%",Txt_Institutions_by_number_of_centres,NULL,
                      NULL,Box_NOT_CLOSABLE,2);

   /***** Get institutions ordered by number of centres *****/
   switch (Gbl.Scope.Current)
     {
      case Hie_SYS:
	 NumInss =
	 (unsigned) DB_QuerySELECT (&mysql_res,"can not get institutions",
				    "SELECT InsCod,COUNT(*) AS N"
				    " FROM centres"
				    " GROUP BY InsCod"
				    " ORDER BY N DESC");
         break;
      case Hie_CTY:
	 NumInss =
	 (unsigned) DB_QuerySELECT (&mysql_res,"can not get institutions",
				    "SELECT centres.InsCod,COUNT(*) AS N"
				    " FROM institutions,centres"
				    " WHERE institutions.CtyCod=%ld"
				    " AND institutions.InsCod=centres.InsCod"
				    " GROUP BY centres.InsCod"
				    " ORDER BY N DESC",
				    Gbl.Hierarchy.Cty.CtyCod);
         break;
      case Hie_INS:
      case Hie_CTR:
      case Hie_DEG:
      case Hie_CRS:
	 NumInss =
	 (unsigned) DB_QuerySELECT (&mysql_res,"can not get institutions",
				    "SELECT InsCod,COUNT(*) AS N"
				    " FROM centres"
				    " WHERE InsCod=%ld"
				    " GROUP BY InsCod"
				    " ORDER BY N DESC",
				    Gbl.Hierarchy.Ins.InsCod);
         break;
      default:
	 Lay_WrongScopeExit ();
	 break;
     }

   /***** Show institutions *****/
   Fig_ShowInss (&mysql_res,NumInss,Txt_Centres);

   /***** Free structure that stores the query result *****/
   DB_FreeMySQLResult (&mysql_res);

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/**** Get and show stats about institutions ordered by number of degrees *****/
/*****************************************************************************/

static void Fig_GetAndShowInssOrderedByNumDegs (void)
  {
   extern const char *Txt_Institutions_by_number_of_degrees;
   extern const char *Txt_Degrees;
   MYSQL_RES *mysql_res;
   unsigned NumInss = 0;

   /***** Start box and table *****/
   Box_StartBoxTable ("100%",Txt_Institutions_by_number_of_degrees,NULL,
                      NULL,Box_NOT_CLOSABLE,2);

   /***** Get institutions ordered by number of degrees *****/
   switch (Gbl.Scope.Current)
     {
      case Hie_SYS:
	 NumInss =
	 (unsigned) DB_QuerySELECT (&mysql_res,"can not get institutions",
				    "SELECT centres.InsCod,COUNT(*) AS N"
				    " FROM centres,degrees"
				    " WHERE centres.CtrCod=degrees.CtrCod"
				    " GROUP BY InsCod"
				    " ORDER BY N DESC");
         break;
      case Hie_CTY:
	 NumInss =
	 (unsigned) DB_QuerySELECT (&mysql_res,"can not get institutions",
				    "SELECT centres.InsCod,COUNT(*) AS N"
				    " FROM institutions,centres,degrees"
				    " WHERE institutions.CtyCod=%ld"
				    " AND institutions.InsCod=centres.InsCod"
				    " AND centres.CtrCod=degrees.CtrCod"
				    " GROUP BY centres.InsCod"
				    " ORDER BY N DESC",
				    Gbl.Hierarchy.Cty.CtyCod);
         break;
      case Hie_INS:
      case Hie_CTR:
      case Hie_DEG:
      case Hie_CRS:
	 NumInss =
	 (unsigned) DB_QuerySELECT (&mysql_res,"can not get institutions",
				    "SELECT centres.InsCod,COUNT(*) AS N"
				    " FROM centres,degrees"
				    " WHERE centres.InsCod=%ld"
				    " AND centres.CtrCod=degrees.CtrCod"
				    " GROUP BY centres.InsCod"
				    " ORDER BY N DESC",
				    Gbl.Hierarchy.Ins.InsCod);
         break;
      default:
	 Lay_WrongScopeExit ();
	 break;
     }

   /***** Show institutions *****/
   Fig_ShowInss (&mysql_res,NumInss,Txt_Degrees);

   /***** Free structure that stores the query result *****/
   DB_FreeMySQLResult (&mysql_res);

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/**** Get and show stats about institutions ordered by number of courses *****/
/*****************************************************************************/

static void Fig_GetAndShowInssOrderedByNumCrss (void)
  {
   extern const char *Txt_Institutions_by_number_of_courses;
   extern const char *Txt_Courses;
   MYSQL_RES *mysql_res;
   unsigned NumInss = 0;

   /***** Start box and table *****/
   Box_StartBoxTable ("100%",Txt_Institutions_by_number_of_courses,NULL,
                      NULL,Box_NOT_CLOSABLE,2);

   /***** Get institutions ordered by number of courses *****/
   switch (Gbl.Scope.Current)
     {
      case Hie_SYS:
	 NumInss =
	 (unsigned) DB_QuerySELECT (&mysql_res,"can not get institutions",
				    "SELECT centres.InsCod,COUNT(*) AS N"
				    " FROM centres,degrees,courses"
				    " WHERE centres.CtrCod=degrees.CtrCod"
				    " AND degrees.DegCod=courses.DegCod"
				    " GROUP BY InsCod"
				    " ORDER BY N DESC");
         break;
      case Hie_CTY:
	 NumInss =
	 (unsigned) DB_QuerySELECT (&mysql_res,"can not get institutions",
				    "SELECT centres.InsCod,COUNT(*) AS N"
				    " FROM institutions,centres,degrees,courses"
				    " WHERE institutions.CtyCod=%ld"
				    " AND institutions.InsCod=centres.InsCod"
				    " AND centres.CtrCod=degrees.CtrCod"
				    " AND degrees.DegCod=courses.DegCod"
				    " GROUP BY centres.InsCod"
				    " ORDER BY N DESC",
				    Gbl.Hierarchy.Cty.CtyCod);
         break;
      case Hie_INS:
      case Hie_CTR:
      case Hie_DEG:
      case Hie_CRS:
	 NumInss =
	 (unsigned) DB_QuerySELECT (&mysql_res,"can not get institutions",
				    "SELECT centres.InsCod,COUNT(*) AS N"
				    " FROM centres,degrees,courses"
				    " WHERE centres.InsCod=%ld"
				    " AND centres.CtrCod=degrees.CtrCod"
				    " AND degrees.DegCod=courses.DegCod"
				    " GROUP BY centres.InsCod"
				    " ORDER BY N DESC",
				    Gbl.Hierarchy.Ins.InsCod);
         break;
      default:
	 Lay_WrongScopeExit ();
	 break;
     }

   /***** Show institutions *****/
   Fig_ShowInss (&mysql_res,NumInss,Txt_Courses);

   /***** Free structure that stores the query result *****/
   DB_FreeMySQLResult (&mysql_res);

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/***** Get and show stats about institutions ordered by users in courses *****/
/*****************************************************************************/

static void Fig_GetAndShowInssOrderedByNumUsrsInCrss (void)
  {
   extern const char *Txt_Institutions_by_number_of_users_in_courses;
   extern const char *Txt_Users;
   MYSQL_RES *mysql_res;
   unsigned NumInss = 0;

   /***** Start box and table *****/
   Box_StartBoxTable ("100%",Txt_Institutions_by_number_of_users_in_courses,NULL,
                      NULL,Box_NOT_CLOSABLE,2);

   /***** Get institutions ordered by number of users in courses *****/
   switch (Gbl.Scope.Current)
     {
      case Hie_SYS:
	 NumInss =
	 (unsigned) DB_QuerySELECT (&mysql_res,"can not get institutions",
				    "SELECT centres.InsCod,COUNT(DISTINCT crs_usr.UsrCod) AS N"
				    " FROM centres,degrees,courses,crs_usr"
				    " WHERE centres.CtrCod=degrees.CtrCod"
				    " AND degrees.DegCod=courses.DegCod"
				    " AND courses.CrsCod=crs_usr.CrsCod"
				    " GROUP BY InsCod"
				    " ORDER BY N DESC");
         break;
      case Hie_CTY:
	 NumInss =
	 (unsigned) DB_QuerySELECT (&mysql_res,"can not get institutions",
				    "SELECT centres.InsCod,COUNT(DISTINCT crs_usr.UsrCod) AS N"
				    " FROM institutions,centres,degrees,courses,crs_usr"
				    " WHERE institutions.CtyCod=%ld"
				    " AND institutions.InsCod=centres.InsCod"
				    " AND centres.CtrCod=degrees.CtrCod"
				    " AND degrees.DegCod=courses.DegCod"
				    " AND courses.CrsCod=crs_usr.CrsCod"
				    " GROUP BY centres.InsCod"
				    " ORDER BY N DESC",
				    Gbl.Hierarchy.Cty.CtyCod);
         break;
      case Hie_INS:
      case Hie_CTR:
      case Hie_DEG:
      case Hie_CRS:
	 NumInss =
	 (unsigned) DB_QuerySELECT (&mysql_res,"can not get institutions",
				    "SELECT centres.InsCod,COUNT(DISTINCT crs_usr.UsrCod) AS N"
				    " FROM centres,degrees,courses,crs_usr"
				    " WHERE centres.InsCod=%ld"
				    " AND centres.CtrCod=degrees.CtrCod"
				    " AND degrees.DegCod=courses.DegCod"
				    " AND courses.CrsCod=crs_usr.CrsCod"
				    " GROUP BY centres.InsCod"
				    " ORDER BY N DESC",
				    Gbl.Hierarchy.Ins.InsCod);
         break;
      default:
	 Lay_WrongScopeExit ();
	 break;
     }

   /***** Show institutions *****/
   Fig_ShowInss (&mysql_res,NumInss,Txt_Users);

   /***** Free structure that stores the query result *****/
   DB_FreeMySQLResult (&mysql_res);

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/************* Get and show stats about institutions ordered by **************/
/************* number of users who claim to belong to them      **************/
/*****************************************************************************/

static void Fig_GetAndShowInssOrderedByNumUsrsWhoClaimToBelongToThem (void)
  {
   extern const char *Txt_Institutions_by_number_of_users_who_claim_to_belong_to_them;
   extern const char *Txt_Users;
   MYSQL_RES *mysql_res;
   unsigned NumInss;

   /***** Start box and table *****/
   Box_StartBoxTable ("100%",Txt_Institutions_by_number_of_users_who_claim_to_belong_to_them,
                      NULL,
                      NULL,Box_NOT_CLOSABLE,2);

   /***** Get institutions ordered by number of users who claim to belong to them *****/
   switch (Gbl.Scope.Current)
     {
      case Hie_SYS:
	 NumInss =
	 (unsigned) DB_QuerySELECT (&mysql_res,"can not get institutions",
				    "SELECT InsCod,COUNT(*) AS N"
				    " FROM usr_data"
				    " WHERE InsCod>0"
				    " GROUP BY InsCod"
				    " ORDER BY N DESC");
         break;
      case Hie_CTY:
	 NumInss =
	 (unsigned) DB_QuerySELECT (&mysql_res,"can not get institutions",
				    "SELECT usr_data.InsCod,COUNT(*) AS N"
				    " FROM institutions,usr_data"
				    " WHERE institutions.CtyCod=%ld"
				    " AND institutions.InsCod=usr_data.InsCod"
				    " GROUP BY usr_data.InsCod"
				    " ORDER BY N DESC",
				    Gbl.Hierarchy.Cty.CtyCod);
         break;
      case Hie_INS:
      case Hie_CTR:
      case Hie_DEG:
      case Hie_CRS:
	 NumInss =
	 (unsigned) DB_QuerySELECT (&mysql_res,"can not get institutions",
				    "SELECT InsCod,COUNT(*) AS N"
				    " FROM usr_data"
				    " WHERE InsCod=%ld"
				    " GROUP BY InsCod"
				    " ORDER BY N DESC",
				    Gbl.Hierarchy.Ins.InsCod);
         break;
      default:
	 Lay_WrongScopeExit ();
	 NumInss = 0;	// Not reached. Initialized to avoid warning.
	 break;
     }

   /***** Show institutions *****/
   Fig_ShowInss (&mysql_res,NumInss,Txt_Users);

   /***** Free structure that stores the query result *****/
   DB_FreeMySQLResult (&mysql_res);

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/****************** Get and show stats about institutions ********************/
/*****************************************************************************/

static void Fig_ShowInss (MYSQL_RES **mysql_res,unsigned NumInss,
		          const char *TxtFigure)
  {
   extern const char *The_ClassFormInBox[The_NUM_THEMES];
   extern const char *Txt_Institution;
   unsigned NumIns;
   unsigned NumOrder;
   unsigned NumberLastRow;
   unsigned NumberThisRow;
   struct Instit Ins;
   bool TRIsOpen = false;

   /***** Query database *****/
   if (NumInss)
     {
      /* Draw the classphoto/list */
      switch (Gbl.Usrs.Me.ListType)
	{
	 case Usr_LIST_AS_CLASS_PHOTO:
	    /***** Draw institutions as a class photo *****/
	    for (NumIns = 0;
		 NumIns < NumInss;)
	      {
	       if ((NumIns % Gbl.Usrs.ClassPhoto.Cols) == 0)
		 {
		  fprintf (Gbl.F.Out,"<tr>");
		  TRIsOpen = true;
		 }

	       /***** Get institution data and statistic *****/
	       NumberThisRow = Fig_GetInsAndStat (&Ins,*mysql_res);

	       /***** Write link to institution *****/
	       fprintf (Gbl.F.Out,"<td class=\"%s CENTER_MIDDLE\">",
			The_ClassFormInBox[Gbl.Prefs.Theme]);
	       Ins_DrawInstitutionLogoWithLink (&Ins,40);
               fprintf (Gbl.F.Out,"<br />%u</td>",
	                NumberThisRow);

	       /***** End user's cell *****/
	       fprintf (Gbl.F.Out,"</td>");

	       if ((++NumIns % Gbl.Usrs.ClassPhoto.Cols) == 0)
		 {
		  fprintf (Gbl.F.Out,"</tr>");
		  TRIsOpen = false;
		 }
	      }
	    if (TRIsOpen)
	       fprintf (Gbl.F.Out,"</tr>");

	    break;
	 case Usr_LIST_AS_LISTING:
	    /***** Draw institutions as a list *****/
	    fprintf (Gbl.F.Out,"<tr>"
			       "<th></th>"
			       "<th class=\"LEFT_MIDDLE\">"
			       "%s"
			       "</th>"
			       "<th class=\"RIGHT_MIDDLE\">"
			       "%s"
			       "</th>"
			       "</tr>",
		     Txt_Institution,
		     TxtFigure);

	    for (NumIns = 1, NumOrder = 1, NumberLastRow = 0;
		 NumIns <= NumInss;
		 NumIns++)
	      {
	       /***** Get institution data and statistic *****/
	       NumberThisRow = Fig_GetInsAndStat (&Ins,*mysql_res);

	       /***** Number of order *****/
	       if (NumberThisRow != NumberLastRow)
		  NumOrder = NumIns;
	       fprintf (Gbl.F.Out,"<tr>"
				  "<td class=\"DAT RIGHT_MIDDLE\">"
				  "%u"
				  "</td>",
			NumOrder);

	       /***** Write link to institution *****/
	       fprintf (Gbl.F.Out,"<td class=\"%s LEFT_MIDDLE\">",
			The_ClassFormInBox[Gbl.Prefs.Theme]);

	       /* Icon and name of this institution */
	       Frm_StartForm (ActSeeInsInf);
	       Ins_PutParamInsCod (Ins.InsCod);
	       Frm_LinkFormSubmit (Ins.ShrtName,The_ClassFormInBox[Gbl.Prefs.Theme],NULL);
	       if (Gbl.Usrs.Listing.WithPhotos)
		 {
		  Log_DrawLogo (Hie_INS,Ins.InsCod,Ins.ShrtName,
				40,NULL,true);
	          fprintf (Gbl.F.Out,"&nbsp;");
		 }
	       fprintf (Gbl.F.Out,"%s</a>",Ins.FullName);
	       Frm_EndForm ();

	       fprintf (Gbl.F.Out,"</td>");

	       /***** Write statistic *****/
	       fprintf (Gbl.F.Out,"<td class=\"DAT RIGHT_MIDDLE\">"
				  "%u"
				  "</td>"
				  "</tr>",
			NumberThisRow);

	       NumberLastRow = NumberThisRow;
	      }
	    break;
	 default:
	    break;
	}
     }
  }

/*****************************************************************************/
/******************** Get institution data and statistic *********************/
/*****************************************************************************/

static unsigned Fig_GetInsAndStat (struct Instit *Ins,MYSQL_RES *mysql_res)
  {
   MYSQL_ROW row;
   unsigned NumberThisRow;

   /***** Get next institution *****/
   row = mysql_fetch_row (mysql_res);

   /***** Get data of this institution (row[0]) *****/
   Ins->InsCod = Str_ConvertStrCodToLongCod (row[0]);
   if (!Ins_GetDataOfInstitutionByCod (Ins,Ins_GET_BASIC_DATA))
      Lay_ShowErrorAndExit ("Institution not found.");

   /***** Get statistic (row[1]) *****/
   if (sscanf (row[1],"%u",&NumberThisRow) != 1)
      Lay_ShowErrorAndExit ("Error in statistic");

   return NumberThisRow;
  }

/*****************************************************************************/
/****************** Get and show stats about institutions ********************/
/*****************************************************************************/

static void Fig_GetAndShowDegreeTypesStats (void)
  {
   /***** Show statistic about number of degrees in each type of degree *****/
   DT_SeeDegreeTypesInStaTab ();
  }

/*****************************************************************************/
/********************* Show stats about exploration trees ********************/
/*****************************************************************************/
// TODO: add links to statistic

static void Fig_GetAndShowFileBrowsersStats (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_folders_and_files;
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   extern const char *Txt_STAT_COURSE_FILE_ZONES[Fig_NUM_STAT_CRS_FILE_ZONES];
   static const Brw_FileBrowser_t StatCrsFileZones[Fig_NUM_STAT_CRS_FILE_ZONES] =
     {
      Brw_ADMI_DOC_CRS,
      Brw_ADMI_DOC_GRP,
      Brw_ADMI_TCH_CRS,
      Brw_ADMI_TCH_GRP,
      Brw_ADMI_SHR_CRS,
      Brw_ADMI_SHR_GRP,
      Brw_ADMI_MRK_CRS,
      Brw_ADMI_MRK_GRP,
      Brw_ADMI_ASG_USR,
      Brw_ADMI_WRK_USR,
      Brw_UNKNOWN,
      Brw_ADMI_BRF_USR,
     };
   struct Fig_SizeOfFileZones SizeOfFileZones[Fig_NUM_STAT_CRS_FILE_ZONES];
   unsigned NumStat;

   /***** Get sizes of all file zones *****/
   for (NumStat = 0;
	NumStat < Fig_NUM_STAT_CRS_FILE_ZONES;
	NumStat++)
      Fig_GetSizeOfFileZoneFromDB (Gbl.Scope.Current,
	                           StatCrsFileZones[NumStat],
				   &SizeOfFileZones[NumStat]);

   /***** Start box *****/
   Box_StartBox (NULL,Txt_FIGURE_TYPES[Fig_FOLDERS_AND_FILES],NULL,
                 Hlp_ANALYTICS_Figures_folders_and_files,Box_NOT_CLOSABLE);

   /***** Write sizes of all file zones *****/
   Tbl_StartTableCenter (2);
   Fig_WriteStatsExpTreesTableHead1 ();
   for (NumStat = 0;
	NumStat < Fig_NUM_STAT_CRS_FILE_ZONES;
	NumStat++)
      Fig_WriteRowStatsFileBrowsers1 (Txt_STAT_COURSE_FILE_ZONES[NumStat],
	                              StatCrsFileZones[NumStat],
				      &SizeOfFileZones[NumStat]);
   Tbl_EndTable ();

   /***** Write sizes of all file zones per course *****/
   Tbl_StartTableCenter (2);
   Fig_WriteStatsExpTreesTableHead2 ();
   for (NumStat = 0;
	NumStat < Fig_NUM_STAT_CRS_FILE_ZONES;
	NumStat++)
      Fig_WriteRowStatsFileBrowsers2 (Txt_STAT_COURSE_FILE_ZONES[NumStat],
	                              StatCrsFileZones[NumStat],
				      &SizeOfFileZones[NumStat]);
   Tbl_EndTable ();

   /***** Write sizes of all file zones per user *****/
   Tbl_StartTableCenter (2);
   Fig_WriteStatsExpTreesTableHead3 ();
   for (NumStat = 0;
	NumStat < Fig_NUM_STAT_CRS_FILE_ZONES;
	NumStat++)
      Fig_WriteRowStatsFileBrowsers3 (Txt_STAT_COURSE_FILE_ZONES[NumStat],
	                              StatCrsFileZones[NumStat],
				      &SizeOfFileZones[NumStat]);
   Tbl_EndTable ();

   /***** End box *****/
   Box_EndBox ();
  }

/*****************************************************************************/
/**************** Get the size of a file zone from database ******************/
/*****************************************************************************/

static void Fig_GetSizeOfFileZoneFromDB (Hie_Level_t Scope,
                                         Brw_FileBrowser_t FileBrowser,
                                         struct Fig_SizeOfFileZones *SizeOfFileZones)
  {
   MYSQL_RES *mysql_res;
   MYSQL_ROW row;

   /***** Get the size of a file browser *****/
   switch (Scope)
     {
      /* Scope = the whole platform */
      case Hie_SYS:
	 switch (FileBrowser)
	   {
	    case Brw_UNKNOWN:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT COUNT(DISTINCT CrsCod),"
				      "COUNT(DISTINCT GrpCod)-1,"
				      "-1,"
				      "MAX(NumLevels),"
				      "SUM(NumFolders),"
				      "SUM(NumFiles),"
				      "SUM(TotalSize)"
			       " FROM "
	                       "("
	                       "SELECT Cod AS CrsCod,"
				      "-1 AS GrpCod,"
				      "NumLevels,"
				      "NumFolders,"
				      "NumFiles,"
				      "TotalSize"
			       " FROM file_browser_size"
			       " WHERE FileBrowser IN (%u,%u,%u,%u,%u,%u)"
	                       " UNION "
	                       "SELECT crs_grp_types.CrsCod,"
				      "file_browser_size.Cod AS GrpCod,"
				      "file_browser_size.NumLevels,"
				      "file_browser_size.NumFolders,"
				      "file_browser_size.NumFiles,"
				      "file_browser_size.TotalSize"
			       " FROM crs_grp_types,crs_grp,file_browser_size"
			       " WHERE crs_grp_types.GrpTypCod=crs_grp.GrpTypCod"
			       " AND crs_grp.GrpCod=file_browser_size.Cod"
			       " AND file_browser_size.FileBrowser IN (%u,%u,%u,%u)"
			       ") AS sizes",
			       (unsigned) Brw_ADMI_DOC_CRS,
			       (unsigned) Brw_ADMI_TCH_CRS,
			       (unsigned) Brw_ADMI_SHR_CRS,
			       (unsigned) Brw_ADMI_ASG_USR,
			       (unsigned) Brw_ADMI_WRK_USR,
			       (unsigned) Brw_ADMI_MRK_CRS,
			       (unsigned) Brw_ADMI_DOC_GRP,
			       (unsigned) Brw_ADMI_TCH_GRP,
			       (unsigned) Brw_ADMI_SHR_GRP,
			       (unsigned) Brw_ADMI_MRK_GRP);
	       break;
	    case Brw_ADMI_DOC_CRS:
	    case Brw_ADMI_TCH_CRS:
	    case Brw_ADMI_SHR_CRS:
	    case Brw_ADMI_MRK_CRS:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT COUNT(DISTINCT Cod),"
				      "-1,"
				      "-1,"
				      "MAX(NumLevels),"
				      "SUM(NumFolders),"
				      "SUM(NumFiles),"
				      "SUM(TotalSize)"
			       " FROM file_browser_size"
			       " WHERE FileBrowser=%u",
			       (unsigned) FileBrowser);
	       break;
	    case Brw_ADMI_DOC_GRP:
	    case Brw_ADMI_TCH_GRP:
	    case Brw_ADMI_SHR_GRP:
	    case Brw_ADMI_MRK_GRP:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT COUNT(DISTINCT crs_grp_types.CrsCod),"
				      "COUNT(DISTINCT file_browser_size.Cod),"
				      "-1,"
				      "MAX(file_browser_size.NumLevels),"
				      "SUM(file_browser_size.NumFolders),"
				      "SUM(file_browser_size.NumFiles),"
				      "SUM(file_browser_size.TotalSize)"
			       " FROM crs_grp_types,crs_grp,file_browser_size"
			       " WHERE crs_grp_types.GrpTypCod=crs_grp.GrpTypCod"
			       " AND crs_grp.GrpCod=file_browser_size.Cod"
	                       " AND file_browser_size.FileBrowser=%u",
			       (unsigned) FileBrowser);
	       break;
	    case Brw_ADMI_ASG_USR:
	    case Brw_ADMI_WRK_USR:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT COUNT(DISTINCT Cod),"
				      "-1,"
				      "COUNT(DISTINCT ZoneUsrCod),"
				      "MAX(NumLevels),"
				      "SUM(NumFolders),"
				      "SUM(NumFiles),"
				      "SUM(TotalSize)"
			       " FROM file_browser_size"
			       " WHERE FileBrowser=%u",
			       (unsigned) FileBrowser);
	       break;
	    case Brw_ADMI_BRF_USR:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT -1,"
				      "-1,"
				      "COUNT(DISTINCT ZoneUsrCod),"
				      "MAX(NumLevels),"
				      "SUM(NumFolders),"
				      "SUM(NumFiles),"
				      "SUM(TotalSize)"
			       " FROM file_browser_size"
			       " WHERE FileBrowser=%u",
			       (unsigned) FileBrowser);
	       break;
	    default:
	       Lay_ShowErrorAndExit ("Wrong file browser.");
	       break;
	   }
         break;
      /* Scope = the current country */
      case Hie_CTY:
	 switch (FileBrowser)
	   {
	    case Brw_UNKNOWN:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT COUNT(DISTINCT CrsCod),"
				      "COUNT(DISTINCT GrpCod)-1,"
				      "-1,"
				      "MAX(NumLevels),"
				      "SUM(NumFolders),"
				      "SUM(NumFiles),"
				      "SUM(TotalSize)"
			       " FROM "
	                       "("
	                       "SELECT file_browser_size.Cod AS CrsCod,"
				      "-1 AS GrpCod,"				// Course zones
				      "file_browser_size.NumLevels,"
				      "file_browser_size.NumFolders,"
				      "file_browser_size.NumFiles,"
				      "file_browser_size.TotalSize"
			       " FROM institutions,centres,degrees,courses,file_browser_size"
			       " WHERE institutions.CtyCod=%ld"
			       " AND institutions.InsCod=centres.InsCod"
			       " AND centres.CtrCod=degrees.CtrCod"
			       " AND degrees.DegCod=courses.DegCod"
			       " AND courses.CrsCod=file_browser_size.Cod"
			       " AND file_browser_size.FileBrowser IN (%u,%u,%u,%u,%u,%u)"
	                       " UNION "
	                       "SELECT crs_grp_types.CrsCod,"
				      "file_browser_size.Cod AS GrpCod,"	// Group zones
				      "file_browser_size.NumLevels,"
				      "file_browser_size.NumFolders,"
				      "file_browser_size.NumFiles,"
				      "file_browser_size.TotalSize"
			       " FROM institutions,centres,degrees,courses,crs_grp_types,crs_grp,file_browser_size"
			       " WHERE institutions.CtyCod=%ld"
	                       " AND institutions.InsCod=centres.InsCod"
			       " AND centres.CtrCod=degrees.CtrCod"
			       " AND degrees.DegCod=courses.DegCod"
			       " AND courses.CrsCod=crs_grp_types.CrsCod"
			       " AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod"
			       " AND crs_grp.GrpCod=file_browser_size.Cod"
			       " AND file_browser_size.FileBrowser IN (%u,%u,%u,%u)"
			       ") AS sizes",
			       Gbl.Hierarchy.Cty.CtyCod,
			       (unsigned) Brw_ADMI_DOC_CRS,
			       (unsigned) Brw_ADMI_TCH_CRS,
			       (unsigned) Brw_ADMI_SHR_CRS,
			       (unsigned) Brw_ADMI_ASG_USR,
			       (unsigned) Brw_ADMI_WRK_USR,
			       (unsigned) Brw_ADMI_MRK_CRS,
			       Gbl.Hierarchy.Cty.CtyCod,
			       (unsigned) Brw_ADMI_DOC_GRP,
			       (unsigned) Brw_ADMI_TCH_GRP,
			       (unsigned) Brw_ADMI_SHR_GRP,
			       (unsigned) Brw_ADMI_MRK_GRP);
	       break;
	    case Brw_ADMI_DOC_CRS:
	    case Brw_ADMI_TCH_CRS:
	    case Brw_ADMI_SHR_CRS:
	    case Brw_ADMI_MRK_CRS:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT COUNT(DISTINCT file_browser_size.Cod),"
				      "-1,"
				      "-1,"
				      "MAX(file_browser_size.NumLevels),"
				      "SUM(file_browser_size.NumFolders),"
				      "SUM(file_browser_size.NumFiles),"
				      "SUM(file_browser_size.TotalSize)"
			       " FROM institutions,centres,degrees,courses,file_browser_size"
			       " WHERE institutions.CtyCod=%ld"
	                       " AND institutions.InsCod=centres.InsCod"
			       " AND centres.CtrCod=degrees.CtrCod"
			       " AND degrees.DegCod=courses.DegCod"
			       " AND courses.CrsCod=file_browser_size.Cod"
			       " and file_browser_size.FileBrowser=%u",
			       Gbl.Hierarchy.Cty.CtyCod,(unsigned) FileBrowser);
	       break;
	    case Brw_ADMI_DOC_GRP:
	    case Brw_ADMI_TCH_GRP:
	    case Brw_ADMI_SHR_GRP:
	    case Brw_ADMI_MRK_GRP:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT COUNT(DISTINCT crs_grp_types.CrsCod),"
				      "COUNT(DISTINCT file_browser_size.Cod),"
				      "-1,"
				      "MAX(file_browser_size.NumLevels),"
				      "SUM(file_browser_size.NumFolders),"
				      "SUM(file_browser_size.NumFiles),"
				      "SUM(file_browser_size.TotalSize)"
			       " FROM institutions,centres,degrees,courses,crs_grp_types,crs_grp,file_browser_size"
			       " WHERE institutions.CtyCod=%ld"
	                       " AND institutions.InsCod=centres.InsCod"
			       " AND centres.CtrCod=degrees.CtrCod"
			       " AND degrees.DegCod=courses.DegCod"
			       " AND courses.CrsCod=crs_grp_types.CrsCod"
			       " AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod"
			       " AND crs_grp.GrpCod=file_browser_size.Cod"
			       " AND file_browser_size.FileBrowser=%u",
			       Gbl.Hierarchy.Cty.CtyCod,(unsigned) FileBrowser);
	       break;
	    case Brw_ADMI_ASG_USR:
	    case Brw_ADMI_WRK_USR:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT COUNT(DISTINCT file_browser_size.Cod),"
				      "-1,"
				      "COUNT(DISTINCT file_browser_size.ZoneUsrCod),"
				      "MAX(file_browser_size.NumLevels),"
				      "SUM(file_browser_size.NumFolders),"
				      "SUM(file_browser_size.NumFiles),"
				      "SUM(file_browser_size.TotalSize)"
			       " FROM institutions,centres,degrees,courses,file_browser_size"
			       " WHERE institutions.CtyCod=%ld"
	                       " AND institutions.InsCod=centres.InsCod"
			       " AND centres.CtrCod=degrees.CtrCod"
			       " AND degrees.DegCod=courses.DegCod"
			       " AND courses.CrsCod=file_browser_size.Cod"
	                       " AND file_browser_size.FileBrowser=%u",
			       Gbl.Hierarchy.Cty.CtyCod,(unsigned) FileBrowser);
	       break;
	    case Brw_ADMI_BRF_USR:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT -1,"
				      "-1,"
				      "COUNT(DISTINCT file_browser_size.ZoneUsrCod),"
				      "MAX(file_browser_size.NumLevels),"
				      "SUM(file_browser_size.NumFolders),"
				      "SUM(file_browser_size.NumFiles),"
				      "SUM(file_browser_size.TotalSize)"
			       " FROM institutions,centres,degrees,courses,crs_usr,file_browser_size"
			       " WHERE institutions.CtyCod=%ld"
	                       " AND institutions.InsCod=centres.InsCod"
			       " AND centres.CtrCod=degrees.CtrCod"
			       " AND degrees.DegCod=courses.DegCod"
			       " AND courses.CrsCod=crs_usr.CrsCod"
			       " AND crs_usr.UsrCod=file_browser_size.ZoneUsrCod"
			       " AND file_browser_size.FileBrowser=%u",
			       Gbl.Hierarchy.Cty.CtyCod,(unsigned) FileBrowser);
	       break;
	    default:
	       Lay_ShowErrorAndExit ("Wrong file browser.");
	       break;
	   }
         break;
      /* Scope = the current institution */
      case Hie_INS:
	 switch (FileBrowser)
	   {
	    case Brw_UNKNOWN:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT COUNT(DISTINCT CrsCod),"
				      "COUNT(DISTINCT GrpCod)-1,"
				      "-1,"
				      "MAX(NumLevels),"
				      "SUM(NumFolders),"
				      "SUM(NumFiles),"
				      "SUM(TotalSize)"
			       " FROM "
	                       "("
	                       "SELECT file_browser_size.Cod AS CrsCod,"
				      "-1 AS GrpCod,"				// Course zones
				      "file_browser_size.NumLevels,"
				      "file_browser_size.NumFolders,"
				      "file_browser_size.NumFiles,"
				      "file_browser_size.TotalSize"
			       " FROM centres,degrees,courses,file_browser_size"
			       " WHERE centres.InsCod=%ld"
			       " AND centres.CtrCod=degrees.CtrCod"
			       " AND degrees.DegCod=courses.DegCod"
			       " AND courses.CrsCod=file_browser_size.Cod"
			       " AND file_browser_size.FileBrowser IN (%u,%u,%u,%u,%u,%u)"
	                       " UNION "
	                       "SELECT crs_grp_types.CrsCod,"
				      "file_browser_size.Cod AS GrpCod,"	// Group zones
				      "file_browser_size.NumLevels,"
				      "file_browser_size.NumFolders,"
				      "file_browser_size.NumFiles,"
				      "file_browser_size.TotalSize"
			       " FROM centres,degrees,courses,crs_grp_types,crs_grp,file_browser_size"
			       " WHERE centres.InsCod=%ld"
			       " AND centres.CtrCod=degrees.CtrCod"
			       " AND degrees.DegCod=courses.DegCod"
			       " AND courses.CrsCod=crs_grp_types.CrsCod"
			       " AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod"
			       " AND crs_grp.GrpCod=file_browser_size.Cod"
			       " AND file_browser_size.FileBrowser IN (%u,%u,%u,%u)"
			       ") AS sizes",
			       Gbl.Hierarchy.Ins.InsCod,
			       (unsigned) Brw_ADMI_DOC_CRS,
			       (unsigned) Brw_ADMI_TCH_CRS,
			       (unsigned) Brw_ADMI_SHR_CRS,
			       (unsigned) Brw_ADMI_ASG_USR,
			       (unsigned) Brw_ADMI_WRK_USR,
			       (unsigned) Brw_ADMI_MRK_CRS,
			       Gbl.Hierarchy.Ins.InsCod,
			       (unsigned) Brw_ADMI_DOC_GRP,
			       (unsigned) Brw_ADMI_TCH_GRP,
			       (unsigned) Brw_ADMI_SHR_GRP,
			       (unsigned) Brw_ADMI_MRK_GRP);
	       break;
	    case Brw_ADMI_DOC_CRS:
	    case Brw_ADMI_TCH_CRS:
	    case Brw_ADMI_SHR_CRS:
	    case Brw_ADMI_MRK_CRS:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT COUNT(DISTINCT file_browser_size.Cod),"
				      "-1,"
				      "-1,"
				      "MAX(file_browser_size.NumLevels),"
				      "SUM(file_browser_size.NumFolders),"
				      "SUM(file_browser_size.NumFiles),"
				      "SUM(file_browser_size.TotalSize)"
			       " FROM centres,degrees,courses,file_browser_size"
			       " WHERE centres.InsCod=%ld"
			       " AND centres.CtrCod=degrees.CtrCod"
			       " AND degrees.DegCod=courses.DegCod"
			       " AND courses.CrsCod=file_browser_size.Cod"
			       " and file_browser_size.FileBrowser=%u",
			       Gbl.Hierarchy.Ins.InsCod,(unsigned) FileBrowser);
	       break;
	    case Brw_ADMI_DOC_GRP:
	    case Brw_ADMI_TCH_GRP:
	    case Brw_ADMI_SHR_GRP:
	    case Brw_ADMI_MRK_GRP:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT COUNT(DISTINCT crs_grp_types.CrsCod),"
				      "COUNT(DISTINCT file_browser_size.Cod),"
				      "-1,"
				      "MAX(file_browser_size.NumLevels),"
				      "SUM(file_browser_size.NumFolders),"
				      "SUM(file_browser_size.NumFiles),"
				      "SUM(file_browser_size.TotalSize)"
			       " FROM centres,degrees,courses,crs_grp_types,crs_grp,file_browser_size"
			       " WHERE centres.InsCod=%ld"
			       " AND centres.CtrCod=degrees.CtrCod"
			       " AND degrees.DegCod=courses.DegCod"
			       " AND courses.CrsCod=crs_grp_types.CrsCod"
			       " AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod"
			       " AND crs_grp.GrpCod=file_browser_size.Cod"
			       " AND file_browser_size.FileBrowser=%u",
			       Gbl.Hierarchy.Ins.InsCod,(unsigned) FileBrowser);
	       break;
	    case Brw_ADMI_ASG_USR:
	    case Brw_ADMI_WRK_USR:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT COUNT(DISTINCT file_browser_size.Cod),"
				      "-1,"
				      "COUNT(DISTINCT file_browser_size.ZoneUsrCod),"
				      "MAX(file_browser_size.NumLevels),"
				      "SUM(file_browser_size.NumFolders),"
				      "SUM(file_browser_size.NumFiles),"
				      "SUM(file_browser_size.TotalSize)"
			       " FROM centres,degrees,courses,file_browser_size"
			       " WHERE centres.InsCod=%ld"
			       " AND centres.CtrCod=degrees.CtrCod"
			       " AND degrees.DegCod=courses.DegCod"
			       " AND courses.CrsCod=file_browser_size.Cod"
	                       " AND file_browser_size.FileBrowser=%u",
			       Gbl.Hierarchy.Ins.InsCod,(unsigned) FileBrowser);
	       break;
	    case Brw_ADMI_BRF_USR:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT -1,"
				      "-1,"
				      "COUNT(DISTINCT file_browser_size.ZoneUsrCod),"
				      "MAX(file_browser_size.NumLevels),"
				      "SUM(file_browser_size.NumFolders),"
				      "SUM(file_browser_size.NumFiles),"
				      "SUM(file_browser_size.TotalSize)"
			       " FROM centres,degrees,courses,crs_usr,file_browser_size"
			       " WHERE centres.InsCod=%ld"
			       " AND centres.CtrCod=degrees.CtrCod"
			       " AND degrees.DegCod=courses.DegCod"
			       " AND courses.CrsCod=crs_usr.CrsCod"
			       " AND crs_usr.UsrCod=file_browser_size.ZoneUsrCod"
			       " AND file_browser_size.FileBrowser=%u",
			       Gbl.Hierarchy.Ins.InsCod,(unsigned) FileBrowser);
	       break;
	    default:
	       Lay_ShowErrorAndExit ("Wrong file browser.");
	       break;
	   }
         break;
      /* Scope = the current centre */
      case Hie_CTR:
	 switch (FileBrowser)
	   {
	    case Brw_UNKNOWN:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT COUNT(DISTINCT CrsCod),"
				      "COUNT(DISTINCT GrpCod)-1,"
				      "-1,"
				      "MAX(NumLevels),"
				      "SUM(NumFolders),"
				      "SUM(NumFiles),"
				      "SUM(TotalSize)"
			       " FROM "
	                       "("
	                       "SELECT file_browser_size.Cod AS CrsCod,"
				      "-1 AS GrpCod,"				// Course zones
				      "file_browser_size.NumLevels,"
				      "file_browser_size.NumFolders,"
				      "file_browser_size.NumFiles,"
				      "file_browser_size.TotalSize"
			       " FROM degrees,courses,file_browser_size"
			       " WHERE degrees.CtrCod=%ld"
			       " AND degrees.DegCod=courses.DegCod"
			       " AND courses.CrsCod=file_browser_size.Cod"
			       " AND file_browser_size.FileBrowser IN (%u,%u,%u,%u,%u,%u)"
	                       " UNION "
	                       "SELECT crs_grp_types.CrsCod,"
				      "file_browser_size.Cod AS GrpCod,"	// Group zones
				      "file_browser_size.NumLevels,"
				      "file_browser_size.NumFolders,"
				      "file_browser_size.NumFiles,"
				      "file_browser_size.TotalSize"
			       " FROM degrees,courses,crs_grp_types,crs_grp,file_browser_size"
			       " WHERE degrees.CtrCod=%ld"
			       " AND degrees.DegCod=courses.DegCod"
			       " AND courses.CrsCod=crs_grp_types.CrsCod"
			       " AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod"
			       " AND crs_grp.GrpCod=file_browser_size.Cod"
			       " AND file_browser_size.FileBrowser IN (%u,%u,%u,%u)"
			       ") AS sizes",
			       Gbl.Hierarchy.Ctr.CtrCod,
			       (unsigned) Brw_ADMI_DOC_CRS,
			       (unsigned) Brw_ADMI_TCH_CRS,
			       (unsigned) Brw_ADMI_SHR_CRS,
			       (unsigned) Brw_ADMI_ASG_USR,
			       (unsigned) Brw_ADMI_WRK_USR,
			       (unsigned) Brw_ADMI_MRK_CRS,
			       Gbl.Hierarchy.Ctr.CtrCod,
			       (unsigned) Brw_ADMI_DOC_GRP,
			       (unsigned) Brw_ADMI_TCH_GRP,
			       (unsigned) Brw_ADMI_SHR_GRP,
			       (unsigned) Brw_ADMI_MRK_GRP);
	       break;
	    case Brw_ADMI_DOC_CRS:
	    case Brw_ADMI_TCH_CRS:
	    case Brw_ADMI_SHR_CRS:
	    case Brw_ADMI_MRK_CRS:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT COUNT(DISTINCT file_browser_size.Cod),"
				      "-1,"
				      "-1,"
				      "MAX(file_browser_size.NumLevels),"
				      "SUM(file_browser_size.NumFolders),"
				      "SUM(file_browser_size.NumFiles),"
				      "SUM(file_browser_size.TotalSize)"
			       " FROM degrees,courses,file_browser_size"
			       " WHERE degrees.CtrCod=%ld"
			       " AND degrees.DegCod=courses.DegCod"
			       " AND courses.CrsCod=file_browser_size.Cod"
			       " AND file_browser_size.FileBrowser=%u",
			       Gbl.Hierarchy.Ctr.CtrCod,(unsigned) FileBrowser);
               break;
	    case Brw_ADMI_DOC_GRP:
	    case Brw_ADMI_TCH_GRP:
	    case Brw_ADMI_SHR_GRP:
	    case Brw_ADMI_MRK_GRP:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT COUNT(DISTINCT crs_grp_types.CrsCod),"
				      "COUNT(DISTINCT file_browser_size.Cod),"
				      "-1,"
				      "MAX(file_browser_size.NumLevels),"
				      "SUM(file_browser_size.NumFolders),"
				      "SUM(file_browser_size.NumFiles),"
				      "SUM(file_browser_size.TotalSize)"
			       " FROM degrees,courses,crs_grp_types,crs_grp,file_browser_size"
			       " WHERE degrees.CtrCod=%ld"
			       " AND degrees.DegCod=courses.DegCod"
			       " AND courses.CrsCod=crs_grp_types.CrsCod"
			       " AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod"
			       " AND crs_grp.GrpCod=file_browser_size.Cod"
			       " AND file_browser_size.FileBrowser=%u",
			       Gbl.Hierarchy.Ctr.CtrCod,(unsigned) FileBrowser);
               break;
	    case Brw_ADMI_ASG_USR:
	    case Brw_ADMI_WRK_USR:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT COUNT(DISTINCT file_browser_size.Cod),"
				      "-1,"
				      "COUNT(DISTINCT file_browser_size.ZoneUsrCod),"
				      "MAX(file_browser_size.NumLevels),"
				      "SUM(file_browser_size.NumFolders),"
				      "SUM(file_browser_size.NumFiles),"
				      "SUM(file_browser_size.TotalSize)"
			       " FROM degrees,courses,file_browser_size"
			       " WHERE degrees.CtrCod=%ld"
			       " AND degrees.DegCod=courses.DegCod"
			       " AND courses.CrsCod=file_browser_size.Cod"
			       " AND file_browser_size.FileBrowser=%u",
			       Gbl.Hierarchy.Ctr.CtrCod,(unsigned) FileBrowser);
	       break;
	    case Brw_ADMI_BRF_USR:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT -1,"
				      "-1,"
				      "COUNT(DISTINCT file_browser_size.ZoneUsrCod),"
				      "MAX(file_browser_size.NumLevels),"
				      "SUM(file_browser_size.NumFolders),"
				      "SUM(file_browser_size.NumFiles),"
				      "SUM(file_browser_size.TotalSize)"
			       " FROM degrees,courses,crs_usr,file_browser_size"
			       " WHERE degrees.CtrCod=%ld"
			       " AND degrees.DegCod=courses.DegCod"
			       " AND courses.CrsCod=crs_usr.CrsCod"
			       " AND crs_usr.UsrCod=file_browser_size.ZoneUsrCod"
			       " AND file_browser_size.FileBrowser=%u",
			       Gbl.Hierarchy.Ctr.CtrCod,(unsigned) FileBrowser);
	       break;
	    default:
	       Lay_ShowErrorAndExit ("Wrong file browser.");
	       break;
	   }
         break;
      /* Scope = the current degree */
      case Hie_DEG:
	 switch (FileBrowser)
	   {
	    case Brw_UNKNOWN:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT COUNT(DISTINCT CrsCod),"
				      "COUNT(DISTINCT GrpCod)-1,"
				      "-1,"
				      "MAX(NumLevels),"
				      "SUM(NumFolders),"
				      "SUM(NumFiles),"
				      "SUM(TotalSize)"
			       " FROM "
	                       "("
	                       "SELECT file_browser_size.Cod AS CrsCod,"
				      "-1 AS GrpCod,"				// Course zones
				      "file_browser_size.NumLevels,"
				      "file_browser_size.NumFolders,"
				      "file_browser_size.NumFiles,"
				      "file_browser_size.TotalSize"
			       " FROM courses,file_browser_size"
			       " WHERE courses.DegCod=%ld"
			       " AND courses.CrsCod=file_browser_size.Cod"
			       " AND file_browser_size.FileBrowser IN (%u,%u,%u,%u,%u,%u)"
	                       " UNION "
	                       "SELECT crs_grp_types.CrsCod,"
	                              "file_browser_size.Cod AS GrpCod,"	// Group zones
			              "file_browser_size.NumLevels,"
				      "file_browser_size.NumFolders,"
				      "file_browser_size.NumFiles,"
				      "file_browser_size.TotalSize"
			       " FROM courses,crs_grp_types,crs_grp,file_browser_size"
			       " WHERE courses.DegCod=%ld"
			       " AND courses.CrsCod=crs_grp_types.CrsCod"
			       " AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod"
			       " AND crs_grp.GrpCod=file_browser_size.Cod"
			       " AND file_browser_size.FileBrowser IN (%u,%u,%u,%u)"
			       ") AS sizes",
			       Gbl.Hierarchy.Deg.DegCod,
			       (unsigned) Brw_ADMI_DOC_CRS,
			       (unsigned) Brw_ADMI_TCH_CRS,
			       (unsigned) Brw_ADMI_SHR_CRS,
			       (unsigned) Brw_ADMI_ASG_USR,
			       (unsigned) Brw_ADMI_WRK_USR,
			       (unsigned) Brw_ADMI_MRK_CRS,
			       Gbl.Hierarchy.Deg.DegCod,
			       (unsigned) Brw_ADMI_DOC_GRP,
			       (unsigned) Brw_ADMI_TCH_GRP,
			       (unsigned) Brw_ADMI_SHR_GRP,
			       (unsigned) Brw_ADMI_MRK_GRP);
	       break;
	    case Brw_ADMI_DOC_CRS:
	    case Brw_ADMI_TCH_CRS:
	    case Brw_ADMI_SHR_CRS:
	    case Brw_ADMI_MRK_CRS:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT COUNT(DISTINCT file_browser_size.Cod),"
				      "-1,"
				      "-1,"
				      "MAX(file_browser_size.NumLevels),"
				      "SUM(file_browser_size.NumFolders),"
				      "SUM(file_browser_size.NumFiles),"
				      "SUM(file_browser_size.TotalSize)"
			       " FROM courses,file_browser_size"
			       " WHERE courses.DegCod=%ld"
			       " AND courses.CrsCod=file_browser_size.Cod"
			       " AND file_browser_size.FileBrowser=%u",
			       Gbl.Hierarchy.Deg.DegCod,(unsigned) FileBrowser);
	       break;
	    case Brw_ADMI_DOC_GRP:
	    case Brw_ADMI_TCH_GRP:
	    case Brw_ADMI_SHR_GRP:
	    case Brw_ADMI_MRK_GRP:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT COUNT(DISTINCT crs_grp_types.CrsCod),"
				      "COUNT(DISTINCT file_browser_size.Cod),"
				      "-1,"
				      "MAX(file_browser_size.NumLevels),"
				      "SUM(file_browser_size.NumFolders),"
				      "SUM(file_browser_size.NumFiles),"
				      "SUM(file_browser_size.TotalSize)"
			       " FROM courses,crs_grp_types,crs_grp,file_browser_size"
			       " WHERE courses.DegCod=%ld"
			       " AND courses.CrsCod=crs_grp_types.CrsCod"
			       " AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod"
			       " AND crs_grp.GrpCod=file_browser_size.Cod"
			       " AND file_browser_size.FileBrowser=%u",
			       Gbl.Hierarchy.Deg.DegCod,(unsigned) FileBrowser);
	       break;
	    case Brw_ADMI_ASG_USR:
	    case Brw_ADMI_WRK_USR:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT COUNT(DISTINCT file_browser_size.Cod),"
				      "-1,"
				      "COUNT(DISTINCT file_browser_size.ZoneUsrCod),"
				      "MAX(file_browser_size.NumLevels),"
				      "SUM(file_browser_size.NumFolders),"
				      "SUM(file_browser_size.NumFiles),"
				      "SUM(file_browser_size.TotalSize)"
			       " FROM courses,file_browser_size"
			       " WHERE courses.DegCod=%ld"
			       " AND courses.CrsCod=file_browser_size.Cod"
			       " AND file_browser_size.FileBrowser=%u",
			       Gbl.Hierarchy.Deg.DegCod,(unsigned) FileBrowser);
	       break;
	    case Brw_ADMI_BRF_USR:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT -1,"
				      "-1,"
				      "COUNT(DISTINCT file_browser_size.ZoneUsrCod),"
				      "MAX(file_browser_size.NumLevels),"
				      "SUM(file_browser_size.NumFolders),"
				      "SUM(file_browser_size.NumFiles),"
				      "SUM(file_browser_size.TotalSize)"
			       " FROM courses,crs_usr,file_browser_size"
			       " WHERE courses.DegCod=%ld"
			       " AND courses.CrsCod=crs_usr.CrsCod"
			       " AND crs_usr.UsrCod=file_browser_size.ZoneUsrCod"
			       " AND file_browser_size.FileBrowser=%u",
			       Gbl.Hierarchy.Deg.DegCod,(unsigned) FileBrowser);
	       break;
	    default:
	       Lay_ShowErrorAndExit ("Wrong file browser.");
	       break;
	   }
         break;
      /* Scope = the current course */
      case Hie_CRS:
	 switch (FileBrowser)
	   {
	    case Brw_UNKNOWN:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT COUNT(DISTINCT CrsCod),"
				      "COUNT(DISTINCT GrpCod)-1,"
				      "-1,"
				      "MAX(NumLevels),"
				      "SUM(NumFolders),"
				      "SUM(NumFiles),"
				      "SUM(TotalSize)"
			       " FROM "
	                       "("
	                       "SELECT Cod AS CrsCod,"
				      "-1 AS GrpCod,"				// Course zones
				      "NumLevels,"
				      "NumFolders,"
				      "NumFiles,"
				      "TotalSize"
			       " FROM file_browser_size"
			       " WHERE Cod=%ld"
			       " AND FileBrowser IN (%u,%u,%u,%u,%u,%u)"
	                       " UNION "
	                       "SELECT crs_grp_types.CrsCod,"
				      "file_browser_size.Cod AS GrpCod,"	// Group zones
				      "file_browser_size.NumLevels,"
				      "file_browser_size.NumFolders,"
				      "file_browser_size.NumFiles,"
				      "file_browser_size.TotalSize"
			       " FROM crs_grp_types,crs_grp,file_browser_size"
			       " WHERE crs_grp_types.CrsCod=%ld"
			       " AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod"
			       " AND crs_grp.GrpCod=file_browser_size.Cod"
			       " AND file_browser_size.FileBrowser IN (%u,%u,%u,%u)"
			       ") AS sizes",
			       Gbl.Hierarchy.Crs.CrsCod,
			       (unsigned) Brw_ADMI_DOC_CRS,
			       (unsigned) Brw_ADMI_TCH_CRS,
			       (unsigned) Brw_ADMI_SHR_CRS,
			       (unsigned) Brw_ADMI_ASG_USR,
			       (unsigned) Brw_ADMI_WRK_USR,
			       (unsigned) Brw_ADMI_MRK_CRS,
			       Gbl.Hierarchy.Crs.CrsCod,
			       (unsigned) Brw_ADMI_DOC_GRP,
			       (unsigned) Brw_ADMI_TCH_GRP,
			       (unsigned) Brw_ADMI_SHR_GRP,
			       (unsigned) Brw_ADMI_MRK_GRP);
	       break;
	    case Brw_ADMI_DOC_CRS:
	    case Brw_ADMI_TCH_CRS:
	    case Brw_ADMI_SHR_CRS:
	    case Brw_ADMI_MRK_CRS:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT 1,"
				      "-1,"
				      "-1,"
				      "MAX(NumLevels),"
				      "SUM(NumFolders),"
				      "SUM(NumFiles),"
				      "SUM(TotalSize)"
			       " FROM file_browser_size"
			       " WHERE Cod=%ld AND FileBrowser=%u",
			       Gbl.Hierarchy.Crs.CrsCod,(unsigned) FileBrowser);
	       break;
	    case Brw_ADMI_DOC_GRP:
	    case Brw_ADMI_TCH_GRP:
	    case Brw_ADMI_SHR_GRP:
	    case Brw_ADMI_MRK_GRP:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT COUNT(DISTINCT crs_grp_types.CrsCod),"
				      "COUNT(DISTINCT file_browser_size.Cod),"
				      "-1,"
				      "MAX(file_browser_size.NumLevels),"
				      "SUM(file_browser_size.NumFolders),"
				      "SUM(file_browser_size.NumFiles),"
				      "SUM(file_browser_size.TotalSize)"
			       " FROM crs_grp_types,crs_grp,file_browser_size"
			       " WHERE crs_grp_types.CrsCod=%ld"
			       " AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod"
			       " AND crs_grp.GrpCod=file_browser_size.Cod"
			       " AND file_browser_size.FileBrowser=%u",
			       Gbl.Hierarchy.Crs.CrsCod,(unsigned) FileBrowser);
	       break;
	    case Brw_ADMI_ASG_USR:
	    case Brw_ADMI_WRK_USR:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT 1,"
				      "-1,"
				      "COUNT(DISTINCT ZoneUsrCod),"
				      "MAX(NumLevels),"
				      "SUM(NumFolders),"
				      "SUM(NumFiles),"
				      "SUM(TotalSize)"
			       " FROM file_browser_size"
			       " WHERE Cod=%ld AND FileBrowser=%u",
			       Gbl.Hierarchy.Crs.CrsCod,(unsigned) FileBrowser);
	       break;
	    case Brw_ADMI_BRF_USR:
	       DB_QuerySELECT (&mysql_res,"can not get size of a file browser",
			       "SELECT -1,"
				      "-1,"
				      "COUNT(DISTINCT file_browser_size.ZoneUsrCod),"
				      "MAX(file_browser_size.NumLevels),"
				      "SUM(file_browser_size.NumFolders),"
				      "SUM(file_browser_size.NumFiles),"
				      "SUM(file_browser_size.TotalSize)"
			       " FROM crs_usr,file_browser_size"
			       " WHERE crs_usr.CrsCod=%ld"
			       " AND crs_usr.UsrCod=file_browser_size.ZoneUsrCod"
			       " AND file_browser_size.FileBrowser=%u",
			       Gbl.Hierarchy.Crs.CrsCod,(unsigned) FileBrowser);
	       break;
	    default:
	       Lay_ShowErrorAndExit ("Wrong file browser.");
	       break;
	   }
         break;
      default:
	 Lay_WrongScopeExit ();
	 break;
     }

   /* Get row */
   row = mysql_fetch_row (mysql_res);

   /* Reset default values to zero */
   SizeOfFileZones->NumCrss = SizeOfFileZones->NumUsrs = 0;
   SizeOfFileZones->MaxLevels = 0;
   SizeOfFileZones->NumFolders = SizeOfFileZones->NumFiles = 0;
   SizeOfFileZones->Size = 0;

   /* Get number of courses (row[0]) */
   if (row[0])
      if (sscanf (row[0],"%d",&(SizeOfFileZones->NumCrss)) != 1)
         Lay_ShowErrorAndExit ("Error when getting number of courses.");

   /* Get number of groups (row[1]) */
   if (row[1])
      if (sscanf (row[1],"%d",&(SizeOfFileZones->NumGrps)) != 1)
         Lay_ShowErrorAndExit ("Error when getting number of groups.");

   /* Get number of users (row[2]) */
   if (row[2])
      if (sscanf (row[2],"%d",&(SizeOfFileZones->NumUsrs)) != 1)
         Lay_ShowErrorAndExit ("Error when getting number of users.");

   /* Get maximum number of levels (row[3]) */
   if (row[3])
      if (sscanf (row[3],"%u",&(SizeOfFileZones->MaxLevels)) != 1)
         Lay_ShowErrorAndExit ("Error when getting maximum number of levels.");

   /* Get number of folders (row[4]) */
   if (row[4])
      if (sscanf (row[4],"%lu",&(SizeOfFileZones->NumFolders)) != 1)
         Lay_ShowErrorAndExit ("Error when getting number of folders.");

   /* Get number of files (row[5]) */
   if (row[5])
      if (sscanf (row[5],"%lu",&(SizeOfFileZones->NumFiles)) != 1)
         Lay_ShowErrorAndExit ("Error when getting number of files.");

   /* Get total size (row[6]) */
   if (row[6])
      if (sscanf (row[6],"%llu",&(SizeOfFileZones->Size)) != 1)
         Lay_ShowErrorAndExit ("Error when getting toal size.");

   /* Free structure that stores the query result */
   DB_FreeMySQLResult (&mysql_res);
  }

/*****************************************************************************/
/*********** Write table heading for stats of exploration trees **************/
/*****************************************************************************/

static void Fig_WriteStatsExpTreesTableHead1 (void)
  {
   extern const char *Txt_File_zones;
   extern const char *Txt_Courses;
   extern const char *Txt_Groups;
   extern const char *Txt_Users;
   extern const char *Txt_Max_levels;
   extern const char *Txt_Folders;
   extern const char *Txt_Files;
   extern const char *Txt_Size;

   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"LEFT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "</tr>",
            Txt_File_zones,
            Txt_Courses,
            Txt_Groups,
            Txt_Users,
            Txt_Max_levels,
            Txt_Folders,
            Txt_Files,
            Txt_Size);
  }

static void Fig_WriteStatsExpTreesTableHead2 (void)
  {
   extern const char *Txt_File_zones;
   extern const char *Txt_Folders;
   extern const char *Txt_Files;
   extern const char *Txt_Size;
   extern const char *Txt_course;

   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"LEFT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s/<br />%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s/<br />%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s/<br />%s"
                      "</th>"
                      "</tr>",
            Txt_File_zones,
            Txt_Folders,Txt_course,
            Txt_Files,Txt_course,
            Txt_Size,Txt_course);
  }

static void Fig_WriteStatsExpTreesTableHead3 (void)
  {
   extern const char *Txt_File_zones;
   extern const char *Txt_Folders;
   extern const char *Txt_Files;
   extern const char *Txt_Size;
   extern const char *Txt_user[Usr_NUM_SEXS];

   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"LEFT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s/<br />%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s/<br />%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s/<br />%s"
                      "</th>"
                      "</tr>",
            Txt_File_zones,
            Txt_Folders,Txt_user[Usr_SEX_UNKNOWN],
            Txt_Files,Txt_user[Usr_SEX_UNKNOWN],
            Txt_Size,Txt_user[Usr_SEX_UNKNOWN]);
  }

/*****************************************************************************/
/*************** Write a row of stats of exploration trees *******************/
/*****************************************************************************/

static void Fig_WriteRowStatsFileBrowsers1 (const char *NameOfFileZones,
					    Brw_FileBrowser_t FileZone,
                                            struct Fig_SizeOfFileZones *SizeOfFileZones)
  {
   char StrNumCrss[10 + 1];
   char StrNumGrps[10 + 1];
   char StrNumUsrs[10 + 1];
   char FileSizeStr[Fil_MAX_BYTES_FILE_SIZE_STRING + 1];
   char *Class = (FileZone == Brw_UNKNOWN) ? "DAT_N_LINE_TOP" :
	                                     "DAT";

   Fil_WriteFileSizeFull ((double) SizeOfFileZones->Size,FileSizeStr);

   if (SizeOfFileZones->NumCrss == -1)	// Not applicable
      Str_Copy (StrNumCrss,"-",
                10);
   else
      snprintf (StrNumCrss,sizeof (StrNumCrss),
	        "%d",
		SizeOfFileZones->NumCrss);

   if (SizeOfFileZones->NumGrps == -1)	// Not applicable
      Str_Copy (StrNumGrps,"-",
                10);
   else
      snprintf (StrNumGrps,sizeof (StrNumGrps),
	        "%d",
		SizeOfFileZones->NumGrps);

   if (SizeOfFileZones->NumUsrs == -1)	// Not applicable
      Str_Copy (StrNumUsrs,"-",
                10);
   else
      snprintf (StrNumUsrs,sizeof (StrNumUsrs),
	        "%d",
		SizeOfFileZones->NumUsrs);

   fprintf (Gbl.F.Out,"<tr>"
                      "<td class=\"%s LEFT_MIDDLE\">"
                      "%s"
                      "</td>"
                      "<td class=\"%s RIGHT_MIDDLE\">"
                      "%s"
                      "</td>"
                      "<td class=\"%s RIGHT_MIDDLE\">"
                      "%s"
                      "</td>"
                      "<td class=\"%s RIGHT_MIDDLE\">"
                      "%s"
                      "</td>"
                      "<td class=\"%s RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"%s RIGHT_MIDDLE\">"
                      "%lu"
                      "</td>"
                      "<td class=\"%s RIGHT_MIDDLE\">"
                      "%lu"
                      "</td>"
                      "<td class=\"%s RIGHT_MIDDLE\">"
                      "%s"
                      "</td>"
	              "</tr>",
            Class,NameOfFileZones,
            Class,StrNumCrss,
            Class,StrNumGrps,
            Class,StrNumUsrs,
            Class,SizeOfFileZones->MaxLevels,
            Class,SizeOfFileZones->NumFolders,
            Class,SizeOfFileZones->NumFiles,
            Class,FileSizeStr);
  }


static void Fig_WriteRowStatsFileBrowsers2 (const char *NameOfFileZones,
					    Brw_FileBrowser_t FileZone,
                                            struct Fig_SizeOfFileZones *SizeOfFileZones)
  {
   char StrNumFoldersPerCrs[10 + 1];
   char StrNumFilesPerCrs[10 + 1];
   char FileSizePerCrsStr[Fil_MAX_BYTES_FILE_SIZE_STRING + 1];
   char *Class = (FileZone == Brw_UNKNOWN) ? "DAT_N_LINE_TOP" :
	                                     "DAT";

   if (SizeOfFileZones->NumCrss == -1)	// Not applicable
     {
      Str_Copy (StrNumFoldersPerCrs,"-",
                10);
      Str_Copy (StrNumFilesPerCrs,"-",
                10);
      Str_Copy (FileSizePerCrsStr,"-",
                Fil_MAX_BYTES_FILE_SIZE_STRING);
     }
   else
     {
      snprintf (StrNumFoldersPerCrs,sizeof (StrNumFoldersPerCrs),
	        "%.1f",
                SizeOfFileZones->NumCrss ? (double) SizeOfFileZones->NumFolders /
        	                           (double) SizeOfFileZones->NumCrss :
        	                           0.0);
      snprintf (StrNumFilesPerCrs,sizeof (StrNumFilesPerCrs),
	        "%.1f",
                SizeOfFileZones->NumCrss ? (double) SizeOfFileZones->NumFiles /
        	                           (double) SizeOfFileZones->NumCrss :
        	                           0.0);
      Fil_WriteFileSizeFull (SizeOfFileZones->NumCrss ? (double) SizeOfFileZones->Size /
	                                                (double) SizeOfFileZones->NumCrss :
	                                                0.0,
	                     FileSizePerCrsStr);
     }

   fprintf (Gbl.F.Out,"<tr>"
                      "<td class=\"%s LEFT_MIDDLE\">"
                      "%s"
                      "</td>"
                      "<td class=\"%s RIGHT_MIDDLE\">"
                      "%s"
                      "</td>"
                      "<td class=\"%s RIGHT_MIDDLE\">"
                      "%s"
                      "</td>"
                      "<td class=\"%s RIGHT_MIDDLE\">"
                      "%s"
                      "</td>"
	              "</tr>",
            Class,NameOfFileZones,
            Class,StrNumFoldersPerCrs,
            Class,StrNumFilesPerCrs,
            Class,FileSizePerCrsStr);
  }


static void Fig_WriteRowStatsFileBrowsers3 (const char *NameOfFileZones,
					    Brw_FileBrowser_t FileZone,
                                            struct Fig_SizeOfFileZones *SizeOfFileZones)
  {
   char StrNumFoldersPerUsr[10 + 1];
   char StrNumFilesPerUsr[10 + 1];
   char FileSizePerUsrStr[Fil_MAX_BYTES_FILE_SIZE_STRING + 1];
   char *Class = (FileZone == Brw_UNKNOWN) ? "DAT_N_LINE_TOP" :
	                                     "DAT";

   if (SizeOfFileZones->NumUsrs == -1)	// Not applicable
     {
      Str_Copy (StrNumFoldersPerUsr,"-",
                10);
      Str_Copy (StrNumFilesPerUsr,"-",
                10);
      Str_Copy (FileSizePerUsrStr,"-",
                Fil_MAX_BYTES_FILE_SIZE_STRING);
     }
   else
     {
      snprintf (StrNumFoldersPerUsr,sizeof (StrNumFoldersPerUsr),
	        "%.1f",
                SizeOfFileZones->NumUsrs ? (double) SizeOfFileZones->NumFolders /
        	                           (double) SizeOfFileZones->NumUsrs :
        	                           0.0);
      snprintf (StrNumFilesPerUsr,sizeof (StrNumFilesPerUsr),
	        "%.1f",
                SizeOfFileZones->NumUsrs ? (double) SizeOfFileZones->NumFiles /
        	                           (double) SizeOfFileZones->NumUsrs :
        	                           0.0);
      Fil_WriteFileSizeFull (SizeOfFileZones->NumUsrs ? (double) SizeOfFileZones->Size /
	                                                (double) SizeOfFileZones->NumUsrs :
	                                                0.0,
	                     FileSizePerUsrStr);
     }

   fprintf (Gbl.F.Out,"<tr>"
                      "<td class=\"%s LEFT_MIDDLE\">"
                      "%s"
                      "</td>"
                      "<td class=\"%s RIGHT_MIDDLE\">"
                      "%s"
                      "</td>"
                      "<td class=\"%s RIGHT_MIDDLE\">"
                      "%s"
                      "</td>"
                      "<td class=\"%s RIGHT_MIDDLE\">"
                      "%s"
                      "</td>"
	              "</tr>",
            Class,NameOfFileZones,
            Class,StrNumFoldersPerUsr,
            Class,StrNumFilesPerUsr,
            Class,FileSizePerUsrStr);
  }

/*****************************************************************************/
/************ Show stats about Open Educational Resources (OERs) *************/
/*****************************************************************************/

static void Fig_GetAndShowOERsStats (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_open_educational_resources_oer;
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   extern const char *Txt_License;
   extern const char *Txt_No_of_private_files;
   extern const char *Txt_No_of_public_files;
   extern const char *Txt_LICENSES[Brw_NUM_LICENSES];
   Brw_License_t License;
   unsigned long NumFiles[2];

   /***** Start box and table *****/
   Box_StartBoxTable (NULL,Txt_FIGURE_TYPES[Fig_OER],NULL,
                      Hlp_ANALYTICS_Figures_open_educational_resources_oer,Box_NOT_CLOSABLE,2);

   /***** Write table heading *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"LEFT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "</tr>",
            Txt_License,
            Txt_No_of_private_files,
            Txt_No_of_public_files);

   for (License = 0;
	License < Brw_NUM_LICENSES;
	License++)
     {
      Fig_GetNumberOfOERsFromDB (Gbl.Scope.Current,License,NumFiles);

      fprintf (Gbl.F.Out,"<tr>"
                         "<td class=\"DAT LEFT_MIDDLE\">"
                         "%s"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%lu"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%lu"
                         "</td>"
                         "</tr>",
               Txt_LICENSES[License],
               NumFiles[0],
               NumFiles[1]);
     }

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/**************** Get the size of a file zone from database ******************/
/*****************************************************************************/

static void Fig_GetNumberOfOERsFromDB (Hie_Level_t Scope,Brw_License_t License,unsigned long NumFiles[2])
  {
   MYSQL_RES *mysql_res;
   MYSQL_ROW row;
   unsigned NumRows = 0;	// Initialized to avoid warning
   unsigned NumRow;
   unsigned Public;

   /***** Get the size of a file browser *****/
   switch (Scope)
     {
      case Hie_SYS:
         NumRows =
         (unsigned) DB_QuerySELECT (&mysql_res,"can not get number of OERs",
				    "SELECT Public,COUNT(*)"
				    " FROM files"
				    " WHERE License=%u"
				    " GROUP BY Public",
				    (unsigned) License);
         break;
      case Hie_CTY:
         NumRows =
         (unsigned) DB_QuerySELECT (&mysql_res,"can not get number of OERs",
				    "SELECT files.Public,COUNT(*)"
				    " FROM institutions,centres,degrees,courses,files"
				    " WHERE institutions.CtyCod=%ld"
				    " AND institutions.InsCod=centres.InsCod"
				    " AND centres.CtrCod=degrees.CtrCod"
				    " AND degrees.DegCod=courses.DegCod"
				    " AND courses.CrsCod=files.Cod"
				    " AND files.FileBrowser IN (%u,%u)"
				    " AND files.License=%u"
				    " GROUP BY files.Public",
				    Gbl.Hierarchy.Cty.CtyCod,
				    (unsigned) Brw_ADMI_DOC_CRS,
				    (unsigned) Brw_ADMI_SHR_CRS,
				    (unsigned) License);
         break;
      case Hie_INS:
         NumRows =
         (unsigned) DB_QuerySELECT (&mysql_res,"can not get number of OERs",
				    "SELECT files.Public,COUNT(*)"
				    " FROM centres,degrees,courses,files"
				    " WHERE centres.InsCod=%ld"
				    " AND centres.CtrCod=degrees.CtrCod"
				    " AND degrees.DegCod=courses.DegCod"
				    " AND courses.CrsCod=files.Cod"
				    " AND files.FileBrowser IN (%u,%u)"
				    " AND files.License=%u"
				    " GROUP BY files.Public",
				    Gbl.Hierarchy.Ins.InsCod,
				    (unsigned) Brw_ADMI_DOC_CRS,
				    (unsigned) Brw_ADMI_SHR_CRS,
				    (unsigned) License);
         break;
      case Hie_CTR:
         NumRows =
         (unsigned) DB_QuerySELECT (&mysql_res,"can not get number of OERs",
				    "SELECT files.Public,COUNT(*)"
				    " FROM degrees,courses,files"
				    " WHERE degrees.CtrCod=%ld"
				    " AND degrees.DegCod=courses.DegCod"
				    " AND courses.CrsCod=files.Cod"
				    " AND files.FileBrowser IN (%u,%u)"
				    " AND files.License=%u"
				    " GROUP BY files.Public",
				    Gbl.Hierarchy.Ctr.CtrCod,
				    (unsigned) Brw_ADMI_DOC_CRS,
				    (unsigned) Brw_ADMI_SHR_CRS,
				    (unsigned) License);
         break;
      case Hie_DEG:
         NumRows =
         (unsigned) DB_QuerySELECT (&mysql_res,"can not get number of OERs",
				    "SELECT files.Public,COUNT(*)"
				    " FROM courses,files"
				    " WHERE courses.DegCod=%ld"
				    " AND courses.CrsCod=files.Cod"
				    " AND files.FileBrowser IN (%u,%u)"
				    " AND files.License=%u"
				    " GROUP BY files.Public",
				    Gbl.Hierarchy.Deg.DegCod,
				    (unsigned) Brw_ADMI_DOC_CRS,
				    (unsigned) Brw_ADMI_SHR_CRS,
				    (unsigned) License);
         break;
      case Hie_CRS:
         NumRows =
         (unsigned) DB_QuerySELECT (&mysql_res,"can not get number of OERs",
				    "SELECT Public,COUNT(*)"
				    " FROM files"
				    " WHERE Cod=%ld"
				    " AND FileBrowser IN (%u,%u)"
				    " AND License=%u"
				    " GROUP BY Public",
				    Gbl.Hierarchy.Crs.CrsCod,
				    (unsigned) Brw_ADMI_DOC_CRS,
				    (unsigned) Brw_ADMI_SHR_CRS,
				    (unsigned) License);
         break;
      default:
	 Lay_WrongScopeExit ();
	 break;
     }

   /* Reset values to zero */
   NumFiles[0] = NumFiles[1] = 0L;

   for (NumRow = 0;
	NumRow < NumRows;
	NumRow++)
     {
      /* Get row */
      row = mysql_fetch_row (mysql_res);

      /* Get if public (row[0]) */
      Public = (row[0][0] == 'Y') ? 1 :
	                            0;

      /* Get number of files (row[1]) */
      if (sscanf (row[1],"%lu",&NumFiles[Public]) != 1)
         Lay_ShowErrorAndExit ("Error when getting number of files.");
     }

   /* Free structure that stores the query result */
   DB_FreeMySQLResult (&mysql_res);
  }

/*****************************************************************************/
/************************ Show stats about assignments ***********************/
/*****************************************************************************/

static void Fig_GetAndShowAssignmentsStats (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_assignments;
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   extern const char *Txt_Number_of_BR_assignments;
   extern const char *Txt_Number_of_BR_courses_with_BR_assignments;
   extern const char *Txt_Average_number_BR_of_ASSIG_BR_per_course;
   extern const char *Txt_Number_of_BR_notifications;
   unsigned NumAssignments;
   unsigned NumNotif;
   unsigned NumCoursesWithAssignments = 0;
   float NumAssignmentsPerCourse = 0.0;

   /***** Get the number of assignments from this location *****/
   if ((NumAssignments = Asg_GetNumAssignments (Gbl.Scope.Current,&NumNotif)))
      if ((NumCoursesWithAssignments = Asg_GetNumCoursesWithAssignments (Gbl.Scope.Current)) != 0)
         NumAssignmentsPerCourse = (float) NumAssignments / (float) NumCoursesWithAssignments;

   /***** Start box and table *****/
   Box_StartBoxTable (NULL,Txt_FIGURE_TYPES[Fig_ASSIGNMENTS],NULL,
                      Hlp_ANALYTICS_Figures_assignments,Box_NOT_CLOSABLE,2);

   /***** Write table heading *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "</tr>",
            Txt_Number_of_BR_assignments,
            Txt_Number_of_BR_courses_with_BR_assignments,
            Txt_Average_number_BR_of_ASSIG_BR_per_course,
            Txt_Number_of_BR_notifications);

   /***** Write number of assignments *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "%.2f"
                      "</td>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "</tr>",
            NumAssignments,
            NumCoursesWithAssignments,
            NumAssignmentsPerCourse,
            NumNotif);

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/************************ Show figures about projects ************************/
/*****************************************************************************/

static void Fig_GetAndShowProjectsStats (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_projects;
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   extern const char *Txt_Number_of_BR_projects;
   extern const char *Txt_Number_of_BR_courses_with_BR_projects;
   extern const char *Txt_Average_number_BR_of_projects_BR_per_course;
   unsigned NumProjects;
   unsigned NumCoursesWithProjects = 0;
   float NumProjectsPerCourse = 0.0;

   /***** Get the number of projects from this location *****/
   if ((NumProjects = Prj_GetNumProjects (Gbl.Scope.Current)))
      if ((NumCoursesWithProjects = Prj_GetNumCoursesWithProjects (Gbl.Scope.Current)) != 0)
         NumProjectsPerCourse = (float) NumProjects / (float) NumCoursesWithProjects;

   /***** Start box and table *****/
   Box_StartBoxTable (NULL,Txt_FIGURE_TYPES[Fig_PROJECTS],NULL,
                      Hlp_ANALYTICS_Figures_projects,Box_NOT_CLOSABLE,2);

   /***** Write table heading *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "</tr>",
            Txt_Number_of_BR_projects,
            Txt_Number_of_BR_courses_with_BR_projects,
            Txt_Average_number_BR_of_projects_BR_per_course);

   /***** Write number of projects *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "%.2f"
                      "</td>"
                      "</tr>",
            NumProjects,
            NumCoursesWithProjects,
            NumProjectsPerCourse);

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/********************** Show figures about test questions ********************/
/*****************************************************************************/

static void Fig_GetAndShowTestsStats (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_tests;
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   extern const char *Txt_Type_of_BR_answers;
   extern const char *Txt_Number_of_BR_courses_BR_with_test_BR_questions;
   extern const char *Txt_Number_of_BR_courses_with_BR_exportable_BR_test_BR_questions;
   extern const char *Txt_Number_BR_of_test_BR_questions;
   extern const char *Txt_Average_BR_number_BR_of_test_BR_questions_BR_per_course;
   extern const char *Txt_Number_of_BR_times_that_BR_questions_BR_have_been_BR_responded;
   extern const char *Txt_Average_BR_number_of_BR_times_that_BR_questions_BR_have_been_BR_responded_BR_per_course;
   extern const char *Txt_Average_BR_number_of_BR_times_that_BR_a_question_BR_has_been_BR_responded;
   extern const char *Txt_Average_BR_score_BR_per_question_BR_from_0_to_1;
   extern const char *Txt_TST_STR_ANSWER_TYPES[Tst_NUM_ANS_TYPES];
   extern const char *Txt_Total;
   Tst_AnswerType_t AnsType;
   struct Tst_Stats Stats;

   /***** Start box and table *****/
   Box_StartBoxTable (NULL,Txt_FIGURE_TYPES[Fig_TESTS],NULL,
                      Hlp_ANALYTICS_Figures_tests,Box_NOT_CLOSABLE,2);

   /***** Write table heading *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"LEFT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "</tr>",
            Txt_Type_of_BR_answers,
            Txt_Number_of_BR_courses_BR_with_test_BR_questions,
            Txt_Number_of_BR_courses_with_BR_exportable_BR_test_BR_questions,
            Txt_Number_BR_of_test_BR_questions,
            Txt_Average_BR_number_BR_of_test_BR_questions_BR_per_course,
            Txt_Number_of_BR_times_that_BR_questions_BR_have_been_BR_responded,
            Txt_Average_BR_number_of_BR_times_that_BR_questions_BR_have_been_BR_responded_BR_per_course,
            Txt_Average_BR_number_of_BR_times_that_BR_a_question_BR_has_been_BR_responded,
            Txt_Average_BR_score_BR_per_question_BR_from_0_to_1);

   for (AnsType = (Tst_AnswerType_t) 0;
	AnsType < Tst_NUM_ANS_TYPES;
	AnsType++)
     {
      /***** Get the stats about test questions from this location *****/
      Tst_GetTestStats (AnsType,&Stats);

      /***** Write number of assignments *****/
      fprintf (Gbl.F.Out,"<tr>"
                         "<td class=\"DAT LEFT_MIDDLE\">"
                         "%s"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%u"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%u (%.1f%%)"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%u"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%.2f"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%lu"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%.2f"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%.2f"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%.2f"
                         "</td>"
                         "</tr>",
               Txt_TST_STR_ANSWER_TYPES[AnsType],
               Stats.NumCoursesWithQuestions,
               Stats.NumCoursesWithPluggableQuestions,
               Stats.NumCoursesWithQuestions ? (float) Stats.NumCoursesWithPluggableQuestions * 100.0 /
        	                               (float) Stats.NumCoursesWithQuestions :
        	                               0.0,
               Stats.NumQsts,
               Stats.AvgQstsPerCourse,
               Stats.NumHits,
               Stats.AvgHitsPerCourse,
               Stats.AvgHitsPerQuestion,
               Stats.AvgScorePerQuestion);
     }

   /***** Get the stats about test questions from this location *****/
   Tst_GetTestStats (Tst_ANS_ALL,&Stats);

   /***** Write number of assignments *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<td class=\"DAT_N_LINE_TOP LEFT_MIDDLE\">"
                      "%s"
                      "</td>"
                      "<td class=\"DAT_N_LINE_TOP RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT_N_LINE_TOP RIGHT_MIDDLE\">"
                      "%u (%.1f%%)"
                      "</td>"
                      "<td class=\"DAT_N_LINE_TOP RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT_N_LINE_TOP RIGHT_MIDDLE\">"
                      "%.2f"
                      "</td>"
                      "<td class=\"DAT_N_LINE_TOP RIGHT_MIDDLE\">"
                      "%lu"
                      "</td>"
                      "<td class=\"DAT_N_LINE_TOP RIGHT_MIDDLE\">"
                      "%.2f"
                      "</td>"
                      "<td class=\"DAT_N_LINE_TOP RIGHT_MIDDLE\">"
                      "%.2f"
                      "</td>"
                      "<td class=\"DAT_N_LINE_TOP RIGHT_MIDDLE\">"
                      "%.2f"
                      "</td>"
                      "</tr>",
            Txt_Total,
            Stats.NumCoursesWithQuestions,
            Stats.NumCoursesWithPluggableQuestions,
            Stats.NumCoursesWithQuestions ? (float) Stats.NumCoursesWithPluggableQuestions * 100.0 /
        	                            (float) Stats.NumCoursesWithQuestions :
        	                            0.0,
            Stats.NumQsts,
            Stats.AvgQstsPerCourse,
            Stats.NumHits,
            Stats.AvgHitsPerCourse,
            Stats.AvgHitsPerQuestion,
            Stats.AvgScorePerQuestion);

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/*************************** Show stats about games **************************/
/*****************************************************************************/

static void Fig_GetAndShowGamesStats (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_games;
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   extern const char *Txt_Number_of_BR_games;
   extern const char *Txt_Number_of_BR_courses_with_BR_games;
   extern const char *Txt_Average_number_BR_of_games_BR_per_course;
   unsigned NumGames;
   unsigned NumCoursesWithGames = 0;
   float NumGamesPerCourse = 0.0;

   /***** Get the number of games from this location *****/
   if ((NumGames = Gam_GetNumGames (Gbl.Scope.Current)))
      if ((NumCoursesWithGames = Gam_GetNumCoursesWithGames (Gbl.Scope.Current)) != 0)
         NumGamesPerCourse = (float) NumGames / (float) NumCoursesWithGames;

   /***** Start box and table *****/
   Box_StartBoxTable (NULL,Txt_FIGURE_TYPES[Fig_GAMES],NULL,
                      Hlp_ANALYTICS_Figures_games,Box_NOT_CLOSABLE,2);

   /***** Write table heading *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "</tr>",
            Txt_Number_of_BR_games,
            Txt_Number_of_BR_courses_with_BR_games,
            Txt_Average_number_BR_of_games_BR_per_course);

   /***** Write number of games *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "%.2f"
                      "</td>"
                      "</tr>",
            NumGames,
            NumCoursesWithGames,
            NumGamesPerCourse);

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/******************** Get and show number of social notes ********************/
/*****************************************************************************/

static void Fig_GetAndShowSocialActivityStats (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_timeline;
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   extern const char *Txt_Type;
   extern const char *Txt_No_of_social_posts;
   extern const char *Txt_No_of_users;
   extern const char *Txt_PERCENT_of_users;
   extern const char *Txt_No_of_posts_BR_per_user;
   extern const char *Txt_TIMELINE_NOTE[TL_NUM_NOTE_TYPES];
   extern const char *Txt_Total;
   MYSQL_RES *mysql_res;
   MYSQL_ROW row;
   TL_NoteType_t NoteType;
   unsigned long NumSocialNotes;
   unsigned long NumRows;
   unsigned NumUsrs;
   unsigned NumUsrsTotal;

   /***** Start box and table *****/
   Box_StartBoxTable (NULL,Txt_FIGURE_TYPES[Fig_TIMELINE],NULL,
                      Hlp_ANALYTICS_Figures_timeline,Box_NOT_CLOSABLE,2);

   /***** Heading row *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"LEFT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "</tr>",
            Txt_Type,
            Txt_No_of_social_posts,
            Txt_No_of_users,
            Txt_PERCENT_of_users,
            Txt_No_of_posts_BR_per_user);

   /***** Get total number of users *****/
   NumUsrsTotal = (Gbl.Scope.Current == Hie_SYS) ? Usr_GetTotalNumberOfUsersInPlatform () :
                                                         Usr_GetTotalNumberOfUsersInCourses (Gbl.Scope.Current,
                                                                                             1 << Rol_STD |
                                                                                             1 << Rol_NET |
                                                                                             1 << Rol_TCH);

   /***** Get total number of following/followers from database *****/
   for (NoteType = (TL_NoteType_t) 0;
	NoteType < TL_NUM_NOTE_TYPES;
	NoteType++)
     {
      switch (Gbl.Scope.Current)
	{
	 case Hie_SYS:
	    NumRows = DB_QuerySELECT (&mysql_res,"can not get number of social notes",
				      "SELECT COUNT(*),"
					     "COUNT(DISTINCT UsrCod)"
				      " FROM social_notes WHERE NoteType=%u",
				      NoteType);
	    break;
	 case Hie_CTY:
	    NumRows = DB_QuerySELECT (&mysql_res,"can not get number of social notes",
				      "SELECT COUNT(DISTINCT social_notes.NotCod),"
					     "COUNT(DISTINCT social_notes.UsrCod)"
				      " FROM institutions,centres,degrees,courses,crs_usr,social_notes"
				      " WHERE institutions.CtyCod=%ld"
				      " AND institutions.InsCod=centres.InsCod"
				      " AND centres.CtrCod=degrees.CtrCod"
				      " AND degrees.DegCod=courses.DegCod"
				      " AND courses.CrsCod=crs_usr.CrsCod"
				      " AND crs_usr.UsrCod=social_notes.UsrCod"
				      " AND social_notes.NoteType=%u",
				      Gbl.Hierarchy.Cty.CtyCod,
				      (unsigned) NoteType);
	    break;
	 case Hie_INS:
	    NumRows = DB_QuerySELECT (&mysql_res,"can not get number of social notes",
				      "SELECT COUNT(DISTINCT social_notes.NotCod),"
					     "COUNT(DISTINCT social_notes.UsrCod)"
				      " FROM centres,degrees,courses,crs_usr,social_notes"
				      " WHERE centres.InsCod=%ld"
				      " AND centres.CtrCod=degrees.CtrCod"
				      " AND degrees.DegCod=courses.DegCod"
				      " AND courses.CrsCod=crs_usr.CrsCod"
				      " AND crs_usr.UsrCod=social_notes.UsrCod"
				      " AND social_notes.NoteType=%u",
				      Gbl.Hierarchy.Ins.InsCod,
				      (unsigned) NoteType);
	    break;
	 case Hie_CTR:
	    NumRows = DB_QuerySELECT (&mysql_res,"can not get number of social notes",
				      "SELECT COUNT(DISTINCT social_notes.NotCod),"
					     "COUNT(DISTINCT social_notes.UsrCod)"
				      " FROM degrees,courses,crs_usr,social_notes"
				      " WHERE degrees.CtrCod=%ld"
				      " AND degrees.DegCod=courses.DegCod"
				      " AND courses.CrsCod=crs_usr.CrsCod"
				      " AND crs_usr.UsrCod=social_notes.UsrCod"
				      " AND social_notes.NoteType=%u",
				      Gbl.Hierarchy.Ctr.CtrCod,
				      (unsigned) NoteType);
	    break;
	 case Hie_DEG:
	    NumRows = DB_QuerySELECT (&mysql_res,"can not get number of social notes",
				      "SELECT COUNT(DISTINCT social_notes.NotCod),"
					     "COUNT(DISTINCT social_notes.UsrCod)"
				      " FROM courses,crs_usr,social_notes"
				      " WHERE courses.DegCod=%ld"
				      " AND courses.CrsCod=crs_usr.CrsCod"
				      " AND crs_usr.UsrCod=social_notes.UsrCod"
				      " AND social_notes.NoteType=%u",
				      Gbl.Hierarchy.Deg.DegCod,
				      (unsigned) NoteType);
	    break;
	 case Hie_CRS:
	    NumRows = DB_QuerySELECT (&mysql_res,"can not get number of social notes",
				      "SELECT COUNT(DISTINCT social_notes.NotCod),"
					     "COUNT(DISTINCT social_notes.UsrCod)"
				      " FROM crs_usr,social_notes"
				      " WHERE crs_usr.CrsCod=%ld"
				      " AND crs_usr.UsrCod=social_notes.UsrCod"
				      " AND social_notes.NoteType=%u",
				      Gbl.Hierarchy.Crs.CrsCod,
				      (unsigned) NoteType);
	    break;
	 default:
	    Lay_WrongScopeExit ();
	    NumRows = 0;	// Initialized to avoid warning
	    break;
	}
      NumSocialNotes = 0;
      NumUsrs = 0;

      if (NumRows)
	{
	 /***** Get number of social notes and number of users *****/
	 row = mysql_fetch_row (mysql_res);

	 /* Get number of social notes */
	 if (row[0])
	    if (sscanf (row[0],"%lu",&NumSocialNotes) != 1)
	       NumSocialNotes = 0;

	 /* Get number of users */
	 if (row[1])
	    if (sscanf (row[1],"%u",&NumUsrs) != 1)
	       NumUsrs = 0;
	}

      /***** Free structure that stores the query result *****/
      DB_FreeMySQLResult (&mysql_res);

      /***** Write number of social notes and number of users *****/
      fprintf (Gbl.F.Out,"<tr>"
                         "<td class=\"DAT LEFT_MIDDLE\">"
                         "%s"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%lu"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%u"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%5.2f%%"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%.2f"
                         "</td>"
                         "</tr>",
               Txt_TIMELINE_NOTE[NoteType],
               NumSocialNotes,
               NumUsrs,
               NumUsrsTotal ? (float) NumUsrs * 100.0 / (float) NumUsrsTotal :
        	              0.0,
               NumUsrs ? (float) NumSocialNotes / (float) NumUsrs :
        	         0.0);
     }

   /***** Get and write totals *****/
   switch (Gbl.Scope.Current)
     {
      case Hie_SYS:
	 NumRows = DB_QuerySELECT (&mysql_res,"can not get number of social notes",
				   "SELECT COUNT(*),"
					  "COUNT(DISTINCT UsrCod)"
				   " FROM social_notes");
	 break;
      case Hie_CTY:
	 NumRows = DB_QuerySELECT (&mysql_res,"can not get number of social notes",
				   "SELECT COUNT(DISTINCT social_notes.NotCod),"
					  "COUNT(DISTINCT social_notes.UsrCod)"
				   " FROM institutions,centres,degrees,courses,crs_usr,social_notes"
				   " WHERE institutions.CtyCod=%ld"
				   " AND institutions.InsCod=centres.InsCod"
				   " AND centres.CtrCod=degrees.CtrCod"
				   " AND degrees.DegCod=courses.DegCod"
				   " AND courses.CrsCod=crs_usr.CrsCod"
				   " AND crs_usr.UsrCod=social_notes.UsrCod",
				   Gbl.Hierarchy.Cty.CtyCod);
	 break;
      case Hie_INS:
	 NumRows = DB_QuerySELECT (&mysql_res,"can not get number of social notes",
				   "SELECT COUNT(DISTINCT social_notes.NotCod),"
					  "COUNT(DISTINCT social_notes.UsrCod)"
				   " FROM centres,degrees,courses,crs_usr,social_notes"
				   " WHERE centres.InsCod=%ld"
				   " AND centres.CtrCod=degrees.CtrCod"
				   " AND degrees.DegCod=courses.DegCod"
				   " AND courses.CrsCod=crs_usr.CrsCod"
				   " AND crs_usr.UsrCod=social_notes.UsrCod",
				   Gbl.Hierarchy.Ins.InsCod);
	 break;
      case Hie_CTR:
	 NumRows = DB_QuerySELECT (&mysql_res,"can not get number of social notes",
				   "SELECT COUNT(DISTINCT social_notes.NotCod),"
					  "COUNT(DISTINCT social_notes.UsrCod)"
				   " FROM degrees,courses,crs_usr,social_notes"
				   " WHERE degrees.CtrCod=%ld"
				   " AND degrees.DegCod=courses.DegCod"
				   " AND courses.CrsCod=crs_usr.CrsCod"
				   " AND crs_usr.UsrCod=social_notes.UsrCod",
				   Gbl.Hierarchy.Ctr.CtrCod);
	 break;
      case Hie_DEG:
	 NumRows = DB_QuerySELECT (&mysql_res,"can not get number of social notes",
				   "SELECT COUNT(DISTINCT social_notes.NotCod),"
					  "COUNT(DISTINCT social_notes.UsrCod)"
				   " FROM courses,crs_usr,social_notes"
				   " WHERE courses.DegCod=%ld"
				   " AND courses.CrsCod=crs_usr.CrsCod"
				   " AND crs_usr.UsrCod=social_notes.UsrCod",
				   Gbl.Hierarchy.Deg.DegCod);
	 break;
      case Hie_CRS:
	 NumRows = DB_QuerySELECT (&mysql_res,"can not get number of social notes",
				   "SELECT COUNT(DISTINCT social_notes.NotCod),"
					  "COUNT(DISTINCT social_notes.UsrCod)"
				   " FROM crs_usr,social_notes"
				   " WHERE crs_usr.CrsCod=%ld"
				   " AND crs_usr.UsrCod=social_notes.UsrCod",
				   Gbl.Hierarchy.Crs.CrsCod);
	 break;
      default:
	 Lay_WrongScopeExit ();
	 NumRows = 0;	// Initialized to avoid warning
	 break;
     }
   NumSocialNotes = 0;
   NumUsrs = 0;

   if (NumRows)
     {
      /* Get number of social notes and number of users */
      row = mysql_fetch_row (mysql_res);

      /* Get number of social notes */
      if (row[0])
	 if (sscanf (row[0],"%lu",&NumSocialNotes) != 1)
	    NumSocialNotes = 0;

      /* Get number of users */
      if (row[1])
	 if (sscanf (row[1],"%u",&NumUsrs) != 1)
	    NumUsrs = 0;
     }

   /* Free structure that stores the query result */
   DB_FreeMySQLResult (&mysql_res);

   /* Write totals */
   fprintf (Gbl.F.Out,"<tr>"
		      "<td class=\"DAT_N_LINE_TOP LEFT_MIDDLE\">"
		      "%s"
		      "</td>"
		      "<td class=\"DAT_N_LINE_TOP RIGHT_MIDDLE\">"
		      "%lu"
		      "</td>"
		      "<td class=\"DAT_N_LINE_TOP RIGHT_MIDDLE\">"
		      "%u"
		      "</td>"
		      "<td class=\"DAT_N_LINE_TOP RIGHT_MIDDLE\">"
		      "%5.2f%%"
		      "</td>"
		      "<td class=\"DAT_N_LINE_TOP RIGHT_MIDDLE\">"
		      "%.2f"
		      "</td>"
		      "</tr>",
	    Txt_Total,
	    NumSocialNotes,
	    NumUsrs,
	    NumUsrsTotal ? (float) NumUsrs * 100.0 / (float) NumUsrsTotal :
			   0.0,
	    NumUsrs ? (float) NumSocialNotes / (float) NumUsrs :
		      0.0);

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/************** Get and show number of following and followers ***************/
/*****************************************************************************/

static void Fig_GetAndShowFollowStats (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_followed_followers;
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   extern const char *Txt_Users;
   extern const char *Txt_No_of_users;
   extern const char *Txt_PERCENT_of_users;
   extern const char *Txt_Followed;
   extern const char *Txt_Followers;
   extern const char *Txt_FollowPerFollow[2];
   const char *FieldDB[2] =
     {
      "FollowedCod",
      "FollowerCod"
     };
   MYSQL_RES *mysql_res;
   MYSQL_ROW row;
   unsigned Fol;
   unsigned NumUsrsTotal;
   unsigned NumUsrs;
   float Average;

   /***** Start box and table *****/
   Box_StartBoxTable (NULL,Txt_FIGURE_TYPES[Fig_FOLLOW],NULL,
                      Hlp_ANALYTICS_Figures_followed_followers,Box_NOT_CLOSABLE,2);

   /***** Heading row *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"LEFT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "</tr>",
            Txt_Users,
            Txt_No_of_users,
            Txt_PERCENT_of_users);

   /***** Get total number of users *****/
   NumUsrsTotal = (Gbl.Scope.Current == Hie_SYS) ? Usr_GetTotalNumberOfUsersInPlatform () :
                                                         Usr_GetTotalNumberOfUsersInCourses (Gbl.Scope.Current,
                                                                                             1 << Rol_STD |
                                                                                             1 << Rol_NET |
                                                                                             1 << Rol_TCH);

   /***** Get total number of following/followers from database *****/
   for (Fol = 0;
	Fol < 2;
	Fol++)
     {
      switch (Gbl.Scope.Current)
	{
	 case Hie_SYS:
	    NumUsrs =
	    (unsigned) DB_QueryCOUNT ("can not get the total number"
				      " of following/followers",
				      "SELECT COUNT(DISTINCT %s) FROM usr_follow",
				      FieldDB[Fol]);
	    break;
	 case Hie_CTY:
	    NumUsrs =
	    (unsigned) DB_QueryCOUNT ("can not get the total number"
				      " of following/followers",
				      "SELECT COUNT(DISTINCT usr_follow.%s)"
				      " FROM institutions,centres,degrees,courses,crs_usr,usr_follow"
				      " WHERE institutions.CtyCod=%ld"
				      " AND institutions.InsCod=centres.InsCod"
				      " AND centres.CtrCod=degrees.CtrCod"
				      " AND degrees.DegCod=courses.DegCod"
				      " AND courses.CrsCod=crs_usr.CrsCod"
				      " AND crs_usr.UsrCod=usr_follow.%s",
				      FieldDB[Fol],
				      Gbl.Hierarchy.Cty.CtyCod,
				      FieldDB[Fol]);
	    break;
	 case Hie_INS:
	    NumUsrs =
	    (unsigned) DB_QueryCOUNT ("can not get the total number"
				      " of following/followers",
				      "SELECT COUNT(DISTINCT usr_follow.%s)"
				      " FROM centres,degrees,courses,crs_usr,usr_follow"
				      " WHERE centres.InsCod=%ld"
				      " AND centres.CtrCod=degrees.CtrCod"
				      " AND degrees.DegCod=courses.DegCod"
				      " AND courses.CrsCod=crs_usr.CrsCod"
				      " AND crs_usr.UsrCod=usr_follow.%s",
				      FieldDB[Fol],
				      Gbl.Hierarchy.Ins.InsCod,
				      FieldDB[Fol]);
	    break;
	 case Hie_CTR:
	    NumUsrs =
	    (unsigned) DB_QueryCOUNT ("can not get the total number"
				      " of following/followers",
				      "SELECT COUNT(DISTINCT usr_follow.%s)"
				      " FROM degrees,courses,crs_usr,usr_follow"
				      " WHERE degrees.CtrCod=%ld"
				      " AND degrees.DegCod=courses.DegCod"
				      " AND courses.CrsCod=crs_usr.CrsCod"
				      " AND crs_usr.UsrCod=usr_follow.%s",
				      FieldDB[Fol],
				      Gbl.Hierarchy.Ctr.CtrCod,
				      FieldDB[Fol]);
	    break;
	 case Hie_DEG:
	    NumUsrs =
	    (unsigned) DB_QueryCOUNT ("can not get the total number"
				      " of following/followers",
				      "SELECT COUNT(DISTINCT usr_follow.%s)"
				      " FROM courses,crs_usr,usr_follow"
				      " WHERE courses.DegCod=%ld"
				      " AND courses.CrsCod=crs_usr.CrsCod"
				      " AND crs_usr.UsrCod=usr_follow.%s",
				      FieldDB[Fol],
				      Gbl.Hierarchy.Deg.DegCod,
				      FieldDB[Fol]);
	    break;
	 case Hie_CRS:
	    NumUsrs =
	    (unsigned) DB_QueryCOUNT ("can not get the total number"
				      " of following/followers",
				      "SELECT COUNT(DISTINCT usr_follow.%s)"
				      " FROM crs_usr,usr_follow"
				      " WHERE crs_usr.CrsCod=%ld"
				      " AND crs_usr.UsrCod=usr_follow.%s",
				      FieldDB[Fol],
				      Gbl.Hierarchy.Crs.CrsCod,
				      FieldDB[Fol]);
	    break;
	 default:
	    Lay_WrongScopeExit ();
	    NumUsrs = 0;	// Not reached. Initialized to av oid warning
	    break;
	}

      /***** Write number of followed / followers *****/
      fprintf (Gbl.F.Out,"<tr>"
                         "<td class=\"DAT LEFT_MIDDLE\">"
                         "%s"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%u"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%5.2f%%"
                         "</td>"
                         "</tr>",
               Fol == 0 ? Txt_Followed :
        	          Txt_Followers,
               NumUsrs,
               NumUsrsTotal ? (float) NumUsrs * 100.0 /
        	              (float) NumUsrsTotal :
        	              0.0);
     }

   /***** Write number of followed/followers per follower/followed *****/
   for (Fol = 0;
	Fol < 2;
	Fol++)
     {
      switch (Gbl.Scope.Current)
	{
	 case Hie_SYS:
	    DB_QuerySELECT (&mysql_res,"can not get number of questions"
				       " per survey",
			    "SELECT AVG(N) FROM "
			    "(SELECT COUNT(%s) AS N"
			    " FROM usr_follow"
			    " GROUP BY %s) AS F",
			    FieldDB[Fol],
			    FieldDB[1 - Fol]);
	    break;
	 case Hie_CTY:
	    DB_QuerySELECT (&mysql_res,"can not get number of questions"
				       " per survey",
			    "SELECT AVG(N) FROM "
			    "(SELECT COUNT(DISTINCT usr_follow.%s) AS N"
			    " FROM institutions,centres,degrees,courses,crs_usr,usr_follow"
			    " WHERE institutions.CtyCod=%ld"
			    " AND institutions.InsCod=centres.InsCod"
			    " AND centres.CtrCod=degrees.CtrCod"
			    " AND degrees.DegCod=courses.DegCod"
			    " AND courses.CrsCod=crs_usr.CrsCod"
			    " AND crs_usr.UsrCod=usr_follow.%s"
			    " GROUP BY %s) AS F",
			    FieldDB[Fol],
			    Gbl.Hierarchy.Cty.CtyCod,
			    FieldDB[Fol],
			    FieldDB[1 - Fol]);
	    break;
	 case Hie_INS:
	    DB_QuerySELECT (&mysql_res,"can not get number of questions"
				       " per survey",
			    "SELECT AVG(N) FROM "
			    "(SELECT COUNT(DISTINCT usr_follow.%s) AS N"
			    " FROM centres,degrees,courses,crs_usr,usr_follow"
			    " WHERE centres.InsCod=%ld"
			    " AND centres.CtrCod=degrees.CtrCod"
			    " AND degrees.DegCod=courses.DegCod"
			    " AND courses.CrsCod=crs_usr.CrsCod"
			    " AND crs_usr.UsrCod=usr_follow.%s"
			    " GROUP BY %s) AS F",
			    FieldDB[Fol],
			    Gbl.Hierarchy.Ins.InsCod,
			    FieldDB[Fol],
			    FieldDB[1 - Fol]);
	    break;
	 case Hie_CTR:
	    DB_QuerySELECT (&mysql_res,"can not get number of questions"
				       " per survey",
			    "SELECT AVG(N) FROM "
			    "(SELECT COUNT(DISTINCT usr_follow.%s) AS N"
			    " FROM degrees,courses,crs_usr,usr_follow"
			    " WHERE degrees.CtrCod=%ld"
			    " AND degrees.DegCod=courses.DegCod"
			    " AND courses.CrsCod=crs_usr.CrsCod"
			    " AND crs_usr.UsrCod=usr_follow.%s"
			    " GROUP BY %s) AS F",
			    FieldDB[Fol],
			    Gbl.Hierarchy.Ctr.CtrCod,
			    FieldDB[Fol],
			    FieldDB[1 - Fol]);
	    break;
	 case Hie_DEG:
	    DB_QuerySELECT (&mysql_res,"can not get number of questions"
				       " per survey",
			    "SELECT AVG(N) FROM "
			    "(SELECT COUNT(DISTINCT usr_follow.%s) AS N"
			    " FROM courses,crs_usr,usr_follow"
			    " WHERE courses.DegCod=%ld"
			    " AND courses.CrsCod=crs_usr.CrsCod"
			    " AND crs_usr.UsrCod=usr_follow.%s"
			    " GROUP BY %s) AS F",
			    FieldDB[Fol],
			    Gbl.Hierarchy.Deg.DegCod,
			    FieldDB[Fol],
			    FieldDB[1 - Fol]);
	    break;
	 case Hie_CRS:
	    DB_QuerySELECT (&mysql_res,"can not get number of questions"
				       " per survey",
			    "SELECT AVG(N) FROM "
			    "(SELECT COUNT(DISTINCT usr_follow.%s) AS N"
			    " FROM crs_usr,usr_follow"
			    " WHERE crs_usr.CrsCod=%ld"
			    " AND crs_usr.UsrCod=usr_follow.%s"
			    " GROUP BY %s) AS F",
			    FieldDB[Fol],
			    Gbl.Hierarchy.Crs.CrsCod,
			    FieldDB[Fol],
			    FieldDB[1 - Fol]);
	    break;
	 default:
	    Lay_WrongScopeExit ();
	    break;
	}

      /***** Get average *****/
      row = mysql_fetch_row (mysql_res);
      Average = Str_GetFloatNumFromStr (row[0]);

      /***** Free structure that stores the query result *****/
      DB_FreeMySQLResult (&mysql_res);

      /***** Write number of followed per follower *****/
      fprintf (Gbl.F.Out,"<tr>"
			 "<td class=\"DAT LEFT_MIDDLE\">"
			 "%s"
			 "</td>"
			 "<td class=\"DAT RIGHT_MIDDLE\">"
			 "%5.2f"
			 "</td>"
			 "<td>"
			 "</td>"
			 "</tr>",
	       Txt_FollowPerFollow[Fol],
	       Average);
     }

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/************************** Show figures about forums ************************/
/*****************************************************************************/

static void Fig_GetAndShowForumStats (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_forums;
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   extern const char *Txt_Scope;
   extern const char *Txt_Forums;
   extern const char *Txt_No_of_forums;
   extern const char *Txt_No_of_threads;
   extern const char *Txt_No_of_posts;
   extern const char *Txt_Number_of_BR_notifications;
   extern const char *Txt_No_of_threads_BR_per_forum;
   extern const char *Txt_No_of_posts_BR_per_thread;
   extern const char *Txt_No_of_posts_BR_per_forum;
   struct Fig_FiguresForum FiguresForum;

   /***** Reset total stats *****/
   FiguresForum.NumForums           = 0;
   FiguresForum.NumThreads          = 0;
   FiguresForum.NumPosts            = 0;
   FiguresForum.NumUsrsToBeNotifiedByEMail = 0;

   /***** Start box and table *****/
   Box_StartBoxTable (NULL,Txt_FIGURE_TYPES[Fig_FORUMS],NULL,
                      Hlp_ANALYTICS_Figures_forums,Box_NOT_CLOSABLE,2);

   /***** Write table heading *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"LEFT_TOP\" style=\"width:20px;\">"
                      "<img src=\"%s/comments.svg\""
                      " alt=\"%s\" title=\"%s\""
                      " class=\"ICO16x16\" />"
                      "</th>"
                      "<th class=\"LEFT_TOP\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_TOP\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_TOP\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_TOP\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_TOP\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_TOP\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_TOP\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_TOP\">"
                      "%s"
                      "</th>"
                      "</tr>",
            Cfg_URL_ICON_PUBLIC,
            Txt_Scope,
            Txt_Scope,
            Txt_Forums,
            Txt_No_of_forums,
            Txt_No_of_threads,
            Txt_No_of_posts,
            Txt_Number_of_BR_notifications,
            Txt_No_of_threads_BR_per_forum,
            Txt_No_of_posts_BR_per_thread,
            Txt_No_of_posts_BR_per_forum);

   /***** Write a row for each type of forum *****/
   switch (Gbl.Scope.Current)
     {
      case Hie_SYS:
         Fig_ShowStatOfAForumType (For_FORUM_GLOBAL_USRS     ,-1L,-1L,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_GLOBAL_TCHS     ,-1L,-1L,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM__SWAD__USRS       ,-1L,-1L,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM__SWAD__TCHS       ,-1L,-1L,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_INSTIT_USRS,-1L,-1L,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_INSTIT_TCHS,-1L,-1L,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_CENTRE_USRS     ,-1L,-1L,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_CENTRE_TCHS     ,-1L,-1L,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_DEGREE_USRS     ,-1L,-1L,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_DEGREE_TCHS     ,-1L,-1L,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_COURSE_USRS     ,-1L,-1L,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_COURSE_TCHS     ,-1L,-1L,-1L,-1L,-1L,&FiguresForum);
         break;
      case Hie_CTY:
         Fig_ShowStatOfAForumType (For_FORUM_INSTIT_USRS,Gbl.Hierarchy.Cty.CtyCod,-1L,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_INSTIT_TCHS,Gbl.Hierarchy.Cty.CtyCod,-1L,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_CENTRE_USRS     ,Gbl.Hierarchy.Cty.CtyCod,-1L,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_CENTRE_TCHS     ,Gbl.Hierarchy.Cty.CtyCod,-1L,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_DEGREE_USRS     ,Gbl.Hierarchy.Cty.CtyCod,-1L,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_DEGREE_TCHS     ,Gbl.Hierarchy.Cty.CtyCod,-1L,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_COURSE_USRS     ,Gbl.Hierarchy.Cty.CtyCod,-1L,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_COURSE_TCHS     ,Gbl.Hierarchy.Cty.CtyCod,-1L,-1L,-1L,-1L,&FiguresForum);
         break;
      case Hie_INS:
         Fig_ShowStatOfAForumType (For_FORUM_INSTIT_USRS,-1L,Gbl.Hierarchy.Ins.InsCod,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_INSTIT_TCHS,-1L,Gbl.Hierarchy.Ins.InsCod,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_CENTRE_USRS     ,-1L,Gbl.Hierarchy.Ins.InsCod,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_CENTRE_TCHS     ,-1L,Gbl.Hierarchy.Ins.InsCod,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_DEGREE_USRS     ,-1L,Gbl.Hierarchy.Ins.InsCod,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_DEGREE_TCHS     ,-1L,Gbl.Hierarchy.Ins.InsCod,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_COURSE_USRS     ,-1L,Gbl.Hierarchy.Ins.InsCod,-1L,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_COURSE_TCHS     ,-1L,Gbl.Hierarchy.Ins.InsCod,-1L,-1L,-1L,&FiguresForum);
         break;
      case Hie_CTR:
         Fig_ShowStatOfAForumType (For_FORUM_CENTRE_USRS,-1L,-1L,Gbl.Hierarchy.Ctr.CtrCod,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_CENTRE_TCHS,-1L,-1L,Gbl.Hierarchy.Ctr.CtrCod,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_DEGREE_USRS,-1L,-1L,Gbl.Hierarchy.Ctr.CtrCod,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_DEGREE_TCHS,-1L,-1L,Gbl.Hierarchy.Ctr.CtrCod,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_COURSE_USRS,-1L,-1L,Gbl.Hierarchy.Ctr.CtrCod,-1L,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_COURSE_TCHS,-1L,-1L,Gbl.Hierarchy.Ctr.CtrCod,-1L,-1L,&FiguresForum);
         break;
      case Hie_DEG:
         Fig_ShowStatOfAForumType (For_FORUM_DEGREE_USRS,-1L,-1L,-1L,Gbl.Hierarchy.Deg.DegCod,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_DEGREE_TCHS,-1L,-1L,-1L,Gbl.Hierarchy.Deg.DegCod,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_COURSE_USRS,-1L,-1L,-1L,Gbl.Hierarchy.Deg.DegCod,-1L,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_COURSE_TCHS,-1L,-1L,-1L,Gbl.Hierarchy.Deg.DegCod,-1L,&FiguresForum);
         break;
      case Hie_CRS:
         Fig_ShowStatOfAForumType (For_FORUM_COURSE_USRS,-1L,-1L,-1L,-1L,Gbl.Hierarchy.Crs.CrsCod,&FiguresForum);
         Fig_ShowStatOfAForumType (For_FORUM_COURSE_TCHS,-1L,-1L,-1L,-1L,Gbl.Hierarchy.Crs.CrsCod,&FiguresForum);
         break;
      default:
	 Lay_WrongScopeExit ();
	 break;
     }

   Fig_WriteForumTotalStats (&FiguresForum);

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/************************* Show stats of a forum type ************************/
/*****************************************************************************/

static void Fig_ShowStatOfAForumType (For_ForumType_t ForumType,
                                      long CtyCod,long InsCod,long CtrCod,long DegCod,long CrsCod,
                                      struct Fig_FiguresForum *FiguresForum)
  {
   extern const char *Txt_Courses;
   extern const char *Txt_Degrees;
   extern const char *Txt_Centres;
   extern const char *Txt_Institutions;
   extern const char *Txt_General;
   extern const char *Txt_only_teachers;

   switch (ForumType)
     {
      case For_FORUM_GLOBAL_USRS:
         Fig_WriteForumTitleAndStats (ForumType,CtyCod,InsCod,CtrCod,DegCod,CrsCod,
                                      "comments.svg",FiguresForum,
                                      Txt_General,"");
         break;
      case For_FORUM_GLOBAL_TCHS:
         Fig_WriteForumTitleAndStats (ForumType,CtyCod,InsCod,CtrCod,DegCod,CrsCod,
                                      "comments.svg",FiguresForum,
                                      Txt_General,Txt_only_teachers);
         break;
      case For_FORUM__SWAD__USRS:
         Fig_WriteForumTitleAndStats (ForumType,CtyCod,InsCod,CtrCod,DegCod,CrsCod,
                                      "swad64x64.png",FiguresForum,
                                      Cfg_PLATFORM_SHORT_NAME,"");
         break;
      case For_FORUM__SWAD__TCHS:
         Fig_WriteForumTitleAndStats (ForumType,CtyCod,InsCod,CtrCod,DegCod,CrsCod,
                                      "swad64x64.png",FiguresForum,
                                      Cfg_PLATFORM_SHORT_NAME,Txt_only_teachers);
         break;
      case For_FORUM_INSTIT_USRS:
         Fig_WriteForumTitleAndStats (ForumType,CtyCod,InsCod,CtrCod,DegCod,CrsCod,
                                      "university.svg",FiguresForum,
                                      Txt_Institutions,"");
         break;
      case For_FORUM_INSTIT_TCHS:
         Fig_WriteForumTitleAndStats (ForumType,CtyCod,InsCod,CtrCod,DegCod,CrsCod,
                                      "university.svg",FiguresForum,
                                      Txt_Institutions,Txt_only_teachers);
         break;
      case For_FORUM_CENTRE_USRS:
         Fig_WriteForumTitleAndStats (ForumType,CtyCod,InsCod,CtrCod,DegCod,CrsCod,
                                      "building.svg",FiguresForum,
                                      Txt_Centres,"");
         break;
      case For_FORUM_CENTRE_TCHS:
         Fig_WriteForumTitleAndStats (ForumType,CtyCod,InsCod,CtrCod,DegCod,CrsCod,
                                      "building.svg",FiguresForum,
                                      Txt_Centres,Txt_only_teachers);
         break;
      case For_FORUM_DEGREE_USRS:
         Fig_WriteForumTitleAndStats (ForumType,CtyCod,InsCod,CtrCod,DegCod,CrsCod,
                                      "graduation-cap.svg",FiguresForum,
                                      Txt_Degrees,"");
         break;
      case For_FORUM_DEGREE_TCHS:
         Fig_WriteForumTitleAndStats (ForumType,CtyCod,InsCod,CtrCod,DegCod,CrsCod,
                                      "graduation-cap.svg",FiguresForum,
                                      Txt_Degrees,Txt_only_teachers);
         break;
      case For_FORUM_COURSE_USRS:
         Fig_WriteForumTitleAndStats (ForumType,CtyCod,InsCod,CtrCod,DegCod,CrsCod,
                                      "list-ol.svg",FiguresForum,
                                      Txt_Courses,"");
         break;
      case For_FORUM_COURSE_TCHS:
         Fig_WriteForumTitleAndStats (ForumType,CtyCod,InsCod,CtrCod,DegCod,CrsCod,
                                      "list-ol.svg",FiguresForum,
                                      Txt_Courses,Txt_only_teachers);
         break;
      default:
	 break;
     }
  }

/*****************************************************************************/
/******************* Write title and stats of a forum type *******************/
/*****************************************************************************/

static void Fig_WriteForumTitleAndStats (For_ForumType_t ForumType,
                                         long CtyCod,long InsCod,long CtrCod,long DegCod,long CrsCod,
                                         const char *Icon,struct Fig_FiguresForum *FiguresForum,
                                         const char *ForumName1,const char *ForumName2)
  {
   unsigned NumForums;
   unsigned NumThreads;
   unsigned NumPosts;
   unsigned NumUsrsToBeNotifiedByEMail;
   float NumThrsPerForum;
   float NumPostsPerThread;
   float NumPostsPerForum;

   /***** Compute number of forums, number of threads and number of posts *****/
   NumForums  = For_GetNumTotalForumsOfType       (ForumType,CtyCod,InsCod,CtrCod,DegCod,CrsCod);
   NumThreads = For_GetNumTotalThrsInForumsOfType (ForumType,CtyCod,InsCod,CtrCod,DegCod,CrsCod);
   NumPosts   = For_GetNumTotalPstsInForumsOfType (ForumType,CtyCod,InsCod,CtrCod,DegCod,CrsCod,&NumUsrsToBeNotifiedByEMail);

   /***** Compute number of threads per forum, number of posts per forum and number of posts per thread *****/
   NumThrsPerForum = (NumForums ? (float) NumThreads / (float) NumForums :
	                          0.0);
   NumPostsPerThread = (NumThreads ? (float) NumPosts / (float) NumThreads :
	                             0.0);
   NumPostsPerForum = (NumForums ? (float) NumPosts / (float) NumForums :
	                           0.0);

   /***** Update total stats *****/
   FiguresForum->NumForums                  += NumForums;
   FiguresForum->NumThreads                 += NumThreads;
   FiguresForum->NumPosts                   += NumPosts;
   FiguresForum->NumUsrsToBeNotifiedByEMail += NumUsrsToBeNotifiedByEMail;

   /***** Write forum name and stats *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<td class=\"LEFT_TOP\" style=\"width:20px;\">"
                      "<img src=\"%s/%s\""
                      " alt=\"%s%s\" title=\"%s%s\""
                      " class=\"ICO16x16\" />"
                      "</td>"
                      "<td class=\"DAT LEFT_TOP\">"
                      "%s%s"
                      "</td>"
                      "<td class=\"DAT RIGHT_TOP\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT RIGHT_TOP\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT RIGHT_TOP\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT RIGHT_TOP\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT RIGHT_TOP\">"
                      "%.2f"
                      "</td>"
                      "<td class=\"DAT RIGHT_TOP\">"
                      "%.2f"
                      "</td>"
                      "<td class=\"DAT RIGHT_TOP\">"
                      "%.2f"
                      "</td>"
                      "</tr>",
            Cfg_URL_ICON_PUBLIC,Icon,
            ForumName1,ForumName2,
            ForumName1,ForumName2,
            ForumName1,ForumName2,
            NumForums,NumThreads,NumPosts,NumUsrsToBeNotifiedByEMail,
            NumThrsPerForum,NumPostsPerThread,NumPostsPerForum);
  }

/*****************************************************************************/
/******************* Write title and stats of a forum type *******************/
/*****************************************************************************/

static void Fig_WriteForumTotalStats (struct Fig_FiguresForum *FiguresForum)
  {
   extern const char *Txt_Total;
   float NumThrsPerForum;
   float NumPostsPerThread;
   float NumPostsPerForum;

   /***** Compute number of threads per forum, number of posts per forum and number of posts per thread *****/
   NumThrsPerForum  = (FiguresForum->NumForums ? (float) FiguresForum->NumThreads / (float) FiguresForum->NumForums :
	                                       0.0);
   NumPostsPerThread = (FiguresForum->NumThreads ? (float) FiguresForum->NumPosts / (float) FiguresForum->NumThreads :
	                                         0.0);
   NumPostsPerForum = (FiguresForum->NumForums ? (float) FiguresForum->NumPosts / (float) FiguresForum->NumForums :
	                                       0.0);

   /***** Write forum name and stats *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<td class=\"DAT_N_LINE_TOP\" style=\"width:20px;\">"
                      "</td>"
                      "<td class=\"DAT_N_LINE_TOP LEFT_MIDDLE\">"
                      "%s"
                      "</td>"
                      "<td class=\"DAT_N_LINE_TOP RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT_N_LINE_TOP RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT_N_LINE_TOP RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT_N_LINE_TOP RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT_N_LINE_TOP RIGHT_MIDDLE\">"
                      "%.2f"
                      "</td>"
                      "<td class=\"DAT_N_LINE_TOP RIGHT_MIDDLE\">"
                      "%.2f"
                      "</td>"
                      "<td class=\"DAT_N_LINE_TOP RIGHT_MIDDLE\">"
                      "%.2f"
                      "</td>"
                      "</tr>",
            Txt_Total,
            FiguresForum->NumForums,
            FiguresForum->NumThreads,
            FiguresForum->NumPosts,
            FiguresForum->NumUsrsToBeNotifiedByEMail,
            NumThrsPerForum,
            NumPostsPerThread,
            NumPostsPerForum);
  }

/*****************************************************************************/
/****** Get and show number of users who want to be notified by email ********/
/*****************************************************************************/

static void Fig_GetAndShowNumUsrsPerNotifyEvent (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_notifications;
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   extern const char *Txt_Event;
   extern const char *Txt_NOTIFY_EVENTS_PLURAL[Ntf_NUM_NOTIFY_EVENTS];
   extern const char *Txt_No_of_users;
   extern const char *Txt_PERCENT_of_users;
   extern const char *Txt_Number_of_BR_events;
   extern const char *Txt_Number_of_BR_emails;
   extern const char *Txt_Total;
   Ntf_NotifyEvent_t NotifyEvent;
   char *SubQuery;
   MYSQL_RES *mysql_res;
   MYSQL_ROW row;
   unsigned NumUsrsTotal;
   unsigned NumUsrsTotalWhoWantToBeNotifiedByEMailAboutSomeEvent;
   unsigned NumUsrs[Ntf_NUM_NOTIFY_EVENTS];
   unsigned NumEventsTotal = 0;
   unsigned NumEvents[Ntf_NUM_NOTIFY_EVENTS];
   unsigned NumMailsTotal = 0;
   unsigned NumMails[Ntf_NUM_NOTIFY_EVENTS];

   /***** Start box and table *****/
   Box_StartBoxTable (NULL,Txt_FIGURE_TYPES[Fig_NOTIFY_EVENTS],NULL,
                      Hlp_ANALYTICS_Figures_notifications,Box_NOT_CLOSABLE,2);

   /***** Heading row *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"LEFT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "</tr>",
            Txt_Event,
            Txt_No_of_users,
            Txt_PERCENT_of_users,
            Txt_Number_of_BR_events,
            Txt_Number_of_BR_emails);

   /***** Get total number of users *****/
   NumUsrsTotal = (Gbl.Scope.Current == Hie_SYS) ? Usr_GetTotalNumberOfUsersInPlatform () :
                                                         Usr_GetTotalNumberOfUsersInCourses (Gbl.Scope.Current,
                                                                                             1 << Rol_STD |
                                                                                             1 << Rol_NET |
                                                                                             1 << Rol_TCH);

   /***** Get total number of users who want to be
          notified by email on some event, from database *****/
   NumUsrsTotalWhoWantToBeNotifiedByEMailAboutSomeEvent =
   Fig_GetNumUsrsWhoChoseAnOption ("usr_data.EmailNtfEvents<>0");

   /***** For each notify event... *****/
   for (NotifyEvent = (Ntf_NotifyEvent_t) 1;
	NotifyEvent < Ntf_NUM_NOTIFY_EVENTS;
	NotifyEvent++) // 0 is reserved for Ntf_EVENT_UNKNOWN
     {
      /* Get the number of users who want to be notified by email on this event, from database */
      if (asprintf (&SubQuery,"((usr_data.EmailNtfEvents & %u)<>0)",
	            (1 << NotifyEvent)) < 0)
	 Lay_NotEnoughMemoryExit ();
      NumUsrs[NotifyEvent] = Fig_GetNumUsrsWhoChoseAnOption (SubQuery);
      free ((void *) SubQuery);

      /* Get number of notifications by email from database */
      switch (Gbl.Scope.Current)
        {
         case Hie_SYS:
            DB_QuerySELECT (&mysql_res,"can not get the number"
        			       " of notifications by email",
        		    "SELECT SUM(NumEvents),SUM(NumMails)"
                            " FROM sta_notif"
                            " WHERE NotifyEvent=%u",
			    (unsigned) NotifyEvent);
            break;
	 case Hie_CTY:
            DB_QuerySELECT (&mysql_res,"can not get the number"
        			       " of notifications by email",
        		    "SELECT SUM(sta_notif.NumEvents),SUM(sta_notif.NumMails)"
                            " FROM institutions,centres,degrees,sta_notif"
                            " WHERE institutions.CtyCod=%ld"
                            " AND institutions.InsCod=centres.InsCod"
                            " AND centres.CtrCod=degrees.CtrCod"
                            " AND degrees.DegCod=sta_notif.DegCod"
                            " AND sta_notif.NotifyEvent=%u",
			    Gbl.Hierarchy.Cty.CtyCod,(unsigned) NotifyEvent);
            break;
	 case Hie_INS:
            DB_QuerySELECT (&mysql_res,"can not get the number"
        			       " of notifications by email",
        		    "SELECT SUM(sta_notif.NumEvents),SUM(sta_notif.NumMails)"
                            " FROM centres,degrees,sta_notif"
                            " WHERE centres.InsCod=%ld"
                            " AND centres.CtrCod=degrees.CtrCod"
                            " AND degrees.DegCod=sta_notif.DegCod"
                            " AND sta_notif.NotifyEvent=%u",
			    Gbl.Hierarchy.Ins.InsCod,(unsigned) NotifyEvent);
            break;
         case Hie_CTR:
            DB_QuerySELECT (&mysql_res,"can not get the number"
        			       " of notifications by email",
        		    "SELECT SUM(sta_notif.NumEvents),SUM(sta_notif.NumMails)"
                            " FROM degrees,sta_notif"
                            " WHERE degrees.CtrCod=%ld"
                            " AND degrees.DegCod=sta_notif.DegCod"
                            " AND sta_notif.NotifyEvent=%u",
			    Gbl.Hierarchy.Ctr.CtrCod,(unsigned) NotifyEvent);
            break;
         case Hie_DEG:
            DB_QuerySELECT (&mysql_res,"can not get the number"
        			       " of notifications by email",
        		    "SELECT SUM(NumEvents),SUM(NumMails)"
                            " FROM sta_notif"
                            " WHERE DegCod=%ld"
                            " AND NotifyEvent=%u",
			    Gbl.Hierarchy.Deg.DegCod,(unsigned) NotifyEvent);
            break;
         case Hie_CRS:
            DB_QuerySELECT (&mysql_res,"can not get the number"
        			       " of notifications by email",
        		    "SELECT SUM(NumEvents),SUM(NumMails)"
                            " FROM sta_notif"
                            " WHERE CrsCod=%ld"
                            " AND NotifyEvent=%u",
			    Gbl.Hierarchy.Crs.CrsCod,(unsigned) NotifyEvent);
            break;
	 default:
	    Lay_WrongScopeExit ();
	    break;
        }

      row = mysql_fetch_row (mysql_res);

      /* Get number of events notified */
      if (row[0])
        {
         if (sscanf (row[0],"%u",&NumEvents[NotifyEvent]) != 1)
            Lay_ShowErrorAndExit ("Error when getting the number of notifications by email.");
        }
      else
         NumEvents[NotifyEvent] = 0;

      /* Get number of mails sent */
      if (row[1])
        {
         if (sscanf (row[1],"%u",&NumMails[NotifyEvent]) != 1)
            Lay_ShowErrorAndExit ("Error when getting the number of emails to notify events3.");
        }
      else
         NumMails[NotifyEvent] = 0;

      /* Free structure that stores the query result */
      DB_FreeMySQLResult (&mysql_res);

      /* Update total number of events and mails */
      NumEventsTotal += NumEvents[NotifyEvent];
      NumMailsTotal  += NumMails [NotifyEvent];
     }

   /***** Write number of users who want to be notified by email on each event *****/
   for (NotifyEvent = (Ntf_NotifyEvent_t) 1;
	NotifyEvent < Ntf_NUM_NOTIFY_EVENTS;
	NotifyEvent++) // 0 is reserved for Ntf_EVENT_UNKNOWN
      fprintf (Gbl.F.Out,"<tr>"
                         "<td class=\"DAT LEFT_MIDDLE\">"
                         "%s"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%u"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%5.2f%%"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%u"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%u"
                         "</td>"
                         "</tr>",
               Txt_NOTIFY_EVENTS_PLURAL[NotifyEvent],
               NumUsrs[NotifyEvent],
               NumUsrsTotal ? (float) NumUsrs[NotifyEvent] * 100.0 /
        	              (float) NumUsrsTotal :
        	              0.0,
               NumEvents[NotifyEvent],
               NumMails[NotifyEvent]);

   /***** Write total number of users who want to be notified by email on some event *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<td class=\"DAT_N_LINE_TOP LEFT_MIDDLE\">"
                      "%s"
                      "</td>"
                      "<td class=\"DAT_N_LINE_TOP RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT_N_LINE_TOP RIGHT_MIDDLE\">"
                      "%5.2f%%"
                      "</td>"
                      "<td class=\"DAT_N_LINE_TOP RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT_N_LINE_TOP RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "</tr>",
            Txt_Total,
            NumUsrsTotalWhoWantToBeNotifiedByEMailAboutSomeEvent,
            NumUsrsTotal ? (float) NumUsrsTotalWhoWantToBeNotifiedByEMailAboutSomeEvent * 100.0 /
        	           (float) NumUsrsTotal :
        	           0.0,
            NumEventsTotal,
            NumMailsTotal);

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/************************** Show figures about notices ***********************/
/*****************************************************************************/

static void Fig_GetAndShowNoticesStats (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_notices;
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   extern const char *Txt_NOTICE_Active_BR_notices;
   extern const char *Txt_NOTICE_Obsolete_BR_notices;
   extern const char *Txt_NOTICE_Deleted_BR_notices;
   extern const char *Txt_Total;
   extern const char *Txt_Number_of_BR_notifications;
   Not_Status_t NoticeStatus;
   unsigned NumNotices[Not_NUM_STATUS];
   unsigned NumNoticesDeleted;
   unsigned NumTotalNotices = 0;
   unsigned NumNotif;
   unsigned NumTotalNotifications = 0;

   /***** Get the number of notices active and obsolete *****/
   for (NoticeStatus = (Not_Status_t) 0;
	NoticeStatus < Not_NUM_STATUS;
	NoticeStatus++)
     {
      NumNotices[NoticeStatus] = Not_GetNumNotices (Gbl.Scope.Current,NoticeStatus,&NumNotif);
      NumTotalNotices += NumNotices[NoticeStatus];
      NumTotalNotifications += NumNotif;
     }
   NumNoticesDeleted = Not_GetNumNoticesDeleted (Gbl.Scope.Current,&NumNotif);
   NumTotalNotices += NumNoticesDeleted;
   NumTotalNotifications += NumNotif;

   /***** Start box and table *****/
   Box_StartBoxTable (NULL,Txt_FIGURE_TYPES[Fig_NOTICES],NULL,
                      Hlp_ANALYTICS_Figures_notices,Box_NOT_CLOSABLE,2);

   /***** Write table heading *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "</tr>",
            Txt_NOTICE_Active_BR_notices,
            Txt_NOTICE_Obsolete_BR_notices,
            Txt_NOTICE_Deleted_BR_notices,
            Txt_Total,
            Txt_Number_of_BR_notifications);

   /***** Write number of notices *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT_N RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "</tr>",
            NumNotices[Not_ACTIVE_NOTICE],
            NumNotices[Not_OBSOLETE_NOTICE],
            NumNoticesDeleted,
            NumTotalNotices,
            NumTotalNotifications);

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/************************ Show figures about messages ************************/
/*****************************************************************************/

static void Fig_GetAndShowMsgsStats (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_messages;
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   extern const char *Txt_Messages;
   extern const char *Txt_MSGS_Not_deleted;
   extern const char *Txt_MSGS_Deleted;
   extern const char *Txt_Total;
   extern const char *Txt_Number_of_BR_notifications;
   extern const char *Txt_MSGS_Sent;
   extern const char *Txt_MSGS_Received;
   unsigned NumMsgsSentNotDeleted,NumMsgsSentDeleted;
   unsigned NumMsgsReceivedNotDeleted,NumMsgsReceivedAndDeleted;
   unsigned NumMsgsReceivedAndNotified;

   /***** Get the number of unique messages sent from this location *****/
   NumMsgsSentNotDeleted      = Msg_GetNumMsgsSent     (Gbl.Scope.Current,Msg_STATUS_ALL     );
   NumMsgsSentDeleted         = Msg_GetNumMsgsSent     (Gbl.Scope.Current,Msg_STATUS_DELETED );

   NumMsgsReceivedNotDeleted  = Msg_GetNumMsgsReceived (Gbl.Scope.Current,Msg_STATUS_ALL     );
   NumMsgsReceivedAndDeleted  = Msg_GetNumMsgsReceived (Gbl.Scope.Current,Msg_STATUS_DELETED );
   NumMsgsReceivedAndNotified = Msg_GetNumMsgsReceived (Gbl.Scope.Current,Msg_STATUS_NOTIFIED);

   /***** Start box and table *****/
   Box_StartBoxTable (NULL,Txt_FIGURE_TYPES[Fig_MESSAGES],NULL,
                      Hlp_ANALYTICS_Figures_messages,Box_NOT_CLOSABLE,2);

   /***** Write table heading *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"LEFT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "</tr>",
            Txt_Messages,
            Txt_MSGS_Not_deleted,
            Txt_MSGS_Deleted,
            Txt_Total,
            Txt_Number_of_BR_notifications);

   /***** Write number of messages *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<td class=\"DAT LEFT_MIDDLE\">"
                      "%s"
                      "</td>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT_N RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "-"
                      "</td>"
                      "</tr>"
                      "<tr>"
                      "<td class=\"DAT LEFT_MIDDLE\">"
                      "%s"
                      "</td>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT_N RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "</tr>",
            Txt_MSGS_Sent,
            NumMsgsSentNotDeleted,
            NumMsgsSentDeleted,
            NumMsgsSentNotDeleted + NumMsgsSentDeleted,
            Txt_MSGS_Received,
            NumMsgsReceivedNotDeleted,
            NumMsgsReceivedAndDeleted,
            NumMsgsReceivedNotDeleted + NumMsgsReceivedAndDeleted,
            NumMsgsReceivedAndNotified);

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/***************************** Show stats of surveys *************************/
/*****************************************************************************/

static void Fig_GetAndShowSurveysStats (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_surveys;
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   extern const char *Txt_Number_of_BR_surveys;
   extern const char *Txt_Number_of_BR_courses_with_BR_surveys;
   extern const char *Txt_Average_number_BR_of_surveys_BR_per_course;
   extern const char *Txt_Average_number_BR_of_questions_BR_per_survey;
   extern const char *Txt_Number_of_BR_notifications;
   unsigned NumSurveys;
   unsigned NumNotif;
   unsigned NumCoursesWithSurveys = 0;
   float NumSurveysPerCourse = 0.0;
   float NumQstsPerSurvey = 0.0;

   /***** Get the number of surveys and the average number of questions per survey from this location *****/
   if ((NumSurveys = Svy_GetNumCrsSurveys (Gbl.Scope.Current,&NumNotif)))
     {
      if ((NumCoursesWithSurveys = Svy_GetNumCoursesWithCrsSurveys (Gbl.Scope.Current)) != 0)
         NumSurveysPerCourse = (float) NumSurveys / (float) NumCoursesWithSurveys;
      NumQstsPerSurvey = Svy_GetNumQstsPerCrsSurvey (Gbl.Scope.Current);
     }

   /***** Start box and table *****/
   Box_StartBoxTable (NULL,Txt_FIGURE_TYPES[Fig_SURVEYS],NULL,
                      Hlp_ANALYTICS_Figures_surveys,Box_NOT_CLOSABLE,2);

   /***** Write table heading *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "</tr>",
            Txt_Number_of_BR_surveys,
            Txt_Number_of_BR_courses_with_BR_surveys,
            Txt_Average_number_BR_of_surveys_BR_per_course,
            Txt_Average_number_BR_of_questions_BR_per_survey,
            Txt_Number_of_BR_notifications);

   /***** Write number of surveys *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "%.2f"
                      "</td>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "%.2f"
                      "</td>"
                      "<td class=\"DAT RIGHT_MIDDLE\">"
                      "%u"
                      "</td>"
                      "</tr>",
            NumSurveys,
            NumCoursesWithSurveys,
            NumSurveysPerCourse,
            NumQstsPerSurvey,
            NumNotif);

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/********** Get and show number of users who have chosen a privacy ***********/
/*****************************************************************************/

static void Fig_GetAndShowNumUsrsPerPrivacy (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_privacy;
   extern const char *Txt_Photo;
   extern const char *Txt_Basic_public_profile;
   extern const char *Txt_Extended_public_profile;
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];

   /***** Start box and table *****/
   Box_StartBoxTable (NULL,Txt_FIGURE_TYPES[Fig_PRIVACY],NULL,
                      Hlp_ANALYTICS_Figures_privacy,Box_NOT_CLOSABLE,2);

   /***** Privacy for photo *****/
   Fig_GetAndShowNumUsrsPerPrivacyForAnObject (Txt_Photo,
	                                       "PhotoVisibility",
					       Pri_PHOTO_ALLOWED_VIS);

   /***** Privacy for public profile *****/
   Fig_GetAndShowNumUsrsPerPrivacyForAnObject (Txt_Basic_public_profile,
	                                       "BaPrfVisibility",
					       Pri_BASIC_PROFILE_ALLOWED_VIS);
   Fig_GetAndShowNumUsrsPerPrivacyForAnObject (Txt_Extended_public_profile,
	                                       "ExPrfVisibility",
					       Pri_EXTENDED_PROFILE_ALLOWED_VIS);

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/********** Get and show number of users who have chosen a privacy ***********/
/*****************************************************************************/

static void Fig_GetAndShowNumUsrsPerPrivacyForAnObject (const char *TxtObject,
                                                        const char *FieldName,
                                                        unsigned MaskAllowedVisibility)
  {
   extern const char *Txt_No_of_users;
   extern const char *Txt_PERCENT_of_users;
   extern const char *Pri_VisibilityDB[Pri_NUM_OPTIONS_PRIVACY];
   extern const char *Txt_PRIVACY_OPTIONS[Pri_NUM_OPTIONS_PRIVACY];
   Pri_Visibility_t Visibility;
   char *SubQuery;
   unsigned NumUsrs[Pri_NUM_OPTIONS_PRIVACY];
   unsigned NumUsrsTotal = 0;

   /***** Heading row *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"LEFT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "</tr>",
            TxtObject,
            Txt_No_of_users,
            Txt_PERCENT_of_users);

   /***** For each privacy option... *****/
   for (Visibility = (Pri_Visibility_t) 0;
	Visibility < Pri_NUM_OPTIONS_PRIVACY;
	Visibility++)
      if (MaskAllowedVisibility & (1 << Visibility))
	{
	 /* Get the number of users who have chosen this privacy option from database */
	 if (asprintf (&SubQuery,"usr_data.%s='%s'",
		       FieldName,Pri_VisibilityDB[Visibility]) < 0)
	    Lay_NotEnoughMemoryExit ();
	 NumUsrs[Visibility] = Fig_GetNumUsrsWhoChoseAnOption (SubQuery);
	 free ((void *) SubQuery);

	 /* Update total number of users */
	 NumUsrsTotal += NumUsrs[Visibility];
	}

   /***** Write number of users who have chosen each privacy option *****/
   for (Visibility = (Pri_Visibility_t) 0;
	Visibility < Pri_NUM_OPTIONS_PRIVACY;
	Visibility++)
      if (MaskAllowedVisibility & (1 << Visibility))
	 fprintf (Gbl.F.Out,"<tr>"
			    "<td class=\"DAT LEFT_MIDDLE\">"
			    "%s"
			    "</td>"
			    "<td class=\"DAT RIGHT_MIDDLE\">"
			    "%u"
			    "</td>"
			    "<td class=\"DAT RIGHT_MIDDLE\">"
			    "%5.2f%%"
			    "</td>"
			    "</tr>",
		  Txt_PRIVACY_OPTIONS[Visibility],NumUsrs[Visibility],
		  NumUsrsTotal ? (float) NumUsrs[Visibility] * 100.0 /
				 (float) NumUsrsTotal :
				 0);
   }

/*****************************************************************************/
/** Get and show number of users who have chosen a preference about cookies **/
/*****************************************************************************/

static void Fig_GetAndShowNumUsrsPerCookies (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_cookies;
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   extern const char *Txt_Cookies;
   extern const char *Txt_No_of_users;
   extern const char *Txt_PERCENT_of_users;
   unsigned i;
   char AcceptedInDB[2] =
     {
      'N',		// false
      'Y'		// true
     };
   char *AcceptedClass[2] =
     {
      "DAT_RED",	// false
      "DAT_GREEN"	// true
     };
   char *AcceptedSymbol[2] =
     {
      "&cross;",	// false
      "&check;"		// true
     };

   char *SubQuery;
   unsigned NumUsrs[Mnu_NUM_MENUS];
   unsigned NumUsrsTotal = 0;

   /***** Start box and table *****/
   Box_StartBoxTable (NULL,Txt_FIGURE_TYPES[Fig_COOKIES],NULL,
                      Hlp_ANALYTICS_Figures_cookies,Box_NOT_CLOSABLE,2);

   /***** Heading row *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"LEFT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "</tr>",
            Txt_Cookies,
            Txt_No_of_users,
            Txt_PERCENT_of_users);

   /***** For each option... *****/
   for (i = 0;
	i < 2;
	i++)
     {
      /* Get number of users who have chosen this menu from database */
      if (asprintf (&SubQuery,"usr_data.ThirdPartyCookies='%c'",
	            AcceptedInDB[i]) < 0)
	 Lay_NotEnoughMemoryExit ();
      NumUsrs[i] = Fig_GetNumUsrsWhoChoseAnOption (SubQuery);
      free ((void *) SubQuery);

      /* Update total number of users */
      NumUsrsTotal += NumUsrs[i];
     }

   /***** Write number of users who have chosen each option *****/
   for (i = 0;
	i < 2;
	i++)
      fprintf (Gbl.F.Out,"<tr>"
                         "<td class=\"%s CENTER_MIDDLE\">"
                         "%s"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%u"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%5.2f%%"
                         "</td>"
                         "</tr>",
	       AcceptedClass[i],
               AcceptedSymbol[i],
               NumUsrs[i],
               NumUsrsTotal ? (float) NumUsrs[i] * 100.0 /
        	              (float) NumUsrsTotal :
        	              0);

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/********* Get and show number of users who have chosen a language ***********/
/*****************************************************************************/

static void Fig_GetAndShowNumUsrsPerLanguage (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_language;
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   extern const char *Txt_Language;
   extern const char *Lan_STR_LANG_ID[1 + Lan_NUM_LANGUAGES];
   extern const char *Txt_STR_LANG_NAME[1 + Lan_NUM_LANGUAGES];
   extern const char *Txt_No_of_users;
   extern const char *Txt_PERCENT_of_users;
   Lan_Language_t Lan;
   char *SubQuery;
   unsigned NumUsrs[1 + Lan_NUM_LANGUAGES];
   unsigned NumUsrsTotal = 0;

   /***** Start box and table *****/
   Box_StartBoxTable (NULL,Txt_FIGURE_TYPES[Fig_LANGUAGES],NULL,
                      Hlp_ANALYTICS_Figures_language,Box_NOT_CLOSABLE,2);

   /***** Heading row *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"LEFT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "</tr>",
            Txt_Language,
            Txt_No_of_users,
            Txt_PERCENT_of_users);

   /***** For each language... *****/
   for (Lan = (Lan_Language_t) 1;
	Lan <= Lan_NUM_LANGUAGES;
	Lan++)
     {
      /* Get the number of users who have chosen this language from database */
      if (asprintf (&SubQuery,"usr_data.Language='%s'",
		    Lan_STR_LANG_ID[Lan]) < 0)
	 Lay_NotEnoughMemoryExit ();
      NumUsrs[Lan] = Fig_GetNumUsrsWhoChoseAnOption (SubQuery);
      free ((void *) SubQuery);

      /* Update total number of users */
      NumUsrsTotal += NumUsrs[Lan];
     }

   /***** Write number of users who have chosen each language *****/
   for (Lan = (Lan_Language_t) 1;
	Lan <= Lan_NUM_LANGUAGES;
	Lan++)
      fprintf (Gbl.F.Out,"<tr>"
                         "<td class=\"DAT LEFT_MIDDLE\">"
                         "%s"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%u"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%5.2f%%"
                         "</td>"
                         "</tr>",
               Txt_STR_LANG_NAME[Lan],NumUsrs[Lan],
               NumUsrsTotal ? (float) NumUsrs[Lan] * 100.0 /
        	              (float) NumUsrsTotal :
        	              0);

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/***** Get and show number of users who have chosen a first day of week ******/
/*****************************************************************************/

static void Fig_GetAndShowNumUsrsPerFirstDayOfWeek (void)
  {
   extern const bool Cal_DayIsValidAsFirstDayOfWeek[7];
   extern const char *Hlp_ANALYTICS_Figures_calendar;
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   extern const char *Txt_Calendar;
   extern const char *Txt_First_day_of_the_week;
   extern const char *Txt_DAYS_SMALL[7];
   extern const char *Txt_No_of_users;
   extern const char *Txt_PERCENT_of_users;
   unsigned FirstDayOfWeek;
   char *SubQuery;
   unsigned NumUsrs[7];	// 7: seven days in a week
   unsigned NumUsrsTotal = 0;

   /***** Start box and table *****/
   Box_StartBoxTable (NULL,Txt_FIGURE_TYPES[Fig_FIRST_DAY_OF_WEEK],NULL,
                      Hlp_ANALYTICS_Figures_calendar,Box_NOT_CLOSABLE,2);

   /***** Heading row *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"LEFT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "</tr>",
            Txt_Calendar,
            Txt_No_of_users,
            Txt_PERCENT_of_users);

   /***** For each day... *****/
   for (FirstDayOfWeek = 0;	// Monday
	FirstDayOfWeek <= 6;	// Sunday
	FirstDayOfWeek++)
      if (Cal_DayIsValidAsFirstDayOfWeek[FirstDayOfWeek])
	{
	 /* Get number of users who have chosen this first day of week from database */
	 if (asprintf (&SubQuery,"usr_data.FirstDayOfWeek=%u",
		       (unsigned) FirstDayOfWeek) < 0)
	    Lay_NotEnoughMemoryExit ();
	 NumUsrs[FirstDayOfWeek] = Fig_GetNumUsrsWhoChoseAnOption (SubQuery);
	 free ((void *) SubQuery);

	 /* Update total number of users */
	 NumUsrsTotal += NumUsrs[FirstDayOfWeek];
        }

   /***** Write number of users who have chosen each first day of week *****/
   for (FirstDayOfWeek = 0;	// Monday
	FirstDayOfWeek <= 6;	// Sunday
	FirstDayOfWeek++)
      if (Cal_DayIsValidAsFirstDayOfWeek[FirstDayOfWeek])
	 fprintf (Gbl.F.Out,"<tr>"
			    "<td class=\"CENTER_MIDDLE\">"
			    "<img src=\"%s/first-day-of-week-%u.png\""
			    " alt=\"%s\" title=\"%s: %s\""
			    " class=\"ICO40x40\" />"
			    "</td>"
			    "<td class=\"DAT RIGHT_MIDDLE\">"
			    "%u"
			    "</td>"
			    "<td class=\"DAT RIGHT_MIDDLE\">"
			    "%5.2f%%"
			    "</td>"
			    "</tr>",
		  Cfg_URL_ICON_PUBLIC,FirstDayOfWeek,
		  Txt_DAYS_SMALL[FirstDayOfWeek],
		  Txt_First_day_of_the_week,Txt_DAYS_SMALL[FirstDayOfWeek],
		  NumUsrs[FirstDayOfWeek],
		  NumUsrsTotal ? (float) NumUsrs[FirstDayOfWeek] * 100.0 /
				 (float) NumUsrsTotal :
				 0);

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/******** Get and show number of users who have chosen a date format *********/
/*****************************************************************************/

static void Fig_GetAndShowNumUsrsPerDateFormat (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_dates;
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   extern const char *Txt_Format;
   extern const char *Txt_No_of_users;
   extern const char *Txt_PERCENT_of_users;
   unsigned Format;
   char *SubQuery;
   unsigned NumUsrs[Dat_NUM_OPTIONS_FORMAT];
   unsigned NumUsrsTotal = 0;

   /***** Start box and table *****/
   Box_StartBoxTable (NULL,Txt_FIGURE_TYPES[Fig_DATE_FORMAT],NULL,
                      Hlp_ANALYTICS_Figures_dates,Box_NOT_CLOSABLE,2);

   /***** Heading row *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"LEFT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "</tr>",
            Txt_Format,
            Txt_No_of_users,
            Txt_PERCENT_of_users);

   /***** For each format... *****/
   for (Format = (Dat_Format_t) 0;
	Format <= (Dat_Format_t) (Dat_NUM_OPTIONS_FORMAT - 1);
	Format++)
     {
      /* Get number of users who have chosen this date format from database */
      if (asprintf (&SubQuery,"usr_data.DateFormat=%u",
	            (unsigned) Format) < 0)
	 Lay_NotEnoughMemoryExit ();
      NumUsrs[Format] = Fig_GetNumUsrsWhoChoseAnOption (SubQuery);
      free ((void *) SubQuery);

      /* Update total number of users */
      NumUsrsTotal += NumUsrs[Format];
     }

   /***** Write number of users who have chosen each date format *****/
   for (Format = (Dat_Format_t) 0;
	Format <= (Dat_Format_t) (Dat_NUM_OPTIONS_FORMAT - 1);
	Format++)
     {
      fprintf (Gbl.F.Out,"<tr>"
			 "<td class=\"DAT_N LEFT_MIDDLE\">");
      Dat_PutSpanDateFormat (Format);
      Dat_PutScriptDateFormat (Format);
      fprintf (Gbl.F.Out,"</td>"
			 "<td class=\"DAT RIGHT_MIDDLE\">"
			 "%u"
			 "</td>"
			 "<td class=\"DAT RIGHT_MIDDLE\">"
			 "%5.2f%%"
			 "</td>"
			 "</tr>",
	       NumUsrs[Format],
	       NumUsrsTotal ? (float) NumUsrs[Format] * 100.0 /
			      (float) NumUsrsTotal :
			      0);
     }

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/********* Get and show number of users who have chosen an icon set **********/
/*****************************************************************************/

static void Fig_GetAndShowNumUsrsPerIconSet (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_icons;
   extern const char *Ico_IconSetId[Ico_NUM_ICON_SETS];
   extern const char *Ico_IconSetNames[Ico_NUM_ICON_SETS];
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   extern const char *Txt_Icons;
   extern const char *Txt_No_of_users;
   extern const char *Txt_PERCENT_of_users;
   Ico_IconSet_t IconSet;
   char *SubQuery;
   unsigned NumUsrs[Ico_NUM_ICON_SETS];
   unsigned NumUsrsTotal = 0;

   /***** Start box and table *****/
   Box_StartBoxTable (NULL,Txt_FIGURE_TYPES[Fig_ICON_SETS],NULL,
                      Hlp_ANALYTICS_Figures_icons,Box_NOT_CLOSABLE,2);

   /***** Heading row *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"LEFT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "</tr>",
            Txt_Icons,
            Txt_No_of_users,
            Txt_PERCENT_of_users);

   /***** For each icon set... *****/
   for (IconSet = (Ico_IconSet_t) 0;
	IconSet < Ico_NUM_ICON_SETS;
	IconSet++)
     {
      /* Get the number of users who have chosen this icon set from database */
      if (asprintf (&SubQuery,"usr_data.IconSet='%s'",
	            Ico_IconSetId[IconSet]) < 0)
	 Lay_NotEnoughMemoryExit ();
      NumUsrs[IconSet] = Fig_GetNumUsrsWhoChoseAnOption (SubQuery);
      free ((void *) SubQuery);

      /* Update total number of users */
      NumUsrsTotal += NumUsrs[IconSet];
     }

   /***** Write number of users who have chosen each icon set *****/
   for (IconSet = (Ico_IconSet_t) 0;
	IconSet < Ico_NUM_ICON_SETS;
	IconSet++)
      fprintf (Gbl.F.Out,"<tr>"
                         "<td class=\"LEFT_MIDDLE\">"
                         "<img src=\"%s/%s/cog.svg\""
                         " alt=\"%s\" title=\"%s\""
                         " class=\"ICO40x40\" />"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%u"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%5.2f%%"
                         "</td>"
                         "</tr>",
               Cfg_URL_ICON_SETS_PUBLIC,
               Ico_IconSetId[IconSet],
               Ico_IconSetNames[IconSet],
               Ico_IconSetNames[IconSet],
               NumUsrs[IconSet],
               NumUsrsTotal ? (float) NumUsrs[IconSet] * 100.0 /
        	              (float) NumUsrsTotal :
        	              0);

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/*********** Get and show number of users who have chosen a menu *************/
/*****************************************************************************/

static void Fig_GetAndShowNumUsrsPerMenu (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_menu;
   extern const char *Mnu_MenuIcons[Mnu_NUM_MENUS];
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   extern const char *Txt_Menu;
   extern const char *Txt_No_of_users;
   extern const char *Txt_PERCENT_of_users;
   extern const char *Txt_MENU_NAMES[Mnu_NUM_MENUS];
   Mnu_Menu_t Menu;
   char *SubQuery;
   unsigned NumUsrs[Mnu_NUM_MENUS];
   unsigned NumUsrsTotal = 0;

   /***** Start box and table *****/
   Box_StartBoxTable (NULL,Txt_FIGURE_TYPES[Fig_MENUS],NULL,
                      Hlp_ANALYTICS_Figures_menu,Box_NOT_CLOSABLE,2);

   /***** Heading row *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"LEFT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "</tr>",
            Txt_Menu,
            Txt_No_of_users,
            Txt_PERCENT_of_users);

   /***** For each menu... *****/
   for (Menu = (Mnu_Menu_t) 0;
	Menu < Mnu_NUM_MENUS;
	Menu++)
     {
      /* Get number of users who have chosen this menu from database */
      if (asprintf (&SubQuery,"usr_data.Menu=%u",
	            (unsigned) Menu) < 0)
	 Lay_NotEnoughMemoryExit ();
      NumUsrs[Menu] = Fig_GetNumUsrsWhoChoseAnOption (SubQuery);
      free ((void *) SubQuery);

      /* Update total number of users */
      NumUsrsTotal += NumUsrs[Menu];
     }

   /***** Write number of users who have chosen each menu *****/
   for (Menu = (Mnu_Menu_t) 0;
	Menu < Mnu_NUM_MENUS;
	Menu++)
      fprintf (Gbl.F.Out,"<tr>"
                         "<td class=\"CENTER_MIDDLE\">"
                         "<img src=\"%s/%s\""
                         " alt=\"%s\" title=\"%s\""
                         " class=\"ICO40x40\" />"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%u"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%5.2f%%"
                         "</td>"
                         "</tr>",
               Cfg_URL_ICON_PUBLIC,Mnu_MenuIcons[Menu],
               Txt_MENU_NAMES[Menu],
               Txt_MENU_NAMES[Menu],
               NumUsrs[Menu],
               NumUsrsTotal ? (float) NumUsrs[Menu] * 100.0 /
        	              (float) NumUsrsTotal :
        	              0);

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/********** Get and show number of users who have chosen a theme *************/
/*****************************************************************************/

static void Fig_GetAndShowNumUsrsPerTheme (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_theme;
   extern const char *The_ThemeId[The_NUM_THEMES];
   extern const char *The_ThemeNames[The_NUM_THEMES];
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   extern const char *Txt_Theme_SKIN;
   extern const char *Txt_No_of_users;
   extern const char *Txt_PERCENT_of_users;
   The_Theme_t Theme;
   char *SubQuery;
   unsigned NumUsrs[The_NUM_THEMES];
   unsigned NumUsrsTotal = 0;

   /***** Start box and table *****/
   Box_StartBoxTable (NULL,Txt_FIGURE_TYPES[Fig_THEMES],NULL,
                      Hlp_ANALYTICS_Figures_theme,Box_NOT_CLOSABLE,2);

   /***** Heading row *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"LEFT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "</tr>",
            Txt_Theme_SKIN,
            Txt_No_of_users,
            Txt_PERCENT_of_users);

   /***** For each theme... *****/
   for (Theme = (The_Theme_t) 0;
	Theme < The_NUM_THEMES;
	Theme++)
     {
      /* Get number of users who have chosen this theme from database */
      if (asprintf (&SubQuery,"usr_data.Theme='%s'",
		    The_ThemeId[Theme]) < 0)
	 Lay_NotEnoughMemoryExit ();
      NumUsrs[Theme] = Fig_GetNumUsrsWhoChoseAnOption (SubQuery);
      free ((void *) SubQuery);

      /* Update total number of users */
      NumUsrsTotal += NumUsrs[Theme];
     }

   /***** Write number of users who have chosen each theme *****/
   for (Theme = (The_Theme_t) 0;
	Theme < The_NUM_THEMES;
	Theme++)
      fprintf (Gbl.F.Out,"<tr>"
                         "<td class=\"CENTER_MIDDLE\">"
                         "<img src=\"%s/%s/theme_32x20.gif\""
                         " alt=\"%s\" title=\"%s\""
                         " style=\"width:40px; height:25px;\" />"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%u"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%5.2f%%"
                         "</td>"
                         "</tr>",
               Cfg_URL_ICON_THEMES_PUBLIC,The_ThemeId[Theme],
               The_ThemeNames[Theme],
               The_ThemeNames[Theme],
               NumUsrs[Theme],
               NumUsrsTotal ? (float) NumUsrs[Theme] * 100.0 /
        	              (float) NumUsrsTotal :
        	              0);

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/***** Get and show number of users who have chosen a layout of columns ******/
/*****************************************************************************/

static void Fig_GetAndShowNumUsrsPerSideColumns (void)
  {
   extern const char *Hlp_ANALYTICS_Figures_columns;
   extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
   extern const char *Txt_Columns;
   extern const char *Txt_No_of_users;
   extern const char *Txt_PERCENT_of_users;
   unsigned SideCols;
   char *SubQuery;
   unsigned NumUsrs[4];
   unsigned NumUsrsTotal = 0;
   extern const char *Txt_LAYOUT_SIDE_COLUMNS[4];

   /***** Start box and table *****/
   Box_StartBoxTable (NULL,Txt_FIGURE_TYPES[Fig_SIDE_COLUMNS],NULL,
                      Hlp_ANALYTICS_Figures_columns,Box_NOT_CLOSABLE,2);

   /***** Heading row *****/
   fprintf (Gbl.F.Out,"<tr>"
                      "<th class=\"CENTER_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "<th class=\"RIGHT_MIDDLE\">"
                      "%s"
                      "</th>"
                      "</tr>",
            Txt_Columns,
            Txt_No_of_users,
            Txt_PERCENT_of_users);

   /***** For each language... *****/
   for (SideCols = 0;
	SideCols <= Lay_SHOW_BOTH_COLUMNS;
	SideCols++)
     {
      /* Get the number of users who have chosen this layout of columns from database */
      if (asprintf (&SubQuery,"usr_data.SideCols=%u",
	            SideCols) < 0)
	 Lay_NotEnoughMemoryExit ();
      NumUsrs[SideCols] = Fig_GetNumUsrsWhoChoseAnOption (SubQuery);
      free ((void *) SubQuery);

      /* Update total number of users */
      NumUsrsTotal += NumUsrs[SideCols];
     }

   /***** Write number of users who have chosen this layout of columns *****/
   for (SideCols = 0;
	SideCols <= Lay_SHOW_BOTH_COLUMNS;
	SideCols++)
      fprintf (Gbl.F.Out,"<tr>"
                         "<td class=\"CENTER_MIDDLE\">"
                         "<img src=\"%s/layout%u%u_32x20.gif\""
                         " alt=\"%s\" title=\"%s\""
                         " style=\"width:40px; height:25px;\" />"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%u"
                         "</td>"
                         "<td class=\"DAT RIGHT_MIDDLE\">"
                         "%5.2f%%"
                         "</td>"
                         "</tr>",
               Cfg_URL_ICON_PUBLIC,SideCols >> 1,SideCols & 1,
               Txt_LAYOUT_SIDE_COLUMNS[SideCols],
               Txt_LAYOUT_SIDE_COLUMNS[SideCols],
               NumUsrs[SideCols],
               NumUsrsTotal ? (float) NumUsrs[SideCols] * 100.0 /
        	              (float) NumUsrsTotal :
        	              0);

   /***** End table and box *****/
   Box_EndBoxTable ();
  }

/*****************************************************************************/
/************** Get number of users who have chosen an option ****************/
/*****************************************************************************/

unsigned Fig_GetNumUsrsWhoChoseAnOption (const char *SubQuery)
  {
   unsigned NumUsrs;

   /***** Get the number of users who have chosen this privacy option from database *****/
   switch (Gbl.Scope.Current)
     {
      case Hie_SYS:
	 NumUsrs =
	 (unsigned) DB_QueryCOUNT ("can not get the number of users"
				   " who have chosen an option",
				   "SELECT COUNT(*)"
				   " FROM usr_data WHERE %s",
				   SubQuery);
	 break;
      case Hie_CTY:
	 NumUsrs =
	 (unsigned) DB_QueryCOUNT ("can not get the number of users"
				   " who have chosen an option",
				   "SELECT COUNT(DISTINCT usr_data.UsrCod)"
				   " FROM institutions,centres,degrees,courses,crs_usr,usr_data"
				   " WHERE institutions.CtyCod=%ld"
				   " AND institutions.InsCod=centres.InsCod"
				   " AND centres.CtrCod=degrees.CtrCod"
				   " AND degrees.DegCod=courses.DegCod"
				   " AND courses.CrsCod=crs_usr.CrsCod"
				   " AND crs_usr.UsrCod=usr_data.UsrCod"
				   " AND %s",
				   Gbl.Hierarchy.Cty.CtyCod,SubQuery);
	 break;
      case Hie_INS:
	 NumUsrs =
	 (unsigned) DB_QueryCOUNT ("can not get the number of users"
				   " who have chosen an option",
				   "SELECT COUNT(DISTINCT usr_data.UsrCod)"
				   " FROM centres,degrees,courses,crs_usr,usr_data"
				   " WHERE centres.InsCod=%ld"
				   " AND centres.CtrCod=degrees.CtrCod"
				   " AND degrees.DegCod=courses.DegCod"
				   " AND courses.CrsCod=crs_usr.CrsCod"
				   " AND crs_usr.UsrCod=usr_data.UsrCod"
				   " AND %s",
				   Gbl.Hierarchy.Ins.InsCod,SubQuery);
	 break;
      case Hie_CTR:
	 NumUsrs =
	 (unsigned) DB_QueryCOUNT ("can not get the number of users"
				   " who have chosen an option",
				   "SELECT COUNT(DISTINCT usr_data.UsrCod)"
				   " FROM degrees,courses,crs_usr,usr_data"
				   " WHERE degrees.CtrCod=%ld"
				   " AND degrees.DegCod=courses.DegCod"
				   " AND courses.CrsCod=crs_usr.CrsCod"
				   " AND crs_usr.UsrCod=usr_data.UsrCod"
				   " AND %s",
				   Gbl.Hierarchy.Ctr.CtrCod,SubQuery);
	 break;
      case Hie_DEG:
	 NumUsrs =
	 (unsigned) DB_QueryCOUNT ("can not get the number of users"
				   " who have chosen an option",
				   "SELECT COUNT(DISTINCT usr_data.UsrCod)"
				   " FROM courses,crs_usr,usr_data"
				   " WHERE courses.DegCod=%ld"
				   " AND courses.CrsCod=crs_usr.CrsCod"
				   " AND crs_usr.UsrCod=usr_data.UsrCod"
				   " AND %s",
				   Gbl.Hierarchy.Deg.DegCod,SubQuery);
	 break;
      case Hie_CRS:
	 NumUsrs =
	 (unsigned) DB_QueryCOUNT ("can not get the number of users"
				   " who have chosen an option",
				   "SELECT COUNT(DISTINCT usr_data.UsrCod)"
				   " FROM crs_usr,usr_data"
				   " WHERE crs_usr.CrsCod=%ld"
				   " AND crs_usr.UsrCod=usr_data.UsrCod"
				   " AND %s",
				   Gbl.Hierarchy.Crs.CrsCod,SubQuery);
	 break;
      default:
	 Lay_WrongScopeExit ();
	 NumUsrs = 0;	// Not reached. Initialized to avoid warning.
	 break;
     }

   return NumUsrs;
  }
