swad-core/swad_match_result.c

1357 lines
44 KiB
C
Raw Permalink Normal View History

2019-09-28 02:31:42 +02:00
// swad_match_result.c: matches results in games using remote control
/*
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-2024 Antonio Ca<EFBFBD>as Vargas
2019-09-28 02:31:42 +02:00
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*****************************************************************************/
/********************************* Headers ***********************************/
/*****************************************************************************/
#define _GNU_SOURCE // For asprintf
#include <linux/limits.h> // For PATH_MAX
2019-12-29 12:39:00 +01:00
#include <stddef.h> // For NULL
2019-09-28 02:31:42 +02:00
#include <stdio.h> // For asprintf
#include <stdlib.h> // For free
2019-09-28 02:31:42 +02:00
#include <string.h> // For string functions
2019-09-30 01:23:24 +02:00
#include "swad_action.h"
#include "swad_action_list.h"
#include "swad_box.h"
2019-09-28 02:31:42 +02:00
#include "swad_database.h"
2019-09-30 01:23:24 +02:00
#include "swad_date.h"
#include "swad_error.h"
2019-09-28 02:31:42 +02:00
#include "swad_form.h"
#include "swad_global.h"
2019-10-23 19:05:05 +02:00
#include "swad_HTML.h"
2019-09-28 02:31:42 +02:00
#include "swad_ID.h"
#include "swad_match.h"
#include "swad_match_database.h"
2019-09-28 02:31:42 +02:00
#include "swad_match_result.h"
#include "swad_parameter.h"
#include "swad_parameter_code.h"
2020-04-14 17:15:17 +02:00
#include "swad_photo.h"
2020-02-18 09:19:33 +01:00
#include "swad_test_visibility.h"
2019-09-28 02:31:42 +02:00
#include "swad_user.h"
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
extern struct Globals Gbl;
/*****************************************************************************/
/******************************* Private types *******************************/
/*****************************************************************************/
2020-06-23 11:48:06 +02:00
struct MchRes_ICanView
{
Usr_Can_t Result;
Usr_Can_t Score;
2020-06-23 11:48:06 +02:00
};
2019-09-28 02:31:42 +02:00
/*****************************************************************************/
/***************************** Private prototypes ****************************/
/*****************************************************************************/
static void MchRes_PutFormToSelUsrsToViewMchResults (__attribute__((unused)) void *Args);
2020-04-08 03:06:45 +02:00
static void MchRes_ListMyMchResultsInCrs (struct Gam_Games *Games);
static void MchRes_ListMyMchResultsInGam (struct Gam_Games *Games);
2020-04-08 03:06:45 +02:00
static void MchRes_ListMyMchResultsInMch (struct Gam_Games *Games,long MchCod);
static void MchRes_ShowAllMchResultsInSelectedGames (void *Games);
static void MchRes_ListAllMchResultsInSelectedGames (struct Gam_Games *Games);
static void MchRes_ListAllMchResultsInGam (struct Gam_Games *Games);
2020-04-08 03:06:45 +02:00
static void MchRes_ListAllMchResultsInMch (struct Gam_Games *Games,long MchCod);
static void MchRes_ShowResultsBegin (struct Gam_Games *Games,
const char *Title,bool ListGamesToSelect);
2020-04-02 03:28:08 +02:00
static void MchRes_ShowResultsEnd (void);
2020-04-08 03:06:45 +02:00
static void MchRes_ListGamesToSelect (struct Gam_Games *Games);
2020-04-02 03:28:08 +02:00
static void MchRes_ShowHeaderMchResults (Usr_MeOrOther_t MeOrOther);
2020-04-08 03:06:45 +02:00
static void MchRes_BuildGamesSelectedCommas (struct Gam_Games *Games,
char **GamesSelectedCommas);
static void MchRes_ShowMchResults (struct Gam_Games *Games,
Usr_MeOrOther_t MeOrOther,
long MchCod, // <= 0 ==> any
long GamCod, // <= 0 ==> any
const char *GamesSelectedCommas);
2020-04-02 03:28:08 +02:00
static void MchRes_ShowMchResultsSummaryRow (unsigned NumResults,
2020-06-24 20:10:57 +02:00
struct MchPrn_NumQuestions *NumTotalQsts,
double TotalScore,
2020-04-08 03:06:45 +02:00
double TotalGrade);
2020-06-24 20:10:57 +02:00
static void MchRes_CheckIfICanViewMatchResult (const struct Gam_Game *Game,
const struct Mch_Match *Match,
long UsrCod,
struct MchRes_ICanView *ICanView);
2019-09-28 02:31:42 +02:00
2019-12-08 13:34:12 +01:00
/*****************************************************************************/
/*************************** Show my matches results *************************/
/*****************************************************************************/
2020-04-02 03:28:08 +02:00
void MchRes_ShowMyMchResultsInCrs (void)
2019-12-08 13:34:12 +01:00
{
extern const char *Txt_Results;
2020-04-08 03:06:45 +02:00
struct Gam_Games Games;
2020-04-23 23:09:28 +02:00
/***** Reset games context *****/
2020-04-08 03:06:45 +02:00
Gam_ResetGames (&Games);
2019-12-08 13:34:12 +01:00
/***** Get list of games *****/
2020-04-08 03:06:45 +02:00
Gam_GetListGames (&Games,Gam_ORDER_BY_TITLE);
Gam_GetListSelectedGamCods (&Games);
2019-12-08 13:34:12 +01:00
2019-12-08 23:19:16 +01:00
/***** List my matches results in the current course *****/
2020-04-08 03:06:45 +02:00
MchRes_ShowResultsBegin (&Games,Txt_Results,true); // List games to select
MchRes_ListMyMchResultsInCrs (&Games);
2020-04-02 03:28:08 +02:00
MchRes_ShowResultsEnd ();
2019-12-08 13:34:12 +01:00
2019-12-08 23:19:16 +01:00
/***** Free list of games *****/
2020-04-08 03:06:45 +02:00
free (Games.GamCodsSelected);
Gam_FreeListGames (&Games);
2019-12-08 23:19:16 +01:00
}
2019-12-08 15:03:40 +01:00
2020-04-08 03:06:45 +02:00
static void MchRes_ListMyMchResultsInCrs (struct Gam_Games *Games)
2019-12-08 23:19:16 +01:00
{
char *GamesSelectedCommas = NULL; // Initialized to avoid warning
/***** Table header *****/
2020-04-02 03:28:08 +02:00
MchRes_ShowHeaderMchResults (Usr_ME);
2019-12-08 13:34:12 +01:00
2019-12-08 23:19:16 +01:00
/***** List my matches results in the current course *****/
TstCfg_GetConfig (); // Get feedback type
2020-04-08 03:06:45 +02:00
MchRes_BuildGamesSelectedCommas (Games,&GamesSelectedCommas);
MchRes_ShowMchResults (Games,Usr_ME,-1L,-1L,GamesSelectedCommas);
2019-12-08 13:34:12 +01:00
free (GamesSelectedCommas);
}
/*****************************************************************************/
/***************** Show my matches results in a given game *******************/
/*****************************************************************************/
2020-04-02 03:28:08 +02:00
void MchRes_ShowMyMchResultsInGam (void)
2019-12-08 13:34:12 +01:00
{
2019-12-08 23:19:16 +01:00
extern const char *Txt_Results_of_game_X;
2020-04-08 03:06:45 +02:00
struct Gam_Games Games;
char *Title;
2020-04-08 03:06:45 +02:00
2020-04-23 23:09:28 +02:00
/***** Reset games context *****/
2020-04-08 03:06:45 +02:00
Gam_ResetGames (&Games);
Gam_ResetGame (&Games.Game);
2020-04-23 23:09:28 +02:00
2019-12-08 14:14:29 +01:00
/***** Get parameters *****/
if ((Games.Game.GamCod = Gam_GetPars (&Games)) <= 0)
Err_WrongGameExit ();
Gam_GetGameDataByCod (&Games.Game);
2019-12-08 13:34:12 +01:00
2019-12-08 17:08:15 +01:00
/***** Game begin *****/
Gam_ShowOnlyOneGameBegin (&Games,
2019-12-08 17:08:15 +01:00
false, // Do not list game questions
Frm_DONT_PUT_FORM);
2019-12-08 13:34:12 +01:00
2019-12-08 23:19:16 +01:00
/***** List my matches results in game *****/
if (asprintf (&Title,Txt_Results_of_game_X,Games.Game.Title) < 0)
Err_NotEnoughMemoryExit ();
MchRes_ShowResultsBegin (&Games,Title,false); // Do not list games to select
free (Title);
MchRes_ListMyMchResultsInGam (&Games);
2020-04-02 03:28:08 +02:00
MchRes_ShowResultsEnd ();
2019-12-08 13:34:12 +01:00
2019-12-08 23:19:16 +01:00
/***** Game end *****/
Gam_ShowOnlyOneGameEnd ();
}
static void MchRes_ListMyMchResultsInGam (struct Gam_Games *Games)
2019-12-08 23:19:16 +01:00
{
/***** Table header *****/
2020-04-02 03:28:08 +02:00
MchRes_ShowHeaderMchResults (Usr_ME);
2019-12-08 13:34:12 +01:00
2019-12-08 23:19:16 +01:00
/***** List my matches results in game *****/
TstCfg_GetConfig (); // Get feedback type
MchRes_ShowMchResults (Games,Usr_ME,-1L,Games->Game.GamCod,NULL);
2019-12-08 23:19:16 +01:00
}
2019-12-08 13:34:12 +01:00
2019-12-08 23:19:16 +01:00
/*****************************************************************************/
/***************** Show my matches results in a given match ******************/
/*****************************************************************************/
2019-12-08 13:34:12 +01:00
2020-04-02 03:28:08 +02:00
void MchRes_ShowMyMchResultsInMch (void)
2019-12-08 23:19:16 +01:00
{
extern const char *Txt_Results_of_match_X;
2020-04-08 03:06:45 +02:00
struct Gam_Games Games;
struct Mch_Match Match;
char *Title;
2020-04-08 03:06:45 +02:00
2020-04-23 23:09:28 +02:00
/***** Reset games context *****/
2020-04-08 03:06:45 +02:00
Gam_ResetGames (&Games);
Gam_ResetGame (&Games.Game);
2020-04-23 23:09:28 +02:00
Mch_ResetMatch (&Match);
2019-12-08 23:19:16 +01:00
/***** Get parameters *****/
if ((Games.Game.GamCod = Gam_GetPars (&Games)) <= 0)
Err_WrongGameExit ();
Match.MchCod = ParCod_GetAndCheckPar (ParCod_Mch);
Gam_GetGameDataByCod (&Games.Game);
Mch_GetMatchDataByCod (&Match);
2019-12-08 23:19:16 +01:00
/***** Game begin *****/
Gam_ShowOnlyOneGameBegin (&Games,
2019-12-08 23:19:16 +01:00
false, // Do not list game questions
Frm_DONT_PUT_FORM);
2019-12-08 23:19:16 +01:00
/***** List my matches results in match *****/
if (asprintf (&Title,Txt_Results_of_match_X,Match.Title) < 0)
Err_NotEnoughMemoryExit ();
MchRes_ShowResultsBegin (&Games,Title,false); // Do not list games to select
free (Title);
MchRes_ListMyMchResultsInMch (&Games,Match.MchCod);
2020-04-02 03:28:08 +02:00
MchRes_ShowResultsEnd ();
2019-12-08 13:34:12 +01:00
2019-12-08 17:08:15 +01:00
/***** Game end *****/
Gam_ShowOnlyOneGameEnd ();
2019-12-08 23:19:16 +01:00
}
2019-12-08 17:08:15 +01:00
2020-04-08 03:06:45 +02:00
static void MchRes_ListMyMchResultsInMch (struct Gam_Games *Games,long MchCod)
2019-12-08 23:19:16 +01:00
{
/***** Table header *****/
2020-04-02 03:28:08 +02:00
MchRes_ShowHeaderMchResults (Usr_ME);
2019-12-08 23:19:16 +01:00
/***** List my matches results in game *****/
TstCfg_GetConfig (); // Get feedback type
2020-04-08 03:06:45 +02:00
MchRes_ShowMchResults (Games,Usr_ME,MchCod,-1L,NULL);
2019-12-08 13:34:12 +01:00
}
2019-11-14 14:34:34 +01:00
/*****************************************************************************/
/****************** Get users and show their matches results *****************/
/*****************************************************************************/
2020-04-02 03:28:08 +02:00
void MchRes_ShowAllMchResultsInCrs (void)
2019-11-14 14:34:34 +01:00
{
2020-04-08 03:06:45 +02:00
struct Gam_Games Games;
2020-04-23 23:09:28 +02:00
/***** Reset games context *****/
2020-04-08 03:06:45 +02:00
Gam_ResetGames (&Games);
/***** Get users and show their matches results *****/
2019-11-15 03:34:48 +01:00
Usr_GetSelectedUsrsAndGoToAct (&Gbl.Usrs.Selected,
2020-04-08 03:06:45 +02:00
MchRes_ShowAllMchResultsInSelectedGames,&Games,
MchRes_PutFormToSelUsrsToViewMchResults,NULL);
2019-12-07 02:12:13 +01:00
}
2019-09-28 02:31:42 +02:00
/*****************************************************************************/
/****************** Show matches results for several users *******************/
/*****************************************************************************/
2020-04-08 03:06:45 +02:00
static void MchRes_ShowAllMchResultsInSelectedGames (void *Games)
2019-09-28 02:31:42 +02:00
{
extern const char *Txt_Results;
2020-04-08 03:06:45 +02:00
if (!Games)
2020-04-06 16:00:06 +02:00
return;
2019-11-25 23:18:08 +01:00
/***** Get list of games *****/
2020-04-08 03:06:45 +02:00
Gam_GetListGames ((struct Gam_Games *) Games,Gam_ORDER_BY_TITLE);
Gam_GetListSelectedGamCods ((struct Gam_Games *) Games);
2019-12-08 13:34:12 +01:00
2019-12-08 23:19:16 +01:00
/***** List the matches results of the selected users *****/
2020-04-08 03:06:45 +02:00
MchRes_ShowResultsBegin ((struct Gam_Games *) Games,
Txt_Results,
true); // List games to select
MchRes_ListAllMchResultsInSelectedGames ((struct Gam_Games *) Games);
2020-04-02 03:28:08 +02:00
MchRes_ShowResultsEnd ();
2019-11-25 23:18:08 +01:00
2019-12-08 23:19:16 +01:00
/***** Free list of games *****/
2020-04-08 03:06:45 +02:00
free (((struct Gam_Games *) Games)->GamCodsSelected);
Gam_FreeListGames ((struct Gam_Games *) Games);
2019-12-08 23:19:16 +01:00
}
2019-11-25 23:18:08 +01:00
2020-04-08 03:06:45 +02:00
static void MchRes_ListAllMchResultsInSelectedGames (struct Gam_Games *Games)
2019-12-08 23:19:16 +01:00
{
char *GamesSelectedCommas = NULL; // Initialized to avoid warning
const char *Ptr;
/***** Table head *****/
2020-04-02 03:28:08 +02:00
MchRes_ShowHeaderMchResults (Usr_OTHER);
2019-12-08 13:34:12 +01:00
/***** List the matches results of the selected users *****/
2020-04-08 03:06:45 +02:00
MchRes_BuildGamesSelectedCommas (Games,&GamesSelectedCommas);
2019-12-08 13:34:12 +01:00
Ptr = Gbl.Usrs.Selected.List[Rol_UNK];
while (*Ptr)
2019-11-25 23:18:08 +01:00
{
Par_GetNextStrUntilSeparParMult (&Ptr,Gbl.Usrs.Other.UsrDat.EnUsrCod,
2019-12-08 13:34:12 +01:00
Cry_BYTES_ENCRYPTED_STR_SHA256_BASE64);
Usr_GetUsrCodFromEncryptedUsrCod (&Gbl.Usrs.Other.UsrDat);
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat,
Usr_DONT_GET_PREFS,
Usr_GET_ROLE_IN_CRS))
if (Usr_CheckIfICanViewTstExaMchResult (&Gbl.Usrs.Other.UsrDat) == Usr_CAN)
2019-12-08 13:34:12 +01:00
{
/***** Show matches results *****/
Gbl.Usrs.Other.UsrDat.Accepted = Enr_CheckIfUsrHasAcceptedInCurrentCrs (&Gbl.Usrs.Other.UsrDat);
2020-04-08 03:06:45 +02:00
MchRes_ShowMchResults (Games,Usr_OTHER,-1L,-1L,GamesSelectedCommas);
2019-12-08 13:34:12 +01:00
}
}
free (GamesSelectedCommas);
}
2020-04-08 03:06:45 +02:00
/*****************************************************************************/
/**************** Select users to show their matches results *****************/
/*****************************************************************************/
void MchRes_SelUsrsToViewMchResults (void)
{
MchRes_PutFormToSelUsrsToViewMchResults (NULL);
2020-04-08 03:06:45 +02:00
}
static void MchRes_PutFormToSelUsrsToViewMchResults (__attribute__((unused)) void *Args)
2020-04-08 03:06:45 +02:00
{
extern const char *Hlp_ASSESSMENT_Games_results;
extern const char *Txt_Results;
2020-05-18 22:59:07 +02:00
extern const char *Txt_View_results;
2020-04-08 03:06:45 +02:00
Usr_PutFormToSelectUsrsToGoToAct (&Gbl.Usrs.Selected,
ActSeeUsrMchResCrs,
NULL,NULL,
Txt_Results,
Hlp_ASSESSMENT_Games_results,
Txt_View_results,
Frm_DONT_PUT_FORM); // Do not put form with date range
2020-04-08 03:06:45 +02:00
}
2019-12-08 13:34:12 +01:00
/*****************************************************************************/
2019-12-08 23:19:16 +01:00
/*** Show matches results of a game for the users who answered in that game **/
2019-12-08 13:34:12 +01:00
/*****************************************************************************/
2020-04-02 03:28:08 +02:00
void MchRes_ShowAllMchResultsInGam (void)
2019-12-08 13:34:12 +01:00
{
2019-12-08 23:19:16 +01:00
extern const char *Txt_Results_of_game_X;
2020-04-08 03:06:45 +02:00
struct Gam_Games Games;
char *Title;
2020-04-08 03:06:45 +02:00
2020-04-23 23:09:28 +02:00
/***** Reset games context *****/
2020-04-08 03:06:45 +02:00
Gam_ResetGames (&Games);
Gam_ResetGame (&Games.Game);
2020-04-23 23:09:28 +02:00
2019-12-08 23:19:16 +01:00
/***** Get parameters *****/
if ((Games.Game.GamCod = Gam_GetPars (&Games)) <= 0)
Err_WrongGameExit ();
Gam_GetGameDataByCod (&Games.Game);
2019-12-08 23:19:16 +01:00
/***** Game begin *****/
Gam_ShowOnlyOneGameBegin (&Games,
2019-12-08 23:19:16 +01:00
false, // Do not list game questions
Frm_DONT_PUT_FORM);
2019-12-08 23:19:16 +01:00
/***** List matches results in game *****/
if (asprintf (&Title,Txt_Results_of_game_X,Games.Game.Title) < 0)
Err_NotEnoughMemoryExit ();
MchRes_ShowResultsBegin (&Games,Title,false); // Do not list games to select
free (Title);
MchRes_ListAllMchResultsInGam (&Games);
2020-04-02 03:28:08 +02:00
MchRes_ShowResultsEnd ();
2019-12-08 23:19:16 +01:00
/***** Game end *****/
Gam_ShowOnlyOneGameEnd ();
}
static void MchRes_ListAllMchResultsInGam (struct Gam_Games *Games)
2019-12-08 23:19:16 +01:00
{
2019-12-08 13:34:12 +01:00
MYSQL_RES *mysql_res;
unsigned NumUsrs;
unsigned NumUsr;
2019-12-08 13:34:12 +01:00
2019-12-08 23:19:16 +01:00
/***** Table head *****/
2020-04-02 03:28:08 +02:00
MchRes_ShowHeaderMchResults (Usr_OTHER);
2019-12-08 23:19:16 +01:00
/***** Get all users who have answered any match question in this game *****/
NumUsrs = Mch_DB_GetUsrsWhoHavePlayedGam (&mysql_res,Games->Game.GamCod);
/***** List matches results for each user *****/
for (NumUsr = 0;
NumUsr < NumUsrs;
NumUsr++)
/* Get match code */
if ((Gbl.Usrs.Other.UsrDat.UsrCod = DB_GetNextCode (mysql_res)) > 0)
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat,
Usr_DONT_GET_PREFS,
Usr_GET_ROLE_IN_CRS))
if (Usr_CheckIfICanViewTstExaMchResult (&Gbl.Usrs.Other.UsrDat) == Usr_CAN)
{
/***** Show matches results *****/
Gbl.Usrs.Other.UsrDat.Accepted = Enr_CheckIfUsrHasAcceptedInCurrentCrs (&Gbl.Usrs.Other.UsrDat);
MchRes_ShowMchResults (Games,Usr_OTHER,-1L,Games->Game.GamCod,NULL);
}
2019-12-08 23:19:16 +01:00
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
/*****************************************************************************/
/** Show matches results of a match for the users who answered in that match */
/*****************************************************************************/
2020-04-02 03:28:08 +02:00
void MchRes_ShowAllMchResultsInMch (void)
2019-12-08 23:19:16 +01:00
{
extern const char *Txt_Results_of_match_X;
2020-04-08 03:06:45 +02:00
struct Gam_Games Games;
struct Mch_Match Match;
char *Title;
2020-04-08 03:06:45 +02:00
2020-04-23 23:09:28 +02:00
/***** Reset games context *****/
2020-04-08 03:06:45 +02:00
Gam_ResetGames (&Games);
Gam_ResetGame (&Games.Game);
2020-04-23 23:09:28 +02:00
Mch_ResetMatch (&Match);
2019-12-08 14:14:29 +01:00
/***** Get parameters *****/
if ((Games.Game.GamCod = Gam_GetPars (&Games)) <= 0)
Err_WrongGameExit ();
Match.MchCod = ParCod_GetAndCheckPar (ParCod_Mch);
Gam_GetGameDataByCod (&Games.Game);
Mch_GetMatchDataByCod (&Match);
2019-12-08 13:34:12 +01:00
2019-12-08 17:08:15 +01:00
/***** Game begin *****/
Gam_ShowOnlyOneGameBegin (&Games,
2019-12-08 17:08:15 +01:00
false, // Do not list game questions
Frm_DONT_PUT_FORM);
2019-12-08 14:14:29 +01:00
2019-12-08 23:19:16 +01:00
/***** List matches results in match *****/
if (asprintf (&Title,Txt_Results_of_match_X,Match.Title) < 0)
Err_NotEnoughMemoryExit ();
MchRes_ShowResultsBegin (&Games,Title,false); // Do not list games to select
free (Title);
MchRes_ListAllMchResultsInMch (&Games,Match.MchCod);
2020-04-02 03:28:08 +02:00
MchRes_ShowResultsEnd ();
2019-12-08 13:34:12 +01:00
2019-12-08 23:19:16 +01:00
/***** Game end *****/
Gam_ShowOnlyOneGameEnd ();
}
2020-04-08 03:06:45 +02:00
static void MchRes_ListAllMchResultsInMch (struct Gam_Games *Games,long MchCod)
2019-12-08 23:19:16 +01:00
{
MYSQL_RES *mysql_res;
unsigned NumUsrs;
unsigned NumUsr;
2019-12-08 23:19:16 +01:00
/***** Table head *****/
2020-04-02 03:28:08 +02:00
MchRes_ShowHeaderMchResults (Usr_OTHER);
2019-12-08 23:19:16 +01:00
/***** Get all users who have answered any match question in this game *****/
NumUsrs = Mch_DB_GetUsrsWhoHavePlayedMch (&mysql_res,MchCod);
/***** List matches results for each user *****/
for (NumUsr = 0;
NumUsr < NumUsrs;
NumUsr++)
/* Get match code (row[0]) */
if ((Gbl.Usrs.Other.UsrDat.UsrCod = DB_GetNextCode (mysql_res)) > 0)
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat,
Usr_DONT_GET_PREFS,
Usr_GET_ROLE_IN_CRS))
if (Usr_CheckIfICanViewTstExaMchResult (&Gbl.Usrs.Other.UsrDat) == Usr_CAN)
{
/***** Show matches results *****/
Gbl.Usrs.Other.UsrDat.Accepted = Enr_CheckIfUsrHasAcceptedInCurrentCrs (&Gbl.Usrs.Other.UsrDat);
MchRes_ShowMchResults (Games,Usr_OTHER,MchCod,-1L,NULL);
}
2019-11-25 23:18:08 +01:00
2019-12-08 13:34:12 +01:00
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
2019-12-08 23:19:16 +01:00
}
2019-11-25 23:18:08 +01:00
2019-12-08 23:19:16 +01:00
/*****************************************************************************/
/************************ Show results (begin / end) *************************/
/*****************************************************************************/
2019-12-08 13:34:12 +01:00
2020-04-08 03:06:45 +02:00
static void MchRes_ShowResultsBegin (struct Gam_Games *Games,
const char *Title,bool ListGamesToSelect)
2019-12-08 23:19:16 +01:00
{
extern const char *Hlp_ASSESSMENT_Games_results;
2019-12-08 17:08:15 +01:00
2019-12-08 23:19:16 +01:00
/***** Begin box *****/
2020-04-02 03:28:08 +02:00
HTM_SECTION_Begin (MchRes_RESULTS_BOX_ID);
Box_BoxBegin (Title,NULL,NULL,
Hlp_ASSESSMENT_Games_results,Box_NOT_CLOSABLE);
2019-12-08 23:19:16 +01:00
/***** List games to select *****/
if (ListGamesToSelect)
MchRes_ListGamesToSelect (Games);
2019-12-08 23:19:16 +01:00
/***** Begin match results table *****/
HTM_SECTION_Begin (MchRes_RESULTS_TABLE_ID);
HTM_TABLE_BeginWidePadding (5);
2019-12-08 23:19:16 +01:00
}
2020-04-02 03:28:08 +02:00
static void MchRes_ShowResultsEnd (void)
2019-12-08 23:19:16 +01:00
{
/***** End match results table *****/
HTM_TABLE_End ();
HTM_SECTION_End ();
2019-12-08 23:19:16 +01:00
/***** End box *****/
Box_BoxEnd ();
2019-12-09 11:09:12 +01:00
HTM_SECTION_End ();
2019-11-25 23:18:08 +01:00
}
/*****************************************************************************/
/********** Write list of those attendance events that have students *********/
/*****************************************************************************/
2020-04-08 03:06:45 +02:00
static void MchRes_ListGamesToSelect (struct Gam_Games *Games)
2019-11-25 23:18:08 +01:00
{
extern const char *Par_CodeStr[Par_NUM_PAR_COD];
2019-11-25 23:18:08 +01:00
extern const char *Txt_Games;
extern const char *Txt_Game;
extern const char *Txt_Update_results;
unsigned UniqueId;
unsigned NumGame;
2019-09-28 02:31:42 +02:00
2020-04-23 23:09:28 +02:00
/***** Reset game *****/
Gam_ResetGame (&Games->Game);
2020-04-23 23:09:28 +02:00
2019-11-25 23:18:08 +01:00
/***** Begin box *****/
Box_BoxBegin (Txt_Games,NULL,NULL,NULL,Box_CLOSABLE);
2019-11-25 23:18:08 +01:00
/***** Begin form to update the results
depending on the games selected *****/
Frm_BeginFormAnchor (Gbl.Action.Act,MchRes_RESULTS_TABLE_ID);
Grp_PutParsCodGrps ();
Usr_PutParSelectedUsrsCods (&Gbl.Usrs.Selected);
2019-11-14 14:34:34 +01:00
/***** Begin table *****/
HTM_TABLE_BeginWidePadding (2);
2019-11-25 23:18:08 +01:00
/***** Heading row *****/
HTM_TR_Begin (NULL);
HTM_TH_Empty (2);
HTM_TH (Txt_Game,HTM_HEAD_LEFT);
HTM_TR_End ();
2019-11-25 23:18:08 +01:00
/***** List the events *****/
for (NumGame = 0, UniqueId = 1, The_ResetRowColor ();
NumGame < Games->Num;
NumGame++, UniqueId++, The_ChangeRowColor ())
{
/* Get data of this game */
Games->Game.GamCod = Games->Lst[NumGame].GamCod;
Gam_GetGameDataByCod (&Games->Game);
/* Write a row for this event */
HTM_TR_Begin (NULL);
HTM_TD_Begin ("class=\"CT DAT_%s %s\"",
The_GetSuffix (),The_GetColorRows ());
HTM_INPUT_CHECKBOX (Par_CodeStr[ParCod_Gam],
Games->Lst[NumGame].Checked,
HTM_DONT_SUBMIT_ON_CHANGE,
"id=\"Gam%u\" value=\"%ld\"",
NumGame,Games->Lst[NumGame].GamCod);
HTM_TD_End ();
HTM_TD_Begin ("class=\"RT DAT_%s %s\"",
The_GetSuffix (),The_GetColorRows ());
HTM_LABEL_Begin ("for=\"Gam%u\"",NumGame);
HTM_UnsignedColon (NumGame + 1);
HTM_LABEL_End ();
HTM_TD_End ();
HTM_TD_Begin ("class=\"LT DAT_%s %s\"",
The_GetSuffix (),The_GetColorRows ());
HTM_Txt (Games->Game.Title);
HTM_TD_End ();
HTM_TR_End ();
}
2019-09-28 02:31:42 +02:00
/***** End table *****/
HTM_TABLE_End ();
2019-11-25 23:18:08 +01:00
/***** Put button to refresh *****/
Lay_WriteLinkToUpdate (Txt_Update_results,NULL);
/***** End form *****/
Frm_EndForm ();
2019-11-25 23:18:08 +01:00
/***** End box *****/
Box_BoxEnd ();
2019-09-28 02:31:42 +02:00
}
/*****************************************************************************/
/********************* Show header of my matches results *********************/
/*****************************************************************************/
2020-04-02 03:28:08 +02:00
static void MchRes_ShowHeaderMchResults (Usr_MeOrOther_t MeOrOther)
2019-09-28 02:31:42 +02:00
{
extern const char *Txt_User[Usr_NUM_SEXS];
2019-09-30 20:13:08 +02:00
extern const char *Txt_Match;
2019-09-28 02:31:42 +02:00
extern const char *Txt_START_END_TIME[Dat_NUM_START_END_TIME];
extern const char *Txt_Questions;
2020-06-24 20:10:57 +02:00
extern const char *Txt_Answers;
2019-11-28 22:17:00 +01:00
extern const char *Txt_Score;
2019-11-28 00:19:42 +01:00
extern const char *Txt_Grade;
2020-06-24 20:10:57 +02:00
extern const char *Txt_ANSWERS_non_blank;
extern const char *Txt_ANSWERS_blank;
extern const char *Txt_total;
extern const char *Txt_average;
/***** First row *****/
HTM_TR_Begin (NULL);
HTM_TH_Span (Txt_User[MeOrOther == Usr_ME ? Gbl.Usrs.Me.UsrDat.Sex :
Usr_SEX_UNKNOWN],HTM_HEAD_CENTER,3,2,"LINE_BOTTOM");
HTM_TH_Span (Txt_START_END_TIME[Dat_STR_TIME] ,HTM_HEAD_LEFT ,3,1,"LINE_BOTTOM");
HTM_TH_Span (Txt_START_END_TIME[Dat_END_TIME] ,HTM_HEAD_LEFT ,3,1,"LINE_BOTTOM");
HTM_TH_Span (Txt_Match ,HTM_HEAD_LEFT ,3,1,"LINE_BOTTOM");
HTM_TH_Span (Txt_Questions ,HTM_HEAD_RIGHT ,3,1,"LINE_BOTTOM LINE_LEFT");
HTM_TH_Span (Txt_Answers ,HTM_HEAD_CENTER,1,2,"LINE_LEFT");
HTM_TH_Span (Txt_Score ,HTM_HEAD_CENTER,1,2,"LINE_LEFT");
HTM_TH_Span (Txt_Grade ,HTM_HEAD_RIGHT ,3,1,"LINE_BOTTOM LINE_LEFT");
HTM_TH_Span (NULL ,HTM_HEAD_LEFT ,3,1,"LINE_BOTTOM LINE_LEFT");
2020-06-24 20:10:57 +02:00
HTM_TR_End ();
/***** Second row *****/
HTM_TR_Begin (NULL);
HTM_TH_Span (Txt_ANSWERS_non_blank ,HTM_HEAD_RIGHT ,1,1,"LINE_LEFT");
HTM_TH (Txt_ANSWERS_blank ,HTM_HEAD_RIGHT);
HTM_TH_Span (Txt_total ,HTM_HEAD_RIGHT ,1,1,"LINE_LEFT");
HTM_TH (Txt_average ,HTM_HEAD_RIGHT);
2020-06-24 20:10:57 +02:00
HTM_TR_End ();
/***** Third row *****/
2019-10-23 19:05:05 +02:00
HTM_TR_Begin (NULL);
HTM_TH_Span ("{-1&le;<em>p<sub>i</sub></em>&le;1}" ,HTM_HEAD_RIGHT ,1,1,"LINE_BOTTOM LINE_LEFT");
HTM_TH_Span ("{<em>p<sub>i</sub></em>=0}" ,HTM_HEAD_RIGHT ,1,1,"LINE_BOTTOM");
HTM_TH_Span ("<em>&Sigma;p<sub>i</sub></em>" ,HTM_HEAD_RIGHT ,1,1,"LINE_BOTTOM LINE_LEFT");
HTM_TH_Span ("-1&le;"
"<em style=\"text-decoration:overline;\">p</em>"
"&le;1" ,HTM_HEAD_RIGHT ,1,1,"LINE_BOTTOM");
2019-10-23 19:05:05 +02:00
HTM_TR_End ();
2019-09-28 02:31:42 +02:00
}
2019-12-08 13:34:12 +01:00
/*****************************************************************************/
/******* Build string with list of selected games separated by commas ********/
/******* from list of selected games ********/
/*****************************************************************************/
2020-04-08 03:06:45 +02:00
static void MchRes_BuildGamesSelectedCommas (struct Gam_Games *Games,
char **GamesSelectedCommas)
2019-12-08 13:34:12 +01:00
{
size_t MaxLength;
unsigned NumGame;
char LongStr[Cns_MAX_DECIMAL_DIGITS_LONG + 1];
/***** Allocate memory for subquery of games selected *****/
2020-04-08 03:06:45 +02:00
MaxLength = (size_t) Games->NumSelected * (Cns_MAX_DECIMAL_DIGITS_LONG + 1);
if ((*GamesSelectedCommas = malloc (MaxLength + 1)) == NULL)
Err_NotEnoughMemoryExit ();
2019-12-08 13:34:12 +01:00
/***** Build subquery with list of selected games *****/
2019-12-08 14:14:29 +01:00
(*GamesSelectedCommas)[0] = '\0';
2019-12-08 13:34:12 +01:00
for (NumGame = 0;
2020-04-08 03:06:45 +02:00
NumGame < Games->Num;
2019-12-08 13:34:12 +01:00
NumGame++)
if (Games->Lst[NumGame].Checked == Cns_CHECKED)
2019-12-08 13:34:12 +01:00
{
2020-04-08 03:06:45 +02:00
sprintf (LongStr,"%ld",Games->Lst[NumGame].GamCod);
2019-12-08 14:14:29 +01:00
if ((*GamesSelectedCommas)[0])
Str_Concat (*GamesSelectedCommas,",",MaxLength);
Str_Concat (*GamesSelectedCommas,LongStr,MaxLength);
2019-12-08 13:34:12 +01:00
}
}
2019-09-28 02:31:42 +02:00
/*****************************************************************************/
/********* Show the matches results of a user in the current course **********/
/*****************************************************************************/
2020-04-08 03:06:45 +02:00
static void MchRes_ShowMchResults (struct Gam_Games *Games,
Usr_MeOrOther_t MeOrOther,
long MchCod, // <= 0 ==> any
long GamCod, // <= 0 ==> any
const char *GamesSelectedCommas)
2019-09-28 02:31:42 +02:00
{
MYSQL_RES *mysql_res;
struct Usr_Data *UsrDat;
2020-06-23 11:48:06 +02:00
struct MchRes_ICanView ICanView;
2019-09-28 02:31:42 +02:00
unsigned NumResults;
unsigned NumResult;
static unsigned UniqueId = 0;
2020-06-24 20:10:57 +02:00
Dat_StartEndTime_t StartEndTime;
2019-11-01 22:53:39 +01:00
char *Id;
2020-06-24 20:10:57 +02:00
struct MchPrn_Print Print;
unsigned NumQstsBlank;
2020-04-08 03:06:45 +02:00
struct Mch_Match Match;
2019-11-28 00:19:42 +01:00
double Grade;
2020-06-24 20:10:57 +02:00
struct MchPrn_NumQuestions NumTotalQsts;
double TotalScore;
double TotalGrade;
2019-09-28 02:31:42 +02:00
2020-06-24 20:10:57 +02:00
/***** Reset total number of questions and total score *****/
NumTotalQsts.All =
NumTotalQsts.NotBlank = 0;
TotalScore = 0.0;
TotalGrade = 0.0;
2020-04-23 23:09:28 +02:00
2019-09-28 02:31:42 +02:00
/***** Set user *****/
UsrDat = (MeOrOther == Usr_ME) ? &Gbl.Usrs.Me.UsrDat :
2019-11-25 23:18:08 +01:00
&Gbl.Usrs.Other.UsrDat;
2019-09-28 02:31:42 +02:00
/***** Make database query *****/
NumResults = Mch_DB_GetUsrMchResults (&mysql_res,MeOrOther,MchCod,GamCod,GamesSelectedCommas);
2019-09-28 02:31:42 +02:00
/***** Show user's data *****/
2019-10-23 19:05:05 +02:00
HTM_TR_Begin (NULL);
2019-09-28 02:31:42 +02:00
Usr_ShowTableCellWithUsrData (UsrDat,NumResults);
/***** Get and print matches results *****/
if (NumResults)
{
for (NumResult = 0;
2019-11-25 23:18:08 +01:00
NumResult < NumResults;
NumResult++)
{
/* Get match code */
MchPrn_ResetPrint (&Print);
if ((Print.MchCod = DB_GetNextCode (mysql_res)) < 0)
Err_WrongMatchExit ();
2020-06-24 20:10:57 +02:00
/* Get match result data */
Print.UsrCod = UsrDat->UsrCod;
MchPrn_GetMatchPrintDataByMchCodAndUsrCod (&Print);
2019-09-28 02:31:42 +02:00
2020-06-23 11:48:06 +02:00
/* Get data of match and game */
2020-06-24 20:10:57 +02:00
Match.MchCod = Print.MchCod;
Mch_GetMatchDataByCod (&Match);
Games->Game.GamCod = Match.GamCod;
Gam_GetGameDataByCod (&Games->Game);
2020-02-18 15:40:04 +01:00
/* Check if I can view this match result and score */
MchRes_CheckIfICanViewMatchResult (&Games->Game,&Match,UsrDat->UsrCod,&ICanView);
2019-09-28 02:31:42 +02:00
2019-11-25 23:18:08 +01:00
if (NumResult)
HTM_TR_Begin (NULL);
2019-09-28 02:31:42 +02:00
2020-06-24 20:10:57 +02:00
/* Write start/end times */
2019-12-15 20:02:34 +01:00
for (StartEndTime = (Dat_StartEndTime_t) 0;
2019-09-28 02:31:42 +02:00
StartEndTime <= (Dat_StartEndTime_t) (Dat_NUM_START_END_TIME - 1);
StartEndTime++)
2019-11-25 23:18:08 +01:00
{
2019-09-28 02:31:42 +02:00
UniqueId++;
if (asprintf (&Id,"mch_res_time_%u_%u",
(unsigned) StartEndTime,UniqueId) < 0)
Err_NotEnoughMemoryExit ();
HTM_TD_Begin ("id=\"%s\" class=\"LT DAT_%s %s\"",
Id,The_GetSuffix (),The_GetColorRows ());
Dat_WriteLocalDateHMSFromUTC (Id,Print.TimeUTC[StartEndTime],
Gbl.Prefs.DateFormat,Dat_SEPARATOR_BREAK,
Dat_WRITE_TODAY |
Dat_WRITE_DATE_ON_SAME_DAY |
Dat_WRITE_HOUR |
Dat_WRITE_MINUTE |
Dat_WRITE_SECOND);
2019-10-23 19:05:05 +02:00
HTM_TD_End ();
2019-11-25 23:18:08 +01:00
free (Id);
}
2019-09-28 02:31:42 +02:00
2019-11-25 23:18:08 +01:00
/* Write match title */
HTM_TD_Begin ("class=\"LT DAT_%s %s\"",
The_GetSuffix (),The_GetColorRows ());
HTM_Txt (Match.Title);
2019-10-23 19:05:05 +02:00
HTM_TD_End ();
2019-09-30 22:31:07 +02:00
2020-06-24 20:10:57 +02:00
/* Accumulate questions and score */
if (ICanView.Score == Usr_CAN)
2019-09-28 02:31:42 +02:00
{
2020-06-24 20:10:57 +02:00
NumTotalQsts.All += Print.NumQsts.All;
NumTotalQsts.NotBlank += Print.NumQsts.NotBlank;
TotalScore += Print.Score;
2019-09-28 02:31:42 +02:00
}
2019-11-25 23:18:08 +01:00
/* Write number of questions */
HTM_TD_Begin ("class=\"RT DAT_%s LINE_LEFT %s\"",
The_GetSuffix (),The_GetColorRows ());
switch (ICanView.Score)
{
case Usr_CAN:
HTM_Unsigned (Print.NumQsts.All);
break;
case Usr_CAN_NOT:
default:
Ico_PutIconNotVisible ();
break;
}
HTM_TD_End ();
2019-09-28 02:31:42 +02:00
2020-06-24 20:10:57 +02:00
/* Write number of non-blank answers */
HTM_TD_Begin ("class=\"RT DAT_%s LINE_LEFT %s\"",
The_GetSuffix (),The_GetColorRows ());
switch (ICanView.Score)
{
case Usr_CAN:
if (Print.NumQsts.NotBlank)
HTM_Unsigned (Print.NumQsts.NotBlank);
else
HTM_Light0 ();
break;
case Usr_CAN_NOT:
default:
Ico_PutIconNotVisible ();
break;
}
2020-06-24 20:10:57 +02:00
HTM_TD_End ();
/* Write number of blank answers */
HTM_TD_Begin ("class=\"RT DAT_%s %s\"",
The_GetSuffix (),The_GetColorRows ());
NumQstsBlank = Print.NumQsts.All - Print.NumQsts.NotBlank;
switch (ICanView.Score)
{
case Usr_CAN:
if (NumQstsBlank)
HTM_Unsigned (NumQstsBlank);
else
HTM_Light0 ();
break;
case Usr_CAN_NOT:
default:
Ico_PutIconNotVisible ();
break;
}
2019-10-23 19:05:05 +02:00
HTM_TD_End ();
2019-09-28 02:31:42 +02:00
/* Write score */
HTM_TD_Begin ("class=\"RT DAT_%s LINE_LEFT %s\"",
The_GetSuffix (),The_GetColorRows ());
switch (ICanView.Score)
{
case Usr_CAN:
HTM_Double2Decimals (Print.Score);
HTM_Txt ("/");
HTM_Unsigned (Print.NumQsts.All);
break;
case Usr_CAN_NOT:
default:
Ico_PutIconNotVisible ();
break;
}
2019-10-23 19:05:05 +02:00
HTM_TD_End ();
2019-09-28 02:31:42 +02:00
2019-11-25 23:18:08 +01:00
/* Write average score per question */
HTM_TD_Begin ("class=\"RT DAT_%s %s\"",
The_GetSuffix (),The_GetColorRows ());
switch (ICanView.Score)
{
case Usr_CAN:
HTM_Double2Decimals (Print.NumQsts.All ? Print.Score /
(double) Print.NumQsts.All :
0.0);
break;
case Usr_CAN_NOT:
default:
Ico_PutIconNotVisible ();
break;
}
2019-10-23 19:05:05 +02:00
HTM_TD_End ();
2019-09-28 02:31:42 +02:00
2019-11-28 00:19:42 +01:00
/* Write grade over maximum grade */
HTM_TD_Begin ("class=\"RT DAT_%s LINE_LEFT %s\"",
The_GetSuffix (),The_GetColorRows ());
switch (ICanView.Score)
{
case Usr_CAN:
Grade = TstPrn_ComputeGrade (Print.NumQsts.All,Print.Score,
Games->Game.MaxGrade);
TstPrn_ShowGrade (Grade,Games->Game.MaxGrade);
TotalGrade += Grade;
break;
case Usr_CAN_NOT:
default:
Ico_PutIconNotVisible ();
break;
}
2019-10-23 19:05:05 +02:00
HTM_TD_End ();
2019-09-28 02:31:42 +02:00
/* Link to show this result */
HTM_TD_Begin ("class=\"RT LINE_LEFT %s\"",
The_GetColorRows ());
switch (ICanView.Result)
2019-09-28 02:31:42 +02:00
{
case Usr_CAN:
Games->Game.GamCod = Match.GamCod;
Games->MchCod = Match.MchCod;
switch (MeOrOther)
{
case Usr_ME:
Frm_BeginForm (ActSeeOneMchResMe);
Mch_PutParsEdit (Games);
Ico_PutIconLink ("tasks.svg",Ico_BLACK,ActSeeOneMchResMe);
break;
case Usr_OTHER:
Frm_BeginForm (ActSeeOneMchResOth);
Mch_PutParsEdit (Games);
Usr_PutParOtherUsrCodEncrypted (Gbl.Usrs.Other.UsrDat.EnUsrCod);
Ico_PutIconLink ("tasks.svg",Ico_BLACK,ActSeeOneMchResOth);
break;
}
Frm_EndForm ();
break;
case Usr_CAN_NOT:
default:
Ico_PutIconNotVisible ();
break;
2019-09-28 02:31:42 +02:00
}
2019-10-23 19:05:05 +02:00
HTM_TD_End ();
2019-09-28 02:31:42 +02:00
2019-11-25 23:18:08 +01:00
HTM_TR_End ();
}
2019-09-28 02:31:42 +02:00
/***** Write totals for this user *****/
2020-04-02 03:28:08 +02:00
MchRes_ShowMchResultsSummaryRow (NumResults,
2020-06-24 20:10:57 +02:00
&NumTotalQsts,
TotalScore,
2020-06-18 20:06:17 +02:00
TotalGrade);
2019-09-28 02:31:42 +02:00
}
else // No results
2019-09-28 02:31:42 +02:00
{
2020-06-24 20:10:57 +02:00
/* Columns for dates and match */
HTM_TD_Begin ("colspan=\"3\" class=\"LINE_BOTTOM %s\"",
The_GetColorRows ());
2020-06-24 20:10:57 +02:00
HTM_TD_End ();
/* Column for questions */
HTM_TD_Begin ("class=\"LINE_BOTTOM LINE_LEFT %s\"",
The_GetColorRows ());
2020-06-24 20:10:57 +02:00
HTM_TD_End ();
/* Columns for answers */
HTM_TD_Begin ("colspan=\"2\" class=\"LINE_BOTTOM LINE_LEFT %s\"",
The_GetColorRows ());
2020-06-24 20:10:57 +02:00
HTM_TD_End ();
/* Columns for score */
HTM_TD_Begin ("colspan=\"2\" class=\"LINE_BOTTOM LINE_LEFT %s\"",
The_GetColorRows ());
2020-06-24 20:10:57 +02:00
HTM_TD_End ();
/* Column for grade */
HTM_TD_Begin ("class=\"LINE_BOTTOM LINE_LEFT %s\"",
The_GetColorRows ());
2020-06-24 20:10:57 +02:00
HTM_TD_End ();
/* Column for link to show the result */
HTM_TD_Begin ("class=\"LINE_BOTTOM LINE_LEFT %s\"",
The_GetColorRows ());
2020-06-24 20:10:57 +02:00
HTM_TD_End ();
2019-10-23 19:05:05 +02:00
HTM_TR_End ();
2019-09-28 02:31:42 +02:00
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
The_ChangeRowColor ();
2019-09-28 02:31:42 +02:00
}
/*****************************************************************************/
/************** Show row with summary of user's matches results **************/
/*****************************************************************************/
2020-04-02 03:28:08 +02:00
static void MchRes_ShowMchResultsSummaryRow (unsigned NumResults,
2020-06-24 20:10:57 +02:00
struct MchPrn_NumQuestions *NumTotalQsts,
double TotalScore,
2020-04-08 03:06:45 +02:00
double TotalGrade)
2019-09-28 02:31:42 +02:00
{
extern const char *Txt_Matches;
/***** Begin row *****/
2019-10-23 19:05:05 +02:00
HTM_TR_Begin (NULL);
2019-09-28 02:31:42 +02:00
/***** Row title *****/
HTM_TD_Begin ("colspan=\"3\" class=\"RM DAT_STRONG_%s LINE_TOP LINE_BOTTOM %s\"",
The_GetSuffix (),
The_GetColorRows ());
HTM_TxtColonNBSP (Txt_Matches);
HTM_Unsigned (NumResults);
HTM_TD_End ();
2019-09-28 02:31:42 +02:00
/***** Write total number of questions *****/
HTM_TD_Begin ("class=\"RM DAT_STRONG_%s LINE_TOP LINE_BOTTOM LINE_LEFT %s\"",
The_GetSuffix (),
The_GetColorRows ());
if (NumResults)
HTM_Unsigned (NumTotalQsts->All);
HTM_TD_End ();
2019-09-28 02:31:42 +02:00
/***** Write total number of non-blank answers *****/
HTM_TD_Begin ("class=\"RM DAT_STRONG_%s LINE_TOP LINE_BOTTOM LINE_LEFT %s\"",
The_GetSuffix (),
The_GetColorRows ());
if (NumResults)
HTM_Unsigned (NumTotalQsts->NotBlank);
HTM_TD_End ();
2020-06-24 20:10:57 +02:00
/***** Write total number of blank answers *****/
HTM_TD_Begin ("class=\"RM DAT_STRONG_%s LINE_TOP LINE_BOTTOM %s\"",
The_GetSuffix (),
The_GetColorRows ());
if (NumResults)
HTM_Unsigned (NumTotalQsts->All - NumTotalQsts->NotBlank);
HTM_TD_End ();
2019-09-28 02:31:42 +02:00
/***** Write total score *****/
HTM_TD_Begin ("class=\"RM DAT_STRONG_%s LINE_TOP LINE_BOTTOM LINE_LEFT %s\"",
The_GetSuffix (),
The_GetColorRows ());
HTM_Double2Decimals (TotalScore);
HTM_Txt ("/");
HTM_Unsigned (NumTotalQsts->All);
HTM_TD_End ();
2019-09-28 02:31:42 +02:00
/***** Write average score per question *****/
HTM_TD_Begin ("class=\"RM DAT_STRONG_%s LINE_TOP LINE_BOTTOM %s\"",
The_GetSuffix (),
The_GetColorRows ());
HTM_Double2Decimals (NumTotalQsts->All ? TotalScore /
(double) NumTotalQsts->All :
0.0);
HTM_TD_End ();
2019-09-28 02:31:42 +02:00
/***** Write total grade *****/
HTM_TD_Begin ("class=\"RM DAT_STRONG_%s LINE_TOP LINE_BOTTOM LINE_LEFT %s\"",
The_GetSuffix (),
The_GetColorRows ());
HTM_Double2Decimals (TotalGrade);
HTM_TD_End ();
2019-09-28 02:31:42 +02:00
/***** Last cell *****/
HTM_TD_Begin ("class=\"DAT_STRONG_%s LINE_TOP LINE_BOTTOM LINE_LEFT %s\"",
The_GetSuffix (),
The_GetColorRows ());
HTM_TD_End ();
2019-09-28 02:31:42 +02:00
/***** End row *****/
2019-10-23 19:05:05 +02:00
HTM_TR_End ();
2019-09-28 02:31:42 +02:00
}
/*****************************************************************************/
/******************* Show one match result of another user *******************/
/*****************************************************************************/
2020-04-02 03:28:08 +02:00
void MchRes_ShowOneMchResult (void)
2019-09-28 02:31:42 +02:00
{
extern const char *Hlp_ASSESSMENT_Games_results;
extern const char *Txt_ROLES_SINGUL_Abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
extern const char *Txt_START_END_TIME[Dat_NUM_START_END_TIME];
extern const char *Txt_Questions;
2020-06-22 19:27:23 +02:00
extern const char *Txt_Answers;
2019-09-28 02:31:42 +02:00
extern const char *Txt_Score;
2019-11-28 09:45:32 +01:00
extern const char *Txt_Grade;
2019-09-28 02:31:42 +02:00
extern const char *Txt_Tags;
static const char *ClassPhoto[PhoSha_NUM_SHAPES] =
{
[PhoSha_SHAPE_CIRCLE ] = "PHOTOC45x60",
[PhoSha_SHAPE_ELLIPSE ] = "PHOTOE45x60",
[PhoSha_SHAPE_OVAL ] = "PHOTOO45x60",
[PhoSha_SHAPE_RECTANGLE] = "PHOTOR45x60",
};
2020-04-08 03:06:45 +02:00
struct Gam_Games Games;
struct Mch_Match Match;
2019-09-28 02:31:42 +02:00
Usr_MeOrOther_t MeOrOther;
struct Usr_Data *UsrDat;
2019-09-28 02:31:42 +02:00
Dat_StartEndTime_t StartEndTime;
2019-11-01 22:53:39 +01:00
char *Id;
2020-06-24 20:10:57 +02:00
struct MchPrn_Print Print;
2020-06-23 11:48:06 +02:00
struct MchRes_ICanView ICanView;
2019-09-28 02:31:42 +02:00
2020-04-23 23:09:28 +02:00
/***** Reset games context *****/
2020-04-08 03:06:45 +02:00
Gam_ResetGames (&Games);
Gam_ResetGame (&Games.Game);
2020-04-23 23:09:28 +02:00
Mch_ResetMatch (&Match);
2019-09-29 22:38:32 +02:00
/***** Get and check parameters *****/
Mch_GetAndCheckPars (&Games,&Match);
2019-09-28 02:31:42 +02:00
/***** Pointer to user's data *****/
MeOrOther = (Gbl.Action.Act == ActSeeOneMchResMe) ? Usr_ME :
Usr_OTHER;
switch (MeOrOther)
{
case Usr_ME:
UsrDat = &Gbl.Usrs.Me.UsrDat;
break;
case Usr_OTHER:
UsrDat = &Gbl.Usrs.Other.UsrDat;
Usr_GetParOtherUsrCodEncrypted (UsrDat);
2019-09-28 02:31:42 +02:00
break;
}
/***** Get match result data *****/
2020-06-24 20:10:57 +02:00
Print.MchCod = Match.MchCod;
Print.UsrCod = UsrDat->UsrCod;
2020-06-24 20:47:54 +02:00
MchPrn_GetMatchPrintDataByMchCodAndUsrCod (&Print);
2019-09-28 02:31:42 +02:00
2020-06-23 11:48:06 +02:00
/***** Check if I can view this match result and score *****/
MchRes_CheckIfICanViewMatchResult (&Games.Game,&Match,UsrDat->UsrCod,&ICanView);
if (ICanView.Result == Usr_CAN_NOT)
Err_NoPermissionExit ();
2020-05-22 20:10:45 +02:00
/***** Get questions and user's answers of the match result from database *****/
Mch_GetMatchQuestionsFromDB (&Print);
/***** Begin box *****/
Box_BoxBegin (Match.Title,NULL,NULL,
Hlp_ASSESSMENT_Games_results,Box_NOT_CLOSABLE);
Lay_WriteHeaderClassPhoto (Vie_VIEW);
/***** Begin table *****/
HTM_TABLE_BeginWideMarginPadding (10);
/***** User *****/
/* Get data of the user who answer the match */
if (!Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (UsrDat,
Usr_DONT_GET_PREFS,
Usr_GET_ROLE_IN_CRS))
Err_WrongUserExit ();
if (Usr_CheckIfICanViewTstExaMchResult (UsrDat) == Usr_CAN_NOT)
Err_NoPermissionExit ();
/* Get if user has accepted enrolment */
UsrDat->Accepted = Enr_CheckIfUsrHasAcceptedInCurrentCrs (UsrDat);
/* User */
HTM_TR_Begin (NULL);
HTM_TD_Begin ("class=\"RT DAT_STRONG_%s\"",
The_GetSuffix ());
HTM_TxtColon (Txt_ROLES_SINGUL_Abc[UsrDat->Roles.InCurrentCrs][UsrDat->Sex]);
HTM_TD_End ();
HTM_TD_Begin ("class=\"LB DAT_%s\"",
The_GetSuffix ());
ID_WriteUsrIDs (UsrDat,NULL);
HTM_SPTxt (UsrDat->Surname1);
if (UsrDat->Surname2[0])
HTM_SPTxt (UsrDat->Surname2);
if (UsrDat->FrstName[0])
{
HTM_Comma ();
HTM_SPTxt (UsrDat->FrstName);
}
HTM_BR ();
Pho_ShowUsrPhotoIfAllowed (UsrDat,
ClassPhoto[Gbl.Prefs.PhotoShape],Pho_ZOOM);
HTM_TD_End ();
HTM_TR_End ();
/***** Start/end time (for user in this match) *****/
for (StartEndTime = (Dat_StartEndTime_t) 0;
StartEndTime <= (Dat_StartEndTime_t) (Dat_NUM_START_END_TIME - 1);
StartEndTime++)
{
HTM_TR_Begin (NULL);
2019-09-28 02:31:42 +02:00
HTM_TD_Begin ("class=\"RT DAT_STRONG_%s\"",
The_GetSuffix ());
HTM_TxtColon (Txt_START_END_TIME[StartEndTime]);
HTM_TD_End ();
if (asprintf (&Id,"match_%u",(unsigned) StartEndTime) < 0)
Err_NotEnoughMemoryExit ();
HTM_TD_Begin ("id=\"%s\" class=\"LT DAT_%s\"",
Id,The_GetSuffix ());
Dat_WriteLocalDateHMSFromUTC (Id,Print.TimeUTC[StartEndTime],
Gbl.Prefs.DateFormat,Dat_SEPARATOR_COMMA,
Dat_WRITE_TODAY |
Dat_WRITE_DATE_ON_SAME_DAY |
Dat_WRITE_WEEK_DAY |
Dat_WRITE_HOUR |
Dat_WRITE_MINUTE |
Dat_WRITE_SECOND);
HTM_TD_End ();
free (Id);
HTM_TR_End ();
}
/***** Number of questions *****/
HTM_TR_Begin (NULL);
2019-10-07 17:36:41 +02:00
HTM_TD_Begin ("class=\"RT DAT_STRONG_%s\"",
The_GetSuffix ());
HTM_TxtColon (Txt_Questions);
HTM_TD_End ();
2020-06-22 19:27:23 +02:00
HTM_TD_Begin ("class=\"LB DAT_%s\"",
The_GetSuffix ());
HTM_Unsigned (Print.NumQsts.All);
HTM_TD_End ();
2020-06-22 19:27:23 +02:00
HTM_TR_End ();
2020-06-22 19:27:23 +02:00
/***** Number of answers *****/
HTM_TR_Begin (NULL);
2020-06-22 19:27:23 +02:00
HTM_TD_Begin ("class=\"RT DAT_STRONG_%s\"",
The_GetSuffix ());
HTM_TxtColon (Txt_Answers);
HTM_TD_End ();
2019-10-07 17:36:41 +02:00
HTM_TD_Begin ("class=\"LB DAT_%s\"",
The_GetSuffix ());
HTM_Unsigned (Print.NumQsts.NotBlank);
HTM_TD_End ();
2019-09-28 02:31:42 +02:00
HTM_TR_End ();
2019-10-07 17:36:41 +02:00
/***** Score *****/
HTM_TR_Begin (NULL);
2019-11-28 09:45:32 +01:00
HTM_TD_Begin ("class=\"RT DAT_STRONG_%s\"",
The_GetSuffix ());
HTM_TxtColon (Txt_Score);
HTM_TD_End ();
HTM_TD_Begin ("class=\"LB DAT_%s\"",
The_GetSuffix ());
switch (ICanView.Score)
{
case Usr_CAN:
HTM_STRONG_Begin ();
HTM_Double2Decimals (Print.Score);
HTM_Txt ("/");
HTM_Unsigned (Print.NumQsts.All);
HTM_STRONG_End ();
break;
case Usr_CAN_NOT:
default:
Ico_PutIconNotVisible ();
break;
}
HTM_TD_End ();
HTM_TR_End ();
/***** Grade *****/
HTM_TR_Begin (NULL);
2019-11-28 09:45:32 +01:00
HTM_TD_Begin ("class=\"RT DAT_STRONG_%s\"",
The_GetSuffix ());
HTM_TxtColon (Txt_Grade);
HTM_TD_End ();
2019-11-28 09:45:32 +01:00
HTM_TD_Begin ("class=\"LB DAT_%s\"",
The_GetSuffix ());
switch (ICanView.Score)
{
case Usr_CAN:
HTM_STRONG_Begin ();
TstPrn_ComputeAndShowGrade (Print.NumQsts.All,Print.Score,
Games.Game.MaxGrade);
HTM_STRONG_End ();
break;
case Usr_CAN_NOT:
default:
Ico_PutIconNotVisible ();
break;
}
HTM_TD_End ();
2019-10-07 17:36:41 +02:00
HTM_TR_End ();
2019-09-28 02:31:42 +02:00
/***** Tags present in this result *****/
HTM_TR_Begin (NULL);
2019-10-07 17:36:41 +02:00
HTM_TD_Begin ("class=\"RT DAT_STRONG_%s\"",
The_GetSuffix ());
HTM_TxtColon (Txt_Tags);
HTM_TD_End ();
2019-10-07 17:36:41 +02:00
HTM_TD_Begin ("class=\"LB DAT_%s\"",
The_GetSuffix ());
Gam_ShowTstTagsPresentInAGame (Match.GamCod);
HTM_TD_End ();
2019-10-07 17:36:41 +02:00
HTM_TR_End ();
2019-09-28 02:31:42 +02:00
/***** Write answers and solutions *****/
TstPrn_ShowPrintAnswers (UsrDat,
Print.NumQsts.All,
Print.PrintedQuestions,
Print.TimeUTC,
Games.Game.Visibility);
2019-09-28 02:31:42 +02:00
/***** End table *****/
HTM_TABLE_End ();
2019-09-28 02:31:42 +02:00
/***** End box *****/
Box_BoxEnd ();
2019-09-28 02:31:42 +02:00
}
/*****************************************************************************/
/********************** Get if I can view match result ***********************/
2019-09-28 02:31:42 +02:00
/*****************************************************************************/
static void MchRes_CheckIfICanViewMatchResult (const struct Gam_Game *Game,
const struct Mch_Match *Match,
long UsrCod,
struct MchRes_ICanView *ICanView)
2019-09-28 02:31:42 +02:00
{
2020-06-23 11:48:06 +02:00
/***** Check if I can view print result and score *****/
2019-09-28 02:31:42 +02:00
switch (Gbl.Usrs.Me.Role.Logged)
{
case Rol_STD:
2020-06-23 11:48:06 +02:00
// Depends on visibility of game and result (eye icons)
ICanView->Result = (Game->HiddenOrVisible == HidVis_VISIBLE && // The game is visible
Match->Status.ShowUsrResults && // The results of the match are visible to users
Usr_ItsMe (UsrCod) == Usr_ME) ? Usr_CAN : // The result is mine
Usr_CAN_NOT;
2020-06-19 13:37:45 +02:00
// Whether I belong or not to groups of match is not checked here...
// ...because I should be able to see old matches made in old groups to which I belonged
2019-09-28 02:31:42 +02:00
switch (ICanView->Result)
{
case Usr_CAN:
// Depends on 5 visibility icons associated to game
ICanView->Score = TstVis_IsVisibleTotalScore (Game->Visibility) ? Usr_CAN :
Usr_CAN_NOT;
break;
case Usr_CAN_NOT:
default:
ICanView->Score = Usr_CAN_NOT;
break;
}
2020-02-18 15:40:04 +01:00
break;
case Rol_NET:
case Rol_TCH:
case Rol_DEG_ADM:
case Rol_CTR_ADM:
case Rol_INS_ADM:
case Rol_SYS_ADM:
2020-06-23 11:48:06 +02:00
ICanView->Result =
ICanView->Score = Usr_CAN;
2020-06-23 11:48:06 +02:00
break;
2020-02-18 15:40:04 +01:00
default:
2020-06-23 11:48:06 +02:00
ICanView->Result =
ICanView->Score = Usr_CAN_NOT;
2020-06-23 11:48:06 +02:00
break;
2019-09-28 02:31:42 +02:00
}
}