Version19.160.1

This commit is contained in:
acanas 2020-04-04 02:07:54 +02:00
parent f668a24593
commit d567240d06
9 changed files with 217 additions and 542 deletions

View File

@ -497,7 +497,7 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - *
En OpenSWAD:
ps2pdf source.ps destination.pdf
*/
#define Log_PLATFORM_VERSION "SWAD 19.160.1 (2020-04-03)"
#define Log_PLATFORM_VERSION "SWAD 19.161 (2020-04-04)"
#define CSS_FILE "swad19.146.css"
#define JS_FILE "swad19.153.js"
/*
@ -516,6 +516,10 @@ Si es as
Función API newLocation...
Paramétros: MAC, string con ubicación (ej. "Aula 0.1")
// TODO: Laura García: "Ahora estoy utilizando la plataforma SWAD más que nunca, evidentemente, debido a las circunstancias, e incluso les he hecho un examencillo a los alumnos utilizando los test de autoevaluación.
Pero quería preguntarte un par de cosas:
- lo primero es si se pueden borrar los test realizados por cualquier usuario, incluido profesores. Yo misma he hecho un montón para simular el examen, y ya me están sobrando.
- por otra parte, he buscado pero no he encontrado, la posibilidad de cambiar la manera de corregir los tes, quitar la penalización por respuesta negativa,, o cambiarla, etc.. La verdad es que si se puede hacer me facilitaría un montón el trabajo próximo que nos espera con los alumnos."
// TODO: Hacer un nuevo rol en los TFG: tutor externo (profesor de áreas no vinculadas con el centro, profesionales de empresas, etc.)
// TODO: Impedir la creación y edición de proyectos si no son editables.
// TODO: No se puede entrar con DNI '1' suponiendo que no tenga password ¿por qué?
@ -524,9 +528,8 @@ Param
// TODO: Oresti Baños: cambiar ojos por candados en descriptores para prohibir/permitir y dejar los ojos para poder elegir descriptores
// TODO: Integrar pull requests con traducciones del alemán del usuario eruedin en GitHub
// TODO: Integrar Stem y Feedback en question, creando espacio con malloc como en las respuestas
// TODO: Intentar cambiar Tst_WriteChoiceAnsSeeing usando Tst_GetQstDataFromDB y quitar Tst_GetChoiceAns
// TODO: Intentar quitar Tst_GetOneQuestionByCod usando Tst_GetQstDataFromDB
Version 19.161: Apr 04, 2020 Code refactoring in tests. (284529 lines)
Version 19.160.1: Apr 03, 2020 Score calculated is removed from each test question. (284817 lines)
Version 19.160: Apr 03, 2020 The score for each test question displayed in an exam is the one stored in the database instead of being calculated.
New file extension, suggested by Rosa Medina Doménech. (284933 lines)

View File

@ -156,8 +156,9 @@ static void Gam_ListGameQuestions (struct Game *Game);
static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts,
MYSQL_RES *mysql_res,
bool ICanEditQuestions);
static void Gam_ListQuestionForEdition (struct Tst_Question *Question,
unsigned QstInd);
static void Gam_ListQuestionForEdition (const struct Tst_Question *Question,
const char *Stem,const char *Feedback,
unsigned QstInd,bool QuestionExists);
static void Gam_PutIconToAddNewQuestions (void *Args);
static void Gam_PutButtonToAddNewQuestions (void);
@ -1911,9 +1912,12 @@ static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts,
unsigned NumQst;
MYSQL_ROW row;
struct Tst_Question Question;
char Stem[Cns_MAX_BYTES_TEXT + 1];
char Feedback[Cns_MAX_BYTES_TEXT + 1];
unsigned QstInd;
unsigned MaxQstInd;
char StrQstInd[Cns_MAX_DECIMAL_DIGITS_UINT + 1];
bool QuestionExists;
/***** Get maximum question index *****/
MaxQstInd = Gam_GetMaxQuestionIndexInGame (GamCod);
@ -2010,7 +2014,8 @@ static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts,
HTM_TD_End ();
/***** Question *****/
Gam_ListQuestionForEdition (&Question,QstInd);
QuestionExists = Tst_GetQstDataFromDB (&Question,Stem,Feedback);
Gam_ListQuestionForEdition (&Question,Stem,Feedback,QstInd,QuestionExists);
HTM_TR_End ();
@ -2026,44 +2031,17 @@ static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts,
/********************** List game question for edition ***********************/
/*****************************************************************************/
static void Gam_ListQuestionForEdition (struct Tst_Question *Question,
unsigned QstInd)
static void Gam_ListQuestionForEdition (const struct Tst_Question *Question,
const char *Stem,const char *Feedback,
unsigned QstInd,bool QuestionExists)
{
extern const char *Txt_Question_removed;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
bool QstExists;
Tst_AnswerType_t AnswerType;
struct Media Media;
/***** Get question from database *****/
QstExists = Tst_GetOneQuestionByCod (Question->QstCod,&mysql_res); // Question exists?
if (QstExists)
{
/***** Get row of the result of the query *****/
row = mysql_fetch_row (mysql_res);
/*
row[0] UNIX_TIMESTAMP(EditTime)
row[1] AnsType
row[2] Shuffle
row[3] Stem
row[4] Feedback
row[5] MedCod
row[6] NumHits
row[7] NumHitsNotBlank
row[8] Score
*/
}
/***** Number of question and answer type (row[1]) *****/
HTM_TD_Begin ("class=\"RT COLOR%u\"",Gbl.RowEvenOdd);
Tst_WriteNumQst (QstInd);
if (QstExists)
{
AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
Tst_WriteAnswerType (AnswerType);
}
if (QuestionExists)
Tst_WriteAnswerType (Question->Answer.Type);
HTM_TD_End ();
/***** Write question code *****/
@ -2073,29 +2051,25 @@ static void Gam_ListQuestionForEdition (struct Tst_Question *Question,
/***** Write the question tags *****/
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
if (QstExists)
if (QuestionExists)
Tst_GetAndWriteTagsQst (Question->QstCod);
HTM_TD_End ();
/***** Write stem (row[3]) and media *****/
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
if (QstExists)
if (QuestionExists)
{
/* Write stem */
Tst_WriteQstStem (row[3],"TEST_EDI",
Tst_WriteQstStem (Stem,"TEST_EDI",
true); // Visible
/* Get media (row[5]) */
Media.MedCod = Str_ConvertStrCodToLongCod (row[5]);
Med_GetMediaDataByCod (&Media);
/* Show media */
Med_ShowMedia (&Media,
Med_ShowMedia (&Question->Media,
"TEST_MED_EDIT_LIST_STEM_CONTAINER",
"TEST_MED_EDIT_LIST_STEM");
/* Show feedback (row[4]) */
Tst_WriteQstFeedback (row[4],"TEST_EDI_LIGHT");
/* Show feedback */
Tst_WriteQstFeedback (Feedback,"TEST_EDI_LIGHT");
/* Show answers */
Tst_WriteAnswersListing (Question);
@ -2107,9 +2081,6 @@ static void Gam_ListQuestionForEdition (struct Tst_Question *Question,
HTM_SPAN_End ();
}
HTM_TD_End ();
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
/*****************************************************************************/

View File

@ -192,7 +192,7 @@ static void Mch_PutIfAnswered (const struct Match *Match,bool Answered);
static void Mch_PutIconToRemoveMyAnswer (const struct Match *Match);
static void Mch_ShowQuestionAndAnswersTch (const struct Match *Match);
static void Mch_WriteAnswersMatchResult (const struct Match *Match,
struct Tst_Question *Question,
const struct Tst_Question *Question,
const char *Class,bool ShowResult);
static bool Mch_ShowQuestionAndAnswersStd (const struct Match *Match,
const struct Mch_UsrAnswer *UsrAnswer,
@ -2889,9 +2889,9 @@ static void Mch_ShowQuestionAndAnswersTch (const struct Match *Match)
{
extern const char *Txt_MATCH_Paused;
extern const char *Txt_Question_removed;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
struct Tst_Question Question;
char Stem[Cns_MAX_BYTES_TEXT + 1];
char Feedback[Cns_MAX_BYTES_TEXT + 1];
/***** Create test question *****/
Tst_QstConstructor (&Question);
@ -2908,41 +2908,25 @@ static void Mch_ShowQuestionAndAnswersTch (const struct Match *Match)
}
/***** Get data of question from database *****/
if (DB_QuerySELECT (&mysql_res,"can not get data of a question",
"SELECT AnsType," // row[0]
"Stem," // row[1]
"MedCod" // row[2]
" FROM tst_questions"
" WHERE QstCod=%ld",
Question.QstCod))
if (Tst_GetQstDataFromDB (&Question,Stem,Feedback))
{
row = mysql_fetch_row (mysql_res);
/***** Show question *****/
/* Get answer type (row[0]) */
Question.Answer.Type = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[0]);
/* Check answer type */
if (Question.Answer.Type != Tst_ANS_UNIQUE_CHOICE)
Lay_ShowErrorAndExit ("Wrong answer type.");
/* Begin container */
HTM_DIV_Begin ("class=\"MCH_BOTTOM\""); // Bottom
/* Write stem (row[1]) */
Tst_WriteQstStem (row[1],"MCH_TCH_STEM",
/* Write stem */
Tst_WriteQstStem (Stem,"MCH_TCH_STEM",
true); // Visible
/* Get media (row[2]) */
Question.Media.MedCod = Str_ConvertStrCodToLongCod (row[2]);
Med_GetMediaDataByCod (&Question.Media);
/* Show media */
Med_ShowMedia (&Question.Media,
"TEST_MED_EDIT_LIST_STEM_CONTAINER",
"TEST_MED_EDIT_LIST_STEM");
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
/***** Write answers? *****/
switch (Match->Status.Showing)
{
@ -2983,7 +2967,7 @@ static void Mch_ShowQuestionAndAnswersTch (const struct Match *Match)
/*****************************************************************************/
static void Mch_WriteAnswersMatchResult (const struct Match *Match,
struct Tst_Question *Question,
const struct Tst_Question *Question,
const char *Class,bool ShowResult)
{
/***** Write answer depending on type *****/
@ -3000,13 +2984,11 @@ static void Mch_WriteAnswersMatchResult (const struct Match *Match,
/*****************************************************************************/
void Mch_WriteChoiceAnsViewMatch (const struct Match *Match,
struct Tst_Question *Question,
const struct Tst_Question *Question,
const char *Class,bool ShowResult)
{
unsigned NumOpt;
bool RowIsOpen = false;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumRespondersQst;
unsigned NumRespondersAns;
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION]; // Indexes of all answers of this question
@ -3014,47 +2996,6 @@ void Mch_WriteChoiceAnsViewMatch (const struct Match *Match,
/***** Get number of users who have answered this question from database *****/
NumRespondersQst = Mch_GetNumUsrsWhoAnsweredQst (Match->MchCod,Match->Status.QstInd);
/***** Get answers of a question from database *****/
Tst_GetAnswersQst (Question,&mysql_res,
false); // Don't shuffle
/*
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 answer */
if (!Tst_AllocateTextChoiceAnswer (Question,NumOpt))
/* Abort on error */
Ale_ShowAlertsAndExit ();
/* Copy 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);
/* Get media (row[3]) */
Question->Answer.Options[NumOpt].Media.MedCod = Str_ConvertStrCodToLongCod (row[3]);
Med_GetMediaDataByCod (&Question->Answer.Options[NumOpt].Media);
/* Get if correct (row[4]) */
Question->Answer.Options[NumOpt].Correct = (row[4][0] == 'Y');
}
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_res);
/***** Get indexes for this question in match *****/
Mch_GetIndexes (Match->MchCod,Match->Status.QstInd,Indexes);
@ -3083,7 +3024,13 @@ void Mch_WriteChoiceAnsViewMatch (const struct 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

@ -118,7 +118,7 @@ unsigned Mch_GetNumUnfinishedMchsInGame (long GamCod);
bool Mch_CheckIfICanPlayThisMatchBasedOnGrps (const struct Match *Match);
void Mch_WriteChoiceAnsViewMatch (const struct Match *Match,
struct Tst_Question *Question,
const struct Tst_Question *Question,
const char *Class,bool ShowResult);
bool Mch_RegisterMeAsPlayerInMatch (struct Match *Match);

View File

@ -149,10 +149,10 @@ static void Tst_ShowTestExamToFillIt (struct TstExa_Exam *Exam,
unsigned NumExamsGeneratedByMe,
Tst_RequestOrConfirm_t RequestOrConfirm);
static void Tst_WriteQstAndAnsSeeing (struct TstExa_Exam *Exam,
static void Tst_WriteQstAndAnsSeeing (const struct TstExa_Exam *Exam,
unsigned NumQst,
struct Tst_Question *Question,
MYSQL_ROW row);
const struct Tst_Question *Question,
const char *Stem);
static void Tst_PutFormToEditQstMedia (const struct Media *Media,int NumMediaInForm,
bool OptionsDisabled);
@ -185,8 +185,8 @@ static void Tst_GetQuestions (struct Tst_Test *Test,MYSQL_RES **mysql_res);
static void Tst_GetQuestionsForNewTestFromDB (struct Tst_Test *Test,
struct TstExa_Exam *Exam);
static void Tst_GenerateChoiceIndexesDependingOnShuffle (struct TstExa_Exam *Exam,
unsigned NumQst,
bool Shuffle);
unsigned NumQst,
bool Shuffle);
static void Tst_ListOneQstToEdit (struct Tst_Test *Test);
static void Tst_ListOneOrMoreQuestionsForEdition (struct Tst_Test *Test,
@ -198,31 +198,26 @@ static void Tst_ListOneOrMoreQuestionsForSelection (unsigned NumQsts,
static void Tst_WriteQuestionRowForSelection (unsigned NumQst,
struct Tst_Question *Question);
static void Tst_WriteAnswersSeeing (struct TstExa_Exam *Exam,
static void Tst_WriteAnswersSeeing (const struct TstExa_Exam *Exam,
unsigned NumQst,
struct Tst_Question *Question);
const struct Tst_Question *Question);
static void Tst_WriteIntAnsListing (const struct Tst_Question *Question,
MYSQL_RES *mysql_res);
static void Tst_WriteIntAnsListing (const struct Tst_Question *Question);
static void Tst_WriteIntAnsSeeing (const struct TstExa_Exam *Exam,
unsigned NumQst);
static void Tst_WriteFloatAnsEdit (const struct Tst_Question *Question,
MYSQL_RES *mysql_res);
static void Tst_WriteFloatAnsEdit (const struct Tst_Question *Question);
static void Tst_WriteFloatAnsSeeing (const struct TstExa_Exam *Exam,
unsigned NumQst);
static void Tst_WriteTFAnsListing (const struct Tst_Question *Question,
MYSQL_RES *mysql_res);
static void Tst_WriteTFAnsListing (const struct Tst_Question *Question);
static void Tst_WriteTFAnsSeeing (const struct TstExa_Exam *Exam,
unsigned NumQst);
static void Tst_WriteChoiceAnsListing (struct Tst_Question *Question,
MYSQL_RES *mysql_res);
static void Tst_WriteChoiceAnsListing (const struct Tst_Question *Question);
static void Tst_WriteChoiceAnsSeeing (const struct TstExa_Exam *Exam,
unsigned NumQst,
struct Tst_Question *Question,
MYSQL_RES *mysql_res);
const struct Tst_Question *Question);
static void Tst_WriteTextAnsSeeing (const struct TstExa_Exam *Exam,
unsigned NumQst);
@ -870,11 +865,10 @@ static void Tst_ShowTestExamToFillIt (struct TstExa_Exam *Exam,
{
extern const char *Hlp_ASSESSMENT_Tests;
extern const char *Txt_Test;
// extern const char *Txt_Done_assess_test;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumQst;
struct Tst_Question Question;
char Stem[Cns_MAX_BYTES_TEXT + 1];
char Feedback[Cns_MAX_BYTES_TEXT + 1];
static const Act_Action_t Action[Tst_NUM_REQUEST_OR_CONFIRM] =
{
[Tst_REQUEST] = ActReqAssTst,
@ -912,17 +906,12 @@ static void Tst_ShowTestExamToFillIt (struct TstExa_Exam *Exam,
Question.QstCod = Exam->Questions[NumQst].QstCod;
/* Show question */
if (Tst_GetOneQuestionByCod (Question.QstCod,&mysql_res)) // Question exists
{
/* Get row of the result of the query */
row = mysql_fetch_row (mysql_res);
/* Write question and answers */
Tst_WriteQstAndAnsSeeing (Exam,NumQst,&Question,row);
}
else
if (!Tst_GetQstDataFromDB (&Question,Stem,Feedback)) // Question exists
Lay_ShowErrorAndExit ("Wrong question.");
/* Write question and answers */
Tst_WriteQstAndAnsSeeing (Exam,NumQst,&Question,Stem);
/* Destroy test question */
Tst_QstDestructor (&Question);
}
@ -985,30 +974,17 @@ void Tst_ShowTagList (unsigned NumTags,MYSQL_RES *mysql_res)
/********** Write a row of a test, with one question and its answer **********/
/*****************************************************************************/
static void Tst_WriteQstAndAnsSeeing (struct TstExa_Exam *Exam,
static void Tst_WriteQstAndAnsSeeing (const struct TstExa_Exam *Exam,
unsigned NumQst,
struct Tst_Question *Question,
MYSQL_ROW row)
const struct Tst_Question *Question,
const char *Stem)
{
/*
row[0] UNIX_TIMESTAMP(EditTime)
row[1] AnsType
row[2] Shuffle
row[3] Stem
row[4] Feedback
row[5] MedCod
row[6] NumHits
row[7] NumHitsNotBlank
row[8] Score
*/
/***** Begin row *****/
HTM_TR_Begin (NULL);
/***** Number of question and answer type (row[1]) *****/
/***** Number of question and answer type *****/
HTM_TD_Begin ("class=\"RT COLOR%u\"",Gbl.RowEvenOdd);
Tst_WriteNumQst (NumQst + 1);
Question->Answer.Type = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
Tst_WriteAnswerType (Question->Answer.Type);
HTM_TD_End ();
@ -1018,12 +994,10 @@ static void Tst_WriteQstAndAnsSeeing (struct TstExa_Exam *Exam,
/* Write parameter with question code */
Tst_WriteParamQstCod (NumQst,Question->QstCod);
/* Stem (row[3]) */
Tst_WriteQstStem (row[3],"TEST_EXA",true);
/* Stem */
Tst_WriteQstStem (Stem,"TEST_EXA",true);
/* Media (row[5]) */
Question->Media.MedCod = Str_ConvertStrCodToLongCod (row[5]);
Med_GetMediaDataByCod (&Question->Media);
/* Media */
Med_ShowMedia (&Question->Media,
"TEST_MED_SHOW_CONT",
"TEST_MED_SHOW");
@ -2613,8 +2587,8 @@ static void Tst_GetQuestionsForNewTestFromDB (struct Tst_Test *Test,
/*****************************************************************************/
static void Tst_GenerateChoiceIndexesDependingOnShuffle (struct TstExa_Exam *Exam,
unsigned NumQst,
bool Shuffle)
unsigned NumQst,
bool Shuffle)
{
extern const char *Par_SEPARATOR_PARAM_MULTIPLE;
struct Tst_Question Question;
@ -2709,29 +2683,6 @@ static void Tst_ListOneQstToEdit (struct Tst_Test *Test)
Box_BoxEnd ();
}
/*****************************************************************************/
/*********************** Get data of one test question ***********************/
/*****************************************************************************/
// Return true on success, false on error
bool Tst_GetOneQuestionByCod (long QstCod,MYSQL_RES **mysql_res)
{
/***** Get data of a question from database *****/
return (DB_QuerySELECT (mysql_res,"can not get data of a question",
"SELECT UNIX_TIMESTAMP(EditTime)," // row[0]
"AnsType," // row[1]
"Shuffle," // row[2]
"Stem," // row[3]
"Feedback," // row[4]
"MedCod," // row[5]
"NumHits," // row[6]
"NumHitsNotBlank," // row[7]
"Score" // row[8]
" FROM tst_questions"
" WHERE QstCod=%ld",
QstCod) == 1);
}
/*****************************************************************************/
/****************** List for edition one or more test questions **************/
/*****************************************************************************/
@ -2853,32 +2804,14 @@ static void Tst_WriteHeadingRowQuestionsForEdition (const struct Tst_Test *Test)
static void Tst_WriteQuestionListing (struct Tst_Test *Test,unsigned NumQst)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
static unsigned UniqueId = 0;
char *Id;
time_t TimeUTC;
unsigned long NumHitsThisQst;
unsigned long NumHitsNotBlankThisQst;
double Score;
char Stem[Cns_MAX_BYTES_TEXT + 1];
char Feedback[Cns_MAX_BYTES_TEXT + 1];
/***** Get and show question data *****/
if (Tst_GetOneQuestionByCod (Test->Question.QstCod,&mysql_res))
if (Tst_GetQstDataFromDB (&Test->Question,Stem,Feedback))
{
/***** Get row from database *****/
row = mysql_fetch_row (mysql_res);
/*
row[0] UNIX_TIMESTAMP(EditTime)
row[1] AnsType
row[2] Shuffle
row[3] Stem
row[4] Feedback
row[5] MedCod
row[6] NumHits
row[7] NumHitsNotBlank
row[8] Score
*/
/***** Begin table row *****/
HTM_TR_Begin (NULL);
@ -2901,10 +2834,9 @@ static void Tst_WriteQuestionListing (struct Tst_Test *Test,unsigned NumQst)
HTM_TD_End ();
/* Number of question and answer type (row[1]) */
/* Number of question and answer type */
HTM_TD_Begin ("class=\"RT COLOR%u\"",Gbl.RowEvenOdd);
Tst_WriteNumQst (NumQst + 1);
Test->Question.Answer.Type = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
Tst_WriteAnswerType (Test->Question.Answer.Type);
HTM_TD_End ();
@ -2914,12 +2846,11 @@ static void Tst_WriteQuestionListing (struct Tst_Test *Test,unsigned NumQst)
HTM_TD_End ();
/* Date (row[0] has the UTC date-time) */
TimeUTC = Dat_GetUNIXTimeFromStr (row[0]);
if (asprintf (&Id,"tst_date_%u",++UniqueId) < 0)
Lay_NotEnoughMemoryExit ();
HTM_TD_Begin ("id=\"%s\" class=\"DAT_SMALL CT COLOR%u\"",
Id,Gbl.RowEvenOdd);
Dat_WriteLocalDateHMSFromUTC (Id,TimeUTC,
Dat_WriteLocalDateHMSFromUTC (Id,Test->Question.EditTime,
Gbl.Prefs.DateFormat,Dat_SEPARATOR_BREAK,
true,true,false,0x7);
HTM_TD_End ();
@ -2944,69 +2875,49 @@ static void Tst_WriteQuestionListing (struct Tst_Test *Test,unsigned NumQst)
Par_PutHiddenParamUnsigned (NULL,"Order",(unsigned) Test->SelectedOrder);
HTM_INPUT_CHECKBOX ("Shuffle",HTM_SUBMIT_ON_CHANGE,
"value=\"Y\"%s",
row[2][0] == 'Y' ? " checked=\"checked\"" :
"");
Test->Question.Answer.Shuffle ? " checked=\"checked\"" :
"");
Frm_EndForm ();
}
HTM_TD_End ();
/* Stem (row[3]) */
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
Tst_WriteQstStem (row[3],"TEST_EDI",
Tst_WriteQstStem (Stem,"TEST_EDI",
true); // Visible
/***** Get and show media (row[5]) *****/
Test->Question.Media.MedCod = Str_ConvertStrCodToLongCod (row[5]);
Med_GetMediaDataByCod (&Test->Question.Media);
Med_ShowMedia (&Test->Question.Media,
"TEST_MED_EDIT_LIST_CONT",
"TEST_MED_EDIT_LIST");
/* Feedback (row[4]) and answers */
Tst_WriteQstFeedback (row[4],"TEST_EDI_LIGHT");
Tst_WriteQstFeedback (Feedback,"TEST_EDI_LIGHT");
Tst_WriteAnswersListing (&Test->Question);
HTM_TD_End ();
/* Get number of hits
(number of times that the question has been answered,
including blank answers) (row[6]) */
if (sscanf (row[6],"%lu",&NumHitsThisQst) != 1)
Lay_ShowErrorAndExit ("Wrong number of hits to a question.");
/* Get number of hits not blank
(number of times that the question has been answered
with a not blank answer) (row[7]) */
if (sscanf (row[7],"%lu",&NumHitsNotBlankThisQst) != 1)
Lay_ShowErrorAndExit ("Wrong number of hits not blank to a question.");
/* Get the acumulated score of the question (row[8]) */
Str_SetDecimalPointToUS (); // To get the decimal point as a dot
if (sscanf (row[8],"%lf",&Score) != 1)
Lay_ShowErrorAndExit ("Wrong score of a question.");
Str_SetDecimalPointToLocal (); // Return to local system
/* Number of times this question has been answered */
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
HTM_UnsignedLong (NumHitsThisQst);
HTM_UnsignedLong (Test->Question.NumHits);
HTM_TD_End ();
/* Average score */
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
if (NumHitsThisQst)
HTM_Double2Decimals (Score / (double) NumHitsThisQst);
if (Test->Question.NumHits)
HTM_Double2Decimals (Test->Question.Score / (double) Test->Question.NumHits);
else
HTM_Txt ("N.A.");
HTM_TD_End ();
/* Number of times this question has been answered (not blank) */
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
HTM_UnsignedLong (NumHitsNotBlankThisQst);
HTM_UnsignedLong (Test->Question.NumHitsNotBlank);
HTM_TD_End ();
/* Average score (not blank) */
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
if (NumHitsNotBlankThisQst)
HTM_Double2Decimals (Score / (double) NumHitsNotBlankThisQst);
if (Test->Question.NumHitsNotBlank)
HTM_Double2Decimals (Test->Question.Score / (double) Test->Question.NumHitsNotBlank);
else
HTM_Txt ("N.A.");
HTM_TD_End ();
@ -3014,9 +2925,6 @@ static void Tst_WriteQuestionListing (struct Tst_Test *Test,unsigned NumQst)
/***** End table row *****/
HTM_TR_End ();
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
/*****************************************************************************/
@ -3108,29 +3016,14 @@ static void Tst_WriteQuestionRowForSelection (unsigned NumQst,
struct Tst_Question *Question)
{
extern const char *Txt_TST_STR_ANSWER_TYPES[Tst_NUM_ANS_TYPES];
MYSQL_RES *mysql_res;
MYSQL_ROW row;
char Stem[Cns_MAX_BYTES_TEXT + 1];
char Feedback[Cns_MAX_BYTES_TEXT + 1];
static unsigned UniqueId = 0;
char *Id;
time_t TimeUTC;
/***** Get and show questvoidion data *****/
if (Tst_GetOneQuestionByCod (Question->QstCod,&mysql_res))
if (Tst_GetQstDataFromDB (Question,Stem,Feedback))
{
/***** Get row of the result of the query *****/
row = mysql_fetch_row (mysql_res);
/*
row[0] UNIX_TIMESTAMP(EditTime)
row[1] AnsType
row[2] Shuffle
row[3] Stem
row[4] Feedback
row[5] MedCod
row[6] NumHits
row[7] NumHitsNotBlank
row[8] Score
*/
/***** Begin table row *****/
HTM_TR_Begin (NULL);
@ -3153,12 +3046,11 @@ static void Tst_WriteQuestionRowForSelection (unsigned NumQst,
HTM_TD_End ();
/* Write the date (row[0] has the UTC date-time) */
TimeUTC = Dat_GetUNIXTimeFromStr (row[0]);
if (asprintf (&Id,"tst_date_%u",++UniqueId) < 0)
Lay_NotEnoughMemoryExit ();
HTM_TD_Begin ("id=\"%s\" class=\"DAT_SMALL CT COLOR%u\">",
Id,Gbl.RowEvenOdd);
Dat_WriteLocalDateHMSFromUTC (Id,TimeUTC,
Dat_WriteLocalDateHMSFromUTC (Id,Question->EditTime,
Gbl.Prefs.DateFormat,Dat_SEPARATOR_BREAK,
true,true,false,0x7);
HTM_TD_End ();
@ -3169,34 +3061,31 @@ static void Tst_WriteQuestionRowForSelection (unsigned NumQst,
Tst_GetAndWriteTagsQst (Question->QstCod);
HTM_TD_End ();
/* Write the question type (row[1]) */
Question->Answer.Type = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
/* Write the question type */
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
HTM_TxtF ("%s&nbsp;",Txt_TST_STR_ANSWER_TYPES[Question->Answer.Type]);
HTM_TD_End ();
/* Write if shuffle is enabled (row[2]) */
/* Write if shuffle is enabled */
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
HTM_INPUT_CHECKBOX ("Shuffle",HTM_DONT_SUBMIT_ON_CHANGE,
"value=\"Y\"%s disabled=\"disabled\"",
row[2][0] == 'Y' ? " checked=\"checked\"" :
"");
Question->Answer.Shuffle ? " checked=\"checked\"" :
"");
HTM_TD_End ();
/* Write stem (row[3]) */
/* Write stem */
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
Tst_WriteQstStem (row[3],"TEST_EDI",
Tst_WriteQstStem (Stem,"TEST_EDI",
true); // Visible
/***** Get and show media (row[5]) *****/
Question->Media.MedCod = Str_ConvertStrCodToLongCod (row[5]);
Med_GetMediaDataByCod (&Question->Media);
/***** Get and show media *****/
Med_ShowMedia (&Question->Media,
"TEST_MED_EDIT_LIST_CONT",
"TEST_MED_EDIT_LIST");
/* Write feedback (row[4]) */
Tst_WriteQstFeedback (row[4],"TEST_EDI_LIGHT");
/* Write feedback */
Tst_WriteQstFeedback (Feedback,"TEST_EDI_LIGHT");
/* Write answers */
Tst_WriteAnswersListing (Question);
@ -3260,56 +3149,38 @@ void Tst_GetAnswersQst (struct Tst_Question *Question,MYSQL_RES **mysql_res,
/**************** Get and write the answers of a test question ***************/
/*****************************************************************************/
void Tst_WriteAnswersListing (struct Tst_Question *Question)
void Tst_WriteAnswersListing (const struct Tst_Question *Question)
{
MYSQL_RES *mysql_res;
/***** Get answers *****/
Tst_GetAnswersQst (Question,&mysql_res,
false); // Don't shuffle
/*
row[0] AnsInd
row[1] Answer
row[2] Feedback
row[3] MedCod
row[4] Correct
*/
/***** Write answers *****/
switch (Question->Answer.Type)
{
case Tst_ANS_INT:
Tst_WriteIntAnsListing (Question,mysql_res);
Tst_WriteIntAnsListing (Question);
break;
case Tst_ANS_FLOAT:
Tst_WriteFloatAnsEdit (Question,mysql_res);
Tst_WriteFloatAnsEdit (Question);
break;
case Tst_ANS_TRUE_FALSE:
Tst_WriteTFAnsListing (Question,mysql_res);
Tst_WriteTFAnsListing (Question);
break;
case Tst_ANS_UNIQUE_CHOICE:
case Tst_ANS_MULTIPLE_CHOICE:
case Tst_ANS_TEXT:
Tst_WriteChoiceAnsListing (Question,mysql_res);
Tst_WriteChoiceAnsListing (Question);
break;
default:
break;
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
/*****************************************************************************/
/************** Write answers of a question when seeing a test ***************/
/*****************************************************************************/
static void Tst_WriteAnswersSeeing (struct TstExa_Exam *Exam,
static void Tst_WriteAnswersSeeing (const struct TstExa_Exam *Exam,
unsigned NumQst,
struct Tst_Question *Question)
const struct Tst_Question *Question)
{
MYSQL_RES *mysql_res;
/***** Write answer depending on type *****/
switch (Question->Answer.Type)
{
@ -3324,15 +3195,7 @@ static void Tst_WriteAnswersSeeing (struct TstExa_Exam *Exam,
break;
case Tst_ANS_UNIQUE_CHOICE:
case Tst_ANS_MULTIPLE_CHOICE:
/* Get answer of a question from database */
Tst_GetAnswersQst (Question,&mysql_res,
false); // Don't shuffle
/* Write answer */
Tst_WriteChoiceAnsSeeing (Exam,NumQst,Question,mysql_res);
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_res);
Tst_WriteChoiceAnsSeeing (Exam,NumQst,Question);
break;
case Tst_ANS_TEXT:
Tst_WriteTextAnsSeeing (Exam,NumQst);
@ -3360,22 +3223,10 @@ bool Tst_CheckIfQuestionIsValidForGame (long QstCod)
/****************** Write integer answer when editing a test *****************/
/*****************************************************************************/
static void Tst_WriteIntAnsListing (const struct Tst_Question *Question,
MYSQL_RES *mysql_res)
static void Tst_WriteIntAnsListing (const struct Tst_Question *Question)
{
MYSQL_ROW row;
/*
row[0] AnsInd
row[1] Answer
row[2] Feedback
row[3] MedCod
row[4] Correct
*/
Tst_CheckIfNumberOfAnswersIsOne (Question);
row = mysql_fetch_row (mysql_res);
HTM_SPAN_Begin ("class=\"TEST_EDI\"");
HTM_TxtF ("(%ld)",Tst_GetIntAnsFromStr (row[1]));
HTM_TxtF ("(%ld)",Question->Answer.Integer);
HTM_SPAN_End ();
}
@ -3400,35 +3251,13 @@ static void Tst_WriteIntAnsSeeing (const struct TstExa_Exam *Exam,
/****************** Write float answer when editing a test *******************/
/*****************************************************************************/
static void Tst_WriteFloatAnsEdit (const struct Tst_Question *Question,
MYSQL_RES *mysql_res)
static void Tst_WriteFloatAnsEdit (const struct Tst_Question *Question)
{
MYSQL_ROW row;
unsigned i;
double FloatNum[2];
/*
row[0] AnsInd
row[1] Answer
row[2] Feedback
row[3] MedCod
row[4] Correct
*/
if (Question->Answer.NumOptions != 2)
Lay_ShowErrorAndExit ("Wrong float range.");
for (i = 0;
i < 2;
i++)
{
row = mysql_fetch_row (mysql_res);
FloatNum[i] = Str_GetDoubleFromStr (row[1]);
}
HTM_SPAN_Begin ("class=\"TEST_EDI\"");
HTM_Txt ("([");
HTM_Double (FloatNum[0]);
HTM_Double (Question->Answer.FloatingPoint[0]);
HTM_Txt ("; ");
HTM_Double (FloatNum[1]);
HTM_Double (Question->Answer.FloatingPoint[1]);
HTM_Txt ("])");
HTM_SPAN_End ();
}
@ -3454,27 +3283,12 @@ static void Tst_WriteFloatAnsSeeing (const struct TstExa_Exam *Exam,
/*********** Write false / true answer when listing test questions ***********/
/*****************************************************************************/
static void Tst_WriteTFAnsListing (const struct Tst_Question *Question,
MYSQL_RES *mysql_res)
static void Tst_WriteTFAnsListing (const struct Tst_Question *Question)
{
MYSQL_ROW row;
/*
row[0] AnsInd
row[1] Answer
row[2] Feedback
row[3] MedCod
row[4] Correct
*/
Tst_CheckIfNumberOfAnswersIsOne (Question);
/***** Get answer true or false *****/
row = mysql_fetch_row (mysql_res);
/***** Write answer *****/
HTM_SPAN_Begin ("class=\"TEST_EDI\"");
HTM_Txt ("(");
Tst_WriteAnsTF (row[1][0]);
Tst_WriteAnsTF (Question->Answer.TF);
HTM_Txt (")");
HTM_SPAN_End ();
}
@ -3526,65 +3340,55 @@ void Tst_WriteAnsTF (char AnsTF)
/**** Write single or multiple choice answer when listing test questions *****/
/*****************************************************************************/
static void Tst_WriteChoiceAnsListing (struct Tst_Question *Question,
MYSQL_RES *mysql_res)
static void Tst_WriteChoiceAnsListing (const struct Tst_Question *Question)
{
extern const char *Txt_TST_Answer_given_by_the_teachers;
MYSQL_ROW row;
unsigned NumOpt;
char *AnswerTxt;
char *Feedback;
size_t LengthAnswerTxt;
size_t LengthFeedback;
/*
row[0] AnsInd
row[1] Answer
row[2] Feedback
row[3] MedCod
row[4] Correct
*/
HTM_TABLE_BeginPadding (2);
for (NumOpt = 0;
NumOpt < Question->Answer.NumOptions;
NumOpt++)
{
row = mysql_fetch_row (mysql_res);
/* 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 answer (row[1]), that is in HTML, to rigorous HTML */
LengthAnswerTxt = strlen (row[1]) * Str_MAX_BYTES_PER_CHAR;
if ((AnswerTxt = (char *) malloc (LengthAnswerTxt + 1)) == NULL)
Lay_NotEnoughMemoryExit ();
Str_Copy (AnswerTxt,row[1],
LengthAnswerTxt);
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
AnswerTxt,LengthAnswerTxt,false);
/* Convert the feedback (row[2]), that is in HTML, to rigorous HTML */
/* Convert the feedback, that is in HTML, to rigorous HTML */
LengthFeedback = 0;
Feedback = NULL;
if (row[2])
if (row[2][0])
if (Question->Answer.Options[NumOpt].Feedback)
if (Question->Answer.Options[NumOpt].Feedback[0])
{
LengthFeedback = strlen (row[2]) * Str_MAX_BYTES_PER_CHAR;
LengthFeedback = strlen (Question->Answer.Options[NumOpt].Feedback) * Str_MAX_BYTES_PER_CHAR;
if ((Feedback = (char *) malloc (LengthFeedback + 1)) == NULL)
Lay_NotEnoughMemoryExit ();
Str_Copy (Feedback,row[2],
Str_Copy (Feedback,Question->Answer.Options[NumOpt].Feedback,
LengthFeedback);
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
Feedback,LengthFeedback,false);
}
/* Get media (row[3]) */
Question->Answer.Options[NumOpt].Media.MedCod = Str_ConvertStrCodToLongCod (row[3]);
Med_GetMediaDataByCod (&Question->Answer.Options[NumOpt].Media);
HTM_TR_Begin (NULL);
/* Put an icon that indicates whether the answer
is correct or wrong (row[4]) */
/* Put an icon that indicates whether the answer is correct or wrong */
HTM_TD_Begin ("class=\"BT%u\"",Gbl.RowEvenOdd);
if (row[4][0] == 'Y')
if (Question->Answer.Options[NumOpt].Correct)
Ico_PutIcon ("check.svg",Txt_TST_Answer_given_by_the_teachers,"CONTEXT_ICO_16x16");
HTM_TD_End ();
@ -3597,7 +3401,8 @@ static void Tst_WriteChoiceAnsListing (struct Tst_Question *Question,
/* Write the text of the answer and the media */
HTM_DIV_Begin ("class=\"TEST_EDI\"");
HTM_Txt (AnswerTxt);
if (LengthAnswerTxt)
HTM_Txt (AnswerTxt);
Med_ShowMedia (&Question->Answer.Options[NumOpt].Media,
"TEST_MED_EDIT_LIST_CONT",
"TEST_MED_EDIT_LIST");
@ -3627,23 +3432,12 @@ static void Tst_WriteChoiceAnsListing (struct Tst_Question *Question,
static void Tst_WriteChoiceAnsSeeing (const struct TstExa_Exam *Exam,
unsigned NumQst,
struct Tst_Question *Question,
MYSQL_RES *mysql_res)
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"
/*
row[0] AnsInd
row[1] Answer
row[2] Feedback
row[3] MedCod
row[4] Correct
*/
/***** Get text and correctness of answers for this question
from database (one row per answer) *****/
Tst_GetChoiceAns (Question,mysql_res);
/***** Get indexes for this question from string *****/
TstExa_GetIndexesFromStr (Exam->Questions[NumQst].StrIndexes,Indexes);
@ -4041,9 +3835,11 @@ static int Tst_CountNumAnswerTypesInList (const struct Tst_AnswerTypes *AnswerTy
void Tst_ShowFormEditOneQst (void)
{
extern const char *Txt_Question_removed;
struct Tst_Question Question;
char Stem[Cns_MAX_BYTES_TEXT + 1];
char Feedback[Cns_MAX_BYTES_TEXT + 1];
bool PutFormToEditQuestion;
/***** Create test question *****/
Tst_QstConstructor (&Question);
@ -4051,11 +3847,16 @@ void Tst_ShowFormEditOneQst (void)
/***** Get question data *****/
Question.QstCod = Tst_GetQstCod ();
Stem[0] = Feedback[0] = '\0';
if (Question.QstCod > 0) // If question already exists in the database
Tst_GetQstDataFromDB (&Question,Stem,Feedback);
if (Question.QstCod > 0) // Question already exists in the database
PutFormToEditQuestion = Tst_GetQstDataFromDB (&Question,Stem,Feedback);
else // New question
PutFormToEditQuestion = true;
/***** Put form to edit question *****/
Tst_PutFormEditOneQst (&Question,Stem,Feedback);
if (PutFormToEditQuestion)
Tst_PutFormEditOneQst (&Question,Stem,Feedback);
else
Ale_ShowAlert (Ale_WARNING,Txt_Question_removed);
/***** Destroy test question *****/
Tst_QstDestructor (&Question);
@ -4565,6 +4366,11 @@ void Tst_QstConstructor (struct Tst_Question *Question)
Question->Answer.Integer = 0;
Question->Answer.FloatingPoint[0] =
Question->Answer.FloatingPoint[1] = 0.0;
/* Initialize stats */
Question->NumHits =
Question->NumHitsNotBlank = 0;
Question->Score = 0.0;
}
/*****************************************************************************/
@ -4701,9 +4507,8 @@ Tst_AnswerType_t Tst_GetQstAnswerType (long QstCod)
/*****************************************************************************/
/****************** Get data of a question from database *********************/
/*****************************************************************************/
// If question does not exist ==> set question code to -1
void Tst_GetQstDataFromDB (struct Tst_Question *Question,
bool Tst_GetQstDataFromDB (struct Tst_Question *Question,
char Stem[Cns_MAX_BYTES_TEXT + 1],
char Feedback[Cns_MAX_BYTES_TEXT + 1])
{
@ -4721,7 +4526,10 @@ void Tst_GetQstDataFromDB (struct Tst_Question *Question,
"Shuffle," // row[2]
"Stem," // row[3]
"Feedback," // row[4]
"MedCod" // row[5]
"MedCod," // row[5]
"NumHits," // row[6]
"NumHitsNotBlank," // row[7]
"Score" // row[8]
" FROM tst_questions"
" WHERE QstCod=%ld"
" AND CrsCod=%ld", // Extra check
@ -4759,6 +4567,24 @@ void Tst_GetQstDataFromDB (struct Tst_Question *Question,
Question->Media.MedCod = Str_ConvertStrCodToLongCod (row[5]);
Med_GetMediaDataByCod (&Question->Media);
/* Get number of hits
(number of times that the question has been answered,
including blank answers) (row[6]) */
if (sscanf (row[6],"%lu",&Question->NumHits) != 1)
Question->NumHits = 0;
/* Get number of hits not blank
(number of times that the question has been answered
with a not blank answer) (row[7]) */
if (sscanf (row[7],"%lu",&Question->NumHitsNotBlank) != 1)
Question->NumHitsNotBlank = 0;
/* Get the acumulated score of the question (row[8]) */
Str_SetDecimalPointToUS (); // To get the decimal point as a dot
if (sscanf (row[8],"%lf",&Question->Score) != 1)
Question->Score = 0.0;
Str_SetDecimalPointToLocal (); // Return to local system
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_res);
@ -4844,11 +4670,11 @@ void Tst_GetQstDataFromDB (struct Tst_Question *Question,
}
}
}
else
Question->QstCod = -1L;
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_res);
return QuestionExists;
}
/*****************************************************************************/

View File

@ -117,6 +117,9 @@ struct Tst_Question
long Integer;
double FloatingPoint[2];
} Answer;
unsigned long NumHits;
unsigned long NumHitsNotBlank;
double Score;
};
struct Tst_Test
@ -170,13 +173,12 @@ void Tst_RequestSelectTestsForGame (void);
void Tst_ListQuestionsToEdit (void);
void Tst_ListQuestionsToSelect (void);
bool Tst_GetOneQuestionByCod (long QstCod,MYSQL_RES **mysql_res);
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_WriteAnswersListing (struct Tst_Question *Question);
void Tst_WriteAnswersListing (const 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);
@ -200,7 +202,7 @@ void Tst_QstDestructor (struct Tst_Question *Question);
bool Tst_AllocateTextChoiceAnswer (struct Tst_Question *Question,unsigned NumOpt);
Tst_AnswerType_t Tst_GetQstAnswerType (long QstCod);
void Tst_GetQstDataFromDB (struct Tst_Question *Question,
bool Tst_GetQstDataFromDB (struct Tst_Question *Question,
char Stem[Cns_MAX_BYTES_TEXT + 1],
char Feedback[Cns_MAX_BYTES_TEXT + 1]);
Tst_AnswerType_t Tst_ConvertFromStrAnsTypDBToAnsTyp (const char *StrAnsTypeBD);

View File

@ -245,8 +245,7 @@ void TstExa_ShowExamAfterAssess (struct TstExa_Exam *Exam)
Question.QstCod = Exam->Questions[NumQst].QstCod;
/***** Get question data *****/
Tst_GetQstDataFromDB (&Question,Stem,Feedback);
if (Question.QstCod > 0) // Question exists
if (Tst_GetQstDataFromDB (&Question,Stem,Feedback)) // Question exists
{
/***** Write question and answers *****/
TstExa_WriteQstAndAnsExam (&Gbl.Usrs.Me.UsrDat,
@ -2218,13 +2217,12 @@ void TstExa_ShowExamAnswers (struct UsrData *UsrDat,
Question.QstCod = Exam->Questions[NumQst].QstCod;
/***** Get question data *****/
Tst_GetQstDataFromDB (&Question,Stem,Feedback);
/***** Write questions and answers *****/
TstExa_WriteQstAndAnsExam (UsrDat,
Exam,NumQst,
&Question,Stem,Feedback,
Visibility);
if (Tst_GetQstDataFromDB (&Question,Stem,Feedback)) // Question exists?
/***** Write questions and answers *****/
TstExa_WriteQstAndAnsExam (UsrDat,
Exam,NumQst,
&Question,Stem,Feedback,
Visibility);
/***** Destroy test question *****/
Tst_QstDestructor (&Question);

View File

@ -71,7 +71,7 @@ static void TsI_PutCreateXMLParam (void);
static void TsI_ExportQuestion (struct Tst_Question *Question,FILE *FileXML);
static void TsI_GetAndWriteTagsXML (long QstCod,FILE *FileXML);
static void TsI_WriteAnswersOfAQstXML (struct Tst_Question *Question,
static void TsI_WriteAnswersOfAQstXML (const struct Tst_Question *Question,
FILE *FileXML);
static void TsI_ReadQuestionsFromXMLFileAndStoreInDB (const char *FileNameXML);
static void TsI_ImportQuestionsFromXMLBuffer (const char *XMLBuffer);
@ -259,27 +259,12 @@ static void TsI_ExportQuestion (struct Tst_Question *Question,FILE *FileXML)
{
extern const char *Tst_StrAnswerTypesXML[Tst_NUM_ANS_TYPES];
extern const char *Txt_NEW_LINE;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
char Stem[Cns_MAX_BYTES_TEXT + 1];
char Feedback[Cns_MAX_BYTES_TEXT + 1];
if (Tst_GetOneQuestionByCod (Question->QstCod,&mysql_res))
if (Tst_GetQstDataFromDB (Question,Stem,Feedback))
{
/***** Get row *****/
row = mysql_fetch_row (mysql_res);
/*
row[0] UNIX_TIMESTAMP(EditTime)
row[1] AnsType
row[2] Shuffle
row[3] Stem
row[4] Feedback
row[5] MedCod
row[6] NumHits
row[7] NumHitsNotBlank
row[8] Score
*/
/***** Write the answer type (row[1]) *****/
Question->Answer.Type = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
/***** Write the answer type *****/
fprintf (FileXML,"<question type=\"%s\">%s",
Tst_StrAnswerTypesXML[Question->Answer.Type],Txt_NEW_LINE);
@ -288,24 +273,23 @@ static void TsI_ExportQuestion (struct Tst_Question *Question,FILE *FileXML)
TsI_GetAndWriteTagsXML (Question->QstCod,FileXML);
fprintf (FileXML,"</tags>%s",Txt_NEW_LINE);
/***** Write the stem (row[3]), that is in HTML format *****/
/***** Write the stem, that is in HTML format *****/
fprintf (FileXML,"<stem>%s</stem>%s",
row[3],Txt_NEW_LINE);
Stem,Txt_NEW_LINE);
/***** Write the feedback (row[4]), that is in HTML format *****/
if (row[4])
if (row[4][0])
fprintf (FileXML,"<feedback>%s</feedback>%s",
row[4],Txt_NEW_LINE);
/***** Write the feedback, that is in HTML format *****/
if (Feedback[0])
fprintf (FileXML,"<feedback>%s</feedback>%s",
Feedback,Txt_NEW_LINE);
/***** Write the answers of this question.
Shuffle can be enabled or disabled (row[2]) *****/
Shuffle can be enabled or disabled *****/
fprintf (FileXML,"<answer");
if (Question->Answer.Type == Tst_ANS_UNIQUE_CHOICE ||
Question->Answer.Type == Tst_ANS_MULTIPLE_CHOICE)
fprintf (FileXML," shuffle=\"%s\"",
(row[2][0] == 'Y') ? "yes" :
"no");
Question->Answer.Shuffle ? "yes" :
"no");
fprintf (FileXML,">");
TsI_WriteAnswersOfAQstXML (Question,FileXML);
fprintf (FileXML,"</answer>%s",Txt_NEW_LINE);
@ -347,60 +331,30 @@ static void TsI_GetAndWriteTagsXML (long QstCod,FILE *FileXML)
/**************** Get and write the answers of a test question ***************/
/*****************************************************************************/
static void TsI_WriteAnswersOfAQstXML (struct Tst_Question *Question,
static void TsI_WriteAnswersOfAQstXML (const struct Tst_Question *Question,
FILE *FileXML)
{
extern const char *Txt_NEW_LINE;
unsigned NumOpt;
unsigned i;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
double FloatNum[2];
/***** Get answers *****/
Tst_GetAnswersQst (Question,&mysql_res,
false); // Don't shuffle
/*
row[0] AnsInd
row[1] Answer
row[2] Feedback
row[3] MedCod
row[4] Correct
*/
/***** Write answers *****/
switch (Question->Answer.Type)
{
case Tst_ANS_INT:
Tst_CheckIfNumberOfAnswersIsOne (Question);
row = mysql_fetch_row (mysql_res);
fprintf (FileXML,"%ld",
Tst_GetIntAnsFromStr (row[1]));
fprintf (FileXML,"%ld",Question->Answer.Integer);
break;
case Tst_ANS_FLOAT:
if (Question->Answer.NumOptions != 2)
Lay_ShowErrorAndExit ("Wrong float range.");
for (i = 0;
i < 2;
i++)
{
row = mysql_fetch_row (mysql_res);
FloatNum[i] = Str_GetDoubleFromStr (row[1]);
}
fprintf (FileXML,"%s"
"<lower>%.15lg</lower>%s"
"<upper>%.15lg</upper>%s",
Txt_NEW_LINE,
FloatNum[0],Txt_NEW_LINE,
FloatNum[1],Txt_NEW_LINE);
Question->Answer.FloatingPoint[0],Txt_NEW_LINE,
Question->Answer.FloatingPoint[1],Txt_NEW_LINE);
break;
case Tst_ANS_TRUE_FALSE:
Tst_CheckIfNumberOfAnswersIsOne (Question);
row = mysql_fetch_row (mysql_res);
fprintf (FileXML,"%s",
row[1][0] == 'T' ? "true" :
"false");
Question->Answer.TF == 'T' ? "true" :
"false");
break;
case Tst_ANS_UNIQUE_CHOICE:
case Tst_ANS_MULTIPLE_CHOICE:
@ -410,28 +364,26 @@ static void TsI_WriteAnswersOfAQstXML (struct Tst_Question *Question,
NumOpt < Question->Answer.NumOptions;
NumOpt++)
{
row = mysql_fetch_row (mysql_res);
/* Start answer */
fprintf (FileXML,"<option");
/* Write whether the answer is correct or not (row[4]) */
/* Write whether the answer is correct or not */
if (Question->Answer.Type != Tst_ANS_TEXT)
fprintf (FileXML," correct=\"%s\"",
(row[4][0] == 'Y') ? "yes" :
"no");
Question->Answer.Options[NumOpt].Correct ? "yes" :
"no");
fprintf (FileXML,">%s",Txt_NEW_LINE);
/* Write the answer (row[1]), that is in HTML */
/* Write the answer, that is in HTML */
fprintf (FileXML,"<text>%s</text>%s",
row[1],Txt_NEW_LINE);
Question->Answer.Options[NumOpt].Text,Txt_NEW_LINE);
/* Write the feedback (row[2]) */
if (row[2])
if (row[2][0])
/* Write the feedback */
if (Question->Answer.Options[NumOpt].Feedback)
if (Question->Answer.Options[NumOpt].Feedback[0])
fprintf (FileXML,"<feedback>%s</feedback>%s",
row[2],Txt_NEW_LINE);
Question->Answer.Options[NumOpt].Feedback,Txt_NEW_LINE);
/* End answer */
fprintf (FileXML,"</option>%s",
@ -441,9 +393,6 @@ static void TsI_WriteAnswersOfAQstXML (struct Tst_Question *Question,
default:
break;
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
/*****************************************************************************/

View File

@ -9791,27 +9791,6 @@ const char *Txt_Done =
"Feito";
#endif
const char *Txt_Done_assess_test =
#if L==1 // ca
"He acabat; corregir test";
#elif L==2 // de
"Geschehen; beurteilen Test";
#elif L==3 // en
"Done; assess test";
#elif L==4 // es
"He terminado; corregir test";
#elif L==5 // fr
"Fait; corriger test";
#elif L==6 // gn
"He terminado; corregir test"; // Okoteve traducción
#elif L==7 // it
"Finito; correggere test";
#elif L==8 // pl
"Sporz&aogon;dzono; oceny test";
#elif L==9 // pt
"Feito; corrigir teste";
#endif
const char *Txt_Download = // As a verb
#if L==1 // ca
"Descarregar";