Version19.225

This commit is contained in:
acanas 2020-05-12 02:45:03 +02:00
parent b7456dd5b3
commit 059fef2345
11 changed files with 150 additions and 165 deletions

View File

@ -680,9 +680,34 @@ function updateExamPrint (idDiv,idInput,nameInput,Params) {
}
};
var input = document.getElementById(idInput);
if (input)
Params = Params + '&' + nameInput + '=' + input.value;
var inputElem = document.getElementById(idInput);
if (inputElem)
if (inputElem.type) {
if (inputElem.type === 'radio') {
if (inputElem.checked)
Params += '&' + nameInput + '=' + inputElem.value;
}
else if (inputElem.type === 'checkbox') {
var inputElems = inputElem.form.elements;
var i = 0;
// First checkbox checked
for (; i<inputElems.length; i++)
if (inputElems[i].checked) {
Params += '&' + nameInput + '=' + inputElems[i].value;
i++;
break;
}
// Other checked checkboxes
for (; i<inputElems.length; i++)
if (inputElems[i].checked)
Params += ',' + inputElems[i].value;
}
else
Params += '&' + nameInput + '=' + inputElem.value;
}
objXMLHttp.open('POST',ActionAJAX,true);
objXMLHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

View File

@ -548,11 +548,12 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - *
En OpenSWAD:
ps2pdf source.ps destination.pdf
*/
#define Log_PLATFORM_VERSION "SWAD 19.224 (2020-05-11)"
#define Log_PLATFORM_VERSION "SWAD 19.225 (2020-05-12)"
#define CSS_FILE "swad19.217.css"
#define JS_FILE "swad19.223.js"
/*
Version 19.224.1: May 11, 2020 Stored unique/multiple choice questions in exam print. (? lines)
Version 19.225: May 12, 2020 Stored unique/multiple choice questions in exam print.
Code refactoring in tests, exams and games. (303037 lines)
Version 19.224: May 11, 2020 API function getLocations returns only one room. (303048 lines)
Version 19.223.3: May 11, 2020 Fixed bug in test exam print, reported by Julio Ortega Lopera. (303050 lines)
Version 19.223.2: May 11, 2020 Stored T/F answers in exam print. (303034 lines)

View File

@ -2015,7 +2015,6 @@ void ExaEvt_GetIndexes (long EvtCod,unsigned QstInd,
DB_FreeMySQLResult (&mysql_res);
/***** Get indexes from string *****/
Par_ReplaceCommaBySeparatorMultiple (StrIndexesOneQst);
TstPrn_GetIndexesFromStr (StrIndexesOneQst,Indexes);
}

View File

