mirror of https://github.com/acanas/swad-core.git
Version19.225
This commit is contained in:
parent
b7456dd5b3
commit
059fef2345
|
@ -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');
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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 *****/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 *****/
|
||||
|
|
|
@ -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 = ',';
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 *****/
|
||||
|
|
Loading…
Reference in New Issue