mirror of https://github.com/acanas/swad-core.git
Version19.217
This commit is contained in:
parent
a04402a458
commit
dc919206d6
4
Makefile
4
Makefile
|
@ -58,8 +58,8 @@ OBJS = swad_account.o swad_action.o swad_agenda.o swad_alert.o \
|
|||
swad_scope.o swad_search.o swad_session.o swad_setting.o \
|
||||
swad_statistic.o swad_string.o swad_survey.o swad_syllabus.o \
|
||||
swad_system_config.o \
|
||||
swad_tab.o swad_test.o swad_test_config.o swad_test_exam.o \
|
||||
swad_test_import.o swad_test_visibility.o swad_theme.o swad_timeline.o \
|
||||
swad_tab.o swad_test.o swad_test_config.o swad_test_import.o \
|
||||
swad_test_print.o swad_test_visibility.o swad_theme.o swad_timeline.o \
|
||||
swad_timetable.o \
|
||||
swad_user.o \
|
||||
swad_xml.o \
|
||||
|
|
|
@ -2654,9 +2654,9 @@ table.CELLS_PAD_10 > tbody > tr > td {padding:10px;}
|
|||
text-align:center;
|
||||
vertical-align:middle;
|
||||
}
|
||||
.TEST_EXA {color:#202020; font-size:12pt;}
|
||||
.TEST_EXA {color:#202020; font-size:12pt;}
|
||||
.TEST_EXA_LIGHT {color:#a0a0a0; font-size:12pt;}
|
||||
.TEST_EDI {color:#202020; font-size:12pt;}
|
||||
.TEST_EDI {color:#202020; font-size:12pt;}
|
||||
.TEST_EDI_LIGHT {color:#a0a0a0; font-size:12pt;}
|
||||
|
||||
.TEST_TAG_LIST
|
||||
|
@ -2744,6 +2744,21 @@ table.CELLS_PAD_10 > tbody > tr > td {padding:10px;}
|
|||
}
|
||||
|
||||
/*********************************** Exams ***********************************/
|
||||
.EXA_SET_TITLE
|
||||
{
|
||||
text-align:left;
|
||||
vertical-align:top;
|
||||
color:black;
|
||||
font-size:16pt;
|
||||
}
|
||||
.EXA_SET_NUM_QSTS
|
||||
{
|
||||
text-align:right;
|
||||
vertical-align:top;
|
||||
color:#404040;
|
||||
font-size:12pt;
|
||||
}
|
||||
|
||||
.EXA_BG
|
||||
{
|
||||
background-image:url("/swad/icon/bg.jpg");
|
14
swad_API.c
14
swad_API.c
|
@ -3955,7 +3955,7 @@ int swad__sendNotice (struct soap *soap,
|
|||
/****************** Return test configuration in a course ********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#define TstRes_MAX_BYTES_FEEDBACK_TYPE 32
|
||||
#define TstPrn_MAX_BYTES_FEEDBACK_TYPE 32
|
||||
|
||||
int swad__getTestConfig (struct soap *soap,
|
||||
char *wsKey,int courseCode, // input
|
||||
|
@ -4010,7 +4010,7 @@ int swad__getTestConfig (struct soap *soap,
|
|||
getTestConfigOut->visibility = TstVis_MIN_VISIBILITY;
|
||||
|
||||
/* TODO: Remove these lines in 2021 */
|
||||
getTestConfigOut->feedback = (char *) soap_malloc (soap,TstRes_MAX_BYTES_FEEDBACK_TYPE + 1);
|
||||
getTestConfigOut->feedback = (char *) soap_malloc (soap,TstPrn_MAX_BYTES_FEEDBACK_TYPE + 1);
|
||||
getTestConfigOut->feedback[0] = '\0';
|
||||
|
||||
/***** Get test configuration *****/
|
||||
|
@ -4028,23 +4028,23 @@ int swad__getTestConfig (struct soap *soap,
|
|||
if (!TstVis_IsVisibleTotalScore (TstCfg_GetConfigVisibility ()))
|
||||
Str_Copy (getTestConfigOut->feedback,
|
||||
"nothing",
|
||||
TstRes_MAX_BYTES_FEEDBACK_TYPE);
|
||||
TstPrn_MAX_BYTES_FEEDBACK_TYPE);
|
||||
else if (!TstVis_IsVisibleEachQstScore (TstCfg_GetConfigVisibility ()))
|
||||
Str_Copy (getTestConfigOut->feedback,
|
||||
"totalResult",
|
||||
TstRes_MAX_BYTES_FEEDBACK_TYPE);
|
||||
TstPrn_MAX_BYTES_FEEDBACK_TYPE);
|
||||
else if (!TstVis_IsVisibleCorrectAns (TstCfg_GetConfigVisibility ()))
|
||||
Str_Copy (getTestConfigOut->feedback,
|
||||
"eachResult",
|
||||
TstRes_MAX_BYTES_FEEDBACK_TYPE);
|
||||
TstPrn_MAX_BYTES_FEEDBACK_TYPE);
|
||||
else if (!TstVis_IsVisibleFeedbackTxt (TstCfg_GetConfigVisibility ()))
|
||||
Str_Copy (getTestConfigOut->feedback,
|
||||
"eachGoodBad",
|
||||
TstRes_MAX_BYTES_FEEDBACK_TYPE);
|
||||
TstPrn_MAX_BYTES_FEEDBACK_TYPE);
|
||||
else
|
||||
Str_Copy (getTestConfigOut->feedback,
|
||||
"fullFeedback",
|
||||
TstRes_MAX_BYTES_FEEDBACK_TYPE);
|
||||
TstPrn_MAX_BYTES_FEEDBACK_TYPE);
|
||||
|
||||
/***** Get number of tests *****/
|
||||
if (TstCfg_GetConfigPluggable () == TstCfg_PLUGGABLE_YES &&
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
#include "swad_profile.h"
|
||||
#include "swad_project.h"
|
||||
#include "swad_report.h"
|
||||
#include "swad_test_exam.h"
|
||||
#include "swad_test_print.h"
|
||||
#include "swad_timeline.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -1082,7 +1082,7 @@ void Acc_CompletelyEliminateAccount (struct UsrData *UsrDat,
|
|||
UsrDat->FullName);
|
||||
|
||||
/***** Remove test results made by user in all courses *****/
|
||||
TstRes_RemoveExamsMadeByUsrInAllCrss (UsrDat->UsrCod);
|
||||
TstPrn_RemoveExamsMadeByUsrInAllCrss (UsrDat->UsrCod);
|
||||
|
||||
/***** Remove user's notifications *****/
|
||||
Ntf_RemoveUsrNtfs (UsrDat->UsrCod);
|
||||
|
|
|
@ -670,12 +670,12 @@ const struct Act_Actions Act_Actions[Act_NUM_ACTIONS] =
|
|||
[ActRenTag ] = { 143,-1,TabUnk,ActReqTst ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Tst_RenameTag ,NULL},
|
||||
[ActRcvCfgTst ] = { 454,-1,TabUnk,ActReqTst ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,TstCfg_ReceiveConfigTst ,NULL},
|
||||
|
||||
[ActReqSeeMyTstRes ] = {1083,-1,TabUnk,ActReqTst ,0x208,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,Dat_SetIniEndDates ,TstRes_SelDatesToSeeMyExams ,NULL},
|
||||
[ActSeeMyTstRes ] = {1084,-1,TabUnk,ActReqTst ,0x208,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,TstRes_ShowMyExams ,NULL},
|
||||
[ActSeeOneTstResMe ] = {1085,-1,TabUnk,ActReqTst ,0x208,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,TstRes_ShowOneExam ,NULL},
|
||||
[ActReqSeeUsrTstRes ] = {1080,-1,TabUnk,ActReqTst ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,Dat_SetIniEndDates ,TstRes_SelUsrsToViewUsrsExams ,NULL},
|
||||
[ActSeeUsrTstRes ] = {1081,-1,TabUnk,ActReqTst ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,TstRes_GetUsrsAndShowExams ,NULL},
|
||||
[ActSeeOneTstResOth ] = {1082,-1,TabUnk,ActReqTst ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,TstRes_ShowOneExam ,NULL},
|
||||
[ActReqSeeMyTstRes ] = {1083,-1,TabUnk,ActReqTst ,0x208,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,Dat_SetIniEndDates ,TstPrn_SelDatesToSeeMyExams ,NULL},
|
||||
[ActSeeMyTstRes ] = {1084,-1,TabUnk,ActReqTst ,0x208,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,TstPrn_ShowMyExams ,NULL},
|
||||
[ActSeeOneTstResMe ] = {1085,-1,TabUnk,ActReqTst ,0x208,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,TstPrn_ShowOneExam ,NULL},
|
||||
[ActReqSeeUsrTstRes ] = {1080,-1,TabUnk,ActReqTst ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,Dat_SetIniEndDates ,TstPrn_SelUsrsToViewUsrsExams ,NULL},
|
||||
[ActSeeUsrTstRes ] = {1081,-1,TabUnk,ActReqTst ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,TstPrn_GetUsrsAndShowExams ,NULL},
|
||||
[ActSeeOneTstResOth ] = {1082,-1,TabUnk,ActReqTst ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,TstPrn_ShowOneExam ,NULL},
|
||||
|
||||
[ActSeeExa ] = {1849,-1,TabUnk,ActSeeAllExa ,0x238,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Exa_SeeOneExam ,NULL},
|
||||
|
||||
|
|
|
@ -548,11 +548,11 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - *
|
|||
En OpenSWAD:
|
||||
ps2pdf source.ps destination.pdf
|
||||
*/
|
||||
#define Log_PLATFORM_VERSION "SWAD 19.216.1 (2020-05-07)"
|
||||
#define CSS_FILE "swad19.193.1.css"
|
||||
#define Log_PLATFORM_VERSION "SWAD 19.217 (2020-05-07)"
|
||||
#define CSS_FILE "swad19.217.css"
|
||||
#define JS_FILE "swad19.193.1.js"
|
||||
/*
|
||||
Version 19.217: May 07, 2020 Generate and show questions of each set in an exam print. (? lines)
|
||||
Version 19.217: May 07, 2020 Generate and show questions of each set in an exam print. Not finished. (302124 lines)
|
||||
Version 19.216.1: May 07, 2020 Fixed bug in edition of exam questions, reported by Antonio Cañas Martínez.
|
||||
Changes in some texts. (301957 lines)
|
||||
Version 19.216: May 07, 2020 New module exam_print to generate new exam prints. (301949 lines)
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "swad_figure_cache.h"
|
||||
#include "swad_form.h"
|
||||
#include "swad_forum.h"
|
||||
#include "swad_game.h"
|
||||
#include "swad_global.h"
|
||||
#include "swad_help.h"
|
||||
#include "swad_HTML.h"
|
||||
|
@ -49,7 +50,7 @@
|
|||
#include "swad_project.h"
|
||||
#include "swad_search.h"
|
||||
#include "swad_survey.h"
|
||||
#include "swad_test_exam.h"
|
||||
#include "swad_test.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/************** External global variables from others modules ****************/
|
||||
|
@ -1988,7 +1989,7 @@ static void Crs_EmptyCourseCompletely (long CrsCod)
|
|||
Svy_RemoveSurveys (Hie_CRS,CrsCod);
|
||||
|
||||
/***** Remove all test exams made in the course *****/
|
||||
TstRes_RemoveCrsExams (CrsCod);
|
||||
TstPrn_RemoveCrsExams (CrsCod);
|
||||
|
||||
/***** Remove all tests questions in the course *****/
|
||||
Tst_RemoveCrsTests (CrsCod);
|
||||
|
|
|
@ -1768,7 +1768,7 @@ mysql> DESCRIBE mch_indexes;
|
|||
DB_CreateTable ("CREATE TABLE IF NOT EXISTS mch_indexes ("
|
||||
"MchCod INT NOT NULL,"
|
||||
"QstInd INT NOT NULL,"
|
||||
"Indexes TEXT NOT NULL," // TstRes_MAX_BYTES_INDEXES_ONE_QST
|
||||
"Indexes TEXT NOT NULL," // TstPrn_MAX_BYTES_INDEXES_ONE_QST
|
||||
"UNIQUE INDEX(MchCod,QstInd))");
|
||||
|
||||
/***** Table mch_results *****/
|
||||
|
@ -3189,8 +3189,8 @@ mysql> DESCRIBE tst_exam_questions;
|
|||
"QstCod INT NOT NULL,"
|
||||
"QstInd INT NOT NULL,"
|
||||
"Score DOUBLE PRECISION NOT NULL DEFAULT 0,"
|
||||
"Indexes TEXT NOT NULL," // TstRes_MAX_BYTES_INDEXES_ONE_QST
|
||||
"Answers TEXT NOT NULL," // TstRes_MAX_BYTES_ANSWERS_ONE_QST
|
||||
"Indexes TEXT NOT NULL," // TstPrn_MAX_BYTES_INDEXES_ONE_QST
|
||||
"Answers TEXT NOT NULL," // TstPrn_MAX_BYTES_ANSWERS_ONE_QST
|
||||
"UNIQUE INDEX(ExaCod,QstCod))");
|
||||
|
||||
/***** Table tst_exams *****/
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
#include "swad_parameter.h"
|
||||
#include "swad_photo.h"
|
||||
#include "swad_role.h"
|
||||
#include "swad_test_exam.h"
|
||||
#include "swad_test_print.h"
|
||||
#include "swad_user.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -4128,7 +4128,7 @@ static void Enr_EffectivelyRemUsrFromCrs (struct UsrData *UsrDat,
|
|||
Brw_RemoveSomeInfoAboutCrsUsrFilesFromDB (UsrDat->UsrCod,Crs->CrsCod);
|
||||
|
||||
/***** Remove test results made by user in course *****/
|
||||
TstRes_RemoveExamsMadeByUsrInCrs (UsrDat->UsrCod,Crs->CrsCod);
|
||||
TstPrn_RemoveExamsMadeByUsrInCrs (UsrDat->UsrCod,Crs->CrsCod);
|
||||
|
||||
/***** Set all the notifications for this user in this course as removed,
|
||||
except notifications about new messages *****/
|
||||
|
|
|
@ -239,7 +239,7 @@ static void ExaEvt_GetNumParticipants (struct ExaEvt_Event *Event);
|
|||
|
||||
static void ExaEvt_RemoveMyAnswerToEventQuestion (const struct ExaEvt_Event *Event);
|
||||
|
||||
static void ExaEvt_ComputeScore (struct TstRes_Result *Result);
|
||||
static void ExaEvt_ComputeScore (struct TstPrn_Print *Print);
|
||||
|
||||
static unsigned ExaEvt_GetNumUsrsWhoHaveAnswerEvt (long EvtCod);
|
||||
|
||||
|
@ -1934,7 +1934,7 @@ static void ExaEvt_ReorderAnswer (long EvtCod,unsigned QstInd,
|
|||
long LongNum;
|
||||
unsigned AnsInd;
|
||||
char StrOneAnswer[Cns_MAX_DECIMAL_DIGITS_UINT + 1];
|
||||
char StrAnswersOneQst[TstRes_MAX_BYTES_ANSWERS_ONE_QST + 1];
|
||||
char StrAnswersOneQst[TstPrn_MAX_BYTES_ANSWERS_ONE_QST + 1];
|
||||
|
||||
***** Initialize list of answers to empty string *****
|
||||
StrAnswersOneQst[0] = '\0';
|
||||
|
@ -1967,9 +1967,9 @@ static void ExaEvt_ReorderAnswer (long EvtCod,unsigned QstInd,
|
|||
* Concatenate answer index to list of answers *
|
||||
if (NumAns)
|
||||
Str_Concat (StrAnswersOneQst,",",
|
||||
TstRes_MAX_BYTES_ANSWERS_ONE_QST);
|
||||
TstPrn_MAX_BYTES_ANSWERS_ONE_QST);
|
||||
Str_Concat (StrAnswersOneQst,StrOneAnswer,
|
||||
TstRes_MAX_BYTES_ANSWERS_ONE_QST);
|
||||
TstPrn_MAX_BYTES_ANSWERS_ONE_QST);
|
||||
}
|
||||
|
||||
***** Free structure that stores the query result *****
|
||||
|
@ -1993,7 +1993,7 @@ void ExaEvt_GetIndexes (long EvtCod,unsigned QstInd,
|
|||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
char StrIndexesOneQst[TstRes_MAX_BYTES_INDEXES_ONE_QST + 1];
|
||||
char StrIndexesOneQst[TstPrn_MAX_BYTES_INDEXES_ONE_QST + 1];
|
||||
|
||||
/***** Get indexes for a question from database *****/
|
||||
if (!DB_QuerySELECT (&mysql_res,"can not get data of a question",
|
||||
|
@ -2006,14 +2006,14 @@ void ExaEvt_GetIndexes (long EvtCod,unsigned QstInd,
|
|||
|
||||
/* Get indexes (row[0]) */
|
||||
Str_Copy (StrIndexesOneQst,row[0],
|
||||
TstRes_MAX_BYTES_INDEXES_ONE_QST);
|
||||
TstPrn_MAX_BYTES_INDEXES_ONE_QST);
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
|
||||
/***** Get indexes from string *****/
|
||||
Par_ReplaceCommaBySeparatorMultiple (StrIndexesOneQst);
|
||||
TstRes_GetIndexesFromStr (StrIndexesOneQst,Indexes);
|
||||
TstPrn_GetIndexesFromStr (StrIndexesOneQst,Indexes);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -4212,7 +4212,7 @@ void ExaEvt_ReceiveQuestionAnswer (void)
|
|||
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION];
|
||||
struct ExaEvt_UsrAnswer PreviousUsrAnswer;
|
||||
struct ExaEvt_UsrAnswer UsrAnswer;
|
||||
struct TstRes_Result Result;
|
||||
struct TstPrn_Print Print;
|
||||
|
||||
/***** Reset event *****/
|
||||
ExaEvt_ResetEvent (&Event);
|
||||
|
@ -4271,8 +4271,8 @@ void ExaEvt_ReceiveQuestionAnswer (void)
|
|||
|
||||
/***** Update student's exam event result *****/
|
||||
ExaRes_GetExamResultQuestionsFromDB (Event.EvtCod,Gbl.Usrs.Me.UsrDat.UsrCod,
|
||||
&Result);
|
||||
ExaEvt_ComputeScore (&Result);
|
||||
&Print);
|
||||
ExaEvt_ComputeScore (&Print);
|
||||
|
||||
Str_SetDecimalPointToUS (); // To print the floating point as a dot
|
||||
if (DB_QueryCOUNT ("can not get if exam event result exists",
|
||||
|
@ -4287,9 +4287,9 @@ void ExaEvt_ReceiveQuestionAnswer (void)
|
|||
"NumQstsNotBlank=%u,"
|
||||
"Score='%.15lg'"
|
||||
" WHERE EvtCod=%ld AND UsrCod=%ld",
|
||||
Result.NumQsts,
|
||||
Result.NumQstsNotBlank,
|
||||
Result.Score,
|
||||
Print.NumQsts,
|
||||
Print.NumQstsNotBlank,
|
||||
Print.Score,
|
||||
Event.EvtCod,Gbl.Usrs.Me.UsrDat.UsrCod);
|
||||
else // Result doesn't exist
|
||||
/* Create result */
|
||||
|
@ -4305,9 +4305,9 @@ void ExaEvt_ReceiveQuestionAnswer (void)
|
|||
"%u," // NumQstsNotBlank
|
||||
"'%.15lg')", // Score
|
||||
Event.EvtCod,Gbl.Usrs.Me.UsrDat.UsrCod,
|
||||
Result.NumQsts,
|
||||
Result.NumQstsNotBlank,
|
||||
Result.Score);
|
||||
Print.NumQsts,
|
||||
Print.NumQstsNotBlank,
|
||||
Print.Score);
|
||||
Str_SetDecimalPointToLocal (); // Return to local system
|
||||
}
|
||||
|
||||
|
@ -4333,25 +4333,25 @@ static void ExaEvt_RemoveMyAnswerToEventQuestion (const struct ExaEvt_Event *Eve
|
|||
/******************** Compute exam event score for a student **********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void ExaEvt_ComputeScore (struct TstRes_Result *Result)
|
||||
static void ExaEvt_ComputeScore (struct TstPrn_Print *Print)
|
||||
{
|
||||
unsigned NumQst;
|
||||
struct Tst_Question Question;
|
||||
|
||||
for (NumQst = 0, Result->Score = 0.0;
|
||||
NumQst < Result->NumQsts;
|
||||
for (NumQst = 0, Print->Score = 0.0;
|
||||
NumQst < Print->NumQsts;
|
||||
NumQst++)
|
||||
{
|
||||
/***** Create test question *****/
|
||||
Tst_QstConstructor (&Question);
|
||||
Question.QstCod = Result->Questions[NumQst].QstCod;
|
||||
Question.QstCod = Print->PrintedQuestions[NumQst].QstCod;
|
||||
Question.Answer.Type = Tst_ANS_UNIQUE_CHOICE;
|
||||
|
||||
/***** Compute score for this answer ******/
|
||||
TstRes_ComputeChoiceAnsScore (Result,NumQst,&Question);
|
||||
TstPrn_ComputeChoiceAnsScore (Print,NumQst,&Question);
|
||||
|
||||
/***** Update total score *****/
|
||||
Result->Score += Result->Questions[NumQst].Score;
|
||||
Print->Score += Print->PrintedQuestions[NumQst].Score;
|
||||
|
||||
/***** Destroy test question *****/
|
||||
Tst_QstDestructor (&Question);
|
||||
|
|
|
@ -51,13 +51,22 @@ extern struct Globals Gbl;
|
|||
/***************************** Private constants *****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#define ExaPrn_MAX_QUESTIONS_PER_EXAM_PRINT 100 // Absolute maximum number of questions in an exam print
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************************* Private types *******************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
struct ExaPrn_Print
|
||||
{
|
||||
unsigned foo;
|
||||
long PrnCod; // Exam print code
|
||||
time_t TimeUTC[Dat_NUM_START_END_TIME];
|
||||
unsigned NumQsts; // Number of questions
|
||||
unsigned NumQstsNotBlank; // Number of questions not blank
|
||||
bool Sent; // This exam print has been sent or not?
|
||||
// "Sent" means that user has clicked "Send" button after finishing
|
||||
double Score; // Total score of the exam print
|
||||
struct TstPrn_PrintedQuestion PrintedQuestions[ExaPrn_MAX_QUESTIONS_PER_EXAM_PRINT];
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -72,11 +81,33 @@ struct ExaPrn_Print
|
|||
/***************************** Private prototypes ****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void ExaPrn_PrintConstructor (struct ExaPrn_Print *Print);
|
||||
static void ExaPrn_PrintDestructor (struct ExaPrn_Print *Print);
|
||||
static void ExaPrn_ResetPrint (struct ExaPrn_Print *Print);
|
||||
static void ExaPrn_ResetPrintExceptPrnCod (struct ExaPrn_Print *Print);
|
||||
|
||||
static void ExaPrn_GetQuestionsForNewPrintFromDB (struct Exa_Exam *Exam,
|
||||
struct ExaPrn_Print *Print);
|
||||
static void ExaPrn_ShowQuestionsFromSet (struct ExaPrn_Print *Print,
|
||||
struct ExaSet_Set *Set);
|
||||
|
||||
/*****************************************************************************/
|
||||
/**************************** Reset exam print *******************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void ExaPrn_ResetPrint (struct ExaPrn_Print *Print)
|
||||
{
|
||||
Print->PrnCod = -1L;
|
||||
ExaPrn_ResetPrintExceptPrnCod (Print);
|
||||
}
|
||||
|
||||
static void ExaPrn_ResetPrintExceptPrnCod (struct ExaPrn_Print *Print)
|
||||
{
|
||||
Print->TimeUTC[Dat_START_TIME] =
|
||||
Print->TimeUTC[Dat_END_TIME ] = (time_t) 0;
|
||||
Print->NumQsts =
|
||||
Print->NumQstsNotBlank = 0;
|
||||
Print->Sent = false; // After creating an exam print, it's not sent
|
||||
Print->Score = 0.0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************* Generate print of an exam in an event *******************/
|
||||
|
@ -94,13 +125,11 @@ void ExaPrn_ShowNewExamPrint (void)
|
|||
Exa_ResetExams (&Exams);
|
||||
Exa_ResetExam (&Exam);
|
||||
ExaEvt_ResetEvent (&Event);
|
||||
ExaPrn_ResetPrint (&Print);
|
||||
|
||||
/***** Get and check parameters *****/
|
||||
ExaEvt_GetAndCheckParameters (&Exams,&Exam,&Event);
|
||||
|
||||
/***** Create print *****/
|
||||
ExaPrn_PrintConstructor (&Print);
|
||||
|
||||
/***** Begin box *****/
|
||||
Box_BoxBegin (NULL,Exam.Title,
|
||||
NULL,NULL,
|
||||
|
@ -118,35 +147,12 @@ void ExaPrn_ShowNewExamPrint (void)
|
|||
|
||||
/***** End table *****/
|
||||
HTM_TABLE_End ();
|
||||
|
||||
/***** Destroy print *****/
|
||||
ExaPrn_PrintDestructor (&Print);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Print constructor *****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void ExaPrn_PrintConstructor (struct ExaPrn_Print *Print)
|
||||
{
|
||||
Print->foo = 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/****************************** Print destructor *****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void ExaPrn_PrintDestructor (struct ExaPrn_Print *Print)
|
||||
{
|
||||
Print->foo = 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*********** Get questions for a new exam print from the database ************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#define ExaPrn_MAX_BYTES_QUERY_PRINT (16 * 1024 - 1)
|
||||
|
||||
static void ExaPrn_GetQuestionsForNewPrintFromDB (struct Exa_Exam *Exam,
|
||||
struct ExaPrn_Print *Print)
|
||||
{
|
||||
|
@ -158,8 +164,6 @@ static void ExaPrn_GetQuestionsForNewPrintFromDB (struct Exa_Exam *Exam,
|
|||
unsigned NumSet;
|
||||
struct ExaSet_Set Set;
|
||||
|
||||
Print->foo = 1;
|
||||
|
||||
/***** Get data of set of questions from database *****/
|
||||
NumSets = (unsigned)
|
||||
DB_QuerySELECT (&mysql_res,"can not get sets of questions",
|
||||
|
@ -178,8 +182,6 @@ static void ExaPrn_GetQuestionsForNewPrintFromDB (struct Exa_Exam *Exam,
|
|||
NumSet < NumSets;
|
||||
NumSet++)
|
||||
{
|
||||
Gbl.RowEvenOdd = NumSet % 2;
|
||||
|
||||
/***** Create set of questions *****/
|
||||
ExaSet_ResetSet (&Set);
|
||||
|
||||
|
@ -200,26 +202,130 @@ static void ExaPrn_GetQuestionsForNewPrintFromDB (struct Exa_Exam *Exam,
|
|||
Str_Copy (Set.Title,row[2],
|
||||
ExaSet_MAX_BYTES_TITLE);
|
||||
|
||||
/***** Begin row for this set *****/
|
||||
/***** Title for this set *****/
|
||||
/* Begin title for this set */
|
||||
HTM_TR_Begin (NULL);
|
||||
HTM_TD_Begin ("colspan=\"2\"");
|
||||
HTM_TABLE_BeginWide ();
|
||||
|
||||
/***** Title *****/
|
||||
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
|
||||
/* Title */
|
||||
HTM_TD_Begin ("class=\"EXA_SET_TITLE\"");
|
||||
HTM_Txt (Set.Title);
|
||||
HTM_TD_End ();
|
||||
|
||||
/***** Number of questions to appear in exam print *****/
|
||||
HTM_TD_Begin ("class=\"RT COLOR%u\"",Gbl.RowEvenOdd);
|
||||
/* Number of questions to appear in exam print */
|
||||
HTM_TD_Begin ("class=\"EXA_SET_NUM_QSTS\"");
|
||||
HTM_Unsigned (Set.NumQstsToPrint);
|
||||
HTM_NBSP ();
|
||||
HTM_Txt (Set.NumQstsToPrint == 1 ? Txt_question :
|
||||
Txt_questions);
|
||||
HTM_TD_End ();
|
||||
|
||||
/***** End first row *****/
|
||||
/* End title for this set */
|
||||
HTM_TABLE_End ();
|
||||
HTM_TD_End ();
|
||||
HTM_TR_End ();
|
||||
|
||||
/***** Questions in this set *****/
|
||||
ExaPrn_ShowQuestionsFromSet (Print,&Set);
|
||||
}
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/************************ Show questions from a set **************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void ExaPrn_ShowQuestionsFromSet (struct ExaPrn_Print *Print,
|
||||
struct ExaSet_Set *Set)
|
||||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
unsigned NumQsts;
|
||||
unsigned NumQst;
|
||||
long QstCod;
|
||||
Tst_AnswerType_t AnswerType;
|
||||
bool Shuffle;
|
||||
|
||||
/***** Get questions from database *****/
|
||||
NumQsts = (unsigned)
|
||||
DB_QuerySELECT (&mysql_res,"can not get questions from set",
|
||||
"SELECT tst_questions.QstCod," // row[0]
|
||||
"tst_questions.AnsType," // row[1]
|
||||
"tst_questions.Shuffle" // row[2]
|
||||
" FROM exa_questions,tst_questions"
|
||||
" WHERE exa_questions.setCod=%ld"
|
||||
" AND exa_questions.QstCod=tst_questions.QstCod"
|
||||
" ORDER BY RAND(NOW())"
|
||||
" LIMIT %u",
|
||||
Set->SetCod,
|
||||
Set->NumQstsToPrint);
|
||||
|
||||
/***** Questions in this set *****/
|
||||
for (NumQst = 0;
|
||||
NumQst < NumQsts;
|
||||
NumQst++)
|
||||
{
|
||||
Gbl.RowEvenOdd = 1 - Gbl.RowEvenOdd;
|
||||
|
||||
/***** Get question data *****/
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
/*
|
||||
row[0] QstCod
|
||||
row[1] AnsType
|
||||
row[2] Shuffle
|
||||
*/
|
||||
|
||||
/* Get question code (row[0]) */
|
||||
QstCod = Str_ConvertStrCodToLongCod (row[0]);
|
||||
|
||||
/* Get answer type (row[1]) */
|
||||
AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
|
||||
|
||||
/* Get shuffle (row[2]) */
|
||||
Shuffle = (row[2][0] == 'Y');
|
||||
|
||||
/* Set indexes of answers */
|
||||
switch (AnswerType)
|
||||
{
|
||||
case Tst_ANS_INT:
|
||||
case Tst_ANS_FLOAT:
|
||||
case Tst_ANS_TRUE_FALSE:
|
||||
case Tst_ANS_TEXT:
|
||||
Print->PrintedQuestions[NumQst].StrIndexes[0] = '\0';
|
||||
break;
|
||||
case Tst_ANS_UNIQUE_CHOICE:
|
||||
case Tst_ANS_MULTIPLE_CHOICE:
|
||||
/* If answer type is unique or multiple option,
|
||||
generate indexes of answers depending on shuffle */
|
||||
Tst_GenerateChoiceIndexesDependingOnShuffle (&Print->PrintedQuestions[NumQst],Shuffle);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Reset user's answers.
|
||||
Initially user has not answered the question ==> initially all the answers will be blank.
|
||||
If the user does not confirm the submission of their exam ==>
|
||||
==> the exam may be half filled ==> the answers displayed will be those selected by the user. */
|
||||
Print->PrintedQuestions[NumQst].StrAnswers[0] = '\0';
|
||||
|
||||
/* Begin row for this question */
|
||||
HTM_TR_Begin (NULL);
|
||||
|
||||
/* Title */
|
||||
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
|
||||
HTM_TxtF ("Pregunta %ld",QstCod);
|
||||
HTM_TD_End ();
|
||||
|
||||
/* Number of questions to appear in exam print */
|
||||
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
|
||||
HTM_Txt ("Enunciado y respuestas");
|
||||
HTM_TD_End ();
|
||||
|
||||
/* End title for this question */
|
||||
HTM_TR_End ();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ static void ExaRes_ShowEvtResultsSummaryRow (unsigned NumResults,
|
|||
double TotalScoreOfAllResults,
|
||||
double TotalGrade);
|
||||
static void ExaRes_GetEventResultDataByEvtCod (long EvtCod,long UsrCod,
|
||||
struct TstRes_Result *Result);
|
||||
struct TstPrn_Print *Print);
|
||||
|
||||
static bool ExaRes_CheckIfICanSeeEventResult (struct ExaEvt_Event *Event,long UsrCod);
|
||||
static bool ExaRes_CheckIfICanViewScore (bool ICanViewResult,unsigned Visibility);
|
||||
|
@ -958,8 +958,8 @@ static void ExaRes_ShowEvtResults (struct Exa_Exams *Exams,
|
|||
HTM_TD_Begin ("class=\"DAT RT COLOR%u\"",Gbl.RowEvenOdd);
|
||||
if (ICanViewScore)
|
||||
{
|
||||
Grade = TstRes_ComputeGrade (NumQstsInThisResult,ScoreInThisResult,MaxGrade);
|
||||
TstRes_ShowGrade (Grade,MaxGrade);
|
||||
Grade = TstPrn_ComputeGrade (NumQstsInThisResult,ScoreInThisResult,MaxGrade);
|
||||
TstPrn_ShowGrade (Grade,MaxGrade);
|
||||
TotalGrade += Grade;
|
||||
}
|
||||
else
|
||||
|
@ -1092,7 +1092,7 @@ void ExaRes_ShowOneExaResult (void)
|
|||
struct UsrData *UsrDat;
|
||||
Dat_StartEndTime_t StartEndTime;
|
||||
char *Id;
|
||||
struct TstRes_Result Result;
|
||||
struct TstPrn_Print Print;
|
||||
bool ShowPhoto;
|
||||
char PhotoURL[PATH_MAX + 1];
|
||||
bool ICanViewResult;
|
||||
|
@ -1122,8 +1122,8 @@ void ExaRes_ShowOneExaResult (void)
|
|||
}
|
||||
|
||||
/***** Get event result data *****/
|
||||
TstRes_ResetResult (&Result);
|
||||
ExaRes_GetEventResultDataByEvtCod (Event.EvtCod,UsrDat->UsrCod,&Result);
|
||||
TstPrn_ResetResult (&Print);
|
||||
ExaRes_GetEventResultDataByEvtCod (Event.EvtCod,UsrDat->UsrCod,&Print);
|
||||
|
||||
/***** Check if I can view this event result *****/
|
||||
switch (Gbl.Usrs.Me.Role.Logged)
|
||||
|
@ -1154,7 +1154,7 @@ void ExaRes_ShowOneExaResult (void)
|
|||
{
|
||||
/***** Get questions and user's answers of the event result from database *****/
|
||||
ExaRes_GetExamResultQuestionsFromDB (Event.EvtCod,UsrDat->UsrCod,
|
||||
&Result);
|
||||
&Print);
|
||||
|
||||
/***** Begin box *****/
|
||||
Box_BoxBegin (NULL,Event.Title,
|
||||
|
@ -1230,8 +1230,8 @@ void ExaRes_ShowOneExaResult (void)
|
|||
|
||||
HTM_TD_Begin ("class=\"DAT LT\"");
|
||||
HTM_TxtF ("%u (%u %s)",
|
||||
Result.NumQsts,
|
||||
Result.NumQstsNotBlank,Txt_non_blank_QUESTIONS);
|
||||
Print.NumQsts,
|
||||
Print.NumQstsNotBlank,Txt_non_blank_QUESTIONS);
|
||||
HTM_TD_End ();
|
||||
|
||||
HTM_TR_End ();
|
||||
|
@ -1245,7 +1245,7 @@ void ExaRes_ShowOneExaResult (void)
|
|||
|
||||
HTM_TD_Begin ("class=\"DAT LT\"");
|
||||
if (ICanViewScore)
|
||||
HTM_Double2Decimals (Result.Score);
|
||||
HTM_Double2Decimals (Print.Score);
|
||||
else
|
||||
Ico_PutIconNotVisible ();
|
||||
HTM_TD_End ();
|
||||
|
@ -1261,7 +1261,7 @@ void ExaRes_ShowOneExaResult (void)
|
|||
|
||||
HTM_TD_Begin ("class=\"DAT LT\"");
|
||||
if (ICanViewScore)
|
||||
TstRes_ComputeAndShowGrade (Result.NumQsts,Result.Score,
|
||||
TstPrn_ComputeAndShowGrade (Print.NumQsts,Print.Score,
|
||||
Exam.MaxGrade);
|
||||
else
|
||||
Ico_PutIconNotVisible ();
|
||||
|
@ -1283,7 +1283,7 @@ void ExaRes_ShowOneExaResult (void)
|
|||
HTM_TR_End ();
|
||||
|
||||
/***** Write answers and solutions *****/
|
||||
TstRes_ShowExamAnswers (UsrDat,&Result,Exam.Visibility);
|
||||
TstPrn_ShowExamAnswers (UsrDat,&Print,Exam.Visibility);
|
||||
|
||||
/***** End table *****/
|
||||
HTM_TABLE_End ();
|
||||
|
@ -1293,10 +1293,10 @@ void ExaRes_ShowOneExaResult (void)
|
|||
{
|
||||
HTM_DIV_Begin ("class=\"DAT_N_BOLD CM\"");
|
||||
HTM_TxtColonNBSP (Txt_Score);
|
||||
HTM_Double2Decimals (Result.Score);
|
||||
HTM_Double2Decimals (Print.Score);
|
||||
HTM_BR ();
|
||||
HTM_TxtColonNBSP (Txt_Grade);
|
||||
TstRes_ComputeAndShowGrade (Result.NumQsts,Result.Score,
|
||||
TstPrn_ComputeAndShowGrade (Print.NumQsts,Print.Score,
|
||||
Exam.MaxGrade);
|
||||
HTM_DIV_End ();
|
||||
}
|
||||
|
@ -1313,7 +1313,7 @@ void ExaRes_ShowOneExaResult (void)
|
|||
/*****************************************************************************/
|
||||
|
||||
void ExaRes_GetExamResultQuestionsFromDB (long EvtCod,long UsrCod,
|
||||
struct TstRes_Result *Result)
|
||||
struct TstPrn_Print *Print)
|
||||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
|
@ -1323,27 +1323,27 @@ void ExaRes_GetExamResultQuestionsFromDB (long EvtCod,long UsrCod,
|
|||
struct ExaEvt_UsrAnswer UsrAnswer;
|
||||
|
||||
/***** Get questions and answers of a event result *****/
|
||||
Result->NumQsts = (unsigned)
|
||||
DB_QuerySELECT (&mysql_res,"can not get questions and answers"
|
||||
" of a event result",
|
||||
"SELECT exa_questions.QstCod," // row[0]
|
||||
"exa_questions.QstInd," // row[1]
|
||||
"exa_indexes.Indexes" // row[2]
|
||||
" FROM exa_events,exa_questions,exa_indexes"
|
||||
" WHERE exa_events.EvtCod=%ld"
|
||||
" AND exa_events.ExaCod=exa_questions.ExaCod"
|
||||
" AND exa_events.EvtCod=exa_indexes.EvtCod"
|
||||
" AND exa_questions.QstInd=exa_indexes.QstInd"
|
||||
" ORDER BY exa_questions.QstInd",
|
||||
EvtCod);
|
||||
for (NumQst = 0, Result->NumQstsNotBlank = 0;
|
||||
NumQst < Result->NumQsts;
|
||||
Print->NumQsts = (unsigned)
|
||||
DB_QuerySELECT (&mysql_res,"can not get questions and answers"
|
||||
" of a event result",
|
||||
"SELECT exa_questions.QstCod," // row[0]
|
||||
"exa_questions.QstInd," // row[1]
|
||||
"exa_indexes.Indexes" // row[2]
|
||||
" FROM exa_events,exa_questions,exa_indexes"
|
||||
" WHERE exa_events.EvtCod=%ld"
|
||||
" AND exa_events.ExaCod=exa_questions.ExaCod"
|
||||
" AND exa_events.EvtCod=exa_indexes.EvtCod"
|
||||
" AND exa_questions.QstInd=exa_indexes.QstInd"
|
||||
" ORDER BY exa_questions.QstInd",
|
||||
EvtCod);
|
||||
for (NumQst = 0, Print->NumQstsNotBlank = 0;
|
||||
NumQst < Print->NumQsts;
|
||||
NumQst++)
|
||||
{
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
|
||||
/* Get question code (row[0]) */
|
||||
if ((Result->Questions[NumQst].QstCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
|
||||
if ((Print->PrintedQuestions[NumQst].QstCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
|
||||
Lay_ShowErrorAndExit ("Wrong code of question.");
|
||||
|
||||
/* Get question index (row[1]) */
|
||||
|
@ -1352,24 +1352,24 @@ void ExaRes_GetExamResultQuestionsFromDB (long EvtCod,long UsrCod,
|
|||
QstInd = (unsigned) LongNum;
|
||||
|
||||
/* Get indexes for this question (row[2]) */
|
||||
Str_Copy (Result->Questions[NumQst].StrIndexes,row[2],
|
||||
TstRes_MAX_BYTES_INDEXES_ONE_QST);
|
||||
Str_Copy (Print->PrintedQuestions[NumQst].StrIndexes,row[2],
|
||||
TstPrn_MAX_BYTES_INDEXES_ONE_QST);
|
||||
|
||||
/* Get answers selected by user for this question */
|
||||
ExaEvt_GetQstAnsFromDB (EvtCod,UsrCod,QstInd,&UsrAnswer);
|
||||
if (UsrAnswer.AnsInd >= 0) // UsrAnswer.AnsInd >= 0 ==> answer selected
|
||||
{
|
||||
snprintf (Result->Questions[NumQst].StrAnswers,TstRes_MAX_BYTES_ANSWERS_ONE_QST + 1,
|
||||
snprintf (Print->PrintedQuestions[NumQst].StrAnswers,TstPrn_MAX_BYTES_ANSWERS_ONE_QST + 1,
|
||||
"%d",UsrAnswer.AnsInd);
|
||||
Result->NumQstsNotBlank++;
|
||||
Print->NumQstsNotBlank++;
|
||||
}
|
||||
else // UsrAnswer.AnsInd < 0 ==> no answer selected
|
||||
Result->Questions[NumQst].StrAnswers[0] = '\0'; // Empty answer
|
||||
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 (Result->Questions[NumQst].StrIndexes);
|
||||
Par_ReplaceCommaBySeparatorMultiple (Result->Questions[NumQst].StrAnswers);
|
||||
Par_ReplaceCommaBySeparatorMultiple (Print->PrintedQuestions[NumQst].StrIndexes);
|
||||
Par_ReplaceCommaBySeparatorMultiple (Print->PrintedQuestions[NumQst].StrAnswers);
|
||||
}
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
|
@ -1381,7 +1381,7 @@ void ExaRes_GetExamResultQuestionsFromDB (long EvtCod,long UsrCod,
|
|||
/*****************************************************************************/
|
||||
|
||||
static void ExaRes_GetEventResultDataByEvtCod (long EvtCod,long UsrCod,
|
||||
struct TstRes_Result *Result)
|
||||
struct TstPrn_Print *Print)
|
||||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
|
@ -1410,27 +1410,27 @@ static void ExaRes_GetEventResultDataByEvtCod (long EvtCod,long UsrCod,
|
|||
for (StartEndTime = (Dat_StartEndTime_t) 0;
|
||||
StartEndTime <= (Dat_StartEndTime_t) (Dat_NUM_START_END_TIME - 1);
|
||||
StartEndTime++)
|
||||
Result->TimeUTC[StartEndTime] = Dat_GetUNIXTimeFromStr (row[StartEndTime]);
|
||||
Print->TimeUTC[StartEndTime] = Dat_GetUNIXTimeFromStr (row[StartEndTime]);
|
||||
|
||||
/* Get number of questions (row[2]) */
|
||||
if (sscanf (row[2],"%u",&Result->NumQsts) != 1)
|
||||
Result->NumQsts = 0;
|
||||
if (sscanf (row[2],"%u",&Print->NumQsts) != 1)
|
||||
Print->NumQsts = 0;
|
||||
|
||||
/* Get number of questions not blank (row[3]) */
|
||||
if (sscanf (row[3],"%u",&Result->NumQstsNotBlank) != 1)
|
||||
Result->NumQstsNotBlank = 0;
|
||||
if (sscanf (row[3],"%u",&Print->NumQstsNotBlank) != 1)
|
||||
Print->NumQstsNotBlank = 0;
|
||||
|
||||
/* Get score (row[4]) */
|
||||
Str_SetDecimalPointToUS (); // To get the decimal point as a dot
|
||||
if (sscanf (row[4],"%lf",&Result->Score) != 1)
|
||||
Result->Score = 0.0;
|
||||
if (sscanf (row[4],"%lf",&Print->Score) != 1)
|
||||
Print->Score = 0.0;
|
||||
Str_SetDecimalPointToLocal (); // Return to local system
|
||||
}
|
||||
else
|
||||
{
|
||||
Result->NumQsts = 0;
|
||||
Result->NumQstsNotBlank = 0;
|
||||
Result->Score = 0.0;
|
||||
Print->NumQsts = 0;
|
||||
Print->NumQstsNotBlank = 0;
|
||||
Print->Score = 0.0;
|
||||
}
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
/********************************* Headers ***********************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "swad_test_exam.h"
|
||||
#include "swad_test_print.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/************************** Public types and constants ***********************/
|
||||
|
@ -51,6 +51,6 @@ void ExaRes_ShowAllExaResultsInEvt (void);
|
|||
|
||||
void ExaRes_ShowOneExaResult (void);
|
||||
void ExaRes_GetExamResultQuestionsFromDB (long EvtCod,long UsrCod,
|
||||
struct TstRes_Result *Result);
|
||||
struct TstPrn_Print *Print);
|
||||
|
||||
#endif
|
||||
|
|
48
swad_match.c
48
swad_match.c
|
@ -229,7 +229,7 @@ static void Mch_GetNumPlayers (struct Mch_Match *Match);
|
|||
|
||||
static void Mch_RemoveMyAnswerToMatchQuestion (const struct Mch_Match *Match);
|
||||
|
||||
static void Mch_ComputeScore (struct TstRes_Result *Result);
|
||||
static void Mch_ComputeScore (struct TstPrn_Print *Print);
|
||||
|
||||
static unsigned Mch_GetNumUsrsWhoHaveAnswerMch (long MchCod);
|
||||
|
||||
|
@ -1612,7 +1612,7 @@ static void Mch_ReorderAnswer (long MchCod,unsigned QstInd,
|
|||
long LongNum;
|
||||
unsigned AnsInd;
|
||||
char StrOneAnswer[Cns_MAX_DECIMAL_DIGITS_UINT + 1];
|
||||
char StrAnswersOneQst[TstRes_MAX_BYTES_ANSWERS_ONE_QST + 1];
|
||||
char StrAnswersOneQst[TstPrn_MAX_BYTES_ANSWERS_ONE_QST + 1];
|
||||
|
||||
/***** Initialize list of answers to empty string *****/
|
||||
StrAnswersOneQst[0] = '\0';
|
||||
|
@ -1645,9 +1645,9 @@ static void Mch_ReorderAnswer (long MchCod,unsigned QstInd,
|
|||
/* Concatenate answer index to list of answers */
|
||||
if (NumAns)
|
||||
Str_Concat (StrAnswersOneQst,",",
|
||||
TstRes_MAX_BYTES_ANSWERS_ONE_QST);
|
||||
TstPrn_MAX_BYTES_ANSWERS_ONE_QST);
|
||||
Str_Concat (StrAnswersOneQst,StrOneAnswer,
|
||||
TstRes_MAX_BYTES_ANSWERS_ONE_QST);
|
||||
TstPrn_MAX_BYTES_ANSWERS_ONE_QST);
|
||||
}
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
|
@ -1671,7 +1671,7 @@ void Mch_GetIndexes (long MchCod,unsigned QstInd,
|
|||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
char StrIndexesOneQst[TstRes_MAX_BYTES_INDEXES_ONE_QST + 1];
|
||||
char StrIndexesOneQst[TstPrn_MAX_BYTES_INDEXES_ONE_QST + 1];
|
||||
|
||||
/***** Get indexes for a question from database *****/
|
||||
if (!DB_QuerySELECT (&mysql_res,"can not get data of a question",
|
||||
|
@ -1684,14 +1684,14 @@ void Mch_GetIndexes (long MchCod,unsigned QstInd,
|
|||
|
||||
/* Get indexes (row[0]) */
|
||||
Str_Copy (StrIndexesOneQst,row[0],
|
||||
TstRes_MAX_BYTES_INDEXES_ONE_QST);
|
||||
TstPrn_MAX_BYTES_INDEXES_ONE_QST);
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
|
||||
/***** Get indexes from string *****/
|
||||
Par_ReplaceCommaBySeparatorMultiple (StrIndexesOneQst);
|
||||
TstRes_GetIndexesFromStr (StrIndexesOneQst,Indexes);
|
||||
TstPrn_GetIndexesFromStr (StrIndexesOneQst,Indexes);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -3881,7 +3881,7 @@ void Mch_ReceiveQuestionAnswer (void)
|
|||
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION];
|
||||
struct Mch_UsrAnswer PreviousUsrAnswer;
|
||||
struct Mch_UsrAnswer UsrAnswer;
|
||||
struct TstRes_Result Result;
|
||||
struct TstPrn_Print Print;
|
||||
|
||||
/***** Reset match *****/
|
||||
Mch_ResetMatch (&Match);
|
||||
|
@ -3940,14 +3940,14 @@ void Mch_ReceiveQuestionAnswer (void)
|
|||
|
||||
/***** Update student's match result *****/
|
||||
MchRes_GetMatchResultQuestionsFromDB (Match.MchCod,Gbl.Usrs.Me.UsrDat.UsrCod,
|
||||
&Result);
|
||||
Mch_ComputeScore (&Result);
|
||||
&Print);
|
||||
Mch_ComputeScore (&Print);
|
||||
|
||||
Str_SetDecimalPointToUS (); // To print the floating point as a dot
|
||||
if (DB_QueryCOUNT ("can not get if match result exists",
|
||||
"SELECT COUNT(*) FROM mch_results"
|
||||
" WHERE MchCod=%ld AND UsrCod=%ld",
|
||||
Match.MchCod,Gbl.Usrs.Me.UsrDat.UsrCod)) // Result exists
|
||||
Match.MchCod,Gbl.Usrs.Me.UsrDat.UsrCod)) // Match print exists
|
||||
/* Update result */
|
||||
DB_QueryUPDATE ("can not update match result",
|
||||
"UPDATE mch_results"
|
||||
|
@ -3956,11 +3956,11 @@ void Mch_ReceiveQuestionAnswer (void)
|
|||
"NumQstsNotBlank=%u,"
|
||||
"Score='%.15lg'"
|
||||
" WHERE MchCod=%ld AND UsrCod=%ld",
|
||||
Result.NumQsts,
|
||||
Result.NumQstsNotBlank,
|
||||
Result.Score,
|
||||
Print.NumQsts,
|
||||
Print.NumQstsNotBlank,
|
||||
Print.Score,
|
||||
Match.MchCod,Gbl.Usrs.Me.UsrDat.UsrCod);
|
||||
else // Result doesn't exist
|
||||
else // Match print doesn't exist
|
||||
/* Create result */
|
||||
DB_QueryINSERT ("can not create match result",
|
||||
"INSERT mch_results "
|
||||
|
@ -3974,9 +3974,9 @@ void Mch_ReceiveQuestionAnswer (void)
|
|||
"%u," // NumQstsNotBlank
|
||||
"'%.15lg')", // Score
|
||||
Match.MchCod,Gbl.Usrs.Me.UsrDat.UsrCod,
|
||||
Result.NumQsts,
|
||||
Result.NumQstsNotBlank,
|
||||
Result.Score);
|
||||
Print.NumQsts,
|
||||
Print.NumQstsNotBlank,
|
||||
Print.Score);
|
||||
Str_SetDecimalPointToLocal (); // Return to local system
|
||||
}
|
||||
|
||||
|
@ -4002,25 +4002,25 @@ static void Mch_RemoveMyAnswerToMatchQuestion (const struct Mch_Match *Match)
|
|||
/******************** Compute match score for a student **********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Mch_ComputeScore (struct TstRes_Result *Result)
|
||||
static void Mch_ComputeScore (struct TstPrn_Print *Print)
|
||||
{
|
||||
unsigned NumQst;
|
||||
struct Tst_Question Question;
|
||||
|
||||
for (NumQst = 0, Result->Score = 0.0;
|
||||
NumQst < Result->NumQsts;
|
||||
for (NumQst = 0, Print->Score = 0.0;
|
||||
NumQst < Print->NumQsts;
|
||||
NumQst++)
|
||||
{
|
||||
/***** Create test question *****/
|
||||
Tst_QstConstructor (&Question);
|
||||
Question.QstCod = Result->Questions[NumQst].QstCod;
|
||||
Question.QstCod = Print->PrintedQuestions[NumQst].QstCod;
|
||||
Question.Answer.Type = Tst_ANS_UNIQUE_CHOICE;
|
||||
|
||||
/***** Compute score for this answer ******/
|
||||
TstRes_ComputeChoiceAnsScore (Result,NumQst,&Question);
|
||||
TstPrn_ComputeChoiceAnsScore (Print,NumQst,&Question);
|
||||
|
||||
/***** Update total score *****/
|
||||
Result->Score += Result->Questions[NumQst].Score;
|
||||
Print->Score += Print->PrintedQuestions[NumQst].Score;
|
||||
|
||||
/***** Destroy test question *****/
|
||||
Tst_QstDestructor (&Question);
|
||||
|
|
|
@ -101,7 +101,7 @@ static void MchRes_ShowMchResultsSummaryRow (unsigned NumResults,
|
|||
double TotalScoreOfAllResults,
|
||||
double TotalGrade);
|
||||
static void MchRes_GetMatchResultDataByMchCod (long MchCod,long UsrCod,
|
||||
struct TstRes_Result *Result);
|
||||
struct TstPrn_Print *Print);
|
||||
|
||||
static bool MchRes_CheckIfICanSeeMatchResult (struct Mch_Match *Match,long UsrCod);
|
||||
static bool MchRes_CheckIfICanViewScore (bool ICanViewResult,unsigned Visibility);
|
||||
|
@ -947,8 +947,8 @@ static void MchRes_ShowMchResults (struct Gam_Games *Games,
|
|||
HTM_TD_Begin ("class=\"DAT RT COLOR%u\"",Gbl.RowEvenOdd);
|
||||
if (ICanViewScore)
|
||||
{
|
||||
Grade = TstRes_ComputeGrade (NumQstsInThisResult,ScoreInThisResult,MaxGrade);
|
||||
TstRes_ShowGrade (Grade,MaxGrade);
|
||||
Grade = TstPrn_ComputeGrade (NumQstsInThisResult,ScoreInThisResult,MaxGrade);
|
||||
TstPrn_ShowGrade (Grade,MaxGrade);
|
||||
TotalGrade += Grade;
|
||||
}
|
||||
else
|
||||
|
@ -1081,7 +1081,7 @@ void MchRes_ShowOneMchResult (void)
|
|||
struct UsrData *UsrDat;
|
||||
Dat_StartEndTime_t StartEndTime;
|
||||
char *Id;
|
||||
struct TstRes_Result Result;
|
||||
struct TstPrn_Print Print;
|
||||
bool ShowPhoto;
|
||||
char PhotoURL[PATH_MAX + 1];
|
||||
bool ICanViewResult;
|
||||
|
@ -1113,8 +1113,8 @@ void MchRes_ShowOneMchResult (void)
|
|||
}
|
||||
|
||||
/***** Get match result data *****/
|
||||
TstRes_ResetResult (&Result);
|
||||
MchRes_GetMatchResultDataByMchCod (Match.MchCod,UsrDat->UsrCod,&Result);
|
||||
TstPrn_ResetResult (&Print);
|
||||
MchRes_GetMatchResultDataByMchCod (Match.MchCod,UsrDat->UsrCod,&Print);
|
||||
|
||||
/***** Check if I can view this match result *****/
|
||||
switch (Gbl.Usrs.Me.Role.Logged)
|
||||
|
@ -1145,7 +1145,7 @@ void MchRes_ShowOneMchResult (void)
|
|||
{
|
||||
/***** Get questions and user's answers of the match result from database *****/
|
||||
MchRes_GetMatchResultQuestionsFromDB (Match.MchCod,UsrDat->UsrCod,
|
||||
&Result);
|
||||
&Print);
|
||||
|
||||
/***** Begin box *****/
|
||||
Box_BoxBegin (NULL,Match.Title,
|
||||
|
@ -1203,7 +1203,7 @@ void MchRes_ShowOneMchResult (void)
|
|||
if (asprintf (&Id,"match_%u",(unsigned) StartEndTime) < 0)
|
||||
Lay_NotEnoughMemoryExit ();
|
||||
HTM_TD_Begin ("id=\"%s\" class=\"DAT LT\"",Id);
|
||||
Dat_WriteLocalDateHMSFromUTC (Id,Result.TimeUTC[StartEndTime],
|
||||
Dat_WriteLocalDateHMSFromUTC (Id,Print.TimeUTC[StartEndTime],
|
||||
Gbl.Prefs.DateFormat,Dat_SEPARATOR_COMMA,
|
||||
true,true,true,0x7);
|
||||
HTM_TD_End ();
|
||||
|
@ -1221,8 +1221,8 @@ void MchRes_ShowOneMchResult (void)
|
|||
|
||||
HTM_TD_Begin ("class=\"DAT LT\"");
|
||||
HTM_TxtF ("%u (%u %s)",
|
||||
Result.NumQsts,
|
||||
Result.NumQstsNotBlank,Txt_non_blank_QUESTIONS);
|
||||
Print.NumQsts,
|
||||
Print.NumQstsNotBlank,Txt_non_blank_QUESTIONS);
|
||||
HTM_TD_End ();
|
||||
|
||||
HTM_TR_End ();
|
||||
|
@ -1236,7 +1236,7 @@ void MchRes_ShowOneMchResult (void)
|
|||
|
||||
HTM_TD_Begin ("class=\"DAT LT\"");
|
||||
if (ICanViewScore)
|
||||
HTM_Double2Decimals (Result.Score);
|
||||
HTM_Double2Decimals (Print.Score);
|
||||
else
|
||||
Ico_PutIconNotVisible ();
|
||||
HTM_TD_End ();
|
||||
|
@ -1252,7 +1252,7 @@ void MchRes_ShowOneMchResult (void)
|
|||
|
||||
HTM_TD_Begin ("class=\"DAT LT\"");
|
||||
if (ICanViewScore)
|
||||
TstRes_ComputeAndShowGrade (Result.NumQsts,Result.Score,
|
||||
TstPrn_ComputeAndShowGrade (Print.NumQsts,Print.Score,
|
||||
Game.MaxGrade);
|
||||
else
|
||||
Ico_PutIconNotVisible ();
|
||||
|
@ -1274,7 +1274,7 @@ void MchRes_ShowOneMchResult (void)
|
|||
HTM_TR_End ();
|
||||
|
||||
/***** Write answers and solutions *****/
|
||||
TstRes_ShowExamAnswers (UsrDat,&Result,Game.Visibility);
|
||||
TstPrn_ShowExamAnswers (UsrDat,&Print,Game.Visibility);
|
||||
|
||||
/***** End table *****/
|
||||
HTM_TABLE_End ();
|
||||
|
@ -1284,10 +1284,10 @@ void MchRes_ShowOneMchResult (void)
|
|||
{
|
||||
HTM_DIV_Begin ("class=\"DAT_N_BOLD CM\"");
|
||||
HTM_TxtColonNBSP (Txt_Score);
|
||||
HTM_Double2Decimals (Result.Score);
|
||||
HTM_Double2Decimals (Print.Score);
|
||||
HTM_BR ();
|
||||
HTM_TxtColonNBSP (Txt_Grade);
|
||||
TstRes_ComputeAndShowGrade (Result.NumQsts,Result.Score,
|
||||
TstPrn_ComputeAndShowGrade (Print.NumQsts,Print.Score,
|
||||
Game.MaxGrade);
|
||||
HTM_DIV_End ();
|
||||
}
|
||||
|
@ -1304,7 +1304,7 @@ void MchRes_ShowOneMchResult (void)
|
|||
/*****************************************************************************/
|
||||
|
||||
void MchRes_GetMatchResultQuestionsFromDB (long MchCod,long UsrCod,
|
||||
struct TstRes_Result *Result)
|
||||
struct TstPrn_Print *Print)
|
||||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
|
@ -1314,27 +1314,27 @@ void MchRes_GetMatchResultQuestionsFromDB (long MchCod,long UsrCod,
|
|||
struct Mch_UsrAnswer UsrAnswer;
|
||||
|
||||
/***** Get questions and answers of a match result *****/
|
||||
Result->NumQsts = (unsigned)
|
||||
DB_QuerySELECT (&mysql_res,"can not get questions and answers"
|
||||
" of a match result",
|
||||
"SELECT gam_questions.QstCod," // row[0]
|
||||
"gam_questions.QstInd," // row[1]
|
||||
"mch_indexes.Indexes" // row[2]
|
||||
" FROM mch_matches,gam_questions,mch_indexes"
|
||||
" WHERE mch_matches.MchCod=%ld"
|
||||
" AND mch_matches.GamCod=gam_questions.GamCod"
|
||||
" AND mch_matches.MchCod=mch_indexes.MchCod"
|
||||
" AND gam_questions.QstInd=mch_indexes.QstInd"
|
||||
" ORDER BY gam_questions.QstInd",
|
||||
MchCod);
|
||||
for (NumQst = 0, Result->NumQstsNotBlank = 0;
|
||||
NumQst < Result->NumQsts;
|
||||
Print->NumQsts = (unsigned)
|
||||
DB_QuerySELECT (&mysql_res,"can not get questions and answers"
|
||||
" of a match result",
|
||||
"SELECT gam_questions.QstCod," // row[0]
|
||||
"gam_questions.QstInd," // row[1]
|
||||
"mch_indexes.Indexes" // row[2]
|
||||
" FROM mch_matches,gam_questions,mch_indexes"
|
||||
" WHERE mch_matches.MchCod=%ld"
|
||||
" AND mch_matches.GamCod=gam_questions.GamCod"
|
||||
" AND mch_matches.MchCod=mch_indexes.MchCod"
|
||||
" AND gam_questions.QstInd=mch_indexes.QstInd"
|
||||
" ORDER BY gam_questions.QstInd",
|
||||
MchCod);
|
||||
for (NumQst = 0, Print->NumQstsNotBlank = 0;
|
||||
NumQst < Print->NumQsts;
|
||||
NumQst++)
|
||||
{
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
|
||||
/* Get question code (row[0]) */
|
||||
if ((Result->Questions[NumQst].QstCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
|
||||
if ((Print->PrintedQuestions[NumQst].QstCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
|
||||
Lay_ShowErrorAndExit ("Wrong code of question.");
|
||||
|
||||
/* Get question index (row[1]) */
|
||||
|
@ -1343,24 +1343,24 @@ void MchRes_GetMatchResultQuestionsFromDB (long MchCod,long UsrCod,
|
|||
QstInd = (unsigned) LongNum;
|
||||
|
||||
/* Get indexes for this question (row[2]) */
|
||||
Str_Copy (Result->Questions[NumQst].StrIndexes,row[2],
|
||||
TstRes_MAX_BYTES_INDEXES_ONE_QST);
|
||||
Str_Copy (Print->PrintedQuestions[NumQst].StrIndexes,row[2],
|
||||
TstPrn_MAX_BYTES_INDEXES_ONE_QST);
|
||||
|
||||
/* Get answers selected by user for this question */
|
||||
Mch_GetQstAnsFromDB (MchCod,UsrCod,QstInd,&UsrAnswer);
|
||||
if (UsrAnswer.AnsInd >= 0) // UsrAnswer.AnsInd >= 0 ==> answer selected
|
||||
{
|
||||
snprintf (Result->Questions[NumQst].StrAnswers,TstRes_MAX_BYTES_ANSWERS_ONE_QST + 1,
|
||||
snprintf (Print->PrintedQuestions[NumQst].StrAnswers,TstPrn_MAX_BYTES_ANSWERS_ONE_QST + 1,
|
||||
"%d",UsrAnswer.AnsInd);
|
||||
Result->NumQstsNotBlank++;
|
||||
Print->NumQstsNotBlank++;
|
||||
}
|
||||
else // UsrAnswer.AnsInd < 0 ==> no answer selected
|
||||
Result->Questions[NumQst].StrAnswers[0] = '\0'; // Empty answer
|
||||
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 (Result->Questions[NumQst].StrIndexes);
|
||||
Par_ReplaceCommaBySeparatorMultiple (Result->Questions[NumQst].StrAnswers);
|
||||
Par_ReplaceCommaBySeparatorMultiple (Print->PrintedQuestions[NumQst].StrIndexes);
|
||||
Par_ReplaceCommaBySeparatorMultiple (Print->PrintedQuestions[NumQst].StrAnswers);
|
||||
}
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
|
@ -1372,7 +1372,7 @@ void MchRes_GetMatchResultQuestionsFromDB (long MchCod,long UsrCod,
|
|||
/*****************************************************************************/
|
||||
|
||||
static void MchRes_GetMatchResultDataByMchCod (long MchCod,long UsrCod,
|
||||
struct TstRes_Result *Result)
|
||||
struct TstPrn_Print *Print)
|
||||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
|
@ -1401,27 +1401,27 @@ static void MchRes_GetMatchResultDataByMchCod (long MchCod,long UsrCod,
|
|||
for (StartEndTime = (Dat_StartEndTime_t) 0;
|
||||
StartEndTime <= (Dat_StartEndTime_t) (Dat_NUM_START_END_TIME - 1);
|
||||
StartEndTime++)
|
||||
Result->TimeUTC[StartEndTime] = Dat_GetUNIXTimeFromStr (row[StartEndTime]);
|
||||
Print->TimeUTC[StartEndTime] = Dat_GetUNIXTimeFromStr (row[StartEndTime]);
|
||||
|
||||
/* Get number of questions (row[2]) */
|
||||
if (sscanf (row[2],"%u",&Result->NumQsts) != 1)
|
||||
Result->NumQsts = 0;
|
||||
if (sscanf (row[2],"%u",&Print->NumQsts) != 1)
|
||||
Print->NumQsts = 0;
|
||||
|
||||
/* Get number of questions not blank (row[3]) */
|
||||
if (sscanf (row[3],"%u",&Result->NumQstsNotBlank) != 1)
|
||||
Result->NumQstsNotBlank = 0;
|
||||
if (sscanf (row[3],"%u",&Print->NumQstsNotBlank) != 1)
|
||||
Print->NumQstsNotBlank = 0;
|
||||
|
||||
/* Get score (row[4]) */
|
||||
Str_SetDecimalPointToUS (); // To get the decimal point as a dot
|
||||
if (sscanf (row[4],"%lf",&Result->Score) != 1)
|
||||
Result->Score = 0.0;
|
||||
if (sscanf (row[4],"%lf",&Print->Score) != 1)
|
||||
Print->Score = 0.0;
|
||||
Str_SetDecimalPointToLocal (); // Return to local system
|
||||
}
|
||||
else
|
||||
{
|
||||
Result->NumQsts = 0;
|
||||
Result->NumQstsNotBlank = 0;
|
||||
Result->Score = 0.0;
|
||||
Print->NumQsts = 0;
|
||||
Print->NumQstsNotBlank = 0;
|
||||
Print->Score = 0.0;
|
||||
}
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
/********************************* Headers ***********************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "swad_test_exam.h"
|
||||
#include "swad_test_print.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/************************** Public types and constants ***********************/
|
||||
|
@ -51,6 +51,6 @@ void MchRes_ShowAllMchResultsInMch (void);
|
|||
|
||||
void MchRes_ShowOneMchResult (void);
|
||||
void MchRes_GetMatchResultQuestionsFromDB (long MchCod,long UsrCod,
|
||||
struct TstRes_Result *Result);
|
||||
struct TstPrn_Print *Print);
|
||||
|
||||
#endif
|
||||
|
|
191
swad_test.c
191
swad_test.c
|
@ -52,9 +52,9 @@
|
|||
#include "swad_parameter.h"
|
||||
#include "swad_theme.h"
|
||||
#include "swad_test.h"
|
||||
#include "swad_test_exam.h"
|
||||
#include "swad_test_config.h"
|
||||
#include "swad_test_import.h"
|
||||
#include "swad_test_print.h"
|
||||
#include "swad_test_visibility.h"
|
||||
#include "swad_user.h"
|
||||
#include "swad_xml.h"
|
||||
|
@ -133,15 +133,15 @@ static void Tst_ShowFormRequestTest (struct Tst_Test *Test);
|
|||
|
||||
static void Tst_PutCheckBoxAllowTeachers (bool AllowTeachers);
|
||||
|
||||
static void Tst_GetAnswersFromForm (struct TstRes_Result *Result);
|
||||
static void Tst_GetAnswersFromForm (struct TstPrn_Print *Print);
|
||||
|
||||
static bool Tst_CheckIfNextTstAllowed (void);
|
||||
static unsigned Tst_GetNumExamsGeneratedByMe (void);
|
||||
static void Tst_ShowTestExamToFillIt (struct TstRes_Result *Result,
|
||||
static void Tst_ShowTestExamToFillIt (struct TstPrn_Print *Print,
|
||||
unsigned NumExamsGeneratedByMe,
|
||||
Tst_RequestOrConfirm_t RequestOrConfirm);
|
||||
|
||||
static void Tst_WriteQstAndAnsSeeing (const struct TstRes_Result *Result,
|
||||
static void Tst_WriteQstAndAnsSeeing (const struct TstPrn_Print *Print,
|
||||
unsigned NumQst,
|
||||
const struct Tst_Question *Question);
|
||||
|
||||
|
@ -177,10 +177,7 @@ static void Tst_PutInputFieldNumQst (const char *Field,const char *Label,
|
|||
static void Tst_ShowFormAnswerTypes (const struct Tst_AnswerTypes *AnswerTypes);
|
||||
static void Tst_GetQuestions (struct Tst_Test *Test,MYSQL_RES **mysql_res);
|
||||
static void Tst_GetQuestionsForNewTestFromDB (struct Tst_Test *Test,
|
||||
struct TstRes_Result *Result);
|
||||
static void Tst_GenerateChoiceIndexesDependingOnShuffle (struct TstRes_Result *Result,
|
||||
unsigned NumQst,
|
||||
bool Shuffle);
|
||||
struct TstPrn_Print *Print);
|
||||
|
||||
static void Tst_ListOneQstToEdit (struct Tst_Test *Test);
|
||||
static void Tst_ListOneOrMoreQuestionsForEdition (struct Tst_Test *Test,
|
||||
|
@ -196,28 +193,28 @@ static void Tst_ListOneOrMoreQuestionsForSelectionForGame (struct Gam_Games *Gam
|
|||
static void Tst_WriteQuestionRowForSelection (unsigned NumQst,
|
||||
struct Tst_Question *Question);
|
||||
|
||||
static void Tst_WriteAnswersSeeing (const struct TstRes_Result *Result,
|
||||
static void Tst_WriteAnswersSeeing (const struct TstPrn_Print *Print,
|
||||
unsigned NumQst,
|
||||
const struct Tst_Question *Question);
|
||||
|
||||
static void Tst_WriteIntAnsListing (const struct Tst_Question *Question);
|
||||
static void Tst_WriteIntAnsSeeing (const struct TstRes_Result *Result,
|
||||
static void Tst_WriteIntAnsSeeing (const struct TstPrn_Print *Print,
|
||||
unsigned NumQst);
|
||||
|
||||
static void Tst_WriteFloatAnsEdit (const struct Tst_Question *Question);
|
||||
static void Tst_WriteFloatAnsSeeing (const struct TstRes_Result *Result,
|
||||
static void Tst_WriteFloatAnsSeeing (const struct TstPrn_Print *Print,
|
||||
unsigned NumQst);
|
||||
|
||||
static void Tst_WriteTFAnsListing (const struct Tst_Question *Question);
|
||||
static void Tst_WriteTFAnsSeeing (const struct TstRes_Result *Result,
|
||||
static void Tst_WriteTFAnsSeeing (const struct TstPrn_Print *Print,
|
||||
unsigned NumQst);
|
||||
|
||||
static void Tst_WriteChoiceAnsListing (const struct Tst_Question *Question);
|
||||
static void Tst_WriteChoiceAnsSeeing (const struct TstRes_Result *Result,
|
||||
static void Tst_WriteChoiceAnsSeeing (const struct TstPrn_Print *Print,
|
||||
unsigned NumQst,
|
||||
const struct Tst_Question *Question);
|
||||
|
||||
static void Tst_WriteTextAnsSeeing (const struct TstRes_Result *Result,
|
||||
static void Tst_WriteTextAnsSeeing (const struct TstPrn_Print *Print,
|
||||
unsigned NumQst);
|
||||
|
||||
static void Tst_WriteParamQstCod (unsigned NumQst,long QstCod);
|
||||
|
@ -446,7 +443,7 @@ void Tst_ShowNewTest (void)
|
|||
{
|
||||
extern const char *Txt_No_questions_found_matching_your_search_criteria;
|
||||
struct Tst_Test Test;
|
||||
struct TstRes_Result Exam;
|
||||
struct TstPrn_Print Print;
|
||||
unsigned NumExamsGeneratedByMe;
|
||||
|
||||
/***** Create test *****/
|
||||
|
@ -461,21 +458,21 @@ void Tst_ShowNewTest (void)
|
|||
if (Tst_GetParamsTst (&Test,Tst_SHOW_TEST_TO_ANSWER)) // Get parameters from form
|
||||
{
|
||||
/***** Get questions *****/
|
||||
TstRes_ResetResult (&Exam);
|
||||
Tst_GetQuestionsForNewTestFromDB (&Test,&Exam);
|
||||
if (Exam.NumQsts)
|
||||
TstPrn_ResetResult (&Print);
|
||||
Tst_GetQuestionsForNewTestFromDB (&Test,&Print);
|
||||
if (Print.NumQsts)
|
||||
{
|
||||
/***** Increase number of exams generated (answered or not) by me *****/
|
||||
Tst_IncreaseMyNumAccessTst ();
|
||||
NumExamsGeneratedByMe = Tst_GetNumExamsGeneratedByMe ();
|
||||
|
||||
/***** Create new test exam in database *****/
|
||||
TstRes_CreateExamInDB (&Exam);
|
||||
TstRes_ComputeScoresAndStoreExamQuestions (&Exam,
|
||||
TstPrn_CreateExamInDB (&Print);
|
||||
TstPrn_ComputeScoresAndStoreExamQuestions (&Print,
|
||||
false); // Don't update question score
|
||||
|
||||
/***** Show test exam to be answered *****/
|
||||
Tst_ShowTestExamToFillIt (&Exam,NumExamsGeneratedByMe,Tst_REQUEST);
|
||||
Tst_ShowTestExamToFillIt (&Print,NumExamsGeneratedByMe,Tst_REQUEST);
|
||||
|
||||
/***** Update date-time of my next allowed access to test *****/
|
||||
if (Gbl.Usrs.Me.Role.Logged == Rol_STD)
|
||||
|
@ -523,47 +520,48 @@ static void Tst_PutCheckBoxAllowTeachers (bool AllowTeachers)
|
|||
void Tst_ReceiveTestDraft (void)
|
||||
{
|
||||
extern const char *Txt_The_test_X_has_already_been_assessed_previously;
|
||||
extern const char *Txt_Please_review_your_answers_before_submitting_the_exam;
|
||||
unsigned NumTst;
|
||||
struct TstRes_Result Result;
|
||||
struct TstPrn_Print Print;
|
||||
|
||||
/***** Read test configuration from database *****/
|
||||
TstCfg_GetConfigFromDB ();
|
||||
|
||||
/***** Get basic parameters of the exam *****/
|
||||
/* Get test exam code from form */
|
||||
TstRes_ResetResult (&Result);
|
||||
if ((Result.ResCod = TstRes_GetParamExaCod ()) <= 0)
|
||||
TstPrn_ResetResult (&Print);
|
||||
if ((Print.PrnCod = TstPrn_GetParamExaCod ()) <= 0)
|
||||
Lay_ShowErrorAndExit ("Wrong test exam.");
|
||||
|
||||
/* Get number of this test from form */
|
||||
NumTst = Tst_GetParamNumTst ();
|
||||
|
||||
/***** Get test exam from database *****/
|
||||
TstRes_GetExamDataByExaCod (&Result);
|
||||
TstPrn_GetExamDataByExaCod (&Print);
|
||||
|
||||
/****** Get test status in database for this session-course-num.test *****/
|
||||
if (Result.Sent)
|
||||
if (Print.Sent)
|
||||
Ale_ShowAlert (Ale_WARNING,Txt_The_test_X_has_already_been_assessed_previously,
|
||||
NumTst);
|
||||
else // Exam not yet sent
|
||||
else // Print not yet sent
|
||||
{
|
||||
/***** Get test exam questions from database *****/
|
||||
TstRes_GetExamQuestionsFromDB (&Result);
|
||||
TstPrn_GetExamQuestionsFromDB (&Print);
|
||||
|
||||
/***** Get answers from form to assess a test *****/
|
||||
Tst_GetAnswersFromForm (&Result);
|
||||
Tst_GetAnswersFromForm (&Print);
|
||||
|
||||
/***** Update test exam in database *****/
|
||||
TstRes_ComputeScoresAndStoreExamQuestions (&Result,
|
||||
TstPrn_ComputeScoresAndStoreExamQuestions (&Print,
|
||||
false); // Don't update question score
|
||||
TstRes_UpdateExamInDB (&Result);
|
||||
TstPrn_UpdateExamInDB (&Print);
|
||||
|
||||
/***** Show question and button to send the test *****/
|
||||
/* Start alert */
|
||||
Ale_ShowAlert (Ale_WARNING,"Por favor, revise sus respuestas antes de enviar el examen:"); // TODO: Need translation!!!
|
||||
Ale_ShowAlert (Ale_WARNING,Txt_Please_review_your_answers_before_submitting_the_exam);
|
||||
|
||||
/* Show the same test exam to be answered */
|
||||
Tst_ShowTestExamToFillIt (&Result,NumTst,Tst_CONFIRM);
|
||||
Tst_ShowTestExamToFillIt (&Print,NumTst,Tst_CONFIRM);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -580,43 +578,43 @@ void Tst_AssessTest (void)
|
|||
extern const char *Txt_Grade;
|
||||
extern const char *Txt_The_test_X_has_already_been_assessed_previously;
|
||||
unsigned NumTst;
|
||||
struct TstRes_Result Result;
|
||||
struct TstPrn_Print Print;
|
||||
|
||||
/***** Read test configuration from database *****/
|
||||
TstCfg_GetConfigFromDB ();
|
||||
|
||||
/***** Get basic parameters of the exam *****/
|
||||
/* Get test exam code from form */
|
||||
TstRes_ResetResult (&Result);
|
||||
if ((Result.ResCod = TstRes_GetParamExaCod ()) <= 0)
|
||||
TstPrn_ResetResult (&Print);
|
||||
if ((Print.PrnCod = TstPrn_GetParamExaCod ()) <= 0)
|
||||
Lay_ShowErrorAndExit ("Wrong test exam.");
|
||||
|
||||
/* Get number of this test from form */
|
||||
NumTst = Tst_GetParamNumTst ();
|
||||
|
||||
/***** Get test exam from database *****/
|
||||
TstRes_GetExamDataByExaCod (&Result);
|
||||
TstPrn_GetExamDataByExaCod (&Print);
|
||||
|
||||
/****** Get test status in database for this session-course-num.test *****/
|
||||
if (Result.Sent)
|
||||
if (Print.Sent)
|
||||
Ale_ShowAlert (Ale_WARNING,Txt_The_test_X_has_already_been_assessed_previously,
|
||||
NumTst);
|
||||
else // Exam not yet sent
|
||||
else // Print not yet sent
|
||||
{
|
||||
/***** Get test exam questions from database *****/
|
||||
TstRes_GetExamQuestionsFromDB (&Result);
|
||||
TstPrn_GetExamQuestionsFromDB (&Print);
|
||||
|
||||
/***** Get answers from form to assess a test *****/
|
||||
Tst_GetAnswersFromForm (&Result);
|
||||
Tst_GetAnswersFromForm (&Print);
|
||||
|
||||
/***** Get if test exam will be visible by teachers *****/
|
||||
Result.Sent = true; // The exam has been finished and sent by student
|
||||
Result.AllowTeachers = Par_GetParToBool ("AllowTchs");
|
||||
Print.Sent = true; // The exam has been finished and sent by student
|
||||
Print.AllowTeachers = Par_GetParToBool ("AllowTchs");
|
||||
|
||||
/***** Update test exam in database *****/
|
||||
TstRes_ComputeScoresAndStoreExamQuestions (&Result,
|
||||
TstPrn_ComputeScoresAndStoreExamQuestions (&Print,
|
||||
Gbl.Usrs.Me.Role.Logged == Rol_STD); // Update question score?
|
||||
TstRes_UpdateExamInDB (&Result);
|
||||
TstPrn_UpdateExamInDB (&Print);
|
||||
|
||||
/***** Begin box *****/
|
||||
Box_BoxBegin (NULL,Txt_Test_result,
|
||||
|
@ -636,19 +634,19 @@ void Tst_AssessTest (void)
|
|||
}
|
||||
|
||||
/***** Write answers and solutions *****/
|
||||
TstRes_ShowExamAfterAssess (&Result);
|
||||
TstPrn_ShowExamAfterAssess (&Print);
|
||||
|
||||
/***** Write total score and grade *****/
|
||||
if (TstVis_IsVisibleTotalScore (TstCfg_GetConfigVisibility ()))
|
||||
{
|
||||
HTM_DIV_Begin ("class=\"DAT_N_BOLD CM\"");
|
||||
HTM_TxtColonNBSP (Txt_Score);
|
||||
HTM_Double2Decimals (Result.Score);
|
||||
HTM_Double2Decimals (Print.Score);
|
||||
HTM_BR ();
|
||||
HTM_TxtColonNBSP (Txt_Grade);
|
||||
TstRes_ComputeAndShowGrade (Result.NumQsts,
|
||||
Result.Score,
|
||||
TstRes_SCORE_MAX);
|
||||
TstPrn_ComputeAndShowGrade (Print.NumQsts,
|
||||
Print.Score,
|
||||
TstPrn_SCORE_MAX);
|
||||
HTM_DIV_End ();
|
||||
}
|
||||
|
||||
|
@ -661,22 +659,22 @@ void Tst_AssessTest (void)
|
|||
/*********** Get questions and answers from form to assess a test ************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Tst_GetAnswersFromForm (struct TstRes_Result *Result)
|
||||
static void Tst_GetAnswersFromForm (struct TstPrn_Print *Print)
|
||||
{
|
||||
unsigned NumQst;
|
||||
char StrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x"
|
||||
|
||||
/***** Loop for every question getting user's answers *****/
|
||||
for (NumQst = 0;
|
||||
NumQst < Result->NumQsts;
|
||||
NumQst < Print->NumQsts;
|
||||
NumQst++)
|
||||
{
|
||||
/* Get answers selected by user for this question */
|
||||
snprintf (StrAns,sizeof (StrAns),
|
||||
"Ans%010u",
|
||||
NumQst);
|
||||
Par_GetParMultiToText (StrAns,Result->Questions[NumQst].StrAnswers,
|
||||
TstRes_MAX_BYTES_ANSWERS_ONE_QST); /* If answer type == T/F ==> " ", "T", "F"; if choice ==> "0", "2",... */
|
||||
Par_GetParMultiToText (StrAns,Print->PrintedQuestions[NumQst].StrAnswers,
|
||||
TstPrn_MAX_BYTES_ANSWERS_ONE_QST); /* If answer type == T/F ==> " ", "T", "F"; if choice ==> "0", "2",... */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -788,7 +786,7 @@ static unsigned Tst_GetNumExamsGeneratedByMe (void)
|
|||
/************************ Show a test exam to be answered ********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Tst_ShowTestExamToFillIt (struct TstRes_Result *Result,
|
||||
static void Tst_ShowTestExamToFillIt (struct TstPrn_Print *Print,
|
||||
unsigned NumExamsGeneratedByMe,
|
||||
Tst_RequestOrConfirm_t RequestOrConfirm)
|
||||
{
|
||||
|
@ -813,11 +811,11 @@ static void Tst_ShowTestExamToFillIt (struct TstRes_Result *Result,
|
|||
Gbl.Hierarchy.Deg.DegCod,
|
||||
Gbl.Hierarchy.Crs.CrsCod);
|
||||
|
||||
if (Result->NumQsts)
|
||||
if (Print->NumQsts)
|
||||
{
|
||||
/***** Begin form *****/
|
||||
Frm_StartForm (Action[RequestOrConfirm]);
|
||||
TstRes_PutParamExaCod (Result->ResCod);
|
||||
TstPrn_PutParamExaCod (Print->PrnCod);
|
||||
Par_PutHiddenParamUnsigned (NULL,"NumTst",NumExamsGeneratedByMe);
|
||||
|
||||
/***** Begin table *****/
|
||||
|
@ -825,21 +823,21 @@ static void Tst_ShowTestExamToFillIt (struct TstRes_Result *Result,
|
|||
|
||||
/***** Write one row for each question *****/
|
||||
for (NumQst = 0;
|
||||
NumQst < Result->NumQsts;
|
||||
NumQst < Print->NumQsts;
|
||||
NumQst++)
|
||||
{
|
||||
Gbl.RowEvenOdd = NumQst % 2;
|
||||
|
||||
/* Create test question */
|
||||
Tst_QstConstructor (&Question);
|
||||
Question.QstCod = Result->Questions[NumQst].QstCod;
|
||||
Question.QstCod = Print->PrintedQuestions[NumQst].QstCod;
|
||||
|
||||
/* Show question */
|
||||
if (!Tst_GetQstDataFromDB (&Question)) // Question exists
|
||||
Lay_ShowErrorAndExit ("Wrong question.");
|
||||
|
||||
/* Write question and answers */
|
||||
Tst_WriteQstAndAnsSeeing (Result,NumQst,&Question);
|
||||
Tst_WriteQstAndAnsSeeing (Print,NumQst,&Question);
|
||||
|
||||
/* Destroy test question */
|
||||
Tst_QstDestructor (&Question);
|
||||
|
@ -903,7 +901,7 @@ void Tst_ShowTagList (unsigned NumTags,MYSQL_RES *mysql_res)
|
|||
/********** Write a row of a test, with one question and its answer **********/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Tst_WriteQstAndAnsSeeing (const struct TstRes_Result *Result,
|
||||
static void Tst_WriteQstAndAnsSeeing (const struct TstPrn_Print *Print,
|
||||
unsigned NumQst,
|
||||
const struct Tst_Question *Question)
|
||||
{
|
||||
|
@ -931,7 +929,7 @@ static void Tst_WriteQstAndAnsSeeing (const struct TstRes_Result *Result,
|
|||
"TEST_MED_SHOW");
|
||||
|
||||
/* Answers */
|
||||
Tst_WriteAnswersSeeing (Result,NumQst,Question);
|
||||
Tst_WriteAnswersSeeing (Print,NumQst,Question);
|
||||
|
||||
HTM_TD_End ();
|
||||
|
||||
|
@ -2512,7 +2510,7 @@ static void Tst_GetQuestions (struct Tst_Test *Test,MYSQL_RES **mysql_res)
|
|||
/*****************************************************************************/
|
||||
|
||||
static void Tst_GetQuestionsForNewTestFromDB (struct Tst_Test *Test,
|
||||
struct TstRes_Result *Result)
|
||||
struct TstPrn_Print *Print)
|
||||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
|
@ -2625,14 +2623,14 @@ static void Tst_GetQuestionsForNewTestFromDB (struct Tst_Test *Test,
|
|||
Lay_ShowAlert (Lay_INFO,Query);
|
||||
*/
|
||||
/* Make the query */
|
||||
Result->NumQsts =
|
||||
Print->NumQsts =
|
||||
Test->NumQsts = (unsigned) DB_QuerySELECT (&mysql_res,"can not get questions",
|
||||
"%s",
|
||||
Query);
|
||||
|
||||
/***** Get questions and answers from database *****/
|
||||
for (NumQst = 0;
|
||||
NumQst < Result->NumQsts;
|
||||
NumQst < Print->NumQsts;
|
||||
NumQst++)
|
||||
{
|
||||
/* Get question row */
|
||||
|
@ -2644,7 +2642,7 @@ static void Tst_GetQuestionsForNewTestFromDB (struct Tst_Test *Test,
|
|||
*/
|
||||
|
||||
/* Get question code (row[0]) */
|
||||
if ((Result->Questions[NumQst].QstCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
|
||||
if ((Print->PrintedQuestions[NumQst].QstCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
|
||||
Lay_ShowErrorAndExit ("Wrong code of question.");
|
||||
|
||||
/* Get answer type (row[1]) */
|
||||
|
@ -2660,13 +2658,13 @@ static void Tst_GetQuestionsForNewTestFromDB (struct Tst_Test *Test,
|
|||
case Tst_ANS_FLOAT:
|
||||
case Tst_ANS_TRUE_FALSE:
|
||||
case Tst_ANS_TEXT:
|
||||
Result->Questions[NumQst].StrIndexes[0] = '\0';
|
||||
Print->PrintedQuestions[NumQst].StrIndexes[0] = '\0';
|
||||
break;
|
||||
case Tst_ANS_UNIQUE_CHOICE:
|
||||
case Tst_ANS_MULTIPLE_CHOICE:
|
||||
/* If answer type is unique or multiple option,
|
||||
generate indexes of answers depending on shuffle */
|
||||
Tst_GenerateChoiceIndexesDependingOnShuffle (Result,NumQst,Shuffle);
|
||||
Tst_GenerateChoiceIndexesDependingOnShuffle (&Print->PrintedQuestions[NumQst],Shuffle);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -2676,20 +2674,19 @@ static void Tst_GetQuestionsForNewTestFromDB (struct Tst_Test *Test,
|
|||
Initially user has not answered the question ==> initially all the answers will be blank.
|
||||
If the user does not confirm the submission of their exam ==>
|
||||
==> the exam may be half filled ==> the answers displayed will be those selected by the user. */
|
||||
Result->Questions[NumQst].StrAnswers[0] = '\0';
|
||||
Print->PrintedQuestions[NumQst].StrAnswers[0] = '\0';
|
||||
}
|
||||
|
||||
/***** Get if test exam will be visible by teachers *****/
|
||||
Result->AllowTeachers = Par_GetParToBool ("AllowTchs");
|
||||
Print->AllowTeachers = Par_GetParToBool ("AllowTchs");
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/********* Get single or multiple choice answer when seeing a test ***********/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Tst_GenerateChoiceIndexesDependingOnShuffle (struct TstRes_Result *Result,
|
||||
unsigned NumQst,
|
||||
bool Shuffle)
|
||||
void Tst_GenerateChoiceIndexesDependingOnShuffle (struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
bool Shuffle)
|
||||
{
|
||||
extern const char *Par_SEPARATOR_PARAM_MULTIPLE;
|
||||
struct Tst_Question Question;
|
||||
|
@ -2702,7 +2699,7 @@ static void Tst_GenerateChoiceIndexesDependingOnShuffle (struct TstRes_Result *R
|
|||
|
||||
/***** Create test question *****/
|
||||
Tst_QstConstructor (&Question);
|
||||
Question.QstCod = Result->Questions[NumQst].QstCod;
|
||||
Question.QstCod = PrintedQuestion->QstCod;
|
||||
|
||||
/***** Get answers of question from database *****/
|
||||
Tst_GetAnswersQst (&Question,&mysql_res,Shuffle);
|
||||
|
@ -2739,8 +2736,8 @@ static void Tst_GenerateChoiceIndexesDependingOnShuffle (struct TstRes_Result *R
|
|||
snprintf (StrInd,sizeof (StrInd),"%u",Index);
|
||||
else
|
||||
snprintf (StrInd,sizeof (StrInd),"%s%u",Par_SEPARATOR_PARAM_MULTIPLE,Index);
|
||||
Str_Concat (Result->Questions[NumQst].StrIndexes,StrInd,
|
||||
TstRes_MAX_BYTES_INDEXES_ONE_QST);
|
||||
Str_Concat (PrintedQuestion->StrIndexes,StrInd,
|
||||
TstPrn_MAX_BYTES_INDEXES_ONE_QST);
|
||||
}
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
|
@ -3360,7 +3357,7 @@ void Tst_WriteAnswersListing (const struct Tst_Question *Question)
|
|||
/************** Write answers of a question when seeing a test ***************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Tst_WriteAnswersSeeing (const struct TstRes_Result *Result,
|
||||
static void Tst_WriteAnswersSeeing (const struct TstPrn_Print *Print,
|
||||
unsigned NumQst,
|
||||
const struct Tst_Question *Question)
|
||||
{
|
||||
|
@ -3368,20 +3365,20 @@ static void Tst_WriteAnswersSeeing (const struct TstRes_Result *Result,
|
|||
switch (Question->Answer.Type)
|
||||
{
|
||||
case Tst_ANS_INT:
|
||||
Tst_WriteIntAnsSeeing (Result,NumQst);
|
||||
Tst_WriteIntAnsSeeing (Print,NumQst);
|
||||
break;
|
||||
case Tst_ANS_FLOAT:
|
||||
Tst_WriteFloatAnsSeeing (Result,NumQst);
|
||||
Tst_WriteFloatAnsSeeing (Print,NumQst);
|
||||
break;
|
||||
case Tst_ANS_TRUE_FALSE:
|
||||
Tst_WriteTFAnsSeeing (Result,NumQst);
|
||||
Tst_WriteTFAnsSeeing (Print,NumQst);
|
||||
break;
|
||||
case Tst_ANS_UNIQUE_CHOICE:
|
||||
case Tst_ANS_MULTIPLE_CHOICE:
|
||||
Tst_WriteChoiceAnsSeeing (Result,NumQst,Question);
|
||||
Tst_WriteChoiceAnsSeeing (Print,NumQst,Question);
|
||||
break;
|
||||
case Tst_ANS_TEXT:
|
||||
Tst_WriteTextAnsSeeing (Result,NumQst);
|
||||
Tst_WriteTextAnsSeeing (Print,NumQst);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -3417,7 +3414,7 @@ static void Tst_WriteIntAnsListing (const struct Tst_Question *Question)
|
|||
/****************** Write integer answer when seeing a test ******************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Tst_WriteIntAnsSeeing (const struct TstRes_Result *Exam,
|
||||
static void Tst_WriteIntAnsSeeing (const struct TstPrn_Print *Print,
|
||||
unsigned NumQst)
|
||||
{
|
||||
char StrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x"
|
||||
|
@ -3426,7 +3423,7 @@ static void Tst_WriteIntAnsSeeing (const struct TstRes_Result *Exam,
|
|||
snprintf (StrAns,sizeof (StrAns),
|
||||
"Ans%010u",
|
||||
NumQst);
|
||||
HTM_INPUT_TEXT (StrAns,11,Exam->Questions[NumQst].StrAnswers,
|
||||
HTM_INPUT_TEXT (StrAns,11,Print->PrintedQuestions[NumQst].StrAnswers,
|
||||
HTM_DONT_SUBMIT_ON_CHANGE,
|
||||
"size=\"11\"");
|
||||
}
|
||||
|
@ -3450,7 +3447,7 @@ static void Tst_WriteFloatAnsEdit (const struct Tst_Question *Question)
|
|||
/****************** Write float answer when seeing a test ********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Tst_WriteFloatAnsSeeing (const struct TstRes_Result *Exam,
|
||||
static void Tst_WriteFloatAnsSeeing (const struct TstPrn_Print *Print,
|
||||
unsigned NumQst)
|
||||
{
|
||||
char StrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x"
|
||||
|
@ -3459,7 +3456,7 @@ static void Tst_WriteFloatAnsSeeing (const struct TstRes_Result *Exam,
|
|||
snprintf (StrAns,sizeof (StrAns),
|
||||
"Ans%010u",
|
||||
NumQst);
|
||||
HTM_INPUT_TEXT (StrAns,Tst_MAX_BYTES_FLOAT_ANSWER,Exam->Questions[NumQst].StrAnswers,
|
||||
HTM_INPUT_TEXT (StrAns,Tst_MAX_BYTES_FLOAT_ANSWER,Print->PrintedQuestions[NumQst].StrAnswers,
|
||||
HTM_DONT_SUBMIT_ON_CHANGE,
|
||||
"size=\"11\"");
|
||||
}
|
||||
|
@ -3482,7 +3479,7 @@ static void Tst_WriteTFAnsListing (const struct Tst_Question *Question)
|
|||
/************** Write false / true answer when seeing a test ****************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Tst_WriteTFAnsSeeing (const struct TstRes_Result *Exam,
|
||||
static void Tst_WriteTFAnsSeeing (const struct TstPrn_Print *Print,
|
||||
unsigned NumQst)
|
||||
{
|
||||
extern const char *Txt_TF_QST[2];
|
||||
|
@ -3493,9 +3490,9 @@ static void Tst_WriteTFAnsSeeing (const struct TstRes_Result *Exam,
|
|||
==> the exam may be half filled ==> the answers displayed will be those selected by the user. */
|
||||
HTM_SELECT_Begin (HTM_DONT_SUBMIT_ON_CHANGE,
|
||||
"name=\"Ans%010u\"",NumQst);
|
||||
HTM_OPTION (HTM_Type_STRING,"" ,Exam->Questions[NumQst].StrAnswers[0] == '\0',false," ");
|
||||
HTM_OPTION (HTM_Type_STRING,"T",Exam->Questions[NumQst].StrAnswers[0] == 'T' ,false,"%s",Txt_TF_QST[0]);
|
||||
HTM_OPTION (HTM_Type_STRING,"F",Exam->Questions[NumQst].StrAnswers[0] == 'F' ,false,"%s",Txt_TF_QST[1]);
|
||||
HTM_OPTION (HTM_Type_STRING,"" ,Print->PrintedQuestions[NumQst].StrAnswers[0] == '\0',false," ");
|
||||
HTM_OPTION (HTM_Type_STRING,"T",Print->PrintedQuestions[NumQst].StrAnswers[0] == 'T' ,false,"%s",Txt_TF_QST[0]);
|
||||
HTM_OPTION (HTM_Type_STRING,"F",Print->PrintedQuestions[NumQst].StrAnswers[0] == 'F' ,false,"%s",Txt_TF_QST[1]);
|
||||
HTM_SELECT_End ();
|
||||
}
|
||||
|
||||
|
@ -3615,7 +3612,7 @@ static void Tst_WriteChoiceAnsListing (const struct Tst_Question *Question)
|
|||
/******** Write single or multiple choice answer when seeing a test **********/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Tst_WriteChoiceAnsSeeing (const struct TstRes_Result *Exam,
|
||||
static void Tst_WriteChoiceAnsSeeing (const struct TstPrn_Print *Print,
|
||||
unsigned NumQst,
|
||||
const struct Tst_Question *Question)
|
||||
{
|
||||
|
@ -3625,10 +3622,10 @@ static void Tst_WriteChoiceAnsSeeing (const struct TstRes_Result *Exam,
|
|||
char StrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x"
|
||||
|
||||
/***** Get indexes for this question from string *****/
|
||||
TstRes_GetIndexesFromStr (Exam->Questions[NumQst].StrIndexes,Indexes);
|
||||
TstPrn_GetIndexesFromStr (Print->PrintedQuestions[NumQst].StrIndexes,Indexes);
|
||||
|
||||
/***** Get the user's answers for this question from string *****/
|
||||
TstRes_GetAnswersFromStr (Exam->Questions[NumQst].StrAnswers,UsrAnswers);
|
||||
TstPrn_GetAnswersFromStr (Print->PrintedQuestions[NumQst].StrAnswers,UsrAnswers);
|
||||
|
||||
/***** Begin table *****/
|
||||
HTM_TABLE_BeginPadding (2);
|
||||
|
@ -3756,7 +3753,7 @@ void Tst_GetChoiceAns (struct Tst_Question *Question,MYSQL_RES *mysql_res)
|
|||
/******************** Write text answer when seeing a test *******************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Tst_WriteTextAnsSeeing (const struct TstRes_Result *Result,
|
||||
static void Tst_WriteTextAnsSeeing (const struct TstPrn_Print *Print,
|
||||
unsigned NumQst)
|
||||
{
|
||||
char StrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x"
|
||||
|
@ -3765,7 +3762,7 @@ static void Tst_WriteTextAnsSeeing (const struct TstRes_Result *Result,
|
|||
snprintf (StrAns,sizeof (StrAns),
|
||||
"Ans%010u",
|
||||
NumQst);
|
||||
HTM_INPUT_TEXT (StrAns,TstRes_MAX_CHARS_ANSWERS_ONE_QST,Result->Questions[NumQst].StrAnswers,
|
||||
HTM_INPUT_TEXT (StrAns,TstPrn_MAX_CHARS_ANSWERS_ONE_QST,Print->PrintedQuestions[NumQst].StrAnswers,
|
||||
HTM_DONT_SUBMIT_ON_CHANGE,
|
||||
"size=\"40\"");
|
||||
}
|
||||
|
@ -5052,7 +5049,7 @@ static void Tst_GetQstFromForm (struct Tst_Question *Question)
|
|||
char TagStr[6 + Cns_MAX_DECIMAL_DIGITS_UINT + 1];
|
||||
char AnsStr[6 + Cns_MAX_DECIMAL_DIGITS_UINT + 1];
|
||||
char FbStr[5 + Cns_MAX_DECIMAL_DIGITS_UINT + 1];
|
||||
char StrMultiAns[TstRes_MAX_BYTES_ANSWERS_ONE_QST + 1];
|
||||
char StrMultiAns[TstPrn_MAX_BYTES_ANSWERS_ONE_QST + 1];
|
||||
char TF[1 + 1]; // (T)rue or (F)alse
|
||||
const char *Ptr;
|
||||
unsigned NumCorrectAns;
|
||||
|
@ -5204,7 +5201,7 @@ static void Tst_GetQstFromForm (struct Tst_Question *Question)
|
|||
}
|
||||
else if (Question->Answer.Type == Tst_ANS_MULTIPLE_CHOICE)
|
||||
{
|
||||
Par_GetParMultiToText ("AnsMulti",StrMultiAns,TstRes_MAX_BYTES_ANSWERS_ONE_QST);
|
||||
Par_GetParMultiToText ("AnsMulti",StrMultiAns,TstPrn_MAX_BYTES_ANSWERS_ONE_QST);
|
||||
Ptr = StrMultiAns;
|
||||
while (*Ptr)
|
||||
{
|
||||
|
|
63
swad_test.h
63
swad_test.h
|
@ -31,48 +31,22 @@
|
|||
#include "swad_game.h"
|
||||
#include "swad_media.h"
|
||||
#include "swad_test_config.h"
|
||||
#include "swad_test_print.h"
|
||||
#include "swad_test_type.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Public constants ******************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#define Tst_MAX_TAGS_PER_QUESTION 5
|
||||
|
||||
#define Tst_MAX_CHARS_TAG (128 - 1) // 127
|
||||
#define Tst_MAX_BYTES_TAG ((Tst_MAX_CHARS_TAG + 1) * Str_MAX_BYTES_PER_CHAR - 1) // 2047
|
||||
|
||||
#define Tst_MAX_CHARS_ANSWER_OR_FEEDBACK (1024 - 1) // 1023
|
||||
#define Tst_MAX_BYTES_ANSWER_OR_FEEDBACK ((Tst_MAX_CHARS_ANSWER_OR_FEEDBACK + 1) * Str_MAX_BYTES_PER_CHAR - 1) // 16383
|
||||
|
||||
#define Tst_MAX_BYTES_ANSWER_TYPE 32
|
||||
|
||||
#define Tst_MAX_OPTIONS_PER_QUESTION 10
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************************* Public types ********************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
struct Tst_Tags
|
||||
{
|
||||
unsigned Num;
|
||||
bool All;
|
||||
char *List;
|
||||
char Txt[Tst_MAX_TAGS_PER_QUESTION][Tst_MAX_BYTES_TAG + 1];
|
||||
};
|
||||
|
||||
#define Tst_NUM_ANS_TYPES 6
|
||||
#define Tst_MAX_BYTES_LIST_ANSWER_TYPES (Tst_NUM_ANS_TYPES * (Cns_MAX_DECIMAL_DIGITS_UINT + 1))
|
||||
typedef enum
|
||||
{
|
||||
Tst_ANS_INT = 0,
|
||||
Tst_ANS_FLOAT = 1,
|
||||
Tst_ANS_TRUE_FALSE = 2,
|
||||
Tst_ANS_UNIQUE_CHOICE = 3,
|
||||
Tst_ANS_MULTIPLE_CHOICE = 4,
|
||||
Tst_ANS_TEXT = 5,
|
||||
Tst_ANS_ALL = 6, // All/any type of answer
|
||||
} Tst_AnswerType_t;
|
||||
|
||||
struct Tst_AnswerTypes
|
||||
{
|
||||
bool All;
|
||||
|
@ -90,35 +64,6 @@ typedef enum
|
|||
} Tst_QuestionsOrder_t;
|
||||
#define Tst_DEFAULT_ORDER Tst_ORDER_STEM
|
||||
|
||||
struct Tst_Question
|
||||
{
|
||||
long QstCod;
|
||||
struct Tst_Tags Tags;
|
||||
time_t EditTime;
|
||||
char *Stem;
|
||||
char *Feedback;
|
||||
struct Media Media;
|
||||
struct
|
||||
{
|
||||
Tst_AnswerType_t Type;
|
||||
unsigned NumOptions;
|
||||
bool Shuffle;
|
||||
char TF;
|
||||
struct
|
||||
{
|
||||
bool Correct;
|
||||
char *Text;
|
||||
char *Feedback;
|
||||
struct Media Media;
|
||||
} Options[Tst_MAX_OPTIONS_PER_QUESTION];
|
||||
long Integer;
|
||||
double FloatingPoint[2];
|
||||
} Answer;
|
||||
unsigned long NumHits;
|
||||
unsigned long NumHitsNotBlank;
|
||||
double Score;
|
||||
};
|
||||
|
||||
struct Tst_Test
|
||||
{
|
||||
struct Tst_Tags Tags; // Selected tags
|
||||
|
@ -176,6 +121,10 @@ void Tst_RequestSelectTestsForGame (struct Gam_Games *Games);
|
|||
void Tst_ListQuestionsToEdit (void);
|
||||
void Tst_ListQuestionsToSelectForSet (struct Exa_Exams *Exams);
|
||||
void Tst_ListQuestionsToSelectForGame (struct Gam_Games *Games);
|
||||
|
||||
void Tst_GenerateChoiceIndexesDependingOnShuffle (struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
bool Shuffle);
|
||||
|
||||
void Tst_WriteParamEditQst (const struct Tst_Test *Test);
|
||||
|
||||
unsigned Tst_GetNumAnswersQst (long QstCod);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,7 @@
|
|||
// swad_test_exam.c: test exams made by users
|
||||
// swad_test_print.h: test exam prints made by users
|
||||
|
||||
#ifndef _SWAD_TST_EXA
|
||||
#define _SWAD_TST_EXA
|
||||
#ifndef _SWAD_TST_PRN
|
||||
#define _SWAD_TST_PRN
|
||||
/*
|
||||
SWAD (Shared Workspace At a Distance in Spanish),
|
||||
is a web platform developed at the University of Granada (Spain),
|
||||
|
@ -27,85 +27,88 @@
|
|||
/********************************* Headers ***********************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "swad_test.h"
|
||||
#include "swad_test_config.h"
|
||||
#include "swad_test_type.h"
|
||||
#include "swad_user.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Public constants ******************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#define TstRes_MAX_BYTES_INDEXES_ONE_QST (Tst_MAX_OPTIONS_PER_QUESTION * (3 + 1))
|
||||
#define TstPrn_MAX_BYTES_INDEXES_ONE_QST (Tst_MAX_OPTIONS_PER_QUESTION * (3 + 1))
|
||||
|
||||
#define TstRes_MAX_CHARS_ANSWERS_ONE_QST (128 - 1) // 127
|
||||
#define TstRes_MAX_BYTES_ANSWERS_ONE_QST ((TstRes_MAX_CHARS_ANSWERS_ONE_QST + 1) * Str_MAX_BYTES_PER_CHAR - 1) // 2047
|
||||
#define TstPrn_MAX_CHARS_ANSWERS_ONE_QST (128 - 1) // 127
|
||||
#define TstPrn_MAX_BYTES_ANSWERS_ONE_QST ((TstPrn_MAX_CHARS_ANSWERS_ONE_QST + 1) * Str_MAX_BYTES_PER_CHAR - 1) // 2047
|
||||
|
||||
#define TstRes_SCORE_MAX 10 // Maximum score of a test (10 in Spain). Must be unsigned! // TODO: Make this configurable by teachers
|
||||
#define TstPrn_SCORE_MAX 10 // Maximum score of a test (10 in Spain). Must be unsigned! // TODO: Make this configurable by teachers
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************************* Public types ********************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
struct TstRes_Result
|
||||
struct TstPrn_PrintedQuestion
|
||||
{
|
||||
long ResCod; // Test result code
|
||||
long QstCod; // Question code
|
||||
char StrIndexes[TstPrn_MAX_BYTES_INDEXES_ONE_QST + 1]; // 0 1 2 3, 3 0 2 1, etc.
|
||||
char StrAnswers[TstPrn_MAX_BYTES_ANSWERS_ONE_QST + 1]; // Answers selected by user
|
||||
double Score; // Question score
|
||||
bool AnswerIsNotBlank; // Answer not blank?
|
||||
};
|
||||
|
||||
struct TstPrn_Print
|
||||
{
|
||||
long PrnCod; // Test print code
|
||||
time_t TimeUTC[Dat_NUM_START_END_TIME];
|
||||
unsigned NumQsts; // Number of questions
|
||||
unsigned NumQstsNotBlank; // Number of questions not blank
|
||||
bool Sent; // This test result has been sent or not?
|
||||
bool Sent; // This test print has been sent or not?
|
||||
// "Sent" means that user has clicked "Send" button after finishing
|
||||
bool AllowTeachers; // Are teachers allowed to see this test result?
|
||||
double Score; // Total score of the test result
|
||||
struct
|
||||
{
|
||||
long QstCod; // Question code
|
||||
char StrIndexes[TstRes_MAX_BYTES_INDEXES_ONE_QST + 1]; // 0 1 2 3, 3 0 2 1, etc.
|
||||
char StrAnswers[TstRes_MAX_BYTES_ANSWERS_ONE_QST + 1]; // Answers selected by user
|
||||
double Score; // Question score
|
||||
bool AnswerIsNotBlank; // Answer not blank?
|
||||
} Questions[TstCfg_MAX_QUESTIONS_PER_TEST];
|
||||
double Score; // Total score of the test print
|
||||
struct TstPrn_PrintedQuestion PrintedQuestions[TstCfg_MAX_QUESTIONS_PER_TEST];
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Public prototypes *****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void TstRes_ResetResult (struct TstRes_Result *Result);
|
||||
void TstRes_CreateExamInDB (struct TstRes_Result *Exam);
|
||||
void TstRes_UpdateExamInDB (const struct TstRes_Result *Exam);
|
||||
void TstPrn_ResetResult (struct TstPrn_Print *Print);
|
||||
void TstPrn_CreateExamInDB (struct TstPrn_Print *Print);
|
||||
void TstPrn_UpdateExamInDB (const struct TstPrn_Print *Print);
|
||||
|
||||
void TstRes_ShowExamAfterAssess (struct TstRes_Result *Exam);
|
||||
void TstPrn_ShowExamAfterAssess (struct TstPrn_Print *Print);
|
||||
|
||||
void TstRes_ComputeScoresAndStoreExamQuestions (struct TstRes_Result *Exam,
|
||||
void TstPrn_ComputeScoresAndStoreExamQuestions (struct TstPrn_Print *Print,
|
||||
bool UpdateQstScore);
|
||||
void TstRes_ComputeChoiceAnsScore (struct TstRes_Result *Result,
|
||||
void TstPrn_ComputeChoiceAnsScore (struct TstPrn_Print *Print,
|
||||
unsigned NumQst,
|
||||
struct Tst_Question *Question);
|
||||
void TstRes_GetIndexesFromStr (const char StrIndexesOneQst[TstRes_MAX_BYTES_INDEXES_ONE_QST + 1], // 0 1 2 3, 3 0 2 1, etc.
|
||||
void TstPrn_GetIndexesFromStr (const char StrIndexesOneQst[TstPrn_MAX_BYTES_INDEXES_ONE_QST + 1], // 0 1 2 3, 3 0 2 1, etc.
|
||||
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION]);
|
||||
void TstRes_GetAnswersFromStr (const char StrAnswersOneQst[TstRes_MAX_BYTES_ANSWERS_ONE_QST + 1],
|
||||
void TstPrn_GetAnswersFromStr (const char StrAnswersOneQst[TstPrn_MAX_BYTES_ANSWERS_ONE_QST + 1],
|
||||
bool UsrAnswers[Tst_MAX_OPTIONS_PER_QUESTION]);
|
||||
|
||||
void TstRes_ComputeAndShowGrade (unsigned NumQsts,double Score,double MaxGrade);
|
||||
double TstRes_ComputeGrade (unsigned NumQsts,double Score,double MaxGrade);
|
||||
void TstRes_ShowGrade (double Grade,double MaxGrade);
|
||||
void TstPrn_ComputeAndShowGrade (unsigned NumQsts,double Score,double MaxGrade);
|
||||
double TstPrn_ComputeGrade (unsigned NumQsts,double Score,double MaxGrade);
|
||||
void TstPrn_ShowGrade (double Grade,double MaxGrade);
|
||||
|
||||
void TstRes_SelUsrsToViewUsrsExams (void);
|
||||
void TstRes_SelDatesToSeeMyExams (void);
|
||||
void TstRes_ShowMyExams (void);
|
||||
void TstRes_GetUsrsAndShowExams (void);
|
||||
void TstPrn_SelUsrsToViewUsrsExams (void);
|
||||
void TstPrn_SelDatesToSeeMyExams (void);
|
||||
void TstPrn_ShowMyExams (void);
|
||||
void TstPrn_GetUsrsAndShowExams (void);
|
||||
|
||||
void TstRes_PutParamExaCod (long ExaCod);
|
||||
long TstRes_GetParamExaCod (void);
|
||||
void TstPrn_PutParamExaCod (long ExaCod);
|
||||
long TstPrn_GetParamExaCod (void);
|
||||
|
||||
void TstRes_ShowOneExam (void);
|
||||
void TstRes_ShowExamAnswers (struct UsrData *UsrDat,
|
||||
struct TstRes_Result *Result,
|
||||
void TstPrn_ShowOneExam (void);
|
||||
void TstPrn_ShowExamAnswers (struct UsrData *UsrDat,
|
||||
struct TstPrn_Print *Print,
|
||||
unsigned Visibility);
|
||||
void TstRes_GetExamDataByExaCod (struct TstRes_Result *Result);
|
||||
void TstPrn_GetExamDataByExaCod (struct TstPrn_Print *Print);
|
||||
|
||||
void TstRes_GetExamQuestionsFromDB (struct TstRes_Result *Result);
|
||||
void TstRes_RemoveExamsMadeByUsrInAllCrss (long UsrCod);
|
||||
void TstRes_RemoveExamsMadeByUsrInCrs (long UsrCod,long CrsCod);
|
||||
void TstRes_RemoveCrsExams (long CrsCod);
|
||||
void TstPrn_GetExamQuestionsFromDB (struct TstPrn_Print *Print);
|
||||
void TstPrn_RemoveExamsMadeByUsrInAllCrss (long UsrCod);
|
||||
void TstPrn_RemoveExamsMadeByUsrInCrs (long UsrCod,long CrsCod);
|
||||
void TstPrn_RemoveCrsExams (long CrsCod);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,99 @@
|
|||
// swad_test_type.h: definition of types for tests
|
||||
|
||||
#ifndef _SWAD_TST_TYP
|
||||
#define _SWAD_TST_TYP
|
||||
/*
|
||||
SWAD (Shared Workspace At a Distance in Spanish),
|
||||
is a web platform developed at the University of Granada (Spain),
|
||||
and used to support university teaching.
|
||||
|
||||
This file is part of SWAD core.
|
||||
Copyright (C) 1999-2020 Antonio Cañas Vargas
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
/********************************* Headers ***********************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#define Tst_MAX_TAGS_PER_QUESTION 5
|
||||
|
||||
#define Tst_MAX_CHARS_TAG (128 - 1) // 127
|
||||
#define Tst_MAX_BYTES_TAG ((Tst_MAX_CHARS_TAG + 1) * Str_MAX_BYTES_PER_CHAR - 1) // 2047
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Public constants ******************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#define Tst_MAX_OPTIONS_PER_QUESTION 10
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************************* Public types ********************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
struct Tst_Tags
|
||||
{
|
||||
unsigned Num;
|
||||
bool All;
|
||||
char *List;
|
||||
char Txt[Tst_MAX_TAGS_PER_QUESTION][Tst_MAX_BYTES_TAG + 1];
|
||||
};
|
||||
|
||||
#define Tst_NUM_ANS_TYPES 6
|
||||
#define Tst_MAX_BYTES_LIST_ANSWER_TYPES (Tst_NUM_ANS_TYPES * (Cns_MAX_DECIMAL_DIGITS_UINT + 1))
|
||||
typedef enum
|
||||
{
|
||||
Tst_ANS_INT = 0,
|
||||
Tst_ANS_FLOAT = 1,
|
||||
Tst_ANS_TRUE_FALSE = 2,
|
||||
Tst_ANS_UNIQUE_CHOICE = 3,
|
||||
Tst_ANS_MULTIPLE_CHOICE = 4,
|
||||
Tst_ANS_TEXT = 5,
|
||||
Tst_ANS_ALL = 6, // All/any type of answer
|
||||
} Tst_AnswerType_t;
|
||||
|
||||
struct Tst_Question
|
||||
{
|
||||
long QstCod;
|
||||
struct Tst_Tags Tags;
|
||||
time_t EditTime;
|
||||
char *Stem;
|
||||
char *Feedback;
|
||||
struct Media Media;
|
||||
struct
|
||||
{
|
||||
Tst_AnswerType_t Type;
|
||||
unsigned NumOptions;
|
||||
bool Shuffle;
|
||||
char TF;
|
||||
struct
|
||||
{
|
||||
bool Correct;
|
||||
char *Text;
|
||||
char *Feedback;
|
||||
struct Media Media;
|
||||
} Options[Tst_MAX_OPTIONS_PER_QUESTION];
|
||||
long Integer;
|
||||
double FloatingPoint[2];
|
||||
} Answer;
|
||||
unsigned long NumHits;
|
||||
unsigned long NumHitsNotBlank;
|
||||
double Score;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Public prototypes *****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
21
swad_text.c
21
swad_text.c
|
@ -30708,6 +30708,27 @@ const char *Txt_Please_check_your_privacy_settings =
|
|||
"Por favor, verifique suas configurações de privacidade.";
|
||||
#endif
|
||||
|
||||
const char *Txt_Please_review_your_answers_before_submitting_the_exam =
|
||||
#if L==1 // ca
|
||||
"Si us plau, revisi les seves respostes abans d'enviar l'examen.";
|
||||
#elif L==2 // de
|
||||
"Bitte überprüfen Sie Ihre Antworten, bevor Sie die Prüfung einreichen.";
|
||||
#elif L==3 // en
|
||||
"Please review your answers before submitting the exam.";
|
||||
#elif L==4 // es
|
||||
"Por favor, revise sus respuestas antes de enviar el examen.";
|
||||
#elif L==5 // fr
|
||||
"S'il vous plaît, veuillez revoir vos réponses avant de soumettre l'examen.";
|
||||
#elif L==6 // gn
|
||||
"Por favor, revise sus respuestas antes de enviar el examen."; // Okoteve traducción
|
||||
#elif L==7 // it
|
||||
"Si prega di rivedere le risposte prima di inviare l'esame.";
|
||||
#elif L==8 // pl
|
||||
"Przejrzyj swoje odpowiedzi przed przesłaniem egzaminu.";
|
||||
#elif L==9 // pt
|
||||
"Por favor, revise suas respostas antes de enviar o exame.";
|
||||
#endif
|
||||
|
||||
const char *Txt_Please_select_the_country_of_your_institution =
|
||||
#if L==1 // ca
|
||||
"Si us plau, seleccioneu el país de la seva institució.";
|
||||
|
|
Loading…
Reference in New Issue