@ -103,7 +103,7 @@ static void ExaPrn_ShowTableWithQstsToFill (struct ExaPrn_Print *Print);
static void ExaPrn_WriteQstAndAnsToFill (struct ExaPrn_Print *Print,
unsigned NumQst,
const struct Tst_Question *Question);
static void ExaPrn_WriteAnswersToFill (const struct ExaPrn_Print *Print,
static void ExaPrn_WriteAnswersToFill (struct ExaPrn_Print *Print,
unsigned NumQst,
const struct Tst_Question *Question);
static void ExaPrn_WriteIntAnsToFill (const struct ExaPrn_Print *Print,
@ -112,7 +112,7 @@ static void ExaPrn_WriteFloatAnsToFill (const struct ExaPrn_Print *Print,
unsigned NumQst);
static void ExaPrn_WriteTFAnsToFill (const struct ExaPrn_Print *Print,
unsigned NumQst);
static void ExaPrn_WriteChoiceAnsToFill (const struct ExaPrn_Print *Print,
static void ExaPrn_WriteChoiceAnsToFill (struct ExaPrn_Print *Print,
unsigned NumQst,
const struct Tst_Question *Question);
static void ExaPrn_WriteTextAnsToFill (const struct ExaPrn_Print *Print,
@ -456,22 +456,19 @@ static void ExaPrn_GetPrintQuestionsFromDB (struct ExaPrn_Print *Print)
MYSQL_ROW row;
unsigned NumQsts;
unsigned NumQst;
Tst_AnswerType_t AnswerType;
/***** Get questions of an exam print from database *****/
NumQsts =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get questions"
" of an exam print",
"SELECT exa_print_questions.QstCod," // row[0]
"exa_print_questions.SetCod," // row[1]
"tst_questions.AnsType," // row[2]
"exa_print_questions.Score," // row[3]
"exa_print_questions.Indexes," // row[4]
"exa_print_questions.Answers" // row[5]
" FROM exa_print_questions LEFT JOIN tst_questions"
" ON (exa_print_questions.QstCod=tst_questions.QstCod)"
" WHERE exa_print_questions.PrnCod=%ld"
" ORDER BY exa_print_questions.QstInd",
"SELECT QstCod," // row[0]
"SetCod," // row[1]
"Score," // row[2]
"Indexes," // row[3]
"Answers" // row[4]
" FROM exa_print_questions"
" WHERE PrnCod=%ld"
" ORDER BY QstInd",
Print->PrnCod);
/***** Get questions *****/
@ -490,30 +487,19 @@ static void ExaPrn_GetPrintQuestionsFromDB (struct ExaPrn_Print *Print)
if ((Print->PrintedQuestions[NumQst].SetCod = Str_ConvertStrCodToLongCod (row[1])) < 0)
Lay_ShowErrorAndExit ("Wrong code of set.");
/* Get answer type (row[2]) */
AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[2]);
/* Get score (row[3]) */
/* Get score (row[2]) */
Str_SetDecimalPointToUS (); // To get the decimal point as a dot
if (sscanf (row[3],"%lf",&Print->PrintedQuestions[NumQst].Score) != 1)
if (sscanf (row[2],"%lf",&Print->PrintedQuestions[NumQst].Score) != 1)
Lay_ShowErrorAndExit ("Wrong question score.");
Str_SetDecimalPointToLocal (); // Return to local system
/* Get indexes for this question (row[4]) */
Str_Copy (Print->PrintedQuestions[NumQst].StrIndexes,row[4],
/* Get indexes for this question (row[3]) */
Str_Copy (Print->PrintedQuestions[NumQst].StrIndexes,row[3],
Tst_MAX_BYTES_INDEXES_ONE_QST);
/* Get answers selected by user for this question (row[5]) */
Str_Copy (Print->PrintedQuestions[NumQst].StrAnswers,row[5],
/* Get answers selected by user for this question (row[4]) */
Str_Copy (Print->PrintedQuestions[NumQst].StrAnswers,row[4],
Tst_MAX_BYTES_ANSWERS_ONE_QST);
/* Replace each comma by a separator of multiple parameters */
/* In database commas are used as separators instead of special chars */
Par_ReplaceCommaBySeparatorMultiple (Print->PrintedQuestions[NumQst].StrIndexes);
if (AnswerType == Tst_ANS_MULTIPLE_CHOICE)
// Only multiple choice questions have multiple answers separated by commas
// Other types of questions have a unique answer, and comma may be part of that answer
Par_ReplaceCommaBySeparatorMultiple (Print->PrintedQuestions[NumQst].StrAnswers);
}
/***** Free structure that stores the query result *****/
@ -544,11 +530,9 @@ static void ExaPrn_ShowExamPrintToFillIt (const char *Title,
if (Print->NumQsts)
{
/***** Show table with questions to answer *****/
Frm_StartFormNoAction (); // Form that can not be submitted, to avoid enter key to send it
HTM_DIV_Begin ("id=\"examprint\""); // Used for AJAX based refresh
ExaPrn_ShowTableWithQstsToFill (Print);
HTM_DIV_End (); // Used for AJAX based refresh
Frm_EndForm ();
/***** Form to end/close this exam print *****/
Frm_StartForm (ActEndExaPrn);
@ -653,7 +637,9 @@ static void ExaPrn_WriteQstAndAnsToFill (struct ExaPrn_Print *Print,
"TEST_MED_SHOW");
/* Answers */
Frm_StartFormNoAction (); // Form that can not be submitted, to avoid enter key to send it
ExaPrn_WriteAnswersToFill (Print,NumQst,Question);
Frm_EndForm ();
HTM_TD_End ();
@ -665,7 +651,7 @@ static void ExaPrn_WriteQstAndAnsToFill (struct ExaPrn_Print *Print,
/***************** Write answers of a question to fill them ******************/
/*****************************************************************************/
static void ExaPrn_WriteAnswersToFill (const struct ExaPrn_Print *Print,
static void ExaPrn_WriteAnswersToFill (struct ExaPrn_Print *Print,
unsigned NumQst,
const struct Tst_Question *Question)
{
@ -706,16 +692,15 @@ static void ExaPrn_WriteIntAnsToFill (const struct ExaPrn_Print *Print,
snprintf (Id,sizeof (Id),
"Ans%010u",
NumQst);
HTM_TxtF ("<input type=\"text\" id=\"%s\" name=\"%s\""
HTM_TxtF ("<input type=\"text\" id=\"%s\" name=\"Ans\""
" size=\"11\" maxlength=\"11\" value=\"%s\"",
Id,Id,
Id,
Print->PrintedQuestions[NumQst].StrAnswers);
HTM_TxtF (" onchange=\"updateExamPrint('examprint','%s','%s',"
HTM_TxtF (" onchange=\"updateExamPrint('examprint','%s','Ans',"
"'act=%ld&ses=%s&EvtCod=%ld&NumQst=%u');"
" return false;\"", // return false is necessary to not submit form
Id,Id,
Act_GetActCod (ActAnsExaPrn),
Gbl.Session.Id,Print->EvtCod,NumQst);
Id,
Act_GetActCod (ActAnsExaPrn),Gbl.Session.Id,Print->EvtCod,NumQst);
HTM_Txt (" />");
}
@ -732,16 +717,15 @@ static void ExaPrn_WriteFloatAnsToFill (const struct ExaPrn_Print *Print,
snprintf (Id,sizeof (Id),
"Ans%010u",
NumQst);
HTM_TxtF ("<input type=\"text\" id=\"%s\" name=\"%s\""
HTM_TxtF ("<input type=\"text\" id=\"%s\" name=\"Ans\""
" size=\"11\" maxlength=\"%u\" value=\"%s\"",
Id,Id,Tst_MAX_BYTES_FLOAT_ANSWER,
Id,Tst_MAX_BYTES_FLOAT_ANSWER,
Print->PrintedQuestions[NumQst].StrAnswers);
HTM_TxtF (" onchange=\"updateExamPrint('examprint','%s','%s',"
HTM_TxtF (" onchange=\"updateExamPrint('examprint','%s','Ans',"
"'act=%ld&ses=%s&EvtCod=%ld&NumQst=%u');"
" return false;\"", // return false is necessary to not submit form
Id,Id,
Act_GetActCod (ActAnsExaPrn),
Gbl.Session.Id,Print->EvtCod,NumQst);
Id,
Act_GetActCod (ActAnsExaPrn),Gbl.Session.Id,Print->EvtCod,NumQst);
HTM_Txt (" />");
}
@ -762,11 +746,11 @@ static void ExaPrn_WriteTFAnsToFill (const struct ExaPrn_Print *Print,
snprintf (Id,sizeof (Id),
"Ans%010u",
NumQst);
HTM_TxtF ("<select id=\"%s\" name=\"%s\"",Id,Id);
HTM_TxtF (" onchange=\"updateExamPrint('examprint','%s','%s',"
HTM_TxtF ("<select id=\"%s\" name=\"Ans\"",Id);
HTM_TxtF (" onchange=\"updateExamPrint('examprint','%s','Ans',"
"'act=%ld&ses=%s&EvtCod=%ld&NumQst=%u');"
" return false;\"", // return false is necessary to not submit form
Id,Id,
Id,
Act_GetActCod (ActAnsExaPrn),
Gbl.Session.Id,Print->EvtCod,NumQst);
HTM_Txt (" />");
@ -780,7 +764,7 @@ static void ExaPrn_WriteTFAnsToFill (const struct ExaPrn_Print *Print,
/******** Write single or multiple choice answer when seeing a test **********/
/*****************************************************************************/
static void ExaPrn_WriteChoiceAnsToFill (const struct ExaPrn_Print *Print,
static void ExaPrn_WriteChoiceAnsToFill (struct ExaPrn_Print *Print,
unsigned NumQst,
const struct Tst_Question *Question)
{
@ -816,28 +800,31 @@ static void ExaPrn_WriteChoiceAnsToFill (const struct ExaPrn_Print *Print,
"Ans%010u",
NumQst);
if (Question->Answer.Type == Tst_ANS_UNIQUE_CHOICE)
HTM_INPUT_RADIO (Id,false,
"id=\"Ans%010u_%u\" value=\"%u\"%s"
" onclick=\"selectUnselectRadio(this,this.form.Ans%010u,%u);\"",
NumQst,NumOpt,
Indexes[NumOpt],
UsrAnswers[Indexes[NumOpt]] ? " checked=\"checked\"" :
"",
NumQst,Question->Answer.NumOptions);
{
HTM_TxtF ("<input type=\"radio\" id=\"%s_%u\" name=\"Ans\" value=\"%u\"%s",
Id,NumOpt,Indexes[NumOpt],
UsrAnswers[Indexes[NumOpt]] ? " checked=\"checked\"" :
"");
HTM_TxtF (" onclick=\"updateExamPrint('examprint','%s_%u','Ans',"
"'act=%ld&ses=%s&EvtCod=%ld&NumQst=%u');"
" return false;\"", // return false is necessary to not submit form
Id,NumOpt,
Act_GetActCod (ActAnsExaPrn),Gbl.Session.Id,Print->EvtCod,NumQst);
HTM_Txt (" />");
}
else // Answer.Type == Tst_ANS_MULTIPLE_CHOICE
HTM_INPUT_CHECKBOX (Id,HTM_DONT_SUBMIT_ON_CHANGE,
"id=\"Ans%010u_%u\" value=\"%u\"%s",
NumQst,NumOpt,
Indexes[NumOpt],
UsrAnswers[Indexes[NumOpt]] ? " checked=\"checked\"" :
"");
/* HTM_TxtF (" onchange=\"updateExamPrint('examprint','%s','%s',"
"'act=%ld&ses=%s&EvtCod=%ld&NumQst=%u');"
" return false;\"", // return false is necessary to not submit form
Id,Id,
Act_GetActCod (ActAnsExaPrn),
Gbl.Session.Id,Print->EvtCod,NumQst);
HTM_Txt (" />"); */
{
HTM_TxtF ("<input type=\"checkbox\" id=\"%s_%u\" name=\"Ans\" value=\"%u\"%s",
Id,NumOpt,Indexes[NumOpt],
UsrAnswers[Indexes[NumOpt]] ? " checked=\"checked\"" :
"");
HTM_TxtF (" onclick=\"updateExamPrint('examprint','%s_%u','Ans',"
"'act=%ld&ses=%s&EvtCod=%ld&NumQst=%u');"
" return false;\"", // return false is necessary to not submit form
Id,NumOpt,
Act_GetActCod (ActAnsExaPrn),Gbl.Session.Id,Print->EvtCod,NumQst);
HTM_Txt (" />");
}
HTM_TD_End ();
HTM_TD_Begin ("class=\"LT\"");
@ -876,16 +863,15 @@ static void ExaPrn_WriteTextAnsToFill (const struct ExaPrn_Print *Print,
snprintf (Id,sizeof (Id),
"Ans%010u",
NumQst);
HTM_TxtF ("<input type=\"text\" id=\"%s\" name=\"%s\""
HTM_TxtF ("<input type=\"text\" id=\"%s\" name=\"Ans\""
" size=\"40\" maxlength=\"%u\" value=\"%s\"",
Id,Id,Tst_MAX_CHARS_ANSWERS_ONE_QST,
Id,Tst_MAX_CHARS_ANSWERS_ONE_QST,
Print->PrintedQuestions[NumQst].StrAnswers);
HTM_TxtF (" onchange=\"updateExamPrint('examprint','%s','%s',"
HTM_TxtF (" onchange=\"updateExamPrint('examprint','%s','Ans',"
"'act=%ld&ses=%s&EvtCod=%ld&NumQst=%u');"
" return false;\"", // return false is necessary to not submit form
Id,Id,
Act_GetActCod (ActAnsExaPrn),
Gbl.Session.Id,Print->EvtCod,NumQst);
Id,
Act_GetActCod (ActAnsExaPrn),Gbl.Session.Id,Print->EvtCod,NumQst);
HTM_Txt (" />");
}
@ -932,17 +918,13 @@ void ExaPrn_ReceivePrintAnswer (void)
static unsigned ExaPrn_GetAnswerFromForm (struct ExaPrn_Print *Print)
{
unsigned NumQst;
char AnsName[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x"
/***** Get question index from form *****/
NumQst = ExaPrn_GetParamQstInd ();
/***** Get answers selected by user for this question *****/
snprintf (AnsName,sizeof (AnsName),
"Ans%010u",
NumQst);
Par_GetParMultiToText (AnsName,Print->PrintedQuestions[NumQst].StrAnswers,
Tst_MAX_BYTES_ANSWERS_ONE_QST); /* If answer type == T/F ==> " ", "T", "F"; if choice ==> "0", "2",... */
Par_GetParToText ("Ans",Print->PrintedQuestions[NumQst].StrAnswers,
Tst_MAX_BYTES_ANSWERS_ONE_QST); /* If answer type == T/F ==> " ", "T", "F"; if choice ==> "0", "2",... */
return NumQst;
}
@ -1031,14 +1013,6 @@ static void ExaPrn_ComputeScoreAndStoreQuestionOfPrint (struct ExaPrn_Print *Pri
static void ExaPrn_StoreOneQstOfPrintInDB (const struct ExaPrn_Print *Print,
unsigned NumQst)
{
char StrIndexes[Tst_MAX_BYTES_INDEXES_ONE_QST + 1];
char StrAnswers[Tst_MAX_BYTES_ANSWERS_ONE_QST + 1];
/***** Replace each separator of multiple parameters by a comma *****/
/* In database commas are used as separators instead of special chars */
Par_ReplaceSeparatorMultipleByComma (Print->PrintedQuestions[NumQst].StrIndexes,StrIndexes);
Par_ReplaceSeparatorMultipleByComma (Print->PrintedQuestions[NumQst].StrAnswers,StrAnswers);
/***** Insert question and user's answers into database *****/
Str_SetDecimalPointToUS (); // To print the floating point as a dot
DB_QueryREPLACE ("can not update a question in an exam print",
@ -1050,8 +1024,8 @@ static void ExaPrn_StoreOneQstOfPrintInDB (const struct ExaPrn_Print *Print,
NumQst, // 0, 1, 2, 3...
Print->PrintedQuestions[NumQst].SetCod,
Print->PrintedQuestions[NumQst].Score,
StrIndexes,
StrAnswers);
Print->PrintedQuestions[NumQst].StrIndexes,
Print->PrintedQuestions[NumQst].StrAnswers);
Str_SetDecimalPointToLocal (); // Return to local system
}

View File

@ -1365,11 +1365,6 @@ void ExaRes_GetExamResultQuestionsFromDB (long EvtCod,long UsrCod,
}
else // UsrAnswer.AnsInd < 0 ==> no answer selected
Print->PrintedQuestions[NumQst].StrAnswers[0] = '\0'; // Empty answer
/* Replace each comma by a separator of multiple parameters */
/* In database commas are used as separators instead of special chars */
Par_ReplaceCommaBySeparatorMultiple (Print->PrintedQuestions[NumQst].StrIndexes);
Par_ReplaceCommaBySeparatorMultiple (Print->PrintedQuestions[NumQst].StrAnswers);
}
/***** Free structure that stores the query result *****/

View File

@ -1690,7 +1690,6 @@ void Mch_GetIndexes (long MchCod,unsigned QstInd,
DB_FreeMySQLResult (&mysql_res);
/***** Get indexes from string *****/
Par_ReplaceCommaBySeparatorMultiple (StrIndexesOneQst);
TstPrn_GetIndexesFromStr (StrIndexesOneQst,Indexes);
}

View File

@ -1356,11 +1356,6 @@ void MchRes_GetMatchResultQuestionsFromDB (long MchCod,long UsrCod,
}
else // UsrAnswer.AnsInd < 0 ==> no answer selected
Print->PrintedQuestions[NumQst].StrAnswers[0] = '\0'; // Empty answer
/* Replace each comma by a separator of multiple parameters */
/* In database commas are used as separators instead of special chars */
Par_ReplaceCommaBySeparatorMultiple (Print->PrintedQuestions[NumQst].StrIndexes);
Par_ReplaceCommaBySeparatorMultiple (Print->PrintedQuestions[NumQst].StrAnswers);
}
/***** Free structure that stores the query result *****/

View File

@ -1010,32 +1010,50 @@ bool Par_GetNextStrUntilSeparParamMult (const char **StrSrc,char *StrDst,size_t
}
/*****************************************************************************/
/************ Replace any character between 1 and 31 by a comma **************/
/***** Search in the string StrSrc the next string until find separator ******/
/*****************************************************************************/
// Modifies *StrSrc
// When StrDst is NULL, nothing is stored
// Return true if characters found
void Par_ReplaceSeparatorMultipleByComma (const char *StrSrc,char *StrDst)
bool Par_GetNextStrUntilComma (const char **StrSrc,char *StrDst,size_t LongMax)
{
for (;
*StrSrc;
StrSrc++, StrDst++)
*StrDst = ((unsigned char) *StrSrc < 32) ? ',' :
*StrSrc;
*StrDst = '\0';
size_t i = 0;
unsigned char Ch; // Must be unsigned to work with characters > 127
bool CharsFound = false;
do
if ((Ch = (unsigned char) **StrSrc))
(*StrSrc)++;
while (Ch == ','); // Skip commas
while (Ch && Ch != ',') // Until special character or end
{
CharsFound = true;
if (i < LongMax)
if (StrDst)
StrDst[i++] = (char) Ch;
if ((Ch = (unsigned char) **StrSrc))
(*StrSrc)++;
}
if (StrDst)
StrDst[i] = '\0';
return CharsFound;
}
/*****************************************************************************/
/******** Replace each comma by the separator of multiple parameters *********/
/*****************************************************************************/
void Par_ReplaceCommaBySeparatorMultiple (char *Str)
void Par_ReplaceSeparatorMultipleByComma (char *Str)
{
extern const char *Par_SEPARATOR_PARAM_MULTIPLE;
for (;
*Str;
Str++)
if (*Str == ',')
*Str = Par_SEPARATOR_PARAM_MULTIPLE[0];
if ((unsigned char) *Str < 32)
*Str = ',';
}
/*****************************************************************************/

View File

@ -86,8 +86,7 @@ unsigned Par_GetParAndChangeFormat (const char *ParamName,char *ParamValue,size_
bool Par_GetNextStrUntilSeparParamMult (const char **StrSrc,char *StrDst,size_t LongMax);
bool Par_GetNextStrUntilComma (const char **StrSrc,char *StrDst,size_t LongMax);
void Par_ReplaceSeparatorMultipleByComma (const char *StrSrc,char *StrDst);
void Par_ReplaceCommaBySeparatorMultiple (char *Str);
void Par_ReplaceSeparatorMultipleByComma (char *Str);
void Par_PutHiddenParamUnsigned (const char *Id,const char *ParamName,unsigned Value);
void Par_PutHiddenParamUnsignedDisabled (const char *Id,const char *ParamName,unsigned Value);

View File

@ -672,6 +672,7 @@ static void TstPrn_GetAnswersFromForm (struct TstPrn_Print *Print)
NumQst);
Par_GetParMultiToText (StrAns,Print->PrintedQuestions[NumQst].StrAnswers,
Tst_MAX_BYTES_ANSWERS_ONE_QST); /* If answer type == T/F ==> " ", "T", "F"; if choice ==> "0", "2",... */
Par_ReplaceSeparatorMultipleByComma (Print->PrintedQuestions[NumQst].StrAnswers);
}
}
@ -2685,7 +2686,7 @@ static void Tst_GetQuestionsForNewTestFromDB (struct Tst_Test *Test,
void Tst_GenerateChoiceIndexesDependingOnShuffle (struct TstPrn_PrintedQuestion *PrintedQuestion,
bool Shuffle)
{
extern const char *Par_SEPARATOR_PARAM_MULTIPLE;
// extern const char *Par_SEPARATOR_PARAM_MULTIPLE;
struct Tst_Question Question;
unsigned NumOpt;
MYSQL_RES *mysql_res;
@ -2732,7 +2733,8 @@ void Tst_GenerateChoiceIndexesDependingOnShuffle (struct TstPrn_PrintedQuestion
if (NumOpt == 0)
snprintf (StrInd,sizeof (StrInd),"%u",Index);
else
snprintf (StrInd,sizeof (StrInd),"%s%u",Par_SEPARATOR_PARAM_MULTIPLE,Index);
// snprintf (StrInd,sizeof (StrInd),"%s%u",Par_SEPARATOR_PARAM_MULTIPLE,Index);
snprintf (StrInd,sizeof (StrInd),",%u",Index);
Str_Concat (PrintedQuestion->StrIndexes,StrInd,
Tst_MAX_BYTES_INDEXES_ONE_QST);
}

View File

@ -647,7 +647,7 @@ void TstPrn_GetIndexesFromStr (const char StrIndexesOneQst[Tst_MAX_BYTES_INDEXES
NumOpt < Tst_MAX_OPTIONS_PER_QUESTION && *Ptr;
NumOpt++)
{
Par_GetNextStrUntilSeparParamMult (&Ptr,StrOneIndex,Cns_MAX_DECIMAL_DIGITS_UINT);
Par_GetNextStrUntilComma (&Ptr,StrOneIndex,Cns_MAX_DECIMAL_DIGITS_UINT);
if (sscanf (StrOneIndex,"%u",&(Indexes[NumOpt])) != 1)
Lay_ShowErrorAndExit ("Wrong index of answer.");
@ -686,7 +686,7 @@ void TstPrn_GetAnswersFromStr (const char StrAnswersOneQst[Tst_MAX_BYTES_ANSWERS
NumOpt < Tst_MAX_OPTIONS_PER_QUESTION && *Ptr;
NumOpt++)
{
Par_GetNextStrUntilSeparParamMult (&Ptr,StrOneAnswer,Cns_MAX_DECIMAL_DIGITS_UINT);
Par_GetNextStrUntilComma (&Ptr,StrOneAnswer,Cns_MAX_DECIMAL_DIGITS_UINT);
if (sscanf (StrOneAnswer,"%u",&AnsUsr) != 1)
Lay_ShowErrorAndExit ("Bad user's answer.");
@ -1386,14 +1386,6 @@ static void TstPrn_WriteHeadUserCorrect (struct UsrData *UsrDat)
static void TstPrn_StoreOneQstOfPrintInDB (const struct TstPrn_Print *Print,
unsigned NumQst)
{
char StrIndexes[Tst_MAX_BYTES_INDEXES_ONE_QST + 1];
char StrAnswers[Tst_MAX_BYTES_ANSWERS_ONE_QST + 1];
/***** Replace each separator of multiple parameters by a comma *****/
/* In database commas are used as separators instead of special chars */
Par_ReplaceSeparatorMultipleByComma (Print->PrintedQuestions[NumQst].StrIndexes,StrIndexes);
Par_ReplaceSeparatorMultipleByComma (Print->PrintedQuestions[NumQst].StrAnswers,StrAnswers);
/***** Insert question and user's answers into database *****/
Str_SetDecimalPointToUS (); // To print the floating point as a dot
DB_QueryREPLACE ("can not update a question of a test exam",
@ -1404,8 +1396,8 @@ static void TstPrn_StoreOneQstOfPrintInDB (const struct TstPrn_Print *Print,
Print->PrnCod,Print->PrintedQuestions[NumQst].QstCod,
NumQst, // 0, 1, 2, 3...
Print->PrintedQuestions[NumQst].Score,
StrIndexes,
StrAnswers);
Print->PrintedQuestions[NumQst].StrIndexes,
Print->PrintedQuestions[NumQst].StrAnswers);
Str_SetDecimalPointToLocal (); // Return to local system
}
@ -2266,21 +2258,18 @@ void TstPrn_GetPrintQuestionsFromDB (struct TstPrn_Print *Print)
MYSQL_ROW row;
unsigned NumQsts;
unsigned NumQst;
Tst_AnswerType_t AnswerType;
/***** Get questions of a test exam print from database *****/
NumQsts =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get questions"
" of a test exam",
"SELECT tst_exam_questions.QstCod," // row[0]
"tst_questions.AnsType," // row[1]
"tst_exam_questions.Score," // row[2]
"tst_exam_questions.Indexes," // row[3]
"tst_exam_questions.Answers" // row[4]
" FROM tst_exam_questions LEFT JOIN tst_questions"
" ON (tst_exam_questions.QstCod=tst_questions.QstCod)"
" WHERE tst_exam_questions.ExaCod=%ld"
" ORDER BY tst_exam_questions.QstInd",
"SELECT QstCod," // row[0]
"Score," // row[1]
"Indexes," // row[2]
"Answers" // row[3]
" FROM tst_exam_questions"
" WHERE ExaCod=%ld"
" ORDER BY QstInd",
Print->PrnCod);
/***** Get questions *****/
@ -2295,30 +2284,19 @@ void TstPrn_GetPrintQuestionsFromDB (struct TstPrn_Print *Print)
if ((Print->PrintedQuestions[NumQst].QstCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
Lay_ShowErrorAndExit ("Wrong code of question.");
/* Get answer type (row[1]) */
AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
/* Get score (row[2]) */
/* Get score (row[1]) */
Str_SetDecimalPointToUS (); // To get the decimal point as a dot
if (sscanf (row[2],"%lf",&Print->PrintedQuestions[NumQst].Score) != 1)
if (sscanf (row[1],"%lf",&Print->PrintedQuestions[NumQst].Score) != 1)
Lay_ShowErrorAndExit ("Wrong question score.");
Str_SetDecimalPointToLocal (); // Return to local system
/* Get indexes for this question (row[3]) */
Str_Copy (Print->PrintedQuestions[NumQst].StrIndexes,row[3],
/* Get indexes for this question (row[2]) */
Str_Copy (Print->PrintedQuestions[NumQst].StrIndexes,row[2],
Tst_MAX_BYTES_INDEXES_ONE_QST);
/* Get answers selected by user for this question (row[4]) */
Str_Copy (Print->PrintedQuestions[NumQst].StrAnswers,row[4],
/* Get answers selected by user for this question (row[3]) */
Str_Copy (Print->PrintedQuestions[NumQst].StrAnswers,row[3],
Tst_MAX_BYTES_ANSWERS_ONE_QST);
/* Replace each comma by a separator of multiple parameters */
/* In database commas are used as separators instead of special chars */
Par_ReplaceCommaBySeparatorMultiple (Print->PrintedQuestions[NumQst].StrIndexes);
if (AnswerType == Tst_ANS_MULTIPLE_CHOICE)
// Only multiple choice questions have multiple answers separated by commas
// Other types of questions have a unique answer, and comma may be part of that answer
Par_ReplaceCommaBySeparatorMultiple (Print->PrintedQuestions[NumQst].StrAnswers);
}
/***** Free structure that stores the query result *****/