Version19.148.2

This commit is contained in:
acanas 2020-03-17 13:10:44 +01:00
parent 5d14676c39
commit 3810f664c2
8 changed files with 252 additions and 248 deletions

View File

@ -497,7 +497,7 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - *
En OpenSWAD: En OpenSWAD:
ps2pdf source.ps destination.pdf ps2pdf source.ps destination.pdf
*/ */
#define Log_PLATFORM_VERSION "SWAD 19.148 (2020-03-17)" #define Log_PLATFORM_VERSION "SWAD 19.148.2 (2020-03-17)"
#define CSS_FILE "swad19.146.css" #define CSS_FILE "swad19.146.css"
#define JS_FILE "swad19.91.1.js" #define JS_FILE "swad19.91.1.js"
/* /*
@ -524,6 +524,8 @@ Param
// TODO: Oresti Baños: cambiar ojos por candados en descriptores para prohibir/permitir y dejar los ojos para poder elegir descriptores // TODO: Oresti Baños: cambiar ojos por candados en descriptores para prohibir/permitir y dejar los ojos para poder elegir descriptores
// TODO: Si el alumno ha marcado "Permitir que los profesores...", entonces pedir confirmación al pulsar el botón azul, para evitar que se envíe por error antes de tiempo // TODO: Si el alumno ha marcado "Permitir que los profesores...", entonces pedir confirmación al pulsar el botón azul, para evitar que se envíe por error antes de tiempo
Version 19.148.2: Mar 17, 2020 Code refactoring in tests. (282868 lines)
Version 19.148.1: Mar 17, 2020 Code refactoring in tests. (282851 lines)
Version 19.148: Mar 17, 2020 Code refactoring in tests. Version 19.148: Mar 17, 2020 Code refactoring in tests.
New actions to remove several test questions. (282868 lines) New actions to remove several test questions. (282868 lines)
Version 19.147: Mar 14, 2020 Change MathJax to version 3.0.1. (282550 lines) Version 19.147: Mar 14, 2020 Change MathJax to version 3.0.1. (282550 lines)

View File

@ -2003,16 +2003,15 @@ static void Gam_ListQuestionForEdition (long QstCod,const char *StrQstInd)
/***** Get row of the result of the query *****/ /***** Get row of the result of the query *****/
row = mysql_fetch_row (mysql_res); row = mysql_fetch_row (mysql_res);
/* /*
row[0] QstCod row[0] UNIX_TIMESTAMP(EditTime)
row[1] UNIX_TIMESTAMP(EditTime) row[1] AnsType
row[2] AnsType row[2] Shuffle
row[3] Shuffle row[3] Stem
row[4] Stem row[4] Feedback
row[5] Feedback row[5] MedCod
row[6] MedCod row[6] NumHits
row[7] NumHits row[7] NumHitsNotBlank
row[8] NumHitsNotBlank row[8] Score
row[9] Score
*/ */
} }
@ -2024,11 +2023,11 @@ static void Gam_ListQuestionForEdition (long QstCod,const char *StrQstInd)
HTM_Txt (StrQstInd); HTM_Txt (StrQstInd);
HTM_DIV_End (); HTM_DIV_End ();
/* Write answer type (row[2]) */ /* Write answer type (row[1]) */
HTM_DIV_Begin ("class=\"DAT_SMALL\""); HTM_DIV_Begin ("class=\"DAT_SMALL\"");
if (QstExists) if (QstExists)
{ {
Gbl.Test.AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[2]); Gbl.Test.AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
HTM_Txt (Txt_TST_STR_ANSWER_TYPES[Gbl.Test.AnswerType]); HTM_Txt (Txt_TST_STR_ANSWER_TYPES[Gbl.Test.AnswerType]);
} }
HTM_DIV_End (); HTM_DIV_End ();
@ -2046,25 +2045,25 @@ static void Gam_ListQuestionForEdition (long QstCod,const char *StrQstInd)
Tst_GetAndWriteTagsQst (QstCod); Tst_GetAndWriteTagsQst (QstCod);
HTM_TD_End (); HTM_TD_End ();
/***** Write stem and media (row[4]) *****/ /***** Write stem (row[3]) and media *****/
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd); HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
if (QstExists) if (QstExists)
{ {
/* Write stem */ /* Write stem */
Tst_WriteQstStem (row[4],"TEST_EDI", Tst_WriteQstStem (row[3],"TEST_EDI",
true); // Visible true); // Visible
/* Get media (row[6]) */ /* Get media (row[5]) */
Gbl.Test.Media.MedCod = Str_ConvertStrCodToLongCod (row[6]); Gbl.Test.Question.Media.MedCod = Str_ConvertStrCodToLongCod (row[5]);
Med_GetMediaDataByCod (&Gbl.Test.Media); Med_GetMediaDataByCod (&Gbl.Test.Question.Media);
/* Show media */ /* Show media */
Med_ShowMedia (&Gbl.Test.Media, Med_ShowMedia (&Gbl.Test.Question.Media,
"TEST_MED_EDIT_LIST_STEM_CONTAINER", "TEST_MED_EDIT_LIST_STEM_CONTAINER",
"TEST_MED_EDIT_LIST_STEM"); "TEST_MED_EDIT_LIST_STEM");
/* Show feedback (row[5]) */ /* Show feedback (row[4]) */
Tst_WriteQstFeedback (row[5],"TEST_EDI_LIGHT"); Tst_WriteQstFeedback (row[4],"TEST_EDI_LIGHT");
/* Show answers */ /* Show answers */
Tst_WriteAnswersEdit (QstCod); Tst_WriteAnswersEdit (QstCod);

View File

@ -666,13 +666,7 @@ struct Globals
char StrAnswersOneQst[Tst_MAX_QUESTIONS_PER_TEST][Tst_MAX_BYTES_ANSWERS_ONE_QST + 1]; // Answers selected by user char StrAnswersOneQst[Tst_MAX_QUESTIONS_PER_TEST][Tst_MAX_BYTES_ANSWERS_ONE_QST + 1]; // Answers selected by user
bool AllowTeachers; // Can teachers of this course see the test result? bool AllowTeachers; // Can teachers of this course see the test result?
bool AllAnsTypes; bool AllAnsTypes;
struct struct Tst_Question Question;
{
char *Text;
size_t Length;
} Stem, Feedback;
struct Media Media;
bool Shuffle;
struct struct
{ {
unsigned NumOptions; unsigned NumOptions;

View File

@ -2899,11 +2899,11 @@ static void Mch_ShowQuestionAndAnswersTch (const struct Match *Match)
true); // Visible true); // Visible
/* Get media (row[2]) */ /* Get media (row[2]) */
Gbl.Test.Media.MedCod = Str_ConvertStrCodToLongCod (row[2]); Gbl.Test.Question.Media.MedCod = Str_ConvertStrCodToLongCod (row[2]);
Med_GetMediaDataByCod (&Gbl.Test.Media); Med_GetMediaDataByCod (&Gbl.Test.Question.Media);
/* Show media */ /* Show media */
Med_ShowMedia (&Gbl.Test.Media, Med_ShowMedia (&Gbl.Test.Question.Media,
"TEST_MED_EDIT_LIST_STEM_CONTAINER", "TEST_MED_EDIT_LIST_STEM_CONTAINER",
"TEST_MED_EDIT_LIST_STEM"); "TEST_MED_EDIT_LIST_STEM");

View File

@ -136,6 +136,7 @@ static void Tst_SetTstStatus (unsigned NumTst,Tst_Status_t TstStatus);
static Tst_Status_t Tst_GetTstStatus (unsigned NumTst); static Tst_Status_t Tst_GetTstStatus (unsigned NumTst);
static unsigned Tst_GetNumAccessesTst (void); static unsigned Tst_GetNumAccessesTst (void);
static void Tst_ShowTestQuestionsWhenSeeing (MYSQL_RES *mysql_res); static void Tst_ShowTestQuestionsWhenSeeing (MYSQL_RES *mysql_res);
static void Tst_ShowOneTestQuestionWhenSeeing (unsigned NumQst,long QstCod);
static void Tst_ShowTestResultAfterAssess (long TstCod,unsigned *NumQstsNotBlank,double *TotalScore); static void Tst_ShowTestResultAfterAssess (long TstCod,unsigned *NumQstsNotBlank,double *TotalScore);
static void Tst_PutFormToEditQstMedia (struct Media *Media,int NumMediaInForm, static void Tst_PutFormToEditQstMedia (struct Media *Media,int NumMediaInForm,
bool OptionsDisabled); bool OptionsDisabled);
@ -792,20 +793,6 @@ static void Tst_ShowTestQuestionsWhenSeeing (MYSQL_RES *mysql_res)
unsigned NumQst; unsigned NumQst;
long QstCod; long QstCod;
MYSQL_ROW row; MYSQL_ROW row;
double ScoreThisQst; // Not used here
bool AnswerIsNotBlank; // Not used here
/*
row[0] QstCod
row[1] UNIX_TIMESTAMP(EditTime)
row[2] AnsType
row[3] Shuffle
row[4] Stem
row[5] Feedback
row[6] MedCod
row[7] NumHits
row[8] NumHitsNotBlank
row[9] Score
*/
/***** Write rows *****/ /***** Write rows *****/
for (NumQst = 0; for (NumQst = 0;
@ -819,13 +806,47 @@ static void Tst_ShowTestQuestionsWhenSeeing (MYSQL_RES *mysql_res)
if ((QstCod = Str_ConvertStrCodToLongCod (row[0])) < 0) if ((QstCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
Lay_ShowErrorAndExit ("Wrong code of question."); Lay_ShowErrorAndExit ("Wrong code of question.");
/***** Show question *****/
Tst_ShowOneTestQuestionWhenSeeing (NumQst,QstCod);
}
}
/*****************************************************************************/
/*************************** Write one test question *************************/
/*****************************************************************************/
static void Tst_ShowOneTestQuestionWhenSeeing (unsigned NumQst,long QstCod)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
double ScoreThisQst; // Not used here
bool AnswerIsNotBlank; // Not used here
if (Tst_GetOneQuestionByCod (QstCod,&mysql_res)) // Question exists
{
/***** 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
*/
Tst_WriteQstAndAnsTest (Tst_SHOW_TEST_TO_ANSWER, Tst_WriteQstAndAnsTest (Tst_SHOW_TEST_TO_ANSWER,
&Gbl.Usrs.Me.UsrDat, &Gbl.Usrs.Me.UsrDat,
NumQst,QstCod,row, NumQst,QstCod,row,
TsV_MAX_VISIBILITY, // All visible here TsV_MAX_VISIBILITY, // All visible here
&ScoreThisQst, // Not used here &ScoreThisQst, // Not used here
&AnswerIsNotBlank); // Not used here &AnswerIsNotBlank); // Not used here
} }
else
Lay_ShowErrorAndExit ("Wrong question.");
} }
/*****************************************************************************/ /*****************************************************************************/
@ -867,7 +888,6 @@ static void Tst_ShowTestResultAfterAssess (long TstCod,unsigned *NumQstsNotBlank
MYSQL_RES *mysql_res; MYSQL_RES *mysql_res;
MYSQL_ROW row; MYSQL_ROW row;
unsigned NumQst; unsigned NumQst;
long QstCod;
double ScoreThisQst; double ScoreThisQst;
bool AnswerIsNotBlank; bool AnswerIsNotBlank;
@ -887,31 +907,26 @@ static void Tst_ShowTestResultAfterAssess (long TstCod,unsigned *NumQstsNotBlank
/***** Get row of the result of the query *****/ /***** Get row of the result of the query *****/
row = mysql_fetch_row (mysql_res); row = mysql_fetch_row (mysql_res);
/* /*
row[0] QstCod row[0] UNIX_TIMESTAMP(EditTime)
row[1] UNIX_TIMESTAMP(EditTime) row[1] AnsType
row[2] AnsType row[2] Shuffle
row[3] Shuffle row[3] Stem
row[4] Stem row[4] Feedback
row[5] Feedback row[5] MedCod
row[6] MedCod row[6] NumHits
row[7] NumHits row[7] NumHitsNotBlank
row[8] NumHitsNotBlank row[8] Score
row[9] Score
*/ */
/***** Get the code of question (row[0]) *****/
if ((QstCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
Lay_ShowErrorAndExit ("Wrong code of question.");
/***** Write question and answers *****/ /***** Write question and answers *****/
Tst_WriteQstAndAnsTest (Tst_SHOW_TEST_RESULT, Tst_WriteQstAndAnsTest (Tst_SHOW_TEST_RESULT,
&Gbl.Usrs.Me.UsrDat, &Gbl.Usrs.Me.UsrDat,
NumQst,QstCod,row, NumQst,Gbl.Test.QstCodes[NumQst],row,
Gbl.Test.Config.Visibility, Gbl.Test.Config.Visibility,
&ScoreThisQst,&AnswerIsNotBlank); &ScoreThisQst,&AnswerIsNotBlank);
/***** Store test result question in database *****/ /***** Store test result question in database *****/
TsR_StoreOneTestResultQstInDB (TstCod,QstCod, TsR_StoreOneTestResultQstInDB (TstCod,Gbl.Test.QstCodes[NumQst],
NumQst, // 0, 1, 2, 3... NumQst, // 0, 1, 2, 3...
ScoreThisQst); ScoreThisQst);
@ -922,7 +937,7 @@ static void Tst_ShowTestResultAfterAssess (long TstCod,unsigned *NumQstsNotBlank
/***** Update the number of accesses and the score of this question *****/ /***** Update the number of accesses and the score of this question *****/
if (Gbl.Usrs.Me.Role.Logged == Rol_STD) if (Gbl.Usrs.Me.Role.Logged == Rol_STD)
Tst_UpdateScoreQst (QstCod,ScoreThisQst,AnswerIsNotBlank); Tst_UpdateScoreQst (Gbl.Test.QstCodes[NumQst],ScoreThisQst,AnswerIsNotBlank);
} }
else else
{ {
@ -958,16 +973,15 @@ void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestio
extern const char *Txt_TST_STR_ANSWER_TYPES[Tst_NUM_ANS_TYPES]; extern const char *Txt_TST_STR_ANSWER_TYPES[Tst_NUM_ANS_TYPES];
bool IsVisibleQstAndAnsTxt = TsV_IsVisibleQstAndAnsTxt (Visibility); bool IsVisibleQstAndAnsTxt = TsV_IsVisibleQstAndAnsTxt (Visibility);
/* /*
row[0] QstCod row[0] UNIX_TIMESTAMP(EditTime)
row[1] UNIX_TIMESTAMP(EditTime) row[1] AnsType
row[2] AnsType row[2] Shuffle
row[3] Shuffle row[3] Stem
row[4] Stem row[4] Feedback
row[5] Feedback row[5] MedCod
row[6] MedCod row[6] NumHits
row[7] NumHits row[7] NumHitsNotBlank
row[8] NumHitsNotBlank row[8] Score
row[9] Score
*/ */
/***** Create test question *****/ /***** Create test question *****/
@ -981,42 +995,42 @@ void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestio
HTM_Unsigned (NumQst + 1); HTM_Unsigned (NumQst + 1);
HTM_DIV_End (); HTM_DIV_End ();
/***** Write answer type (row[2]) *****/ /***** Write answer type (row[1]) *****/
Gbl.Test.AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[2]); Gbl.Test.AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
HTM_DIV_Begin ("class=\"DAT_SMALL\""); HTM_DIV_Begin ("class=\"DAT_SMALL\"");
HTM_Txt (Txt_TST_STR_ANSWER_TYPES[Gbl.Test.AnswerType]); HTM_Txt (Txt_TST_STR_ANSWER_TYPES[Gbl.Test.AnswerType]);
HTM_DIV_End (); HTM_DIV_End ();
HTM_TD_End (); HTM_TD_End ();
/***** Write stem (row[4]) *****/ /***** Write stem (row[3]) *****/
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd); HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
Tst_WriteQstStem (row[4],"TEST_EXA",IsVisibleQstAndAnsTxt); Tst_WriteQstStem (row[3],"TEST_EXA",IsVisibleQstAndAnsTxt);
/***** Get and show media (row[6]) *****/ /***** Get and show media (row[5]) *****/
if (IsVisibleQstAndAnsTxt) if (IsVisibleQstAndAnsTxt)
{ {
Gbl.Test.Media.MedCod = Str_ConvertStrCodToLongCod (row[6]); Gbl.Test.Question.Media.MedCod = Str_ConvertStrCodToLongCod (row[5]);
Med_GetMediaDataByCod (&Gbl.Test.Media); Med_GetMediaDataByCod (&Gbl.Test.Question.Media);
Med_ShowMedia (&Gbl.Test.Media, Med_ShowMedia (&Gbl.Test.Question.Media,
"TEST_MED_SHOW_CONT", "TEST_MED_SHOW_CONT",
"TEST_MED_SHOW"); "TEST_MED_SHOW");
} }
/***** Write answers depending on shuffle (row[3]) and feedback (row[5]) *****/ /***** Write answers depending on shuffle (row[2]) and feedback (row[4]) *****/
switch (ActionToDoWithQuestions) switch (ActionToDoWithQuestions)
{ {
case Tst_SHOW_TEST_TO_ANSWER: case Tst_SHOW_TEST_TO_ANSWER:
Tst_WriteAnswersTestToAnswer (NumQst,QstCod,(row[3][0] == 'Y')); Tst_WriteAnswersTestToAnswer (NumQst,QstCod,(row[2][0] == 'Y'));
break; break;
case Tst_SHOW_TEST_RESULT: case Tst_SHOW_TEST_RESULT:
Tst_WriteAnswersTestResult (UsrDat,NumQst,QstCod, Tst_WriteAnswersTestResult (UsrDat,NumQst,QstCod,
Visibility, Visibility,
ScoreThisQst,AnswerIsNotBlank); ScoreThisQst,AnswerIsNotBlank);
/* Write question feedback (row[5]) */ /* Write question feedback (row[4]) */
if (TsV_IsVisibleFeedbackTxt (Visibility)) if (TsV_IsVisibleFeedbackTxt (Visibility))
Tst_WriteQstFeedback (row[5],"TEST_EXA_LIGHT"); Tst_WriteQstFeedback (row[4],"TEST_EXA_LIGHT");
break; break;
default: default:
break; break;
@ -2584,16 +2598,7 @@ static unsigned long Tst_GetQuestionsForTest (MYSQL_RES **mysql_res)
// Select only questions with tags // Select only questions with tags
// DISTINCTROW is necessary to not repeat questions // DISTINCTROW is necessary to not repeat questions
snprintf (Query,Tst_MAX_BYTES_QUERY_TEST + 1, snprintf (Query,Tst_MAX_BYTES_QUERY_TEST + 1,
"SELECT DISTINCTROW tst_questions.QstCod," // row[0] "SELECT DISTINCT tst_questions.QstCod" // row[0]
"UNIX_TIMESTAMP(tst_questions.EditTime)," // row[1]
"tst_questions.AnsType," // row[2]
"tst_questions.Shuffle," // row[3]
"tst_questions.Stem," // row[4]
"tst_questions.Feedback," // row[5]
"tst_questions.MedCod," // row[6]
"tst_questions.NumHits," // row[7]
"tst_questions.NumHitsNotBlank," // row[8]
"tst_questions.Score" // row[9]
" FROM tst_questions,tst_question_tags,tst_tags" " FROM tst_questions,tst_question_tags,tst_tags"
" WHERE tst_questions.CrsCod=%ld" " WHERE tst_questions.CrsCod=%ld"
" AND tst_questions.QstCod NOT IN" " AND tst_questions.QstCod NOT IN"
@ -2718,16 +2723,15 @@ bool Tst_GetOneQuestionByCod (long QstCod,MYSQL_RES **mysql_res)
{ {
/***** Get data of a question from database *****/ /***** Get data of a question from database *****/
return (DB_QuerySELECT (mysql_res,"can not get data of a question", return (DB_QuerySELECT (mysql_res,"can not get data of a question",
"SELECT QstCod," // row[0] "SELECT UNIX_TIMESTAMP(EditTime)," // row[0]
"UNIX_TIMESTAMP(EditTime)," // row[1] "AnsType," // row[1]
"AnsType," // row[2] "Shuffle," // row[2]
"Shuffle," // row[3] "Stem," // row[3]
"Stem," // row[4] "Feedback," // row[4]
"Feedback," // row[5] "MedCod," // row[5]
"MedCod," // row[6] "NumHits," // row[6]
"NumHits," // row[7] "NumHitsNotBlank," // row[7]
"NumHitsNotBlank," // row[8] "Score" // row[8]
"Score" // row[9]
" FROM tst_questions" " FROM tst_questions"
" WHERE QstCod=%ld", " WHERE QstCod=%ld",
QstCod) == 1); QstCod) == 1);
@ -2866,16 +2870,15 @@ static void Tst_WriteQuestionRowForEdition (unsigned long NumRows,
/***** Get row from database *****/ /***** Get row from database *****/
row = mysql_fetch_row (mysql_res); row = mysql_fetch_row (mysql_res);
/* /*
row[0] QstCod row[0] UNIX_TIMESTAMP(EditTime)
row[1] UNIX_TIMESTAMP(EditTime) row[1] AnsType
row[2] AnsType row[2] Shuffle
row[3] Shuffle row[3] Stem
row[4] Stem row[4] Feedback
row[5] Feedback row[5] MedCod
row[6] MedCod row[6] NumHits
row[7] NumHits row[7] NumHitsNotBlank
row[8] NumHitsNotBlank row[8] Score
row[9] Score
*/ */
/***** Create test question *****/ /***** Create test question *****/
@ -2910,8 +2913,8 @@ static void Tst_WriteQuestionRowForEdition (unsigned long NumRows,
HTM_UnsignedLong (NumRow + 1); HTM_UnsignedLong (NumRow + 1);
HTM_DIV_End (); HTM_DIV_End ();
/* Write answer type (row[2]) */ /* Write answer type (row[1]) */
Gbl.Test.AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[2]); Gbl.Test.AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
HTM_DIV_Begin ("class=\"DAT_SMALL\""); HTM_DIV_Begin ("class=\"DAT_SMALL\"");
HTM_Txt (Txt_TST_STR_ANSWER_TYPES[Gbl.Test.AnswerType]); HTM_Txt (Txt_TST_STR_ANSWER_TYPES[Gbl.Test.AnswerType]);
HTM_DIV_End (); HTM_DIV_End ();
@ -2923,8 +2926,8 @@ static void Tst_WriteQuestionRowForEdition (unsigned long NumRows,
HTM_TxtF ("%ld&nbsp;",QstCod); HTM_TxtF ("%ld&nbsp;",QstCod);
HTM_TD_End (); HTM_TD_End ();
/* Write the date (row[1] has the UTC date-time) */ /* Write the date (row[0] has the UTC date-time) */
TimeUTC = Dat_GetUNIXTimeFromStr (row[1]); TimeUTC = Dat_GetUNIXTimeFromStr (row[0]);
if (asprintf (&Id,"tst_date_%u",++UniqueId) < 0) if (asprintf (&Id,"tst_date_%u",++UniqueId) < 0)
Lay_NotEnoughMemoryExit (); Lay_NotEnoughMemoryExit ();
HTM_TD_Begin ("id=\"%s\" class=\"DAT_SMALL CT COLOR%u\"", HTM_TD_Begin ("id=\"%s\" class=\"DAT_SMALL CT COLOR%u\"",
@ -2940,7 +2943,7 @@ static void Tst_WriteQuestionRowForEdition (unsigned long NumRows,
Tst_GetAndWriteTagsQst (QstCod); Tst_GetAndWriteTagsQst (QstCod);
HTM_TD_End (); HTM_TD_End ();
/* Write if shuffle is enabled (row[3]) */ /* Write if shuffle is enabled (row[2]) */
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd); HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
if (Gbl.Test.AnswerType == Tst_ANS_UNIQUE_CHOICE || if (Gbl.Test.AnswerType == Tst_ANS_UNIQUE_CHOICE ||
Gbl.Test.AnswerType == Tst_ANS_MULTIPLE_CHOICE) Gbl.Test.AnswerType == Tst_ANS_MULTIPLE_CHOICE)
@ -2954,44 +2957,44 @@ static void Tst_WriteQuestionRowForEdition (unsigned long NumRows,
Par_PutHiddenParamUnsigned (NULL,"Order",(unsigned) Gbl.Test.SelectedOrder); Par_PutHiddenParamUnsigned (NULL,"Order",(unsigned) Gbl.Test.SelectedOrder);
HTM_INPUT_CHECKBOX ("Shuffle",HTM_SUBMIT_ON_CHANGE, HTM_INPUT_CHECKBOX ("Shuffle",HTM_SUBMIT_ON_CHANGE,
"value=\"Y\"%s", "value=\"Y\"%s",
row[3][0] == 'Y' ? " checked=\"checked\"" : row[2][0] == 'Y' ? " checked=\"checked\"" :
""); "");
Frm_EndForm (); Frm_EndForm ();
} }
HTM_TD_End (); HTM_TD_End ();
/* Write stem (row[4]) */ /* Write stem (row[3]) */
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd); HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
Tst_WriteQstStem (row[4],"TEST_EDI", Tst_WriteQstStem (row[3],"TEST_EDI",
true); // Visible true); // Visible
/***** Get and show media (row[6]) *****/ /***** Get and show media (row[5]) *****/
Gbl.Test.Media.MedCod = Str_ConvertStrCodToLongCod (row[6]); Gbl.Test.Question.Media.MedCod = Str_ConvertStrCodToLongCod (row[5]);
Med_GetMediaDataByCod (&Gbl.Test.Media); Med_GetMediaDataByCod (&Gbl.Test.Question.Media);
Med_ShowMedia (&Gbl.Test.Media, Med_ShowMedia (&Gbl.Test.Question.Media,
"TEST_MED_EDIT_LIST_CONT", "TEST_MED_EDIT_LIST_CONT",
"TEST_MED_EDIT_LIST"); "TEST_MED_EDIT_LIST");
/* Write feedback (row[5]) and answers */ /* Write feedback (row[4]) and answers */
Tst_WriteQstFeedback (row[5],"TEST_EDI_LIGHT"); Tst_WriteQstFeedback (row[4],"TEST_EDI_LIGHT");
Tst_WriteAnswersEdit (QstCod); Tst_WriteAnswersEdit (QstCod);
HTM_TD_End (); HTM_TD_End ();
/* Get number of hits /* Get number of hits
(number of times that the question has been answered, (number of times that the question has been answered,
including blank answers) (row[7]) */ including blank answers) (row[6]) */
if (sscanf (row[7],"%lu",&NumHitsThisQst) != 1) if (sscanf (row[6],"%lu",&NumHitsThisQst) != 1)
Lay_ShowErrorAndExit ("Wrong number of hits to a question."); Lay_ShowErrorAndExit ("Wrong number of hits to a question.");
/* Get number of hits not blank /* Get number of hits not blank
(number of times that the question has been answered (number of times that the question has been answered
with a not blank answer) (row[8]) */ with a not blank answer) (row[7]) */
if (sscanf (row[8],"%lu",&NumHitsNotBlankThisQst) != 1) if (sscanf (row[7],"%lu",&NumHitsNotBlankThisQst) != 1)
Lay_ShowErrorAndExit ("Wrong number of hits not blank to a question."); Lay_ShowErrorAndExit ("Wrong number of hits not blank to a question.");
/* Get the acumulated score of the question (row[9]) */ /* Get the acumulated score of the question (row[8]) */
Str_SetDecimalPointToUS (); // To get the decimal point as a dot Str_SetDecimalPointToUS (); // To get the decimal point as a dot
if (sscanf (row[9],"%lf",&TotalScoreThisQst) != 1) if (sscanf (row[8],"%lf",&TotalScoreThisQst) != 1)
Lay_ShowErrorAndExit ("Wrong score of a question."); Lay_ShowErrorAndExit ("Wrong score of a question.");
Str_SetDecimalPointToLocal (); // Return to local system Str_SetDecimalPointToLocal (); // Return to local system
@ -3126,16 +3129,15 @@ static void Tst_WriteQuestionRowForSelection (unsigned long NumRow,long QstCod)
/***** Get row of the result of the query *****/ /***** Get row of the result of the query *****/
row = mysql_fetch_row (mysql_res); row = mysql_fetch_row (mysql_res);
/* /*
row[0] QstCod row[0] UNIX_TIMESTAMP(EditTime)
row[1] UNIX_TIMESTAMP(EditTime) row[1] AnsType
row[2] AnsType row[2] Shuffle
row[3] Shuffle row[3] Stem
row[4] Stem row[4] Feedback
row[5] Feedback row[5] MedCod
row[6] MedCod row[6] NumHits
row[7] NumHits row[7] NumHitsNotBlank
row[8] NumHitsNotBlank row[8] Score
row[9] Score
*/ */
/***** Create test question *****/ /***** Create test question *****/
@ -3162,8 +3164,8 @@ static void Tst_WriteQuestionRowForSelection (unsigned long NumRow,long QstCod)
HTM_TxtF ("%ld&nbsp;",QstCod); HTM_TxtF ("%ld&nbsp;",QstCod);
HTM_TD_End (); HTM_TD_End ();
/* Write the date (row[1] has the UTC date-time) */ /* Write the date (row[0] has the UTC date-time) */
TimeUTC = Dat_GetUNIXTimeFromStr (row[1]); TimeUTC = Dat_GetUNIXTimeFromStr (row[0]);
if (asprintf (&Id,"tst_date_%u",++UniqueId) < 0) if (asprintf (&Id,"tst_date_%u",++UniqueId) < 0)
Lay_NotEnoughMemoryExit (); Lay_NotEnoughMemoryExit ();
HTM_TD_Begin ("id=\"%s\" class=\"DAT_SMALL CT COLOR%u\">", HTM_TD_Begin ("id=\"%s\" class=\"DAT_SMALL CT COLOR%u\">",
@ -3179,34 +3181,34 @@ static void Tst_WriteQuestionRowForSelection (unsigned long NumRow,long QstCod)
Tst_GetAndWriteTagsQst (QstCod); Tst_GetAndWriteTagsQst (QstCod);
HTM_TD_End (); HTM_TD_End ();
/* Write the question type (row[2]) */ /* Write the question type (row[1]) */
Gbl.Test.AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[2]); Gbl.Test.AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd); HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
HTM_TxtF ("%s&nbsp;",Txt_TST_STR_ANSWER_TYPES[Gbl.Test.AnswerType]); HTM_TxtF ("%s&nbsp;",Txt_TST_STR_ANSWER_TYPES[Gbl.Test.AnswerType]);
HTM_TD_End (); HTM_TD_End ();
/* Write if shuffle is enabled (row[3]) */ /* Write if shuffle is enabled (row[2]) */
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd); HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
HTM_INPUT_CHECKBOX ("Shuffle",HTM_DONT_SUBMIT_ON_CHANGE, HTM_INPUT_CHECKBOX ("Shuffle",HTM_DONT_SUBMIT_ON_CHANGE,
"value=\"Y\"%s disabled=\"disabled\"", "value=\"Y\"%s disabled=\"disabled\"",
row[3][0] == 'Y' ? " checked=\"checked\"" : row[2][0] == 'Y' ? " checked=\"checked\"" :
""); "");
HTM_TD_End (); HTM_TD_End ();
/* Write stem (row[4]) */ /* Write stem (row[3]) */
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd); HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
Tst_WriteQstStem (row[4],"TEST_EDI", Tst_WriteQstStem (row[3],"TEST_EDI",
true); // Visible true); // Visible
/***** Get and show media (row[6]) *****/ /***** Get and show media (row[5]) *****/
Gbl.Test.Media.MedCod = Str_ConvertStrCodToLongCod (row[6]); Gbl.Test.Question.Media.MedCod = Str_ConvertStrCodToLongCod (row[5]);
Med_GetMediaDataByCod (&Gbl.Test.Media); Med_GetMediaDataByCod (&Gbl.Test.Question.Media);
Med_ShowMedia (&Gbl.Test.Media, Med_ShowMedia (&Gbl.Test.Question.Media,
"TEST_MED_EDIT_LIST_CONT", "TEST_MED_EDIT_LIST_CONT",
"TEST_MED_EDIT_LIST"); "TEST_MED_EDIT_LIST");
/* Write feedback (row[5]) */ /* Write feedback (row[4]) */
Tst_WriteQstFeedback (row[5],"TEST_EDI_LIGHT"); Tst_WriteQstFeedback (row[4],"TEST_EDI_LIGHT");
/* Write answers */ /* Write answers */
Tst_WriteAnswersEdit (QstCod); Tst_WriteAnswersEdit (QstCod);
@ -5258,7 +5260,7 @@ static void Tst_PutFormEditOneQst (long QstCod,
HTM_Txt (Stem); HTM_Txt (Stem);
HTM_TEXTAREA_End (); HTM_TEXTAREA_End ();
HTM_BR (); HTM_BR ();
Tst_PutFormToEditQstMedia (&Gbl.Test.Media,-1, Tst_PutFormToEditQstMedia (&Gbl.Test.Question.Media,-1,
false); false);
/***** Feedback *****/ /***** Feedback *****/
@ -5352,7 +5354,8 @@ static void Tst_PutFormEditOneQst (long QstCod,
HTM_LABEL_Begin ("class=\"%s\"",The_ClassFormInBox[Gbl.Prefs.Theme]); HTM_LABEL_Begin ("class=\"%s\"",The_ClassFormInBox[Gbl.Prefs.Theme]);
HTM_INPUT_CHECKBOX ("Shuffle",HTM_DONT_SUBMIT_ON_CHANGE, HTM_INPUT_CHECKBOX ("Shuffle",HTM_DONT_SUBMIT_ON_CHANGE,
"value=\"Y\"%s%s", "value=\"Y\"%s%s",
Gbl.Test.Shuffle ? " checked=\"checked\"" : "", Gbl.Test.Question.Shuffle ? " checked=\"checked\"" :
"",
Gbl.Test.AnswerType != Tst_ANS_UNIQUE_CHOICE && Gbl.Test.AnswerType != Tst_ANS_UNIQUE_CHOICE &&
Gbl.Test.AnswerType != Tst_ANS_MULTIPLE_CHOICE ? " disabled=\"disabled\"" : Gbl.Test.AnswerType != Tst_ANS_MULTIPLE_CHOICE ? " disabled=\"disabled\"" :
""); "");
@ -5548,17 +5551,17 @@ void Tst_QstConstructor (void)
{ {
unsigned NumOpt; unsigned NumOpt;
Gbl.Test.Stem.Text = NULL; Gbl.Test.Question.Stem.Text = NULL;
Gbl.Test.Stem.Length = 0; Gbl.Test.Question.Stem.Length = 0;
Gbl.Test.Feedback.Text = NULL; Gbl.Test.Question.Feedback.Text = NULL;
Gbl.Test.Feedback.Length = 0; Gbl.Test.Question.Feedback.Length = 0;
Gbl.Test.Shuffle = false; Gbl.Test.Question.Shuffle = false;
Gbl.Test.AnswerType = Tst_ANS_UNIQUE_CHOICE; Gbl.Test.AnswerType = Tst_ANS_UNIQUE_CHOICE;
Gbl.Test.Answer.NumOptions = 0; Gbl.Test.Answer.NumOptions = 0;
Gbl.Test.Answer.TF = ' '; Gbl.Test.Answer.TF = ' ';
/***** Initialize image attached to stem *****/ /***** Initialize image attached to stem *****/
Med_MediaConstructor (&Gbl.Test.Media); Med_MediaConstructor (&Gbl.Test.Question.Media);
for (NumOpt = 0; for (NumOpt = 0;
NumOpt < Tst_MAX_OPTIONS_PER_QUESTION; NumOpt < Tst_MAX_OPTIONS_PER_QUESTION;
@ -5655,7 +5658,7 @@ static void Tst_ResetMediaOfQuestion (void)
unsigned NumOpt; unsigned NumOpt;
/***** Reset media for stem *****/ /***** Reset media for stem *****/
Med_ResetMedia (&Gbl.Test.Media); Med_ResetMedia (&Gbl.Test.Question.Media);
/***** Reset media for every answer option *****/ /***** Reset media for every answer option *****/
for (NumOpt = 0; for (NumOpt = 0;
@ -5672,7 +5675,7 @@ static void Tst_FreeMediaOfQuestion (void)
{ {
unsigned NumOpt; unsigned NumOpt;
Med_MediaDestructor (&Gbl.Test.Media); Med_MediaDestructor (&Gbl.Test.Question.Media);
for (NumOpt = 0; for (NumOpt = 0;
NumOpt < Tst_MAX_OPTIONS_PER_QUESTION; NumOpt < Tst_MAX_OPTIONS_PER_QUESTION;
NumOpt++) NumOpt++)
@ -5710,7 +5713,7 @@ static void Tst_GetQstDataFromDB (long QstCod,
Gbl.Test.AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[0]); Gbl.Test.AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[0]);
/* Get shuffle (row[1]) */ /* Get shuffle (row[1]) */
Gbl.Test.Shuffle = (row[1][0] == 'Y'); Gbl.Test.Question.Shuffle = (row[1][0] == 'Y');
/* Get the stem of the question from the database (row[2]) */ /* Get the stem of the question from the database (row[2]) */
Str_Copy (Stem,row[2], Str_Copy (Stem,row[2],
@ -5724,8 +5727,8 @@ static void Tst_GetQstDataFromDB (long QstCod,
Cns_MAX_BYTES_TEXT); Cns_MAX_BYTES_TEXT);
/* Get media (row[4]) */ /* Get media (row[4]) */
Gbl.Test.Media.MedCod = Str_ConvertStrCodToLongCod (row[4]); Gbl.Test.Question.Media.MedCod = Str_ConvertStrCodToLongCod (row[4]);
Med_GetMediaDataByCod (&Gbl.Test.Media); Med_GetMediaDataByCod (&Gbl.Test.Question.Media);
/* Free structure that stores the query result */ /* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_res); DB_FreeMySQLResult (&mysql_res);
@ -5887,7 +5890,7 @@ Tst_AnswerType_t Tst_ConvertFromStrAnsTypDBToAnsTyp (const char *StrAnsTypeBD)
if (!strcmp (StrAnsTypeBD,Tst_StrAnswerTypesDB[AnsType])) if (!strcmp (StrAnsTypeBD,Tst_StrAnswerTypesDB[AnsType]))
return AnsType; return AnsType;
Lay_ShowErrorAndExit ("Wrong type of answer."); Lay_ShowErrorAndExit ("Wrong type of answer. 1");
return (Tst_AnswerType_t) 0; // Not reached return (Tst_AnswerType_t) 0; // Not reached
} }
@ -5900,9 +5903,9 @@ static Tst_AnswerType_t Tst_ConvertFromUnsignedStrToAnsTyp (const char *Unsigned
unsigned AnsType; unsigned AnsType;
if (sscanf (UnsignedStr,"%u",&AnsType) != 1) if (sscanf (UnsignedStr,"%u",&AnsType) != 1)
Lay_ShowErrorAndExit ("Wrong type of answer."); Lay_ShowErrorAndExit ("Wrong type of answer. 2");
if (AnsType >= Tst_NUM_ANS_TYPES) if (AnsType >= Tst_NUM_ANS_TYPES)
Lay_ShowErrorAndExit ("Wrong type of answer."); Lay_ShowErrorAndExit ("Wrong type of answer. 3");
return (Tst_AnswerType_t) AnsType; return (Tst_AnswerType_t) AnsType;
} }
@ -5977,7 +5980,7 @@ static long Tst_GetQstFromForm (char *Stem,char *Feedback)
Tst_NUM_ANS_TYPES - 1, Tst_NUM_ANS_TYPES - 1,
(unsigned long) Tst_ANS_ALL); (unsigned long) Tst_ANS_ALL);
if (Gbl.Test.AnswerType == Tst_ANS_ALL) if (Gbl.Test.AnswerType == Tst_ANS_ALL)
Lay_ShowErrorAndExit ("Wrong type of answer."); Lay_ShowErrorAndExit ("Wrong type of answer. 4");
/***** Get question tags *****/ /***** Get question tags *****/
for (NumTag = 0; for (NumTag = 0;
@ -6012,18 +6015,18 @@ static long Tst_GetQstFromForm (char *Stem,char *Feedback)
Par_GetParToHTML ("Feedback",Feedback,Cns_MAX_BYTES_TEXT); Par_GetParToHTML ("Feedback",Feedback,Cns_MAX_BYTES_TEXT);
/***** Get media associated to the stem (action, file and title) *****/ /***** Get media associated to the stem (action, file and title) *****/
Gbl.Test.Media.Width = Tst_IMAGE_SAVED_MAX_WIDTH; Gbl.Test.Question.Media.Width = Tst_IMAGE_SAVED_MAX_WIDTH;
Gbl.Test.Media.Height = Tst_IMAGE_SAVED_MAX_HEIGHT; Gbl.Test.Question.Media.Height = Tst_IMAGE_SAVED_MAX_HEIGHT;
Gbl.Test.Media.Quality = Tst_IMAGE_SAVED_QUALITY; Gbl.Test.Question.Media.Quality = Tst_IMAGE_SAVED_QUALITY;
Med_GetMediaFromForm (Gbl.Hierarchy.Crs.CrsCod,QstCod, Med_GetMediaFromForm (Gbl.Hierarchy.Crs.CrsCod,QstCod,
-1, // < 0 ==> the image associated to the stem -1, // < 0 ==> the image associated to the stem
&Gbl.Test.Media, &Gbl.Test.Question.Media,
Tst_GetMediaFromDB, Tst_GetMediaFromDB,
NULL); NULL);
Ale_ShowAlerts (NULL); Ale_ShowAlerts (NULL);
/***** Get answers *****/ /***** Get answers *****/
Gbl.Test.Shuffle = false; Gbl.Test.Question.Shuffle = false;
switch (Gbl.Test.AnswerType) switch (Gbl.Test.AnswerType)
{ {
case Tst_ANS_INT: case Tst_ANS_INT:
@ -6056,7 +6059,7 @@ static long Tst_GetQstFromForm (char *Stem,char *Feedback)
case Tst_ANS_UNIQUE_CHOICE: case Tst_ANS_UNIQUE_CHOICE:
case Tst_ANS_MULTIPLE_CHOICE: case Tst_ANS_MULTIPLE_CHOICE:
/* Get shuffle */ /* Get shuffle */
Gbl.Test.Shuffle = Par_GetParToBool ("Shuffle"); Gbl.Test.Question.Shuffle = Par_GetParToBool ("Shuffle");
/* falls through */ /* falls through */
/* no break */ /* no break */
case Tst_ANS_TEXT: case Tst_ANS_TEXT:
@ -6143,10 +6146,10 @@ static long Tst_GetQstFromForm (char *Stem,char *Feedback)
NumTag++) NumTag++)
if (Gbl.Test.Tags.Txt[NumTag][0]) if (Gbl.Test.Tags.Txt[NumTag][0])
Gbl.Test.Tags.Num++; Gbl.Test.Tags.Num++;
Gbl.Test.Stem.Text = Stem; Gbl.Test.Question.Stem.Text = Stem;
Gbl.Test.Stem.Length = strlen (Gbl.Test.Stem.Text); Gbl.Test.Question.Stem.Length = strlen (Gbl.Test.Question.Stem.Text);
Gbl.Test.Feedback.Text = Feedback; Gbl.Test.Question.Feedback.Text = Feedback;
Gbl.Test.Feedback.Length = strlen (Gbl.Test.Feedback.Text); Gbl.Test.Question.Feedback.Length = strlen (Gbl.Test.Question.Feedback.Text);
return QstCod; return QstCod;
} }
@ -6186,7 +6189,7 @@ bool Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (void)
} }
/***** A question must have a stem*****/ /***** A question must have a stem*****/
if (!Gbl.Test.Stem.Length) if (!Gbl.Test.Question.Stem.Length)
{ {
Ale_ShowAlert (Ale_WARNING,Txt_You_must_type_the_stem_of_the_question); Ale_ShowAlert (Ale_WARNING,Txt_You_must_type_the_stem_of_the_question);
return false; return false;
@ -6363,7 +6366,7 @@ bool Tst_CheckIfQuestionExistsInDB (void)
" WHERE CrsCod=%ld AND AnsType='%s' AND Stem='%s'", " WHERE CrsCod=%ld AND AnsType='%s' AND Stem='%s'",
Gbl.Hierarchy.Crs.CrsCod, Gbl.Hierarchy.Crs.CrsCod,
Tst_StrAnswerTypesDB[Gbl.Test.AnswerType], Tst_StrAnswerTypesDB[Gbl.Test.AnswerType],
Gbl.Test.Stem.Text); Gbl.Test.Question.Stem.Text);
if (NumQstsWithThisStem) // There are questions in database with the same stem that the one of this question if (NumQstsWithThisStem) // There are questions in database with the same stem that the one of this question
{ {
@ -6454,7 +6457,7 @@ static void Tst_MoveMediaToDefinitiveDirectories (long QstCod)
/***** Media associated to question stem *****/ /***** Media associated to question stem *****/
CurrentMedCodInDB = Tst_GetMedCodFromDB (Gbl.Hierarchy.Crs.CrsCod,QstCod, CurrentMedCodInDB = Tst_GetMedCodFromDB (Gbl.Hierarchy.Crs.CrsCod,QstCod,
-1L); // Get current media code associated to stem -1L); // Get current media code associated to stem
Med_RemoveKeepOrStoreMedia (CurrentMedCodInDB,&Gbl.Test.Media); Med_RemoveKeepOrStoreMedia (CurrentMedCodInDB,&Gbl.Test.Question.Media);
/****** Move media associated to answers *****/ /****** Move media associated to answers *****/
if (Gbl.Test.AnswerType == Tst_ANS_UNIQUE_CHOICE || if (Gbl.Test.AnswerType == Tst_ANS_UNIQUE_CHOICE ||
@ -6896,11 +6899,12 @@ static long Tst_InsertOrUpdateQstIntoDB (long QstCod)
"0,0)", "0,0)",
Gbl.Hierarchy.Crs.CrsCod, Gbl.Hierarchy.Crs.CrsCod,
Tst_StrAnswerTypesDB[Gbl.Test.AnswerType], Tst_StrAnswerTypesDB[Gbl.Test.AnswerType],
Gbl.Test.Shuffle ? 'Y' : Gbl.Test.Question.Shuffle ? 'Y' :
'N', 'N',
Gbl.Test.Stem.Text, Gbl.Test.Question.Stem.Text,
Gbl.Test.Feedback.Text ? Gbl.Test.Feedback.Text : "", Gbl.Test.Question.Feedback.Text ? Gbl.Test.Question.Feedback.Text :
Gbl.Test.Media.MedCod); "",
Gbl.Test.Question.Media.MedCod);
} }
else // It's an existing question else // It's an existing question
{ {
@ -6912,11 +6916,12 @@ static long Tst_InsertOrUpdateQstIntoDB (long QstCod)
"Stem='%s',Feedback='%s',MedCod=%ld" "Stem='%s',Feedback='%s',MedCod=%ld"
" WHERE QstCod=%ld AND CrsCod=%ld", " WHERE QstCod=%ld AND CrsCod=%ld",
Tst_StrAnswerTypesDB[Gbl.Test.AnswerType], Tst_StrAnswerTypesDB[Gbl.Test.AnswerType],
Gbl.Test.Shuffle ? 'Y' : Gbl.Test.Question.Shuffle ? 'Y' :
'N', 'N',
Gbl.Test.Stem.Text, Gbl.Test.Question.Stem.Text,
Gbl.Test.Feedback.Text ? Gbl.Test.Feedback.Text : "", Gbl.Test.Question.Feedback.Text ? Gbl.Test.Question.Feedback.Text :
Gbl.Test.Media.MedCod, "",
Gbl.Test.Question.Media.MedCod,
QstCod,Gbl.Hierarchy.Crs.CrsCod); QstCod,Gbl.Hierarchy.Crs.CrsCod);
/* Remove answers and tags from this test question */ /* Remove answers and tags from this test question */

View File

@ -28,6 +28,7 @@
/*****************************************************************************/ /*****************************************************************************/
#include "swad_game.h" #include "swad_game.h"
#include "swad_media.h"
#include "swad_test_result.h" #include "swad_test_result.h"
/*****************************************************************************/ /*****************************************************************************/
@ -57,6 +58,17 @@
/******************************* Public types ********************************/ /******************************* Public types ********************************/
/*****************************************************************************/ /*****************************************************************************/
struct Tst_Question
{
struct
{
char *Text;
size_t Length;
} Stem, Feedback;
struct Media Media;
bool Shuffle;
};
#define Tst_NUM_OPTIONS_PLUGGABLE 3 #define Tst_NUM_OPTIONS_PLUGGABLE 3
typedef enum typedef enum
{ {

View File

@ -248,20 +248,19 @@ static void TsI_ExportQuestion (long QstCod,FILE *FileXML)
/***** Get row *****/ /***** Get row *****/
row = mysql_fetch_row (mysql_res); row = mysql_fetch_row (mysql_res);
/* /*
row[0] QstCod row[0] UNIX_TIMESTAMP(EditTime)
row[1] UNIX_TIMESTAMP(EditTime) row[1] AnsType
row[2] AnsType row[2] Shuffle
row[3] Shuffle row[3] Stem
row[4] Stem row[4] Feedback
row[5] Feedback row[5] MedCod
row[6] MedCod row[6] NumHits
row[7] NumHits row[7] NumHitsNotBlank
row[8] NumHitsNotBlank row[8] Score
row[9] Score
*/ */
/***** Write the question type (row[2]) *****/ /***** Write the answer type (row[1]) *****/
Gbl.Test.AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[2]); Gbl.Test.AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
fprintf (FileXML,"<question type=\"%s\">%s", fprintf (FileXML,"<question type=\"%s\">%s",
Tst_StrAnswerTypesXML[Gbl.Test.AnswerType],Txt_NEW_LINE); Tst_StrAnswerTypesXML[Gbl.Test.AnswerType],Txt_NEW_LINE);
@ -270,23 +269,23 @@ static void TsI_ExportQuestion (long QstCod,FILE *FileXML)
TsI_GetAndWriteTagsXML (QstCod,FileXML); TsI_GetAndWriteTagsXML (QstCod,FileXML);
fprintf (FileXML,"</tags>%s",Txt_NEW_LINE); fprintf (FileXML,"</tags>%s",Txt_NEW_LINE);
/***** Write the stem (row[4]), that is in HTML format *****/ /***** Write the stem (row[3]), that is in HTML format *****/
fprintf (FileXML,"<stem>%s</stem>%s", fprintf (FileXML,"<stem>%s</stem>%s",
row[4],Txt_NEW_LINE); row[3],Txt_NEW_LINE);
/***** Write the feedback (row[5]), that is in HTML format *****/ /***** Write the feedback (row[4]), that is in HTML format *****/
if (row[5]) if (row[4])
if (row[5][0]) if (row[4][0])
fprintf (FileXML,"<feedback>%s</feedback>%s", fprintf (FileXML,"<feedback>%s</feedback>%s",
row[5],Txt_NEW_LINE); row[4],Txt_NEW_LINE);
/***** Write the answers of this question. /***** Write the answers of this question.
Shuffle can be enabled or disabled (row[3]) *****/ Shuffle can be enabled or disabled (row[2]) *****/
fprintf (FileXML,"<answer"); fprintf (FileXML,"<answer");
if (Gbl.Test.AnswerType == Tst_ANS_UNIQUE_CHOICE || if (Gbl.Test.AnswerType == Tst_ANS_UNIQUE_CHOICE ||
Gbl.Test.AnswerType == Tst_ANS_MULTIPLE_CHOICE) Gbl.Test.AnswerType == Tst_ANS_MULTIPLE_CHOICE)
fprintf (FileXML," shuffle=\"%s\"", fprintf (FileXML," shuffle=\"%s\"",
(row[3][0] == 'Y') ? "yes" : (row[2][0] == 'Y') ? "yes" :
"no"); "no");
fprintf (FileXML,">"); fprintf (FileXML,">");
TsI_WriteAnswersOfAQstXML (QstCod,FileXML); TsI_WriteAnswersOfAQstXML (QstCod,FileXML);
@ -624,8 +623,8 @@ static void TsI_ImportQuestionsFromXMLBuffer (const char *XMLBuffer)
Str_ChangeFormat (Str_FROM_TEXT,Str_TO_HTML, Str_ChangeFormat (Str_FROM_TEXT,Str_TO_HTML,
Stem,Cns_MAX_BYTES_TEXT,true); Stem,Cns_MAX_BYTES_TEXT,true);
Gbl.Test.Stem.Text = Stem; Gbl.Test.Question.Stem.Text = Stem;
Gbl.Test.Stem.Length = strlen (Stem); Gbl.Test.Question.Stem.Length = strlen (Stem);
} }
break; // Only first element "stem" break; // Only first element "stem"
} }
@ -644,14 +643,14 @@ static void TsI_ImportQuestionsFromXMLBuffer (const char *XMLBuffer)
Str_ChangeFormat (Str_FROM_TEXT,Str_TO_HTML, Str_ChangeFormat (Str_FROM_TEXT,Str_TO_HTML,
Feedback,Cns_MAX_BYTES_TEXT,true); Feedback,Cns_MAX_BYTES_TEXT,true);
Gbl.Test.Feedback.Text = Feedback; Gbl.Test.Question.Feedback.Text = Feedback;
Gbl.Test.Feedback.Length = strlen (Feedback); Gbl.Test.Question.Feedback.Length = strlen (Feedback);
} }
break; // Only first element "feedback" break; // Only first element "feedback"
} }
/* Get shuffle. By default, shuffle is false. */ /* Get shuffle. By default, shuffle is false. */
Gbl.Test.Shuffle = false; Gbl.Test.Question.Shuffle = false;
for (AnswerElem = QuestionElem->FirstChild; for (AnswerElem = QuestionElem->FirstChild;
AnswerElem != NULL; AnswerElem != NULL;
AnswerElem = AnswerElem->NextBrother) AnswerElem = AnswerElem->NextBrother)
@ -665,7 +664,7 @@ static void TsI_ImportQuestionsFromXMLBuffer (const char *XMLBuffer)
Attribute = Attribute->Next) Attribute = Attribute->Next)
if (!strcmp (Attribute->AttributeName,"shuffle")) if (!strcmp (Attribute->AttributeName,"shuffle"))
{ {
Gbl.Test.Shuffle = XML_GetAttributteYesNoFromXMLTree (Attribute); Gbl.Test.Question.Shuffle = XML_GetAttributteYesNoFromXMLTree (Attribute);
break; // Only first attribute "shuffle" break; // Only first attribute "shuffle"
} }
break; // Only first element "answer" break; // Only first element "answer"
@ -987,7 +986,7 @@ static void TsI_WriteRowImportedQst (struct XMLElement *StemElem,
if (Gbl.Test.AnswerType == Tst_ANS_UNIQUE_CHOICE || if (Gbl.Test.AnswerType == Tst_ANS_UNIQUE_CHOICE ||
Gbl.Test.AnswerType == Tst_ANS_MULTIPLE_CHOICE) Gbl.Test.AnswerType == Tst_ANS_MULTIPLE_CHOICE)
/* Put an icon that indicates whether shuffle is enabled or not */ /* Put an icon that indicates whether shuffle is enabled or not */
if (Gbl.Test.Shuffle) if (Gbl.Test.Question.Shuffle)
Ico_PutIcon ("check.svg",Txt_TST_Answer_given_by_the_teachers, Ico_PutIcon ("check.svg",Txt_TST_Answer_given_by_the_teachers,
QuestionExists ? "ICO_HIDDEN ICO16x16" : QuestionExists ? "ICO_HIDDEN ICO16x16" :
"ICO16x16"); "ICO16x16");

View File

@ -847,7 +847,6 @@ void TsR_ShowTestResult (struct UsrData *UsrDat,
MYSQL_RES *mysql_res; MYSQL_RES *mysql_res;
MYSQL_ROW row; MYSQL_ROW row;
unsigned NumQst; unsigned NumQst;
long QstCod;
double ScoreThisQst; double ScoreThisQst;
bool AnswerIsNotBlank; bool AnswerIsNotBlank;
bool ThisQuestionHasBeenEdited; bool ThisQuestionHasBeenEdited;
@ -865,20 +864,20 @@ void TsR_ShowTestResult (struct UsrData *UsrDat,
/***** Get row of the result of the query *****/ /***** Get row of the result of the query *****/
row = mysql_fetch_row (mysql_res); row = mysql_fetch_row (mysql_res);
/* /*
row[0] QstCod row[0] UNIX_TIMESTAMP(EditTime)
row[1] UNIX_TIMESTAMP(EditTime) row[1] AnsType
row[2] AnsType row[2] Shuffle
row[3] Shuffle row[3] Stem
row[4] Stem row[4] Feedback
row[5] Feedback row[5] MedCod
row[6] MedCod row[6] NumHits
row[7] NumHits row[7] NumHitsNotBlank
row[8] NumHitsNotBlank row[8] Score
row[9] Score
*/ */
/***** If this question has been edited later than test time /***** If this question has been edited later than test time
==> don't show question ****/ ==> don't show question ****/
EditTimeUTC = Dat_GetUNIXTimeFromStr (row[1]); EditTimeUTC = Dat_GetUNIXTimeFromStr (row[0]);
ThisQuestionHasBeenEdited = false; ThisQuestionHasBeenEdited = false;
if (EditTimeUTC > TstTimeUTC) if (EditTimeUTC > TstTimeUTC)
ThisQuestionHasBeenEdited = true; ThisQuestionHasBeenEdited = true;
@ -899,19 +898,13 @@ void TsR_ShowTestResult (struct UsrData *UsrDat,
HTM_TR_End (); HTM_TR_End ();
} }
else else
{
/***** Get the code of question (row[0]) *****/
if ((QstCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
Lay_ShowErrorAndExit ("Wrong code of question.");
/***** Write questions and answers *****/ /***** Write questions and answers *****/
Tst_WriteQstAndAnsTest (Tst_SHOW_TEST_RESULT, Tst_WriteQstAndAnsTest (Tst_SHOW_TEST_RESULT,
UsrDat, UsrDat,
NumQst,QstCod,row, NumQst,Gbl.Test.QstCodes[NumQst],row,
Visibility, Visibility,
&ScoreThisQst, // Not used here &ScoreThisQst, // Not used here
&AnswerIsNotBlank); // Not used here &AnswerIsNotBlank); // Not used here
}
} }
else else
{ {