mirror of
https://github.com/acanas/swad-core.git
synced 2024-06-05 08:15:25 +02:00
Version19.149.2
This commit is contained in:
parent
f818cf372d
commit
b0e6cd080f
|
@ -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.149.1 (2020-03-18)"
|
||||
#define Log_PLATFORM_VERSION "SWAD 19.149.2 (2020-03-19)"
|
||||
#define CSS_FILE "swad19.146.css"
|
||||
#define JS_FILE "swad19.91.1.js"
|
||||
/*
|
||||
|
@ -524,6 +524,7 @@ Param
|
|||
// 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
|
||||
|
||||
Version 19.149.2: Mar 19, 2020 Code refactoring in tests. (283062 lines)
|
||||
Version 19.149.1: Mar 18, 2020 Code refactoring in tests. (283094 lines)
|
||||
Version 19.149: Mar 18, 2020 Code refactoring in tests. (283020 lines)
|
||||
Version 19.148.3: Mar 17, 2020 Code refactoring in tests. (282916 lines)
|
||||
|
|
|
@ -1875,7 +1875,6 @@ static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts,
|
|||
MYSQL_ROW row;
|
||||
long QstCod;
|
||||
struct Tst_Question Question;
|
||||
Tst_AnswerType_t AnswerType;
|
||||
struct Tst_Answer Answer;
|
||||
unsigned QstInd;
|
||||
unsigned MaxQstInd;
|
||||
|
@ -1910,7 +1909,7 @@ static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts,
|
|||
row[1] QstCod
|
||||
*/
|
||||
/***** Create test question *****/
|
||||
Tst_QstConstructor (&Question,&AnswerType,&Answer);
|
||||
Tst_QstConstructor (&Question,&Answer);
|
||||
|
||||
/* Get question index (row[0]) */
|
||||
QstInd = Str_ConvertStrToUnsigned (row[0]);
|
||||
|
|
|
@ -659,7 +659,6 @@ struct Globals
|
|||
char *List;
|
||||
char Txt[Tst_MAX_TAGS_PER_QUESTION][Tst_MAX_BYTES_TAG + 1];
|
||||
} Tags;
|
||||
Tst_AnswerType_t AnswerType;
|
||||
unsigned NumQsts;
|
||||
long QstCodes[Tst_MAX_QUESTIONS_PER_TEST]; // Codes of the sent/received questions in a test
|
||||
char StrIndexesOneQst[Tst_MAX_QUESTIONS_PER_TEST][Tst_MAX_BYTES_INDEXES_ONE_QST + 1]; // 0 1 2 3, 3 0 2 1, etc.
|
||||
|
|
|
@ -3791,7 +3791,6 @@ static void Mch_RemoveMyAnswerToMatchQuestion (const struct Match *Match)
|
|||
static double Mch_ComputeScore (unsigned NumQsts)
|
||||
{
|
||||
unsigned NumQst;
|
||||
Tst_AnswerType_t AnswerType = Tst_ANS_UNIQUE_CHOICE;
|
||||
struct Tst_Answer Answer;
|
||||
double ScoreThisQst;
|
||||
bool AnswerIsNotBlank;
|
||||
|
@ -3799,6 +3798,8 @@ static double Mch_ComputeScore (unsigned NumQsts)
|
|||
bool AnswersUsr[Tst_MAX_OPTIONS_PER_QUESTION];
|
||||
double TotalScore = 0.0;
|
||||
|
||||
Answer.Type = Tst_ANS_UNIQUE_CHOICE;
|
||||
|
||||
for (NumQst = 0;
|
||||
NumQst < NumQsts;
|
||||
NumQst++)
|
||||
|
@ -3813,7 +3814,7 @@ static double Mch_ComputeScore (unsigned NumQsts)
|
|||
Tst_GetCorrectAnswersFromDB (Gbl.Test.QstCodes[NumQst],&Answer);
|
||||
|
||||
/***** Compute the total score of this question *****/
|
||||
Tst_ComputeScoreQst (AnswerType,&Answer,
|
||||
Tst_ComputeScoreQst (&Answer,
|
||||
Indexes,AnswersUsr,&ScoreThisQst,&AnswerIsNotBlank);
|
||||
|
||||
/***** Compute total score *****/
|
||||
|
|
168
swad_test.c
168
swad_test.c
|
@ -197,7 +197,6 @@ static void Tst_WriteChoiceAnsViewTest (unsigned NumQst,long QstCod,
|
|||
bool Shuffle);
|
||||
static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat,
|
||||
unsigned NumQst,
|
||||
Tst_AnswerType_t AnswerType,
|
||||
struct Tst_Answer *Answer,
|
||||
MYSQL_RES *mysql_res,
|
||||
unsigned Visibility,
|
||||
|
@ -242,14 +241,12 @@ static int Tst_CountNumTagsInList (void);
|
|||
static int Tst_CountNumAnswerTypesInList (void);
|
||||
static void Tst_PutFormEditOneQst (long QstCod,
|
||||
const struct Tst_Question *Question,
|
||||
Tst_AnswerType_t AnswerType,
|
||||
const struct Tst_Answer *Answer,
|
||||
char Stem[Cns_MAX_BYTES_TEXT + 1],
|
||||
char Feedback[Cns_MAX_BYTES_TEXT + 1]);
|
||||
static void Tst_PutFloatInputField (const char *Label,const char *Field,
|
||||
double Value,Tst_AnswerType_t AnswerType);
|
||||
static void Tst_PutTFInputField (Tst_AnswerType_t AnswerType,
|
||||
const struct Tst_Answer *Answer,
|
||||
static void Tst_PutTFInputField (const struct Tst_Answer *Answer,
|
||||
const char *Label,char Value);
|
||||
|
||||
static void Tst_FreeTextChoiceAnswers (struct Tst_Answer *Answer);
|
||||
|
@ -262,7 +259,6 @@ static void Tst_FreeMediaOfQuestion (struct Tst_Question *Question,
|
|||
|
||||
static void Tst_GetQstDataFromDB (long QstCod,
|
||||
struct Tst_Question *Question,
|
||||
Tst_AnswerType_t *AnswerType,
|
||||
struct Tst_Answer *Answer,
|
||||
char Stem[Cns_MAX_BYTES_TEXT + 1],
|
||||
char Feedback[Cns_MAX_BYTES_TEXT + 1]);
|
||||
|
@ -272,12 +268,10 @@ static void Tst_GetMediaFromDB (long CrsCod,long QstCod,int NumOpt,
|
|||
|
||||
static Tst_AnswerType_t Tst_ConvertFromUnsignedStrToAnsTyp (const char *UnsignedStr);
|
||||
static long Tst_GetQstFromForm (struct Tst_Question *Question,
|
||||
Tst_AnswerType_t *AnswerType,
|
||||
struct Tst_Answer *Answer,
|
||||
char *Stem,char *Feedback);
|
||||
static void Tst_MoveMediaToDefinitiveDirectories (long QstCod,
|
||||
struct Tst_Question *Question,
|
||||
Tst_AnswerType_t AnswerType,
|
||||
struct Tst_Answer *Answer);
|
||||
|
||||
static long Tst_GetTagCodFromTagTxt (const char *TagTxt);
|
||||
|
@ -297,7 +291,6 @@ static long Tst_InsertOrUpdateQstIntoDB (long QstCod,
|
|||
Tst_AnswerType_t AnswerType);
|
||||
static void Tst_InsertTagsIntoDB (long QstCod);
|
||||
static void Tst_InsertAnswersIntoDB (long QstCod,
|
||||
Tst_AnswerType_t AnswerType,
|
||||
struct Tst_Answer *Answer);
|
||||
|
||||
static void Tst_RemAnsFromQst (long QstCod);
|
||||
|
@ -1017,7 +1010,6 @@ void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestio
|
|||
{
|
||||
extern const char *Txt_TST_STR_ANSWER_TYPES[Tst_NUM_ANS_TYPES];
|
||||
struct Tst_Question Question;
|
||||
Tst_AnswerType_t AnswerType;
|
||||
struct Tst_Answer Answer;
|
||||
bool IsVisibleQstAndAnsTxt = TsV_IsVisibleQstAndAnsTxt (Visibility);
|
||||
/*
|
||||
|
@ -1032,7 +1024,7 @@ void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestio
|
|||
row[8] Score
|
||||
*/
|
||||
/***** Create test question *****/
|
||||
Tst_QstConstructor (&Question,&AnswerType,&Answer);
|
||||
Tst_QstConstructor (&Question,&Answer);
|
||||
|
||||
HTM_TR_Begin (NULL);
|
||||
HTM_TD_Begin ("class=\"RT COLOR%u\"",Gbl.RowEvenOdd);
|
||||
|
@ -1043,9 +1035,9 @@ void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestio
|
|||
HTM_DIV_End ();
|
||||
|
||||
/***** Write answer type (row[1]) *****/
|
||||
AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
|
||||
Answer.Type = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
|
||||
HTM_DIV_Begin ("class=\"DAT_SMALL\"");
|
||||
HTM_Txt (Txt_TST_STR_ANSWER_TYPES[AnswerType]);
|
||||
HTM_Txt (Txt_TST_STR_ANSWER_TYPES[Answer.Type]);
|
||||
HTM_DIV_End ();
|
||||
|
||||
HTM_TD_End ();
|
||||
|
@ -1068,10 +1060,10 @@ void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestio
|
|||
switch (ActionToDoWithQuestions)
|
||||
{
|
||||
case Tst_SHOW_TEST_TO_ANSWER:
|
||||
Tst_WriteAnswersTestToAnswer (NumQst,QstCod,AnswerType,(row[2][0] == 'Y'));
|
||||
Tst_WriteAnswersTestToAnswer (NumQst,QstCod,Answer.Type,(row[2][0] == 'Y'));
|
||||
break;
|
||||
case Tst_SHOW_TEST_RESULT:
|
||||
Tst_WriteAnswersTestResult (UsrDat,NumQst,QstCod,AnswerType,
|
||||
Tst_WriteAnswersTestResult (UsrDat,NumQst,QstCod,Answer.Type,
|
||||
Visibility,
|
||||
ScoreThisQst,AnswerIsNotBlank);
|
||||
|
||||
|
@ -2905,7 +2897,6 @@ static void Tst_WriteQuestionRowForEdition (unsigned long NumRows,
|
|||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
struct Tst_Question Question;
|
||||
Tst_AnswerType_t AnswerType;
|
||||
struct Tst_Answer Answer;
|
||||
static unsigned UniqueId = 0;
|
||||
char *Id;
|
||||
|
@ -2915,7 +2906,7 @@ static void Tst_WriteQuestionRowForEdition (unsigned long NumRows,
|
|||
double TotalScoreThisQst;
|
||||
|
||||
/***** Create test question *****/
|
||||
Tst_QstConstructor (&Question,&AnswerType,&Answer);
|
||||
Tst_QstConstructor (&Question,&Answer);
|
||||
|
||||
/***** Get and show questvoidion data *****/
|
||||
if (Tst_GetOneQuestionByCod (QstCod,&mysql_res))
|
||||
|
@ -2964,9 +2955,9 @@ static void Tst_WriteQuestionRowForEdition (unsigned long NumRows,
|
|||
HTM_DIV_End ();
|
||||
|
||||
/* Write answer type (row[1]) */
|
||||
AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
|
||||
Answer.Type = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
|
||||
HTM_DIV_Begin ("class=\"DAT_SMALL\"");
|
||||
HTM_Txt (Txt_TST_STR_ANSWER_TYPES[AnswerType]);
|
||||
HTM_Txt (Txt_TST_STR_ANSWER_TYPES[Answer.Type]);
|
||||
HTM_DIV_End ();
|
||||
|
||||
HTM_TD_End ();
|
||||
|
@ -2995,8 +2986,8 @@ static void Tst_WriteQuestionRowForEdition (unsigned long NumRows,
|
|||
|
||||
/* Write if shuffle is enabled (row[2]) */
|
||||
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
|
||||
if (AnswerType == Tst_ANS_UNIQUE_CHOICE ||
|
||||
AnswerType == Tst_ANS_MULTIPLE_CHOICE)
|
||||
if (Answer.Type == Tst_ANS_UNIQUE_CHOICE ||
|
||||
Answer.Type == Tst_ANS_MULTIPLE_CHOICE)
|
||||
{
|
||||
Frm_StartForm (ActChgShfTstQst);
|
||||
Tst_PutParamQstCod (QstCod);
|
||||
|
@ -3027,7 +3018,7 @@ static void Tst_WriteQuestionRowForEdition (unsigned long NumRows,
|
|||
|
||||
/* Write feedback (row[4]) and answers */
|
||||
Tst_WriteQstFeedback (row[4],"TEST_EDI_LIGHT");
|
||||
Tst_WriteAnswersEdit (QstCod,AnswerType);
|
||||
Tst_WriteAnswersEdit (QstCod,Answer.Type);
|
||||
HTM_TD_End ();
|
||||
|
||||
/* Get number of hits
|
||||
|
@ -3172,14 +3163,13 @@ static void Tst_WriteQuestionRowForSelection (unsigned long NumRow,long QstCod)
|
|||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
struct Tst_Question Question;
|
||||
Tst_AnswerType_t AnswerType;
|
||||
struct Tst_Answer Answer;
|
||||
static unsigned UniqueId = 0;
|
||||
char *Id;
|
||||
time_t TimeUTC;
|
||||
|
||||
/***** Create test question *****/
|
||||
Tst_QstConstructor (&Question,&AnswerType,&Answer);
|
||||
Tst_QstConstructor (&Question,&Answer);
|
||||
|
||||
/***** Get and show questvoidion data *****/
|
||||
if (Tst_GetOneQuestionByCod (QstCod,&mysql_res))
|
||||
|
@ -3237,9 +3227,9 @@ static void Tst_WriteQuestionRowForSelection (unsigned long NumRow,long QstCod)
|
|||
HTM_TD_End ();
|
||||
|
||||
/* Write the question type (row[1]) */
|
||||
AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
|
||||
Answer.Type = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
|
||||
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
|
||||
HTM_TxtF ("%s ",Txt_TST_STR_ANSWER_TYPES[AnswerType]);
|
||||
HTM_TxtF ("%s ",Txt_TST_STR_ANSWER_TYPES[Answer.Type]);
|
||||
HTM_TD_End ();
|
||||
|
||||
/* Write if shuffle is enabled (row[2]) */
|
||||
|
@ -3266,7 +3256,7 @@ static void Tst_WriteQuestionRowForSelection (unsigned long NumRow,long QstCod)
|
|||
Tst_WriteQstFeedback (row[4],"TEST_EDI_LIGHT");
|
||||
|
||||
/* Write answers */
|
||||
Tst_WriteAnswersEdit (QstCod,AnswerType);
|
||||
Tst_WriteAnswersEdit (QstCod,Answer.Type);
|
||||
HTM_TD_End ();
|
||||
|
||||
/***** End table row *****/
|
||||
|
@ -3380,7 +3370,8 @@ void Tst_WriteAnswersEdit (long QstCod,Tst_AnswerType_t AnswerType)
|
|||
double FloatNum[2];
|
||||
|
||||
/***** Create test question *****/
|
||||
Tst_QstConstructor (&Question,&AnswerType,&Answer);
|
||||
Tst_QstConstructor (&Question,&Answer);
|
||||
Answer.Type = AnswerType;
|
||||
|
||||
/***** Get answers *****/
|
||||
Answer.NumOptions = Tst_GetAnswersQst (QstCod,&mysql_res,false);
|
||||
|
@ -3393,7 +3384,7 @@ void Tst_WriteAnswersEdit (long QstCod,Tst_AnswerType_t AnswerType)
|
|||
*/
|
||||
|
||||
/***** Write answers *****/
|
||||
switch (AnswerType)
|
||||
switch (Answer.Type)
|
||||
{
|
||||
case Tst_ANS_INT:
|
||||
Tst_CheckIfNumberOfAnswersIsOne (&Answer);
|
||||
|
@ -3569,7 +3560,8 @@ static void Tst_WriteAnswersTestResult (struct UsrData *UsrDat,
|
|||
struct Tst_Answer Answer;
|
||||
|
||||
/***** Create test question *****/
|
||||
Tst_QstConstructor (&Question,&AnswerType,&Answer);
|
||||
Tst_QstConstructor (&Question,&Answer);
|
||||
Answer.Type = AnswerType;
|
||||
|
||||
/***** Get answer of a question from database *****/
|
||||
Answer.NumOptions = Tst_GetAnswersQst (QstCod,&mysql_res,false);
|
||||
|
@ -3582,7 +3574,7 @@ static void Tst_WriteAnswersTestResult (struct UsrData *UsrDat,
|
|||
*/
|
||||
|
||||
/***** Write answer depending on type *****/
|
||||
switch (AnswerType)
|
||||
switch (Answer.Type)
|
||||
{
|
||||
case Tst_ANS_INT:
|
||||
Tst_WriteIntAnsAssessTest (UsrDat,NumQst,&Answer,mysql_res,
|
||||
|
@ -3601,7 +3593,7 @@ static void Tst_WriteAnswersTestResult (struct UsrData *UsrDat,
|
|||
break;
|
||||
case Tst_ANS_UNIQUE_CHOICE:
|
||||
case Tst_ANS_MULTIPLE_CHOICE:
|
||||
Tst_WriteChoiceAnsAssessTest (UsrDat,NumQst,AnswerType,&Answer,mysql_res,
|
||||
Tst_WriteChoiceAnsAssessTest (UsrDat,NumQst,&Answer,mysql_res,
|
||||
Visibility,
|
||||
ScoreThisQst,AnswerIsNotBlank);
|
||||
break;
|
||||
|
@ -3790,7 +3782,8 @@ static void Tst_WriteChoiceAnsViewTest (unsigned NumQst,long QstCod,
|
|||
char StrAns[32];
|
||||
|
||||
/***** Create test question *****/
|
||||
Tst_QstConstructor (&Question,&AnswerType,&Answer);
|
||||
Tst_QstConstructor (&Question,&Answer);
|
||||
Answer.Type = AnswerType;
|
||||
|
||||
/***** Get answers of a question from database *****/
|
||||
Answer.NumOptions = Tst_GetAnswersQst (QstCod,&mysql_res,Shuffle);
|
||||
|
@ -3852,14 +3845,14 @@ static void Tst_WriteChoiceAnsViewTest (unsigned NumQst,long QstCod,
|
|||
snprintf (StrAns,sizeof (StrAns),
|
||||
"Ans%06u",
|
||||
NumQst);
|
||||
if (AnswerType == Tst_ANS_UNIQUE_CHOICE)
|
||||
if (Answer.Type == Tst_ANS_UNIQUE_CHOICE)
|
||||
HTM_INPUT_RADIO (StrAns,false,
|
||||
"id=\"Ans%06u_%u\" value=\"%u\""
|
||||
" onclick=\"selectUnselectRadio(this,this.form.Ans%06u,%u);\"",
|
||||
NumQst,NumOpt,
|
||||
Index,
|
||||
NumQst,Answer.NumOptions);
|
||||
else // AnswerType == Tst_ANS_MULTIPLE_CHOICE
|
||||
else // Answer.Type == Tst_ANS_MULTIPLE_CHOICE
|
||||
HTM_INPUT_CHECKBOX (StrAns,HTM_DONT_SUBMIT_ON_CHANGE,
|
||||
"id=\"Ans%06u_%u\" value=\"%u\"",
|
||||
NumQst,NumOpt,
|
||||
|
@ -3901,7 +3894,6 @@ static void Tst_WriteChoiceAnsViewTest (unsigned NumQst,long QstCod,
|
|||
|
||||
static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat,
|
||||
unsigned NumQst,
|
||||
Tst_AnswerType_t AnswerType,
|
||||
struct Tst_Answer *Answer,
|
||||
MYSQL_RES *mysql_res,
|
||||
unsigned Visibility,
|
||||
|
@ -3930,7 +3922,7 @@ static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat,
|
|||
Tst_GetAnswersFromStr (Gbl.Test.StrAnswersOneQst[NumQst],AnswersUsr);
|
||||
|
||||
/***** Compute the total score of this question *****/
|
||||
Tst_ComputeScoreQst (AnswerType,Answer,
|
||||
Tst_ComputeScoreQst (Answer,
|
||||
Indexes,AnswersUsr,ScoreThisQst,AnswerIsNotBlank);
|
||||
|
||||
/***** Begin table *****/
|
||||
|
@ -4181,8 +4173,7 @@ void Tst_GetAnswersFromStr (const char StrAnswersOneQst[Tst_MAX_BYTES_ANSWERS_ON
|
|||
/********************* Compute the score of this question ********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void Tst_ComputeScoreQst (Tst_AnswerType_t AnswerType,
|
||||
const struct Tst_Answer *Answer,
|
||||
void Tst_ComputeScoreQst (const struct Tst_Answer *Answer,
|
||||
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION], // Indexes of all answers of this question
|
||||
bool AnswersUsr[Tst_MAX_OPTIONS_PER_QUESTION],
|
||||
double *ScoreThisQst,bool *AnswerIsNotBlank)
|
||||
|
@ -4216,7 +4207,7 @@ void Tst_ComputeScoreQst (Tst_AnswerType_t AnswerType,
|
|||
if (*AnswerIsNotBlank)
|
||||
{
|
||||
/* Compute the score */
|
||||
if (AnswerType == Tst_ANS_UNIQUE_CHOICE)
|
||||
if (Answer->Type == Tst_ANS_UNIQUE_CHOICE)
|
||||
{
|
||||
if (NumOptTotInQst >= 2) // It should be 2 options at least
|
||||
*ScoreThisQst = (double) NumAnsGood -
|
||||
|
@ -4255,7 +4246,6 @@ void Tst_WriteChoiceAnsViewMatch (long MchCod,unsigned QstInd,long QstCod,
|
|||
unsigned NumCols,const char *Class,bool ShowResult)
|
||||
{
|
||||
struct Tst_Question Question;
|
||||
Tst_AnswerType_t AnswerType;
|
||||
struct Tst_Answer Answer;
|
||||
unsigned NumOpt;
|
||||
bool RowIsOpen = false;
|
||||
|
@ -4266,7 +4256,7 @@ void Tst_WriteChoiceAnsViewMatch (long MchCod,unsigned QstInd,long QstCod,
|
|||
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION]; // Indexes of all answers of this question
|
||||
|
||||
/***** Create test question *****/
|
||||
Tst_QstConstructor (&Question,&AnswerType,&Answer);
|
||||
Tst_QstConstructor (&Question,&Answer);
|
||||
|
||||
/***** Get number of users who have answered this question from database *****/
|
||||
NumRespondersQst = Mch_GetNumUsrsWhoAnsweredQst (MchCod,QstInd);
|
||||
|
@ -5186,22 +5176,21 @@ void Tst_ShowFormEditOneQst (void)
|
|||
{
|
||||
long QstCod;
|
||||
struct Tst_Question Question;
|
||||
Tst_AnswerType_t AnswerType;
|
||||
struct Tst_Answer Answer;
|
||||
char Stem[Cns_MAX_BYTES_TEXT + 1];
|
||||
char Feedback[Cns_MAX_BYTES_TEXT + 1];
|
||||
|
||||
/***** Create test question *****/
|
||||
Tst_QstConstructor (&Question,&AnswerType,&Answer);
|
||||
Tst_QstConstructor (&Question,&Answer);
|
||||
|
||||
/***** Get question data *****/
|
||||
QstCod = Tst_GetQstCod ();
|
||||
Stem[0] = Feedback[0] = '\0';
|
||||
if (QstCod > 0) // If question already exists in the database
|
||||
Tst_GetQstDataFromDB (QstCod,&Question,&AnswerType,&Answer,Stem,Feedback);
|
||||
Tst_GetQstDataFromDB (QstCod,&Question,&Answer,Stem,Feedback);
|
||||
|
||||
/***** Put form to edit question *****/
|
||||
Tst_PutFormEditOneQst (QstCod,&Question,AnswerType,&Answer,Stem,Feedback);
|
||||
Tst_PutFormEditOneQst (QstCod,&Question,&Answer,Stem,Feedback);
|
||||
|
||||
/***** Destroy test question *****/
|
||||
Tst_QstDestructor (&Question,&Answer);
|
||||
|
@ -5218,7 +5207,6 @@ void Tst_ShowFormEditOneQst (void)
|
|||
|
||||
static void Tst_PutFormEditOneQst (long QstCod,
|
||||
const struct Tst_Question *Question,
|
||||
Tst_AnswerType_t AnswerType,
|
||||
const struct Tst_Answer *Answer,
|
||||
char Stem[Cns_MAX_BYTES_TEXT + 1],
|
||||
char Feedback[Cns_MAX_BYTES_TEXT + 1])
|
||||
|
@ -5415,7 +5403,7 @@ static void Tst_PutFormEditOneQst (long QstCod,
|
|||
HTM_INPUT_RADIO ("AnswerType",false,
|
||||
"value=\"%u\"%s onclick=\"enableDisableAns(this.form);\"",
|
||||
(unsigned) AnsType,
|
||||
AnsType == AnswerType ? " checked=\"checked\"" :
|
||||
AnsType == Answer->Type ? " checked=\"checked\"" :
|
||||
"");
|
||||
HTM_TxtF ("%s ",Txt_TST_STR_ANSWER_TYPES[AnsType]);
|
||||
HTM_LABEL_End ();
|
||||
|
@ -5441,7 +5429,7 @@ static void Tst_PutFormEditOneQst (long QstCod,
|
|||
Answer->Integer);
|
||||
HTM_INPUT_TEXT ("AnsInt",Cns_MAX_DECIMAL_DIGITS_LONG,StrInteger,false,
|
||||
"size=\"11\" required=\"required\"%s",
|
||||
AnswerType == Tst_ANS_INT ? "" :
|
||||
Answer->Type == Tst_ANS_INT ? "" :
|
||||
" disabled=\"disabled\"");
|
||||
HTM_LABEL_End ();
|
||||
HTM_TD_End ();
|
||||
|
@ -5453,9 +5441,9 @@ static void Tst_PutFormEditOneQst (long QstCod,
|
|||
HTM_TD_Empty (1);
|
||||
HTM_TD_Begin ("class=\"LT\"");
|
||||
Tst_PutFloatInputField (Txt_Real_number_between_A_and_B_1,"AnsFloatMin",
|
||||
Answer->FloatingPoint[0],AnswerType);
|
||||
Answer->FloatingPoint[0],Answer->Type);
|
||||
Tst_PutFloatInputField (Txt_Real_number_between_A_and_B_2,"AnsFloatMax",
|
||||
Answer->FloatingPoint[1],AnswerType);
|
||||
Answer->FloatingPoint[1],Answer->Type);
|
||||
HTM_TD_End ();
|
||||
HTM_TR_End ();
|
||||
|
||||
|
@ -5463,8 +5451,8 @@ static void Tst_PutFormEditOneQst (long QstCod,
|
|||
HTM_TR_Begin (NULL);
|
||||
HTM_TD_Empty (1);
|
||||
HTM_TD_Begin ("class=\"LT\"");
|
||||
Tst_PutTFInputField (AnswerType,Answer,Txt_TF_QST[0],'T');
|
||||
Tst_PutTFInputField (AnswerType,Answer,Txt_TF_QST[1],'F');
|
||||
Tst_PutTFInputField (Answer,Txt_TF_QST[0],'T');
|
||||
Tst_PutTFInputField (Answer,Txt_TF_QST[1],'F');
|
||||
HTM_TD_End ();
|
||||
HTM_TR_End ();
|
||||
|
||||
|
@ -5479,8 +5467,8 @@ static void Tst_PutFormEditOneQst (long QstCod,
|
|||
"value=\"Y\"%s%s",
|
||||
Question->Shuffle ? " checked=\"checked\"" :
|
||||
"",
|
||||
AnswerType != Tst_ANS_UNIQUE_CHOICE &&
|
||||
AnswerType != Tst_ANS_MULTIPLE_CHOICE ? " disabled=\"disabled\"" :
|
||||
Answer->Type != Tst_ANS_UNIQUE_CHOICE &&
|
||||
Answer->Type != Tst_ANS_MULTIPLE_CHOICE ? " disabled=\"disabled\"" :
|
||||
"");
|
||||
HTM_Txt (Txt_Shuffle);
|
||||
HTM_LABEL_End ();
|
||||
|
@ -5494,9 +5482,9 @@ static void Tst_PutFormEditOneQst (long QstCod,
|
|||
HTM_TD_Begin ("class=\"LT\"");
|
||||
HTM_TABLE_BeginPadding (2); // Table with choice answers
|
||||
|
||||
OptionsDisabled = AnswerType != Tst_ANS_UNIQUE_CHOICE &&
|
||||
AnswerType != Tst_ANS_MULTIPLE_CHOICE &&
|
||||
AnswerType != Tst_ANS_TEXT;
|
||||
OptionsDisabled = Answer->Type != Tst_ANS_UNIQUE_CHOICE &&
|
||||
Answer->Type != Tst_ANS_MULTIPLE_CHOICE &&
|
||||
Answer->Type != Tst_ANS_TEXT;
|
||||
for (NumOpt = 0;
|
||||
NumOpt < Tst_MAX_OPTIONS_PER_QUESTION;
|
||||
NumOpt++)
|
||||
|
@ -5523,7 +5511,7 @@ static void Tst_PutFormEditOneQst (long QstCod,
|
|||
Answer->Options[NumOpt].Correct ? " checked=\"checked\"" : "",
|
||||
NumOpt < 2 ? " required=\"required\"" : // First or second options required
|
||||
"",
|
||||
AnswerType == Tst_ANS_UNIQUE_CHOICE ? "" :
|
||||
Answer->Type == Tst_ANS_UNIQUE_CHOICE ? "" :
|
||||
" disabled=\"disabled\"");
|
||||
|
||||
/* Checkbox for multiple choice answers */
|
||||
|
@ -5532,7 +5520,7 @@ static void Tst_PutFormEditOneQst (long QstCod,
|
|||
NumOpt,
|
||||
Answer->Options[NumOpt].Correct ? " checked=\"checked\"" :
|
||||
"",
|
||||
AnswerType == Tst_ANS_MULTIPLE_CHOICE ? "" :
|
||||
Answer->Type == Tst_ANS_MULTIPLE_CHOICE ? "" :
|
||||
" disabled=\"disabled\"");
|
||||
|
||||
HTM_TD_End ();
|
||||
|
@ -5655,8 +5643,7 @@ static void Tst_PutFloatInputField (const char *Label,const char *Field,
|
|||
/*********************** Put input field for T/F answer **********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Tst_PutTFInputField (Tst_AnswerType_t AnswerType,
|
||||
const struct Tst_Answer *Answer,
|
||||
static void Tst_PutTFInputField (const struct Tst_Answer *Answer,
|
||||
const char *Label,char Value)
|
||||
{
|
||||
extern const char *The_ClassFormInBox[The_NUM_THEMES];
|
||||
|
@ -5667,7 +5654,7 @@ static void Tst_PutTFInputField (Tst_AnswerType_t AnswerType,
|
|||
Value,
|
||||
Answer->TF == Value ? " checked=\"checked\"" :
|
||||
"",
|
||||
AnswerType == Tst_ANS_TRUE_FALSE ? "" :
|
||||
Answer->Type == Tst_ANS_TRUE_FALSE ? "" :
|
||||
" disabled=\"disabled\"");
|
||||
HTM_Txt (Label);
|
||||
HTM_LABEL_End ();
|
||||
|
@ -5678,7 +5665,6 @@ static void Tst_PutTFInputField (Tst_AnswerType_t AnswerType,
|
|||
/*****************************************************************************/
|
||||
|
||||
void Tst_QstConstructor (struct Tst_Question *Question,
|
||||
Tst_AnswerType_t *AnswerType,
|
||||
struct Tst_Answer *Answer)
|
||||
{
|
||||
unsigned NumOpt;
|
||||
|
@ -5689,7 +5675,7 @@ void Tst_QstConstructor (struct Tst_Question *Question,
|
|||
Question->Feedback.Length = 0;
|
||||
Question->Shuffle = false;
|
||||
|
||||
*AnswerType = Tst_ANS_UNIQUE_CHOICE;
|
||||
Answer->Type = Tst_ANS_UNIQUE_CHOICE;
|
||||
Answer->NumOptions = 0;
|
||||
Answer->TF = ' ';
|
||||
|
||||
|
@ -5824,7 +5810,6 @@ static void Tst_FreeMediaOfQuestion (struct Tst_Question *Question,
|
|||
|
||||
static void Tst_GetQstDataFromDB (long QstCod,
|
||||
struct Tst_Question *Question,
|
||||
Tst_AnswerType_t *AnswerType,
|
||||
struct Tst_Answer *Answer,
|
||||
char Stem[Cns_MAX_BYTES_TEXT + 1],
|
||||
char Feedback[Cns_MAX_BYTES_TEXT + 1])
|
||||
|
@ -5849,7 +5834,7 @@ static void Tst_GetQstDataFromDB (long QstCod,
|
|||
row = mysql_fetch_row (mysql_res);
|
||||
|
||||
/* Get the type of answer */
|
||||
*AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[0]);
|
||||
Answer->Type = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[0]);
|
||||
|
||||
/* Get shuffle (row[1]) */
|
||||
Question->Shuffle = (row[1][0] == 'Y');
|
||||
|
@ -5900,7 +5885,7 @@ static void Tst_GetQstDataFromDB (long QstCod,
|
|||
NumOpt++)
|
||||
{
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
switch (*AnswerType)
|
||||
switch (Answer->Type)
|
||||
{
|
||||
case Tst_ANS_INT:
|
||||
if (Answer->NumOptions != 1)
|
||||
|
@ -6056,26 +6041,25 @@ void Tst_ReceiveQst (void)
|
|||
{
|
||||
long QstCod;
|
||||
struct Tst_Question Question;
|
||||
Tst_AnswerType_t AnswerType;
|
||||
struct Tst_Answer Answer;
|
||||
char Stem[Cns_MAX_BYTES_TEXT + 1];
|
||||
char Feedback[Cns_MAX_BYTES_TEXT + 1];
|
||||
|
||||
/***** Create test question *****/
|
||||
Tst_QstConstructor (&Question,&AnswerType,&Answer);
|
||||
Tst_QstConstructor (&Question,&Answer);
|
||||
|
||||
/***** Get parameters of the question from form *****/
|
||||
Stem[0] = Feedback[0] = '\0';
|
||||
QstCod = Tst_GetQstFromForm (&Question,&AnswerType,&Answer,Stem,Feedback);
|
||||
QstCod = Tst_GetQstFromForm (&Question,&Answer,Stem,Feedback);
|
||||
|
||||
/***** Make sure that tags, text and answer are not empty *****/
|
||||
if (Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (&Question,AnswerType,&Answer))
|
||||
if (Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (&Question,&Answer))
|
||||
{
|
||||
/***** Move images to definitive directories *****/
|
||||
Tst_MoveMediaToDefinitiveDirectories (QstCod,&Question,AnswerType,&Answer);
|
||||
Tst_MoveMediaToDefinitiveDirectories (QstCod,&Question,&Answer);
|
||||
|
||||
/***** Insert or update question, tags and answer in the database *****/
|
||||
QstCod = Tst_InsertOrUpdateQstTagsAnsIntoDB (QstCod,&Question,AnswerType,&Answer);
|
||||
QstCod = Tst_InsertOrUpdateQstTagsAnsIntoDB (QstCod,&Question,&Answer);
|
||||
|
||||
/***** Show the question just inserted in the database *****/
|
||||
Tst_ListOneQstToEdit (QstCod);
|
||||
|
@ -6086,7 +6070,7 @@ void Tst_ReceiveQst (void)
|
|||
Tst_ResetMediaOfQuestion (&Question,&Answer);
|
||||
|
||||
/***** Put form to edit question again *****/
|
||||
Tst_PutFormEditOneQst (QstCod,&Question,AnswerType,&Answer,Stem,Feedback);
|
||||
Tst_PutFormEditOneQst (QstCod,&Question,&Answer,Stem,Feedback);
|
||||
}
|
||||
|
||||
/***** Destroy test question *****/
|
||||
|
@ -6098,7 +6082,6 @@ void Tst_ReceiveQst (void)
|
|||
/*****************************************************************************/
|
||||
|
||||
static long Tst_GetQstFromForm (struct Tst_Question *Question,
|
||||
Tst_AnswerType_t *AnswerType,
|
||||
struct Tst_Answer *Answer,
|
||||
char *Stem,char *Feedback)
|
||||
{
|
||||
|
@ -6119,12 +6102,12 @@ static long Tst_GetQstFromForm (struct Tst_Question *Question,
|
|||
QstCod = Tst_GetQstCod ();
|
||||
|
||||
/***** Get answer type *****/
|
||||
*AnswerType = (Tst_AnswerType_t)
|
||||
Answer->Type = (Tst_AnswerType_t)
|
||||
Par_GetParToUnsignedLong ("AnswerType",
|
||||
0,
|
||||
Tst_NUM_ANS_TYPES - 1,
|
||||
(unsigned long) Tst_ANS_ALL);
|
||||
if (*AnswerType == Tst_ANS_ALL)
|
||||
if (Answer->Type == Tst_ANS_ALL)
|
||||
Lay_ShowErrorAndExit ("Wrong type of answer. 4");
|
||||
|
||||
/***** Get question tags *****/
|
||||
|
@ -6172,7 +6155,7 @@ static long Tst_GetQstFromForm (struct Tst_Question *Question,
|
|||
|
||||
/***** Get answers *****/
|
||||
Question->Shuffle = false;
|
||||
switch (*AnswerType)
|
||||
switch (Answer->Type)
|
||||
{
|
||||
case Tst_ANS_INT:
|
||||
if (!Tst_AllocateTextChoiceAnswer (Answer,0))
|
||||
|
@ -6223,7 +6206,7 @@ static long Tst_GetQstFromForm (struct Tst_Question *Question,
|
|||
NumOpt);
|
||||
Par_GetParToHTML (AnsStr,Answer->Options[NumOpt].Text,
|
||||
Tst_MAX_BYTES_ANSWER_OR_FEEDBACK);
|
||||
if (*AnswerType == Tst_ANS_TEXT)
|
||||
if (Answer->Type == Tst_ANS_TEXT)
|
||||
/* In order to compare student answer to stored answer,
|
||||
the text answers are stored avoiding two or more consecurive spaces */
|
||||
Str_ReplaceSeveralSpacesForOne (Answer->Options[NumOpt].Text);
|
||||
|
@ -6236,8 +6219,8 @@ static long Tst_GetQstFromForm (struct Tst_Question *Question,
|
|||
Tst_MAX_BYTES_ANSWER_OR_FEEDBACK);
|
||||
|
||||
/* Get media associated to the answer (action, file and title) */
|
||||
if (*AnswerType == Tst_ANS_UNIQUE_CHOICE ||
|
||||
*AnswerType == Tst_ANS_MULTIPLE_CHOICE)
|
||||
if (Answer->Type == Tst_ANS_UNIQUE_CHOICE ||
|
||||
Answer->Type == Tst_ANS_MULTIPLE_CHOICE)
|
||||
{
|
||||
Answer->Options[NumOpt].Media.Width = Tst_IMAGE_SAVED_MAX_WIDTH;
|
||||
Answer->Options[NumOpt].Media.Height = Tst_IMAGE_SAVED_MAX_HEIGHT;
|
||||
|
@ -6252,7 +6235,7 @@ static long Tst_GetQstFromForm (struct Tst_Question *Question,
|
|||
}
|
||||
|
||||
/* Get the numbers of correct answers */
|
||||
if (*AnswerType == Tst_ANS_UNIQUE_CHOICE)
|
||||
if (Answer->Type == Tst_ANS_UNIQUE_CHOICE)
|
||||
{
|
||||
NumCorrectAns = (unsigned) Par_GetParToUnsignedLong ("AnsUni",
|
||||
0,
|
||||
|
@ -6260,7 +6243,7 @@ static long Tst_GetQstFromForm (struct Tst_Question *Question,
|
|||
0);
|
||||
Answer->Options[NumCorrectAns].Correct = true;
|
||||
}
|
||||
else if (*AnswerType == Tst_ANS_MULTIPLE_CHOICE)
|
||||
else if (Answer->Type == Tst_ANS_MULTIPLE_CHOICE)
|
||||
{
|
||||
Par_GetParMultiToText ("AnsMulti",StrMultiAns,Tst_MAX_BYTES_ANSWERS_ONE_QST);
|
||||
Ptr = StrMultiAns;
|
||||
|
@ -6307,7 +6290,6 @@ static long Tst_GetQstFromForm (struct Tst_Question *Question,
|
|||
// Computes Answer->Integer and Answer->FloatingPoint[0..1]
|
||||
|
||||
bool Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (const struct Tst_Question *Question,
|
||||
Tst_AnswerType_t AnswerType,
|
||||
struct Tst_Answer *Answer)
|
||||
{
|
||||
extern const char *Txt_You_must_type_at_least_one_tag_for_the_question;
|
||||
|
@ -6343,7 +6325,7 @@ bool Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (const struct Tst_Question
|
|||
}
|
||||
|
||||
/***** Check answer *****/
|
||||
switch (AnswerType)
|
||||
switch (Answer->Type)
|
||||
{
|
||||
case Tst_ANS_INT:
|
||||
/* First option should be filled */
|
||||
|
@ -6491,7 +6473,6 @@ bool Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (const struct Tst_Question
|
|||
/*****************************************************************************/
|
||||
|
||||
bool Tst_CheckIfQuestionExistsInDB (const struct Tst_Question *Question,
|
||||
Tst_AnswerType_t AnswerType,
|
||||
const struct Tst_Answer *Answer)
|
||||
{
|
||||
extern const char *Tst_StrAnswerTypesDB[Tst_NUM_ANS_TYPES];
|
||||
|
@ -6514,7 +6495,7 @@ bool Tst_CheckIfQuestionExistsInDB (const struct Tst_Question *Question,
|
|||
"SELECT QstCod FROM tst_questions"
|
||||
" WHERE CrsCod=%ld AND AnsType='%s' AND Stem='%s'",
|
||||
Gbl.Hierarchy.Crs.CrsCod,
|
||||
Tst_StrAnswerTypesDB[AnswerType],
|
||||
Tst_StrAnswerTypesDB[Answer->Type],
|
||||
Question->Stem.Text);
|
||||
|
||||
if (NumQstsWithThisStem) // There are questions in database with the same stem that the one of this question
|
||||
|
@ -6538,7 +6519,7 @@ bool Tst_CheckIfQuestionExistsInDB (const struct Tst_Question *Question,
|
|||
" WHERE QstCod=%ld ORDER BY AnsInd",
|
||||
QstCod);
|
||||
|
||||
switch (AnswerType)
|
||||
switch (Answer->Type)
|
||||
{
|
||||
case Tst_ANS_INT:
|
||||
row = mysql_fetch_row (mysql_res_ans);
|
||||
|
@ -6600,7 +6581,6 @@ bool Tst_CheckIfQuestionExistsInDB (const struct Tst_Question *Question,
|
|||
|
||||
static void Tst_MoveMediaToDefinitiveDirectories (long QstCod,
|
||||
struct Tst_Question *Question,
|
||||
Tst_AnswerType_t AnswerType,
|
||||
struct Tst_Answer *Answer)
|
||||
{
|
||||
unsigned NumOpt;
|
||||
|
@ -6612,7 +6592,7 @@ static void Tst_MoveMediaToDefinitiveDirectories (long QstCod,
|
|||
Med_RemoveKeepOrStoreMedia (CurrentMedCodInDB,&Question->Media);
|
||||
|
||||
/****** Move media associated to answers *****/
|
||||
switch (AnswerType)
|
||||
switch (Answer->Type)
|
||||
{
|
||||
case Tst_ANS_UNIQUE_CHOICE:
|
||||
case Tst_ANS_MULTIPLE_CHOICE:
|
||||
|
@ -7019,11 +6999,10 @@ void Tst_PutParamQstCod (long QstCod)
|
|||
|
||||
long Tst_InsertOrUpdateQstTagsAnsIntoDB (long QstCod,
|
||||
const struct Tst_Question *Question,
|
||||
Tst_AnswerType_t AnswerType,
|
||||
struct Tst_Answer *Answer)
|
||||
{
|
||||
/***** Insert or update question in the table of questions *****/
|
||||
QstCod = Tst_InsertOrUpdateQstIntoDB (QstCod,Question,AnswerType);
|
||||
QstCod = Tst_InsertOrUpdateQstIntoDB (QstCod,Question,Answer->Type);
|
||||
if (QstCod > 0)
|
||||
{
|
||||
/***** Insert tags in the tags table *****/
|
||||
|
@ -7033,7 +7012,7 @@ long Tst_InsertOrUpdateQstTagsAnsIntoDB (long QstCod,
|
|||
Tst_RemoveUnusedTagsFromCrs (Gbl.Hierarchy.Crs.CrsCod);
|
||||
|
||||
/***** Insert answers in the answers table *****/
|
||||
Tst_InsertAnswersIntoDB (QstCod,AnswerType,Answer);
|
||||
Tst_InsertAnswersIntoDB (QstCod,Answer);
|
||||
}
|
||||
|
||||
return QstCod;
|
||||
|
@ -7149,14 +7128,13 @@ static void Tst_InsertTagsIntoDB (long QstCod)
|
|||
/*****************************************************************************/
|
||||
|
||||
static void Tst_InsertAnswersIntoDB (long QstCod,
|
||||
Tst_AnswerType_t AnswerType,
|
||||
struct Tst_Answer *Answer)
|
||||
{
|
||||
unsigned NumOpt;
|
||||
unsigned i;
|
||||
|
||||
/***** Insert answers in the answers table *****/
|
||||
switch (AnswerType)
|
||||
switch (Answer->Type)
|
||||
{
|
||||
case Tst_ANS_INT:
|
||||
DB_QueryINSERT ("can not create answer",
|
||||
|
|
34
swad_test.h
34
swad_test.h
|
@ -58,6 +58,19 @@
|
|||
/******************************* Public types ********************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#define Tst_NUM_ANS_TYPES 6
|
||||
#define Tst_MAX_BYTES_LIST_ANSWER_TYPES (Tst_NUM_ANS_TYPES * (Cns_MAX_DECIMAL_DIGITS_UINT + 1))
|
||||
typedef enum
|
||||
{
|
||||
Tst_ANS_INT = 0,
|
||||
Tst_ANS_FLOAT = 1,
|
||||
Tst_ANS_TRUE_FALSE = 2,
|
||||
Tst_ANS_UNIQUE_CHOICE = 3,
|
||||
Tst_ANS_MULTIPLE_CHOICE = 4,
|
||||
Tst_ANS_TEXT = 5,
|
||||
Tst_ANS_ALL = 6, // All/any type of answer
|
||||
} Tst_AnswerType_t;
|
||||
|
||||
struct Tst_Question
|
||||
{
|
||||
struct
|
||||
|
@ -71,6 +84,7 @@ struct Tst_Question
|
|||
|
||||
struct Tst_Answer
|
||||
{
|
||||
Tst_AnswerType_t Type;
|
||||
unsigned NumOptions;
|
||||
char TF;
|
||||
struct
|
||||
|
@ -110,19 +124,6 @@ struct Tst_Config
|
|||
unsigned Visibility; // One bit for each visibility item
|
||||
};
|
||||
|
||||
#define Tst_NUM_ANS_TYPES 6
|
||||
#define Tst_MAX_BYTES_LIST_ANSWER_TYPES (Tst_NUM_ANS_TYPES * (Cns_MAX_DECIMAL_DIGITS_UINT + 1))
|
||||
typedef enum
|
||||
{
|
||||
Tst_ANS_INT = 0,
|
||||
Tst_ANS_FLOAT = 1,
|
||||
Tst_ANS_TRUE_FALSE = 2,
|
||||
Tst_ANS_UNIQUE_CHOICE = 3,
|
||||
Tst_ANS_MULTIPLE_CHOICE = 4,
|
||||
Tst_ANS_TEXT = 5,
|
||||
Tst_ANS_ALL = 6, // All/any type of answer
|
||||
} Tst_AnswerType_t;
|
||||
|
||||
#define Tst_NUM_TYPES_ORDER_QST 5
|
||||
typedef enum
|
||||
{
|
||||
|
@ -187,8 +188,7 @@ void Tst_GetIndexesFromStr (const char StrIndexesOneQst[Tst_MAX_BYTES_INDEXES_ON
|
|||
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION]);
|
||||
void Tst_GetAnswersFromStr (const char StrAnswersOneQst[Tst_MAX_BYTES_ANSWERS_ONE_QST + 1],
|
||||
bool AnswersUsr[Tst_MAX_OPTIONS_PER_QUESTION]);
|
||||
void Tst_ComputeScoreQst (Tst_AnswerType_t AnswerType,
|
||||
const struct Tst_Answer *Answer,
|
||||
void Tst_ComputeScoreQst (const struct Tst_Answer *Answer,
|
||||
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION],
|
||||
bool AnswersUsr[Tst_MAX_OPTIONS_PER_QUESTION],
|
||||
double *ScoreThisQst,bool *AnswerIsNotBlank);
|
||||
|
@ -213,7 +213,6 @@ void Tst_ReceiveConfigTst (void);
|
|||
void Tst_ShowFormEditOneQst (void);
|
||||
|
||||
void Tst_QstConstructor (struct Tst_Question *Question,
|
||||
Tst_AnswerType_t *AnswerType,
|
||||
struct Tst_Answer *Answer);
|
||||
void Tst_QstDestructor (struct Tst_Question *Question,
|
||||
struct Tst_Answer *Answer);
|
||||
|
@ -223,11 +222,9 @@ int Tst_AllocateTextChoiceAnswer (struct Tst_Answer *Answer,unsigned NumOpt);
|
|||
Tst_AnswerType_t Tst_ConvertFromStrAnsTypDBToAnsTyp (const char *StrAnsTypeBD);
|
||||
void Tst_ReceiveQst (void);
|
||||
bool Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (const struct Tst_Question *Question,
|
||||
Tst_AnswerType_t AnswerType,
|
||||
struct Tst_Answer *Answer);
|
||||
|
||||
bool Tst_CheckIfQuestionExistsInDB (const struct Tst_Question *Question,
|
||||
Tst_AnswerType_t AnswerType,
|
||||
const struct Tst_Answer *Answer);
|
||||
|
||||
long Tst_GetIntAnsFromStr (char *Str);
|
||||
|
@ -246,7 +243,6 @@ void Tst_PutParamQstCod (long QstCod);
|
|||
|
||||
long Tst_InsertOrUpdateQstTagsAnsIntoDB (long QstCod,
|
||||
const struct Tst_Question *Question,
|
||||
Tst_AnswerType_t AnswerType,
|
||||
struct Tst_Answer *Answer);
|
||||
|
||||
void Tst_RemoveCrsTests (long CrsCod);
|
||||
|
|
|
@ -77,13 +77,11 @@ static void TsI_ReadQuestionsFromXMLFileAndStoreInDB (const char *FileNameXML);
|
|||
static void TsI_ImportQuestionsFromXMLBuffer (const char *XMLBuffer);
|
||||
static Tst_AnswerType_t TsI_ConvertFromStrAnsTypXMLToAnsTyp (const char *StrAnsTypeXML);
|
||||
static void TsI_GetAnswerFromXML (struct XMLElement *AnswerElem,
|
||||
Tst_AnswerType_t AnswerType,
|
||||
struct Tst_Answer *Answer);
|
||||
static void TsI_WriteHeadingListImportedQst (void);
|
||||
static void TsI_WriteRowImportedQst (struct XMLElement *StemElem,
|
||||
struct XMLElement *FeedbackElem,
|
||||
const struct Tst_Question *Question,
|
||||
Tst_AnswerType_t AnswerType,
|
||||
const struct Tst_Answer *Answer,
|
||||
bool QuestionExists);
|
||||
|
||||
|
@ -540,7 +538,6 @@ static void TsI_ImportQuestionsFromXMLBuffer (const char *XMLBuffer)
|
|||
bool AnswerTypeFound;
|
||||
bool QuestionExists;
|
||||
struct Tst_Question Question;
|
||||
Tst_AnswerType_t AnswerType;
|
||||
struct Tst_Answer Answer;
|
||||
char Stem[Cns_MAX_BYTES_TEXT + 1];
|
||||
char Feedback[Cns_MAX_BYTES_TEXT + 1];
|
||||
|
@ -585,7 +582,7 @@ static void TsI_ImportQuestionsFromXMLBuffer (const char *XMLBuffer)
|
|||
if (!strcmp (QuestionElem->TagName,"question"))
|
||||
{
|
||||
/***** Create test question *****/
|
||||
Tst_QstConstructor (&Question,&AnswerType,&Answer);
|
||||
Tst_QstConstructor (&Question,&Answer);
|
||||
|
||||
/* Get answer type (in mandatory attribute "type") */
|
||||
AnswerTypeFound = false;
|
||||
|
@ -594,7 +591,7 @@ static void TsI_ImportQuestionsFromXMLBuffer (const char *XMLBuffer)
|
|||
Attribute = Attribute->Next)
|
||||
if (!strcmp (Attribute->AttributeName,"type"))
|
||||
{
|
||||
AnswerType = TsI_ConvertFromStrAnsTypXMLToAnsTyp (Attribute->Content);
|
||||
Answer.Type = TsI_ConvertFromStrAnsTypXMLToAnsTyp (Attribute->Content);
|
||||
AnswerTypeFound = true;
|
||||
break; // Only first attribute "type"
|
||||
}
|
||||
|
@ -670,8 +667,8 @@ static void TsI_ImportQuestionsFromXMLBuffer (const char *XMLBuffer)
|
|||
AnswerElem = AnswerElem->NextBrother)
|
||||
if (!strcmp (AnswerElem->TagName,"answer"))
|
||||
{
|
||||
if (AnswerType == Tst_ANS_UNIQUE_CHOICE ||
|
||||
AnswerType == Tst_ANS_MULTIPLE_CHOICE)
|
||||
if (Answer.Type == Tst_ANS_UNIQUE_CHOICE ||
|
||||
Answer.Type == Tst_ANS_MULTIPLE_CHOICE)
|
||||
/* Get whether shuffle answers (in attribute "shuffle") */
|
||||
for (Attribute = AnswerElem->FirstAttribute;
|
||||
Attribute != NULL;
|
||||
|
@ -685,22 +682,22 @@ static void TsI_ImportQuestionsFromXMLBuffer (const char *XMLBuffer)
|
|||
}
|
||||
|
||||
/* Get answer (mandatory) */
|
||||
TsI_GetAnswerFromXML (AnswerElem,AnswerType,&Answer);
|
||||
TsI_GetAnswerFromXML (AnswerElem,&Answer);
|
||||
|
||||
/* Make sure that tags, text and answer are not empty */
|
||||
if (Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (&Question,AnswerType,&Answer))
|
||||
if (Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (&Question,&Answer))
|
||||
{
|
||||
/* Check if question already exists in database */
|
||||
QuestionExists = Tst_CheckIfQuestionExistsInDB (&Question,AnswerType,&Answer);
|
||||
QuestionExists = Tst_CheckIfQuestionExistsInDB (&Question,&Answer);
|
||||
|
||||
/* Write row with this imported question */
|
||||
TsI_WriteRowImportedQst (StemElem,FeedbackElem,
|
||||
&Question,AnswerType,&Answer,
|
||||
&Question,&Answer,
|
||||
QuestionExists);
|
||||
|
||||
/***** If a new question ==> insert question, tags and answer in the database *****/
|
||||
if (!QuestionExists)
|
||||
if (Tst_InsertOrUpdateQstTagsAnsIntoDB (-1L,&Question,AnswerType,&Answer) <= 0)
|
||||
if (Tst_InsertOrUpdateQstTagsAnsIntoDB (-1L,&Question,&Answer) <= 0)
|
||||
Lay_ShowErrorAndExit ("Can not create question.");
|
||||
}
|
||||
}
|
||||
|
@ -751,7 +748,6 @@ static Tst_AnswerType_t TsI_ConvertFromStrAnsTypXMLToAnsTyp (const char *StrAnsT
|
|||
// Answer is mandatory
|
||||
|
||||
static void TsI_GetAnswerFromXML (struct XMLElement *AnswerElem,
|
||||
Tst_AnswerType_t AnswerType,
|
||||
struct Tst_Answer *Answer)
|
||||
{
|
||||
struct XMLElement *OptionElem;
|
||||
|
@ -761,7 +757,7 @@ static void TsI_GetAnswerFromXML (struct XMLElement *AnswerElem,
|
|||
struct XMLAttribute *Attribute;
|
||||
unsigned NumOpt;
|
||||
|
||||
switch (AnswerType)
|
||||
switch (Answer->Type)
|
||||
{
|
||||
case Tst_ANS_INT:
|
||||
if (!Tst_AllocateTextChoiceAnswer (Answer,0))
|
||||
|
@ -869,7 +865,7 @@ static void TsI_GetAnswerFromXML (struct XMLElement *AnswerElem,
|
|||
break; // Only first element "feedback"
|
||||
}
|
||||
|
||||
if (AnswerType == Tst_ANS_TEXT)
|
||||
if (Answer->Type == Tst_ANS_TEXT)
|
||||
Answer->Options[NumOpt].Correct = true;
|
||||
else
|
||||
/* Check if option is correct or wrong */
|
||||
|
@ -921,7 +917,6 @@ static void TsI_WriteHeadingListImportedQst (void)
|
|||
static void TsI_WriteRowImportedQst (struct XMLElement *StemElem,
|
||||
struct XMLElement *FeedbackElem,
|
||||
const struct Tst_Question *Question,
|
||||
Tst_AnswerType_t AnswerType,
|
||||
const struct Tst_Answer *Answer,
|
||||
bool QuestionExists)
|
||||
{
|
||||
|
@ -1002,13 +997,13 @@ static void TsI_WriteRowImportedQst (struct XMLElement *StemElem,
|
|||
|
||||
/***** Write the question type *****/
|
||||
HTM_TD_Begin ("class=\"%s CT COLOR%u\"",ClassData,Gbl.RowEvenOdd);
|
||||
HTM_TxtF ("%s ",Txt_TST_STR_ANSWER_TYPES[AnswerType]);
|
||||
HTM_TxtF ("%s ",Txt_TST_STR_ANSWER_TYPES[Answer->Type]);
|
||||
HTM_TD_End ();
|
||||
|
||||
/***** Write if shuffle is enabled *****/
|
||||
HTM_TD_Begin ("class=\"CT COLOR%u\"",Gbl.RowEvenOdd);
|
||||
if (AnswerType == Tst_ANS_UNIQUE_CHOICE ||
|
||||
AnswerType == Tst_ANS_MULTIPLE_CHOICE)
|
||||
if (Answer->Type == Tst_ANS_UNIQUE_CHOICE ||
|
||||
Answer->Type == Tst_ANS_MULTIPLE_CHOICE)
|
||||
/* Put an icon that indicates whether shuffle is enabled or not */
|
||||
if (Question->Shuffle)
|
||||
Ico_PutIcon ("check.svg",Txt_TST_Answer_given_by_the_teachers,
|
||||
|
@ -1021,7 +1016,7 @@ static void TsI_WriteRowImportedQst (struct XMLElement *StemElem,
|
|||
Tst_WriteQstStem (Stem,ClassStem,
|
||||
true); // Visible
|
||||
Tst_WriteQstFeedback (Feedback,"TEST_EDI_LIGHT");
|
||||
switch (AnswerType)
|
||||
switch (Answer->Type)
|
||||
{
|
||||
case Tst_ANS_INT:
|
||||
HTM_SPAN_Begin ("class=\"%s\"",ClassStem);
|
||||
|
|
Loading…
Reference in New Issue
Block a user