mirror of https://github.com/acanas/swad-core.git
Version 15.184
This commit is contained in:
parent
72c3301506
commit
58ccf23b80
|
@ -1743,12 +1743,12 @@ a:hover img.CENTRE_PHOTO_SHOW
|
|||
.TEST_EXA_LIGHT {color:#A0A0A0; font-size:12pt;}
|
||||
.TEST_EDI {color:#404040; font-size:12pt;}
|
||||
.TEST_EDI_LIGHT {color:#A0A0A0; font-size:12pt;}
|
||||
.TEST_IMG_SHOW_STEM {width:600px; margin:10px 0;}
|
||||
.TEST_IMG_SHOW_ANS {width:450px; margin:10px 0;}
|
||||
.TEST_IMG_EDIT_LIST_STEM {width:300px; margin:5px 0;}
|
||||
.TEST_IMG_EDIT_LIST_ANS {width:225px; margin:5px 0;}
|
||||
.TEST_IMG_EDIT_ONE_STEM {width:600px;}
|
||||
.TEST_IMG_EDIT_ONE_ANS {width:450px;}
|
||||
.TEST_IMG_SHOW_STEM {width:600px; border-radius:4px; margin:10px 0;}
|
||||
.TEST_IMG_SHOW_ANS {width:450px; border-radius:4px; margin:10px 0;}
|
||||
.TEST_IMG_EDIT_LIST_STEM {width:300px; border-radius:2px; margin:5px 0;}
|
||||
.TEST_IMG_EDIT_LIST_ANS {width:225px; border-radius:2px; margin:5px 0;}
|
||||
.TEST_IMG_EDIT_ONE_STEM {width:600px; border-radius:4px;}
|
||||
.TEST_IMG_EDIT_ONE_ANS {width:450px; border-radius:4px;}
|
||||
|
||||
/******************************* Time table **********************************/
|
||||
#timetable
|
||||
|
|
|
@ -132,13 +132,15 @@
|
|||
/****************************** Public constants *****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#define Log_PLATFORM_VERSION "SWAD 15.183.1 (2016-04-06)"
|
||||
#define Log_PLATFORM_VERSION "SWAD 15.184 (2016-04-06)"
|
||||
#define CSS_FILE "swad15.178.2.css"
|
||||
#define JS_FILE "swad15.178.2.js"
|
||||
|
||||
// Number of lines (includes comments but not blank lines) has been got with the following command:
|
||||
// nl swad*.c swad*.h css/swad*.css py/swad*.py js/swad*.js soap/swad*.h sql/swad*.sql | tail -1
|
||||
/*
|
||||
Version 15.184: Apr 06, 2016 Code refactoring in tests and images.
|
||||
Fixed bugs in test questions. (198682 lines)
|
||||
Version 15.183.1: Apr 06, 2016 Fix bug in feedback of test question. (198706 lines)
|
||||
Version 15.183: Apr 06, 2016 Change in length of title/attribution of images. (198704 lines)
|
||||
2 changes necessary in database:
|
||||
|
|
106
swad_image.c
106
swad_image.c
|
@ -71,45 +71,47 @@ static void Img_ProcessImage (const char *FileNameImgOriginal,
|
|||
/*************************** Reset image title *******************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void Img_ResetImageTitle (struct Image *Image)
|
||||
void Img_FreeImageTitle (struct Image *Image)
|
||||
{
|
||||
// Image->Title must be initialized to NULL
|
||||
if (Image->Title)
|
||||
{
|
||||
free ((void *) Image->Title);
|
||||
Image->Title = NULL;
|
||||
Image->Title = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/********* Get image name and title from strings and copy to struct **********/
|
||||
/****** Get image name and title from a query result and copy to struct ******/
|
||||
/*****************************************************************************/
|
||||
|
||||
void Img_GetImageNameAndTitle (const char *Name,const char *Title,
|
||||
struct Image *Image)
|
||||
void Img_GetImageNameAndTitleFromRow (const char *Name,const char *Title,
|
||||
struct Image *Image)
|
||||
{
|
||||
size_t Length;
|
||||
|
||||
Img_ResetImageTitle (Image);
|
||||
/***** Copy image name to struct *****/
|
||||
strncpy (Image->Name,Name,Cry_LENGTH_ENCRYPTED_STR_SHA256_BASE64);
|
||||
Image->Name[Cry_LENGTH_ENCRYPTED_STR_SHA256_BASE64] = '\0';
|
||||
|
||||
if (Name[0])
|
||||
/***** Set status of image file *****/
|
||||
Image->Status = Image->Name[0] ? Img_NAME_STORED_IN_DB :
|
||||
Img_FILE_NONE;
|
||||
|
||||
/***** Copy image title to struct *****/
|
||||
Img_FreeImageTitle (Image);
|
||||
if (Title[0])
|
||||
{
|
||||
strncpy (Image->Name,Name,Cry_LENGTH_ENCRYPTED_STR_SHA256_BASE64);
|
||||
Image->Name[Cry_LENGTH_ENCRYPTED_STR_SHA256_BASE64] = '\0';
|
||||
/* Get and limit length of the title */
|
||||
Length = strlen (Title);
|
||||
if (Length > Img_MAX_BYTES_TITLE)
|
||||
Length = Img_MAX_BYTES_TITLE;
|
||||
|
||||
if (Image->Name[0]) // There is an image
|
||||
if (Title[0])
|
||||
{
|
||||
/* Get and limit length of the title */
|
||||
Length = strlen (Title);
|
||||
if (Length > Img_MAX_BYTES_TITLE)
|
||||
Length = Img_MAX_BYTES_TITLE;
|
||||
|
||||
if ((Image->Title = (char *) malloc (Length+1)) == NULL)
|
||||
Lay_ShowErrorAndExit ("Error allocating memory for image title.");
|
||||
strncpy (Image->Title,Title,Length);
|
||||
Image->Title[Length] = '\0';
|
||||
}
|
||||
if ((Image->Title = (char *) malloc (Length+1)) == NULL)
|
||||
Lay_ShowErrorAndExit ("Error allocating memory for image title.");
|
||||
strncpy (Image->Title,Title,Length);
|
||||
Image->Title[Length] = '\0';
|
||||
}
|
||||
else // No image in this question
|
||||
Image->Name[0] = '\0';
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -117,50 +119,60 @@ void Img_GetImageNameAndTitle (const char *Name,const char *Title,
|
|||
/*****************************************************************************/
|
||||
|
||||
void Img_GetImageFromForm (unsigned NumOpt,struct Image *Image,
|
||||
void (*GetImageNameFromDB) (unsigned NumOpt,struct Image *Image),
|
||||
void (*GetImageFromDB) (unsigned NumOpt,struct Image *Image),
|
||||
const char *ParamAction,const char *ParamFile,const char *ParamTitle,
|
||||
unsigned Width,unsigned Height,unsigned Quality)
|
||||
{
|
||||
char Title[Img_MAX_BYTES_TITLE+1];
|
||||
size_t Length;
|
||||
|
||||
Image->Action = Img_GetImageActionFromForm (ParamAction);
|
||||
Image->Status = Img_FILE_NONE;
|
||||
Img_FreeImageTitle (Image); // Reset to NULL
|
||||
|
||||
switch (Image->Action)
|
||||
{
|
||||
case Img_ACTION_NO_IMAGE: // Do not use image (remove current image if exists)
|
||||
/***** Reset image name *****/
|
||||
Image->Name[0] = '\0';
|
||||
Img_ResetImageTitle (Image);
|
||||
break;
|
||||
case Img_ACTION_KEEP_IMAGE: // Keep current image unchanged
|
||||
/***** Get image name *****/
|
||||
GetImageNameFromDB (NumOpt,Image);
|
||||
if (Image->Name[0])
|
||||
Image->Status = Img_NAME_STORED_IN_DB;
|
||||
GetImageFromDB (NumOpt,Image);
|
||||
break;
|
||||
case Img_ACTION_NEW_IMAGE: // Upload new image
|
||||
/***** Get new image (if present ==> process and create temporary file) *****/
|
||||
Img_GetAndProcessImageFileFromForm (Image,ParamFile,ParamTitle,
|
||||
Img_GetAndProcessImageFileFromForm (Image,ParamFile,
|
||||
Width,Height,Quality);
|
||||
if (Image->Status != Img_FILE_PROCESSED) // No new image received-processed successfully
|
||||
{
|
||||
/* Reset image name */
|
||||
Image->Status = Img_FILE_NONE;
|
||||
Image->Name[0] = '\0';
|
||||
Img_ResetImageTitle (Image);
|
||||
}
|
||||
break;
|
||||
case Img_ACTION_CHANGE_IMAGE: // Replace old image by new image
|
||||
/***** Get new image (if present ==> process and create temporary file) *****/
|
||||
Img_GetAndProcessImageFileFromForm (Image,ParamFile,ParamTitle,
|
||||
Img_GetAndProcessImageFileFromForm (Image,ParamFile,
|
||||
Width,Height,Quality);
|
||||
if (Image->Status != Img_FILE_PROCESSED) // No new image received-processed successfully
|
||||
{
|
||||
/* Get image name */
|
||||
GetImageNameFromDB (NumOpt,Image);
|
||||
Image->Status = (Image->Name[0] ? Img_NAME_STORED_IN_DB :
|
||||
Img_FILE_NONE);
|
||||
}
|
||||
GetImageFromDB (NumOpt,Image);
|
||||
break;
|
||||
}
|
||||
|
||||
/***** Get image title from form *****/
|
||||
Par_GetParToHTML (ParamTitle,Title,Img_MAX_BYTES_TITLE);
|
||||
if ((Length = strlen (Title)) > 0) // If title comming from the form is not empty
|
||||
{
|
||||
/* Overwrite current title (empty or coming from database)
|
||||
with the title coming from the form */
|
||||
Img_FreeImageTitle (Image);
|
||||
if ((Image->Title = (char *) malloc (Length + 1)) == NULL)
|
||||
Lay_ShowErrorAndExit ("Error allocating memory for image title.");
|
||||
strncpy (Image->Title,Title,Length);
|
||||
Image->Title[Length] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -183,12 +195,9 @@ Img_Action_t Img_GetImageActionFromForm (const char *ParamAction)
|
|||
/*****************************************************************************/
|
||||
/**************************** Get image from form ****************************/
|
||||
/*****************************************************************************/
|
||||
// Return true if image is created
|
||||
|
||||
void Img_GetAndProcessImageFileFromForm (struct Image *Image,
|
||||
const char *ParamFile,const char *ParamTitle,
|
||||
unsigned Width,unsigned Height,
|
||||
unsigned Quality)
|
||||
void Img_GetAndProcessImageFileFromForm (struct Image *Image,const char *ParamFile,
|
||||
unsigned Width,unsigned Height,unsigned Quality)
|
||||
{
|
||||
struct Param *Param;
|
||||
char FileNameImgSrc[PATH_MAX+1];
|
||||
|
@ -199,8 +208,6 @@ void Img_GetAndProcessImageFileFromForm (struct Image *Image,
|
|||
char FileNameImgOrig[PATH_MAX+1]; // Full name of original uploaded file
|
||||
char FileNameImgTmp[PATH_MAX+1]; // Full name of temporary processed file
|
||||
bool WrongType = false;
|
||||
char Title[Img_MAX_BYTES_TITLE+1];
|
||||
size_t Length;
|
||||
|
||||
/***** Rest image file status *****/
|
||||
Image->Status = Img_FILE_NONE;
|
||||
|
@ -265,17 +272,6 @@ void Img_GetAndProcessImageFileFromForm (struct Image *Image,
|
|||
|
||||
/***** Remove temporary original file *****/
|
||||
unlink (FileNameImgOrig);
|
||||
|
||||
/***** Get image title from form *****/
|
||||
Par_GetParToHTML (ParamTitle,Title,Img_MAX_BYTES_TITLE); // TODO: Create a function to get only the length of a parameter
|
||||
Length = strlen (Title);
|
||||
if (Length > 0)
|
||||
{
|
||||
if ((Image->Title = (char *) malloc (Length+1)) == NULL)
|
||||
Lay_ShowErrorAndExit ("Error allocating memory for image title.");
|
||||
strncpy (Image->Title,Title,Length);
|
||||
Image->Title[Length] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
14
swad_image.h
14
swad_image.h
|
@ -94,19 +94,17 @@ struct Image
|
|||
/***************************** Public prototypes *****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void Img_ResetImageTitle (struct Image *Image);
|
||||
void Img_GetImageNameAndTitle (const char *Name,const char *Title,
|
||||
struct Image *Image);
|
||||
void Img_FreeImageTitle (struct Image *Image);
|
||||
void Img_GetImageNameAndTitleFromRow (const char *Name,const char *Title,
|
||||
struct Image *Image);
|
||||
|
||||
void Img_GetImageFromForm (unsigned NumOpt,struct Image *Image,
|
||||
void (*GetImageNameFromDB) (unsigned NumOpt,struct Image *Image),
|
||||
void (*GetImageFromDB) (unsigned NumOpt,struct Image *Image),
|
||||
const char *ParamAction,const char *ParamFile,const char *ParamTitle,
|
||||
unsigned Width,unsigned Height,unsigned Quality);
|
||||
Img_Action_t Img_GetImageActionFromForm (const char *ParamAction);
|
||||
void Img_GetAndProcessImageFileFromForm (struct Image *Image,
|
||||
const char *ParamFile,const char *ParamTitle,
|
||||
unsigned Width,unsigned Height,
|
||||
unsigned Quality);
|
||||
void Img_GetAndProcessImageFileFromForm (struct Image *Image,const char *ParamFile,
|
||||
unsigned Width,unsigned Height,unsigned Quality);
|
||||
|
||||
void Img_MoveImageToDefinitiveDirectory (struct Image *Image);
|
||||
void Img_ShowImage (struct Image *Image,const char *ClassImg);
|
||||
|
|
|
@ -2527,7 +2527,7 @@ static unsigned Svy_GetAnswersQst (long QstCod,MYSQL_RES **mysql_res)
|
|||
|
||||
/***** Count number of rows of result *****/
|
||||
if (NumRows == 0)
|
||||
Lay_ShowErrorAndExit ("Error when getting answers of a question.");
|
||||
Lay_ShowAlert (Lay_ERROR,"Error when getting answers of a question.");
|
||||
|
||||
return (unsigned) NumRows;
|
||||
}
|
||||
|
@ -3024,64 +3024,67 @@ static void Svy_WriteAnswersOfAQst (struct Survey *Svy,struct SurveyQuestion *Sv
|
|||
NumAnswers = Svy_GetAnswersQst (SvyQst->QstCod,&mysql_res); // Result: AnsInd,NumUsrs,Answer
|
||||
|
||||
/***** Write the answers *****/
|
||||
fprintf (Gbl.F.Out,"<table class=\"CELLS_PAD_5\" style=\"width:100%%;\">");
|
||||
for (NumAns = 0;
|
||||
NumAns < NumAnswers;
|
||||
NumAns++)
|
||||
if (NumAnswers)
|
||||
{
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
fprintf (Gbl.F.Out,"<table class=\"CELLS_PAD_5\" style=\"width:100%%;\">");
|
||||
for (NumAns = 0;
|
||||
NumAns < NumAnswers;
|
||||
NumAns++)
|
||||
{
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
|
||||
/* Get number of users who have marked this answer (row[1]) */
|
||||
if (sscanf (row[1],"%u",&NumUsrsThisAnswer) != 1)
|
||||
Lay_ShowErrorAndExit ("Error when getting number of users who have marked an answer.");
|
||||
/* Get number of users who have marked this answer (row[1]) */
|
||||
if (sscanf (row[1],"%u",&NumUsrsThisAnswer) != 1)
|
||||
Lay_ShowErrorAndExit ("Error when getting number of users who have marked an answer.");
|
||||
|
||||
/* Convert the answer (row[2]), that is in HTML, to rigorous HTML */
|
||||
AnsLength = strlen (row[2]) * Str_MAX_LENGTH_SPEC_CHAR_HTML;
|
||||
if ((Answer = malloc (AnsLength+1)) == NULL)
|
||||
Lay_ShowErrorAndExit ("Not enough memory to store answer.");
|
||||
strcpy (Answer,row[2]);
|
||||
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
||||
Answer,AnsLength,false);
|
||||
/* Convert the answer (row[2]), that is in HTML, to rigorous HTML */
|
||||
AnsLength = strlen (row[2]) * Str_MAX_LENGTH_SPEC_CHAR_HTML;
|
||||
if ((Answer = malloc (AnsLength+1)) == NULL)
|
||||
Lay_ShowErrorAndExit ("Not enough memory to store answer.");
|
||||
strcpy (Answer,row[2]);
|
||||
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
||||
Answer,AnsLength,false);
|
||||
|
||||
/* Selectors and label with the letter of the answer */
|
||||
fprintf (Gbl.F.Out,"<tr>");
|
||||
/* Selectors and label with the letter of the answer */
|
||||
fprintf (Gbl.F.Out,"<tr>");
|
||||
|
||||
if (PutFormAnswerSurvey)
|
||||
{
|
||||
/* Write selector to choice this answer */
|
||||
fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP\">"
|
||||
"<input type=\"");
|
||||
if (SvyQst->AnswerType == Svy_ANS_UNIQUE_CHOICE)
|
||||
fprintf (Gbl.F.Out,"radio\""
|
||||
" onclick=\"selectUnselectRadio(this,this.form.Ans%010u,%u)\"",
|
||||
(unsigned) SvyQst->QstCod,NumAnswers);
|
||||
else // SvyQst->AnswerType == Svy_ANS_MULTIPLE_CHOICE
|
||||
fprintf (Gbl.F.Out,"checkbox\"");
|
||||
fprintf (Gbl.F.Out," name=\"Ans%010u\" value=\"%u\" />"
|
||||
"</td>",
|
||||
(unsigned) SvyQst->QstCod,NumAns);
|
||||
}
|
||||
if (PutFormAnswerSurvey)
|
||||
{
|
||||
/* Write selector to choice this answer */
|
||||
fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP\">"
|
||||
"<input type=\"");
|
||||
if (SvyQst->AnswerType == Svy_ANS_UNIQUE_CHOICE)
|
||||
fprintf (Gbl.F.Out,"radio\""
|
||||
" onclick=\"selectUnselectRadio(this,this.form.Ans%010u,%u)\"",
|
||||
(unsigned) SvyQst->QstCod,NumAnswers);
|
||||
else // SvyQst->AnswerType == Svy_ANS_MULTIPLE_CHOICE
|
||||
fprintf (Gbl.F.Out,"checkbox\"");
|
||||
fprintf (Gbl.F.Out," name=\"Ans%010u\" value=\"%u\" />"
|
||||
"</td>",
|
||||
(unsigned) SvyQst->QstCod,NumAns);
|
||||
}
|
||||
|
||||
/* Write the number of option */
|
||||
fprintf (Gbl.F.Out,"<td class=\"DAT LEFT_TOP\" style=\"width:50px;\">"
|
||||
"%u)"
|
||||
"</td>",
|
||||
NumAns + 1);
|
||||
/* Write the number of option */
|
||||
fprintf (Gbl.F.Out,"<td class=\"DAT LEFT_TOP\" style=\"width:50px;\">"
|
||||
"%u)"
|
||||
"</td>",
|
||||
NumAns + 1);
|
||||
|
||||
/* Write the text of the answer */
|
||||
fprintf (Gbl.F.Out,"<td class=\"TEST_EDI LEFT_TOP\">%s</td>",
|
||||
Answer);
|
||||
/* Write the text of the answer */
|
||||
fprintf (Gbl.F.Out,"<td class=\"TEST_EDI LEFT_TOP\">%s</td>",
|
||||
Answer);
|
||||
|
||||
/* Show stats of this answer */
|
||||
if (Svy->Status.ICanViewResults)
|
||||
Svy_DrawBarNumUsrs (NumUsrsThisAnswer,Svy->NumUsrs);
|
||||
/* Show stats of this answer */
|
||||
if (Svy->Status.ICanViewResults)
|
||||
Svy_DrawBarNumUsrs (NumUsrsThisAnswer,Svy->NumUsrs);
|
||||
|
||||
fprintf (Gbl.F.Out,"</tr>");
|
||||
fprintf (Gbl.F.Out,"</tr>");
|
||||
|
||||
/* Free memory allocated for the answer */
|
||||
free ((void *) Answer);
|
||||
/* Free memory allocated for the answer */
|
||||
free ((void *) Answer);
|
||||
}
|
||||
fprintf (Gbl.F.Out,"</table>");
|
||||
}
|
||||
fprintf (Gbl.F.Out,"</table>");
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
|
|
324
swad_test.c
324
swad_test.c
|
@ -219,6 +219,9 @@ static int Tst_CountNumTagsInList (void);
|
|||
static int Tst_CountNumAnswerTypesInList (void);
|
||||
static void Tst_PutFormEditOneQst (char *Stem,char *Feedback);
|
||||
|
||||
static void Tst_FreeTextChoiceAnswers (void);
|
||||
static void Tst_FreeTextChoiceAnswer (unsigned NumOpt);
|
||||
|
||||
static void Tst_InitImagesOfQuestion (void);
|
||||
static void Tst_FreeImagesOfQuestion (void);
|
||||
|
||||
|
@ -236,7 +239,7 @@ static void Tst_EnableOrDisableTag (long TagCod,bool TagHidden);
|
|||
static void Tst_PutIconToRemoveOneQst (void);
|
||||
static void Tst_PutParamsRemoveOneQst (void);
|
||||
|
||||
static bool Tst_GetQstCod (void);
|
||||
static long Tst_GetQstCod (void);
|
||||
|
||||
static void Tst_InsertOrUpdateQstIntoDB (void);
|
||||
static void Tst_InsertTagsIntoDB (void);
|
||||
|
@ -249,8 +252,6 @@ static void Tst_RemoveUnusedTagsFromCurrentCrs (void);
|
|||
static void Tst_RemoveImgFilesFromStemOfQsts (long CrsCod,long QstCod);
|
||||
static void Tst_RemoveImgFilesFromAnsOfQsts (long CrsCod,long QstCod,unsigned AnsInd);
|
||||
|
||||
static void Tst_FreeTextChoiceAnswer (unsigned NumOpt);
|
||||
|
||||
static unsigned Tst_GetNumTstQuestions (Sco_Scope_t Scope,Tst_AnswerType_t AnsType,struct Tst_Stats *Stats);
|
||||
static unsigned Tst_GetNumCoursesWithTstQuestions (Sco_Scope_t Scope,Tst_AnswerType_t AnsType);
|
||||
static unsigned Tst_GetNumCoursesWithPluggableTstQuestions (Sco_Scope_t Scope,Tst_AnswerType_t AnsType);
|
||||
|
@ -981,6 +982,10 @@ static void Tst_WriteQstAndAnsExam (unsigned NumQst,long QstCod,MYSQL_ROW row,
|
|||
row[10] Score
|
||||
*/
|
||||
|
||||
/***** Create test question *****/
|
||||
Tst_QstConstructor ();
|
||||
Gbl.Test.QstCod = QstCod;
|
||||
|
||||
/***** Write number of question *****/
|
||||
fprintf (Gbl.F.Out,"<tr>"
|
||||
"<td class=\"RIGHT_TOP COLOR%u\">"
|
||||
|
@ -999,12 +1004,9 @@ static void Tst_WriteQstAndAnsExam (unsigned NumQst,long QstCod,MYSQL_ROW row,
|
|||
fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP COLOR%u\">",
|
||||
Gbl.RowEvenOdd);
|
||||
Tst_WriteQstStem (row[4],"TEST_EXA");
|
||||
if (row[6][0])
|
||||
{
|
||||
Gbl.Test.Image.Status = Img_NAME_STORED_IN_DB;
|
||||
Img_GetImageNameAndTitle (row[6],row[7],&Gbl.Test.Image);
|
||||
Img_ShowImage (&Gbl.Test.Image,"TEST_IMG_SHOW_STEM");
|
||||
}
|
||||
Img_GetImageNameAndTitleFromRow (row[6],row[7],&Gbl.Test.Image);
|
||||
Img_ShowImage (&Gbl.Test.Image,"TEST_IMG_SHOW_STEM");
|
||||
|
||||
if (Gbl.Action.Act == ActSeeTst)
|
||||
Tst_WriteAnswersOfAQstSeeExam (NumQst,QstCod,(Str_ConvertToUpperLetter (row[3][0]) == 'Y'));
|
||||
else // Assessing exam / Viewing old exam
|
||||
|
@ -1018,9 +1020,8 @@ static void Tst_WriteQstAndAnsExam (unsigned NumQst,long QstCod,MYSQL_ROW row,
|
|||
fprintf (Gbl.F.Out,"</td>"
|
||||
"</tr>");
|
||||
|
||||
/***** Free answers and images of this test question *****/
|
||||
Tst_FreeTextChoiceAnswers ();
|
||||
Tst_FreeImagesOfQuestion ();
|
||||
/***** Destroy test question *****/
|
||||
Tst_QstDestructor ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -2615,7 +2616,6 @@ static void Tst_ListOneOrMoreQuestionsToEdit (unsigned long NumRows,MYSQL_RES *m
|
|||
Tst_QuestionsOrder_t Order;
|
||||
unsigned long NumRow;
|
||||
MYSQL_ROW row;
|
||||
long QstCod;
|
||||
unsigned UniqueId;
|
||||
time_t TimeUTC;
|
||||
unsigned long NumHitsThisQst;
|
||||
|
@ -2706,8 +2706,11 @@ static void Tst_ListOneOrMoreQuestionsToEdit (unsigned long NumRows,MYSQL_RES *m
|
|||
row[ 9] NumHitsNotBlank
|
||||
row[10] Score
|
||||
*/
|
||||
/***** Create test question *****/
|
||||
Tst_QstConstructor ();
|
||||
|
||||
/* row[0] holds the code of the question */
|
||||
if ((QstCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
|
||||
if ((Gbl.Test.QstCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
|
||||
Lay_ShowErrorAndExit ("Wrong code of question.");
|
||||
|
||||
/* Write icon to remove the question */
|
||||
|
@ -2716,7 +2719,7 @@ static void Tst_ListOneOrMoreQuestionsToEdit (unsigned long NumRows,MYSQL_RES *m
|
|||
Act_FormStart (ActReqRemTstQst);
|
||||
Sta_WriteParamsDatesSeeAccesses ();
|
||||
Tst_WriteParamEditQst ();
|
||||
Par_PutHiddenParamLong ("QstCod",QstCod);
|
||||
Par_PutHiddenParamLong ("QstCod",Gbl.Test.QstCod);
|
||||
if (NumRows == 1)
|
||||
Par_PutHiddenParamChar ("OnlyThisQst",'Y'); // If there are only one row, don't list again after removing
|
||||
Lay_PutIconRemove ();
|
||||
|
@ -2726,7 +2729,7 @@ static void Tst_ListOneOrMoreQuestionsToEdit (unsigned long NumRows,MYSQL_RES *m
|
|||
/* Write icon to edit the question */
|
||||
fprintf (Gbl.F.Out,"<td class=\"BT%u\">",Gbl.RowEvenOdd);
|
||||
Act_FormStart (ActEdiOneTstQst);
|
||||
Par_PutHiddenParamLong ("QstCod",QstCod);
|
||||
Par_PutHiddenParamLong ("QstCod",Gbl.Test.QstCod);
|
||||
fprintf (Gbl.F.Out,"<input type=\"image\" src=\"%s/edit64x64.png\""
|
||||
" alt=\"%s\" title=\"%s\""
|
||||
" class=\"ICON20x20\" />",
|
||||
|
@ -2746,7 +2749,7 @@ static void Tst_ListOneOrMoreQuestionsToEdit (unsigned long NumRows,MYSQL_RES *m
|
|||
fprintf (Gbl.F.Out,"<td class=\"DAT_SMALL CENTER_TOP COLOR%u\">"
|
||||
"%ld "
|
||||
"</td>",
|
||||
Gbl.RowEvenOdd,QstCod);
|
||||
Gbl.RowEvenOdd,Gbl.Test.QstCod);
|
||||
|
||||
/* Write the date (row[1] has the UTC date-time) */
|
||||
TimeUTC = Dat_GetUNIXTimeFromStr (row[1]);
|
||||
|
@ -2762,7 +2765,7 @@ static void Tst_ListOneOrMoreQuestionsToEdit (unsigned long NumRows,MYSQL_RES *m
|
|||
/* Write the question tags */
|
||||
fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP COLOR%u\">",
|
||||
Gbl.RowEvenOdd);
|
||||
Tst_GetAndWriteTagsQst (QstCod);
|
||||
Tst_GetAndWriteTagsQst (Gbl.Test.QstCod);
|
||||
fprintf (Gbl.F.Out,"</td>");
|
||||
|
||||
/* Write the question type (row[2]) */
|
||||
|
@ -2780,7 +2783,7 @@ static void Tst_ListOneOrMoreQuestionsToEdit (unsigned long NumRows,MYSQL_RES *m
|
|||
Gbl.Test.AnswerType == Tst_ANS_MULTIPLE_CHOICE)
|
||||
{
|
||||
Act_FormStart (ActShfTstQst);
|
||||
Par_PutHiddenParamLong ("QstCod",QstCod);
|
||||
Par_PutHiddenParamLong ("QstCod",Gbl.Test.QstCod);
|
||||
Sta_WriteParamsDatesSeeAccesses ();
|
||||
Tst_WriteParamEditQst ();
|
||||
if (NumRows == 1)
|
||||
|
@ -2800,20 +2803,12 @@ static void Tst_ListOneOrMoreQuestionsToEdit (unsigned long NumRows,MYSQL_RES *m
|
|||
fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP COLOR%u\">",
|
||||
Gbl.RowEvenOdd);
|
||||
Tst_WriteQstStem (row[4],"TEST_EDI");
|
||||
if (row[6][0])
|
||||
{
|
||||
Gbl.Test.Image.Status = Img_NAME_STORED_IN_DB;
|
||||
Img_GetImageNameAndTitle (row[6],row[7],&Gbl.Test.Image);
|
||||
Img_ShowImage (&Gbl.Test.Image,"TEST_IMG_EDIT_LIST_STEM");
|
||||
}
|
||||
Img_GetImageNameAndTitleFromRow (row[6],row[7],&Gbl.Test.Image);
|
||||
Img_ShowImage (&Gbl.Test.Image,"TEST_IMG_EDIT_LIST_STEM");
|
||||
Tst_WriteQstFeedback (row[5],"TEST_EDI_LIGHT");
|
||||
Tst_WriteAnswersOfAQstEdit (QstCod);
|
||||
Tst_WriteAnswersOfAQstEdit (Gbl.Test.QstCod);
|
||||
fprintf (Gbl.F.Out,"</td>");
|
||||
|
||||
/* Free answers and images of this test question */
|
||||
Tst_FreeTextChoiceAnswers ();
|
||||
Tst_FreeImagesOfQuestion ();
|
||||
|
||||
/* Get number of hits
|
||||
(number of times that the question has been answered,
|
||||
including blank answers) (row[8]) */
|
||||
|
@ -2865,6 +2860,9 @@ static void Tst_ListOneOrMoreQuestionsToEdit (unsigned long NumRows,MYSQL_RES *m
|
|||
fprintf (Gbl.F.Out,"N.A.");
|
||||
fprintf (Gbl.F.Out,"</td>"
|
||||
"</tr>");
|
||||
|
||||
/***** Destroy test question *****/
|
||||
Tst_QstDestructor ();
|
||||
}
|
||||
|
||||
/***** End table *****/
|
||||
|
@ -2901,7 +2899,7 @@ void Tst_WriteParamEditQst (void)
|
|||
|
||||
unsigned Tst_GetAnswersQst (long QstCod,MYSQL_RES **mysql_res,bool Shuffle)
|
||||
{
|
||||
char Query[256];
|
||||
char Query[512];
|
||||
unsigned long NumRows;
|
||||
|
||||
/***** Get answers of a question from database *****/
|
||||
|
@ -2911,7 +2909,7 @@ unsigned Tst_GetAnswersQst (long QstCod,MYSQL_RES **mysql_res,bool Shuffle)
|
|||
Shuffle ? "RAND(NOW())" :
|
||||
"AnsInd");
|
||||
if (!(NumRows = DB_QuerySELECT (Query,mysql_res,"can not get answers of a question")))
|
||||
Lay_ShowErrorAndExit ("Error when getting answers of a question.");
|
||||
Lay_ShowAlert (Lay_ERROR,"Error when getting answers of a question.");
|
||||
|
||||
return (unsigned) NumRows;
|
||||
}
|
||||
|
@ -3007,11 +3005,7 @@ static void Tst_WriteAnswersOfAQstEdit (long QstCod)
|
|||
}
|
||||
|
||||
/* Copy image */
|
||||
if (row[3][0])
|
||||
{
|
||||
Gbl.Test.Answer.Options[NumOpt].Image.Status = Img_NAME_STORED_IN_DB;
|
||||
Img_GetImageNameAndTitle (row[3],row[4],&Gbl.Test.Answer.Options[NumOpt].Image);
|
||||
}
|
||||
Img_GetImageNameAndTitleFromRow (row[3],row[4],&Gbl.Test.Answer.Options[NumOpt].Image);
|
||||
|
||||
/* Put an icon that indicates whether the answer is correct or wrong */
|
||||
fprintf (Gbl.F.Out,"<tr>"
|
||||
|
@ -3037,8 +3031,7 @@ static void Tst_WriteAnswersOfAQstEdit (long QstCod)
|
|||
"<div class=\"TEST_EDI\">"
|
||||
"%s",
|
||||
Answer);
|
||||
if (Gbl.Test.Answer.Options[NumOpt].Image.Name[0])
|
||||
Img_ShowImage (&Gbl.Test.Answer.Options[NumOpt].Image,"TEST_IMG_EDIT_LIST_ANS");
|
||||
Img_ShowImage (&Gbl.Test.Answer.Options[NumOpt].Image,"TEST_IMG_EDIT_LIST_ANS");
|
||||
fprintf (Gbl.F.Out,"</div>");
|
||||
|
||||
/* Write the text of the feedback */
|
||||
|
@ -3106,6 +3099,10 @@ static void Tst_WriteAnswersOfAQstAssessExam (unsigned NumQst,long QstCod,
|
|||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
|
||||
/***** Create test question *****/
|
||||
Tst_QstConstructor ();
|
||||
Gbl.Test.QstCod = QstCod;
|
||||
|
||||
/***** Get answers of a question from database *****/
|
||||
Gbl.Test.Answer.NumOptions = Tst_GetAnswersQst (QstCod,&mysql_res,false); // Result: AnsInd,Answer,Correct
|
||||
/*
|
||||
|
@ -3141,6 +3138,9 @@ static void Tst_WriteAnswersOfAQstAssessExam (unsigned NumQst,long QstCod,
|
|||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
|
||||
/***** Destroy test question *****/
|
||||
Tst_QstDestructor ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -3281,8 +3281,9 @@ static void Tst_WriteChoiceAnsSeeExam (unsigned NumQst,long QstCod,bool Shuffle)
|
|||
bool ErrorInIndex = false;
|
||||
char ParamName[3+6+1];
|
||||
|
||||
/***** Start of table *****/
|
||||
fprintf (Gbl.F.Out,"<table class=\"CELLS_PAD_2\">");
|
||||
/***** Create test question *****/
|
||||
Tst_QstConstructor ();
|
||||
Gbl.Test.QstCod = QstCod;
|
||||
|
||||
/***** Get answers of a question from database *****/
|
||||
Gbl.Test.Answer.NumOptions = Tst_GetAnswersQst (QstCod,&mysql_res,Shuffle); // Result: AnsInd,Answer,Correct
|
||||
|
@ -3294,6 +3295,10 @@ static void Tst_WriteChoiceAnsSeeExam (unsigned NumQst,long QstCod,bool Shuffle)
|
|||
row[ 4] ImageTitle
|
||||
row[ 5] Correct
|
||||
*/
|
||||
|
||||
/***** Start of table *****/
|
||||
fprintf (Gbl.F.Out,"<table class=\"CELLS_PAD_2\">");
|
||||
|
||||
for (NumOpt = 0;
|
||||
NumOpt < Gbl.Test.Answer.NumOptions;
|
||||
NumOpt++)
|
||||
|
@ -3324,11 +3329,7 @@ static void Tst_WriteChoiceAnsSeeExam (unsigned NumQst,long QstCod,bool Shuffle)
|
|||
Gbl.Test.Answer.Options[NumOpt].Text,Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false);
|
||||
|
||||
/***** Copy image *****/
|
||||
if (row[3][0])
|
||||
{
|
||||
Gbl.Test.Answer.Options[NumOpt].Image.Status = Img_NAME_STORED_IN_DB;
|
||||
Img_GetImageNameAndTitle (row[3],row[4],&Gbl.Test.Answer.Options[NumOpt].Image);
|
||||
}
|
||||
Img_GetImageNameAndTitleFromRow (row[3],row[4],&Gbl.Test.Answer.Options[NumOpt].Image);
|
||||
|
||||
/***** Write selectors and letter of this option *****/
|
||||
fprintf (Gbl.F.Out,"<tr>"
|
||||
|
@ -3351,8 +3352,7 @@ static void Tst_WriteChoiceAnsSeeExam (unsigned NumQst,long QstCod,bool Shuffle)
|
|||
fprintf (Gbl.F.Out,"<td class=\"TEST_EXA LEFT_TOP\">"
|
||||
"%s",
|
||||
Gbl.Test.Answer.Options[NumOpt].Text);
|
||||
if (Gbl.Test.Answer.Options[NumOpt].Image.Name[0])
|
||||
Img_ShowImage (&Gbl.Test.Answer.Options[NumOpt].Image,"TEST_IMG_SHOW_ANS");
|
||||
Img_ShowImage (&Gbl.Test.Answer.Options[NumOpt].Image,"TEST_IMG_SHOW_ANS");
|
||||
fprintf (Gbl.F.Out,"</td>"
|
||||
"</tr>");
|
||||
}
|
||||
|
@ -3360,12 +3360,11 @@ static void Tst_WriteChoiceAnsSeeExam (unsigned NumQst,long QstCod,bool Shuffle)
|
|||
/***** End of table *****/
|
||||
fprintf (Gbl.F.Out,"</table>");
|
||||
|
||||
/***** Free answers and images of this test question *****/
|
||||
Tst_FreeTextChoiceAnswers ();
|
||||
Tst_FreeImagesOfQuestion ();
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
|
||||
/***** Destroy test question *****/
|
||||
Tst_QstDestructor ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -3430,11 +3429,7 @@ static void Tst_WriteChoiceAnsAssessExam (unsigned NumQst,MYSQL_RES *mysql_res,
|
|||
}
|
||||
|
||||
/***** Copy image *****/
|
||||
if (row[3][0])
|
||||
{
|
||||
Gbl.Test.Answer.Options[NumOpt].Image.Status = Img_NAME_STORED_IN_DB;
|
||||
Img_GetImageNameAndTitle (row[3],row[4],&Gbl.Test.Answer.Options[NumOpt].Image);
|
||||
}
|
||||
Img_GetImageNameAndTitleFromRow (row[3],row[4],&Gbl.Test.Answer.Options[NumOpt].Image);
|
||||
|
||||
/***** Assign correctness (row[5]) of this answer (this option) *****/
|
||||
Gbl.Test.Answer.Options[NumOpt].Correct = (Str_ConvertToUpperLetter (row[5][0]) == 'Y');
|
||||
|
@ -3526,8 +3521,7 @@ static void Tst_WriteChoiceAnsAssessExam (unsigned NumQst,MYSQL_RES *mysql_res,
|
|||
"<div class=\"TEST_EXA\">"
|
||||
"%s",
|
||||
Gbl.Test.Answer.Options[Indexes[NumOpt]].Text);
|
||||
if (Gbl.Test.Answer.Options[Indexes[NumOpt]].Image.Name[0])
|
||||
Img_ShowImage (&Gbl.Test.Answer.Options[Indexes[NumOpt]].Image,"TEST_IMG_SHOW_ANS");
|
||||
Img_ShowImage (&Gbl.Test.Answer.Options[Indexes[NumOpt]].Image,"TEST_IMG_SHOW_ANS");
|
||||
fprintf (Gbl.F.Out,"</div>");
|
||||
if (Gbl.Test.Config.FeedbackType == Tst_FEEDBACK_FULL_FEEDBACK)
|
||||
if (Gbl.Test.Answer.Options[Indexes[NumOpt]].Feedback)
|
||||
|
@ -3606,10 +3600,6 @@ static void Tst_WriteChoiceAnsAssessExam (unsigned NumQst,MYSQL_RES *mysql_res,
|
|||
|
||||
/***** End of table *****/
|
||||
fprintf (Gbl.F.Out,"</table>");
|
||||
|
||||
/***** Free answers and images of this test question *****/
|
||||
Tst_FreeTextChoiceAnswers ();
|
||||
Tst_FreeImagesOfQuestion ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -3791,9 +3781,6 @@ static void Tst_WriteTextAnsAssessExam (unsigned NumQst,MYSQL_RES *mysql_res,
|
|||
}
|
||||
|
||||
fprintf (Gbl.F.Out,"</table>");
|
||||
|
||||
/***** Free answers *****/
|
||||
Tst_FreeTextChoiceAnswers ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -4351,8 +4338,18 @@ void Tst_ShowFormEditOneQst (void)
|
|||
char Stem[Cns_MAX_BYTES_TEXT+1];
|
||||
char Feedback[Cns_MAX_BYTES_TEXT+1];
|
||||
|
||||
/***** Create test question *****/
|
||||
Tst_QstConstructor ();
|
||||
Gbl.Test.QstCod = Tst_GetQstCod ();
|
||||
Stem[0] = Feedback[0] = '\0';
|
||||
if (Gbl.Test.QstCod > 0) // If question already exists in the database
|
||||
Tst_GetQstDataFromDB (Stem,Feedback);
|
||||
|
||||
/***** Put form to edit question *****/
|
||||
Tst_PutFormEditOneQst (Stem,Feedback);
|
||||
|
||||
/***** Destroy test question *****/
|
||||
Tst_QstDestructor ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -4398,16 +4395,6 @@ static void Tst_PutFormEditOneQst (char *Stem,char *Feedback)
|
|||
char ParamFile[32];
|
||||
char ParamTitle[32];
|
||||
|
||||
/***** If no receiving the question, but editing a new or existing question
|
||||
==> init or edit data of question *****/
|
||||
if (Gbl.Action.Act == ActEdiOneTstQst)
|
||||
{
|
||||
Tst_InitQst ();
|
||||
if (Tst_GetQstCod ()) // If parameter QstCod received ==>
|
||||
// ==> question already exists in the database
|
||||
Tst_GetQstDataFromDB (Stem,Feedback);
|
||||
}
|
||||
|
||||
/***** Start frame *****/
|
||||
if (Gbl.Test.QstCod > 0) // The question already has assigned a code
|
||||
{
|
||||
|
@ -4737,21 +4724,18 @@ static void Tst_PutFormEditOneQst (char *Stem,char *Feedback)
|
|||
|
||||
/***** End frame *****/
|
||||
Lay_EndRoundFrame ();
|
||||
|
||||
/***** Free memory for answers *****/
|
||||
Tst_FreeTextChoiceAnswers ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/********************* Initialize a new question to zero *********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void Tst_InitQst (void)
|
||||
void Tst_QstConstructor (void)
|
||||
{
|
||||
unsigned NumOpt;
|
||||
unsigned NumTag;
|
||||
|
||||
Gbl.Test.QstCod = -1;
|
||||
Gbl.Test.QstCod = -1L;
|
||||
for (NumTag = 0;
|
||||
NumTag < Tst_MAX_TAGS_PER_QUESTION;
|
||||
NumTag++)
|
||||
|
@ -4781,6 +4765,74 @@ void Tst_InitQst (void)
|
|||
Tst_InitImagesOfQuestion ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************** Free memory allocated for test question *******************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void Tst_QstDestructor (void)
|
||||
{
|
||||
Tst_FreeTextChoiceAnswers ();
|
||||
Tst_FreeImagesOfQuestion ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************* Allocate memory for a choice answer *********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
int Tst_AllocateTextChoiceAnswer (unsigned NumOpt)
|
||||
{
|
||||
Tst_FreeTextChoiceAnswer (NumOpt);
|
||||
|
||||
if ((Gbl.Test.Answer.Options[NumOpt].Text =
|
||||
malloc (Tst_MAX_BYTES_ANSWER_OR_FEEDBACK + 1)) == NULL)
|
||||
{
|
||||
sprintf (Gbl.Message,"Not enough memory to store answer.");
|
||||
return 0;
|
||||
}
|
||||
if ((Gbl.Test.Answer.Options[NumOpt].Feedback =
|
||||
malloc (Tst_MAX_BYTES_ANSWER_OR_FEEDBACK + 1)) == NULL)
|
||||
{
|
||||
sprintf (Gbl.Message,"Not enough memory to store feedback.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Gbl.Test.Answer.Options[NumOpt].Text[0] =
|
||||
Gbl.Test.Answer.Options[NumOpt].Feedback[0] = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************** Free memory of all choice answers **********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Tst_FreeTextChoiceAnswers (void)
|
||||
{
|
||||
unsigned NumOpt;
|
||||
|
||||
for (NumOpt = 0;
|
||||
NumOpt < Tst_MAX_OPTIONS_PER_QUESTION;
|
||||
NumOpt++)
|
||||
Tst_FreeTextChoiceAnswer (NumOpt);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/********************** Free memory of a choice answer ***********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Tst_FreeTextChoiceAnswer (unsigned NumOpt)
|
||||
{
|
||||
if (Gbl.Test.Answer.Options[NumOpt].Text)
|
||||
{
|
||||
free ((void *) Gbl.Test.Answer.Options[NumOpt].Text);
|
||||
Gbl.Test.Answer.Options[NumOpt].Text = NULL;
|
||||
}
|
||||
if (Gbl.Test.Answer.Options[NumOpt].Feedback)
|
||||
{
|
||||
free ((void *) Gbl.Test.Answer.Options[NumOpt].Feedback);
|
||||
Gbl.Test.Answer.Options[NumOpt].Feedback = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************** Initialize images of a question to zero *******************/
|
||||
/*****************************************************************************/
|
||||
|
@ -4812,11 +4864,11 @@ static void Tst_FreeImagesOfQuestion (void)
|
|||
{
|
||||
unsigned NumOpt;
|
||||
|
||||
Img_ResetImageTitle (&Gbl.Test.Image);
|
||||
Img_FreeImageTitle (&Gbl.Test.Image);
|
||||
for (NumOpt = 0;
|
||||
NumOpt < Tst_MAX_OPTIONS_PER_QUESTION;
|
||||
NumOpt++)
|
||||
Img_ResetImageTitle (&Gbl.Test.Answer.Options[NumOpt].Image);
|
||||
Img_FreeImageTitle (&Gbl.Test.Answer.Options[NumOpt].Image);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -4869,13 +4921,7 @@ static void Tst_GetQstDataFromDB (char *Stem,char *Feedback)
|
|||
}
|
||||
|
||||
/* Get the image name of the question from the database (row[4]) */
|
||||
if (row[4][0])
|
||||
{
|
||||
Gbl.Test.Image.Status = Img_NAME_STORED_IN_DB;
|
||||
Img_GetImageNameAndTitle (row[4],row[5],&Gbl.Test.Image);
|
||||
}
|
||||
else
|
||||
Gbl.Test.Image.Status = Img_FILE_NONE;
|
||||
Img_GetImageNameAndTitleFromRow (row[4],row[5],&Gbl.Test.Image);
|
||||
|
||||
/* Free structure that stores the query result */
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
|
@ -4946,11 +4992,7 @@ static void Tst_GetQstDataFromDB (char *Stem,char *Feedback)
|
|||
}
|
||||
|
||||
/* Copy image */
|
||||
if (row[3][0])
|
||||
{
|
||||
Gbl.Test.Answer.Options[NumOpt].Image.Status = Img_NAME_STORED_IN_DB;
|
||||
Img_GetImageNameAndTitle (row[3],row[4],&Gbl.Test.Answer.Options[NumOpt].Image);
|
||||
}
|
||||
Img_GetImageNameAndTitleFromRow (row[3],row[4],&Gbl.Test.Answer.Options[NumOpt].Image);
|
||||
|
||||
Gbl.Test.Answer.Options[NumOpt].Correct = (Str_ConvertToUpperLetter (row[5][0]) == 'Y');
|
||||
break;
|
||||
|
@ -4991,7 +5033,7 @@ static void Tst_GetImageFromDB (unsigned NumOpt,struct Image *Image)
|
|||
row = mysql_fetch_row (mysql_res);
|
||||
|
||||
/***** Get the image name (row[0]) *****/
|
||||
Img_GetImageNameAndTitle (row[0],row[1],Image);
|
||||
Img_GetImageNameAndTitleFromRow (row[0],row[1],Image);
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
|
@ -5040,11 +5082,11 @@ void Tst_ReceiveQst (void)
|
|||
char Stem[Cns_MAX_BYTES_TEXT+1];
|
||||
char Feedback[Cns_MAX_BYTES_TEXT+1];
|
||||
|
||||
/***** Initialize new question to zero *****/
|
||||
Tst_InitQst ();
|
||||
Stem[0] = Feedback[0] = '\0';
|
||||
/***** Create test question *****/
|
||||
Tst_QstConstructor ();
|
||||
|
||||
/***** Get parameters of the question from form *****/
|
||||
Stem[0] = Feedback[0] = '\0';
|
||||
Tst_GetQstFromForm (Stem,Feedback);
|
||||
|
||||
/***** Make sure that tags, text and answer are not empty *****/
|
||||
|
@ -5068,8 +5110,8 @@ void Tst_ReceiveQst (void)
|
|||
Tst_PutFormEditOneQst (Stem,Feedback);
|
||||
}
|
||||
|
||||
/***** Free answers *****/
|
||||
Tst_FreeTextChoiceAnswers ();
|
||||
/***** Destroy test question *****/
|
||||
Tst_QstDestructor ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -5094,7 +5136,7 @@ static void Tst_GetQstFromForm (char *Stem,char *Feedback)
|
|||
char ParamTitle[32];
|
||||
|
||||
/***** Get question code *****/
|
||||
Tst_GetQstCod ();
|
||||
Gbl.Test.QstCod = Tst_GetQstCod ();
|
||||
|
||||
/***** Get answer type *****/
|
||||
Par_GetParToText ("AnswerType",UnsignedStr,10);
|
||||
|
@ -5645,7 +5687,8 @@ void Tst_RequestRemoveQst (void)
|
|||
|
||||
/***** Get main parameters from form *****/
|
||||
/* Get the question code */
|
||||
if (!Tst_GetQstCod ())
|
||||
Gbl.Test.QstCod = Tst_GetQstCod ();
|
||||
if (Gbl.Test.QstCod <= 0)
|
||||
Lay_ShowErrorAndExit ("Wrong code of question.");
|
||||
|
||||
/* Get a parameter that indicates whether it's necessary
|
||||
|
@ -5697,7 +5740,8 @@ void Tst_RemoveQst (void)
|
|||
bool EditingOnlyThisQst;
|
||||
|
||||
/***** Get the question code *****/
|
||||
if (!Tst_GetQstCod ())
|
||||
Gbl.Test.QstCod = Tst_GetQstCod ();
|
||||
if (Gbl.Test.QstCod <= 0)
|
||||
Lay_ShowErrorAndExit ("Wrong code of question.");
|
||||
|
||||
/***** Get a parameter that indicates whether it's necessary
|
||||
|
@ -5749,7 +5793,8 @@ void Tst_ChangeShuffleQst (void)
|
|||
bool Shuffle;
|
||||
|
||||
/***** Get the question code *****/
|
||||
if (!Tst_GetQstCod ())
|
||||
Gbl.Test.QstCod = Tst_GetQstCod ();
|
||||
if (Gbl.Test.QstCod <= 0)
|
||||
Lay_ShowErrorAndExit ("Wrong code of question.");
|
||||
|
||||
/***** Get a parameter that indicates whether it's necessary to continue listing the rest of questions ******/
|
||||
|
@ -5787,14 +5832,12 @@ void Tst_ChangeShuffleQst (void)
|
|||
/************ Get the parameter with the code of a test question *************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static bool Tst_GetQstCod (void)
|
||||
static long Tst_GetQstCod (void)
|
||||
{
|
||||
char LongStr[1+10+1];
|
||||
|
||||
Par_GetParToText ("QstCod",LongStr,1+10);
|
||||
if ((Gbl.Test.QstCod = Str_ConvertStrCodToLongCod (LongStr)) < 0)
|
||||
return false;
|
||||
return true;
|
||||
return Str_ConvertStrCodToLongCod (LongStr);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -5825,9 +5868,10 @@ static void Tst_InsertOrUpdateQstIntoDB (void)
|
|||
char *Query;
|
||||
|
||||
/***** Allocate space for query *****/
|
||||
if ((Query = malloc (256 +
|
||||
if ((Query = malloc (512 +
|
||||
Gbl.Test.Stem.Length +
|
||||
Gbl.Test.Feedback.Length)) == NULL)
|
||||
Gbl.Test.Feedback.Length +
|
||||
Img_MAX_BYTES_TITLE)) == NULL)
|
||||
Lay_ShowErrorAndExit ("Not enough memory to store database query.");
|
||||
|
||||
if (Gbl.Test.QstCod < 0) // It's a new question
|
||||
|
@ -6144,64 +6188,6 @@ static void Tst_RemoveImgFilesFromAnsOfQsts (long CrsCod,
|
|||
DB_FreeMySQLResult (&mysql_res);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************* Allocate memory for a choice answer *********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
int Tst_AllocateTextChoiceAnswer (unsigned NumOpt)
|
||||
{
|
||||
Tst_FreeTextChoiceAnswer (NumOpt);
|
||||
|
||||
if ((Gbl.Test.Answer.Options[NumOpt].Text =
|
||||
malloc (Tst_MAX_BYTES_ANSWER_OR_FEEDBACK + 1)) == NULL)
|
||||
{
|
||||
sprintf (Gbl.Message,"Not enough memory to store answer.");
|
||||
return 0;
|
||||
}
|
||||
if ((Gbl.Test.Answer.Options[NumOpt].Feedback =
|
||||
malloc (Tst_MAX_BYTES_ANSWER_OR_FEEDBACK + 1)) == NULL)
|
||||
{
|
||||
sprintf (Gbl.Message,"Not enough memory to store feedback.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Gbl.Test.Answer.Options[NumOpt].Text[0] =
|
||||
Gbl.Test.Answer.Options[NumOpt].Feedback[0] = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************** Free memory of all choice answers **********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void Tst_FreeTextChoiceAnswers (void)
|
||||
{
|
||||
unsigned NumOpt;
|
||||
|
||||
for (NumOpt = 0;
|
||||
NumOpt < Tst_MAX_OPTIONS_PER_QUESTION;
|
||||
NumOpt++)
|
||||
Tst_FreeTextChoiceAnswer (NumOpt);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/********************** Free memory of a choice answer ***********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Tst_FreeTextChoiceAnswer (unsigned NumOpt)
|
||||
{
|
||||
if (Gbl.Test.Answer.Options[NumOpt].Text)
|
||||
{
|
||||
free ((void *) Gbl.Test.Answer.Options[NumOpt].Text);
|
||||
Gbl.Test.Answer.Options[NumOpt].Text = NULL;
|
||||
}
|
||||
if (Gbl.Test.Answer.Options[NumOpt].Feedback)
|
||||
{
|
||||
free ((void *) Gbl.Test.Answer.Options[NumOpt].Feedback);
|
||||
Gbl.Test.Answer.Options[NumOpt].Feedback = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*********************** Get stats about test questions **********************/
|
||||
/*****************************************************************************/
|
||||
|
|
|
@ -141,7 +141,12 @@ void Tst_GetConfigFromRow (MYSQL_ROW row);
|
|||
bool Tst_CheckIfCourseHaveTestsAndPluggableIsUnknown (void);
|
||||
void Tst_ReceiveConfigTst (void);
|
||||
void Tst_ShowFormEditOneQst (void);
|
||||
void Tst_InitQst (void);
|
||||
|
||||
void Tst_QstConstructor (void);
|
||||
void Tst_QstDestructor (void);
|
||||
|
||||
int Tst_AllocateTextChoiceAnswer (unsigned NumOpt);
|
||||
|
||||
Tst_AnswerType_t Tst_ConvertFromStrAnsTypDBToAnsTyp (const char *StrAnsTypeBD);
|
||||
void Tst_ReceiveQst (void);
|
||||
bool Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (void);
|
||||
|
@ -152,8 +157,6 @@ void Tst_RemoveQst (void);
|
|||
void Tst_ChangeShuffleQst (void);
|
||||
void Tst_InsertOrUpdateQstTagsAnsIntoDB (void);
|
||||
|
||||
int Tst_AllocateTextChoiceAnswer (unsigned NumOpt);
|
||||
void Tst_FreeTextChoiceAnswers (void);
|
||||
void Tst_FreeTagsList (void);
|
||||
|
||||
void Tst_GetTestStats (Tst_AnswerType_t AnsType,struct Tst_Stats *Stats);
|
||||
|
|
|
@ -533,8 +533,8 @@ static void TsI_ImportQuestionsFromXMLBuffer (const char *XMLBuffer)
|
|||
{
|
||||
if (!strcmp (QuestionElem->TagName,"question"))
|
||||
{
|
||||
/***** Initialize new question to zero *****/
|
||||
Tst_InitQst ();
|
||||
/***** Create test question *****/
|
||||
Tst_QstConstructor ();
|
||||
|
||||
/* Get type of questions (in mandatory attribute "type") */
|
||||
AnswerTypeFound = false;
|
||||
|
@ -653,8 +653,8 @@ static void TsI_ImportQuestionsFromXMLBuffer (const char *XMLBuffer)
|
|||
}
|
||||
}
|
||||
|
||||
/***** Free answers *****/
|
||||
Tst_FreeTextChoiceAnswers ();
|
||||
/***** Destroy test question *****/
|
||||
Tst_QstDestructor ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue