diff --git a/swad_HTML.c b/swad_HTML.c index f13d586b1..b29741e51 100644 --- a/swad_HTML.c +++ b/swad_HTML.c @@ -1779,7 +1779,9 @@ static void HTM_SPTxt (const char *Txt) void HTM_Txt (const char *Txt) { - fputs (Txt,Gbl.F.Out); + if (Txt) + if (Txt[0]) + fputs (Txt,Gbl.F.Out); } void HTM_TxtColonNBSP (const char *Txt) diff --git a/swad_changelog.h b/swad_changelog.h index cb6b3ad09..b5bd997da 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -556,10 +556,16 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - * En OpenSWAD: ps2pdf source.ps destination.pdf */ -#define Log_PLATFORM_VERSION "SWAD 19.248.4 (2020-05-25)" +#define Log_PLATFORM_VERSION "SWAD 19.249 (2020-06-17)" #define CSS_FILE "swad19.238.2.css" #define JS_FILE "swad19.246.1.js" /* +TODO: Encarnación Hidalgo Tenorio: Antonio, ¿podría @swad_ugr mandar una notificación cuando el alumnado ha mandado su tarea? + Se trataría de añadir un par de líneas "Nuevos archivos en actividades", "Nuevos archivos en otros trabajos". +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. + + Version 19.249: Jun 17, 2020 Fixed bug in exams and matches. + Code refactoring in test questions. (302786 lines) Version 19.248.4: May 30, 2020 Code refactoring in selection of questions. (302867 lines) Version 19.248.3: May 30, 2020 Selection of all questions to add to a game. (302863 lines) Version 19.248.2: May 30, 2020 Selection of all questions to add to a set. Suggested by Nuria Torres Rosell. (302854 lines) diff --git a/swad_exam_print.c b/swad_exam_print.c index 04f00236a..eb04181d3 100644 --- a/swad_exam_print.c +++ b/swad_exam_print.c @@ -84,25 +84,27 @@ static void ExaPrn_ShowTableWithQstsToFill (struct Exa_Exams *Exams, const struct ExaPrn_Print *Print); static void ExaPrn_WriteQstAndAnsToFill (const struct ExaPrn_Print *Print, unsigned NumQst, - const struct Tst_Question *Question); + struct Tst_Question *Question); static void ExaPrn_WriteAnswersToFill (const struct ExaPrn_Print *Print, unsigned NumQst, - const struct Tst_Question *Question); + struct Tst_Question *Question); //----------------------------------------------------------------------------- - static void ExaPrn_WriteIntAnsToFill (const struct ExaPrn_Print *Print, - unsigned NumQst); -static void ExaPrn_WriteFloAnsToFill (const struct ExaPrn_Print *Print, - unsigned NumQst); + unsigned NumQst, + __attribute__((unused)) struct Tst_Question *Question); +static void ExaPrn_WriteFltAnsToFill (const struct ExaPrn_Print *Print, + unsigned NumQst, + __attribute__((unused)) struct Tst_Question *Question); static void ExaPrn_WriteTF_AnsToFill (const struct ExaPrn_Print *Print, - unsigned NumQst); + unsigned NumQst, + __attribute__((unused)) struct Tst_Question *Question); static void ExaPrn_WriteChoAnsToFill (const struct ExaPrn_Print *Print, unsigned NumQst, - const struct Tst_Question *Question); + struct Tst_Question *Question); static void ExaPrn_WriteTxtAnsToFill (const struct ExaPrn_Print *Print, - unsigned NumQst); - + unsigned NumQst, + __attribute__((unused)) struct Tst_Question *Question); //----------------------------------------------------------------------------- static void ExaPrn_WriteJSToUpdateExamPrint (const struct ExaPrn_Print *Print, @@ -117,7 +119,6 @@ static void ExaPrn_ComputeScoreAndStoreQuestionOfPrint (struct ExaPrn_Print *Pri unsigned NumQst); //----------------------------------------------------------------------------- - static void ExaPrn_GetCorrectAndComputeIntAnsScore (struct TstPrn_PrintedQuestion *PrintedQuestion, struct Tst_Question *Question); static void ExaPrn_GetCorrectAndComputeFltAnsScore (struct TstPrn_PrintedQuestion *PrintedQuestion, @@ -128,15 +129,12 @@ static void ExaPrn_GetCorrectAndComputeChoAnsScore (struct TstPrn_PrintedQuestio struct Tst_Question *Question); static void ExaPrn_GetCorrectAndComputeTxtAnsScore (struct TstPrn_PrintedQuestion *PrintedQuestion, struct Tst_Question *Question); - //----------------------------------------------------------------------------- - static void ExaPrn_GetCorrectIntAnswerFromDB (struct Tst_Question *Question); static void ExaPrn_GetCorrectFltAnswerFromDB (struct Tst_Question *Question); static void ExaPrn_GetCorrectTF_AnswerFromDB (struct Tst_Question *Question); static void ExaPrn_GetCorrectChoAnswerFromDB (struct Tst_Question *Question); static void ExaPrn_GetCorrectTxtAnswerFromDB (struct Tst_Question *Question); - //----------------------------------------------------------------------------- static void ExaPrn_GetAnswerFromDB (struct ExaPrn_Print *Print,long QstCod, @@ -702,7 +700,7 @@ static void ExaPrn_ShowTableWithQstsToFill (struct Exa_Exams *Exams, static void ExaPrn_WriteQstAndAnsToFill (const struct ExaPrn_Print *Print, unsigned NumQst, - const struct Tst_Question *Question) + struct Tst_Question *Question) { static struct ExaSet_Set CurrentSet = { @@ -764,30 +762,22 @@ static void ExaPrn_WriteQstAndAnsToFill (const struct ExaPrn_Print *Print, static void ExaPrn_WriteAnswersToFill (const struct ExaPrn_Print *Print, unsigned NumQst, - const struct Tst_Question *Question) + struct Tst_Question *Question) { - /***** Write answer depending on type *****/ - switch (Question->Answer.Type) - { - case Tst_ANS_INT: - ExaPrn_WriteIntAnsToFill (Print,NumQst); - break; - case Tst_ANS_FLOAT: - ExaPrn_WriteFloAnsToFill (Print,NumQst); - break; - case Tst_ANS_TRUE_FALSE: - ExaPrn_WriteTF_AnsToFill (Print,NumQst); - break; - case Tst_ANS_UNIQUE_CHOICE: - case Tst_ANS_MULTIPLE_CHOICE: - ExaPrn_WriteChoAnsToFill (Print,NumQst,Question); - break; - case Tst_ANS_TEXT: - ExaPrn_WriteTxtAnsToFill (Print,NumQst); - break; - default: - break; - } + void (*ExaPrn_WriteAnsToFill[Tst_NUM_ANS_TYPES]) (const struct ExaPrn_Print *Print, + unsigned NumQst, + struct Tst_Question *Question) = + { + [Tst_ANS_INT ] = ExaPrn_WriteIntAnsToFill, + [Tst_ANS_FLOAT ] = ExaPrn_WriteFltAnsToFill, + [Tst_ANS_TRUE_FALSE ] = ExaPrn_WriteTF_AnsToFill, + [Tst_ANS_UNIQUE_CHOICE ] = ExaPrn_WriteChoAnsToFill, + [Tst_ANS_MULTIPLE_CHOICE] = ExaPrn_WriteChoAnsToFill, + [Tst_ANS_TEXT ] = ExaPrn_WriteTxtAnsToFill, + }; + + /***** Write answers *****/ + ExaPrn_WriteAnsToFill[Question->Answer.Type] (Print,NumQst,Question); } /*****************************************************************************/ @@ -795,7 +785,8 @@ static void ExaPrn_WriteAnswersToFill (const struct ExaPrn_Print *Print, /*****************************************************************************/ static void ExaPrn_WriteIntAnsToFill (const struct ExaPrn_Print *Print, - unsigned NumQst) + unsigned NumQst, + __attribute__((unused)) struct Tst_Question *Question) { char Id[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x" @@ -815,8 +806,9 @@ static void ExaPrn_WriteIntAnsToFill (const struct ExaPrn_Print *Print, /****************** Write float answer when seeing a test ********************/ /*****************************************************************************/ -static void ExaPrn_WriteFloAnsToFill (const struct ExaPrn_Print *Print, - unsigned NumQst) +static void ExaPrn_WriteFltAnsToFill (const struct ExaPrn_Print *Print, + unsigned NumQst, + __attribute__((unused)) struct Tst_Question *Question) { char Id[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x" @@ -837,7 +829,8 @@ static void ExaPrn_WriteFloAnsToFill (const struct ExaPrn_Print *Print, /*****************************************************************************/ static void ExaPrn_WriteTF_AnsToFill (const struct ExaPrn_Print *Print, - unsigned NumQst) + unsigned NumQst, + __attribute__((unused)) struct Tst_Question *Question) { extern const char *Txt_TF_QST[2]; char Id[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x" @@ -864,13 +857,16 @@ static void ExaPrn_WriteTF_AnsToFill (const struct ExaPrn_Print *Print, static void ExaPrn_WriteChoAnsToFill (const struct ExaPrn_Print *Print, unsigned NumQst, - const struct Tst_Question *Question) + struct Tst_Question *Question) { unsigned NumOpt; unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION]; // Indexes of all answers of this question bool UsrAnswers[Tst_MAX_OPTIONS_PER_QUESTION]; char Id[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x" + /***** Change format of answers text *****/ + Tst_ChangeFormatAnswersText (Question); + /***** Get indexes for this question from string *****/ TstPrn_GetIndexesFromStr (Print->PrintedQuestions[NumQst].StrIndexes,Indexes); @@ -934,7 +930,8 @@ static void ExaPrn_WriteChoAnsToFill (const struct ExaPrn_Print *Print, /*****************************************************************************/ static void ExaPrn_WriteTxtAnsToFill (const struct ExaPrn_Print *Print, - unsigned NumQst) + unsigned NumQst, + __attribute__((unused)) struct Tst_Question *Question) { char Id[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x" @@ -1354,14 +1351,14 @@ static void ExaPrn_GetCorrectTxtAnswerFromDB (struct Tst_Question *Question) /* Abort on error */ Ale_ShowAlertsAndExit (); - /***** Copy answer text (row[0]) and convert it, that is in HTML, to rigorous HTML ******/ + /***** Copy answer text (row[0]) ******/ Str_Copy (Question->Answer.Options[NumOpt].Text,row[0], Tst_MAX_BYTES_ANSWER_OR_FEEDBACK); - Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML, - Question->Answer.Options[NumOpt].Text, - Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false); } + /***** Change format of answers text *****/ + Tst_ChangeFormatAnswersText (Question); + /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); } diff --git a/swad_exam_set.c b/swad_exam_set.c index 1cb84e23c..57c1a49d5 100644 --- a/swad_exam_set.c +++ b/swad_exam_set.c @@ -123,7 +123,7 @@ static void ExaSet_ListOneOrMoreQuestionsForEdition (struct Exa_Exams *Exams, unsigned NumQsts, MYSQL_RES *mysql_res, bool ICanEditQuestions); -static void ExaSet_ListQuestionForEdition (const struct Tst_Question *Question, +static void ExaSet_ListQuestionForEdition (struct Tst_Question *Question, unsigned QstInd,const char *Anchor); static void ExaSet_AllocateListSelectedQuestions (struct Exa_Exams *Exams); @@ -1540,7 +1540,7 @@ void ExaSet_GetAnswersQst (struct Tst_Question *Question,MYSQL_RES **mysql_res, /********************* List question in set for edition **********************/ /*****************************************************************************/ -static void ExaSet_ListQuestionForEdition (const struct Tst_Question *Question, +static void ExaSet_ListQuestionForEdition (struct Tst_Question *Question, unsigned QstInd,const char *Anchor) { /***** Number of question and answer type (row[1]) *****/ diff --git a/swad_match.c b/swad_match.c index 29dabe166..035405560 100644 --- a/swad_match.c +++ b/swad_match.c @@ -200,7 +200,7 @@ static void Mch_PutIfAnswered (const struct Mch_Match *Match,bool Answered); static void Mch_PutIconToRemoveMyAnswer (const struct Mch_Match *Match); static void Mch_ShowQuestionAndAnswersTch (const struct Mch_Match *Match); static void Mch_WriteAnswersMatchResult (const struct Mch_Match *Match, - const struct Tst_Question *Question, + struct Tst_Question *Question, const char *Class,bool ShowResult); static bool Mch_ShowQuestionAndAnswersStd (const struct Mch_Match *Match, const struct Mch_UsrAnswer *UsrAnswer, @@ -3078,7 +3078,7 @@ static void Mch_ShowQuestionAndAnswersTch (const struct Mch_Match *Match) /*****************************************************************************/ static void Mch_WriteAnswersMatchResult (const struct Mch_Match *Match, - const struct Tst_Question *Question, + struct Tst_Question *Question, const char *Class,bool ShowResult) { /***** Write answer depending on type *****/ @@ -3095,7 +3095,7 @@ static void Mch_WriteAnswersMatchResult (const struct Mch_Match *Match, /*****************************************************************************/ void Mch_WriteChoiceAnsViewMatch (const struct Mch_Match *Match, - const struct Tst_Question *Question, + struct Tst_Question *Question, const char *Class,bool ShowResult) { unsigned NumOpt; @@ -3107,6 +3107,9 @@ void Mch_WriteChoiceAnsViewMatch (const struct Mch_Match *Match, /***** Get number of users who have answered this question from database *****/ NumRespondersQst = Mch_GetNumUsrsWhoAnsweredQst (Match->MchCod,Match->Status.QstInd); + /***** Change format of answers text *****/ + Tst_ChangeFormatAnswersText (Question); + /***** Get indexes for this question in match *****/ Mch_GetIndexes (Match->MchCod,Match->Status.QstInd,Indexes); @@ -3135,13 +3138,7 @@ void Mch_WriteChoiceAnsViewMatch (const struct Mch_Match *Match, /***** Write the option text and the result *****/ HTM_TD_Begin ("class=\"LT\""); HTM_LABEL_Begin ("for=\"Ans%06u_%u\" class=\"%s\"",Match->Status.QstInd,NumOpt,Class); - - /* Convert text, that is in HTML, to rigorous HTML */ - Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML, - Question->Answer.Options[NumOpt].Text, - Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false); HTM_Txt (Question->Answer.Options[Indexes[NumOpt]].Text); - HTM_LABEL_End (); Med_ShowMedia (&Question->Answer.Options[Indexes[NumOpt]].Media, "TEST_MED_SHOW_CONT", diff --git a/swad_match.h b/swad_match.h index 686c71f4a..f9ebf2518 100644 --- a/swad_match.h +++ b/swad_match.h @@ -128,7 +128,7 @@ unsigned Mch_GetNumUnfinishedMchsInGame (long GamCod); bool Mch_CheckIfICanPlayThisMatchBasedOnGrps (const struct Mch_Match *Match); void Mch_WriteChoiceAnsViewMatch (const struct Mch_Match *Match, - const struct Tst_Question *Question, + struct Tst_Question *Question, const char *Class,bool ShowResult); bool Mch_RegisterMeAsPlayerInMatch (struct Mch_Match *Match); diff --git a/swad_test.c b/swad_test.c index 0b52e0ba0..edb0b3e79 100644 --- a/swad_test.c +++ b/swad_test.c @@ -100,13 +100,6 @@ const char *Tst_StrAnswerTypesDB[Tst_NUM_ANS_TYPES] = /******************************* Private types *******************************/ /*****************************************************************************/ -#define Tst_NUM_REQUEST_OR_CONFIRM 2 -typedef enum - { - Tst_REQUEST, - Tst_CONFIRM, - } Tst_RequestOrConfirm_t; - /*****************************************************************************/ /************** External global variables from others modules ****************/ /*****************************************************************************/ @@ -126,18 +119,10 @@ static void Tst_TstDestructor (struct Tst_Test *Test); static void Tst_ShowFormRequestTest (struct Tst_Test *Test); -static void Tst_PutCheckBoxAllowTeachers (bool AllowTeachers); - static void TstPrn_GetAnswersFromForm (struct TstPrn_Print *Print); static bool Tst_CheckIfNextTstAllowed (void); static unsigned Tst_GetNumExamsGeneratedByMe (void); -static void Tst_ShowTestPrintToFillIt (struct TstPrn_Print *Print, - unsigned NumExamsGeneratedByMe, - Tst_RequestOrConfirm_t RequestOrConfirm); -static void TstPrn_WriteQstAndAnsToFill (struct TstPrn_PrintedQuestion *PrintedQuestion, - unsigned NumQst, - const struct Tst_Question *Question); static void Tst_PutFormToEditQstMedia (const struct Media *Media,int NumMediaInForm, bool OptionsDisabled); @@ -180,34 +165,12 @@ static void Tst_PutCheckboxToSelectAllQuestions (void); static void Tst_WriteQuestionRowForSelection (unsigned NumQst, struct Tst_Question *Question); -static void TstPrn_WriteAnswersToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion, - unsigned NumQst, - const struct Tst_Question *Question); - //----------------------------------------------------------------------------- -static void Tst_WriteIntAnsBank (const struct Tst_Question *Question); -static void Tst_WriteFltAnsBank (const struct Tst_Question *Question); -static void Tst_WriteTF_AnsBank (const struct Tst_Question *Question); -static void Tst_WriteChoAnsBank (const struct Tst_Question *Question); - -//----------------------------------------------------------------------------- - -static void TstPrn_WriteIntAnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion, - unsigned NumQst, - __attribute__((unused)) const struct Tst_Question *Question); -static void TstPrn_WriteFltAnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion, - unsigned NumQst, - __attribute__((unused)) const struct Tst_Question *Question); -static void TstPrn_WriteTF_AnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion, - unsigned NumQst, - __attribute__((unused)) const struct Tst_Question *Question); -static void TstPrn_WriteChoAnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion, - unsigned NumQst, - const struct Tst_Question *Question); -static void TstPrn_WriteTxtAnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion, - unsigned NumQst, - __attribute__((unused)) const struct Tst_Question *Question); +static void Tst_WriteIntAnsBank (struct Tst_Question *Question); +static void Tst_WriteFltAnsBank (struct Tst_Question *Question); +static void Tst_WriteTF_AnsBank (struct Tst_Question *Question); +static void Tst_WriteChoAnsBank (struct Tst_Question *Question); //----------------------------------------------------------------------------- @@ -428,7 +391,7 @@ void Tst_ShowNewTest (void) false); // Don't update question score /***** Show test exam to be answered *****/ - Tst_ShowTestPrintToFillIt (&Print,NumExamsGeneratedByMe,Tst_REQUEST); + TstPrn_ShowTestPrintToFillIt (&Print,NumExamsGeneratedByMe,TstPrn_REQUEST); /***** Update date-time of my next allowed access to test *****/ if (Gbl.Usrs.Me.Role.Logged == Rol_STD) @@ -448,27 +411,6 @@ void Tst_ShowNewTest (void) Tst_TstDestructor (&Test); } -/*****************************************************************************/ -/************* Put checkbox to allow teachers to see test exam ***************/ -/*****************************************************************************/ - -static void Tst_PutCheckBoxAllowTeachers (bool AllowTeachers) - { - extern const char *The_ClassFormInBox[The_NUM_THEMES]; - extern const char *Txt_Allow_teachers_to_consult_this_test; - - /***** Test exam will be available for teachers? *****/ - HTM_DIV_Begin ("class=\"CM\""); - HTM_LABEL_Begin ("class=\"%s\"",The_ClassFormInBox[Gbl.Prefs.Theme]); - HTM_INPUT_CHECKBOX ("AllowTchs",HTM_DONT_SUBMIT_ON_CHANGE, - "value=\"Y\"%s", - AllowTeachers ? " checked=\"checked\"" : // Teachers can see test exam - ""); - HTM_TxtF (" %s",Txt_Allow_teachers_to_consult_this_test); - HTM_LABEL_End (); - HTM_DIV_End (); - } - /*****************************************************************************/ /** Receive the draft of a test exam already (total or partially) answered ***/ /*****************************************************************************/ @@ -517,7 +459,7 @@ void Tst_ReceiveTestDraft (void) Ale_ShowAlert (Ale_WARNING,Txt_Please_review_your_answers_before_submitting_the_exam); /* Show the same test exam to be answered */ - Tst_ShowTestPrintToFillIt (&Print,NumTst,Tst_CONFIRM); + TstPrn_ShowTestPrintToFillIt (&Print,NumTst,TstPrn_CONFIRM); } } @@ -739,92 +681,6 @@ static unsigned Tst_GetNumExamsGeneratedByMe (void) return NumExamsGeneratedByMe; } -/*****************************************************************************/ -/****************** Show a test exam print to be answered ********************/ -/*****************************************************************************/ - -static void Tst_ShowTestPrintToFillIt (struct TstPrn_Print *Print, - unsigned NumExamsGeneratedByMe, - Tst_RequestOrConfirm_t RequestOrConfirm) - { - extern const char *Hlp_ASSESSMENT_Tests; - extern const char *Txt_Test; - extern const char *Txt_Continue; - extern const char *Txt_Send; - unsigned NumQst; - struct Tst_Question Question; - static const Act_Action_t Action[Tst_NUM_REQUEST_OR_CONFIRM] = - { - [Tst_REQUEST] = ActReqAssTst, - [Tst_CONFIRM] = ActAssTst, - }; - - /***** Begin box *****/ - Box_BoxBegin (NULL,Txt_Test, - NULL,NULL, - Hlp_ASSESSMENT_Tests,Box_NOT_CLOSABLE); - Lay_WriteHeaderClassPhoto (false,false, - Gbl.Hierarchy.Ins.InsCod, - Gbl.Hierarchy.Deg.DegCod, - Gbl.Hierarchy.Crs.CrsCod); - - if (Print->NumQsts) - { - /***** Begin form *****/ - Frm_StartForm (Action[RequestOrConfirm]); - TstPrn_PutParamPrnCod (Print->PrnCod); - Par_PutHiddenParamUnsigned (NULL,"NumTst",NumExamsGeneratedByMe); - - /***** Begin table *****/ - HTM_TABLE_BeginWideMarginPadding (10); - - /***** Write one row for each question *****/ - for (NumQst = 0; - NumQst < Print->NumQsts; - NumQst++) - { - Gbl.RowEvenOdd = NumQst % 2; - - /* Create test question */ - Tst_QstConstructor (&Question); - Question.QstCod = Print->PrintedQuestions[NumQst].QstCod; - - /* Show question */ - if (!Tst_GetQstDataFromDB (&Question)) // Question exists - Lay_ShowErrorAndExit ("Wrong question."); - - /* Write question and answers */ - TstPrn_WriteQstAndAnsToFill (&Print->PrintedQuestions[NumQst],NumQst,&Question); - - /* Destroy test question */ - Tst_QstDestructor (&Question); - } - - /***** End table *****/ - HTM_TABLE_End (); - - /***** End form *****/ - switch (RequestOrConfirm) - { - case Tst_REQUEST: - /* Send button */ - Btn_PutConfirmButton (Txt_Continue); - break; - case Tst_CONFIRM: - /* Will the test exam be visible by teachers? */ - Tst_PutCheckBoxAllowTeachers (true); - - /* Send button */ - Btn_PutCreateButton (Txt_Send); - break; - } - Frm_EndForm (); - } - - /***** End box *****/ - Box_BoxEnd (); - } - /*****************************************************************************/ /************************** Show list of test tags ***************************/ /*****************************************************************************/ @@ -854,51 +710,11 @@ void Tst_ShowTagList (unsigned NumTags,MYSQL_RES *mysql_res) HTM_Txt (Txt_no_tags); } -/*****************************************************************************/ -/********** Write a row of a test, with one question and its answer **********/ -/*****************************************************************************/ - -static void TstPrn_WriteQstAndAnsToFill (struct TstPrn_PrintedQuestion *PrintedQuestion, - unsigned NumQst, - const struct Tst_Question *Question) - { - /***** Begin row *****/ - HTM_TR_Begin (NULL); - - /***** Number of question and answer type *****/ - HTM_TD_Begin ("class=\"RT COLOR%u\"",Gbl.RowEvenOdd); - Tst_WriteNumQst (NumQst + 1); - Tst_WriteAnswerType (Question->Answer.Type); - HTM_TD_End (); - - /***** Stem, media and answers *****/ - HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd); - - /* Write parameter with question code */ - Tst_WriteParamQstCod (NumQst,Question->QstCod); - - /* Stem */ - Tst_WriteQstStem (Question->Stem,"TEST_EXA",true); - - /* Media */ - Med_ShowMedia (&Question->Media, - "TEST_MED_SHOW_CONT", - "TEST_MED_SHOW"); - - /* Answers */ - TstPrn_WriteAnswersToFill (PrintedQuestion,NumQst,Question); - - HTM_TD_End (); - - /***** End row *****/ - HTM_TR_End (); - } - /*****************************************************************************/ /********************* List game question for edition ************************/ /*****************************************************************************/ -void Tst_ListQuestionForEdition (const struct Tst_Question *Question, +void Tst_ListQuestionForEdition (struct Tst_Question *Question, unsigned QstInd,bool QuestionExists, const char *Anchor) { @@ -2911,13 +2727,48 @@ void Tst_GetAnswersQst (struct Tst_Question *Question,MYSQL_RES **mysql_res, Ale_ShowAlert (Ale_ERROR,"Error when getting answers of a question."); } +/*****************************************************************************/ +/***************** Change format of answers text / feedback ******************/ +/*****************************************************************************/ + +void Tst_ChangeFormatAnswersText (struct Tst_Question *Question) + { + unsigned NumOpt; + + /***** Change format of answers text *****/ + for (NumOpt = 0; + NumOpt < Question->Answer.NumOptions; + NumOpt++) + /* Convert answer text, that is in HTML, to rigorous HTML */ + if (Question->Answer.Options[NumOpt].Text[0]) + Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML, + Question->Answer.Options[NumOpt].Text, + Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false); + } + +void Tst_ChangeFormatAnswersFeedback (struct Tst_Question *Question) + { + unsigned NumOpt; + + /***** Change format of answers text and feedback *****/ + for (NumOpt = 0; + NumOpt < Question->Answer.NumOptions; + NumOpt++) + /* Convert answer feedback, that is in HTML, to rigorous HTML */ + if (Question->Answer.Options[NumOpt].Feedback) + if (Question->Answer.Options[NumOpt].Feedback[0]) + Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML, + Question->Answer.Options[NumOpt].Feedback, + Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false); + } + /*****************************************************************************/ /**************** Get and write the answers of a test question ***************/ /*****************************************************************************/ -void Tst_WriteAnswersBank (const struct Tst_Question *Question) +void Tst_WriteAnswersBank (struct Tst_Question *Question) { - void (*TstPrn_WriteAnsBank[Tst_NUM_ANS_TYPES]) (const struct Tst_Question *Question) = + void (*Tst_WriteAnsBank[Tst_NUM_ANS_TYPES]) (struct Tst_Question *Question) = { [Tst_ANS_INT ] = Tst_WriteIntAnsBank, [Tst_ANS_FLOAT ] = Tst_WriteFltAnsBank, @@ -2928,31 +2779,7 @@ void Tst_WriteAnswersBank (const struct Tst_Question *Question) }; /***** Write answers *****/ - TstPrn_WriteAnsBank[Question->Answer.Type] (Question); - } - -/*****************************************************************************/ -/***************** Write answers of a question to fill them ******************/ -/*****************************************************************************/ - -static void TstPrn_WriteAnswersToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion, - unsigned NumQst, - const struct Tst_Question *Question) - { - void (*TstPrn_WriteAnsBank[Tst_NUM_ANS_TYPES]) (const struct TstPrn_PrintedQuestion *PrintedQuestion, - unsigned NumQst, - const struct Tst_Question *Question) = - { - [Tst_ANS_INT ] = TstPrn_WriteIntAnsToFill, - [Tst_ANS_FLOAT ] = TstPrn_WriteFltAnsToFill, - [Tst_ANS_TRUE_FALSE ] = TstPrn_WriteTF_AnsToFill, - [Tst_ANS_UNIQUE_CHOICE ] = TstPrn_WriteChoAnsToFill, - [Tst_ANS_MULTIPLE_CHOICE] = TstPrn_WriteChoAnsToFill, - [Tst_ANS_TEXT ] = TstPrn_WriteTxtAnsToFill, - }; - - /***** Write answers *****/ - TstPrn_WriteAnsBank[Question->Answer.Type] (PrintedQuestion,NumQst,Question); + Tst_WriteAnsBank[Question->Answer.Type] (Question); } /*****************************************************************************/ @@ -2973,7 +2800,7 @@ bool Tst_CheckIfQuestionIsValidForGame (long QstCod) /****************** Write integer answer when editing a test *****************/ /*****************************************************************************/ -static void Tst_WriteIntAnsBank (const struct Tst_Question *Question) +static void Tst_WriteIntAnsBank (struct Tst_Question *Question) { HTM_SPAN_Begin ("class=\"TEST_EDI\""); HTM_TxtF ("(%ld)",Question->Answer.Integer); @@ -2984,7 +2811,7 @@ static void Tst_WriteIntAnsBank (const struct Tst_Question *Question) /****************** Write float answer when editing a test *******************/ /*****************************************************************************/ -static void Tst_WriteFltAnsBank (const struct Tst_Question *Question) +static void Tst_WriteFltAnsBank (struct Tst_Question *Question) { HTM_SPAN_Begin ("class=\"TEST_EDI\""); HTM_Txt ("(["); @@ -2999,7 +2826,7 @@ static void Tst_WriteFltAnsBank (const struct Tst_Question *Question) /*********** Write false / true answer when listing test questions ***********/ /*****************************************************************************/ -static void Tst_WriteTF_AnsBank (const struct Tst_Question *Question) +static void Tst_WriteTF_AnsBank (struct Tst_Question *Question) { /***** Write answer *****/ HTM_SPAN_Begin ("class=\"TEST_EDI\""); @@ -3013,50 +2840,22 @@ static void Tst_WriteTF_AnsBank (const struct Tst_Question *Question) /**** Write single or multiple choice answer when listing test questions *****/ /*****************************************************************************/ -static void Tst_WriteChoAnsBank (const struct Tst_Question *Question) +static void Tst_WriteChoAnsBank (struct Tst_Question *Question) { extern const char *Txt_TST_Answer_given_by_the_teachers; unsigned NumOpt; - char *AnswerTxt; - char *Feedback; - size_t LengthAnswerTxt; - size_t LengthFeedback; + + /***** Change format of answers text *****/ + Tst_ChangeFormatAnswersText (Question); + + /***** Change format of answers feedback *****/ + Tst_ChangeFormatAnswersFeedback (Question); HTM_TABLE_BeginPadding (2); for (NumOpt = 0; NumOpt < Question->Answer.NumOptions; NumOpt++) { - /* Convert the answer, that is in HTML, to rigorous HTML */ - LengthAnswerTxt = 0; - AnswerTxt = NULL; - if (Question->Answer.Options[NumOpt].Text) - if (Question->Answer.Options[NumOpt].Text[0]) - { - LengthAnswerTxt = strlen (Question->Answer.Options[NumOpt].Text) * Str_MAX_BYTES_PER_CHAR; - if ((AnswerTxt = (char *) malloc (LengthAnswerTxt + 1)) == NULL) - Lay_NotEnoughMemoryExit (); - Str_Copy (AnswerTxt,Question->Answer.Options[NumOpt].Text, - LengthAnswerTxt); - Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML, - AnswerTxt,LengthAnswerTxt,false); - } - - /* Convert the feedback, that is in HTML, to rigorous HTML */ - LengthFeedback = 0; - Feedback = NULL; - if (Question->Answer.Options[NumOpt].Feedback) - if (Question->Answer.Options[NumOpt].Feedback[0]) - { - LengthFeedback = strlen (Question->Answer.Options[NumOpt].Feedback) * Str_MAX_BYTES_PER_CHAR; - if ((Feedback = (char *) malloc (LengthFeedback + 1)) == NULL) - Lay_NotEnoughMemoryExit (); - Str_Copy (Feedback,Question->Answer.Options[NumOpt].Feedback, - LengthFeedback); - Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML, - Feedback,LengthFeedback,false); - } - HTM_TR_Begin (NULL); /* Put an icon that indicates whether the answer is correct or wrong */ @@ -3074,8 +2873,7 @@ static void Tst_WriteChoAnsBank (const struct Tst_Question *Question) /* Write the text of the answer and the media */ HTM_DIV_Begin ("class=\"TEST_EDI\""); - if (LengthAnswerTxt) - HTM_Txt (AnswerTxt); + HTM_Txt (Question->Answer.Options[NumOpt].Text); Med_ShowMedia (&Question->Answer.Options[NumOpt].Media, "TEST_MED_EDIT_LIST_CONT", "TEST_MED_EDIT_LIST"); @@ -3083,192 +2881,16 @@ static void Tst_WriteChoAnsBank (const struct Tst_Question *Question) /* Write the text of the feedback */ HTM_DIV_Begin ("class=\"TEST_EDI_LIGHT\""); - if (LengthFeedback) - HTM_Txt (Feedback); + HTM_Txt (Question->Answer.Options[NumOpt].Feedback); HTM_DIV_End (); HTM_TD_End (); HTM_TR_End (); - - /* Free memory allocated for the answer and the feedback */ - free (AnswerTxt); - if (LengthFeedback) - free (Feedback); } HTM_TABLE_End (); } -/*****************************************************************************/ -/****************** Write integer answer when seeing a test ******************/ -/*****************************************************************************/ - -static void TstPrn_WriteIntAnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion, - unsigned NumQst, - __attribute__((unused)) const struct Tst_Question *Question) - { - char StrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x" - - /***** Write input field for the answer *****/ - snprintf (StrAns,sizeof (StrAns), - "Ans%010u", - NumQst); - HTM_INPUT_TEXT (StrAns,11,PrintedQuestion->StrAnswers, - HTM_DONT_SUBMIT_ON_CHANGE, - "size=\"11\""); - } - -/*****************************************************************************/ -/****************** Write float answer when seeing a test ********************/ -/*****************************************************************************/ - -static void TstPrn_WriteFltAnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion, - unsigned NumQst, - __attribute__((unused)) const struct Tst_Question *Question) - { - char StrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x" - - /***** Write input field for the answer *****/ - snprintf (StrAns,sizeof (StrAns), - "Ans%010u", - NumQst); - HTM_INPUT_TEXT (StrAns,Tst_MAX_BYTES_FLOAT_ANSWER,PrintedQuestion->StrAnswers, - HTM_DONT_SUBMIT_ON_CHANGE, - "size=\"11\""); - } - -/*****************************************************************************/ -/************** Write false / true answer when seeing a test ****************/ -/*****************************************************************************/ - -static void TstPrn_WriteTF_AnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion, - unsigned NumQst, - __attribute__((unused)) const struct Tst_Question *Question) - { - extern const char *Txt_TF_QST[2]; - - /***** Write selector for the answer *****/ - /* Initially user has not answered the question ==> initially all the answers will be blank. - If the user does not confirm the submission of their exam ==> - ==> the exam may be half filled ==> the answers displayed will be those selected by the user. */ - HTM_SELECT_Begin (HTM_DONT_SUBMIT_ON_CHANGE, - "name=\"Ans%010u\"",NumQst); - HTM_OPTION (HTM_Type_STRING,"" ,PrintedQuestion->StrAnswers[0] == '\0',false," "); - HTM_OPTION (HTM_Type_STRING,"T",PrintedQuestion->StrAnswers[0] == 'T' ,false,"%s",Txt_TF_QST[0]); - HTM_OPTION (HTM_Type_STRING,"F",PrintedQuestion->StrAnswers[0] == 'F' ,false,"%s",Txt_TF_QST[1]); - HTM_SELECT_End (); - } - -/*****************************************************************************/ -/******** Write single or multiple choice answer when seeing a test **********/ -/*****************************************************************************/ - -static void TstPrn_WriteChoAnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion, - unsigned NumQst, - const struct Tst_Question *Question) - { - unsigned NumOpt; - unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION]; // Indexes of all answers of this question - bool UsrAnswers[Tst_MAX_OPTIONS_PER_QUESTION]; - char StrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x" - - /***** Change format of answers text *****/ - for (NumOpt = 0; - NumOpt < Question->Answer.NumOptions; - NumOpt++) - /* Convert answer text, that is in HTML, to rigorous HTML */ - if (Question->Answer.Options[NumOpt].Text[0]) - Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML, - Question->Answer.Options[NumOpt].Text, - Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false); - - /***** Get indexes for this question from string *****/ - TstPrn_GetIndexesFromStr (PrintedQuestion->StrIndexes,Indexes); - - /***** Get the user's answers for this question from string *****/ - TstPrn_GetAnswersFromStr (PrintedQuestion->StrAnswers,UsrAnswers); - - /***** Begin table *****/ - HTM_TABLE_BeginPadding (2); - - for (NumOpt = 0; - NumOpt < Question->Answer.NumOptions; - NumOpt++) - { - /***** Indexes are 0 1 2 3... if no shuffle - or 3 1 0 2... (example) if shuffle *****/ - HTM_TR_Begin (NULL); - - /***** Write selectors and letter of this option *****/ - /* Initially user has not answered the question ==> initially all the answers will be blank. - If the user does not confirm the submission of their exam ==> - ==> the exam may be half filled ==> the answers displayed will be those selected by the user. */ - HTM_TD_Begin ("class=\"LT\""); - - snprintf (StrAns,sizeof (StrAns), - "Ans%010u", - NumQst); - if (Question->Answer.Type == Tst_ANS_UNIQUE_CHOICE) - HTM_INPUT_RADIO (StrAns,false, - "id=\"Ans%010u_%u\" value=\"%u\"%s" - " onclick=\"selectUnselectRadio(this,this.form.Ans%010u,%u);\"", - NumQst,NumOpt, - Indexes[NumOpt], - UsrAnswers[Indexes[NumOpt]] ? " checked=\"checked\"" : - "", - NumQst,Question->Answer.NumOptions); - else // Answer.Type == Tst_ANS_MULTIPLE_CHOICE - HTM_INPUT_CHECKBOX (StrAns,HTM_DONT_SUBMIT_ON_CHANGE, - "id=\"Ans%010u_%u\" value=\"%u\"%s", - NumQst,NumOpt, - Indexes[NumOpt], - UsrAnswers[Indexes[NumOpt]] ? " checked=\"checked\"" : - ""); - - HTM_TD_End (); - - HTM_TD_Begin ("class=\"LT\""); - HTM_LABEL_Begin ("for=\"Ans%010u_%u\" class=\"ANS_TXT\"",NumQst,NumOpt); - HTM_TxtF ("%c) ",'a' + (char) NumOpt); - HTM_LABEL_End (); - HTM_TD_End (); - - /***** Write the option text *****/ - HTM_TD_Begin ("class=\"LT\""); - HTM_LABEL_Begin ("for=\"Ans%010u_%u\" class=\"ANS_TXT\"",NumQst,NumOpt); - HTM_Txt (Question->Answer.Options[Indexes[NumOpt]].Text); - HTM_LABEL_End (); - Med_ShowMedia (&Question->Answer.Options[Indexes[NumOpt]].Media, - "TEST_MED_SHOW_CONT", - "TEST_MED_SHOW"); - HTM_TD_End (); - - HTM_TR_End (); - } - - /***** End table *****/ - HTM_TABLE_End (); - } - -/*****************************************************************************/ -/******************** Write text answer when seeing a test *******************/ -/*****************************************************************************/ - -static void TstPrn_WriteTxtAnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion, - unsigned NumQst, - __attribute__((unused)) const struct Tst_Question *Question) - { - char StrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x" - - /***** Write input field for the answer *****/ - snprintf (StrAns,sizeof (StrAns), - "Ans%010u", - NumQst); - HTM_INPUT_TEXT (StrAns,Tst_MAX_CHARS_ANSWERS_ONE_QST,PrintedQuestion->StrAnswers, - HTM_DONT_SUBMIT_ON_CHANGE, - "size=\"40\""); - } - /*****************************************************************************/ /************** Write false / true answer when seeing a test *****************/ /*****************************************************************************/ @@ -3291,66 +2913,6 @@ void Tst_WriteAnsTF (char AnsTF) } } -/*****************************************************************************/ -/************************ Get choice answer from row *************************/ -/*****************************************************************************/ - -void Tst_GetChoiceAns (struct Tst_Question *Question,MYSQL_RES *mysql_res) - { - unsigned NumOpt; - MYSQL_ROW row; - - /***** Get text and correctness of answers for this question - from database (one row per answer) *****/ - /* - row[0] AnsInd - row[1] Answer - row[2] Feedback - row[3] MedCod - row[4] Correct - */ - for (NumOpt = 0; - NumOpt < Question->Answer.NumOptions; - NumOpt++) - { - /***** Get next answer *****/ - row = mysql_fetch_row (mysql_res); - - /***** Allocate memory for text in this choice option *****/ - if (!Tst_AllocateTextChoiceAnswer (Question,NumOpt)) - /* Abort on error */ - Ale_ShowAlertsAndExit (); - - /***** Copy answer text (row[1]) and convert it, - that is in HTML, to rigorous HTML ******/ - Str_Copy (Question->Answer.Options[NumOpt].Text,row[1], - Tst_MAX_BYTES_ANSWER_OR_FEEDBACK); - Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML, - Question->Answer.Options[NumOpt].Text, - Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false); - - /***** Copy answer feedback (row[2]) and convert it, - that is in HTML, to rigorous HTML ******/ - if (TstVis_IsVisibleFeedbackTxt (TstCfg_GetConfigVisibility ())) - if (row[2]) - if (row[2][0]) - { - Str_Copy (Question->Answer.Options[NumOpt].Feedback,row[2], - Tst_MAX_BYTES_ANSWER_OR_FEEDBACK); - Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML, - Question->Answer.Options[NumOpt].Feedback, - Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false); - } - - /***** Get media (row[3]) *****/ - Question->Answer.Options[NumOpt].Media.MedCod = Str_ConvertStrCodToLongCod (row[3]); - Med_GetMediaDataByCod (&Question->Answer.Options[NumOpt].Media); - - /***** Assign correctness (row[4]) of this answer (this option) *****/ - Question->Answer.Options[NumOpt].Correct = (row[4][0] == 'Y'); - } - } - /*****************************************************************************/ /*************** Write parameter with the code of a question *****************/ /*****************************************************************************/ diff --git a/swad_test.h b/swad_test.h index 45494119c..d5b5ed496 100644 --- a/swad_test.h +++ b/swad_test.h @@ -106,7 +106,7 @@ void Tst_AssessTest (void); void Tst_ShowTagList (unsigned NumTags,MYSQL_RES *mysql_res); -void Tst_ListQuestionForEdition (const struct Tst_Question *Question, +void Tst_ListQuestionForEdition (struct Tst_Question *Question, unsigned QstInd,bool QuestionExists, const char *Anchor); void Tst_WriteNumQst (unsigned NumQst); @@ -130,10 +130,13 @@ void Tst_WriteParamEditQst (const struct Tst_Test *Test); unsigned Tst_GetNumAnswersQst (long QstCod); void Tst_GetAnswersQst (struct Tst_Question *Question,MYSQL_RES **mysql_res, bool Shuffle); -void Tst_WriteAnswersBank (const struct Tst_Question *Question); + +void Tst_ChangeFormatAnswersText (struct Tst_Question *Question); +void Tst_ChangeFormatAnswersFeedback (struct Tst_Question *Question); + +void Tst_WriteAnswersBank (struct Tst_Question *Question); bool Tst_CheckIfQuestionIsValidForGame (long QstCod); void Tst_WriteAnsTF (char AnsTF); -void Tst_GetChoiceAns (struct Tst_Question *Question,MYSQL_RES *mysql_res); void Tst_WriteParamQstCod (unsigned NumQst,long QstCod); diff --git a/swad_test_print.c b/swad_test_print.c index 3c62e5bbe..6baffcb71 100644 --- a/swad_test_print.c +++ b/swad_test_print.c @@ -72,6 +72,33 @@ extern struct Globals Gbl; static void TstPrn_ResetPrintExceptPrnCod (struct TstPrn_Print *Print); +static void TstPrn_WriteQstAndAnsToFill (struct TstPrn_PrintedQuestion *PrintedQuestion, + unsigned NumQst, + struct Tst_Question *Question); +static void TstPrn_WriteAnswersToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion, + unsigned NumQst, + struct Tst_Question *Question); + +//----------------------------------------------------------------------------- +static void TstPrn_WriteIntAnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion, + unsigned NumQst, + __attribute__((unused)) struct Tst_Question *Question); +static void TstPrn_WriteFltAnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion, + unsigned NumQst, + __attribute__((unused)) struct Tst_Question *Question); +static void TstPrn_WriteTF_AnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion, + unsigned NumQst, + __attribute__((unused)) struct Tst_Question *Question); +static void TstPrn_WriteChoAnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion, + unsigned NumQst, + struct Tst_Question *Question); +static void TstPrn_WriteTxtAnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion, + unsigned NumQst, + __attribute__((unused)) struct Tst_Question *Question); +//----------------------------------------------------------------------------- + +static void TstPrn_PutCheckBoxAllowTeachers (bool AllowTeachers); + static void TstPrn_WriteQstAndAnsExam (struct UsrData *UsrDat, struct TstPrn_Print *Print, unsigned NumQst, @@ -80,7 +107,6 @@ static void TstPrn_WriteQstAndAnsExam (struct UsrData *UsrDat, unsigned Visibility); //----------------------------------------------------------------------------- - static void TstPrn_GetCorrectAndComputeIntAnsScore (struct TstPrn_PrintedQuestion *PrintedQuestion, struct Tst_Question *Question); static void TstPrn_GetCorrectAndComputeFltAnsScore (struct TstPrn_PrintedQuestion *PrintedQuestion, @@ -91,38 +117,33 @@ static void TstPrn_GetCorrectAndComputeChoAnsScore (struct TstPrn_PrintedQuestio struct Tst_Question *Question); static void TstPrn_GetCorrectAndComputeTxtAnsScore (struct TstPrn_PrintedQuestion *PrintedQuestion, struct Tst_Question *Question); - //----------------------------------------------------------------------------- - static void TstPrn_GetCorrectIntAnswerFromDB (struct Tst_Question *Question); static void TstPrn_GetCorrectFltAnswerFromDB (struct Tst_Question *Question); static void TstPrn_GetCorrectTF_AnswerFromDB (struct Tst_Question *Question); static void TstPrn_GetCorrectChoAnswerFromDB (struct Tst_Question *Question); static void TstPrn_GetCorrectTxtAnswerFromDB (struct Tst_Question *Question); - //----------------------------------------------------------------------------- - static void TstPrn_WriteIntAnsPrint (struct UsrData *UsrDat, const struct TstPrn_PrintedQuestion *PrintedQuestion, - const struct Tst_Question *Question, + struct Tst_Question *Question, bool ICanView[TstVis_NUM_ITEMS_VISIBILITY]); static void TstPrn_WriteFltAnsPrint (struct UsrData *UsrDat, const struct TstPrn_PrintedQuestion *PrintedQuestion, - const struct Tst_Question *Question, + struct Tst_Question *Question, bool ICanView[TstVis_NUM_ITEMS_VISIBILITY]); static void TstPrn_WriteTF_AnsPrint (struct UsrData *UsrDat, const struct TstPrn_PrintedQuestion *PrintedQuestion, - const struct Tst_Question *Question, + struct Tst_Question *Question, bool ICanView[TstVis_NUM_ITEMS_VISIBILITY]); static void TstPrn_WriteChoAnsPrint (struct UsrData *UsrDat, const struct TstPrn_PrintedQuestion *PrintedQuestion, - const struct Tst_Question *Question, + struct Tst_Question *Question, bool ICanView[TstVis_NUM_ITEMS_VISIBILITY]); static void TstPrn_WriteTxtAnsPrint (struct UsrData *UsrDat, const struct TstPrn_PrintedQuestion *PrintedQuestion, - const struct Tst_Question *Question, + struct Tst_Question *Question, bool ICanView[TstVis_NUM_ITEMS_VISIBILITY]); - //----------------------------------------------------------------------------- static void TstPrn_WriteHeadUserCorrect (struct UsrData *UsrDat); @@ -210,6 +231,340 @@ void TstPrn_UpdatePrintInDB (const struct TstPrn_Print *Print) Str_SetDecimalPointToLocal (); // Return to local system } +/*****************************************************************************/ +/****************** Show a test exam print to be answered ********************/ +/*****************************************************************************/ + +void TstPrn_ShowTestPrintToFillIt (struct TstPrn_Print *Print, + unsigned NumExamsGeneratedByMe, + TstPrn_RequestOrConfirm_t RequestOrConfirm) + { + extern const char *Hlp_ASSESSMENT_Tests; + extern const char *Txt_Test; + extern const char *Txt_Continue; + extern const char *Txt_Send; + unsigned NumQst; + struct Tst_Question Question; + static const Act_Action_t Action[Tst_NUM_REQUEST_OR_CONFIRM] = + { + [TstPrn_REQUEST] = ActReqAssTst, + [TstPrn_CONFIRM] = ActAssTst, + }; + + /***** Begin box *****/ + Box_BoxBegin (NULL,Txt_Test, + NULL,NULL, + Hlp_ASSESSMENT_Tests,Box_NOT_CLOSABLE); + Lay_WriteHeaderClassPhoto (false,false, + Gbl.Hierarchy.Ins.InsCod, + Gbl.Hierarchy.Deg.DegCod, + Gbl.Hierarchy.Crs.CrsCod); + + if (Print->NumQsts) + { + /***** Begin form *****/ + Frm_StartForm (Action[RequestOrConfirm]); + TstPrn_PutParamPrnCod (Print->PrnCod); + Par_PutHiddenParamUnsigned (NULL,"NumTst",NumExamsGeneratedByMe); + + /***** Begin table *****/ + HTM_TABLE_BeginWideMarginPadding (10); + + /***** Write one row for each question *****/ + for (NumQst = 0; + NumQst < Print->NumQsts; + NumQst++) + { + Gbl.RowEvenOdd = NumQst % 2; + + /* Create test question */ + Tst_QstConstructor (&Question); + Question.QstCod = Print->PrintedQuestions[NumQst].QstCod; + + /* Show question */ + if (!Tst_GetQstDataFromDB (&Question)) // Question exists + Lay_ShowErrorAndExit ("Wrong question."); + + /* Write question and answers */ + TstPrn_WriteQstAndAnsToFill (&Print->PrintedQuestions[NumQst],NumQst,&Question); + + /* Destroy test question */ + Tst_QstDestructor (&Question); + } + + /***** End table *****/ + HTM_TABLE_End (); + + /***** End form *****/ + switch (RequestOrConfirm) + { + case TstPrn_REQUEST: + /* Send button */ + Btn_PutConfirmButton (Txt_Continue); + break; + case TstPrn_CONFIRM: + /* Will the test exam be visible by teachers? */ + TstPrn_PutCheckBoxAllowTeachers (true); + + /* Send button */ + Btn_PutCreateButton (Txt_Send); + break; + } + Frm_EndForm (); + } + + /***** End box *****/ + Box_BoxEnd (); + } + +/*****************************************************************************/ +/********** Write a row of a test, with one question and its answer **********/ +/*****************************************************************************/ + +static void TstPrn_WriteQstAndAnsToFill (struct TstPrn_PrintedQuestion *PrintedQuestion, + unsigned NumQst, + struct Tst_Question *Question) + { + /***** Begin row *****/ + HTM_TR_Begin (NULL); + + /***** Number of question and answer type *****/ + HTM_TD_Begin ("class=\"RT COLOR%u\"",Gbl.RowEvenOdd); + Tst_WriteNumQst (NumQst + 1); + Tst_WriteAnswerType (Question->Answer.Type); + HTM_TD_End (); + + /***** Stem, media and answers *****/ + HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd); + + /* Write parameter with question code */ + Tst_WriteParamQstCod (NumQst,Question->QstCod); + + /* Stem */ + Tst_WriteQstStem (Question->Stem,"TEST_EXA",true); + + /* Media */ + Med_ShowMedia (&Question->Media, + "TEST_MED_SHOW_CONT", + "TEST_MED_SHOW"); + + /* Answers */ + TstPrn_WriteAnswersToFill (PrintedQuestion,NumQst,Question); + + HTM_TD_End (); + + /***** End row *****/ + HTM_TR_End (); + } + +/*****************************************************************************/ +/***************** Write answers of a question to fill them ******************/ +/*****************************************************************************/ + +static void TstPrn_WriteAnswersToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion, + unsigned NumQst, + struct Tst_Question *Question) + { + void (*TstPrn_WriteAnsBank[Tst_NUM_ANS_TYPES]) (const struct TstPrn_PrintedQuestion *PrintedQuestion, + unsigned NumQst, + struct Tst_Question *Question) = + { + [Tst_ANS_INT ] = TstPrn_WriteIntAnsToFill, + [Tst_ANS_FLOAT ] = TstPrn_WriteFltAnsToFill, + [Tst_ANS_TRUE_FALSE ] = TstPrn_WriteTF_AnsToFill, + [Tst_ANS_UNIQUE_CHOICE ] = TstPrn_WriteChoAnsToFill, + [Tst_ANS_MULTIPLE_CHOICE] = TstPrn_WriteChoAnsToFill, + [Tst_ANS_TEXT ] = TstPrn_WriteTxtAnsToFill, + }; + + /***** Write answers *****/ + TstPrn_WriteAnsBank[Question->Answer.Type] (PrintedQuestion,NumQst,Question); + } + +/*****************************************************************************/ +/****************** Write integer answer when seeing a test ******************/ +/*****************************************************************************/ + +static void TstPrn_WriteIntAnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion, + unsigned NumQst, + __attribute__((unused)) struct Tst_Question *Question) + { + char StrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x" + + /***** Write input field for the answer *****/ + snprintf (StrAns,sizeof (StrAns), + "Ans%010u", + NumQst); + HTM_INPUT_TEXT (StrAns,11,PrintedQuestion->StrAnswers, + HTM_DONT_SUBMIT_ON_CHANGE, + "size=\"11\""); + } + +/*****************************************************************************/ +/****************** Write float answer when seeing a test ********************/ +/*****************************************************************************/ + +static void TstPrn_WriteFltAnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion, + unsigned NumQst, + __attribute__((unused)) struct Tst_Question *Question) + { + char StrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x" + + /***** Write input field for the answer *****/ + snprintf (StrAns,sizeof (StrAns), + "Ans%010u", + NumQst); + HTM_INPUT_TEXT (StrAns,Tst_MAX_BYTES_FLOAT_ANSWER,PrintedQuestion->StrAnswers, + HTM_DONT_SUBMIT_ON_CHANGE, + "size=\"11\""); + } + +/*****************************************************************************/ +/************** Write false / true answer when seeing a test ****************/ +/*****************************************************************************/ + +static void TstPrn_WriteTF_AnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion, + unsigned NumQst, + __attribute__((unused)) struct Tst_Question *Question) + { + extern const char *Txt_TF_QST[2]; + + /***** Write selector for the answer *****/ + /* Initially user has not answered the question ==> initially all the answers will be blank. + If the user does not confirm the submission of their exam ==> + ==> the exam may be half filled ==> the answers displayed will be those selected by the user. */ + HTM_SELECT_Begin (HTM_DONT_SUBMIT_ON_CHANGE, + "name=\"Ans%010u\"",NumQst); + HTM_OPTION (HTM_Type_STRING,"" ,PrintedQuestion->StrAnswers[0] == '\0',false," "); + HTM_OPTION (HTM_Type_STRING,"T",PrintedQuestion->StrAnswers[0] == 'T' ,false,"%s",Txt_TF_QST[0]); + HTM_OPTION (HTM_Type_STRING,"F",PrintedQuestion->StrAnswers[0] == 'F' ,false,"%s",Txt_TF_QST[1]); + HTM_SELECT_End (); + } + +/*****************************************************************************/ +/******** Write single or multiple choice answer when seeing a test **********/ +/*****************************************************************************/ + +static void TstPrn_WriteChoAnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion, + unsigned NumQst, + struct Tst_Question *Question) + { + unsigned NumOpt; + unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION]; // Indexes of all answers of this question + bool UsrAnswers[Tst_MAX_OPTIONS_PER_QUESTION]; + char StrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x" + + /***** Change format of answers text *****/ + Tst_ChangeFormatAnswersText (Question); + + /***** Get indexes for this question from string *****/ + TstPrn_GetIndexesFromStr (PrintedQuestion->StrIndexes,Indexes); + + /***** Get the user's answers for this question from string *****/ + TstPrn_GetAnswersFromStr (PrintedQuestion->StrAnswers,UsrAnswers); + + /***** Begin table *****/ + HTM_TABLE_BeginPadding (2); + + for (NumOpt = 0; + NumOpt < Question->Answer.NumOptions; + NumOpt++) + { + /***** Indexes are 0 1 2 3... if no shuffle + or 3 1 0 2... (example) if shuffle *****/ + HTM_TR_Begin (NULL); + + /***** Write selectors and letter of this option *****/ + /* Initially user has not answered the question ==> initially all the answers will be blank. + If the user does not confirm the submission of their exam ==> + ==> the exam may be half filled ==> the answers displayed will be those selected by the user. */ + HTM_TD_Begin ("class=\"LT\""); + + snprintf (StrAns,sizeof (StrAns), + "Ans%010u", + NumQst); + if (Question->Answer.Type == Tst_ANS_UNIQUE_CHOICE) + HTM_INPUT_RADIO (StrAns,false, + "id=\"Ans%010u_%u\" value=\"%u\"%s" + " onclick=\"selectUnselectRadio(this,this.form.Ans%010u,%u);\"", + NumQst,NumOpt, + Indexes[NumOpt], + UsrAnswers[Indexes[NumOpt]] ? " checked=\"checked\"" : + "", + NumQst,Question->Answer.NumOptions); + else // Answer.Type == Tst_ANS_MULTIPLE_CHOICE + HTM_INPUT_CHECKBOX (StrAns,HTM_DONT_SUBMIT_ON_CHANGE, + "id=\"Ans%010u_%u\" value=\"%u\"%s", + NumQst,NumOpt, + Indexes[NumOpt], + UsrAnswers[Indexes[NumOpt]] ? " checked=\"checked\"" : + ""); + + HTM_TD_End (); + + HTM_TD_Begin ("class=\"LT\""); + HTM_LABEL_Begin ("for=\"Ans%010u_%u\" class=\"ANS_TXT\"",NumQst,NumOpt); + HTM_TxtF ("%c) ",'a' + (char) NumOpt); + HTM_LABEL_End (); + HTM_TD_End (); + + /***** Write the option text *****/ + HTM_TD_Begin ("class=\"LT\""); + HTM_LABEL_Begin ("for=\"Ans%010u_%u\" class=\"ANS_TXT\"",NumQst,NumOpt); + HTM_Txt (Question->Answer.Options[Indexes[NumOpt]].Text); + HTM_LABEL_End (); + Med_ShowMedia (&Question->Answer.Options[Indexes[NumOpt]].Media, + "TEST_MED_SHOW_CONT", + "TEST_MED_SHOW"); + HTM_TD_End (); + + HTM_TR_End (); + } + + /***** End table *****/ + HTM_TABLE_End (); + } + +/*****************************************************************************/ +/******************** Write text answer when seeing a test *******************/ +/*****************************************************************************/ + +static void TstPrn_WriteTxtAnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion, + unsigned NumQst, + __attribute__((unused)) struct Tst_Question *Question) + { + char StrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x" + + /***** Write input field for the answer *****/ + snprintf (StrAns,sizeof (StrAns), + "Ans%010u", + NumQst); + HTM_INPUT_TEXT (StrAns,Tst_MAX_CHARS_ANSWERS_ONE_QST,PrintedQuestion->StrAnswers, + HTM_DONT_SUBMIT_ON_CHANGE, + "size=\"40\""); + } + +/*****************************************************************************/ +/************* Put checkbox to allow teachers to see test exam ***************/ +/*****************************************************************************/ + +static void TstPrn_PutCheckBoxAllowTeachers (bool AllowTeachers) + { + extern const char *The_ClassFormInBox[The_NUM_THEMES]; + extern const char *Txt_Allow_teachers_to_consult_this_test; + + /***** Test exam will be available for teachers? *****/ + HTM_DIV_Begin ("class=\"CM\""); + HTM_LABEL_Begin ("class=\"%s\"",The_ClassFormInBox[Gbl.Prefs.Theme]); + HTM_INPUT_CHECKBOX ("AllowTchs",HTM_DONT_SUBMIT_ON_CHANGE, + "value=\"Y\"%s", + AllowTeachers ? " checked=\"checked\"" : // Teachers can see test exam + ""); + HTM_TxtF (" %s",Txt_Allow_teachers_to_consult_this_test); + HTM_LABEL_End (); + HTM_DIV_End (); + } + /*****************************************************************************/ /********************* Show test exam after assessing it *********************/ /*****************************************************************************/ @@ -640,14 +995,14 @@ static void TstPrn_GetCorrectTxtAnswerFromDB (struct Tst_Question *Question) /* Abort on error */ Ale_ShowAlertsAndExit (); - /***** Copy answer text (row[0]) and convert it, that is in HTML, to rigorous HTML ******/ + /***** Copy answer text (row[0]) ******/ Str_Copy (Question->Answer.Options[NumOpt].Text,row[0], Tst_MAX_BYTES_ANSWER_OR_FEEDBACK); - Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML, - Question->Answer.Options[NumOpt].Text, - Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false); } + /***** Change format of answers text *****/ + Tst_ChangeFormatAnswersText (Question); + /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); } @@ -915,12 +1270,12 @@ void TstPrn_ShowGrade (double Grade,double MaxGrade) void TstPrn_WriteAnswersExam (struct UsrData *UsrDat, const struct TstPrn_PrintedQuestion *PrintedQuestion, - const struct Tst_Question *Question, + struct Tst_Question *Question, bool ICanView[TstVis_NUM_ITEMS_VISIBILITY]) { void (*TstPrn_WriteAnsExam[Tst_NUM_ANS_TYPES]) (struct UsrData *UsrDat, const struct TstPrn_PrintedQuestion *PrintedQuestion, - const struct Tst_Question *Question, + struct Tst_Question *Question, bool ICanView[TstVis_NUM_ITEMS_VISIBILITY]) = { [Tst_ANS_INT ] = TstPrn_WriteIntAnsPrint, @@ -942,7 +1297,7 @@ void TstPrn_WriteAnswersExam (struct UsrData *UsrDat, static void TstPrn_WriteIntAnsPrint (struct UsrData *UsrDat, const struct TstPrn_PrintedQuestion *PrintedQuestion, - const struct Tst_Question *Question, + struct Tst_Question *Question, bool ICanView[TstVis_NUM_ITEMS_VISIBILITY]) { long IntAnswerUsr; @@ -1001,7 +1356,7 @@ static void TstPrn_WriteIntAnsPrint (struct UsrData *UsrDat, static void TstPrn_WriteFltAnsPrint (struct UsrData *UsrDat, const struct TstPrn_PrintedQuestion *PrintedQuestion, - const struct Tst_Question *Question, + struct Tst_Question *Question, bool ICanView[TstVis_NUM_ITEMS_VISIBILITY]) { double FloatAnsUsr = 0.0; @@ -1061,7 +1416,7 @@ static void TstPrn_WriteFltAnsPrint (struct UsrData *UsrDat, static void TstPrn_WriteTF_AnsPrint (struct UsrData *UsrDat, const struct TstPrn_PrintedQuestion *PrintedQuestion, - const struct Tst_Question *Question, + struct Tst_Question *Question, bool ICanView[TstVis_NUM_ITEMS_VISIBILITY]) { char AnsTFUsr; @@ -1109,7 +1464,7 @@ static void TstPrn_WriteTF_AnsPrint (struct UsrData *UsrDat, static void TstPrn_WriteChoAnsPrint (struct UsrData *UsrDat, const struct TstPrn_PrintedQuestion *PrintedQuestion, - const struct Tst_Question *Question, + struct Tst_Question *Question, bool ICanView[TstVis_NUM_ITEMS_VISIBILITY]) { extern const char *Txt_TST_Answer_given_by_the_user; @@ -1123,25 +1478,12 @@ static void TstPrn_WriteChoAnsPrint (struct UsrData *UsrDat, char *Str; } Ans; - /***** Change format of answers text and feedback *****/ - for (NumOpt = 0; - NumOpt < Question->Answer.NumOptions; - NumOpt++) - { - /* Convert answer text, that is in HTML, to rigorous HTML */ - if (Question->Answer.Options[NumOpt].Text[0]) - Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML, - Question->Answer.Options[NumOpt].Text, - Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false); + /***** Change format of answers text *****/ + Tst_ChangeFormatAnswersText (Question); - /* Convert answer feedback, that is in HTML, to rigorous HTML */ - if (ICanView[TstVis_VISIBLE_FEEDBACK_TXT]) - if (Question->Answer.Options[NumOpt].Feedback) - if (Question->Answer.Options[NumOpt].Feedback[0]) - Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML, - Question->Answer.Options[NumOpt].Feedback, - Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false); - } + /***** Change format of answers feedback *****/ + if (ICanView[TstVis_VISIBLE_FEEDBACK_TXT]) + Tst_ChangeFormatAnswersFeedback (Question); /***** Get indexes for this question from string *****/ TstPrn_GetIndexesFromStr (PrintedQuestion->StrIndexes,Indexes); @@ -1257,7 +1599,7 @@ static void TstPrn_WriteChoAnsPrint (struct UsrData *UsrDat, static void TstPrn_WriteTxtAnsPrint (struct UsrData *UsrDat, const struct TstPrn_PrintedQuestion *PrintedQuestion, - const struct Tst_Question *Question, + struct Tst_Question *Question, bool ICanView[TstVis_NUM_ITEMS_VISIBILITY]) { unsigned NumOpt; @@ -1265,25 +1607,12 @@ static void TstPrn_WriteTxtAnsPrint (struct UsrData *UsrDat, char TextAnsOK[Tst_MAX_BYTES_ANSWERS_ONE_QST + 1]; bool Correct = false; - /***** Change format of answers text and feedback *****/ - for (NumOpt = 0; - NumOpt < Question->Answer.NumOptions; - NumOpt++) - { - /* Convert answer text, that is in HTML, to rigorous HTML */ - if (Question->Answer.Options[NumOpt].Text[0]) - Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML, - Question->Answer.Options[NumOpt].Text, - Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false); + /***** Change format of answers text *****/ + Tst_ChangeFormatAnswersText (Question); - /* Convert answer feedback, that is in HTML, to rigorous HTML */ - if (ICanView[TstVis_VISIBLE_FEEDBACK_TXT]) - if (Question->Answer.Options[NumOpt].Feedback) - if (Question->Answer.Options[NumOpt].Feedback[0]) - Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML, - Question->Answer.Options[NumOpt].Feedback, - Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false); - } + /***** Change format of answers feedback *****/ + if (ICanView[TstVis_VISIBLE_FEEDBACK_TXT]) + Tst_ChangeFormatAnswersFeedback (Question); /***** Header with the title of each column *****/ HTM_TABLE_BeginPadding (2); diff --git a/swad_test_print.h b/swad_test_print.h index c51a59539..4b6fe8ac7 100644 --- a/swad_test_print.h +++ b/swad_test_print.h @@ -62,6 +62,13 @@ struct TstPrn_Print struct TstPrn_PrintedQuestion PrintedQuestions[TstCfg_MAX_QUESTIONS_PER_TEST]; }; +#define Tst_NUM_REQUEST_OR_CONFIRM 2 +typedef enum + { + TstPrn_REQUEST, + TstPrn_CONFIRM, + } TstPrn_RequestOrConfirm_t; + /*****************************************************************************/ /***************************** Public prototypes *****************************/ /*****************************************************************************/ @@ -70,6 +77,10 @@ void TstPrn_ResetPrint (struct TstPrn_Print *Print); void TstPrn_CreatePrintInDB (struct TstPrn_Print *Print); void TstPrn_UpdatePrintInDB (const struct TstPrn_Print *Print); +void TstPrn_ShowTestPrintToFillIt (struct TstPrn_Print *Print, + unsigned NumExamsGeneratedByMe, + TstPrn_RequestOrConfirm_t RequestOrConfirm); + void TstPrn_ShowPrintAfterAssess (struct TstPrn_Print *Print); void TstPrn_ComputeScoresAndStoreQuestionsOfPrint (struct TstPrn_Print *Print, @@ -91,6 +102,9 @@ void TstPrn_ComputeTxtAnsScore (struct TstPrn_PrintedQuestion *PrintedQuestion, const struct Tst_Question *Question); //----------------------------------------------------------------------------- +void Tst_ChangeFormatAnswersText (struct Tst_Question *Question); +void Tst_ChangeFormatAnswersFeedback (struct Tst_Question *Question); + void TstPrn_GetIndexesFromStr (const char StrIndexesOneQst[Tst_MAX_BYTES_INDEXES_ONE_QST + 1], // 0 1 2 3, 3 0 2 1, etc. unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION]); void TstPrn_GetAnswersFromStr (const char StrAnswersOneQst[Tst_MAX_BYTES_ANSWERS_ONE_QST + 1], @@ -102,7 +116,7 @@ void TstPrn_ShowGrade (double Grade,double MaxGrade); void TstPrn_WriteAnswersExam (struct UsrData *UsrDat, const struct TstPrn_PrintedQuestion *PrintedQuestion, - const struct Tst_Question *Question, + struct Tst_Question *Question, bool IsVisible[TstVis_NUM_ITEMS_VISIBILITY]); void TstPrn_SelUsrsToViewUsrsPrints (void);