diff --git a/swad_API.c b/swad_API.c index 3e7bebae..bbf6050e 100644 --- a/swad_API.c +++ b/swad_API.c @@ -4470,15 +4470,18 @@ int swad__getGames (struct soap *soap, "MIN(mch_matches.StartTime) AS StartTime," // row[2] "MAX(mch_matches.EndTime) AS EndTime," // row[3] "gam_games.MaxGrade," // row[4] - "gam_games.Title," // row[5] - "gam_games.Txt" // row[6] + "gam_games.Visibility," // row[5] + "gam_games.Title," // row[6] + "gam_games.Txt" // row[7] " FROM gam_games" " LEFT JOIN mch_matches" " ON gam_games.GamCod=mch_matches.GamCod" " WHERE gam_games.CrsCod=%ld" " AND Hidden='N'" " GROUP BY gam_games.GamCod" - " ORDER BY StartTime DESC,EndTime DESC,gam_games.Title DESC", + " ORDER BY StartTime DESC," + "EndTime DESC," + "gam_games.Title DESC", Gbl.Hierarchy.Crs.CrsCod); getGamesOut->gamesArray.__size = getGamesOut->numGames = (int) NumRows; @@ -4560,18 +4563,22 @@ int swad__getGames (struct soap *soap, if (getGamesOut->gamesArray.__ptr[NumGame].maxGrade < 0.0) // Only positive values allowed getGamesOut->gamesArray.__ptr[NumGame].maxGrade = 0.0; - /* Get title of the game (row[5]) */ - Length = strlen (row[5]); + /* Get visibility (row[5]) */ + // TODO: Get visibility + // getGamesOut->gamesArray.__ptr[NumGame].Visibility = TsV_GetVisibilityFromStr (row[5]); + + /* Get title of the game (row[6]) */ + Length = strlen (row[6]); getGamesOut->gamesArray.__ptr[NumGame].title = (char *) soap_malloc (Gbl.soap,Length + 1); - Str_Copy (getGamesOut->gamesArray.__ptr[NumGame].title,row[5], + Str_Copy (getGamesOut->gamesArray.__ptr[NumGame].title,row[6], Length); - /* Get Txt (row[6]) */ - Length = strlen (row[6]); + /* Get Txt (row[7]) */ + Length = strlen (row[7]); getGamesOut->gamesArray.__ptr[NumGame].text = (char *) soap_malloc (Gbl.soap,Length + 1); - Str_Copy (getGamesOut->gamesArray.__ptr[NumGame].text,row[6], + Str_Copy (getGamesOut->gamesArray.__ptr[NumGame].text,row[7], Length); } } diff --git a/swad_changelog.h b/swad_changelog.h index 05b7857e..71f62c70 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -501,14 +501,32 @@ ps2pdf source.ps destination.pdf #define CSS_FILE "swad19.118.css" #define JS_FILE "swad19.91.1.js" /* + * +// TODO: Geolocalización: + * Función API +sendLocation +Parámetros: string con ubicación (ej. "Aula 0.1") + +Poblar base de datos: +En Usuarios > Ubicación aparecería un botón pequeño de "Añadir ubicación". Se preguntaría a SWAD a través de una función de la API +si el usuario tiene permiso para añadir ubicaciones. Si es así, se llamaría a la función: +sendPoint +Paramétros: MAC, string con ubicación (ej. "Aula 0.1") + + * // TODO: Hacer un nuevo rol en los TFG: tutor externo (profesor de áreas no vinculadas con el centro, profesionales de empresas, etc.) // TODO: Impedir la creación y edición de proyectos si no son editables. // TODO: No se puede entrar con DNI '1' suponiendo que no tenga password ¿por qué? // TODO: En la lista de conectados central, poner el logo de la institución a la que pertenece el usuario // TODO: Add visibility to API function getTestConfig -// TODO: Add visibility to games +// TODO: Get visibility IN API function getGames // TODO: Sugerencia de Jesús González Peñalver: añadir un poco más de espacio entre pregunta y pregunta en las opciones de un juego + Version 19.127: Feb 18, 2020 Form to define visibility of match results in games. (279103 lines) + 2 changes necessary in database: +ALTER TABLE gam_games ADD COLUMN Visibility INT NOT NULL DEFAULT 0x1f AFTER MaxGrade; +UPDATE gam_games,tst_config SET gam_games.Visibility=tst_config.Visibility WHERE gam_games.CrsCod=tst_config.CrsCod; + Version 19.126: Feb 18, 2020 New module swad_test_visibility for visibility of test results. (279013 lines) Version 19.125.4: Feb 17, 2020 Changes in visibility of answers. (278930 lines) Version 19.125.3: Feb 17, 2020 Changes in visibility of question stem. (278898 lines) diff --git a/swad_database.c b/swad_database.c index ea69a01a..48c91ce4 100644 --- a/swad_database.c +++ b/swad_database.c @@ -1332,6 +1332,7 @@ mysql> DESCRIBE gam_games; "Hidden ENUM('N','Y') NOT NULL DEFAULT 'N'," "UsrCod INT NOT NULL," "MaxGrade DOUBLE PRECISION NOT NULL DEFAULT 1," // Scale from score [0...num.answers] to grade [0...MaxGrade] + "Visibility INT NOT NULL DEFAULT 0x1f," "Title VARCHAR(2047) NOT NULL," // Gam_MAX_BYTES_TITLE "Txt TEXT NOT NULL," // Cns_MAX_BYTES_TEXT "UNIQUE INDEX(GamCod)," diff --git a/swad_game.c b/swad_game.c index e92ae075..ea09f44a 100644 --- a/swad_game.c +++ b/swad_game.c @@ -43,6 +43,7 @@ #include "swad_pagination.h" #include "swad_role.h" #include "swad_test.h" +#include "swad_test_visibility.h" /*****************************************************************************/ /************** External global variables from others modules ****************/ @@ -433,8 +434,9 @@ void Gam_ShowOnlyOneGameEnd (void) static void Gam_ShowOneGame (struct Game *Game,bool ShowOnlyThisGame) { extern const char *Txt_View_game; - extern const char *Txt_Maximum_grade; extern const char *Txt_No_of_questions; + extern const char *Txt_Maximum_grade; + extern const char *Txt_Result_visibility; extern const char *Txt_Matches; char *Anchor = NULL; static unsigned UniqueId = 0; @@ -513,7 +515,7 @@ static void Gam_ShowOneGame (struct Game *Game,bool ShowOnlyThisGame) Frm_EndForm (); HTM_ARTICLE_End (); - /* Number of questions and maximum grade */ + /* Number of questions, maximum grade, visibility of results */ HTM_DIV_Begin ("class=\"%s\"",Game->Hidden ? "ASG_GRP_LIGHT" : "ASG_GRP"); HTM_TxtColonNBSP (Txt_No_of_questions); @@ -521,10 +523,17 @@ static void Gam_ShowOneGame (struct Game *Game,bool ShowOnlyThisGame) HTM_BR (); HTM_TxtColonNBSP (Txt_Maximum_grade); HTM_Double (Game->MaxGrade); + if (ShowOnlyThisGame) + { + HTM_BR (); + HTM_TxtColonNBSP (Txt_Result_visibility); + HTM_BR (); + TsV_ShowVisibility (Game->Visibility, + Game->Hidden ? "ASG_GRP_LIGHT" : + "ASG_GRP"); + } HTM_DIV_End (); - HTM_TD_End (); - /***** Number of matches in game *****/ if (ShowOnlyThisGame) HTM_TD_Begin ("class=\"RT\""); @@ -899,7 +908,8 @@ void Gam_GetDataOfGameByCod (struct Game *Game) "gam_games.Hidden," // row[2] "gam_games.UsrCod," // row[3] "gam_games.MaxGrade," // row[4] - "gam_games.Title" // row[5] + "gam_games.Visibility," // row[5] + "gam_games.Title" // row[6] " FROM gam_games" " LEFT JOIN mch_matches" " ON gam_games.GamCod=mch_matches.GamCod" @@ -927,8 +937,11 @@ void Gam_GetDataOfGameByCod (struct Game *Game) if (Game->MaxGrade < 0.0) // Only positive values allowed Game->MaxGrade = 0.0; - /* Get the title of the game (row[5]) */ - Str_Copy (Game->Title,row[5], + /* Get visibility (row[5]) */ + Game->Visibility = TsV_GetVisibilityFromStr (row[5]); + + /* Get the title of the game (row[6]) */ + Str_Copy (Game->Title,row[6], Gam_MAX_BYTES_TITLE); /* Get number of questions */ @@ -989,6 +1002,7 @@ static void Gam_ResetGame (struct Game *Game) Game->CrsCod = -1L; Game->UsrCod = -1L; Game->MaxGrade = Gam_MAX_GRADE_DEFAULT; + Game->Visibility = TsV_VISIBILITY_DEFAULT; Game->TimeUTC[Dat_START_TIME] = (time_t) 0; Game->TimeUTC[Dat_END_TIME ] = (time_t) 0; Game->Title[0] = '\0'; @@ -1254,6 +1268,7 @@ static void Gam_PutFormsEditionGame (struct Game *Game,bool ItsANewGame) extern const char *Txt_Edit_game; extern const char *Txt_Title; extern const char *Txt_Maximum_grade; + extern const char *Txt_Result_visibility; extern const char *Txt_Description; extern const char *Txt_Create_game; extern const char *Txt_Save_changes; @@ -1316,6 +1331,19 @@ static void Gam_PutFormsEditionGame (struct Game *Game,bool ItsANewGame) HTM_TR_End (); + /***** Visibility of results *****/ + HTM_TR_Begin (NULL); + + HTM_TD_Begin ("class=\"%s RT\"",The_ClassFormInBox[Gbl.Prefs.Theme]); + HTM_TxtF ("%s:",Txt_Result_visibility); + HTM_TD_End (); + + HTM_TD_Begin ("class=\"LB\""); + TsV_PutVisibilityCheckboxes (Game->Visibility); + HTM_TD_End (); + + HTM_TR_End (); + /***** Game text *****/ HTM_TR_Begin (NULL); @@ -1378,6 +1406,9 @@ void Gam_RecFormGame (void) if (Game.MaxGrade < 0.0) // Only positive values allowed Game.MaxGrade = 0.0; + /***** Get visibility from form *****/ + Game.Visibility = TsV_GetVisibilityFromForm (); + /***** Get game text and insert links *****/ Par_GetParToHTML ("Txt",Txt,Cns_MAX_BYTES_TEXT); // Store in HTML format (not rigorous) @@ -1432,12 +1463,13 @@ static void Gam_CreateGame (struct Game *Game,const char *Txt) Game->GamCod = DB_QueryINSERTandReturnCode ("can not create new game", "INSERT INTO gam_games" - " (CrsCod,Hidden,UsrCod,MaxGrade,Title,Txt)" + " (CrsCod,Hidden,UsrCod,MaxGrade,Visibility,Title,Txt)" " VALUES" - " (%ld,'N',%ld,%.15lg,'%s','%s')", + " (%ld,'N',%ld,%.15lg,%u,'%s','%s')", Gbl.Hierarchy.Crs.CrsCod, Gbl.Usrs.Me.UsrDat.UsrCod, Game->MaxGrade, + Game->Visibility, Game->Title, Txt); Str_SetDecimalPointToLocal (); // Return to local system @@ -1461,11 +1493,13 @@ static void Gam_UpdateGame (struct Game *Game,const char *Txt) "UPDATE gam_games" " SET CrsCod=%ld," "MaxGrade=%.15lg," + "Visibility=%u," "Title='%s'," "Txt='%s'" " WHERE GamCod=%ld", Gbl.Hierarchy.Crs.CrsCod, Game->MaxGrade, + Game->Visibility, Game->Title, Txt, Game->GamCod); diff --git a/swad_game.h b/swad_game.h index 53c05011..d472585f 100644 --- a/swad_game.h +++ b/swad_game.h @@ -51,6 +51,7 @@ struct Game double MaxGrade; // Score range [0...max.score] // will be converted to // grade range [0...max.grade] + unsigned Visibility; // Visibility of results char Title[Gam_MAX_BYTES_TITLE + 1]; time_t TimeUTC[Dat_NUM_START_END_TIME]; bool Hidden; // Game is hidden diff --git a/swad_match_result.c b/swad_match_result.c index d395be84..01732a5f 100644 --- a/swad_match_result.c +++ b/swad_match_result.c @@ -100,8 +100,8 @@ static void McR_GetMatchResultDataByMchCod (long MchCod,long UsrCod, unsigned *NumQstsNotBlank, double *Score); -static bool McR_CheckIfICanSeeMatchResult (long MchCod,long UsrCod); -static bool McR_GetVisibilityMchResultFromDB (long MchCod); +static bool McR_CheckIfICanSeeMatchResult (struct Match *Match,long UsrCod); +static bool McR_CheckIfICanViewScore (bool ICanViewResult,unsigned Visibility); /*****************************************************************************/ /*********** Select users and dates to show their matches results ************/ @@ -668,8 +668,8 @@ static void McR_ShowMchResults (Usr_MeOrOther_t MeOrOther, MYSQL_RES *mysql_res; MYSQL_ROW row; struct UsrData *UsrDat; - bool ShowResultThisMatch; - bool ShowSummaryResults = true; + bool ICanViewResult; + bool ICanViewScore; unsigned NumResults; unsigned NumResult; static unsigned UniqueId = 0; @@ -685,6 +685,7 @@ static void McR_ShowMchResults (Usr_MeOrOther_t MeOrOther, double MaxGrade; double Grade; double TotalGrade = 0.0; + unsigned Visibility; time_t TimeUTC[Dat_NUM_START_END_TIME]; /***** Set user *****/ @@ -738,7 +739,8 @@ static void McR_ShowMchResults (Usr_MeOrOther_t MeOrOther, "mch_results.NumQsts," // row[3] "mch_results.NumQstsNotBlank," // row[4] "mch_results.Score," // row[5] - "gam_games.MaxGrade" // row[6] + "gam_games.MaxGrade," // row[6] + "gam_games.Visibility" // row[7] " FROM mch_results,mch_matches,gam_games" " WHERE mch_results.UsrCod=%ld" "%s" // Match subquery @@ -772,9 +774,12 @@ static void McR_ShowMchResults (Usr_MeOrOther_t MeOrOther, Lay_ShowErrorAndExit ("Wrong code of match."); Mch_GetDataOfMatchByCod (&Match); + /* Get visibility (row[7]) */ + Visibility = TsV_GetVisibilityFromStr (row[7]); + /* Show match result? */ - ShowResultThisMatch = McR_CheckIfICanSeeMatchResult (Match.MchCod,UsrDat->UsrCod); - ShowSummaryResults = ShowSummaryResults && ShowResultThisMatch; + ICanViewResult = McR_CheckIfICanSeeMatchResult (&Match,UsrDat->UsrCod); + ICanViewScore = McR_CheckIfICanViewScore (ICanViewResult,Visibility); if (NumResult) HTM_TR_Begin (NULL); @@ -802,7 +807,7 @@ static void McR_ShowMchResults (Usr_MeOrOther_t MeOrOther, HTM_Txt (Match.Title); HTM_TD_End (); - if (ShowResultThisMatch) + if (ICanViewResult) { /* Get number of questions (row[3]) */ if (sscanf (row[3],"%u",&NumQstsInThisResult) != 1) @@ -830,7 +835,7 @@ static void McR_ShowMchResults (Usr_MeOrOther_t MeOrOther, /* Write number of questions */ HTM_TD_Begin ("class=\"DAT RT COLOR%u\"",Gbl.RowEvenOdd); - if (ShowResultThisMatch) + if (ICanViewResult) HTM_Unsigned (NumQstsInThisResult); else Ico_PutIconOff ("eye-slash.svg",Txt_Hidden_results); @@ -838,7 +843,7 @@ static void McR_ShowMchResults (Usr_MeOrOther_t MeOrOther, /* Write number of questions not blank */ HTM_TD_Begin ("class=\"DAT RT COLOR%u\"",Gbl.RowEvenOdd); - if (ShowResultThisMatch) + if (ICanViewResult) HTM_Unsigned (NumQstsNotBlankInThisResult); else Ico_PutIconOff ("eye-slash.svg",Txt_Hidden_results); @@ -846,7 +851,7 @@ static void McR_ShowMchResults (Usr_MeOrOther_t MeOrOther, /* Write score */ HTM_TD_Begin ("class=\"DAT RT COLOR%u\"",Gbl.RowEvenOdd); - if (ShowResultThisMatch) + if (ICanViewScore) HTM_Double2Decimals (ScoreInThisResult); else Ico_PutIconOff ("eye-slash.svg",Txt_Hidden_results); @@ -854,17 +859,17 @@ static void McR_ShowMchResults (Usr_MeOrOther_t MeOrOther, /* Write average score per question */ HTM_TD_Begin ("class=\"DAT RT COLOR%u\"",Gbl.RowEvenOdd); - if (ShowResultThisMatch) + if (ICanViewScore) HTM_Double2Decimals (NumQstsInThisResult ? ScoreInThisResult / - (double) NumQstsInThisResult : - 0.0); + (double) NumQstsInThisResult : + 0.0); else Ico_PutIconOff ("eye-slash.svg",Txt_Hidden_results); HTM_TD_End (); /* Write grade over maximum grade */ HTM_TD_Begin ("class=\"DAT RT COLOR%u\"",Gbl.RowEvenOdd); - if (ShowResultThisMatch) + if (ICanViewScore) { Grade = Tst_ComputeGrade (NumQstsInThisResult,ScoreInThisResult,MaxGrade); Tst_ShowGrade (Grade,MaxGrade); @@ -876,7 +881,7 @@ static void McR_ShowMchResults (Usr_MeOrOther_t MeOrOther, /* Link to show this result */ HTM_TD_Begin ("class=\"RT COLOR%u\"",Gbl.RowEvenOdd); - if (ShowResultThisMatch) + if (ICanViewResult) { Gam_SetCurrentGamCod (Match.GamCod); // Used to pass parameter Mch_SetCurrentMchCod (Match.MchCod); // Used to pass parameter @@ -1004,8 +1009,6 @@ void McR_ShowOneMchResult (void) double TotalScore; bool ShowPhoto; char PhotoURL[PATH_MAX + 1]; - bool ItsMe; - bool ICanPlayThisMatchBasedOnGrps; bool ICanViewResult; bool ICanViewScore; @@ -1033,55 +1036,22 @@ void McR_ShowOneMchResult (void) &NumQsts, &NumQstsNotBlank, &TotalScore); - Gbl.Test.Config.Visibility = TsV_MAX_VISIBILITY; // Initialize visibility to maximum /***** Check if I can view this match result *****/ - ItsMe = Usr_ItsMe (UsrDat->UsrCod); switch (Gbl.Usrs.Me.Role.Logged) { case Rol_STD: - switch (MeOrOther) - { - case Usr_ME: - ICanPlayThisMatchBasedOnGrps = Mch_CheckIfICanPlayThisMatchBasedOnGrps (&Match); - ICanViewResult = ItsMe && ICanPlayThisMatchBasedOnGrps && - Match.Status.ShowUsrResults; - - if (ICanViewResult) - { - Tst_GetConfigTstFromDB (); // To get feedback type - ICanViewScore = TsV_IsVisibleTotalScore (Gbl.Test.Config.Visibility); - } - else - ICanViewScore = false; - break; - default: - ICanViewResult = - ICanViewScore = false; - break; - } + ICanViewResult = McR_CheckIfICanSeeMatchResult (&Match,UsrDat->UsrCod); + if (ICanViewResult) + ICanViewScore = TsV_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: - switch (MeOrOther) - { - case Usr_ME: - ICanViewResult = - ICanViewScore = ItsMe; - break; - case Usr_OTHER: - ICanViewResult = - ICanViewScore = true; - break; - default: - ICanViewResult = - ICanViewScore = false; - break; - } - break; case Rol_SYS_ADM: ICanViewResult = ICanViewScore = true; @@ -1202,7 +1172,7 @@ void McR_ShowOneMchResult (void) if (ICanViewScore) Tst_ComputeAndShowGrade (NumQsts,TotalScore,Game.MaxGrade); else - HTM_Txt ("?"); // No feedback + HTM_Txt ("?"); // Not visible HTM_TD_End (); HTM_TR_End (); @@ -1221,7 +1191,8 @@ void McR_ShowOneMchResult (void) HTM_TR_End (); /***** Write answers and solutions *****/ - TsR_ShowTestResult (UsrDat,NumQsts,TimeUTC[Dat_START_TIME]); + TsR_ShowTestResult (UsrDat,NumQsts,TimeUTC[Dat_START_TIME], + Game.Visibility); /***** End table *****/ HTM_TABLE_End (); @@ -1372,22 +1343,44 @@ static void McR_GetMatchResultDataByMchCod (long MchCod,long UsrCod, } /*****************************************************************************/ -/********************* Get if I can see match result ************************/ +/********************** Get if I can see match result ************************/ /*****************************************************************************/ -static bool McR_CheckIfICanSeeMatchResult (long MchCod,long UsrCod) +static bool McR_CheckIfICanSeeMatchResult (struct Match *Match,long UsrCod) { bool ItsMe; - bool ShowResultThisMatch; switch (Gbl.Usrs.Me.Role.Logged) { case Rol_STD: ItsMe = Usr_ItsMe (UsrCod); - if (ItsMe && Gbl.Test.Config.Visibility != 0) - ShowResultThisMatch = McR_GetVisibilityMchResultFromDB (MchCod); - else - ShowResultThisMatch = false; + if (ItsMe && Match->Status.ShowUsrResults) + return Mch_CheckIfICanPlayThisMatchBasedOnGrps (Match); + return false; + 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 McR_CheckIfICanViewScore (bool ICanViewResult,unsigned Visibility) + { + switch (Gbl.Usrs.Me.Role.Logged) + { + case Rol_STD: + if (ICanViewResult) + return TsV_IsVisibleTotalScore (Visibility); + return false; break; case Rol_NET: case Rol_TCH: @@ -1395,48 +1388,9 @@ static bool McR_CheckIfICanSeeMatchResult (long MchCod,long UsrCod) case Rol_CTR_ADM: case Rol_INS_ADM: case Rol_SYS_ADM: - ShowResultThisMatch = true; - break; + return true; default: - ShowResultThisMatch = false; - break; + return false; } - - return ShowResultThisMatch; } -/*****************************************************************************/ -/********************* Get visibility of match result ************************/ -/*****************************************************************************/ - -static bool McR_GetVisibilityMchResultFromDB (long MchCod) - { - MYSQL_RES *mysql_res; - MYSQL_ROW row; - unsigned long NumRows; - bool ShowUsrResults; - - /***** Get visibility of match result from database *****/ - NumRows = (unsigned) DB_QuerySELECT (&mysql_res,"can not get if show result", - "SELECT ShowUsrResults" // row[0] - " FROM mch_matches" - " WHERE MchCod=%ld" - " AND GamCod IN" // Extra check - " (SELECT GamCod FROM gam_games" - " WHERE CrsCod='%ld')", - MchCod, - Gbl.Hierarchy.Crs.CrsCod); - if (NumRows) // Match found... - { - /* Get whether to show user results or not (row(0)) */ - row = mysql_fetch_row (mysql_res); - ShowUsrResults = (row[0][0] == 'Y'); - } - else - ShowUsrResults = false; - - /***** Free structure that stores the query result *****/ - DB_FreeMySQLResult (&mysql_res); - - return ShowUsrResults; - } diff --git a/swad_test.c b/swad_test.c index d12448c9..d6943101 100644 --- a/swad_test.c +++ b/swad_test.c @@ -1674,12 +1674,10 @@ static void Tst_ShowFormSelTags (unsigned long NumRows,MYSQL_RES *mysql_res, { TagHidden = (row[2][0] == 'Y'); HTM_TD_Begin ("class=\"LM\""); - if (TagHidden) - HTM_IMG (Cfg_URL_ICON_PUBLIC,"eye-slash.svg",Txt_Tag_not_allowed, - "class=\"ICO_HIDDEN ICO16x16\""); - else - HTM_IMG (Cfg_URL_ICON_PUBLIC,"eye.svg",Txt_Tag_allowed, - "class=\"ICO_HIDDEN ICO16x16\""); + Ico_PutIconOff (TagHidden ? "eye-slash.svg" : + "eye.svg", + TagHidden ? Txt_Tag_not_allowed : + Txt_Tag_allowed); HTM_TD_End (); } @@ -2018,7 +2016,6 @@ void Tst_GetConfigFromRow (MYSQL_ROW row) { int IntNum; long LongNum; - unsigned UnsignedNum; Tst_Pluggable_t Pluggable; /***** Get whether test are visible via plugins or not *****/ @@ -2060,8 +2057,7 @@ void Tst_GetConfigFromRow (MYSQL_ROW row) (unsigned long) LongNum; /***** Get visibility (row[5]) *****/ - if (sscanf (row[5],"%u",&UnsignedNum) == 1) - Gbl.Test.Config.Visibility = UnsignedNum & TsV_MAX_VISIBILITY; + Gbl.Test.Config.Visibility = TsV_GetVisibilityFromStr (row[5]); } /*****************************************************************************/ @@ -2154,7 +2150,7 @@ void Tst_ReceiveConfigTst (void) ULONG_MAX, 0); - /***** Get type of feedback from form *****/ + /***** Get visibility from form *****/ Gbl.Test.Config.Visibility = TsV_GetVisibilityFromForm (); /***** Update database *****/ diff --git a/swad_test_result.c b/swad_test_result.c index 1e6a0d6e..477af21c 100644 --- a/swad_test_result.c +++ b/swad_test_result.c @@ -774,7 +774,8 @@ void TsR_ShowOneTstResult (void) /***** Write answers and solutions *****/ TsR_ShowTestResult (&Gbl.Usrs.Other.UsrDat, - Gbl.Test.NumQsts,TstTimeUTC); + Gbl.Test.NumQsts,TstTimeUTC, + Gbl.Test.Config.Visibility); /***** End table *****/ HTM_TABLE_End (); @@ -832,7 +833,8 @@ static void TsR_ShowTstTagsPresentInATestResult (long TstCod) /*****************************************************************************/ void TsR_ShowTestResult (struct UsrData *UsrDat, - unsigned NumQsts,time_t TstTimeUTC) + unsigned NumQsts,time_t TstTimeUTC, + unsigned Visibility) { extern const char *Txt_Question_modified; extern const char *Txt_Question_removed; @@ -900,7 +902,7 @@ void TsR_ShowTestResult (struct UsrData *UsrDat, Tst_WriteQstAndAnsTest (Tst_SHOW_TEST_RESULT, UsrDat, NumQst,QstCod,row, - Gbl.Test.Config.Visibility, + Visibility, &ScoreThisQst, // Not used here &AnswerIsNotBlank); // Not used here } diff --git a/swad_test_result.h b/swad_test_result.h index 449f83f0..f989fb0b 100644 --- a/swad_test_result.h +++ b/swad_test_result.h @@ -52,7 +52,8 @@ void TsR_StoreScoreOfTestResultInDB (long TstCod, void TsR_GetUsrsAndShowTstResults (void); void TsR_ShowOneTstResult (void); void TsR_ShowTestResult (struct UsrData *UsrDat, - unsigned NumQsts,time_t TstTimeUTC); + unsigned NumQsts,time_t TstTimeUTC, + unsigned Visibility); void TsR_StoreOneTestResultQstInDB (long TstCod,long QstCod,unsigned NumQst,double Score); void TsR_RemoveTestResultsMadeByUsrInAllCrss (long UsrCod); void TsR_RemoveTestResultsMadeByUsrInCrs (long UsrCod,long CrsCod); diff --git a/swad_test_visibility.c b/swad_test_visibility.c index c3c1afb4..c6536367 100644 --- a/swad_test_visibility.c +++ b/swad_test_visibility.c @@ -56,7 +56,60 @@ extern struct Globals Gbl; /*****************************************************************************/ /*****************************************************************************/ -/*********************** Get type of feedback from form **********************/ +/************ Put checkboxes in form to select result visibility *************/ +/*****************************************************************************/ + +void TsV_ShowVisibility (unsigned SelectedVisibility,const char *Class) + { + extern const char *Txt_Visible; + extern const char *Txt_Hidden; + extern const char *Txt_TST_STR_VISIBILITY[TsV_NUM_ITEMS_VISIBILITY]; + TsV_Visibility_t Visibility; + bool ItemVisible; + + for (Visibility = (TsV_Visibility_t) 0; + Visibility <= (TsV_Visibility_t) (TsV_NUM_ITEMS_VISIBILITY - 1); + Visibility++) + { + HTM_LABEL_Begin ("class=\"%s\"",Class); + ItemVisible = (SelectedVisibility & (1 << Visibility)) != 0; + Ico_PutIconOff (ItemVisible ? "eye.svg" : + "eye-slash.svg", + ItemVisible ? Txt_Visible : + Txt_Hidden); + HTM_Txt (Txt_TST_STR_VISIBILITY[Visibility]); + HTM_LABEL_End (); + HTM_BR (); + } + } + +/*****************************************************************************/ +/************ Put checkboxes in form to select result visibility *************/ +/*****************************************************************************/ + +void TsV_PutVisibilityCheckboxes (unsigned SelectedVisibility) + { + extern const char *Txt_TST_STR_VISIBILITY[TsV_NUM_ITEMS_VISIBILITY]; + TsV_Visibility_t Visibility; + + for (Visibility = (TsV_Visibility_t) 0; + Visibility <= (TsV_Visibility_t) (TsV_NUM_ITEMS_VISIBILITY - 1); + Visibility++) + { + HTM_LABEL_Begin ("class=\"DAT\""); + HTM_INPUT_CHECKBOX ("Visibility",false, + "value=\"%u\"%s", + (unsigned) Visibility, + (SelectedVisibility & (1 << Visibility)) != 0 ? " checked=\"checked\"" : + ""); + HTM_Txt (Txt_TST_STR_VISIBILITY[Visibility]); + HTM_LABEL_End (); + HTM_BR (); + } + } + +/*****************************************************************************/ +/************************** Get visibility from form *************************/ /*****************************************************************************/ unsigned TsV_GetVisibilityFromForm (void) @@ -66,7 +119,7 @@ unsigned TsV_GetVisibilityFromForm (void) const char *Ptr; char UnsignedStr[Cns_MAX_DECIMAL_DIGITS_UINT + 1]; unsigned UnsignedNum; - TsV_ResultVisibility_t VisibilityItem; + TsV_Visibility_t VisibilityItem; unsigned Visibility = 0; // Nothing selected /***** Allocate memory for list of attendance events selected *****/ @@ -88,7 +141,7 @@ unsigned TsV_GetVisibilityFromForm (void) if (sscanf (UnsignedStr,"%u",&UnsignedNum) == 1) if (UnsignedNum < TsV_NUM_ITEMS_VISIBILITY) { - VisibilityItem = (TsV_ResultVisibility_t) UnsignedNum; + VisibilityItem = (TsV_Visibility_t) UnsignedNum; Visibility |= (1 << VisibilityItem); } } @@ -97,28 +150,21 @@ unsigned TsV_GetVisibilityFromForm (void) } /*****************************************************************************/ -/************ Put checkboxes in form to select result visibility *************/ +/************************** Get visibility from string *************************/ /*****************************************************************************/ -void TsV_PutVisibilityCheckboxes (unsigned SelectedVisibility) +unsigned TsV_GetVisibilityFromStr (const char *Str) { - extern const char *Txt_TST_STR_VISIBILITY[TsV_NUM_ITEMS_VISIBILITY]; - TsV_ResultVisibility_t Visibility; + unsigned UnsignedNum; + unsigned Visibility = TsV_MIN_VISIBILITY; // In nothing is read, return minimum visibility - for (Visibility = (TsV_ResultVisibility_t) 0; - Visibility <= (TsV_ResultVisibility_t) (TsV_NUM_ITEMS_VISIBILITY - 1); - Visibility++) - { - HTM_LABEL_Begin ("class=\"DAT\""); - HTM_INPUT_CHECKBOX ("Visibility",false, - "value=\"%u\"%s", - (unsigned) Visibility, - (SelectedVisibility & (1 << Visibility)) != 0 ? " checked=\"checked\"" : - ""); - HTM_Txt (Txt_TST_STR_VISIBILITY[Visibility]); - HTM_LABEL_End (); - HTM_BR (); - } + /***** Get visibility from string *****/ + if (Str) + if (Str[0]) + if (sscanf (Str,"%u",&UnsignedNum) == 1) + Visibility = UnsignedNum & TsV_MAX_VISIBILITY; + + return Visibility; } /*****************************************************************************/ diff --git a/swad_test_visibility.h b/swad_test_visibility.h index 98cae7df..fd84e146 100644 --- a/swad_test_visibility.h +++ b/swad_test_visibility.h @@ -45,7 +45,8 @@ typedef enum TsV_VISIBLE_CORRECT_ANSWER = 2, // Correct answers TsV_VISIBLE_EACH_QST_SCORE = 3, // Score of each question TsV_VISIBLE_TOTAL_SCORE = 4, // Total score - } TsV_ResultVisibility_t; + } TsV_Visibility_t; +#define TsV_MIN_VISIBILITY 0 // Nothing visible #define TsV_MAX_VISIBILITY ((1 << TsV_NUM_ITEMS_VISIBILITY) - 1) // All visible #define TsV_VISIBILITY_DEFAULT TsV_MAX_VISIBILITY @@ -53,8 +54,10 @@ typedef enum /***************************** Public prototypes *****************************/ /*****************************************************************************/ -unsigned TsV_GetVisibilityFromForm (void); +void TsV_ShowVisibility (unsigned SelectedVisibility,const char *Class); void TsV_PutVisibilityCheckboxes (unsigned SelectedVisibility); +unsigned TsV_GetVisibilityFromForm (void); +unsigned TsV_GetVisibilityFromStr (const char *Str); bool TsV_IsVisibleQstAndAnsTxt (unsigned Visibility); bool TsV_IsVisibleFeedbackTxt (unsigned Visibility); diff --git a/swad_text.c b/swad_text.c index e6cef820..0c8ec432 100644 --- a/swad_text.c +++ b/swad_text.c @@ -14600,6 +14600,27 @@ const char *Txt_HELP_password = "8 ou mais caracteres"; #endif +const char *Txt_Hidden = +#if L==1 // ca + "Ocult"; +#elif L==2 // de + "Verborgen"; +#elif L==3 // en + "Hidden"; +#elif L==4 // es + "Oculto"; +#elif L==5 // fr + "Caché"; +#elif L==6 // gn + "Oculto"; // Okoteve traducción +#elif L==7 // it + "Nascosto"; +#elif L==8 // pl + "Ukryty"; +#elif L==9 // pt + "Oculto"; +#endif + const char *Txt_Hidden_MALE_PLURAL = #if L==1 // ca "Ocultos"; // Necessita traduccio @@ -53734,6 +53755,27 @@ const char *Txt_Result_visibility = "Visibilidade dos resultados"; #endif +const char *Txt_Visible = +#if L==1 // ca + "Visible"; +#elif L==2 // de + "Sichtbare"; +#elif L==3 // en + "Visible"; +#elif L==4 // es + "Visible"; +#elif L==5 // fr + "Visible"; +#elif L==6 // gn + "Visible"; // Okoteve traducción +#elif L==7 // it + "Visibile"; +#elif L==8 // pl + "Widoczny"; +#elif L==9 // pt + "Visível"; +#endif + const char *Txt_Visible_by_BR_the_student = #if L==1 // ca "¿Visible por
el estudiante?"; // Necessita traduccio