Version19.189

This commit is contained in:
acanas 2020-04-16 21:03:22 +02:00
parent c7a91ffaec
commit e31ab3c7e9
12 changed files with 240 additions and 279 deletions

View File

@ -1385,6 +1385,7 @@ CREATE TABLE IF NOT EXISTS tst_exams (
EndTime DATETIME NOT NULL,
NumQsts INT NOT NULL DEFAULT 0,
NumQstsNotBlank INT NOT NULL DEFAULT 0,
Sent ENUM('N','Y') NOT NULL DEFAULT 'N',
AllowTeachers ENUM('N','Y') NOT NULL DEFAULT 'N',
Score DOUBLE PRECISION NOT NULL DEFAULT 0,
UNIQUE INDEX(ExaCod),
@ -1416,15 +1417,6 @@ CREATE TABLE IF NOT EXISTS tst_questions (
INDEX(CrsCod,EditTime),
INDEX(MedCod));
--
-- Table tst_status: stores the status of tests for each session
--
CREATE TABLE IF NOT EXISTS tst_status (
SessionId CHAR(43) NOT NULL,
CrsCod INT NOT NULL,
NumTst INT NOT NULL,
Status TINYINT NOT NULL,
UNIQUE INDEX(SessionId,CrsCod,NumTst));
--
-- Table tst_tags: stores the tags of test questions
--
CREATE TABLE IF NOT EXISTS tst_tags (

View File

@ -642,7 +642,7 @@ const struct Act_Actions Act_Actions[Act_NUM_ACTIONS] =
[ActDowAssPrj ] = {1734,-1,TabUnk,ActSeePrj ,0x238,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_DOWNLD_FILE,Brw_DownloadFile ,NULL ,NULL},
[ActSeeTst ] = { 29,-1,TabUnk,ActReqTst ,0x238,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Tst_ShowNewTest ,NULL},
[ActReqAssTst ] = {1837,-1,TabUnk,ActReqTst ,0x238,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Tst_RequestAssessTest ,NULL},
[ActReqAssTst ] = {1837,-1,TabUnk,ActReqTst ,0x238,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Tst_ReceiveTestDraft ,NULL},
[ActAssTst ] = { 98,-1,TabUnk,ActReqTst ,0x238,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Tst_AssessTest ,NULL},
[ActEdiTstQst ] = { 104,-1,TabUnk,ActReqTst ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,Dat_SetIniEndDates ,Tst_RequestEditTests ,NULL},

View File

@ -497,7 +497,7 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - *
En OpenSWAD:
ps2pdf source.ps destination.pdf
*/
#define Log_PLATFORM_VERSION "SWAD 19.188.2 (2020-04-16)"
#define Log_PLATFORM_VERSION "SWAD 19.189 (2020-04-16)"
#define CSS_FILE "swad19.187.css"
#define JS_FILE "swad19.172.1.js"
/*
@ -547,7 +547,16 @@ Funci
// TODO: Miguel Damas: al principio de los exámenes tendría que poner cuánto resta cada pregunta
// TODO: Oresti Baños: cambiar ojos por candados en descriptores para prohibir/permitir y dejar los ojos para poder elegir descriptores
// TODO: Integrar pull requests con traducciones del alemán del usuario eruedin en GitHub
// TODO: Cambiar icono de inicio a "house-user.svg", notificaciones nuevas con "bell-on.svg"
// TODO: Cambiar icono notificaciones nuevas con "bell-on.svg"
Version 19.189: Apr 16, 2020 Fixed security issue in test exams.
Removed table with test status. (287719 lines)
3/4 changes necessary in database:
ALTER TABLE tst_exams ADD COLUMN Sent ENUM('N','Y') NOT NULL DEFAULT 'N' AFTER NumQstsNotBlank;
UPDATE tst_exams SET Sent='Y';
DROP TABLE IF EXISTS tst_status;
Only if you use MyISAM:
ALTER TABLE buildings ENGINE=MyISAM;
Version 19.188.2: Apr 16, 2020 Changed some icons. (287754 lines)
Copy the following icons to icon public directory:

View File

@ -2876,10 +2876,11 @@ mysql> DESCRIBE tst_exams;
| EndTime | datetime | NO | | NULL | |
| NumQsts | int(11) | NO | | 0 | |
| NumQstsNotBlank | int(11) | NO | | 0 | |
| Sent | enum('N','Y') | NO | | N | |
| AllowTeachers | enum('N','Y') | NO | | N | |
| Score | double | NO | | 0 | |
+-----------------+---------------+------+-----+---------+----------------+
9 rows in set (0.00 sec)
10 rows in set (0.00 sec)
*/
DB_CreateTable ("CREATE TABLE IF NOT EXISTS tst_exams ("
"ExaCod INT NOT NULL AUTO_INCREMENT,"
@ -2889,6 +2890,7 @@ mysql> DESCRIBE tst_exams;
"EndTime DATETIME NOT NULL,"
"NumQsts INT NOT NULL DEFAULT 0,"
"NumQstsNotBlank INT NOT NULL DEFAULT 0,"
"Sent ENUM('N','Y') NOT NULL DEFAULT 'N',"
"AllowTeachers ENUM('N','Y') NOT NULL DEFAULT 'N',"
"Score DOUBLE PRECISION NOT NULL DEFAULT 0,"
"UNIQUE INDEX(ExaCod),"
@ -2948,26 +2950,6 @@ mysql> DESCRIBE tst_questions;
"INDEX(CrsCod,EditTime),"
"INDEX(MedCod))");
/***** Table tst_status *****/
/*
mysql> DESCRIBE tst_status;
+-----------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+------------+------+-----+---------+-------+
| SessionId | char(43) | NO | PRI | NULL | |
| CrsCod | int(11) | NO | PRI | NULL | |
| NumTst | int(11) | NO | PRI | NULL | |
| Status | tinyint(4) | NO | | NULL | |
+-----------+------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
*/
DB_CreateTable ("CREATE TABLE IF NOT EXISTS tst_status ("
"SessionId CHAR(43) NOT NULL,"
"CrsCod INT NOT NULL,"
"NumTst INT NOT NULL,"
"Status TINYINT NOT NULL,"
"UNIQUE INDEX(SessionId,CrsCod,NumTst))");
/***** Table tst_tags *****/
/*
mysql> DESCRIBE tst_tags;

View File

@ -61,7 +61,7 @@ extern struct Globals Gbl;
#define Gam_MAX_ANSWERS_PER_QUESTION 10
#define Gam_MAX_SELECTED_QUESTIONS 1000
#define Gam_MAX_SELECTED_QUESTIONS 10000
#define Gam_MAX_BYTES_LIST_SELECTED_QUESTIONS (Gam_MAX_SELECTED_QUESTIONS * (Cns_MAX_DECIMAL_DIGITS_LONG + 1))
/* Score range [0...max.score]
@ -2150,6 +2150,9 @@ void Gam_AddTstQuestionsToGame (void)
long QstCod;
unsigned MaxQstInd;
/***** Reset games *****/
Gam_ResetGames (&Games);
/***** Get parameters *****/
if ((Game.GamCod = Gam_GetParams (&Games)) <= 0)
Lay_ShowErrorAndExit ("Code of game is missing.");
@ -2214,7 +2217,7 @@ static void Gam_AllocateListSelectedQuestions (struct Gam_Games *Games)
if (!Games->ListQuestions)
{
if ((Games->ListQuestions = (char *) malloc (Gam_MAX_BYTES_LIST_SELECTED_QUESTIONS + 1)) == NULL)
Lay_NotEnoughMemoryExit ();;
Lay_NotEnoughMemoryExit ();
Games->ListQuestions[0] = '\0';
}
}
@ -2429,6 +2432,9 @@ void Gam_MoveDownQst (void)
unsigned QstIndBottom;
unsigned MaxQstInd; // 0 if no questions
/***** Reset games *****/
Gam_ResetGames (&Games);
/***** Get parameters *****/
if ((Game.GamCod = Gam_GetParams (&Games)) <= 0)
Lay_ShowErrorAndExit ("Code of game is missing.");

View File

@ -176,6 +176,11 @@ void Roo_SeeRooms (void)
HTM_Int (Rooms.Lst[NumRoom].Floor);
HTM_TD_End ();
/* Type */
HTM_TD_Begin ("class=\"DAT LM %s\"",Gbl.ColorRows[RowEvenOdd]);
HTM_Txt (Rooms.Lst[NumRoom].ShrtName);
HTM_TD_End ();
/* Short name */
HTM_TD_Begin ("class=\"DAT LM %s\"",Gbl.ColorRows[RowEvenOdd]);
HTM_Txt (Rooms.Lst[NumRoom].ShrtName);
@ -341,9 +346,10 @@ void Roo_GetListRooms (struct Roo_Rooms *Rooms,
{
[Roo_ORDER_BY_BUILDING ] = "buildings.ShortName,rooms.Floor,rooms.ShortName",
[Roo_ORDER_BY_FLOOR ] = "rooms.Floor,buildings.ShortName,rooms.ShortName",
[Roo_ORDER_BY_TYPE ] = "rooms.Floor,buildings.ShortName,rooms.ShortName",
[Roo_ORDER_BY_SHRT_NAME] = "rooms.ShortName,rooms.FullName",
[Roo_ORDER_BY_FULL_NAME] = "rooms.FullName,rooms.ShortName",
[Roo_ORDER_BY_CAPACITY ] = "rooms.Capacity DESC,rooms.ShortName",
[Roo_ORDER_BY_CAPACITY ] = "rooms.Capacity DESC,buildings.ShortName,rooms.Floor,rooms.ShortName",
};
MYSQL_RES *mysql_res;
MYSQL_ROW row;
@ -602,6 +608,15 @@ static void Roo_ListRoomsForEdition (const struct Bld_Buildings *Buildings,
Frm_EndForm ();
HTM_TD_End ();
/* Room type */
HTM_TD_Begin ("class=\"LM\"");
Frm_StartForm (ActRenRooSho);
Roo_PutParamRooCod (Room->RooCod);
HTM_INPUT_TEXT ("ShortName",Roo_MAX_CHARS_SHRT_NAME,Room->ShrtName,true,
"size=\"10\" class=\"INPUT_SHORT_NAME\"");
Frm_EndForm ();
HTM_TD_End ();
/* Room short name */
HTM_TD_Begin ("class=\"LM\"");
Frm_StartForm (ActRenRooSho);
@ -1112,6 +1127,12 @@ static void Roo_PutFormToCreateRoom (const struct Bld_Buildings *Buildings)
"class=\"INPUT_LONG\"");
HTM_TD_End ();
/***** Room type *****/
HTM_TD_Begin ("class=\"LM\"");
HTM_INPUT_TEXT ("ShortName",Roo_MAX_CHARS_SHRT_NAME,Roo_EditingRoom->ShrtName,false,
"size=\"10\" class=\"INPUT_SHORT_NAME\" required=\"required\"");
HTM_TD_End ();
/***** Room short name *****/
HTM_TD_Begin ("class=\"LM\"");
HTM_INPUT_TEXT ("ShortName",Roo_MAX_CHARS_SHRT_NAME,Roo_EditingRoom->ShrtName,false,
@ -1149,6 +1170,7 @@ static void Roo_PutHeadRooms (void)
extern const char *Txt_Code;
extern const char *Txt_Building;
extern const char *Txt_Floor;
extern const char *Txt_Type;
extern const char *Txt_Short_name;
extern const char *Txt_Full_name;
extern const char *Txt_Capacity_OF_A_ROOM;
@ -1159,6 +1181,7 @@ static void Roo_PutHeadRooms (void)
HTM_TH (1,1,"RM",Txt_Code);
HTM_TH (1,1,"LM",Txt_Building);
HTM_TH (1,1,"LM",Txt_Floor);
HTM_TH (1,1,"LM",Txt_Type);
HTM_TH (1,1,"LM",Txt_Short_name);
HTM_TH (1,1,"LM",Txt_Full_name);
HTM_TH (1,1,"LM",Txt_Capacity_OF_A_ROOM);

View File

@ -85,14 +85,15 @@ struct Roo_Room
// (maximum people who fit in the room)
};
#define Roo_NUM_ORDERS 5
#define Roo_NUM_ORDERS 6
typedef enum
{
Roo_ORDER_BY_BUILDING = 0,
Roo_ORDER_BY_FLOOR = 1,
Roo_ORDER_BY_SHRT_NAME = 2,
Roo_ORDER_BY_FULL_NAME = 3,
Roo_ORDER_BY_CAPACITY = 4,
Roo_ORDER_BY_TYPE = 2,
Roo_ORDER_BY_SHRT_NAME = 3,
Roo_ORDER_BY_FULL_NAME = 4,
Roo_ORDER_BY_CAPACITY = 5,
} Roo_Order_t;
#define Roo_ORDER_DEFAULT Roo_ORDER_BY_BUILDING

View File

@ -102,14 +102,6 @@ static const char *Tst_StrAnswerTypesDB[Tst_NUM_ANS_TYPES] =
/******************************* Private types *******************************/
/*****************************************************************************/
#define Tst_NUM_STATUS 2
typedef enum
{
Tst_STATUS_SHOWN_BUT_NOT_ASSESSED = 0,
Tst_STATUS_ASSESSED = 1,
Tst_STATUS_ERROR = 2,
} Tst_Status_t;
#define Tst_NUM_REQUEST_OR_CONFIRM 2
typedef enum
{
@ -143,8 +135,6 @@ static void Tst_PutCheckBoxAllowTeachers (bool AllowTeachers);
static void Tst_GetAnswersFromForm (struct TstExa_Exam *Exam);
static bool Tst_CheckIfNextTstAllowed (void);
static void Tst_SetTstStatus (unsigned NumTst,Tst_Status_t TstStatus);
static Tst_Status_t Tst_GetTstStatus (unsigned NumTst);
static unsigned Tst_GetNumExamsGeneratedByMe (void);
static void Tst_ShowTestExamToFillIt (struct TstExa_Exam *Exam,
unsigned NumExamsGeneratedByMe,
@ -482,9 +472,6 @@ void Tst_ShowNewTest (void)
/***** Show test exam to be answered *****/
Tst_ShowTestExamToFillIt (&Exam,NumExamsGeneratedByMe,Tst_REQUEST);
/***** Set test status *****/
Tst_SetTstStatus (NumExamsGeneratedByMe,Tst_STATUS_SHOWN_BUT_NOT_ASSESSED);
/***** Update date-time of my next allowed access to test *****/
if (Gbl.Usrs.Me.Role.Logged == Rol_STD)
Tst_UpdateLastAccTst (Test.NumQsts);
@ -525,13 +512,12 @@ static void Tst_PutCheckBoxAllowTeachers (bool AllowTeachers)
}
/*****************************************************************************/
/********************* Request the assessment of a test **********************/
/** Receive the draft of a test exam already (total or partially) answered ***/
/*****************************************************************************/
void Tst_RequestAssessTest (void)
void Tst_ReceiveTestDraft (void)
{
extern const char *Txt_The_test_X_has_already_been_assessed_previously;
extern const char *Txt_There_was_an_error_in_assessing_the_test_X;
unsigned NumTst;
struct TstExa_Exam Exam;
@ -547,37 +533,32 @@ void Tst_RequestAssessTest (void)
/* Get number of this test from form */
NumTst = Tst_GetParamNumTst ();
/***** Get test exam from database *****/
TstExa_GetExamDataByExaCod (&Exam);
/****** Get test status in database for this session-course-num.test *****/
switch (Tst_GetTstStatus (NumTst))
if (Exam.Sent)
Ale_ShowAlert (Ale_WARNING,Txt_The_test_X_has_already_been_assessed_previously,
NumTst);
else // Exam not yet sent
{
case Tst_STATUS_SHOWN_BUT_NOT_ASSESSED:
/***** Get test exam from database *****/
TstExa_GetExamDataByExaCod (&Exam);
TstExa_GetExamQuestionsFromDB (&Exam);
/***** Get test exam questions from database *****/
TstExa_GetExamQuestionsFromDB (&Exam);
/***** Get answers from form to assess a test *****/
Tst_GetAnswersFromForm (&Exam);
/***** Get answers from form to assess a test *****/
Tst_GetAnswersFromForm (&Exam);
/***** Update test exam in database *****/
TstExa_ComputeScoresAndStoreExamQuestions (&Exam,
false); // Don't update question score
TstExa_UpdateExamInDB (&Exam);
/***** Update test exam in database *****/
TstExa_ComputeScoresAndStoreExamQuestions (&Exam,
false); // Don't update question score
TstExa_UpdateExamInDB (&Exam);
/***** 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!!!
/***** 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!!!
/* Show the same test exam to be answered */
Tst_ShowTestExamToFillIt (&Exam,NumTst,Tst_CONFIRM);
break;
case Tst_STATUS_ASSESSED:
Ale_ShowAlert (Ale_WARNING,Txt_The_test_X_has_already_been_assessed_previously,
NumTst);
break;
case Tst_STATUS_ERROR:
Ale_ShowAlert (Ale_WARNING,Txt_There_was_an_error_in_assessing_the_test_X,
NumTst);
break;
/* Show the same test exam to be answered */
Tst_ShowTestExamToFillIt (&Exam,NumTst,Tst_CONFIRM);
}
}
@ -593,7 +574,6 @@ void Tst_AssessTest (void)
extern const char *Txt_Score;
extern const char *Txt_Grade;
extern const char *Txt_The_test_X_has_already_been_assessed_previously;
extern const char *Txt_There_was_an_error_in_assessing_the_test_X;
unsigned NumTst;
struct TstExa_Exam Exam;
@ -609,73 +589,66 @@ void Tst_AssessTest (void)
/* Get number of this test from form */
NumTst = Tst_GetParamNumTst ();
/***** Get test exam from database *****/
TstExa_GetExamDataByExaCod (&Exam);
/****** Get test status in database for this session-course-num.test *****/
switch (Tst_GetTstStatus (NumTst))
if (Exam.Sent)
Ale_ShowAlert (Ale_WARNING,Txt_The_test_X_has_already_been_assessed_previously,
NumTst);
else // Exam not yet sent
{
case Tst_STATUS_SHOWN_BUT_NOT_ASSESSED:
/***** Get test exam from database *****/
TstExa_GetExamDataByExaCod (&Exam);
TstExa_GetExamQuestionsFromDB (&Exam);
/***** Get test exam questions from database *****/
TstExa_GetExamQuestionsFromDB (&Exam);
/***** Get answers from form to assess a test *****/
Tst_GetAnswersFromForm (&Exam);
/***** Get answers from form to assess a test *****/
Tst_GetAnswersFromForm (&Exam);
/***** Get if test exam will be visible by teachers *****/
Exam.AllowTeachers = Par_GetParToBool ("AllowTchs");
/***** Get if test exam will be visible by teachers *****/
Exam.Sent = true; // The exam has been finished and sent by student
Exam.AllowTeachers = Par_GetParToBool ("AllowTchs");
/***** Update test exam in database *****/
TstExa_ComputeScoresAndStoreExamQuestions (&Exam,
Gbl.Usrs.Me.Role.Logged == Rol_STD); // Update question score?
TstExa_UpdateExamInDB (&Exam);
/***** Update test exam in database *****/
TstExa_ComputeScoresAndStoreExamQuestions (&Exam,
Gbl.Usrs.Me.Role.Logged == Rol_STD); // Update question score?
TstExa_UpdateExamInDB (&Exam);
/***** Begin box *****/
Box_BoxBegin (NULL,Txt_Test_result,
NULL,NULL,
Hlp_ASSESSMENT_Tests,Box_NOT_CLOSABLE);
Lay_WriteHeaderClassPhoto (false,false,
Gbl.Hierarchy.Ins.InsCod,
Gbl.Hierarchy.Deg.DegCod,
Gbl.Hierarchy.Crs.CrsCod);
/***** Begin box *****/
Box_BoxBegin (NULL,Txt_Test_result,
NULL,NULL,
Hlp_ASSESSMENT_Tests,Box_NOT_CLOSABLE);
Lay_WriteHeaderClassPhoto (false,false,
Gbl.Hierarchy.Ins.InsCod,
Gbl.Hierarchy.Deg.DegCod,
Gbl.Hierarchy.Crs.CrsCod);
/***** Header *****/
if (Gbl.Usrs.Me.IBelongToCurrentCrs)
{
HTM_DIV_Begin ("class=\"TEST_SUBTITLE\"");
HTM_TxtF (Txt_Test_No_X_that_you_make_in_this_course,NumTst);
HTM_DIV_End ();
}
/***** Header *****/
if (Gbl.Usrs.Me.IBelongToCurrentCrs)
{
HTM_DIV_Begin ("class=\"TEST_SUBTITLE\"");
HTM_TxtF (Txt_Test_No_X_that_you_make_in_this_course,NumTst);
HTM_DIV_End ();
}
/***** Write answers and solutions *****/
TstExa_ShowExamAfterAssess (&Exam);
/***** Write answers and solutions *****/
TstExa_ShowExamAfterAssess (&Exam);
/***** Write total score and grade *****/
if (TstVis_IsVisibleTotalScore (TstCfg_GetConfigVisibility ()))
{
HTM_DIV_Begin ("class=\"DAT_N_BOLD CM\"");
HTM_TxtColonNBSP (Txt_Score);
HTM_Double2Decimals (Exam.Score);
HTM_BR ();
HTM_TxtColonNBSP (Txt_Grade);
TstExa_ComputeAndShowGrade (Exam.NumQsts,
Exam.Score,
TstExa_SCORE_MAX);
HTM_DIV_End ();
}
/***** Write total score and grade *****/
if (TstVis_IsVisibleTotalScore (TstCfg_GetConfigVisibility ()))
{
HTM_DIV_Begin ("class=\"DAT_N_BOLD CM\"");
HTM_TxtColonNBSP (Txt_Score);
HTM_Double2Decimals (Exam.Score);
HTM_BR ();
HTM_TxtColonNBSP (Txt_Grade);
TstExa_ComputeAndShowGrade (Exam.NumQsts,
Exam.Score,
TstExa_SCORE_MAX);
HTM_DIV_End ();
}
/***** End box *****/
Box_BoxEnd ();
/***** Set test status *****/
Tst_SetTstStatus (NumTst,Tst_STATUS_ASSESSED);
break;
case Tst_STATUS_ASSESSED:
Ale_ShowAlert (Ale_WARNING,Txt_The_test_X_has_already_been_assessed_previously,
NumTst);
break;
case Tst_STATUS_ERROR:
Ale_ShowAlert (Ale_WARNING,Txt_There_was_an_error_in_assessing_the_test_X,
NumTst);
break;
/***** End box *****/
Box_BoxEnd ();
}
}
@ -764,62 +737,6 @@ static bool Tst_CheckIfNextTstAllowed (void)
return true;
}
/*****************************************************************************/
/****************************** Update test status ***************************/
/*****************************************************************************/
static void Tst_SetTstStatus (unsigned NumTst,Tst_Status_t TstStatus)
{
/***** Delete old status from expired sessions *****/
DB_QueryDELETE ("can not remove old status of tests",
"DELETE FROM tst_status"
" WHERE SessionId NOT IN"
" (SELECT SessionId FROM sessions)");
/***** Update database *****/
DB_QueryREPLACE ("can not update status of test",
"REPLACE INTO tst_status"
" (SessionId,CrsCod,NumTst,Status)"
" VALUES"
" ('%s',%ld,%u,%u)",
Gbl.Session.Id,Gbl.Hierarchy.Crs.CrsCod,
NumTst,(unsigned) TstStatus);
}
/*****************************************************************************/
/****************************** Update test status ***************************/
/*****************************************************************************/
static Tst_Status_t Tst_GetTstStatus (unsigned NumTst)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned UnsignedNum;
Tst_Status_t TstStatus = Tst_STATUS_ERROR;
/***** Get status of test from database *****/
if (DB_QuerySELECT (&mysql_res,"can not get status of test",
"SELECT Status" // row[0]
" FROM tst_status"
" WHERE SessionId='%s'"
" AND CrsCod=%ld"
" AND NumTst=%u",
Gbl.Session.Id,Gbl.Hierarchy.Crs.CrsCod,NumTst) == 1)
{
/* Get number of hits */
row = mysql_fetch_row (mysql_res);
if (row[0])
if (sscanf (row[0],"%u",&UnsignedNum) == 1)
if (UnsignedNum < Tst_NUM_STATUS)
TstStatus = (Tst_Status_t) UnsignedNum;
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return TstStatus;
}
/*****************************************************************************/
/***************** Get number of test exams generated by me ******************/
/*****************************************************************************/
@ -5968,16 +5885,11 @@ static void Tst_InsertAnswersIntoDB (struct Tst_Question *Question)
}
/*****************************************************************************/
/******************* Remove all test exams made in a course ******************/
/******************* Remove all test questions in a course *******************/
/*****************************************************************************/
void Tst_RemoveCrsTests (long CrsCod)
{
/***** Remove tests status in the course *****/
DB_QueryDELETE ("can not remove status of tests of a course",
"DELETE FROM tst_status WHERE CrsCod=%ld",
CrsCod);
/***** Remove test configuration of the course *****/
DB_QueryDELETE ("can not remove configuration of tests of a course",
"DELETE FROM tst_config WHERE CrsCod=%ld",

View File

@ -155,7 +155,7 @@ struct Tst_Stats
void Tst_RequestTest (void);
void Tst_ShowNewTest (void);
void Tst_RequestAssessTest (void);
void Tst_ReceiveTestDraft (void);
void Tst_AssessTest (void);
void Tst_ShowTagList (unsigned NumTags,MYSQL_RES *mysql_res);

View File

@ -56,14 +56,6 @@
/******************************* Private types *******************************/
/*****************************************************************************/
#define Tst_NUM_STATUS 2
typedef enum
{
Tst_STATUS_SHOWN_BUT_NOT_ASSESSED = 0,
Tst_STATUS_ASSESSED = 1,
Tst_STATUS_ERROR = 2,
} Tst_Status_t;
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
@ -78,6 +70,8 @@ extern struct Globals Gbl;
/***************************** Private prototypes ****************************/
/*****************************************************************************/
static void TstExa_ResetExamExceptExaCod (struct TstExa_Exam *Exam);
static void TstExa_WriteQstAndAnsExam (struct UsrData *UsrDat,
struct TstExa_Exam *Exam,
unsigned NumQst,
@ -164,12 +158,18 @@ static void TstExa_ShowTagsPresentInAnExam (long ExaCod);
void TstExa_ResetExam (struct TstExa_Exam *Exam)
{
Exam->ExaCod = -1L;
Exam->ExaCod = -1L;
TstExa_ResetExamExceptExaCod (Exam);
}
static void TstExa_ResetExamExceptExaCod (struct TstExa_Exam *Exam)
{
Exam->TimeUTC[Dat_START_TIME] =
Exam->TimeUTC[Dat_END_TIME ] = (time_t) 0;
Exam->NumQsts =
Exam->NumQstsNotBlank = 0;
Exam->AllowTeachers = false;
Exam->Sent = false; // After creating an exam, it's not sent
Exam->AllowTeachers = false; // Teachers can't seen the exam if student don't allow it
Exam->Score = 0.0;
}
@ -183,9 +183,11 @@ void TstExa_CreateExamInDB (struct TstExa_Exam *Exam)
Exam->ExaCod =
DB_QueryINSERTandReturnCode ("can not create new test exam",
"INSERT INTO tst_exams"
" (CrsCod,UsrCod,StartTime,EndTime,NumQsts,AllowTeachers,Score)"
" (CrsCod,UsrCod,StartTime,EndTime,NumQsts,"
"Sent,AllowTeachers,Score)"
" VALUES"
" (%ld,%ld,NOW(),NOW(),%u,'N',0)",
" (%ld,%ld,NOW(),NOW(),%u,"
"'N','N',0)",
Gbl.Hierarchy.Crs.CrsCod,
Gbl.Usrs.Me.UsrDat.UsrCod,
Exam->NumQsts);
@ -203,11 +205,14 @@ void TstExa_UpdateExamInDB (const struct TstExa_Exam *Exam)
"UPDATE tst_exams"
" SET EndTime=NOW(),"
"NumQstsNotBlank=%u,"
"Sent='%c',"
"AllowTeachers='%c',"
"Score='%.15lg'"
" WHERE ExaCod=%ld"
" AND CrsCod=%ld AND UsrCod=%ld", // Extra checks
Exam->NumQstsNotBlank,
Exam->Sent ? 'Y' :
'N',
Exam->AllowTeachers ? 'Y' :
'N',
Exam->Score,
@ -396,7 +401,6 @@ void TstExa_ComputeScoresAndStoreExamQuestions (struct TstExa_Exam *Exam,
if (Exam->Questions[NumQst].AnswerIsNotBlank)
Exam->NumQstsNotBlank++;
/* Update the number of hits and the score of this question in tests database */
if (UpdateQstScore)
Tst_UpdateQstScoreInDB (Exam,NumQst);
@ -1634,8 +1638,12 @@ static void TstExa_ShowExams (struct UsrData *UsrDat)
double TotalScoreOfAllTests = 0.0;
unsigned NumExamsVisibleByTchs = 0;
bool ItsMe = Usr_ItsMe (UsrDat->UsrCod);
bool ICanViewTest;
bool ICanViewScore;
struct
{
bool NumQsts;
bool Score;
bool Exam;
} ICanView;
char *ClassDat;
/***** Make database query *****/
@ -1651,8 +1659,9 @@ static void TstExa_ShowExams (struct UsrData *UsrDat)
"UNIX_TIMESTAMP(EndTime)," // row[2]
"NumQsts," // row[3]
"NumQstsNotBlank," // row[4]
"AllowTeachers," // row[5]
"Score" // row[6]
"Sent," // row[5]
"AllowTeachers," // row[6]
"Score" // row[7]
" FROM tst_exams"
" WHERE CrsCod=%ld AND UsrCod=%ld"
" AND EndTime>=FROM_UNIXTIME(%ld)"
@ -1681,34 +1690,41 @@ static void TstExa_ShowExams (struct UsrData *UsrDat)
if ((Exam.ExaCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
Lay_ShowErrorAndExit ("Wrong code of test exam.");
/* Get if teachers are allowed to see this test exams (row[5]) */
Exam.AllowTeachers = (row[5][0] == 'Y');
/* Get if exam has been sent (row[5]) */
Exam.Sent = (row[5][0] == 'Y');
/* Get if teachers are allowed to see this test exam (row[6]) */
Exam.AllowTeachers = (row[6][0] == 'Y');
ClassDat = Exam.AllowTeachers ? "DAT" :
"DAT_LIGHT";
"DAT_LIGHT";
switch (Gbl.Usrs.Me.Role.Logged)
{
case Rol_STD:
ICanViewTest = ItsMe;
ICanViewScore = ItsMe &&
TstVis_IsVisibleTotalScore (TstCfg_GetConfigVisibility ());
ICanView.NumQsts = Exam.Sent && ItsMe;
ICanView.Score = Exam.Sent && ItsMe &&
TstVis_IsVisibleTotalScore (TstCfg_GetConfigVisibility ());
ICanView.Exam = Exam.Sent && ItsMe;
break;
case Rol_NET:
case Rol_TCH:
case Rol_DEG_ADM:
case Rol_CTR_ADM:
case Rol_INS_ADM:
ICanViewTest =
ICanViewScore = ItsMe ||
Exam.AllowTeachers;
ICanView.NumQsts = Exam.Sent; // If the exam has been sent,
// teachers can see the number of questions
ICanView.Score =
ICanView.Exam = Exam.Sent && (ItsMe || Exam.AllowTeachers);
break;
case Rol_SYS_ADM:
ICanViewTest =
ICanViewScore = true;
ICanView.NumQsts =
ICanView.Score =
ICanView.Exam = true;
break;
default:
ICanViewTest =
ICanViewScore = false;
ICanView.NumQsts =
ICanView.Score =
ICanView.Exam = false;
break;
}
@ -1746,9 +1762,9 @@ static void TstExa_ShowExams (struct UsrData *UsrDat)
if (Exam.AllowTeachers)
NumTotalQstsNotBlank += Exam.NumQstsNotBlank;
/* Get score (row[6]) */
/* Get score (row[7]) */
Str_SetDecimalPointToUS (); // To get the decimal point as a dot
if (sscanf (row[6],"%lf",&Exam.Score) != 1)
if (sscanf (row[7],"%lf",&Exam.Score) != 1)
Exam.Score = 0.0;
Str_SetDecimalPointToLocal (); // Return to local system
if (Exam.AllowTeachers)
@ -1756,25 +1772,25 @@ static void TstExa_ShowExams (struct UsrData *UsrDat)
/* Write number of questions */
HTM_TD_Begin ("class=\"%s RT COLOR%u\"",ClassDat,Gbl.RowEvenOdd);
if (ICanViewTest)
if (ICanView.NumQsts)
HTM_Unsigned (Exam.NumQsts);
HTM_TD_End ();
/* Write number of questions not blank */
HTM_TD_Begin ("class=\"%s RT COLOR%u\"",ClassDat,Gbl.RowEvenOdd);
if (ICanViewTest)
if (ICanView.NumQsts)
HTM_Unsigned (Exam.NumQstsNotBlank);
HTM_TD_End ();
/* Write score */
HTM_TD_Begin ("class=\"%s RT COLOR%u\"",ClassDat,Gbl.RowEvenOdd);
if (ICanViewScore)
if (ICanView.Score)
HTM_Double2Decimals (Exam.Score);
HTM_TD_End ();
/* Write average score per question */
HTM_TD_Begin ("class=\"%s RT COLOR%u\"",ClassDat,Gbl.RowEvenOdd);
if (ICanViewScore)
if (ICanView.Score)
HTM_Double2Decimals (Exam.NumQsts ? Exam.Score /
(double) Exam.NumQsts :
0.0);
@ -1782,15 +1798,15 @@ static void TstExa_ShowExams (struct UsrData *UsrDat)
/* Write grade */
HTM_TD_Begin ("class=\"%s RT COLOR%u\"",ClassDat,Gbl.RowEvenOdd);
if (ICanViewScore)
if (ICanView.Score)
TstExa_ComputeAndShowGrade (Exam.NumQsts,
Exam.Score,
TstExa_SCORE_MAX);
Exam.Score,
TstExa_SCORE_MAX);
HTM_TD_End ();
/* Link to show this test exam */
HTM_TD_Begin ("class=\"RT COLOR%u\"",Gbl.RowEvenOdd);
if (ICanViewTest)
if (ICanView.Exam)
{
Frm_StartForm (Gbl.Action.Act == ActSeeMyTstRes ? ActSeeOneTstResMe :
ActSeeOneTstResOth);
@ -1807,8 +1823,8 @@ static void TstExa_ShowExams (struct UsrData *UsrDat)
/***** Write totals for this user *****/
TstExa_ShowExamsSummaryRow (ItsMe,NumExamsVisibleByTchs,
NumTotalQsts,NumTotalQstsNotBlank,
TotalScoreOfAllTests);
NumTotalQsts,NumTotalQstsNotBlank,
TotalScoreOfAllTests);
}
else
{
@ -2242,8 +2258,9 @@ void TstExa_GetExamDataByExaCod (struct TstExa_Exam *Exam)
"UNIX_TIMESTAMP(EndTime)," // row[2]
"NumQsts," // row[3]
"NumQstsNotBlank," // row[4]
"AllowTeachers," // row[5]
"Score" // row[6]
"Sent," // row[5]
"AllowTeachers," // row[6]
"Score" // row[7]
" FROM tst_exams"
" WHERE ExaCod=%ld AND CrsCod=%ld",
Exam->ExaCod,
@ -2266,24 +2283,20 @@ void TstExa_GetExamDataByExaCod (struct TstExa_Exam *Exam)
if (sscanf (row[4],"%u",&Exam->NumQstsNotBlank) != 1)
Exam->NumQstsNotBlank = 0;
/* Get if teachers are allowed to see this test exam (row[5]) */
Exam->AllowTeachers = (row[5][0] == 'Y');
/* Get if exam has been sent (row[5]) */
Exam->Sent = (row[5][0] == 'Y');
/* Get score (row[6]) */
/* Get if teachers are allowed to see this test exam (row[6]) */
Exam->AllowTeachers = (row[6][0] == 'Y');
/* Get score (row[7]) */
Str_SetDecimalPointToUS (); // To get the decimal point as a dot
if (sscanf (row[6],"%lf",&Exam->Score) != 1)
if (sscanf (row[7],"%lf",&Exam->Score) != 1)
Exam->Score = 0.0;
Str_SetDecimalPointToLocal (); // Return to local system
}
else
{
Exam->TimeUTC[Dat_START_TIME] =
Exam->TimeUTC[Dat_END_TIME ] = 0;
Exam->NumQsts = 0;
Exam->NumQstsNotBlank = 0;
Exam->AllowTeachers = false;
Exam->Score = 0.0;
}
TstExa_ResetExamExceptExaCod (Exam);
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);

View File

@ -51,6 +51,8 @@ struct TstExa_Exam
time_t TimeUTC[Dat_NUM_START_END_TIME];
unsigned NumQsts; // Number of questions
unsigned NumQstsNotBlank; // Number of questions not blank
bool Sent; // This test exam has been sent or not?
// "Sent" means that user has clicked "Send" button after finishing
bool AllowTeachers; // Are teachers allowed to see this test exam?
double Score; // Total score of the test exam
struct

View File

@ -38201,6 +38201,27 @@ const char *Txt_ROOMS_HELP_ORDER[Roo_NUM_ORDERS] =
"Sortuj wed&lstrok;ug pi&eogon;trze"
#elif L==9 // pt
"Classificar por andar"
#endif
,
[Roo_ORDER_BY_TYPE] =
#if L==1 // ca
"Ordenar per tipus"
#elif L==2 // de
"Nach Art sortieren"
#elif L==3 // en
"Sort by type"
#elif L==4 // es
"Ordenar por tipo"
#elif L==5 // fr
"Trier par type"
#elif L==6 // gn
"Ordenar por tipo" // Okoteve traducción
#elif L==7 // it
"Ordina per tipo"
#elif L==8 // pl
"Sortuj wed&lstrok;ug typ"
#elif L==9 // pt
"Classificar por tipo"
#endif
,
[Roo_ORDER_BY_SHRT_NAME] =
@ -38309,6 +38330,27 @@ const char *Txt_ROOMS_ORDER[Roo_NUM_ORDERS] =
"Pi&eogon;trze"
#elif L==9 // pt
"Andar"
#endif
,
[Roo_ORDER_BY_TYPE] =
#if L==1 // ca
"Tipus"
#elif L==2 // de
"Art"
#elif L==3 // en
"Type"
#elif L==4 // es
"Tipo"
#elif L==5 // fr
"Type"
#elif L==6 // gn
"Teko"
#elif L==7 // it
"Tipo"
#elif L==8 // pl
"Typ"
#elif L==9 // pt
"Tipo"
#endif
,
[Roo_ORDER_BY_SHRT_NAME] =
@ -50306,27 +50348,6 @@ const char *Txt_There_was_a_problem_sending_an_email_automatically =
"Ocorreu um problema ao enviar um email automaticamente.";
#endif
const char *Txt_There_was_an_error_in_assessing_the_test_X = // Warning: it is very important to include %u in the following sentences
#if L==1 // ca
"Se ha producido un error al evaluar el test %u."; // Necessita traduccio
#elif L==2 // de
"There was an error in assessing the test %u."; // Need Übersetzung
#elif L==3 // en
"There was an error in assessing the test %u.";
#elif L==4 // es
"Se ha producido un error al evaluar el test %u.";
#elif L==5 // fr
"There was an error in assessing the test %u."; // Besoin de traduction
#elif L==6 // gn
"Se ha producido un error al evaluar el test %u."; // Okoteve traducción
#elif L==7 // it
"C'&egrave; stato un errore nel valutare il test %u.";
#elif L==8 // pl
"There was an error in assessing the test %u."; // Potrzebujesz tlumaczenie
#elif L==9 // pt
"Houve um erro ao avaliar o teste %u.";
#endif
const char *Txt_This_game_has_no_questions =
#if L==1 // ca
"Aquest joc no t&eacute; preguntes.";