diff --git a/swad_API.c b/swad_API.c index a9e13c715..67455ca5a 100644 --- a/swad_API.c +++ b/swad_API.c @@ -3627,7 +3627,6 @@ int swad__getTestConfig (struct soap *soap, char *wsKey,int courseCode, // input struct swad__getTestConfigOutput *getTestConfigOut) // output { - extern const char *TsR_FeedbackXML[TsR_NUM_TYPES_FEEDBACK]; int ReturnCode; /***** Initializations *****/ @@ -3670,7 +3669,10 @@ int swad__getTestConfig (struct soap *soap, return ReturnCode; /***** Set default result to empty *****/ - getTestConfigOut->numQuestions = getTestConfigOut->minQuestions = getTestConfigOut->defQuestions = getTestConfigOut->maxQuestions = 0; + getTestConfigOut->numQuestions = + getTestConfigOut->minQuestions = + getTestConfigOut->defQuestions = + getTestConfigOut->maxQuestions = 0; getTestConfigOut->feedback = (char *) soap_malloc (Gbl.soap,TsR_MAX_BYTES_FEEDBACK_TYPE + 1); getTestConfigOut->feedback[0] = '\0'; @@ -3682,9 +3684,29 @@ int swad__getTestConfig (struct soap *soap, getTestConfigOut->minQuestions = (int) Gbl.Test.Config.Min; getTestConfigOut->defQuestions = (int) Gbl.Test.Config.Def; getTestConfigOut->maxQuestions = (int) Gbl.Test.Config.Max; - Str_Copy (getTestConfigOut->feedback, - TsR_FeedbackXML[Gbl.Test.Config.Feedback], - TsR_MAX_BYTES_FEEDBACK_TYPE); + + /* Convert from visibility to old feedback */ + /* TODO: Remove these lines in 2021 */ + if ((Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_TOTAL_SCORE )) == 0) + Str_Copy (getTestConfigOut->feedback, + "nothing", + TsR_MAX_BYTES_FEEDBACK_TYPE); + else if ((Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_EACH_QST_SCORE)) == 0) + Str_Copy (getTestConfigOut->feedback, + "totalResult", + TsR_MAX_BYTES_FEEDBACK_TYPE); + else if ((Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_CORRECT_ANSWER)) == 0) + Str_Copy (getTestConfigOut->feedback, + "eachResult", + TsR_MAX_BYTES_FEEDBACK_TYPE); + else if ((Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_FEEDBACK_TEXT )) == 0) + Str_Copy (getTestConfigOut->feedback, + "eachGoodBad", + TsR_MAX_BYTES_FEEDBACK_TYPE); + else + Str_Copy (getTestConfigOut->feedback, + "fullFeedback", + TsR_MAX_BYTES_FEEDBACK_TYPE); /***** Get number of tests *****/ if (Gbl.Test.Config.Pluggable == Tst_PLUGGABLE_YES && @@ -3705,7 +3727,7 @@ static int API_GetTstConfig (long CrsCod) /***** Query database *****/ if (DB_QuerySELECT (&mysql_res,"can not get test configuration", - "SELECT Pluggable,Min,Def,Max,MinTimeNxtTstPerQst,Feedback" + "SELECT Pluggable,Min,Def,Max,MinTimeNxtTstPerQst,Visibility" " FROM tst_config WHERE CrsCod=%ld", CrsCod)) { @@ -3717,7 +3739,7 @@ static int API_GetTstConfig (long CrsCod) { Gbl.Test.Config.Pluggable = Tst_PLUGGABLE_UNKNOWN; Gbl.Test.Config.Min = Gbl.Test.Config.Def = Gbl.Test.Config.Max = 0; - Gbl.Test.Config.Feedback = TsR_FEEDBACK_DEFAULT; + Gbl.Test.Config.Visibility = TsR_VISIBILITY_DEFAULT; } /***** Free structure that stores the query result *****/ diff --git a/swad_attendance.c b/swad_attendance.c index 917657568..3cbb5cca7 100644 --- a/swad_attendance.c +++ b/swad_attendance.c @@ -2808,7 +2808,7 @@ static void Att_ListOrPrintUsrsAttendanceCrs (void) static void Att_GetListSelectedAttCods (char **StrAttCodsSelected) { - unsigned MaxSizeListAttCodsSelected; + size_t MaxSizeListAttCodsSelected; unsigned NumAttEvent; const char *Ptr; long AttCod; @@ -2821,7 +2821,7 @@ static void Att_GetListSelectedAttCods (char **StrAttCodsSelected) unsigned NumGrpSel; /***** Allocate memory for list of attendance events selected *****/ - MaxSizeListAttCodsSelected = Gbl.AttEvents.Num * (Cns_MAX_DECIMAL_DIGITS_LONG + 1); + MaxSizeListAttCodsSelected = (size_t) Gbl.AttEvents.Num * (Cns_MAX_DECIMAL_DIGITS_LONG + 1); if ((*StrAttCodsSelected = (char *) malloc (MaxSizeListAttCodsSelected + 1)) == NULL) Lay_NotEnoughMemoryExit (); @@ -2840,7 +2840,7 @@ static void Att_GetListSelectedAttCods (char **StrAttCodsSelected) /* Set some events as selected */ for (Ptr = *StrAttCodsSelected; *Ptr; - ) + ) { /* Get next attendance event selected */ Par_GetNextStrUntilSeparParamMult (&Ptr,LongStr,Cns_MAX_DECIMAL_DIGITS_LONG); diff --git a/swad_changelog.h b/swad_changelog.h index 7ccc4b507..a36afd510 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -497,7 +497,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.124.1 (2020-02-17)" +#define Log_PLATFORM_VERSION "SWAD 19.125 (2020-02-17)" #define CSS_FILE "swad19.118.css" #define JS_FILE "swad19.91.1.js" /* @@ -505,8 +505,11 @@ ps2pdf source.ps destination.pdf // 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: Urgente: Añadir nuevos niveles de realimentación tras sugerencia de Mancia y conversación con Javier. +// TODO: Remove Feedback field from tst_config database table +// TODO: Add visibility to API function getTestConfig +// TODO: Add visibility to games + Version 19.125: Feb 17, 2020 Removed feedback from test config form. (278823 lines) Version 19.124.1: Feb 17, 2020 Fixed bug reported by Javier Fernández Baldomero. Result visibility in tests is stored in database. (279010 lines) 6 changes necessary in database: diff --git a/swad_match_result.c b/swad_match_result.c index 82d554397..0be846b16 100644 --- a/swad_match_result.c +++ b/swad_match_result.c @@ -1032,7 +1032,7 @@ void McR_ShowOneMchResult (void) &NumQsts, &NumQstsNotBlank, &TotalScore); - Gbl.Test.Config.Feedback = TsR_FEEDBACK_FULL_FEEDBACK; // Initialize feedback to maximum + Gbl.Test.Config.Visibility = TsR_MAX_VISIBILITY; // Initialize visibility to maximum /***** Check if I can view this match result *****/ ItsMe = Usr_ItsMe (UsrDat->UsrCod); @@ -1049,7 +1049,7 @@ void McR_ShowOneMchResult (void) if (ICanViewResult) { Tst_GetConfigTstFromDB (); // To get feedback type - ICanViewScore = Gbl.Test.Config.Feedback != TsR_FEEDBACK_NOTHING; + ICanViewScore = (Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_TOTAL_SCORE)) != 0; } else ICanViewScore = false; @@ -1383,7 +1383,7 @@ static bool McR_CheckIfICanSeeMatchResult (long MchCod,long UsrCod) { case Rol_STD: ItsMe = Usr_ItsMe (UsrCod); - if (ItsMe && Gbl.Test.Config.Feedback != TsR_FEEDBACK_NOTHING) + if (ItsMe && Gbl.Test.Config.Visibility != 0) ShowResultThisMatch = McR_GetVisibilityMchResultFromDB (MchCod); else ShowResultThisMatch = false; diff --git a/swad_test.c b/swad_test.c index 8fab71716..fff6f6326 100644 --- a/swad_test.c +++ b/swad_test.c @@ -488,7 +488,7 @@ void Tst_AssessTest (void) HTM_TABLE_End (); /***** Write total score and grade *****/ - if (Gbl.Test.Config.Feedback != TsR_FEEDBACK_NOTHING) + if ((Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_TOTAL_SCORE)) != 0) { HTM_DIV_Begin ("class=\"DAT_N_BOLD CM\""); HTM_TxtColonNBSP (Txt_Score); @@ -992,7 +992,7 @@ void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestio Tst_WriteAnswersTestResult (UsrDat,NumQst,QstCod,ScoreThisQst,AnswerIsNotBlank); /* Write question feedback (row[5]) */ - if (Gbl.Test.Config.Feedback == TsR_FEEDBACK_FULL_FEEDBACK) + if ((Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_FEEDBACK_TEXT)) != 0) Tst_WriteQstFeedback (row[5],"TEST_EXA_LIGHT"); break; default: @@ -1324,8 +1324,7 @@ static void Tst_PutIconsTests (void) Txt_New_question); /***** Put form to go to test configuration *****/ - if (Gbl.Action.Act != ActCfgTst) - Ico_PutContextualIconToConfigure (ActCfgTst,NULL); + Ico_PutContextualIconToConfigure (ActCfgTst,NULL); } /***** Put icon to view tests results *****/ @@ -1813,11 +1812,8 @@ static void Tst_ShowFormConfigTst (void) extern const char *Txt_maximum; extern const char *Txt_Minimum_time_seconds_per_question_between_two_tests; extern const char *Txt_Result_visibility; - extern const char *Txt_Feedback_to_students; - extern const char *Txt_TST_STR_FEEDBACK[TsR_NUM_TYPES_FEEDBACK]; extern const char *Txt_Save_changes; Tst_Pluggable_t Pluggable; - TsR_Feedback_t Feedback; char StrMinTimeNxtTstPerQst[Cns_MAX_DECIMAL_DIGITS_ULONG + 1]; /***** Read test configuration from database *****/ @@ -1907,30 +1903,6 @@ static void Tst_ShowFormConfigTst (void) HTM_TR_End (); - /***** Feedback to students *****/ - HTM_TR_Begin (NULL); - - HTM_TD_Begin ("class=\"%s RT\"",The_ClassFormInBox[Gbl.Prefs.Theme]); - HTM_TxtF ("%s:",Txt_Feedback_to_students); - HTM_TD_End (); - - HTM_TD_Begin ("class=\"LB\""); - for (Feedback = (TsR_Feedback_t) 0; - Feedback <= (TsR_Feedback_t) (TsR_NUM_TYPES_FEEDBACK - 1); - Feedback++) - { - HTM_LABEL_Begin ("class=\"DAT\""); - HTM_INPUT_RADIO ("Feedback",false, - "value=\"%u\"%s", - (unsigned) Feedback, - Feedback == Gbl.Test.Config.Feedback ? " checked=\"checked\"" : ""); - HTM_Txt (Txt_TST_STR_FEEDBACK[Feedback]); - HTM_LABEL_End (); - HTM_BR (); - } - HTM_TD_End (); - - HTM_TR_End (); HTM_TABLE_End (); /***** Send button *****/ @@ -1988,12 +1960,13 @@ void Tst_GetConfigTstFromDB (void) "Def," // row[2] "Max," // row[3] "MinTimeNxtTstPerQst," // row[4] - "Feedback" // row[5] - " FROM tst_config WHERE CrsCod=%ld", + "Visibility" // row[5] + " FROM tst_config" + " WHERE CrsCod=%ld", Gbl.Hierarchy.Crs.CrsCod); - Gbl.Test.Config.Feedback = TsR_FEEDBACK_DEFAULT; Gbl.Test.Config.MinTimeNxtTstPerQst = 0UL; + Gbl.Test.Config.Visibility = TsR_VISIBILITY_DEFAULT; if (NumRows == 0) { Gbl.Test.Config.Pluggable = Tst_PLUGGABLE_UNKNOWN; @@ -2018,11 +1991,10 @@ void Tst_GetConfigTstFromDB (void) void Tst_GetConfigFromRow (MYSQL_ROW row) { - extern const char *TsR_FeedbackDB[TsR_NUM_TYPES_FEEDBACK]; int IntNum; long LongNum; + unsigned UnsignedNum; Tst_Pluggable_t Pluggable; - TsR_Feedback_t Feedback; /***** Get whether test are visible via plugins or not *****/ Gbl.Test.Config.Pluggable = Tst_PLUGGABLE_UNKNOWN; @@ -2062,15 +2034,9 @@ void Tst_GetConfigFromRow (MYSQL_ROW row) Gbl.Test.Config.MinTimeNxtTstPerQst = (LongNum < 1L) ? 0UL : (unsigned long) LongNum; - /***** Get feedback type (row[5]) *****/ - for (Feedback = (TsR_Feedback_t) 0; - Feedback <= (TsR_Feedback_t) (TsR_NUM_TYPES_FEEDBACK - 1); - Feedback++) - if (!strcmp (row[5],TsR_FeedbackDB[Feedback])) - { - Gbl.Test.Config.Feedback = Feedback; - break; - } + /***** Get visibility (row[5]) *****/ + if (sscanf (row[5],"%u",&UnsignedNum) == 1) + Gbl.Test.Config.Visibility = UnsignedNum & TsR_MAX_VISIBILITY; } /*****************************************************************************/ @@ -2127,7 +2093,6 @@ bool Tst_CheckIfCourseHaveTestsAndPluggableIsUnknown (void) void Tst_ReceiveConfigTst (void) { - extern const char *TsR_FeedbackDB[TsR_NUM_TYPES_FEEDBACK]; extern const char *Txt_The_test_configuration_has_been_updated; /***** Get whether test are visible via plugins or not *****/ @@ -2165,19 +2130,19 @@ void Tst_ReceiveConfigTst (void) 0); /***** Get type of feedback from form *****/ - Gbl.Test.Config.Feedback = TsR_GetFeedbackTypeFromForm (); + Gbl.Test.Config.Visibility = TsR_GetVisibilityFromForm (); /***** Update database *****/ DB_QueryREPLACE ("can not save configuration of tests", "REPLACE INTO tst_config" - " (CrsCod,Pluggable,Min,Def,Max,MinTimeNxtTstPerQst,Feedback)" + " (CrsCod,Pluggable,Min,Def,Max,MinTimeNxtTstPerQst,Visibility)" " VALUES" - " (%ld,'%s',%u,%u,%u,'%lu','%s')", + " (%ld,'%s',%u,%u,%u,'%lu',%u)", Gbl.Hierarchy.Crs.CrsCod, Tst_PluggableDB[Gbl.Test.Config.Pluggable], Gbl.Test.Config.Min,Gbl.Test.Config.Def,Gbl.Test.Config.Max, Gbl.Test.Config.MinTimeNxtTstPerQst, - TsR_FeedbackDB[Gbl.Test.Config.Feedback]); + Gbl.Test.Config.Visibility); /***** Show confirmation message *****/ Ale_ShowAlert (Ale_SUCCESS,Txt_The_test_configuration_has_been_updated); @@ -3534,18 +3499,16 @@ static void Tst_WriteTFAnsAssessTest (struct UsrData *UsrDat, /***** Write the user answer *****/ HTM_TD_Begin ("class=\"%s CM\"", - (Gbl.Test.Config.Feedback == TsR_FEEDBACK_EACH_GOOD_BAD || - Gbl.Test.Config.Feedback == TsR_FEEDBACK_FULL_FEEDBACK) ? - (AnsTF == row[1][0] ? "ANS_OK" : - "ANS_BAD") : - "ANS_0"); + (Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_CORRECT_ANSWER)) != 0 ? + (AnsTF == row[1][0] ? "ANS_OK" : + "ANS_BAD") : + "ANS_0"); Tst_WriteAnsTF (AnsTF); HTM_TD_End (); /***** Write the correct answer *****/ HTM_TD_Begin ("class=\"ANS_0 CM\""); - if (Gbl.Test.Config.Feedback == TsR_FEEDBACK_EACH_GOOD_BAD || - Gbl.Test.Config.Feedback == TsR_FEEDBACK_FULL_FEEDBACK) + if ((Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_CORRECT_ANSWER)) != 0) Tst_WriteAnsTF (row[1][0]); else HTM_Txt ("?"); @@ -3553,10 +3516,8 @@ static void Tst_WriteTFAnsAssessTest (struct UsrData *UsrDat, HTM_TR_End (); - /***** Write the mark *****/ - if (Gbl.Test.Config.Feedback == TsR_FEEDBACK_EACH_RESULT || - Gbl.Test.Config.Feedback == TsR_FEEDBACK_EACH_GOOD_BAD || - Gbl.Test.Config.Feedback == TsR_FEEDBACK_FULL_FEEDBACK) + /***** Write the score of this question *****/ + if ((Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_EACH_QST_SCORE)) != 0) { Tst_WriteScoreStart (2); if (AnsTF == '\0') // If user has omitted the answer @@ -3744,8 +3705,7 @@ static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat, /* Draw icon depending on user's answer */ if (AnswersUsr[Indexes[NumOpt]] == true) // This answer has been selected by the user { - if (Gbl.Test.Config.Feedback == TsR_FEEDBACK_EACH_GOOD_BAD || - Gbl.Test.Config.Feedback == TsR_FEEDBACK_FULL_FEEDBACK) + if ((Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_CORRECT_ANSWER)) != 0) { if (Gbl.Test.Answer.Options[Indexes[NumOpt]].Correct) { @@ -3773,8 +3733,7 @@ static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat, HTM_TD_Empty (1); /* Draw icon that indicates whether the answer is correct */ - if (Gbl.Test.Config.Feedback == TsR_FEEDBACK_EACH_GOOD_BAD || - Gbl.Test.Config.Feedback == TsR_FEEDBACK_FULL_FEEDBACK) + if ((Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_CORRECT_ANSWER)) != 0) { if (Gbl.Test.Answer.Options[Indexes[NumOpt]].Correct) { @@ -3808,7 +3767,7 @@ static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat, "TEST_MED_SHOW"); HTM_DIV_End (); - if (Gbl.Test.Config.Feedback == TsR_FEEDBACK_FULL_FEEDBACK) + if ((Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_CORRECT_ANSWER)) != 0) if (Gbl.Test.Answer.Options[Indexes[NumOpt]].Feedback) if (Gbl.Test.Answer.Options[Indexes[NumOpt]].Feedback[0]) { @@ -3823,9 +3782,7 @@ static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat, } /***** Write the total score of this question *****/ - if (Gbl.Test.Config.Feedback == TsR_FEEDBACK_EACH_RESULT || - Gbl.Test.Config.Feedback == TsR_FEEDBACK_EACH_GOOD_BAD || - Gbl.Test.Config.Feedback == TsR_FEEDBACK_FULL_FEEDBACK) + if ((Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_EACH_QST_SCORE)) != 0) { Tst_WriteScoreStart (4); if (*ScoreThisQst == 0.0) @@ -3883,7 +3840,7 @@ void Tst_GetChoiceAns (MYSQL_RES *mysql_res) /***** Copy answer feedback (row[2]) and convert it, that is in HTML, to rigorous HTML ******/ - if (Gbl.Test.Config.Feedback == TsR_FEEDBACK_FULL_FEEDBACK) + if ((Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_FEEDBACK_TEXT)) != 0) if (row[2]) if (row[2][0]) { @@ -4212,7 +4169,7 @@ static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat, Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false); /***** Copy answer feedback (row[2]) and convert it, that is in HTML, to rigorous HTML ******/ - if (Gbl.Test.Config.Feedback == TsR_FEEDBACK_FULL_FEEDBACK) + if ((Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_FEEDBACK_TEXT)) != 0) if (row[2]) if (row[2][0]) { @@ -4265,11 +4222,10 @@ static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat, } } HTM_TD_Begin ("class=\"%s CT\"", - (Gbl.Test.Config.Feedback == TsR_FEEDBACK_EACH_GOOD_BAD || - Gbl.Test.Config.Feedback == TsR_FEEDBACK_FULL_FEEDBACK) ? - (Correct ? "ANS_OK" : - "ANS_BAD") : - "ANS_0"); + (Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_CORRECT_ANSWER)) != 0 ? + (Correct ? "ANS_OK" : + "ANS_BAD") : + "ANS_0"); HTM_Txt (Gbl.Test.StrAnswersOneQst[NumQst]); } else // If user has omitted the answer @@ -4277,8 +4233,7 @@ static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat, HTM_TD_End (); /***** Write the correct answers *****/ - if (Gbl.Test.Config.Feedback == TsR_FEEDBACK_EACH_GOOD_BAD || - Gbl.Test.Config.Feedback == TsR_FEEDBACK_FULL_FEEDBACK) + if ((Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_CORRECT_ANSWER)) != 0) { HTM_TD_Begin ("class=\"CT\""); HTM_TABLE_BeginPadding (2); @@ -4301,7 +4256,7 @@ static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat, HTM_Txt (Gbl.Test.Answer.Options[NumOpt].Text); HTM_DIV_End (); - if (Gbl.Test.Config.Feedback == TsR_FEEDBACK_FULL_FEEDBACK) + if ((Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_FEEDBACK_TEXT)) != 0) if (Gbl.Test.Answer.Options[NumOpt].Feedback) if (Gbl.Test.Answer.Options[NumOpt].Feedback[0]) { @@ -4342,9 +4297,7 @@ static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat, } /***** Write the mark *****/ - if (Gbl.Test.Config.Feedback == TsR_FEEDBACK_EACH_RESULT || - Gbl.Test.Config.Feedback == TsR_FEEDBACK_EACH_GOOD_BAD || - Gbl.Test.Config.Feedback == TsR_FEEDBACK_FULL_FEEDBACK) + if ((Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_EACH_QST_SCORE)) != 0) { Tst_WriteScoreStart (4); if (!Gbl.Test.StrAnswersOneQst[NumQst][0]) // If user has omitted the answer @@ -4425,11 +4378,10 @@ static void Tst_WriteIntAnsAssessTest (struct UsrData *UsrDat, if (sscanf (Gbl.Test.StrAnswersOneQst[NumQst],"%ld",&IntAnswerUsr) == 1) { HTM_TD_Begin ("class=\"%s CM\"", - (Gbl.Test.Config.Feedback == TsR_FEEDBACK_EACH_GOOD_BAD || - Gbl.Test.Config.Feedback == TsR_FEEDBACK_FULL_FEEDBACK) ? - (IntAnswerUsr == IntAnswerCorr ? "ANS_OK" : - "ANS_BAD") : - "ANS_0"); + (Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_CORRECT_ANSWER)) != 0 ? + (IntAnswerUsr == IntAnswerCorr ? "ANS_OK" : + "ANS_BAD") : + "ANS_0"); HTM_Long (IntAnswerUsr); HTM_TD_End (); } @@ -4446,8 +4398,7 @@ static void Tst_WriteIntAnsAssessTest (struct UsrData *UsrDat, /***** Write the correct answer *****/ HTM_TD_Begin ("class=\"ANS_0 CM\""); - if (Gbl.Test.Config.Feedback == TsR_FEEDBACK_EACH_GOOD_BAD || - Gbl.Test.Config.Feedback == TsR_FEEDBACK_FULL_FEEDBACK) + if ((Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_CORRECT_ANSWER)) != 0) HTM_Long (IntAnswerCorr); else HTM_Txt ("?"); @@ -4471,9 +4422,7 @@ static void Tst_WriteIntAnsAssessTest (struct UsrData *UsrDat, } /***** Write the score *****/ - if (Gbl.Test.Config.Feedback == TsR_FEEDBACK_EACH_RESULT || - Gbl.Test.Config.Feedback == TsR_FEEDBACK_EACH_GOOD_BAD || - Gbl.Test.Config.Feedback == TsR_FEEDBACK_FULL_FEEDBACK) + if ((Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_EACH_QST_SCORE)) != 0) { Tst_WriteScoreStart (2); if (!Gbl.Test.StrAnswersOneQst[NumQst][0]) // If user has omitted the answer @@ -4568,12 +4517,11 @@ static void Tst_WriteFloatAnsAssessTest (struct UsrData *UsrDat, if (Gbl.Test.StrAnswersOneQst[NumQst][0]) // It's a correct floating point number { HTM_TD_Begin ("class=\"%s CM\"", - (Gbl.Test.Config.Feedback == TsR_FEEDBACK_EACH_GOOD_BAD || - Gbl.Test.Config.Feedback == TsR_FEEDBACK_FULL_FEEDBACK) ? - ((FloatAnsUsr >= FloatAnsCorr[0] && - FloatAnsUsr <= FloatAnsCorr[1]) ? "ANS_OK" : - "ANS_BAD") : - "ANS_0"); + (Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_CORRECT_ANSWER)) != 0 ? + ((FloatAnsUsr >= FloatAnsCorr[0] && + FloatAnsUsr <= FloatAnsCorr[1]) ? "ANS_OK" : + "ANS_BAD") : + "ANS_0"); HTM_Double (FloatAnsUsr); } else // Not a floating point number @@ -4588,8 +4536,7 @@ static void Tst_WriteFloatAnsAssessTest (struct UsrData *UsrDat, /***** Write the correct answer *****/ HTM_TD_Begin ("class=\"ANS_0 CM\""); - if (Gbl.Test.Config.Feedback == TsR_FEEDBACK_EACH_GOOD_BAD || - Gbl.Test.Config.Feedback == TsR_FEEDBACK_FULL_FEEDBACK) + if ((Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_CORRECT_ANSWER)) != 0) { HTM_Txt ("["); HTM_Double (FloatAnsCorr[0]); @@ -4620,9 +4567,7 @@ static void Tst_WriteFloatAnsAssessTest (struct UsrData *UsrDat, } /***** Write mark *****/ - if (Gbl.Test.Config.Feedback == TsR_FEEDBACK_EACH_RESULT || - Gbl.Test.Config.Feedback == TsR_FEEDBACK_EACH_GOOD_BAD || - Gbl.Test.Config.Feedback == TsR_FEEDBACK_FULL_FEEDBACK) + if ((Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_EACH_QST_SCORE)) != 0) { Tst_WriteScoreStart (2); if (!Gbl.Test.StrAnswersOneQst[NumQst][0]) // If user has omitted the answer diff --git a/swad_test.h b/swad_test.h index eca490ab6..0139b8879 100644 --- a/swad_test.h +++ b/swad_test.h @@ -83,7 +83,6 @@ struct Tst_Config unsigned Max; // Maximum number of questions unsigned long MinTimeNxtTstPerQst; unsigned Visibility; // One bit for each visibility item - TsR_Feedback_t Feedback; }; #define Tst_NUM_ANS_TYPES 6 diff --git a/swad_test_result.c b/swad_test_result.c index 0a079b0cb..603e439d2 100644 --- a/swad_test_result.c +++ b/swad_test_result.c @@ -43,46 +43,11 @@ /*****************************************************************************/ /***************************** Public constants ******************************/ /*****************************************************************************/ -/* -Visibilidad de resultados: -* Texto de preguntas y respuestas -* Texto de realimentación -* Respuestas correctas -* Puntuación de cada pregunta -* Puntuación total - -Visibility of results: -* Text of questions and answers -* Feedback text -* Correct answers -* Score of each question -* Total score -*/ - -// strings are limited to TsR_MAX_BYTES_FEEDBACK_TYPE bytes -const char *TsR_FeedbackXML[TsR_NUM_TYPES_FEEDBACK] = - { - [TsR_FEEDBACK_NOTHING ] = "nothing", - [TsR_FEEDBACK_TOTAL_RESULT ] = "totalResult", - [TsR_FEEDBACK_EACH_RESULT ] = "eachResult", - [TsR_FEEDBACK_EACH_GOOD_BAD] = "eachGoodBad", - [TsR_FEEDBACK_FULL_FEEDBACK] = "fullFeedback", - }; /*****************************************************************************/ /**************************** Private constants ******************************/ /*****************************************************************************/ -// Feedback to students in tests -const char *TsR_FeedbackDB[TsR_NUM_TYPES_FEEDBACK] = - { - [TsR_FEEDBACK_NOTHING ] = "nothing", // No feedback - [TsR_FEEDBACK_TOTAL_RESULT ] = "total_result", // Little - [TsR_FEEDBACK_EACH_RESULT ] = "each_result", // Medium - [TsR_FEEDBACK_EACH_GOOD_BAD] = "each_good_bad", // High - [TsR_FEEDBACK_FULL_FEEDBACK] = "full_feedback", // Maximum - }; - /*****************************************************************************/ /******************************* Private types *******************************/ /*****************************************************************************/ @@ -384,7 +349,7 @@ static void TsR_ShowTstResults (struct UsrData *UsrDat) case Rol_STD: ICanViewTest = ItsMe; ICanViewScore = ItsMe && - Gbl.Test.Config.Feedback != TsR_FEEDBACK_NOTHING; + (Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_TOTAL_SCORE)) != 0; break; case Rol_NET: case Rol_TCH: @@ -543,7 +508,7 @@ static void TsR_ShowTestResultsSummaryRow (bool ItsMe, { case Rol_STD: ICanViewTotalScore = ItsMe && - Gbl.Test.Config.Feedback != TsR_FEEDBACK_NOTHING; + (Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_TOTAL_SCORE)) != 0; break; case Rol_NET: case Rol_TCH: @@ -642,7 +607,7 @@ void TsR_ShowOneTstResult (void) /***** Get test result data *****/ TsR_GetTestResultDataByTstCod (TstCod,&TstTimeUTC, &NumQstsNotBlank,&TotalScore); - Gbl.Test.Config.Feedback = TsR_FEEDBACK_FULL_FEEDBACK; // Initialize feedback to maximum + Gbl.Test.Config.Visibility = TsR_MAX_VISIBILITY; /***** Check if I can view this test result *****/ ItsMe = Usr_ItsMe (Gbl.Usrs.Other.UsrDat.UsrCod); @@ -653,7 +618,7 @@ void TsR_ShowOneTstResult (void) if (ItsMe) { Tst_GetConfigTstFromDB (); // To get feedback type - ICanViewScore = Gbl.Test.Config.Feedback != TsR_FEEDBACK_NOTHING; + ICanViewScore = (Gbl.Test.Config.Visibility & (1 << TsR_VISIBLE_TOTAL_SCORE)) != 0; } else ICanViewScore = false; @@ -1157,13 +1122,41 @@ void TsR_RemoveCrsTestResults (long CrsCod) /*********************** Get type of feedback from form **********************/ /*****************************************************************************/ -TsR_Feedback_t TsR_GetFeedbackTypeFromForm (void) +unsigned TsR_GetVisibilityFromForm (void) { - return (TsR_Feedback_t) - Par_GetParToUnsignedLong ("Feedback", - 0, - TsR_NUM_TYPES_FEEDBACK - 1, - (unsigned long) TsR_FEEDBACK_DEFAULT); + size_t MaxSizeListVisibilitySelected; + char *StrVisibilitySelected; + const char *Ptr; + char UnsignedStr[Cns_MAX_DECIMAL_DIGITS_UINT + 1]; + unsigned UnsignedNum; + TsR_ResultVisibility_t VisibilityItem; + unsigned Visibility = 0; // Nothing selected + + /***** Allocate memory for list of attendance events selected *****/ + MaxSizeListVisibilitySelected = TsR_NUM_ITEMS_VISIBILITY * (Cns_MAX_DECIMAL_DIGITS_UINT + 1); + if ((StrVisibilitySelected = (char *) malloc (MaxSizeListVisibilitySelected + 1)) == NULL) + Lay_NotEnoughMemoryExit (); + + /***** Get parameter multiple with list of visibility items selected *****/ + Par_GetParMultiToText ("Visibility",StrVisibilitySelected,MaxSizeListVisibilitySelected); + + /***** Set which attendance events will be shown as selected (checkboxes on) *****/ + if (StrVisibilitySelected[0]) // There are events selected + for (Ptr = StrVisibilitySelected; + *Ptr; + ) + { + /* Get next visibility item selected */ + Par_GetNextStrUntilSeparParamMult (&Ptr,UnsignedStr,Cns_MAX_DECIMAL_DIGITS_UINT); + if (sscanf (UnsignedStr,"%u",&UnsignedNum) == 1) + if (UnsignedNum < TsR_NUM_ITEMS_VISIBILITY) + { + VisibilityItem = (TsR_ResultVisibility_t) UnsignedNum; + Visibility |= (1 << VisibilityItem); + } + } + + return Visibility; } /*****************************************************************************/ diff --git a/swad_test_result.h b/swad_test_result.h index 1a58a932b..59d5eb753 100644 --- a/swad_test_result.h +++ b/swad_test_result.h @@ -40,21 +40,7 @@ /*****************************************************************************/ /******************************* Public types ********************************/ /*****************************************************************************/ -/* -Visibilidad de resultados: -* Texto de preguntas y respuestas -* Texto de realimentación -* Respuestas correctas -* Puntuación de cada pregunta -* Puntuación total -Visibility of results: -* Text of questions and answers -* Feedback text -* Correct answers -* Score of each question -* Total score -*/ #define TsR_NUM_ITEMS_VISIBILITY 5 typedef enum { @@ -64,18 +50,8 @@ typedef enum TsR_VISIBLE_EACH_QST_SCORE = 3, // Score of each question TsR_VISIBLE_TOTAL_SCORE = 4, // Total score } TsR_ResultVisibility_t; -#define TsR_VISIBILITY_DEFAULT ((1 << TsR_NUM_ITEMS_VISIBILITY) - 1) // All visible - -#define TsR_NUM_TYPES_FEEDBACK 5 -typedef enum - { - TsR_FEEDBACK_NOTHING = 0, - TsR_FEEDBACK_TOTAL_RESULT = 1, - TsR_FEEDBACK_EACH_RESULT = 2, - TsR_FEEDBACK_EACH_GOOD_BAD = 3, - TsR_FEEDBACK_FULL_FEEDBACK = 4, - } TsR_Feedback_t; -#define TsR_FEEDBACK_DEFAULT TsR_FEEDBACK_FULL_FEEDBACK +#define TsR_MAX_VISIBILITY ((1 << TsR_NUM_ITEMS_VISIBILITY) - 1) // All visible +#define TsR_VISIBILITY_DEFAULT TsR_MAX_VISIBILITY /*****************************************************************************/ /***************************** Public prototypes *****************************/ @@ -96,8 +72,7 @@ void TsR_RemoveTestResultsMadeByUsrInAllCrss (long UsrCod); void TsR_RemoveTestResultsMadeByUsrInCrs (long UsrCod,long CrsCod); void TsR_RemoveCrsTestResults (long CrsCod); -TsR_Feedback_t TsR_GetFeedbackTypeFromForm (void); - +unsigned TsR_GetVisibilityFromForm (void); void TsR_PutVisibilityCheckboxes (unsigned SelectedVisibility); #endif diff --git a/swad_text.c b/swad_text.c index f58d1bc7b..f59646f44 100644 --- a/swad_text.c +++ b/swad_text.c @@ -11787,27 +11787,6 @@ const char *Txt_Feedback = "Feedback"; #endif -const char *Txt_Feedback_to_students = -#if L==1 // ca - "Realimentación para estudiantes"; // Necessita traduccio -#elif L==2 // de - "Feedback an die Studenten"; -#elif L==3 // en - "Feedback to students"; -#elif L==4 // es - "Realimentación para estudiantes"; -#elif L==5 // fr - "Feedback pour les étudiants"; -#elif L==6 // gn - "Realimentación para estudiantes"; // Okoteve traducción -#elif L==7 // it - "Feedback per gli studenti"; -#elif L==8 // pl - "Opinie studentów"; -#elif L==9 // pt - "Feedback para estudantes"; -#endif - const char *Txt_Field_BR_name = #if L==1 // ca "Nombre
del campo"; // Necessita traduccio @@ -51241,114 +51220,6 @@ const char *Txt_TST_STR_ANSWER_TYPES[Tst_NUM_ANS_TYPES] = #endif }; -const char *Txt_TST_STR_FEEDBACK[TsR_NUM_TYPES_FEEDBACK] = - { - [TsR_FEEDBACK_NOTHING] = -#if L==1 // ca - "Ninguna realimentación" // Necessita traduccio -#elif L==2 // de - "Keine Feedback" -#elif L==3 // en - "No feedback" -#elif L==4 // es - "Ninguna realimentación" -#elif L==5 // fr - "Pas de feedback" -#elif L==6 // gn - "Ninguna realimentación" // Okoteve traducción -#elif L==7 // it - "Nessun feedback" -#elif L==8 // pl - "No feedback" // Potrzebujesz tlumaczenie -#elif L==9 // pt - "Nenhum feedback" -#endif - , - [TsR_FEEDBACK_TOTAL_RESULT] = -#if L==1 // ca - "Poca: solo puntuación total" // Necessita traduccio -#elif L==2 // de - "Kleine: nur die Gesamtnote" -#elif L==3 // en - "Little: only the total score" -#elif L==4 // es - "Poca: solo puntuación total" -#elif L==5 // fr - "Petit: seul le note total" -#elif L==6 // gn - "Poca: solo puntuación total" // Okoteve traducción -#elif L==7 // it - "Poco: solo il punteggio totale" -#elif L==8 // pl - "Little: only the total score" // Potrzebujesz tlumaczenie -#elif L==9 // pt - "Pouco: apenas a pontuação total" -#endif - , - [TsR_FEEDBACK_EACH_RESULT] = -#if L==1 // ca - "Media: puntuación de cada pregunta" // Necessita traduccio -#elif L==2 // de - "Medium: Ergebnisse der einzelnen Frage" -#elif L==3 // en - "Medium: result of each question" -#elif L==4 // es - "Media: puntuación de cada pregunta" -#elif L==5 // fr - "Medium: le résultat de chaque question" -#elif L==6 // gn - "Media: puntuación de cada pregunta" // Okoteve traducción -#elif L==7 // it - "Medio: risultato di ogni domanda" -#elif L==8 // pl - "Medium: result of each question" // Potrzebujesz tlumaczenie -#elif L==9 // pt - "Médio: pontuação de cada questão" -#endif - , - [TsR_FEEDBACK_EACH_GOOD_BAD] = -#if L==1 // ca - "Alta: respuesta correcta en cada pregunta" // Necessita traduccio -#elif L==2 // de - "Maximale Details: die richtige Antwort für jede Frage" -#elif L==3 // en - "High: correct answer for each question" -#elif L==4 // es - "Alta: respuesta correcta en cada pregunta" -#elif L==5 // fr - "Haute: bonne réponse pour chaque question" -#elif L==6 // gn - "Alta: respuesta correcta en cada pregunta" // Okoteve traducción -#elif L==7 // it - "Alto: la corretta risposta per ogni domanda" -#elif L==8 // pl - "High: correct answer for each question" // Potrzebujesz tlumaczenie -#elif L==9 // pt - "Alto: resposta correta para cada questão" -#endif - , - [TsR_FEEDBACK_FULL_FEEDBACK] = -#if L==1 // ca - "Máxima: mostrar texto de realimentación" // Necessita traduccio -#elif L==2 // de - "Maximale: zeigen Feedback text" -#elif L==3 // en - "Maximum: show feedback text" -#elif L==4 // es - "Máxima: mostrar texto de realimentación" -#elif L==5 // fr - "Maximum: afficher le texte de feedback" -#elif L==6 // gn - "Máxima: mostrar texto de realimentación" // Okoteve traducción -#elif L==7 // it - "Massimo: visualizzare il testo de feedback" -#elif L==8 // pl - "Maximum: show feedback text" // Potrzebujesz tlumaczenie -#elif L==9 // pt - "Máximo: mostrar o texto de feedback" -#endif - }; - const char *Txt_TST_STR_ORDER_FULL[Tst_NUM_TYPES_ORDER_QST] = { [Tst_ORDER_STEM] =