Version19.217

This commit is contained in:
acanas 2020-05-07 18:33:26 +02:00
parent a04402a458
commit dc919206d6
22 changed files with 924 additions and 733 deletions

View File

@ -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 \

View File

@ -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");

View File

@ -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 &&

View File

@ -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);

View File

@ -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},

View File

@ -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)

View File

@ -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);

View File

@ -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 *****/

View File

@ -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 *****/

View File

@ -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);

View File

@ -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 ();
}
}

View File

@ -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 *****/

View File

@ -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

View File

@ -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);

View File

@ -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 *****/

View File

@ -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

View File

@ -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,"&nbsp;");
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,"&nbsp;");
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)
{

View File

@ -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

View File

@ -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

99
swad_test_type.h Normal file
View File

@ -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

View File

@ -30708,6 +30708,27 @@ const char *Txt_Please_check_your_privacy_settings =
"Por favor, verifique suas configura&ccedil;&otilde;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 &uuml;berpr&uuml;fen Sie Ihre Antworten, bevor Sie die Pr&uuml;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&icirc;t, veuillez revoir vos r&eacute;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&lstrok;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&iacute;s de la seva instituci&oacute;.";