Version19.249

This commit is contained in:
acanas 2020-06-17 02:31:42 +02:00
parent f5ba387847
commit 07078d4504
10 changed files with 529 additions and 619 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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);
}

View File

@ -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]) *****/

View File

@ -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",

View File

@ -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);

View File

@ -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,"&nbsp;");
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)&nbsp;",'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 *****************/
/*****************************************************************************/

View File

@ -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);

View File

@ -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,"&nbsp;");
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)&nbsp;",'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 ("&nbsp;%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);

View File

@ -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);