Version 15.196

This commit is contained in:
Antonio Cañas Vargas 2016-04-15 02:33:16 +02:00
parent 9904b174e8
commit 7cafe043f1
8 changed files with 208 additions and 128 deletions

View File

@ -137,13 +137,14 @@
/****************************** Public constants *****************************/ /****************************** Public constants *****************************/
/*****************************************************************************/ /*****************************************************************************/
#define Log_PLATFORM_VERSION "SWAD 15.195.1 (2016-04-15)" #define Log_PLATFORM_VERSION "SWAD 15.196 (2016-04-15)"
#define CSS_FILE "swad15.193.css" #define CSS_FILE "swad15.193.css"
#define JS_FILE "swad15.193.js" #define JS_FILE "swad15.193.js"
// Number of lines (includes comments but not blank lines) has been got with the following command: // 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 // nl swad*.c swad*.h css/swad*.css py/swad*.py js/swad*.js soap/swad*.h sql/swad*.sql | tail -1
/* /*
Version 15.196: Apr 15, 2016 Changes related to image URL. (199467 lines)
Version 15.195.1: Apr 15, 2016 New fields in images to store URL when a user click in the image. (199390 lines) Version 15.195.1: Apr 15, 2016 New fields in images to store URL when a user click in the image. (199390 lines)
7 changes necessary in database: 7 changes necessary in database:
ALTER TABLE tst_questions ADD COLUMN ImageURL VARCHAR(255) NOT NULL AFTER ImageTitle; ALTER TABLE tst_questions ADD COLUMN ImageURL VARCHAR(255) NOT NULL AFTER ImageTitle;

View File

@ -466,11 +466,14 @@ static long For_InsertForumPst (long ThrCod,long UsrCod,
/***** Insert forum post in the database *****/ /***** Insert forum post in the database *****/
sprintf (Query,"INSERT INTO forum_post" sprintf (Query,"INSERT INTO forum_post"
" (ThrCod,UsrCod,CreatTime,ModifTime,NumNotif," " (ThrCod,UsrCod,CreatTime,ModifTime,NumNotif,"
"Subject,Content,ImageName,ImageTitle)" "Subject,Content,ImageName,ImageTitle,ImageURL)"
" VALUES ('%ld','%ld',NOW(),NOW(),'0'," " VALUES ('%ld','%ld',NOW(),NOW(),'0',"
"'%s','%s','%s','%s')", "'%s','%s','%s','%s','%s')",
ThrCod,UsrCod, ThrCod,UsrCod,
Subject,Content,Image->Name,Image->Title ? Image->Title : ""); Subject,Content,
Image->Name,
Image->Title ? Image->Title : "",
Image->URL ? Image->URL : "");
PstCod = DB_QueryINSERTandReturnCode (Query,"can not create a new post in a forum"); PstCod = DB_QueryINSERTandReturnCode (Query,"can not create a new post in a forum");
/***** Free space used for query *****/ /***** Free space used for query *****/
@ -1332,7 +1335,7 @@ static void For_GetPstData (long PstCod,long *UsrCod,time_t *CreatTimeUTC,
/***** Get data of a post from database *****/ /***** Get data of a post from database *****/
sprintf (Query,"SELECT UsrCod,UNIX_TIMESTAMP(CreatTime)," sprintf (Query,"SELECT UsrCod,UNIX_TIMESTAMP(CreatTime),"
"Subject,Content,ImageName,ImageTitle" "Subject,Content,ImageName,ImageTitle,ImageURL"
" FROM forum_post WHERE PstCod='%ld'", " FROM forum_post WHERE PstCod='%ld'",
PstCod); PstCod);
NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get data of a post"); NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get data of a post");
@ -1358,8 +1361,8 @@ static void For_GetPstData (long PstCod,long *UsrCod,time_t *CreatTimeUTC,
strncpy (Content,row[3],Cns_MAX_BYTES_LONG_TEXT); strncpy (Content,row[3],Cns_MAX_BYTES_LONG_TEXT);
Content[Cns_MAX_BYTES_LONG_TEXT] = '\0'; Content[Cns_MAX_BYTES_LONG_TEXT] = '\0';
/****** Get image name (row[4]) and title (row[5]) *****/ /****** Get image name (row[4]), title (row[5]) and URL (row[6]) *****/
Img_GetImageNameAndTitleFromRow (row[4],row[5],Image); Img_GetImageNameTitleAndURLFromRow (row[4],row[5],row[6],Image);
/***** Free structure that stores the query result *****/ /***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res); DB_FreeMySQLResult (&mysql_res);

View File

@ -76,15 +76,16 @@ static void Img_ProcessImage (struct Image *Image,
void Img_ImageConstructor (struct Image *Image) void Img_ImageConstructor (struct Image *Image)
{ {
Img_ResetImageExceptTitle (Image); Img_ResetImageExceptTitleAndURL (Image);
Image->Title = NULL; Image->Title = NULL;
Image->URL = NULL;
} }
/*****************************************************************************/ /*****************************************************************************/
/********************* Reset image fields except title ***********************/ /***************** Reset image fields except title and URL *******************/
/*****************************************************************************/ /*****************************************************************************/
void Img_ResetImageExceptTitle (struct Image *Image) void Img_ResetImageExceptTitleAndURL (struct Image *Image)
{ {
Image->Action = Img_ACTION_NO_IMAGE; Image->Action = Img_ACTION_NO_IMAGE;
Image->Status = Img_FILE_NONE; Image->Status = Img_FILE_NONE;
@ -98,14 +99,14 @@ void Img_ResetImageExceptTitle (struct Image *Image)
void Img_ImageDestructor (struct Image *Image) void Img_ImageDestructor (struct Image *Image)
{ {
Img_FreeImageTitle (Image); Img_FreeImageTitleAndURL (Image);
} }
/*****************************************************************************/ /*****************************************************************************/
/*************************** Reset image title *******************************/ /*********************** Reset image title and URL ***************************/
/*****************************************************************************/ /*****************************************************************************/
void Img_FreeImageTitle (struct Image *Image) void Img_FreeImageTitleAndURL (struct Image *Image)
{ {
// Image->Title must be initialized to NULL after declaration // Image->Title must be initialized to NULL after declaration
if (Image->Title) if (Image->Title)
@ -113,14 +114,22 @@ void Img_FreeImageTitle (struct Image *Image)
free ((void *) Image->Title); free ((void *) Image->Title);
Image->Title = NULL; Image->Title = NULL;
} }
// Image->URL must be initialized to NULL after declaration
if (Image->URL)
{
free ((void *) Image->URL);
Image->URL = NULL;
}
} }
/*****************************************************************************/ /*****************************************************************************/
/****** Get image name and title from a query result and copy to struct ******/ /**** Get image name, title and URL from a query result and copy to struct ***/
/*****************************************************************************/ /*****************************************************************************/
void Img_GetImageNameAndTitleFromRow (const char *Name,const char *Title, void Img_GetImageNameTitleAndURLFromRow (const char *Name,
struct Image *Image) const char *Title,
const char *URL,
struct Image *Image)
{ {
size_t Length; size_t Length;
@ -132,23 +141,37 @@ void Img_GetImageNameAndTitleFromRow (const char *Name,const char *Title,
Image->Status = Image->Name[0] ? Img_NAME_STORED_IN_DB : Image->Status = Image->Name[0] ? Img_NAME_STORED_IN_DB :
Img_FILE_NONE; Img_FILE_NONE;
/***** Copy image title to struct *****/
// Image->Title can be empty or filled with a previous title /***** Copy image title and URL to struct *****/
// Image->Title and Image->URL can be empty or filled with previous values
// If filled ==> free it // If filled ==> free it
Img_FreeImageTitle (Image); Img_FreeImageTitleAndURL (Image);
if (Title[0]) if (Title[0])
{ {
/* Get and limit length of the title */ /* Get and limit length of the title */
Length = strlen (Title); Length = strlen (Title);
if (Length > Img_MAX_BYTES_TITLE) if (Length > Img_MAX_BYTES_TITLE)
Length = Img_MAX_BYTES_TITLE; Length = Img_MAX_BYTES_TITLE;
if ((Image->Title = (char *) malloc (Length+1)) == NULL) if ((Image->Title = (char *) malloc (Length+1)) == NULL)
Lay_ShowErrorAndExit ("Error allocating memory for image title."); Lay_ShowErrorAndExit ("Error allocating memory for image title.");
strncpy (Image->Title,Title,Length); strncpy (Image->Title,Title,Length);
Image->Title[Length] = '\0'; Image->Title[Length] = '\0';
} }
if (URL[0])
{
/* Get and limit length of the URL */
Length = strlen (URL);
if (Length > Img_MAX_BYTES_TITLE)
Length = Img_MAX_BYTES_TITLE;
if ((Image->URL = (char *) malloc (Length+1)) == NULL)
Lay_ShowErrorAndExit ("Error allocating memory for image URL.");
strncpy (Image->URL,URL,Length);
Image->URL[Length] = '\0';
}
} }
/*****************************************************************************/ /*****************************************************************************/
@ -263,7 +286,7 @@ void Img_GetImageFromForm (int NumImgInForm,struct Image *Image,
{ {
/* Overwrite current title (empty or coming from database) /* Overwrite current title (empty or coming from database)
with the title coming from the form */ with the title coming from the form */
Img_FreeImageTitle (Image); Img_FreeImageTitleAndURL (Image);
if ((Image->Title = (char *) malloc (Length + 1)) == NULL) if ((Image->Title = (char *) malloc (Length + 1)) == NULL)
Lay_ShowErrorAndExit ("Error allocating memory for image title."); Lay_ShowErrorAndExit ("Error allocating memory for image title.");
strncpy (Image->Title,Title,Length); strncpy (Image->Title,Title,Length);

View File

@ -89,6 +89,9 @@ struct Image
char Name[Cry_LENGTH_ENCRYPTED_STR_SHA256_BASE64+1]; char Name[Cry_LENGTH_ENCRYPTED_STR_SHA256_BASE64+1];
char *Title; // Title/attribution (it must be initialized to NULL char *Title; // Title/attribution (it must be initialized to NULL
// in order to not trying to free it when no memory allocated) // in order to not trying to free it when no memory allocated)
char *URL; // URL, i.e. link to original big photo or video
// (it must be initialized to NULL
// in order to not trying to free it when no memory allocated)
unsigned Width; unsigned Width;
unsigned Height; unsigned Height;
unsigned Quality; unsigned Quality;
@ -107,12 +110,14 @@ struct ParamUploadImg
/*****************************************************************************/ /*****************************************************************************/
void Img_ImageConstructor (struct Image *Image); void Img_ImageConstructor (struct Image *Image);
void Img_ResetImageExceptTitle (struct Image *Image); void Img_ResetImageExceptTitleAndURL (struct Image *Image);
void Img_ImageDestructor (struct Image *Image); void Img_ImageDestructor (struct Image *Image);
void Img_FreeImageTitle (struct Image *Image); void Img_FreeImageTitleAndURL (struct Image *Image);
void Img_GetImageNameAndTitleFromRow (const char *Name,const char *Title, void Img_GetImageNameTitleAndURLFromRow (const char *Name,
struct Image *Image); const char *Title,
const char *URL,
struct Image *Image);
void Img_PutImageUploader (int NumImgInForm,const char *ClassImgTit); void Img_PutImageUploader (int NumImgInForm,const char *ClassImgTit);
void Img_GetImageFromForm (int NumImgInForm,struct Image *Image, void Img_GetImageFromForm (int NumImgInForm,struct Image *Image,

View File

@ -1355,9 +1355,12 @@ static long Msg_InsertNewMsg (const char *Subject,const char *Content,
/***** Insert message subject and content in the database *****/ /***** Insert message subject and content in the database *****/
sprintf (Query,"INSERT INTO msg_content" sprintf (Query,"INSERT INTO msg_content"
" (Subject,Content,ImageName,ImageTitle)" " (Subject,Content,ImageName,ImageTitle,ImageURL)"
" VALUES ('%s','%s','%s','%s')", " VALUES ('%s','%s','%s','%s','%s')",
Subject,Content,Image->Name,Image->Title ? Image->Title : ""); Subject,Content,
Image->Name,
Image->Title ? Image->Title : "",
Image->URL ? Image->URL : "");
MsgCod = DB_QueryINSERTandReturnCode (Query,"can not create message"); MsgCod = DB_QueryINSERTandReturnCode (Query,"can not create message");
/***** Insert message in sent messages *****/ /***** Insert message in sent messages *****/
@ -1550,8 +1553,8 @@ static void Msg_MoveMsgContentToDeleted (long MsgCod)
/***** Move message from msg_content to msg_content_deleted *****/ /***** Move message from msg_content to msg_content_deleted *****/
/* Insert message content into msg_content_deleted */ /* Insert message content into msg_content_deleted */
sprintf (Query,"INSERT IGNORE INTO msg_content_deleted" sprintf (Query,"INSERT IGNORE INTO msg_content_deleted"
" (MsgCod,Subject,Content,ImageName,ImageTitle)" " (MsgCod,Subject,Content,ImageName,ImageTitle,ImageURL)"
" SELECT MsgCod,Subject,Content,ImageName,ImageTitle" " SELECT MsgCod,Subject,Content,ImageName,ImageTitle,ImageURL"
" FROM msg_content WHERE MsgCod='%ld'", " FROM msg_content WHERE MsgCod='%ld'",
MsgCod); MsgCod);
DB_QueryINSERT (Query,"can not remove the content of a message"); DB_QueryINSERT (Query,"can not remove the content of a message");
@ -2704,7 +2707,7 @@ static void Msg_GetMsgContent (long MsgCod,char *Content,struct Image *Image)
unsigned long NumRows; unsigned long NumRows;
/***** Get content of message from database *****/ /***** Get content of message from database *****/
sprintf (Query,"SELECT Content,ImageName,ImageTitle" sprintf (Query,"SELECT Content,ImageName,ImageTitle,ImageURL"
" FROM msg_content WHERE MsgCod='%ld'", " FROM msg_content WHERE MsgCod='%ld'",
MsgCod); MsgCod);
NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get the content of a message"); NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get the content of a message");
@ -2720,8 +2723,8 @@ static void Msg_GetMsgContent (long MsgCod,char *Content,struct Image *Image)
strncpy (Content,row[0],Cns_MAX_BYTES_LONG_TEXT); strncpy (Content,row[0],Cns_MAX_BYTES_LONG_TEXT);
Content[Cns_MAX_BYTES_LONG_TEXT] = '\0'; Content[Cns_MAX_BYTES_LONG_TEXT] = '\0';
/****** Get image name (row[1]) and title (row[2]) *****/ /****** Get image name (row[1]), title (row[2]) and URL (row[3]) *****/
Img_GetImageNameAndTitleFromRow (row[1],row[2],Image); Img_GetImageNameTitleAndURLFromRow (row[1],row[2],row[3],Image);
/***** Free structure that stores the query result *****/ /***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res); DB_FreeMySQLResult (&mysql_res);

View File

@ -1456,7 +1456,7 @@ static void Soc_GetAndWriteSocialPost (long PstCod)
Img_ImageConstructor (&Image); Img_ImageConstructor (&Image);
/***** Get social post from database *****/ /***** Get social post from database *****/
sprintf (Query,"SELECT Content,ImageName,ImageTitle" sprintf (Query,"SELECT Content,ImageName,ImageTitle,ImageURL"
" FROM social_posts WHERE PstCod='%ld'", " FROM social_posts WHERE PstCod='%ld'",
PstCod); PstCod);
NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get the content of a social post"); NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get the content of a social post");
@ -1470,8 +1470,8 @@ static void Soc_GetAndWriteSocialPost (long PstCod)
strncpy (Content,row[0],Cns_MAX_BYTES_LONG_TEXT); strncpy (Content,row[0],Cns_MAX_BYTES_LONG_TEXT);
Content[Cns_MAX_BYTES_LONG_TEXT] = '\0'; Content[Cns_MAX_BYTES_LONG_TEXT] = '\0';
/****** Get image name (row[1]) and title (row[2]) *****/ /****** Get image name (row[1]), title (row[2]) and URL (row[3]) *****/
Img_GetImageNameAndTitleFromRow (row[1],row[2],&Image); Img_GetImageNameTitleAndURLFromRow (row[1],row[2],row[3],&Image);
} }
else else
Content[0] = '\0'; Content[0] = '\0';
@ -2111,12 +2111,14 @@ static long Soc_ReceiveSocialPost (void)
/***** Publish *****/ /***** Publish *****/
/* Insert post content in the database */ /* Insert post content in the database */
sprintf (Query,"INSERT INTO social_posts (Content,ImageName,ImageTitle)" sprintf (Query,"INSERT INTO social_posts (Content,ImageName,ImageTitle,ImageURL)"
" VALUES ('%s','%s','%s')", " VALUES ('%s','%s','%s','%s')",
Content, Content,
Image.Name, Image.Name,
(Image.Name[0] && // Save image title only if image attached (Image.Name[0] && // Save image title only if image attached
Image.Title) ? Image.Title : ""); Image.Title) ? Image.Title : "",
(Image.Name[0] && // Save image URL only if image attached
Image.URL ) ? Image.URL : "");
PstCod = DB_QueryINSERTandReturnCode (Query,"can not create post"); PstCod = DB_QueryINSERTandReturnCode (Query,"can not create post");
/* Insert post in social notes */ /* Insert post in social notes */
@ -2263,7 +2265,9 @@ static void Soc_WriteCommentsInSocialNote (const struct SocialNote *SocNot)
"social_pubs.NotCod," "social_pubs.NotCod,"
"UNIX_TIMESTAMP(social_pubs.TimePublish)," "UNIX_TIMESTAMP(social_pubs.TimePublish),"
"social_comments.Content," "social_comments.Content,"
"social_comments.ImageName,social_comments.ImageTitle" "social_comments.ImageName,"
"social_comments.ImageTitle,"
"social_comments.ImageURL"
" FROM social_pubs,social_comments" " FROM social_pubs,social_comments"
" WHERE social_pubs.NotCod='%ld'" " WHERE social_pubs.NotCod='%ld'"
" AND social_pubs.PubType='%u'" " AND social_pubs.PubType='%u'"
@ -2873,13 +2877,15 @@ static long Soc_ReceiveComment (void)
/* Insert comment content in the database */ /* Insert comment content in the database */
sprintf (Query,"INSERT INTO social_comments" sprintf (Query,"INSERT INTO social_comments"
" (PubCod,Content,ImageName,ImageTitle)" " (PubCod,Content,ImageName,ImageTitle,ImageURL)"
" VALUES ('%ld','%s','%s','%s')", " VALUES ('%ld','%s','%s','%s','%s')",
SocPub.PubCod, SocPub.PubCod,
Content, Content,
Image.Name, Image.Name,
(Image.Name[0] && // Save image title only if image attached (Image.Name[0] && // Save image title only if image attached
Image.Title) ? Image.Title : ""); Image.Title) ? Image.Title : "",
(Image.Name[0] && // Save image URL only if image attached
Image.URL ) ? Image.URL : "");
DB_QueryINSERT (Query,"can not store comment content"); DB_QueryINSERT (Query,"can not store comment content");
/***** Free space used for query *****/ /***** Free space used for query *****/
@ -4375,7 +4381,9 @@ static void Soc_GetDataOfSocialComByCod (struct SocialComment *SocCom)
"social_pubs.NotCod," "social_pubs.NotCod,"
"UNIX_TIMESTAMP(social_pubs.TimePublish)," "UNIX_TIMESTAMP(social_pubs.TimePublish),"
"social_comments.Content," "social_comments.Content,"
"social_comments.ImageName,social_comments.ImageTitle" "social_comments.ImageName,"
"social_comments.ImageTitle,"
"social_comments.ImageURL,"
" FROM social_pubs,social_comments" " FROM social_pubs,social_comments"
" WHERE social_pubs.PubCod='%ld'" " WHERE social_pubs.PubCod='%ld'"
" AND social_pubs.PubType='%u'" " AND social_pubs.PubType='%u'"
@ -4508,6 +4516,7 @@ static void Soc_GetDataOfSocialCommentFromRow (MYSQL_ROW row,struct SocialCommen
row[4]: Content row[4]: Content
row[5]: ImageName row[5]: ImageName
row[6]: ImageTitle row[6]: ImageTitle
row[7]: ImageURL
*/ */
/***** Get code of social comment (row[0]) *****/ /***** Get code of social comment (row[0]) *****/
SocCom->PubCod = Str_ConvertStrCodToLongCod (row[0]); SocCom->PubCod = Str_ConvertStrCodToLongCod (row[0]);
@ -4528,8 +4537,8 @@ static void Soc_GetDataOfSocialCommentFromRow (MYSQL_ROW row,struct SocialCommen
/***** Get number of times this comment has been favourited *****/ /***** Get number of times this comment has been favourited *****/
SocCom->NumFavs = Soc_GetNumTimesACommHasBeenFav (SocCom); SocCom->NumFavs = Soc_GetNumTimesACommHasBeenFav (SocCom);
/****** Get image name (row[5]) and title (row[6]) *****/ /****** Get image name (row[5]), title (row[6]) and URL (row[7]) *****/
Img_GetImageNameAndTitleFromRow (row[5],row[6],&SocCom->Image); Img_GetImageNameTitleAndURLFromRow (row[5],row[6],row[7],&SocCom->Image);
} }
/*****************************************************************************/ /*****************************************************************************/

View File

@ -911,9 +911,10 @@ static void Tst_ShowTstResultAfterAssess (long TstCod,unsigned *NumQstsNotBlank,
row[ 5] Feedback row[ 5] Feedback
row[ 6] ImageName row[ 6] ImageName
row[ 7] ImageTitle row[ 7] ImageTitle
row[ 8] NumHits row[ 8] ImageURL
row[ 9] NumHitsNotBlank row[ 9] NumHits
row[10] Score row[10] NumHitsNotBlank
row[11] Score
*/ */
/***** Get the code of question (row[0]) *****/ /***** Get the code of question (row[0]) *****/
@ -973,9 +974,10 @@ static void Tst_WriteQstAndAnsExam (unsigned NumQst,long QstCod,MYSQL_ROW row,
row[ 5] Feedback row[ 5] Feedback
row[ 6] ImageName row[ 6] ImageName
row[ 7] ImageTitle row[ 7] ImageTitle
row[ 8] NumHits row[ 8] ImageURL
row[ 9] NumHitsNotBlank row[ 9] NumHits
row[10] Score row[10] NumHitsNotBlank
row[11] Score
*/ */
/***** Create test question *****/ /***** Create test question *****/
@ -995,12 +997,12 @@ static void Tst_WriteQstAndAnsExam (unsigned NumQst,long QstCod,MYSQL_ROW row,
"</td>", "</td>",
Txt_TST_STR_ANSWER_TYPES[Gbl.Test.AnswerType]); Txt_TST_STR_ANSWER_TYPES[Gbl.Test.AnswerType]);
/***** Write stem (row[4]), image (row[6], row[7]), /***** Write stem (row[4]), image (row[6], row[7], row[8]),
answers depending on shuffle (row[3]) and feedback (row[5]) *****/ answers depending on shuffle (row[3]) and feedback (row[5]) *****/
fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP COLOR%u\">", fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP COLOR%u\">",
Gbl.RowEvenOdd); Gbl.RowEvenOdd);
Tst_WriteQstStem (row[4],"TEST_EXA"); Tst_WriteQstStem (row[4],"TEST_EXA");
Img_GetImageNameAndTitleFromRow (row[6],row[7],&Gbl.Test.Image); Img_GetImageNameTitleAndURLFromRow (row[6],row[7],row[8],&Gbl.Test.Image);
Img_ShowImage (&Gbl.Test.Image,"TEST_IMG_SHOW_STEM"); Img_ShowImage (&Gbl.Test.Image,"TEST_IMG_SHOW_STEM");
if (Gbl.Action.Act == ActSeeTst) if (Gbl.Action.Act == ActSeeTst)
@ -2294,15 +2296,18 @@ static unsigned long Tst_GetQuestionsForEdit (MYSQL_RES **mysql_res)
row[ 5] Feedback row[ 5] Feedback
row[ 6] ImageName row[ 6] ImageName
row[ 7] ImageTitle row[ 7] ImageTitle
row[ 8] NumHits row[ 8] ImageURL
row[ 9] NumHitsNotBlank row[ 9] NumHits
row[10] Score row[10] NumHitsNotBlank
row[11] Score
*/ */
sprintf (Query,"SELECT tst_questions.QstCod," sprintf (Query,"SELECT tst_questions.QstCod,"
"UNIX_TIMESTAMP(tst_questions.EditTime) AS F," "UNIX_TIMESTAMP(tst_questions.EditTime) AS F,"
"tst_questions.AnsType,tst_questions.Shuffle," "tst_questions.AnsType,tst_questions.Shuffle,"
"tst_questions.Stem,tst_questions.Feedback," "tst_questions.Stem,tst_questions.Feedback,"
"tst_questions.ImageName,tst_questions.ImageTitle," "tst_questions.ImageName,"
"tst_questions.ImageTitle,"
"tst_questions.ImageURL,"
"tst_questions.NumHits,tst_questions.NumHitsNotBlank," "tst_questions.NumHits,tst_questions.NumHitsNotBlank,"
"tst_questions.Score" "tst_questions.Score"
" FROM tst_questions"); " FROM tst_questions");
@ -2432,9 +2437,10 @@ static unsigned long Tst_GetQuestionsForExam (MYSQL_RES **mysql_res)
row[ 5] Feedback row[ 5] Feedback
row[ 6] ImageName row[ 6] ImageName
row[ 7] ImageTitle row[ 7] ImageTitle
row[ 8] NumHits row[ 8] ImageURL
row[ 9] NumHitsNotBlank row[ 9] NumHits
row[10] Score row[10] NumHitsNotBlank
row[11] Score
*/ */
/* Start query */ /* Start query */
// Reject questions with any tag hidden // Reject questions with any tag hidden
@ -2444,7 +2450,9 @@ static unsigned long Tst_GetQuestionsForExam (MYSQL_RES **mysql_res)
"UNIX_TIMESTAMP(tst_questions.EditTime)," "UNIX_TIMESTAMP(tst_questions.EditTime),"
"tst_questions.AnsType,tst_questions.Shuffle," "tst_questions.AnsType,tst_questions.Shuffle,"
"tst_questions.Stem,tst_questions.Feedback," "tst_questions.Stem,tst_questions.Feedback,"
"tst_questions.ImageName,tst_questions.ImageTitle," "tst_questions.ImageName,"
"tst_questions.ImageTitle,"
"tst_questions.ImageURL,"
"tst_questions.NumHits,tst_questions.NumHitsNotBlank," "tst_questions.NumHits,tst_questions.NumHitsNotBlank,"
"tst_questions.Score" "tst_questions.Score"
" FROM tst_questions,tst_question_tags,tst_tags" " FROM tst_questions,tst_question_tags,tst_tags"
@ -2556,12 +2564,14 @@ static bool Tst_GetOneQuestionByCod (long QstCod,MYSQL_RES **mysql_res)
row[ 5] Feedback row[ 5] Feedback
row[ 6] ImageName row[ 6] ImageName
row[ 7] ImageTitle row[ 7] ImageTitle
row[ 8] NumHits row[ 8] ImageURL
row[ 9] NumHitsNotBlank row[ 9] NumHits
row[10] Score row[10] NumHitsNotBlank
row[11] Score
*/ */
sprintf (Query,"SELECT QstCod,UNIX_TIMESTAMP(EditTime)," sprintf (Query,"SELECT QstCod,UNIX_TIMESTAMP(EditTime),"
"AnsType,Shuffle,Stem,Feedback,ImageName,ImageTitle," "AnsType,Shuffle,Stem,Feedback,"
"ImageName,ImageTitle,ImageURL,"
"NumHits,NumHitsNotBlank,Score" "NumHits,NumHitsNotBlank,Score"
" FROM tst_questions" " FROM tst_questions"
" WHERE QstCod='%ld'", " WHERE QstCod='%ld'",
@ -2676,9 +2686,10 @@ static void Tst_ListOneOrMoreQuestionsToEdit (unsigned long NumRows,MYSQL_RES *m
row[ 5] Feedback row[ 5] Feedback
row[ 6] ImageName row[ 6] ImageName
row[ 7] ImageTitle row[ 7] ImageTitle
row[ 8] NumHits row[ 8] ImageURL
row[ 9] NumHitsNotBlank row[ 9] NumHits
row[10] Score row[10] NumHitsNotBlank
row[11] Score
*/ */
/***** Create test question *****/ /***** Create test question *****/
Tst_QstConstructor (); Tst_QstConstructor ();
@ -2772,12 +2783,12 @@ static void Tst_ListOneOrMoreQuestionsToEdit (unsigned long NumRows,MYSQL_RES *m
} }
fprintf (Gbl.F.Out,"</td>"); fprintf (Gbl.F.Out,"</td>");
/* Write the stem (row[4]), the image (row[6], row[7]), /* Write the stem (row[4]), the image (row[6], row[7], row[8]),
the feedback (row[5]) and the answers */ the feedback (row[5]) and the answers */
fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP COLOR%u\">", fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP COLOR%u\">",
Gbl.RowEvenOdd); Gbl.RowEvenOdd);
Tst_WriteQstStem (row[4],"TEST_EDI"); Tst_WriteQstStem (row[4],"TEST_EDI");
Img_GetImageNameAndTitleFromRow (row[6],row[7],&Gbl.Test.Image); Img_GetImageNameTitleAndURLFromRow (row[6],row[7],row[8],&Gbl.Test.Image);
Img_ShowImage (&Gbl.Test.Image,"TEST_IMG_EDIT_LIST_STEM"); Img_ShowImage (&Gbl.Test.Image,"TEST_IMG_EDIT_LIST_STEM");
Tst_WriteQstFeedback (row[5],"TEST_EDI_LIGHT"); Tst_WriteQstFeedback (row[5],"TEST_EDI_LIGHT");
Tst_WriteAnswersOfAQstEdit (Gbl.Test.QstCod); Tst_WriteAnswersOfAQstEdit (Gbl.Test.QstCod);
@ -2785,19 +2796,19 @@ static void Tst_ListOneOrMoreQuestionsToEdit (unsigned long NumRows,MYSQL_RES *m
/* Get number of hits /* Get number of hits
(number of times that the question has been answered, (number of times that the question has been answered,
including blank answers) (row[8]) */ including blank answers) (row[9]) */
if (sscanf (row[8],"%lu",&NumHitsThisQst) != 1) if (sscanf (row[9],"%lu",&NumHitsThisQst) != 1)
Lay_ShowErrorAndExit ("Wrong number of hits to a question."); Lay_ShowErrorAndExit ("Wrong number of hits to a question.");
/* Get number of hits not blank /* Get number of hits not blank
(number of times that the question has been answered (number of times that the question has been answered
with a not blank answer) (row[9]) */ with a not blank answer) (row[10]) */
if (sscanf (row[9],"%lu",&NumHitsNotBlankThisQst) != 1) if (sscanf (row[10],"%lu",&NumHitsNotBlankThisQst) != 1)
Lay_ShowErrorAndExit ("Wrong number of hits not blank to a question."); Lay_ShowErrorAndExit ("Wrong number of hits not blank to a question.");
/* Get the acumulated score of the question (row[10]) */ /* Get the acumulated score of the question (row[11]) */
setlocale (LC_NUMERIC,"en_US.utf8"); // To get decimal point setlocale (LC_NUMERIC,"en_US.utf8"); // To get decimal point
if (sscanf (row[10],"%lf",&TotalScoreThisQst) != 1) if (sscanf (row[11],"%lf",&TotalScoreThisQst) != 1)
Lay_ShowErrorAndExit ("Wrong score of a question."); Lay_ShowErrorAndExit ("Wrong score of a question.");
setlocale (LC_NUMERIC,"es_ES.utf8"); // Return to spanish system (TODO: this should be internationalized!!!!!!!) setlocale (LC_NUMERIC,"es_ES.utf8"); // Return to spanish system (TODO: this should be internationalized!!!!!!!)
@ -2877,7 +2888,8 @@ unsigned Tst_GetAnswersQst (long QstCod,MYSQL_RES **mysql_res,bool Shuffle)
unsigned long NumRows; unsigned long NumRows;
/***** Get answers of a question from database *****/ /***** Get answers of a question from database *****/
sprintf (Query,"SELECT AnsInd,Answer,Feedback,ImageName,ImageTitle,Correct" sprintf (Query,"SELECT AnsInd,Answer,Feedback,"
"ImageName,ImageTitle,ImageURL,Correct"
" FROM tst_answers WHERE QstCod='%ld' ORDER BY %s", " FROM tst_answers WHERE QstCod='%ld' ORDER BY %s",
QstCod, QstCod,
Shuffle ? "RAND(NOW())" : Shuffle ? "RAND(NOW())" :
@ -2912,7 +2924,8 @@ static void Tst_WriteAnswersOfAQstEdit (long QstCod)
row[ 2] Feedback row[ 2] Feedback
row[ 3] ImageName row[ 3] ImageName
row[ 4] ImageTitle row[ 4] ImageTitle
row[ 5] Correct row[ 5] ImageURL
row[ 6] Correct
*/ */
/***** Write the answers *****/ /***** Write the answers *****/
switch (Gbl.Test.AnswerType) switch (Gbl.Test.AnswerType)
@ -2979,13 +2992,13 @@ static void Tst_WriteAnswersOfAQstEdit (long QstCod)
} }
/* Copy image */ /* Copy image */
Img_GetImageNameAndTitleFromRow (row[3],row[4],&Gbl.Test.Answer.Options[NumOpt].Image); Img_GetImageNameTitleAndURLFromRow (row[3],row[4],row[5],&Gbl.Test.Answer.Options[NumOpt].Image);
/* Put an icon that indicates whether the answer is correct or wrong */ /* Put an icon that indicates whether the answer is correct or wrong */
fprintf (Gbl.F.Out,"<tr>" fprintf (Gbl.F.Out,"<tr>"
"<td class=\"BT%u\">", "<td class=\"BT%u\">",
Gbl.RowEvenOdd); Gbl.RowEvenOdd);
if (Str_ConvertToUpperLetter (row[5][0]) == 'Y') if (Str_ConvertToUpperLetter (row[6][0]) == 'Y')
fprintf (Gbl.F.Out,"<img src=\"%s/ok_on16x16.gif\"" fprintf (Gbl.F.Out,"<img src=\"%s/ok_on16x16.gif\""
" alt=\"%s\" title=\"%s\"" " alt=\"%s\" title=\"%s\""
" class=\"ICON20x20\" />", " class=\"ICON20x20\" />",
@ -3081,7 +3094,8 @@ static void Tst_WriteAnswersOfAQstAssessExam (unsigned NumQst,long QstCod,
row[ 2] Feedback row[ 2] Feedback
row[ 3] ImageName row[ 3] ImageName
row[ 4] ImageTitle row[ 4] ImageTitle
row[ 5] Correct row[ 5] ImageURL
row[ 6] Correct
*/ */
/***** Write answer depending on type *****/ /***** Write answer depending on type *****/
switch (Gbl.Test.AnswerType) switch (Gbl.Test.AnswerType)
@ -3166,7 +3180,8 @@ static void Tst_WriteTFAnsAssessExam (unsigned NumQst,MYSQL_RES *mysql_res,
row[ 2] Feedback row[ 2] Feedback
row[ 3] ImageName row[ 3] ImageName
row[ 4] ImageTitle row[ 4] ImageTitle
row[ 5] Correct row[ 5] ImageURL
row[ 6] Correct
*/ */
/***** Check if number of rows is correct *****/ /***** Check if number of rows is correct *****/
Tst_CheckIfNumberOfAnswersIsOne (); Tst_CheckIfNumberOfAnswersIsOne ();
@ -3260,7 +3275,8 @@ static void Tst_WriteChoiceAnsSeeExam (unsigned NumQst,long QstCod,bool Shuffle)
row[ 2] Feedback row[ 2] Feedback
row[ 3] ImageName row[ 3] ImageName
row[ 4] ImageTitle row[ 4] ImageTitle
row[ 5] Correct row[ 5] ImageURL
row[ 6] Correct
*/ */
/***** Start of table *****/ /***** Start of table *****/
@ -3296,7 +3312,7 @@ static void Tst_WriteChoiceAnsSeeExam (unsigned NumQst,long QstCod,bool Shuffle)
Gbl.Test.Answer.Options[NumOpt].Text,Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false); Gbl.Test.Answer.Options[NumOpt].Text,Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false);
/***** Copy image *****/ /***** Copy image *****/
Img_GetImageNameAndTitleFromRow (row[3],row[4],&Gbl.Test.Answer.Options[NumOpt].Image); Img_GetImageNameTitleAndURLFromRow (row[3],row[4],row[5],&Gbl.Test.Answer.Options[NumOpt].Image);
/***** Write selectors and letter of this option *****/ /***** Write selectors and letter of this option *****/
fprintf (Gbl.F.Out,"<tr>" fprintf (Gbl.F.Out,"<tr>"
@ -3363,7 +3379,8 @@ static void Tst_WriteChoiceAnsAssessExam (unsigned NumQst,MYSQL_RES *mysql_res,
row[ 2] Feedback row[ 2] Feedback
row[ 3] ImageName row[ 3] ImageName
row[ 4] ImageTitle row[ 4] ImageTitle
row[ 5] Correct row[ 5] ImageURL
row[ 6] Correct
*/ */
for (NumOpt = 0; for (NumOpt = 0;
NumOpt < Gbl.Test.Answer.NumOptions; NumOpt < Gbl.Test.Answer.NumOptions;
@ -3396,10 +3413,10 @@ static void Tst_WriteChoiceAnsAssessExam (unsigned NumQst,MYSQL_RES *mysql_res,
} }
/***** Copy image *****/ /***** Copy image *****/
Img_GetImageNameAndTitleFromRow (row[3],row[4],&Gbl.Test.Answer.Options[NumOpt].Image); Img_GetImageNameTitleAndURLFromRow (row[3],row[4],row[5],&Gbl.Test.Answer.Options[NumOpt].Image);
/***** Assign correctness (row[5]) of this answer (this option) *****/ /***** Assign correctness (row[6]) of this answer (this option) *****/
Gbl.Test.Answer.Options[NumOpt].Correct = (Str_ConvertToUpperLetter (row[5][0]) == 'Y'); Gbl.Test.Answer.Options[NumOpt].Correct = (Str_ConvertToUpperLetter (row[6][0]) == 'Y');
} }
/***** Get indexes for this question from string *****/ /***** Get indexes for this question from string *****/
@ -3598,7 +3615,8 @@ static void Tst_WriteTextAnsAssessExam (unsigned NumQst,MYSQL_RES *mysql_res,
row[ 2] Feedback row[ 2] Feedback
row[ 3] ImageName row[ 3] ImageName
row[ 4] ImageTitle row[ 4] ImageTitle
row[ 5] Correct row[ 5] ImageURL
row[ 6] Correct
*/ */
/***** Get text and correctness of answers for this question from database (one row per answer) *****/ /***** Get text and correctness of answers for this question from database (one row per answer) *****/
for (NumOpt = 0; for (NumOpt = 0;
@ -3628,8 +3646,8 @@ static void Tst_WriteTextAnsAssessExam (unsigned NumQst,MYSQL_RES *mysql_res,
Gbl.Test.Answer.Options[NumOpt].Feedback,Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false); Gbl.Test.Answer.Options[NumOpt].Feedback,Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false);
} }
/***** Assign correctness (row[5]) of this answer (this option) *****/ /***** Assign correctness (row[6]) of this answer (this option) *****/
Gbl.Test.Answer.Options[NumOpt].Correct = (Str_ConvertToUpperLetter (row[5][0]) == 'Y'); Gbl.Test.Answer.Options[NumOpt].Correct = (Str_ConvertToUpperLetter (row[6][0]) == 'Y');
} }
/***** Header with the title of each column *****/ /***** Header with the title of each column *****/
@ -3777,7 +3795,8 @@ static void Tst_WriteIntAnsAssessExam (unsigned NumQst,MYSQL_RES *mysql_res,
row[ 2] Feedback row[ 2] Feedback
row[ 3] ImageName row[ 3] ImageName
row[ 4] ImageTitle row[ 4] ImageTitle
row[ 5] Correct row[ 5] ImageURL
row[ 6] Correct
*/ */
/***** Check if number of rows is correct *****/ /***** Check if number of rows is correct *****/
Tst_CheckIfNumberOfAnswersIsOne (); Tst_CheckIfNumberOfAnswersIsOne ();
@ -3890,7 +3909,8 @@ static void Tst_WriteFloatAnsAssessExam (unsigned NumQst,MYSQL_RES *mysql_res,
row[ 2] Feedback row[ 2] Feedback
row[ 3] ImageName row[ 3] ImageName
row[ 4] ImageTitle row[ 4] ImageTitle
row[ 5] Correct row[ 5] ImageURL
row[ 6] Correct
*/ */
/***** Check if number of rows is correct *****/ /***** Check if number of rows is correct *****/
if (Gbl.Test.Answer.NumOptions != 2) if (Gbl.Test.Answer.NumOptions != 2)
@ -4846,16 +4866,16 @@ static void Tst_InitImagesOfQuestion (void)
unsigned NumOpt; unsigned NumOpt;
/***** Initialize image *****/ /***** Initialize image *****/
Img_ResetImageExceptTitle (&Gbl.Test.Image); Img_ResetImageExceptTitleAndURL (&Gbl.Test.Image);
Img_FreeImageTitle (&Gbl.Test.Image); Img_FreeImageTitleAndURL (&Gbl.Test.Image);
for (NumOpt = 0; for (NumOpt = 0;
NumOpt < Tst_MAX_OPTIONS_PER_QUESTION; NumOpt < Tst_MAX_OPTIONS_PER_QUESTION;
NumOpt++) NumOpt++)
{ {
/***** Initialize image *****/ /***** Initialize image *****/
Img_ResetImageExceptTitle (&Gbl.Test.Answer.Options[NumOpt].Image); Img_ResetImageExceptTitleAndURL (&Gbl.Test.Answer.Options[NumOpt].Image);
Img_FreeImageTitle (&Gbl.Test.Image); Img_FreeImageTitleAndURL (&Gbl.Test.Image);
} }
} }
@ -4889,7 +4909,8 @@ static void Tst_GetQstDataFromDB (char *Stem,char *Feedback)
/***** Get the type of answer and the stem from the database *****/ /***** Get the type of answer and the stem from the database *****/
/* Get the question from database */ /* Get the question from database */
sprintf (Query,"SELECT AnsType,Shuffle,Stem,Feedback,ImageName,ImageTitle" sprintf (Query,"SELECT AnsType,Shuffle,Stem,Feedback,"
"ImageName,ImageTitle,ImageURL"
" FROM tst_questions" " FROM tst_questions"
" WHERE QstCod='%ld' AND CrsCod='%ld'", " WHERE QstCod='%ld' AND CrsCod='%ld'",
Gbl.Test.QstCod,Gbl.CurrentCrs.Crs.CrsCod); Gbl.Test.QstCod,Gbl.CurrentCrs.Crs.CrsCod);
@ -4903,6 +4924,7 @@ static void Tst_GetQstDataFromDB (char *Stem,char *Feedback)
row[ 3] Feedback row[ 3] Feedback
row[ 4] ImageName row[ 4] ImageName
row[ 5] ImageTitle row[ 5] ImageTitle
row[ 6] ImageURL
*/ */
/* Get the type of answer */ /* Get the type of answer */
Gbl.Test.AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[0]); Gbl.Test.AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[0]);
@ -4923,8 +4945,9 @@ static void Tst_GetQstDataFromDB (char *Stem,char *Feedback)
Feedback[Cns_MAX_BYTES_TEXT] = '\0'; Feedback[Cns_MAX_BYTES_TEXT] = '\0';
} }
/* Get the image name of the question from the database (row[4]) */ /* Get the image name, title and URL of the question
Img_GetImageNameAndTitleFromRow (row[4],row[5],&Gbl.Test.Image); from the database (row[4], row[5], row[6]) */
Img_GetImageNameTitleAndURLFromRow (row[4],row[5],row[6],&Gbl.Test.Image);
/* Free structure that stores the query result */ /* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_res); DB_FreeMySQLResult (&mysql_res);
@ -4951,7 +4974,8 @@ static void Tst_GetQstDataFromDB (char *Stem,char *Feedback)
row[ 2] Feedback row[ 2] Feedback
row[ 3] ImageName row[ 3] ImageName
row[ 4] ImageTitle row[ 4] ImageTitle
row[ 5] Correct row[ 5] ImageURL
row[ 6] Correct
*/ */
for (NumOpt = 0; for (NumOpt = 0;
NumOpt < Gbl.Test.Answer.NumOptions; NumOpt < Gbl.Test.Answer.NumOptions;
@ -4995,9 +5019,9 @@ static void Tst_GetQstDataFromDB (char *Stem,char *Feedback)
} }
/* Copy image */ /* Copy image */
Img_GetImageNameAndTitleFromRow (row[3],row[4],&Gbl.Test.Answer.Options[NumOpt].Image); Img_GetImageNameTitleAndURLFromRow (row[3],row[4],row[5],&Gbl.Test.Answer.Options[NumOpt].Image);
Gbl.Test.Answer.Options[NumOpt].Correct = (Str_ConvertToUpperLetter (row[5][0]) == 'Y'); Gbl.Test.Answer.Options[NumOpt].Correct = (Str_ConvertToUpperLetter (row[6][0]) == 'Y');
break; break;
default: default:
break; break;
@ -5022,11 +5046,11 @@ static void Tst_GetImageFromDB (int NumOpt,struct Image *Image)
/***** Build query depending on NumOpt *****/ /***** Build query depending on NumOpt *****/
if (NumOpt < 0) if (NumOpt < 0)
// Get image associated to stem // Get image associated to stem
sprintf (Query,"SELECT ImageName,ImageTitle FROM tst_questions" sprintf (Query,"SELECT ImageName,ImageTitle,ImageURL FROM tst_questions"
" WHERE QstCod='%ld' AND CrsCod='%ld'", " WHERE QstCod='%ld' AND CrsCod='%ld'",
Gbl.Test.QstCod,Gbl.CurrentCrs.Crs.CrsCod); // Get image associated to answer Gbl.Test.QstCod,Gbl.CurrentCrs.Crs.CrsCod); // Get image associated to answer
else else
sprintf (Query,"SELECT ImageName,ImageTitle FROM tst_answers" sprintf (Query,"SELECT ImageName,ImageTitle,ImageURL FROM tst_answers"
" WHERE QstCod='%ld' AND AnsInd='%u'", " WHERE QstCod='%ld' AND AnsInd='%u'",
Gbl.Test.QstCod,(unsigned) NumOpt); Gbl.Test.QstCod,(unsigned) NumOpt);
@ -5034,8 +5058,8 @@ static void Tst_GetImageFromDB (int NumOpt,struct Image *Image)
DB_QuerySELECT (Query,&mysql_res,"can not get image name"); DB_QuerySELECT (Query,&mysql_res,"can not get image name");
row = mysql_fetch_row (mysql_res); row = mysql_fetch_row (mysql_res);
/***** Get the image name (row[0]) *****/ /***** Get the image name, title and URL (row[0], row[1], row[2]) *****/
Img_GetImageNameAndTitleFromRow (row[0],row[1],Image); Img_GetImageNameTitleAndURLFromRow (row[0],row[1],row[2],Image);
/***** Free structure that stores the query result *****/ /***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res); DB_FreeMySQLResult (&mysql_res);
@ -5869,10 +5893,10 @@ static void Tst_InsertOrUpdateQstIntoDB (void)
/***** Insert question in the table of questions *****/ /***** Insert question in the table of questions *****/
sprintf (Query,"INSERT INTO tst_questions" sprintf (Query,"INSERT INTO tst_questions"
" (CrsCod,EditTime,AnsType,Shuffle," " (CrsCod,EditTime,AnsType,Shuffle,"
"Stem,Feedback,ImageName,ImageTitle," "Stem,Feedback,ImageName,ImageTitle,ImageURL,"
"NumHits,Score)" "NumHits,Score)"
" VALUES ('%ld',NOW(),'%s','%c'," " VALUES ('%ld',NOW(),'%s','%c',"
"'%s','%s','%s','%s'," "'%s','%s','%s','%s','%s',"
"'0','0')", "'0','0')",
Gbl.CurrentCrs.Crs.CrsCod, Gbl.CurrentCrs.Crs.CrsCod,
Tst_StrAnswerTypesDB[Gbl.Test.AnswerType], Tst_StrAnswerTypesDB[Gbl.Test.AnswerType],
@ -5881,7 +5905,8 @@ static void Tst_InsertOrUpdateQstIntoDB (void)
Gbl.Test.Stem.Text, Gbl.Test.Stem.Text,
Gbl.Test.Feedback.Text ? Gbl.Test.Feedback.Text : "", Gbl.Test.Feedback.Text ? Gbl.Test.Feedback.Text : "",
Gbl.Test.Image.Name, Gbl.Test.Image.Name,
Gbl.Test.Image.Title ? Gbl.Test.Image.Title : ""); Gbl.Test.Image.Title ? Gbl.Test.Image.Title : "",
Gbl.Test.Image.URL ? Gbl.Test.Image.URL : "");
Gbl.Test.QstCod = DB_QueryINSERTandReturnCode (Query,"can not create question"); Gbl.Test.QstCod = DB_QueryINSERTandReturnCode (Query,"can not create question");
/* Update image status */ /* Update image status */
@ -5894,7 +5919,8 @@ static void Tst_InsertOrUpdateQstIntoDB (void)
/* Update question in database */ /* Update question in database */
sprintf (Query,"UPDATE tst_questions" sprintf (Query,"UPDATE tst_questions"
" SET EditTime=NOW(),AnsType='%s',Shuffle='%c'," " SET EditTime=NOW(),AnsType='%s',Shuffle='%c',"
"Stem='%s',Feedback='%s',ImageName='%s',ImageTitle='%s'" "Stem='%s',Feedback='%s',"
"ImageName='%s',ImageTitle='%s',ImageURL='%s'"
" WHERE QstCod='%ld' AND CrsCod='%ld'", " WHERE QstCod='%ld' AND CrsCod='%ld'",
Tst_StrAnswerTypesDB[Gbl.Test.AnswerType], Tst_StrAnswerTypesDB[Gbl.Test.AnswerType],
Gbl.Test.Shuffle ? 'Y' : Gbl.Test.Shuffle ? 'Y' :
@ -5903,6 +5929,7 @@ static void Tst_InsertOrUpdateQstIntoDB (void)
Gbl.Test.Feedback.Text ? Gbl.Test.Feedback.Text : "", Gbl.Test.Feedback.Text ? Gbl.Test.Feedback.Text : "",
Gbl.Test.Image.Name, Gbl.Test.Image.Name,
Gbl.Test.Image.Title ? Gbl.Test.Image.Title : "", Gbl.Test.Image.Title ? Gbl.Test.Image.Title : "",
Gbl.Test.Image.URL ? Gbl.Test.Image.URL : "",
Gbl.Test.QstCod,Gbl.CurrentCrs.Crs.CrsCod); Gbl.Test.QstCod,Gbl.CurrentCrs.Crs.CrsCod);
DB_QueryUPDATE (Query,"can not update question"); DB_QueryUPDATE (Query,"can not update question");
@ -5970,8 +5997,9 @@ static void Tst_InsertAnswersIntoDB (void)
{ {
case Tst_ANS_INT: case Tst_ANS_INT:
sprintf (Query,"INSERT INTO tst_answers" sprintf (Query,"INSERT INTO tst_answers"
" (QstCod,AnsInd,Answer,Feedback,ImageName,ImageTitle,Correct)" " (QstCod,AnsInd,Answer,Feedback,"
" VALUES (%ld,0,'%ld','','','','Y')", "ImageName,ImageTitle,ImageURL,Correct)"
" VALUES (%ld,0,'%ld','','','','','Y')",
Gbl.Test.QstCod, Gbl.Test.QstCod,
Gbl.Test.Answer.Integer); Gbl.Test.Answer.Integer);
DB_QueryINSERT (Query,"can not create answer"); DB_QueryINSERT (Query,"can not create answer");
@ -5983,8 +6011,9 @@ static void Tst_InsertAnswersIntoDB (void)
i++) i++)
{ {
sprintf (Query,"INSERT INTO tst_answers" sprintf (Query,"INSERT INTO tst_answers"
" (QstCod,AnsInd,Answer,Feedback,ImageName,ImageTitle,Correct)" " (QstCod,AnsInd,Answer,Feedback,"
" VALUES (%ld,%u,'%lg','','','','Y')", "ImageName,ImageTitle,ImageURL,Correct)"
" VALUES (%ld,%u,'%lg','','','','','Y')",
Gbl.Test.QstCod,i, Gbl.Test.QstCod,i,
Gbl.Test.Answer.FloatingPoint[i]); Gbl.Test.Answer.FloatingPoint[i]);
DB_QueryINSERT (Query,"can not create answer"); DB_QueryINSERT (Query,"can not create answer");
@ -5993,8 +6022,9 @@ static void Tst_InsertAnswersIntoDB (void)
break; break;
case Tst_ANS_TRUE_FALSE: case Tst_ANS_TRUE_FALSE:
sprintf (Query,"INSERT INTO tst_answers" sprintf (Query,"INSERT INTO tst_answers"
" (QstCod,AnsInd,Answer,Feedback,ImageName,ImageTitle,Correct)" " (QstCod,AnsInd,Answer,Feedback,"
" VALUES (%ld,0,'%c','','','','Y')", "ImageName,ImageTitle,ImageURL,Correct)"
" VALUES (%ld,0,'%c','','','','','Y')",
Gbl.Test.QstCod, Gbl.Test.QstCod,
Gbl.Test.Answer.TF); Gbl.Test.Answer.TF);
DB_QueryINSERT (Query,"can not create answer"); DB_QueryINSERT (Query,"can not create answer");
@ -6008,13 +6038,16 @@ static void Tst_InsertAnswersIntoDB (void)
if (Gbl.Test.Answer.Options[NumOpt].Text[0]) if (Gbl.Test.Answer.Options[NumOpt].Text[0])
{ {
sprintf (Query,"INSERT INTO tst_answers" sprintf (Query,"INSERT INTO tst_answers"
" (QstCod,AnsInd,Answer,Feedback,ImageName,ImageTitle,Correct)" " (QstCod,AnsInd,Answer,Feedback,"
" VALUES ('%ld','%u','%s','%s','%s','%s','%c')", "ImageName,ImageTitle,ImageURL,Correct)"
" VALUES"
" ('%ld','%u','%s','%s','%s','%s','%s','%c')",
Gbl.Test.QstCod,NumOpt, Gbl.Test.QstCod,NumOpt,
Gbl.Test.Answer.Options[NumOpt].Text, Gbl.Test.Answer.Options[NumOpt].Text,
Gbl.Test.Answer.Options[NumOpt].Feedback ? Gbl.Test.Answer.Options[NumOpt].Feedback : "", Gbl.Test.Answer.Options[NumOpt].Feedback ? Gbl.Test.Answer.Options[NumOpt].Feedback : "",
Gbl.Test.Answer.Options[NumOpt].Image.Name, Gbl.Test.Answer.Options[NumOpt].Image.Name,
Gbl.Test.Answer.Options[NumOpt].Image.Title ? Gbl.Test.Answer.Options[NumOpt].Image.Title : "", Gbl.Test.Answer.Options[NumOpt].Image.Title ? Gbl.Test.Answer.Options[NumOpt].Image.Title : "",
Gbl.Test.Answer.Options[NumOpt].Image.URL ? Gbl.Test.Answer.Options[NumOpt].Image.URL : "",
Gbl.Test.Answer.Options[NumOpt].Correct ? 'Y' : Gbl.Test.Answer.Options[NumOpt].Correct ? 'Y' :
'N'); 'N');
DB_QueryINSERT (Query,"can not create answer"); DB_QueryINSERT (Query,"can not create answer");
@ -7516,9 +7549,10 @@ static void Tst_ShowExamTstResult (time_t TstTimeUTC)
row[ 5] Feedback row[ 5] Feedback
row[ 6] ImageName row[ 6] ImageName
row[ 7] ImageTitle row[ 7] ImageTitle
row[ 8] NumHits row[ 8] ImageURL
row[ 9] NumHitsNotBlank row[ 9] NumHits
row[10] Score row[10] NumHitsNotBlank
row[11] Score
*/ */
/***** If this question has been edited later than test exam time ==> don't show question ****/ /***** If this question has been edited later than test exam time ==> don't show question ****/
EditTimeUTC = Dat_GetUNIXTimeFromStr (row[1]); EditTimeUTC = Dat_GetUNIXTimeFromStr (row[1]);

View File

@ -200,9 +200,10 @@ void TsI_CreateXML (unsigned long NumRows,MYSQL_RES *mysql_res)
row[ 5] Feedback row[ 5] Feedback
row[ 6] ImageName row[ 6] ImageName
row[ 7] ImageTitle row[ 7] ImageTitle
row[ 8] NumHits row[ 8] ImageURL
row[ 9] NumHitsNotBlank row[ 9] NumHits
row[10] Score row[10] NumHitsNotBlank
row[11] Score
*/ */
/* row[0] holds the code of the question */ /* row[0] holds the code of the question */
if ((QstCod = Str_ConvertStrCodToLongCod (row[0])) < 0) if ((QstCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
@ -312,7 +313,8 @@ static void TsI_WriteAnswersOfAQstXML (long QstCod)
row[ 2] Feedback row[ 2] Feedback
row[ 3] ImageName row[ 3] ImageName
row[ 4] ImageTitle row[ 4] ImageTitle
row[ 5] Correct row[ 5] ImageURL
row[ 6] Correct
*/ */
/***** Write the answers *****/ /***** Write the answers *****/
switch (Gbl.Test.AnswerType) switch (Gbl.Test.AnswerType)
@ -362,7 +364,7 @@ static void TsI_WriteAnswersOfAQstXML (long QstCod)
fprintf (Gbl.Test.XML.FileXML,"<option"); fprintf (Gbl.Test.XML.FileXML,"<option");
if (Gbl.Test.AnswerType != Tst_ANS_TEXT) if (Gbl.Test.AnswerType != Tst_ANS_TEXT)
fprintf (Gbl.Test.XML.FileXML," correct=\"%s\"", fprintf (Gbl.Test.XML.FileXML," correct=\"%s\"",
Str_ConvertToUpperLetter (row[5][0]) == 'Y' ? "yes" : Str_ConvertToUpperLetter (row[6][0]) == 'Y' ? "yes" :
"no"); "no");
fprintf (Gbl.Test.XML.FileXML,">%s" fprintf (Gbl.Test.XML.FileXML,">%s"
"<text>%s</text>%s", "<text>%s</text>%s",