mirror of https://github.com/acanas/swad-core.git
Version19.150
This commit is contained in:
parent
b0e6cd080f
commit
919ab2eeeb
|
@ -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.150: Mar 19, 2020 Code refactoring in tests. (283031 lines)
|
||||
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)
|
||||
|
|
|
@ -1875,7 +1875,6 @@ static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts,
|
|||
MYSQL_ROW row;
|
||||
long QstCod;
|
||||
struct Tst_Question Question;
|
||||
struct Tst_Answer Answer;
|
||||
unsigned QstInd;
|
||||
unsigned MaxQstInd;
|
||||
char StrQstInd[Cns_MAX_DECIMAL_DIGITS_UINT + 1];
|
||||
|
@ -1909,7 +1908,7 @@ static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts,
|
|||
row[1] QstCod
|
||||
*/
|
||||
/***** Create test question *****/
|
||||
Tst_QstConstructor (&Question,&Answer);
|
||||
Tst_QstConstructor (&Question);
|
||||
|
||||
/* Get question index (row[0]) */
|
||||
QstInd = Str_ConvertStrToUnsigned (row[0]);
|
||||
|
@ -1978,7 +1977,7 @@ static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts,
|
|||
HTM_TR_End ();
|
||||
|
||||
/***** Destroy test question *****/
|
||||
Tst_QstDestructor (&Question,&Answer);
|
||||
Tst_QstDestructor (&Question);
|
||||
}
|
||||
|
||||
/***** End table *****/
|
||||
|
|
14
swad_match.c
14
swad_match.c
|
@ -3791,14 +3791,16 @@ static void Mch_RemoveMyAnswerToMatchQuestion (const struct Match *Match)
|
|||
static double Mch_ComputeScore (unsigned NumQsts)
|
||||
{
|
||||
unsigned NumQst;
|
||||
struct Tst_Answer Answer;
|
||||
struct Tst_Question Question;
|
||||
double ScoreThisQst;
|
||||
bool AnswerIsNotBlank;
|
||||
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION]; // Indexes of all answers of this question
|
||||
bool AnswersUsr[Tst_MAX_OPTIONS_PER_QUESTION];
|
||||
double TotalScore = 0.0;
|
||||
|
||||
Answer.Type = Tst_ANS_UNIQUE_CHOICE;
|
||||
/***** Create test question *****/
|
||||
Tst_QstConstructor (&Question);
|
||||
Question.Answer.Type = Tst_ANS_UNIQUE_CHOICE;
|
||||
|
||||
for (NumQst = 0;
|
||||
NumQst < NumQsts;
|
||||
|
@ -3811,16 +3813,18 @@ static double Mch_ComputeScore (unsigned NumQsts)
|
|||
Tst_GetAnswersFromStr (Gbl.Test.StrAnswersOneQst[NumQst],AnswersUsr);
|
||||
|
||||
/***** Get correct answers of test question from database *****/
|
||||
Tst_GetCorrectAnswersFromDB (Gbl.Test.QstCodes[NumQst],&Answer);
|
||||
Tst_GetCorrectAnswersFromDB (Gbl.Test.QstCodes[NumQst],&Question);
|
||||
|
||||
/***** Compute the total score of this question *****/
|
||||
Tst_ComputeScoreQst (&Answer,
|
||||
Indexes,AnswersUsr,&ScoreThisQst,&AnswerIsNotBlank);
|
||||
Tst_ComputeScoreQst (&Question,Indexes,AnswersUsr,&ScoreThisQst,&AnswerIsNotBlank);
|
||||
|
||||
/***** Compute total score *****/
|
||||
TotalScore += ScoreThisQst;
|
||||
}
|
||||
|
||||
/***** Destroy test question *****/
|
||||
Tst_QstDestructor (&Question);
|
||||
|
||||
return TotalScore;
|
||||
}
|
||||
|
||||
|
|
667
swad_test.c
667
swad_test.c
File diff suppressed because it is too large
Load Diff
29
swad_test.h
29
swad_test.h
|
@ -80,9 +80,7 @@ struct Tst_Question
|
|||
} Stem, Feedback;
|
||||
struct Media Media;
|
||||
bool Shuffle;
|
||||
};
|
||||
|
||||
struct Tst_Answer
|
||||
struct
|
||||
{
|
||||
Tst_AnswerType_t Type;
|
||||
unsigned NumOptions;
|
||||
|
@ -96,6 +94,7 @@ struct Tst_Answer
|
|||
} Options[Tst_MAX_OPTIONS_PER_QUESTION];
|
||||
long Integer;
|
||||
double FloatingPoint[2];
|
||||
} Answer;
|
||||
};
|
||||
|
||||
#define Tst_NUM_OPTIONS_PLUGGABLE 3
|
||||
|
@ -179,22 +178,21 @@ bool Tst_GetOneQuestionByCod (long QstCod,MYSQL_RES **mysql_res);
|
|||
void Tst_WriteParamEditQst (void);
|
||||
unsigned Tst_GetNumAnswersQst (long QstCod);
|
||||
unsigned Tst_GetAnswersQst (long QstCod,MYSQL_RES **mysql_res,bool Shuffle);
|
||||
void Tst_GetCorrectAnswersFromDB (long QstCod,struct Tst_Answer *Answer);
|
||||
void Tst_GetCorrectAnswersFromDB (long QstCod,struct Tst_Question *Question);
|
||||
void Tst_WriteAnswersEdit (long QstCod,Tst_AnswerType_t AnswerType);
|
||||
bool Tst_CheckIfQuestionIsValidForGame (long QstCod);
|
||||
void Tst_WriteAnsTF (char AnsTF);
|
||||
void Tst_GetChoiceAns (MYSQL_RES *mysql_res,struct Tst_Answer *Answer);
|
||||
void Tst_GetIndexesFromStr (const char StrIndexesOneQst[Tst_MAX_BYTES_INDEXES_ONE_QST + 1], // 0 1 2 3, 3 0 2 1, etc.
|
||||
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION]);
|
||||
void Tst_GetAnswersFromStr (const char StrAnswersOneQst[Tst_MAX_BYTES_ANSWERS_ONE_QST + 1],
|
||||
bool AnswersUsr[Tst_MAX_OPTIONS_PER_QUESTION]);
|
||||
void Tst_ComputeScoreQst (const struct Tst_Answer *Answer,
|
||||
void Tst_ComputeScoreQst (const struct Tst_Question *Question,
|
||||
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION],
|
||||
bool AnswersUsr[Tst_MAX_OPTIONS_PER_QUESTION],
|
||||
double *ScoreThisQst,bool *AnswerIsNotBlank);
|
||||
void Tst_WriteChoiceAnsViewMatch (long MchCod,unsigned QstInd,long QstCod,
|
||||
unsigned NumCols,const char *Class,bool ShowResult);
|
||||
void Tst_CheckIfNumberOfAnswersIsOne (const struct Tst_Answer *Answer);
|
||||
void Tst_CheckIfNumberOfAnswersIsOne (const struct Tst_Question *Question);
|
||||
|
||||
unsigned long Tst_GetTagsQst (long QstCod,MYSQL_RES **mysql_res);
|
||||
void Tst_GetAndWriteTagsQst (long QstCod);
|
||||
|
@ -212,20 +210,16 @@ bool Tst_CheckIfCourseHaveTestsAndPluggableIsUnknown (void);
|
|||
void Tst_ReceiveConfigTst (void);
|
||||
void Tst_ShowFormEditOneQst (void);
|
||||
|
||||
void Tst_QstConstructor (struct Tst_Question *Question,
|
||||
struct Tst_Answer *Answer);
|
||||
void Tst_QstDestructor (struct Tst_Question *Question,
|
||||
struct Tst_Answer *Answer);
|
||||
void Tst_QstConstructor (struct Tst_Question *Question);
|
||||
void Tst_QstDestructor (struct Tst_Question *Question);
|
||||
|
||||
int Tst_AllocateTextChoiceAnswer (struct Tst_Answer *Answer,unsigned NumOpt);
|
||||
int Tst_AllocateTextChoiceAnswer (struct Tst_Question *Question,unsigned NumOpt);
|
||||
|
||||
Tst_AnswerType_t Tst_ConvertFromStrAnsTypDBToAnsTyp (const char *StrAnsTypeBD);
|
||||
void Tst_ReceiveQst (void);
|
||||
bool Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (const struct Tst_Question *Question,
|
||||
struct Tst_Answer *Answer);
|
||||
bool Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (struct Tst_Question *Question);
|
||||
|
||||
bool Tst_CheckIfQuestionExistsInDB (const struct Tst_Question *Question,
|
||||
const struct Tst_Answer *Answer);
|
||||
bool Tst_CheckIfQuestionExistsInDB (const struct Tst_Question *Question);
|
||||
|
||||
long Tst_GetIntAnsFromStr (char *Str);
|
||||
|
||||
|
@ -242,8 +236,7 @@ void Tst_PutParamGblQstCod (void);
|
|||
void Tst_PutParamQstCod (long QstCod);
|
||||
|
||||
long Tst_InsertOrUpdateQstTagsAnsIntoDB (long QstCod,
|
||||
const struct Tst_Question *Question,
|
||||
struct Tst_Answer *Answer);
|
||||
struct Tst_Question *Question);
|
||||
|
||||
void Tst_RemoveCrsTests (long CrsCod);
|
||||
|
||||
|
|
|
@ -77,12 +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,
|
||||
struct Tst_Answer *Answer);
|
||||
struct Tst_Question *Question);
|
||||
static void TsI_WriteHeadingListImportedQst (void);
|
||||
static void TsI_WriteRowImportedQst (struct XMLElement *StemElem,
|
||||
struct XMLElement *FeedbackElem,
|
||||
const struct Tst_Question *Question,
|
||||
const struct Tst_Answer *Answer,
|
||||
bool QuestionExists);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -337,15 +336,17 @@ static void TsI_WriteAnswersOfAQstXML (long QstCod,Tst_AnswerType_t AnswerType,
|
|||
FILE *FileXML)
|
||||
{
|
||||
extern const char *Txt_NEW_LINE;
|
||||
struct Tst_Answer Answer;
|
||||
struct Tst_Question Question;
|
||||
unsigned NumOpt;
|
||||
unsigned i;
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
double FloatNum[2];
|
||||
|
||||
Question.Answer.Type = AnswerType;
|
||||
|
||||
/***** Get answers *****/
|
||||
Answer.NumOptions = Tst_GetAnswersQst (QstCod,&mysql_res,false); // Result: AnsInd,Answer,Correct
|
||||
Question.Answer.NumOptions = Tst_GetAnswersQst (QstCod,&mysql_res,false); // Result: AnsInd,Answer,Correct
|
||||
/*
|
||||
row[0] AnsInd
|
||||
row[1] Answer
|
||||
|
@ -355,16 +356,16 @@ static void TsI_WriteAnswersOfAQstXML (long QstCod,Tst_AnswerType_t AnswerType,
|
|||
*/
|
||||
|
||||
/***** Write answers *****/
|
||||
switch (AnswerType)
|
||||
switch (Question.Answer.Type)
|
||||
{
|
||||
case Tst_ANS_INT:
|
||||
Tst_CheckIfNumberOfAnswersIsOne (&Answer);
|
||||
Tst_CheckIfNumberOfAnswersIsOne (&Question);
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
fprintf (FileXML,"%ld",
|
||||
Tst_GetIntAnsFromStr (row[1]));
|
||||
break;
|
||||
case Tst_ANS_FLOAT:
|
||||
if (Answer.NumOptions != 2)
|
||||
if (Question.Answer.NumOptions != 2)
|
||||
Lay_ShowErrorAndExit ("Wrong float range.");
|
||||
|
||||
for (i = 0;
|
||||
|
@ -382,7 +383,7 @@ static void TsI_WriteAnswersOfAQstXML (long QstCod,Tst_AnswerType_t AnswerType,
|
|||
FloatNum[1],Txt_NEW_LINE);
|
||||
break;
|
||||
case Tst_ANS_TRUE_FALSE:
|
||||
Tst_CheckIfNumberOfAnswersIsOne (&Answer);
|
||||
Tst_CheckIfNumberOfAnswersIsOne (&Question);
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
fprintf (FileXML,"%s",
|
||||
row[1][0] == 'T' ? "true" :
|
||||
|
@ -393,7 +394,7 @@ static void TsI_WriteAnswersOfAQstXML (long QstCod,Tst_AnswerType_t AnswerType,
|
|||
case Tst_ANS_TEXT:
|
||||
fprintf (FileXML,"%s",Txt_NEW_LINE);
|
||||
for (NumOpt = 0;
|
||||
NumOpt < Answer.NumOptions;
|
||||
NumOpt < Question.Answer.NumOptions;
|
||||
NumOpt++)
|
||||
{
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
|
@ -402,7 +403,7 @@ static void TsI_WriteAnswersOfAQstXML (long QstCod,Tst_AnswerType_t AnswerType,
|
|||
fprintf (FileXML,"<option");
|
||||
|
||||
/* Write whether the answer is correct or not (row[4]) */
|
||||
if (AnswerType != Tst_ANS_TEXT)
|
||||
if (Question.Answer.Type != Tst_ANS_TEXT)
|
||||
fprintf (FileXML," correct=\"%s\"",
|
||||
(row[4][0] == 'Y') ? "yes" :
|
||||
"no");
|
||||
|
@ -538,7 +539,6 @@ static void TsI_ImportQuestionsFromXMLBuffer (const char *XMLBuffer)
|
|||
bool AnswerTypeFound;
|
||||
bool QuestionExists;
|
||||
struct Tst_Question Question;
|
||||
struct Tst_Answer Answer;
|
||||
char Stem[Cns_MAX_BYTES_TEXT + 1];
|
||||
char Feedback[Cns_MAX_BYTES_TEXT + 1];
|
||||
|
||||
|
@ -582,7 +582,7 @@ static void TsI_ImportQuestionsFromXMLBuffer (const char *XMLBuffer)
|
|||
if (!strcmp (QuestionElem->TagName,"question"))
|
||||
{
|
||||
/***** Create test question *****/
|
||||
Tst_QstConstructor (&Question,&Answer);
|
||||
Tst_QstConstructor (&Question);
|
||||
|
||||
/* Get answer type (in mandatory attribute "type") */
|
||||
AnswerTypeFound = false;
|
||||
|
@ -591,7 +591,7 @@ static void TsI_ImportQuestionsFromXMLBuffer (const char *XMLBuffer)
|
|||
Attribute = Attribute->Next)
|
||||
if (!strcmp (Attribute->AttributeName,"type"))
|
||||
{
|
||||
Answer.Type = TsI_ConvertFromStrAnsTypXMLToAnsTyp (Attribute->Content);
|
||||
Question.Answer.Type = TsI_ConvertFromStrAnsTypXMLToAnsTyp (Attribute->Content);
|
||||
AnswerTypeFound = true;
|
||||
break; // Only first attribute "type"
|
||||
}
|
||||
|
@ -667,8 +667,8 @@ static void TsI_ImportQuestionsFromXMLBuffer (const char *XMLBuffer)
|
|||
AnswerElem = AnswerElem->NextBrother)
|
||||
if (!strcmp (AnswerElem->TagName,"answer"))
|
||||
{
|
||||
if (Answer.Type == Tst_ANS_UNIQUE_CHOICE ||
|
||||
Answer.Type == Tst_ANS_MULTIPLE_CHOICE)
|
||||
if (Question.Answer.Type == Tst_ANS_UNIQUE_CHOICE ||
|
||||
Question.Answer.Type == Tst_ANS_MULTIPLE_CHOICE)
|
||||
/* Get whether shuffle answers (in attribute "shuffle") */
|
||||
for (Attribute = AnswerElem->FirstAttribute;
|
||||
Attribute != NULL;
|
||||
|
@ -682,22 +682,21 @@ static void TsI_ImportQuestionsFromXMLBuffer (const char *XMLBuffer)
|
|||
}
|
||||
|
||||
/* Get answer (mandatory) */
|
||||
TsI_GetAnswerFromXML (AnswerElem,&Answer);
|
||||
TsI_GetAnswerFromXML (AnswerElem,&Question);
|
||||
|
||||
/* Make sure that tags, text and answer are not empty */
|
||||
if (Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (&Question,&Answer))
|
||||
if (Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (&Question))
|
||||
{
|
||||
/* Check if question already exists in database */
|
||||
QuestionExists = Tst_CheckIfQuestionExistsInDB (&Question,&Answer);
|
||||
QuestionExists = Tst_CheckIfQuestionExistsInDB (&Question);
|
||||
|
||||
/* Write row with this imported question */
|
||||
TsI_WriteRowImportedQst (StemElem,FeedbackElem,
|
||||
&Question,&Answer,
|
||||
QuestionExists);
|
||||
&Question,QuestionExists);
|
||||
|
||||
/***** If a new question ==> insert question, tags and answer in the database *****/
|
||||
if (!QuestionExists)
|
||||
if (Tst_InsertOrUpdateQstTagsAnsIntoDB (-1L,&Question,&Answer) <= 0)
|
||||
if (Tst_InsertOrUpdateQstTagsAnsIntoDB (-1L,&Question) <= 0)
|
||||
Lay_ShowErrorAndExit ("Can not create question.");
|
||||
}
|
||||
}
|
||||
|
@ -705,7 +704,7 @@ static void TsI_ImportQuestionsFromXMLBuffer (const char *XMLBuffer)
|
|||
Lay_ShowErrorAndExit ("Wrong type of answer.");
|
||||
|
||||
/***** Destroy test question *****/
|
||||
Tst_QstDestructor (&Question,&Answer);
|
||||
Tst_QstDestructor (&Question);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -748,7 +747,7 @@ static Tst_AnswerType_t TsI_ConvertFromStrAnsTypXMLToAnsTyp (const char *StrAnsT
|
|||
// Answer is mandatory
|
||||
|
||||
static void TsI_GetAnswerFromXML (struct XMLElement *AnswerElem,
|
||||
struct Tst_Answer *Answer)
|
||||
struct Tst_Question *Question)
|
||||
{
|
||||
struct XMLElement *OptionElem;
|
||||
struct XMLElement *TextElem;
|
||||
|
@ -757,22 +756,22 @@ static void TsI_GetAnswerFromXML (struct XMLElement *AnswerElem,
|
|||
struct XMLAttribute *Attribute;
|
||||
unsigned NumOpt;
|
||||
|
||||
switch (Answer->Type)
|
||||
switch (Question->Answer.Type)
|
||||
{
|
||||
case Tst_ANS_INT:
|
||||
if (!Tst_AllocateTextChoiceAnswer (Answer,0))
|
||||
if (!Tst_AllocateTextChoiceAnswer (Question,0))
|
||||
/* Abort on error */
|
||||
Ale_ShowAlertsAndExit ();
|
||||
|
||||
if (AnswerElem->Content)
|
||||
Str_Copy (Answer->Options[0].Text,AnswerElem->Content,
|
||||
Str_Copy (Question->Answer.Options[0].Text,AnswerElem->Content,
|
||||
Tst_MAX_BYTES_ANSWER_OR_FEEDBACK);
|
||||
break;
|
||||
case Tst_ANS_FLOAT:
|
||||
if (!Tst_AllocateTextChoiceAnswer (Answer,0))
|
||||
if (!Tst_AllocateTextChoiceAnswer (Question,0))
|
||||
/* Abort on error */
|
||||
Ale_ShowAlertsAndExit ();
|
||||
if (!Tst_AllocateTextChoiceAnswer (Answer,1))
|
||||
if (!Tst_AllocateTextChoiceAnswer (Question,1))
|
||||
/* Abort on error */
|
||||
Ale_ShowAlertsAndExit ();
|
||||
|
||||
|
@ -782,7 +781,7 @@ static void TsI_GetAnswerFromXML (struct XMLElement *AnswerElem,
|
|||
if (!strcmp (LowerUpperElem->TagName,"lower"))
|
||||
{
|
||||
if (LowerUpperElem->Content)
|
||||
Str_Copy (Answer->Options[0].Text,
|
||||
Str_Copy (Question->Answer.Options[0].Text,
|
||||
LowerUpperElem->Content,
|
||||
Tst_MAX_BYTES_ANSWER_OR_FEEDBACK);
|
||||
break; // Only first element "lower"
|
||||
|
@ -793,7 +792,7 @@ static void TsI_GetAnswerFromXML (struct XMLElement *AnswerElem,
|
|||
if (!strcmp (LowerUpperElem->TagName,"upper"))
|
||||
{
|
||||
if (LowerUpperElem->Content)
|
||||
Str_Copy (Answer->Options[1].Text,
|
||||
Str_Copy (Question->Answer.Options[1].Text,
|
||||
LowerUpperElem->Content,
|
||||
Tst_MAX_BYTES_ANSWER_OR_FEEDBACK);
|
||||
break; // Only first element "upper"
|
||||
|
@ -802,19 +801,19 @@ static void TsI_GetAnswerFromXML (struct XMLElement *AnswerElem,
|
|||
case Tst_ANS_TRUE_FALSE:
|
||||
// Comparisons must be case insensitive, because users can edit XML
|
||||
if (!AnswerElem->Content)
|
||||
Answer->TF = ' ';
|
||||
Question->Answer.TF = ' ';
|
||||
else if (!strcasecmp (AnswerElem->Content,"true") ||
|
||||
!strcasecmp (AnswerElem->Content,"T") ||
|
||||
!strcasecmp (AnswerElem->Content,"yes") ||
|
||||
!strcasecmp (AnswerElem->Content,"Y"))
|
||||
Answer->TF = 'T';
|
||||
Question->Answer.TF = 'T';
|
||||
else if (!strcasecmp (AnswerElem->Content,"false") ||
|
||||
!strcasecmp (AnswerElem->Content,"F") ||
|
||||
!strcasecmp (AnswerElem->Content,"no") ||
|
||||
!strcasecmp (AnswerElem->Content,"N"))
|
||||
Answer->TF = 'F';
|
||||
Question->Answer.TF = 'F';
|
||||
else
|
||||
Answer->TF = ' ';
|
||||
Question->Answer.TF = ' ';
|
||||
break;
|
||||
case Tst_ANS_UNIQUE_CHOICE:
|
||||
case Tst_ANS_MULTIPLE_CHOICE:
|
||||
|
@ -825,7 +824,7 @@ static void TsI_GetAnswerFromXML (struct XMLElement *AnswerElem,
|
|||
OptionElem = OptionElem->NextBrother, NumOpt++)
|
||||
if (!strcmp (OptionElem->TagName,"option"))
|
||||
{
|
||||
if (!Tst_AllocateTextChoiceAnswer (Answer,NumOpt))
|
||||
if (!Tst_AllocateTextChoiceAnswer (Question,NumOpt))
|
||||
/* Abort on error */
|
||||
Ale_ShowAlertsAndExit ();
|
||||
|
||||
|
@ -836,13 +835,14 @@ static void TsI_GetAnswerFromXML (struct XMLElement *AnswerElem,
|
|||
{
|
||||
if (TextElem->Content)
|
||||
{
|
||||
Str_Copy (Answer->Options[NumOpt].Text,
|
||||
Str_Copy (Question->Answer.Options[NumOpt].Text,
|
||||
TextElem->Content,
|
||||
Tst_MAX_BYTES_ANSWER_OR_FEEDBACK);
|
||||
|
||||
/* Convert answer from text to HTML (in database answer text is stored in HTML) */
|
||||
Str_ChangeFormat (Str_FROM_TEXT,Str_TO_HTML,
|
||||
Answer->Options[NumOpt].Text,Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,true);
|
||||
Question->Answer.Options[NumOpt].Text,
|
||||
Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,true);
|
||||
}
|
||||
break; // Only first element "text"
|
||||
}
|
||||
|
@ -854,19 +854,20 @@ static void TsI_GetAnswerFromXML (struct XMLElement *AnswerElem,
|
|||
{
|
||||
if (FeedbackElem->Content)
|
||||
{
|
||||
Str_Copy (Answer->Options[NumOpt].Feedback,
|
||||
Str_Copy (Question->Answer.Options[NumOpt].Feedback,
|
||||
FeedbackElem->Content,
|
||||
Tst_MAX_BYTES_ANSWER_OR_FEEDBACK);
|
||||
|
||||
/* Convert feedback from text to HTML (in database answer feedback is stored in HTML) */
|
||||
Str_ChangeFormat (Str_FROM_TEXT,Str_TO_HTML,
|
||||
Answer->Options[NumOpt].Feedback,Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,true);
|
||||
Question->Answer.Options[NumOpt].Feedback,
|
||||
Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,true);
|
||||
}
|
||||
break; // Only first element "feedback"
|
||||
}
|
||||
|
||||
if (Answer->Type == Tst_ANS_TEXT)
|
||||
Answer->Options[NumOpt].Correct = true;
|
||||
if (Question->Answer.Type == Tst_ANS_TEXT)
|
||||
Question->Answer.Options[NumOpt].Correct = true;
|
||||
else
|
||||
/* Check if option is correct or wrong */
|
||||
for (Attribute = OptionElem->FirstAttribute;
|
||||
|
@ -874,7 +875,7 @@ static void TsI_GetAnswerFromXML (struct XMLElement *AnswerElem,
|
|||
Attribute = Attribute->Next)
|
||||
if (!strcmp (Attribute->AttributeName,"correct"))
|
||||
{
|
||||
Answer->Options[NumOpt].Correct = XML_GetAttributteYesNoFromXMLTree (Attribute);
|
||||
Question->Answer.Options[NumOpt].Correct = XML_GetAttributteYesNoFromXMLTree (Attribute);
|
||||
break; // Only first attribute "correct"
|
||||
}
|
||||
}
|
||||
|
@ -917,7 +918,6 @@ static void TsI_WriteHeadingListImportedQst (void)
|
|||
static void TsI_WriteRowImportedQst (struct XMLElement *StemElem,
|
||||
struct XMLElement *FeedbackElem,
|
||||
const struct Tst_Question *Question,
|
||||
const struct Tst_Answer *Answer,
|
||||
bool QuestionExists)
|
||||
{
|
||||
extern const char *Txt_Existing_question;
|
||||
|
@ -997,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[Answer->Type]);
|
||||
HTM_TxtF ("%s ",Txt_TST_STR_ANSWER_TYPES[Question->Answer.Type]);
|
||||
HTM_TD_End ();
|
||||
|
||||
/***** Write if shuffle is enabled *****/
|
||||
HTM_TD_Begin ("class=\"CT COLOR%u\"",Gbl.RowEvenOdd);
|
||||
if (Answer->Type == Tst_ANS_UNIQUE_CHOICE ||
|
||||
Answer->Type == Tst_ANS_MULTIPLE_CHOICE)
|
||||
if (Question->Answer.Type == Tst_ANS_UNIQUE_CHOICE ||
|
||||
Question->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,
|
||||
|
@ -1016,26 +1016,26 @@ static void TsI_WriteRowImportedQst (struct XMLElement *StemElem,
|
|||
Tst_WriteQstStem (Stem,ClassStem,
|
||||
true); // Visible
|
||||
Tst_WriteQstFeedback (Feedback,"TEST_EDI_LIGHT");
|
||||
switch (Answer->Type)
|
||||
switch (Question->Answer.Type)
|
||||
{
|
||||
case Tst_ANS_INT:
|
||||
HTM_SPAN_Begin ("class=\"%s\"",ClassStem);
|
||||
HTM_TxtF ("(%ld)",Answer->Integer);
|
||||
HTM_TxtF ("(%ld)",Question->Answer.Integer);
|
||||
HTM_SPAN_End ();
|
||||
break;
|
||||
case Tst_ANS_FLOAT:
|
||||
HTM_SPAN_Begin ("class=\"%s\"",ClassStem);
|
||||
HTM_Txt ("([");
|
||||
HTM_Double (Answer->FloatingPoint[0]);
|
||||
HTM_Double (Question->Answer.FloatingPoint[0]);
|
||||
HTM_Txt ("; ");
|
||||
HTM_Double (Answer->FloatingPoint[1]);
|
||||
HTM_Double (Question->Answer.FloatingPoint[1]);
|
||||
HTM_Txt ("])");
|
||||
HTM_SPAN_End ();
|
||||
break;
|
||||
case Tst_ANS_TRUE_FALSE:
|
||||
HTM_SPAN_Begin ("class=\"%s\"",ClassStem);
|
||||
HTM_Txt ("(");
|
||||
Tst_WriteAnsTF (Answer->TF);
|
||||
Tst_WriteAnsTF (Question->Answer.TF);
|
||||
HTM_Txt (")");
|
||||
HTM_SPAN_End ();
|
||||
break;
|
||||
|
@ -1044,15 +1044,15 @@ static void TsI_WriteRowImportedQst (struct XMLElement *StemElem,
|
|||
case Tst_ANS_TEXT:
|
||||
HTM_TABLE_Begin (NULL);
|
||||
for (NumOpt = 0;
|
||||
NumOpt < Answer->NumOptions;
|
||||
NumOpt < Question->Answer.NumOptions;
|
||||
NumOpt++)
|
||||
{
|
||||
/* Convert the answer, that is in HTML, to rigorous HTML */
|
||||
AnswerTextLength = strlen (Answer->Options[NumOpt].Text) *
|
||||
AnswerTextLength = strlen (Question->Answer.Options[NumOpt].Text) *
|
||||
Str_MAX_BYTES_PER_CHAR;
|
||||
if ((AnswerText = (char *) malloc (AnswerTextLength + 1)) == NULL)
|
||||
Lay_NotEnoughMemoryExit ();
|
||||
Str_Copy (AnswerText,Answer->Options[NumOpt].Text,
|
||||
Str_Copy (AnswerText,Question->Answer.Options[NumOpt].Text,
|
||||
AnswerTextLength);
|
||||
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
||||
AnswerText,AnswerTextLength,false);
|
||||
|
@ -1060,15 +1060,15 @@ static void TsI_WriteRowImportedQst (struct XMLElement *StemElem,
|
|||
/* Convert the feedback, that is in HTML, to rigorous HTML */
|
||||
AnswerFeedbackLength = 0;
|
||||
AnswerFeedback = NULL;
|
||||
if (Answer->Options[NumOpt].Feedback)
|
||||
if (Answer->Options[NumOpt].Feedback[0])
|
||||
if (Question->Answer.Options[NumOpt].Feedback)
|
||||
if (Question->Answer.Options[NumOpt].Feedback[0])
|
||||
{
|
||||
AnswerFeedbackLength = strlen (Answer->Options[NumOpt].Feedback) *
|
||||
AnswerFeedbackLength = strlen (Question->Answer.Options[NumOpt].Feedback) *
|
||||
Str_MAX_BYTES_PER_CHAR;
|
||||
if ((AnswerFeedback = (char *) malloc (AnswerFeedbackLength + 1)) == NULL)
|
||||
Lay_NotEnoughMemoryExit ();
|
||||
Str_Copy (AnswerFeedback,
|
||||
Answer->Options[NumOpt].Feedback,
|
||||
Question->Answer.Options[NumOpt].Feedback,
|
||||
AnswerFeedbackLength);
|
||||
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
||||
AnswerFeedback,AnswerFeedbackLength,false);
|
||||
|
@ -1078,7 +1078,7 @@ static void TsI_WriteRowImportedQst (struct XMLElement *StemElem,
|
|||
|
||||
/* Put an icon that indicates whether the answer is correct or wrong */
|
||||
HTM_TD_Begin ("class=\"BT%u\"",Gbl.RowEvenOdd);
|
||||
if (Answer->Options[NumOpt].Correct)
|
||||
if (Question->Answer.Options[NumOpt].Correct)
|
||||
Ico_PutIcon ("check.svg",Txt_TST_Answer_given_by_the_teachers,
|
||||
QuestionExists ? "ICO_HIDDEN CONTEXT_ICO_16x16" :
|
||||
"CONTEXT_ICO_16x16");
|
||||
|
|
Loading…
Reference in New Issue