mirror of https://github.com/acanas/swad-core.git
Version19.254.1
This commit is contained in:
parent
e6c064c90f
commit
b797c3ff17
|
@ -556,7 +556,7 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - *
|
|||
En OpenSWAD:
|
||||
ps2pdf source.ps destination.pdf
|
||||
*/
|
||||
#define Log_PLATFORM_VERSION "SWAD 19.254 (2020-06-22)"
|
||||
#define Log_PLATFORM_VERSION "SWAD 19.254.1 (2020-06-23)"
|
||||
#define CSS_FILE "swad19.253.css"
|
||||
#define JS_FILE "swad19.254.js"
|
||||
/*
|
||||
|
@ -566,9 +566,9 @@ TODO: Fix bug: Un estudiante recibe una notificaci
|
|||
TODO: Fix bug: Cuando se pulsa en ver fichas, y luego en una ficha en "Ver trabajos" o "Ver exámenes", o lo que sea, sale dos veces ese estudiante.
|
||||
TODO: No limitar el número de preguntas en un examen a ExaPrn_MAX_QUESTIONS_PER_EXAM_PRINT, sino asignar PrintedQuestions dinámicamente con malloc
|
||||
TODO: Que al generar un examen sólo se cojan preguntas válidas. Y si ya está generado, al entrar de nuevo, que se vean en rojo.
|
||||
TODO: Refactorizar MchRes_CheckIfICanSeeMatchResult y MchRes_CheckIfICanViewScore uniéndolas en una función como ExaRes_CheckIfICanSeePrintResult
|
||||
Y dentro de las funciones TstPrn_ShowUsrPrints y TstPrn_ShowOnePrint crear y llamar a una función común similar a ExaRes_CheckIfICanSeePrintResult
|
||||
TODO: Dentro de las funciones TstPrn_ShowUsrPrints y TstPrn_ShowOnePrint crear y llamar a una función común similar a ExaRes_CheckIfICanSeePrintResult
|
||||
|
||||
Version 19.254.1: Jun 23, 2020 Code refactoring in matches results. (303646 lines)
|
||||
Version 19.254: Jun 22, 2020 Fixed bug in Javascript related to quotes. Reported by Laura García Rejón. (303653 lines)
|
||||
Version 19.253: Jun 22, 2020 More details in listing of exams. (303643 lines)
|
||||
Version 19.252.1: Jun 19, 2020 Changes in listing of exams and matches results. (303245 lines)
|
||||
|
|
|
@ -1643,7 +1643,7 @@ static void ExaRes_CheckIfICanSeePrintResult (const struct Exa_Exam *Exam,
|
|||
{
|
||||
bool ItsMe;
|
||||
|
||||
/***** Check if I can view this print result *****/
|
||||
/***** Check if I can view print result and score *****/
|
||||
switch (Gbl.Usrs.Me.Role.Logged)
|
||||
{
|
||||
case Rol_STD:
|
||||
|
|
|
@ -925,6 +925,13 @@ void Gam_GetListSelectedGamCods (struct Gam_Games *Games)
|
|||
long GamCod;
|
||||
char LongStr[Cns_MAX_DECIMAL_DIGITS_LONG + 1];
|
||||
|
||||
/***** Default selected *****/
|
||||
Games->NumSelected = 0;
|
||||
|
||||
/***** Trivial check: there are games visibles by me *****/
|
||||
if (!Games->Num)
|
||||
return;
|
||||
|
||||
/***** Allocate memory for list of games selected *****/
|
||||
MaxSizeListGamCodsSelected = Games->Num * (Cns_MAX_DECIMAL_DIGITS_LONG + 1);
|
||||
if ((Games->GamCodsSelected = (char *) malloc (MaxSizeListGamCodsSelected + 1)) == NULL)
|
||||
|
@ -941,7 +948,6 @@ void Gam_GetListSelectedGamCods (struct Gam_Games *Games)
|
|||
NumGame < Games->Num;
|
||||
NumGame++)
|
||||
Games->Lst[NumGame].Selected = false;
|
||||
Games->NumSelected = 0;
|
||||
|
||||
/* Set some games as selected */
|
||||
for (Ptr = Games->GamCodsSelected;
|
||||
|
|
|
@ -59,6 +59,12 @@ extern struct Globals Gbl;
|
|||
/******************************* Private types *******************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
struct MchRes_ICanView
|
||||
{
|
||||
bool Result;
|
||||
bool Score;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Private constants *****************************/
|
||||
/*****************************************************************************/
|
||||
|
@ -105,8 +111,10 @@ static void MchRes_ShowMchResultsSummaryRow (unsigned NumResults,
|
|||
static void MchRes_GetMatchResultDataByMchCod (long MchCod,long UsrCod,
|
||||
struct TstPrn_Print *Print);
|
||||
|
||||
static bool MchRes_CheckIfICanSeeMatchResult (struct Mch_Match *Match,long UsrCod);
|
||||
static bool MchRes_CheckIfICanViewScore (bool ICanViewResult,unsigned Visibility);
|
||||
static void MchRes_CheckIfICanSeeMatchResult (const struct Gam_Game *Game,
|
||||
const struct Mch_Match *Match,
|
||||
long UsrCod,
|
||||
struct MchRes_ICanView *ICanView);
|
||||
|
||||
/*****************************************************************************/
|
||||
/*********** Compute score and create/update my result in a match ************/
|
||||
|
@ -799,16 +807,17 @@ static void MchRes_ShowMchResults (struct Gam_Games *Games,
|
|||
extern const char *Txt_Result;
|
||||
char *MchSubQuery;
|
||||
char *GamSubQuery;
|
||||
char *HidGamSubQuery;
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
struct UsrData *UsrDat;
|
||||
bool ICanViewResult;
|
||||
bool ICanViewScore;
|
||||
struct MchRes_ICanView ICanView;
|
||||
unsigned NumResults;
|
||||
unsigned NumResult;
|
||||
static unsigned UniqueId = 0;
|
||||
char *Id;
|
||||
struct Mch_Match Match;
|
||||
struct Gam_Game Game;
|
||||
Dat_StartEndTime_t StartEndTime;
|
||||
unsigned NumQstsInThisResult;
|
||||
unsigned NumQstsNotBlankInThisResult;
|
||||
|
@ -816,10 +825,8 @@ static void MchRes_ShowMchResults (struct Gam_Games *Games,
|
|||
unsigned NumTotalQstsNotBlank = 0;
|
||||
double ScoreInThisResult;
|
||||
double TotalScoreOfAllResults = 0.0;
|
||||
double MaxGrade;
|
||||
double Grade;
|
||||
double TotalGrade = 0.0;
|
||||
unsigned Visibility;
|
||||
time_t TimeUTC[Dat_NUM_START_END_TIME];
|
||||
|
||||
/***** Reset match *****/
|
||||
|
@ -867,6 +874,22 @@ static void MchRes_ShowMchResults (struct Gam_Games *Games,
|
|||
Lay_NotEnoughMemoryExit ();
|
||||
}
|
||||
|
||||
/***** Subquery: get hidden games?
|
||||
· A student will not be able to see their results in hidden games
|
||||
· A teacher will be able to see results from other users even in hidden games
|
||||
*****/
|
||||
switch (MeOrOther)
|
||||
{
|
||||
case Usr_ME: // A student watching her/his results
|
||||
if (asprintf (&HidGamSubQuery," AND gam_games.Hidden='N'") < 0)
|
||||
Lay_NotEnoughMemoryExit ();
|
||||
break;
|
||||
default: // A teacher/admin watching the results of other users
|
||||
if (asprintf (&HidGamSubQuery,"%s","") < 0)
|
||||
Lay_NotEnoughMemoryExit ();
|
||||
break;
|
||||
}
|
||||
|
||||
/***** Make database query *****/
|
||||
NumResults =
|
||||
(unsigned) DB_QuerySELECT (&mysql_res,"can not get matches results",
|
||||
|
@ -875,21 +898,22 @@ static void MchRes_ShowMchResults (struct Gam_Games *Games,
|
|||
"UNIX_TIMESTAMP(mch_results.EndTime)," // row[2]
|
||||
"mch_results.NumQsts," // row[3]
|
||||
"mch_results.NumQstsNotBlank," // row[4]
|
||||
"mch_results.Score," // row[5]
|
||||
"gam_games.MaxGrade," // row[6]
|
||||
"gam_games.Visibility" // row[7]
|
||||
"mch_results.Score" // row[5]
|
||||
" FROM mch_results,mch_matches,gam_games"
|
||||
" WHERE mch_results.UsrCod=%ld"
|
||||
"%s" // Match subquery
|
||||
" AND mch_results.MchCod=mch_matches.MchCod"
|
||||
"%s" // Games subquery
|
||||
" AND mch_matches.GamCod=gam_games.GamCod"
|
||||
"%s" // Hidden games subquery
|
||||
" AND gam_games.CrsCod=%ld" // Extra check
|
||||
" ORDER BY mch_matches.Title",
|
||||
UsrDat->UsrCod,
|
||||
MchSubQuery,
|
||||
GamSubQuery,
|
||||
HidGamSubQuery,
|
||||
Gbl.Hierarchy.Crs.CrsCod);
|
||||
free (HidGamSubQuery);
|
||||
free (GamSubQuery);
|
||||
free (MchSubQuery);
|
||||
|
||||
|
@ -911,12 +935,13 @@ static void MchRes_ShowMchResults (struct Gam_Games *Games,
|
|||
Lay_ShowErrorAndExit ("Wrong code of match.");
|
||||
Mch_GetDataOfMatchByCod (&Match);
|
||||
|
||||
/* Get visibility (row[7]) */
|
||||
Visibility = TstVis_GetVisibilityFromStr (row[7]);
|
||||
/* Get data of match and game */
|
||||
Mch_GetDataOfMatchByCod (&Match);
|
||||
Game.GamCod = Match.GamCod;
|
||||
Gam_GetDataOfGameByCod (&Game);
|
||||
|
||||
/* Show match result? */
|
||||
ICanViewResult = MchRes_CheckIfICanSeeMatchResult (&Match,UsrDat->UsrCod);
|
||||
ICanViewScore = MchRes_CheckIfICanViewScore (ICanViewResult,Visibility);
|
||||
/* Check if I can view this match result and score */
|
||||
MchRes_CheckIfICanSeeMatchResult (&Game,&Match,UsrDat->UsrCod,&ICanView);
|
||||
|
||||
if (NumResult)
|
||||
HTM_TR_Begin (NULL);
|
||||
|
@ -944,7 +969,7 @@ static void MchRes_ShowMchResults (struct Gam_Games *Games,
|
|||
HTM_Txt (Match.Title);
|
||||
HTM_TD_End ();
|
||||
|
||||
if (ICanViewScore)
|
||||
if (ICanView.Score)
|
||||
{
|
||||
/* Get number of questions (row[3]) */
|
||||
if (sscanf (row[3],"%u",&NumQstsInThisResult) != 1)
|
||||
|
@ -963,16 +988,12 @@ static void MchRes_ShowMchResults (struct Gam_Games *Games,
|
|||
ScoreInThisResult = 0.0;
|
||||
TotalScoreOfAllResults += ScoreInThisResult;
|
||||
|
||||
/* Get maximum grade (row[6]) */
|
||||
if (sscanf (row[6],"%lf",&MaxGrade) != 1)
|
||||
MaxGrade = 0.0;
|
||||
|
||||
Str_SetDecimalPointToLocal (); // Return to local system
|
||||
}
|
||||
|
||||
/* Write number of questions */
|
||||
HTM_TD_Begin ("class=\"DAT RT COLOR%u\"",Gbl.RowEvenOdd);
|
||||
if (ICanViewScore)
|
||||
if (ICanView.Score)
|
||||
HTM_Unsigned (NumQstsInThisResult);
|
||||
else
|
||||
Ico_PutIconNotVisible ();
|
||||
|
@ -980,7 +1001,7 @@ static void MchRes_ShowMchResults (struct Gam_Games *Games,
|
|||
|
||||
/* Write number of questions not blank */
|
||||
HTM_TD_Begin ("class=\"DAT RT COLOR%u\"",Gbl.RowEvenOdd);
|
||||
if (ICanViewScore)
|
||||
if (ICanView.Score)
|
||||
HTM_Unsigned (NumQstsNotBlankInThisResult);
|
||||
else
|
||||
Ico_PutIconNotVisible ();
|
||||
|
@ -988,7 +1009,7 @@ static void MchRes_ShowMchResults (struct Gam_Games *Games,
|
|||
|
||||
/* Write score */
|
||||
HTM_TD_Begin ("class=\"DAT RT COLOR%u\"",Gbl.RowEvenOdd);
|
||||
if (ICanViewScore)
|
||||
if (ICanView.Score)
|
||||
{
|
||||
HTM_Double2Decimals (ScoreInThisResult);
|
||||
HTM_Txt ("/");
|
||||
|
@ -1000,7 +1021,7 @@ static void MchRes_ShowMchResults (struct Gam_Games *Games,
|
|||
|
||||
/* Write average score per question */
|
||||
HTM_TD_Begin ("class=\"DAT RT COLOR%u\"",Gbl.RowEvenOdd);
|
||||
if (ICanViewScore)
|
||||
if (ICanView.Score)
|
||||
HTM_Double2Decimals (NumQstsInThisResult ? ScoreInThisResult /
|
||||
(double) NumQstsInThisResult :
|
||||
0.0);
|
||||
|
@ -1010,10 +1031,10 @@ static void MchRes_ShowMchResults (struct Gam_Games *Games,
|
|||
|
||||
/* Write grade over maximum grade */
|
||||
HTM_TD_Begin ("class=\"DAT RT COLOR%u\"",Gbl.RowEvenOdd);
|
||||
if (ICanViewScore)
|
||||
if (ICanView.Score)
|
||||
{
|
||||
Grade = TstPrn_ComputeGrade (NumQstsInThisResult,ScoreInThisResult,MaxGrade);
|
||||
TstPrn_ShowGrade (Grade,MaxGrade);
|
||||
Grade = TstPrn_ComputeGrade (NumQstsInThisResult,ScoreInThisResult,Game.MaxGrade);
|
||||
TstPrn_ShowGrade (Grade,Game.MaxGrade);
|
||||
TotalGrade += Grade;
|
||||
}
|
||||
else
|
||||
|
@ -1022,7 +1043,7 @@ static void MchRes_ShowMchResults (struct Gam_Games *Games,
|
|||
|
||||
/* Link to show this result */
|
||||
HTM_TD_Begin ("class=\"RT COLOR%u\"",Gbl.RowEvenOdd);
|
||||
if (ICanViewResult)
|
||||
if (ICanView.Result)
|
||||
{
|
||||
Games->GamCod = Match.GamCod;
|
||||
Games->MchCod = Match.MchCod;
|
||||
|
@ -1151,8 +1172,7 @@ void MchRes_ShowOneMchResult (void)
|
|||
struct TstPrn_Print Print;
|
||||
bool ShowPhoto;
|
||||
char PhotoURL[PATH_MAX + 1];
|
||||
bool ICanViewResult;
|
||||
bool ICanViewScore;
|
||||
struct MchRes_ICanView ICanView;
|
||||
|
||||
/***** Reset games context *****/
|
||||
Gam_ResetGames (&Games);
|
||||
|
@ -1183,35 +1203,10 @@ void MchRes_ShowOneMchResult (void)
|
|||
TstPrn_ResetPrint (&Print);
|
||||
MchRes_GetMatchResultDataByMchCod (Match.MchCod,UsrDat->UsrCod,&Print);
|
||||
|
||||
/***** Check if I can view this match result *****/
|
||||
switch (Gbl.Usrs.Me.Role.Logged)
|
||||
{
|
||||
case Rol_STD:
|
||||
// Depends on visibility of result for this match (eye icon)
|
||||
ICanViewResult = MchRes_CheckIfICanSeeMatchResult (&Match,UsrDat->UsrCod);
|
||||
/***** Check if I can view this match result and score *****/
|
||||
MchRes_CheckIfICanSeeMatchResult (&Game,&Match,UsrDat->UsrCod,&ICanView);
|
||||
|
||||
if (ICanViewResult)
|
||||
// Depends on 5 visibility icons
|
||||
ICanViewScore = TstVis_IsVisibleTotalScore (Game.Visibility);
|
||||
else
|
||||
ICanViewScore = false;
|
||||
break;
|
||||
case Rol_NET:
|
||||
case Rol_TCH:
|
||||
case Rol_DEG_ADM:
|
||||
case Rol_CTR_ADM:
|
||||
case Rol_INS_ADM:
|
||||
case Rol_SYS_ADM:
|
||||
ICanViewResult =
|
||||
ICanViewScore = true;
|
||||
break;
|
||||
default:
|
||||
ICanViewResult =
|
||||
ICanViewScore = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ICanViewResult) // I am allowed to view this match result
|
||||
if (ICanView.Result) // I am allowed to view this match result
|
||||
{
|
||||
/***** Get questions and user's answers of the match result from database *****/
|
||||
Mch_GetMatchQuestionsFromDB (Match.MchCod,UsrDat->UsrCod,&Print);
|
||||
|
@ -1315,7 +1310,7 @@ void MchRes_ShowOneMchResult (void)
|
|||
HTM_TD_End ();
|
||||
|
||||
HTM_TD_Begin ("class=\"DAT LB\"");
|
||||
if (ICanViewScore)
|
||||
if (ICanView.Score)
|
||||
{
|
||||
HTM_STRONG_Begin ();
|
||||
HTM_Double2Decimals (Print.Score);
|
||||
|
@ -1337,7 +1332,7 @@ void MchRes_ShowOneMchResult (void)
|
|||
HTM_TD_End ();
|
||||
|
||||
HTM_TD_Begin ("class=\"DAT LB\"");
|
||||
if (ICanViewScore)
|
||||
if (ICanView.Score)
|
||||
{
|
||||
HTM_STRONG_Begin ();
|
||||
TstPrn_ComputeAndShowGrade (Print.NumQsts,Print.Score,Game.MaxGrade);
|
||||
|
@ -1440,41 +1435,30 @@ static void MchRes_GetMatchResultDataByMchCod (long MchCod,long UsrCod,
|
|||
/********************** Get if I can see match result ************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static bool MchRes_CheckIfICanSeeMatchResult (struct Mch_Match *Match,long UsrCod)
|
||||
static void MchRes_CheckIfICanSeeMatchResult (const struct Gam_Game *Game,
|
||||
const struct Mch_Match *Match,
|
||||
long UsrCod,
|
||||
struct MchRes_ICanView *ICanView)
|
||||
{
|
||||
bool ItsMe;
|
||||
|
||||
/***** Check if I can view print result and score *****/
|
||||
switch (Gbl.Usrs.Me.Role.Logged)
|
||||
{
|
||||
case Rol_STD:
|
||||
// Depends on visibility of game and result (eye icons)
|
||||
ItsMe = Usr_ItsMe (UsrCod);
|
||||
return ItsMe && Match->Status.ShowUsrResults;
|
||||
ICanView->Result = (ItsMe && // The result is mine
|
||||
!Game->Hidden && // The game is visible
|
||||
Match->Status.ShowUsrResults); // The results of the match are visible to users
|
||||
// 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
|
||||
case Rol_NET:
|
||||
case Rol_TCH:
|
||||
case Rol_DEG_ADM:
|
||||
case Rol_CTR_ADM:
|
||||
case Rol_INS_ADM:
|
||||
case Rol_SYS_ADM:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/********************** Get if I can see match result ************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static bool MchRes_CheckIfICanViewScore (bool ICanViewResult,unsigned Visibility)
|
||||
{
|
||||
switch (Gbl.Usrs.Me.Role.Logged)
|
||||
{
|
||||
case Rol_STD:
|
||||
if (ICanViewResult)
|
||||
return TstVis_IsVisibleTotalScore (Visibility);
|
||||
return false;
|
||||
if (ICanView->Result)
|
||||
// Depends on 5 visibility icons associated to game
|
||||
ICanView->Score = TstVis_IsVisibleTotalScore (Game->Visibility);
|
||||
else
|
||||
ICanView->Score = false;
|
||||
break;
|
||||
case Rol_NET:
|
||||
case Rol_TCH:
|
||||
|
@ -1482,8 +1466,12 @@ static bool MchRes_CheckIfICanViewScore (bool ICanViewResult,unsigned Visibility
|
|||
case Rol_CTR_ADM:
|
||||
case Rol_INS_ADM:
|
||||
case Rol_SYS_ADM:
|
||||
return true;
|
||||
ICanView->Result =
|
||||
ICanView->Score = true;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
ICanView->Result =
|
||||
ICanView->Score = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30889,7 +30889,7 @@ const char *Txt_Please_check_your_email_address =
|
|||
#elif L==4 // es
|
||||
"Por favor, compruebe su dirección de correo.";
|
||||
#elif L==5 // fr
|
||||
"S'il vous plaít, v&eaxcute;rifiez votre adresse email.";
|
||||
"S'il vous plaít, vérifiez votre adresse email.";
|
||||
#elif L==6 // gn
|
||||
"Por favor, compruebe su dirección de correo."; // Okoteve traducción
|
||||
#elif L==7 // it
|
||||
|
|
Loading…
Reference in New Issue