mirror of
https://github.com/acanas/swad-core.git
synced 2024-07-01 21:05:42 +02:00
Version19.189
This commit is contained in:
parent
c7a91ffaec
commit
e31ab3c7e9
10
sql/swad.sql
10
sql/swad.sql
|
@ -1385,6 +1385,7 @@ CREATE TABLE IF NOT EXISTS tst_exams (
|
||||||
EndTime DATETIME NOT NULL,
|
EndTime DATETIME NOT NULL,
|
||||||
NumQsts INT NOT NULL DEFAULT 0,
|
NumQsts INT NOT NULL DEFAULT 0,
|
||||||
NumQstsNotBlank 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',
|
AllowTeachers ENUM('N','Y') NOT NULL DEFAULT 'N',
|
||||||
Score DOUBLE PRECISION NOT NULL DEFAULT 0,
|
Score DOUBLE PRECISION NOT NULL DEFAULT 0,
|
||||||
UNIQUE INDEX(ExaCod),
|
UNIQUE INDEX(ExaCod),
|
||||||
|
@ -1416,15 +1417,6 @@ CREATE TABLE IF NOT EXISTS tst_questions (
|
||||||
INDEX(CrsCod,EditTime),
|
INDEX(CrsCod,EditTime),
|
||||||
INDEX(MedCod));
|
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
|
-- Table tst_tags: stores the tags of test questions
|
||||||
--
|
--
|
||||||
CREATE TABLE IF NOT EXISTS tst_tags (
|
CREATE TABLE IF NOT EXISTS tst_tags (
|
||||||
|
|
|
@ -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},
|
[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},
|
[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},
|
[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},
|
[ActEdiTstQst ] = { 104,-1,TabUnk,ActReqTst ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,Dat_SetIniEndDates ,Tst_RequestEditTests ,NULL},
|
||||||
|
|
|
@ -497,7 +497,7 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - *
|
||||||
En OpenSWAD:
|
En OpenSWAD:
|
||||||
ps2pdf source.ps destination.pdf
|
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 CSS_FILE "swad19.187.css"
|
||||||
#define JS_FILE "swad19.172.1.js"
|
#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: 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: 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: 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)
|
Version 19.188.2: Apr 16, 2020 Changed some icons. (287754 lines)
|
||||||
Copy the following icons to icon public directory:
|
Copy the following icons to icon public directory:
|
||||||
|
|
|
@ -2876,10 +2876,11 @@ mysql> DESCRIBE tst_exams;
|
||||||
| EndTime | datetime | NO | | NULL | |
|
| EndTime | datetime | NO | | NULL | |
|
||||||
| NumQsts | int(11) | NO | | 0 | |
|
| NumQsts | int(11) | NO | | 0 | |
|
||||||
| NumQstsNotBlank | int(11) | NO | | 0 | |
|
| NumQstsNotBlank | int(11) | NO | | 0 | |
|
||||||
|
| Sent | enum('N','Y') | NO | | N | |
|
||||||
| AllowTeachers | enum('N','Y') | NO | | N | |
|
| AllowTeachers | enum('N','Y') | NO | | N | |
|
||||||
| Score | double | NO | | 0 | |
|
| 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 ("
|
DB_CreateTable ("CREATE TABLE IF NOT EXISTS tst_exams ("
|
||||||
"ExaCod INT NOT NULL AUTO_INCREMENT,"
|
"ExaCod INT NOT NULL AUTO_INCREMENT,"
|
||||||
|
@ -2889,6 +2890,7 @@ mysql> DESCRIBE tst_exams;
|
||||||
"EndTime DATETIME NOT NULL,"
|
"EndTime DATETIME NOT NULL,"
|
||||||
"NumQsts INT NOT NULL DEFAULT 0,"
|
"NumQsts INT NOT NULL DEFAULT 0,"
|
||||||
"NumQstsNotBlank 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',"
|
"AllowTeachers ENUM('N','Y') NOT NULL DEFAULT 'N',"
|
||||||
"Score DOUBLE PRECISION NOT NULL DEFAULT 0,"
|
"Score DOUBLE PRECISION NOT NULL DEFAULT 0,"
|
||||||
"UNIQUE INDEX(ExaCod),"
|
"UNIQUE INDEX(ExaCod),"
|
||||||
|
@ -2948,26 +2950,6 @@ mysql> DESCRIBE tst_questions;
|
||||||
"INDEX(CrsCod,EditTime),"
|
"INDEX(CrsCod,EditTime),"
|
||||||
"INDEX(MedCod))");
|
"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 *****/
|
/***** Table tst_tags *****/
|
||||||
/*
|
/*
|
||||||
mysql> DESCRIBE tst_tags;
|
mysql> DESCRIBE tst_tags;
|
||||||
|
|
10
swad_game.c
10
swad_game.c
|
@ -61,7 +61,7 @@ extern struct Globals Gbl;
|
||||||
|
|
||||||
#define Gam_MAX_ANSWERS_PER_QUESTION 10
|
#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))
|
#define Gam_MAX_BYTES_LIST_SELECTED_QUESTIONS (Gam_MAX_SELECTED_QUESTIONS * (Cns_MAX_DECIMAL_DIGITS_LONG + 1))
|
||||||
|
|
||||||
/* Score range [0...max.score]
|
/* Score range [0...max.score]
|
||||||
|
@ -2150,6 +2150,9 @@ void Gam_AddTstQuestionsToGame (void)
|
||||||
long QstCod;
|
long QstCod;
|
||||||
unsigned MaxQstInd;
|
unsigned MaxQstInd;
|
||||||
|
|
||||||
|
/***** Reset games *****/
|
||||||
|
Gam_ResetGames (&Games);
|
||||||
|
|
||||||
/***** Get parameters *****/
|
/***** Get parameters *****/
|
||||||
if ((Game.GamCod = Gam_GetParams (&Games)) <= 0)
|
if ((Game.GamCod = Gam_GetParams (&Games)) <= 0)
|
||||||
Lay_ShowErrorAndExit ("Code of game is missing.");
|
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)
|
||||||
{
|
{
|
||||||
if ((Games->ListQuestions = (char *) malloc (Gam_MAX_BYTES_LIST_SELECTED_QUESTIONS + 1)) == NULL)
|
if ((Games->ListQuestions = (char *) malloc (Gam_MAX_BYTES_LIST_SELECTED_QUESTIONS + 1)) == NULL)
|
||||||
Lay_NotEnoughMemoryExit ();;
|
Lay_NotEnoughMemoryExit ();
|
||||||
Games->ListQuestions[0] = '\0';
|
Games->ListQuestions[0] = '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2429,6 +2432,9 @@ void Gam_MoveDownQst (void)
|
||||||
unsigned QstIndBottom;
|
unsigned QstIndBottom;
|
||||||
unsigned MaxQstInd; // 0 if no questions
|
unsigned MaxQstInd; // 0 if no questions
|
||||||
|
|
||||||
|
/***** Reset games *****/
|
||||||
|
Gam_ResetGames (&Games);
|
||||||
|
|
||||||
/***** Get parameters *****/
|
/***** Get parameters *****/
|
||||||
if ((Game.GamCod = Gam_GetParams (&Games)) <= 0)
|
if ((Game.GamCod = Gam_GetParams (&Games)) <= 0)
|
||||||
Lay_ShowErrorAndExit ("Code of game is missing.");
|
Lay_ShowErrorAndExit ("Code of game is missing.");
|
||||||
|
|
25
swad_room.c
25
swad_room.c
|
@ -176,6 +176,11 @@ void Roo_SeeRooms (void)
|
||||||
HTM_Int (Rooms.Lst[NumRoom].Floor);
|
HTM_Int (Rooms.Lst[NumRoom].Floor);
|
||||||
HTM_TD_End ();
|
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 */
|
/* Short name */
|
||||||
HTM_TD_Begin ("class=\"DAT LM %s\"",Gbl.ColorRows[RowEvenOdd]);
|
HTM_TD_Begin ("class=\"DAT LM %s\"",Gbl.ColorRows[RowEvenOdd]);
|
||||||
HTM_Txt (Rooms.Lst[NumRoom].ShrtName);
|
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_BUILDING ] = "buildings.ShortName,rooms.Floor,rooms.ShortName",
|
||||||
[Roo_ORDER_BY_FLOOR ] = "rooms.Floor,buildings.ShortName,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_SHRT_NAME] = "rooms.ShortName,rooms.FullName",
|
||||||
[Roo_ORDER_BY_FULL_NAME] = "rooms.FullName,rooms.ShortName",
|
[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_RES *mysql_res;
|
||||||
MYSQL_ROW row;
|
MYSQL_ROW row;
|
||||||
|
@ -602,6 +608,15 @@ static void Roo_ListRoomsForEdition (const struct Bld_Buildings *Buildings,
|
||||||
Frm_EndForm ();
|
Frm_EndForm ();
|
||||||
HTM_TD_End ();
|
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 */
|
/* Room short name */
|
||||||
HTM_TD_Begin ("class=\"LM\"");
|
HTM_TD_Begin ("class=\"LM\"");
|
||||||
Frm_StartForm (ActRenRooSho);
|
Frm_StartForm (ActRenRooSho);
|
||||||
|
@ -1112,6 +1127,12 @@ static void Roo_PutFormToCreateRoom (const struct Bld_Buildings *Buildings)
|
||||||
"class=\"INPUT_LONG\"");
|
"class=\"INPUT_LONG\"");
|
||||||
HTM_TD_End ();
|
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 *****/
|
/***** Room short name *****/
|
||||||
HTM_TD_Begin ("class=\"LM\"");
|
HTM_TD_Begin ("class=\"LM\"");
|
||||||
HTM_INPUT_TEXT ("ShortName",Roo_MAX_CHARS_SHRT_NAME,Roo_EditingRoom->ShrtName,false,
|
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_Code;
|
||||||
extern const char *Txt_Building;
|
extern const char *Txt_Building;
|
||||||
extern const char *Txt_Floor;
|
extern const char *Txt_Floor;
|
||||||
|
extern const char *Txt_Type;
|
||||||
extern const char *Txt_Short_name;
|
extern const char *Txt_Short_name;
|
||||||
extern const char *Txt_Full_name;
|
extern const char *Txt_Full_name;
|
||||||
extern const char *Txt_Capacity_OF_A_ROOM;
|
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,"RM",Txt_Code);
|
||||||
HTM_TH (1,1,"LM",Txt_Building);
|
HTM_TH (1,1,"LM",Txt_Building);
|
||||||
HTM_TH (1,1,"LM",Txt_Floor);
|
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_Short_name);
|
||||||
HTM_TH (1,1,"LM",Txt_Full_name);
|
HTM_TH (1,1,"LM",Txt_Full_name);
|
||||||
HTM_TH (1,1,"LM",Txt_Capacity_OF_A_ROOM);
|
HTM_TH (1,1,"LM",Txt_Capacity_OF_A_ROOM);
|
||||||
|
|
|
@ -85,14 +85,15 @@ struct Roo_Room
|
||||||
// (maximum people who fit in the room)
|
// (maximum people who fit in the room)
|
||||||
};
|
};
|
||||||
|
|
||||||
#define Roo_NUM_ORDERS 5
|
#define Roo_NUM_ORDERS 6
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
Roo_ORDER_BY_BUILDING = 0,
|
Roo_ORDER_BY_BUILDING = 0,
|
||||||
Roo_ORDER_BY_FLOOR = 1,
|
Roo_ORDER_BY_FLOOR = 1,
|
||||||
Roo_ORDER_BY_SHRT_NAME = 2,
|
Roo_ORDER_BY_TYPE = 2,
|
||||||
Roo_ORDER_BY_FULL_NAME = 3,
|
Roo_ORDER_BY_SHRT_NAME = 3,
|
||||||
Roo_ORDER_BY_CAPACITY = 4,
|
Roo_ORDER_BY_FULL_NAME = 4,
|
||||||
|
Roo_ORDER_BY_CAPACITY = 5,
|
||||||
} Roo_Order_t;
|
} Roo_Order_t;
|
||||||
#define Roo_ORDER_DEFAULT Roo_ORDER_BY_BUILDING
|
#define Roo_ORDER_DEFAULT Roo_ORDER_BY_BUILDING
|
||||||
|
|
||||||
|
|
128
swad_test.c
128
swad_test.c
|
@ -102,14 +102,6 @@ static const char *Tst_StrAnswerTypesDB[Tst_NUM_ANS_TYPES] =
|
||||||
/******************************* Private 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
|
#define Tst_NUM_REQUEST_OR_CONFIRM 2
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
|
@ -143,8 +135,6 @@ static void Tst_PutCheckBoxAllowTeachers (bool AllowTeachers);
|
||||||
static void Tst_GetAnswersFromForm (struct TstExa_Exam *Exam);
|
static void Tst_GetAnswersFromForm (struct TstExa_Exam *Exam);
|
||||||
|
|
||||||
static bool Tst_CheckIfNextTstAllowed (void);
|
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 unsigned Tst_GetNumExamsGeneratedByMe (void);
|
||||||
static void Tst_ShowTestExamToFillIt (struct TstExa_Exam *Exam,
|
static void Tst_ShowTestExamToFillIt (struct TstExa_Exam *Exam,
|
||||||
unsigned NumExamsGeneratedByMe,
|
unsigned NumExamsGeneratedByMe,
|
||||||
|
@ -482,9 +472,6 @@ void Tst_ShowNewTest (void)
|
||||||
/***** Show test exam to be answered *****/
|
/***** Show test exam to be answered *****/
|
||||||
Tst_ShowTestExamToFillIt (&Exam,NumExamsGeneratedByMe,Tst_REQUEST);
|
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 *****/
|
/***** Update date-time of my next allowed access to test *****/
|
||||||
if (Gbl.Usrs.Me.Role.Logged == Rol_STD)
|
if (Gbl.Usrs.Me.Role.Logged == Rol_STD)
|
||||||
Tst_UpdateLastAccTst (Test.NumQsts);
|
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_The_test_X_has_already_been_assessed_previously;
|
||||||
extern const char *Txt_There_was_an_error_in_assessing_the_test_X;
|
|
||||||
unsigned NumTst;
|
unsigned NumTst;
|
||||||
struct TstExa_Exam Exam;
|
struct TstExa_Exam Exam;
|
||||||
|
|
||||||
|
@ -547,12 +533,16 @@ void Tst_RequestAssessTest (void)
|
||||||
/* Get number of this test from form */
|
/* Get number of this test from form */
|
||||||
NumTst = Tst_GetParamNumTst ();
|
NumTst = Tst_GetParamNumTst ();
|
||||||
|
|
||||||
/****** Get test status in database for this session-course-num.test *****/
|
|
||||||
switch (Tst_GetTstStatus (NumTst))
|
|
||||||
{
|
|
||||||
case Tst_STATUS_SHOWN_BUT_NOT_ASSESSED:
|
|
||||||
/***** Get test exam from database *****/
|
/***** Get test exam from database *****/
|
||||||
TstExa_GetExamDataByExaCod (&Exam);
|
TstExa_GetExamDataByExaCod (&Exam);
|
||||||
|
|
||||||
|
/****** Get test status in database for this session-course-num.test *****/
|
||||||
|
if (Exam.Sent)
|
||||||
|
Ale_ShowAlert (Ale_WARNING,Txt_The_test_X_has_already_been_assessed_previously,
|
||||||
|
NumTst);
|
||||||
|
else // Exam not yet sent
|
||||||
|
{
|
||||||
|
/***** Get test exam questions from database *****/
|
||||||
TstExa_GetExamQuestionsFromDB (&Exam);
|
TstExa_GetExamQuestionsFromDB (&Exam);
|
||||||
|
|
||||||
/***** Get answers from form to assess a test *****/
|
/***** Get answers from form to assess a test *****/
|
||||||
|
@ -569,15 +559,6 @@ void Tst_RequestAssessTest (void)
|
||||||
|
|
||||||
/* Show the same test exam to be answered */
|
/* Show the same test exam to be answered */
|
||||||
Tst_ShowTestExamToFillIt (&Exam,NumTst,Tst_CONFIRM);
|
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -593,7 +574,6 @@ void Tst_AssessTest (void)
|
||||||
extern const char *Txt_Score;
|
extern const char *Txt_Score;
|
||||||
extern const char *Txt_Grade;
|
extern const char *Txt_Grade;
|
||||||
extern const char *Txt_The_test_X_has_already_been_assessed_previously;
|
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;
|
unsigned NumTst;
|
||||||
struct TstExa_Exam Exam;
|
struct TstExa_Exam Exam;
|
||||||
|
|
||||||
|
@ -609,18 +589,23 @@ void Tst_AssessTest (void)
|
||||||
/* Get number of this test from form */
|
/* Get number of this test from form */
|
||||||
NumTst = Tst_GetParamNumTst ();
|
NumTst = Tst_GetParamNumTst ();
|
||||||
|
|
||||||
/****** Get test status in database for this session-course-num.test *****/
|
|
||||||
switch (Tst_GetTstStatus (NumTst))
|
|
||||||
{
|
|
||||||
case Tst_STATUS_SHOWN_BUT_NOT_ASSESSED:
|
|
||||||
/***** Get test exam from database *****/
|
/***** Get test exam from database *****/
|
||||||
TstExa_GetExamDataByExaCod (&Exam);
|
TstExa_GetExamDataByExaCod (&Exam);
|
||||||
|
|
||||||
|
/****** Get test status in database for this session-course-num.test *****/
|
||||||
|
if (Exam.Sent)
|
||||||
|
Ale_ShowAlert (Ale_WARNING,Txt_The_test_X_has_already_been_assessed_previously,
|
||||||
|
NumTst);
|
||||||
|
else // Exam not yet sent
|
||||||
|
{
|
||||||
|
/***** Get test exam questions from database *****/
|
||||||
TstExa_GetExamQuestionsFromDB (&Exam);
|
TstExa_GetExamQuestionsFromDB (&Exam);
|
||||||
|
|
||||||
/***** Get answers from form to assess a test *****/
|
/***** Get answers from form to assess a test *****/
|
||||||
Tst_GetAnswersFromForm (&Exam);
|
Tst_GetAnswersFromForm (&Exam);
|
||||||
|
|
||||||
/***** Get if test exam will be visible by teachers *****/
|
/***** 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");
|
Exam.AllowTeachers = Par_GetParToBool ("AllowTchs");
|
||||||
|
|
||||||
/***** Update test exam in database *****/
|
/***** Update test exam in database *****/
|
||||||
|
@ -664,18 +649,6 @@ void Tst_AssessTest (void)
|
||||||
|
|
||||||
/***** End box *****/
|
/***** End box *****/
|
||||||
Box_BoxEnd ();
|
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -764,62 +737,6 @@ static bool Tst_CheckIfNextTstAllowed (void)
|
||||||
return true;
|
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 ******************/
|
/***************** 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)
|
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 *****/
|
/***** Remove test configuration of the course *****/
|
||||||
DB_QueryDELETE ("can not remove configuration of tests of a course",
|
DB_QueryDELETE ("can not remove configuration of tests of a course",
|
||||||
"DELETE FROM tst_config WHERE CrsCod=%ld",
|
"DELETE FROM tst_config WHERE CrsCod=%ld",
|
||||||
|
|
|
@ -155,7 +155,7 @@ struct Tst_Stats
|
||||||
|
|
||||||
void Tst_RequestTest (void);
|
void Tst_RequestTest (void);
|
||||||
void Tst_ShowNewTest (void);
|
void Tst_ShowNewTest (void);
|
||||||
void Tst_RequestAssessTest (void);
|
void Tst_ReceiveTestDraft (void);
|
||||||
void Tst_AssessTest (void);
|
void Tst_AssessTest (void);
|
||||||
|
|
||||||
void Tst_ShowTagList (unsigned NumTags,MYSQL_RES *mysql_res);
|
void Tst_ShowTagList (unsigned NumTags,MYSQL_RES *mysql_res);
|
||||||
|
|
111
swad_test_exam.c
111
swad_test_exam.c
|
@ -56,14 +56,6 @@
|
||||||
/******************************* Private 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;
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/************** External global variables from others modules ****************/
|
/************** External global variables from others modules ****************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@ -78,6 +70,8 @@ extern struct Globals Gbl;
|
||||||
/***************************** Private prototypes ****************************/
|
/***************************** Private prototypes ****************************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static void TstExa_ResetExamExceptExaCod (struct TstExa_Exam *Exam);
|
||||||
|
|
||||||
static void TstExa_WriteQstAndAnsExam (struct UsrData *UsrDat,
|
static void TstExa_WriteQstAndAnsExam (struct UsrData *UsrDat,
|
||||||
struct TstExa_Exam *Exam,
|
struct TstExa_Exam *Exam,
|
||||||
unsigned NumQst,
|
unsigned NumQst,
|
||||||
|
@ -165,11 +159,17 @@ static void TstExa_ShowTagsPresentInAnExam (long ExaCod);
|
||||||
void TstExa_ResetExam (struct TstExa_Exam *Exam)
|
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_START_TIME] =
|
||||||
Exam->TimeUTC[Dat_END_TIME ] = (time_t) 0;
|
Exam->TimeUTC[Dat_END_TIME ] = (time_t) 0;
|
||||||
Exam->NumQsts =
|
Exam->NumQsts =
|
||||||
Exam->NumQstsNotBlank = 0;
|
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;
|
Exam->Score = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,9 +183,11 @@ void TstExa_CreateExamInDB (struct TstExa_Exam *Exam)
|
||||||
Exam->ExaCod =
|
Exam->ExaCod =
|
||||||
DB_QueryINSERTandReturnCode ("can not create new test exam",
|
DB_QueryINSERTandReturnCode ("can not create new test exam",
|
||||||
"INSERT INTO tst_exams"
|
"INSERT INTO tst_exams"
|
||||||
" (CrsCod,UsrCod,StartTime,EndTime,NumQsts,AllowTeachers,Score)"
|
" (CrsCod,UsrCod,StartTime,EndTime,NumQsts,"
|
||||||
|
"Sent,AllowTeachers,Score)"
|
||||||
" VALUES"
|
" VALUES"
|
||||||
" (%ld,%ld,NOW(),NOW(),%u,'N',0)",
|
" (%ld,%ld,NOW(),NOW(),%u,"
|
||||||
|
"'N','N',0)",
|
||||||
Gbl.Hierarchy.Crs.CrsCod,
|
Gbl.Hierarchy.Crs.CrsCod,
|
||||||
Gbl.Usrs.Me.UsrDat.UsrCod,
|
Gbl.Usrs.Me.UsrDat.UsrCod,
|
||||||
Exam->NumQsts);
|
Exam->NumQsts);
|
||||||
|
@ -203,11 +205,14 @@ void TstExa_UpdateExamInDB (const struct TstExa_Exam *Exam)
|
||||||
"UPDATE tst_exams"
|
"UPDATE tst_exams"
|
||||||
" SET EndTime=NOW(),"
|
" SET EndTime=NOW(),"
|
||||||
"NumQstsNotBlank=%u,"
|
"NumQstsNotBlank=%u,"
|
||||||
|
"Sent='%c',"
|
||||||
"AllowTeachers='%c',"
|
"AllowTeachers='%c',"
|
||||||
"Score='%.15lg'"
|
"Score='%.15lg'"
|
||||||
" WHERE ExaCod=%ld"
|
" WHERE ExaCod=%ld"
|
||||||
" AND CrsCod=%ld AND UsrCod=%ld", // Extra checks
|
" AND CrsCod=%ld AND UsrCod=%ld", // Extra checks
|
||||||
Exam->NumQstsNotBlank,
|
Exam->NumQstsNotBlank,
|
||||||
|
Exam->Sent ? 'Y' :
|
||||||
|
'N',
|
||||||
Exam->AllowTeachers ? 'Y' :
|
Exam->AllowTeachers ? 'Y' :
|
||||||
'N',
|
'N',
|
||||||
Exam->Score,
|
Exam->Score,
|
||||||
|
@ -396,7 +401,6 @@ void TstExa_ComputeScoresAndStoreExamQuestions (struct TstExa_Exam *Exam,
|
||||||
if (Exam->Questions[NumQst].AnswerIsNotBlank)
|
if (Exam->Questions[NumQst].AnswerIsNotBlank)
|
||||||
Exam->NumQstsNotBlank++;
|
Exam->NumQstsNotBlank++;
|
||||||
|
|
||||||
|
|
||||||
/* Update the number of hits and the score of this question in tests database */
|
/* Update the number of hits and the score of this question in tests database */
|
||||||
if (UpdateQstScore)
|
if (UpdateQstScore)
|
||||||
Tst_UpdateQstScoreInDB (Exam,NumQst);
|
Tst_UpdateQstScoreInDB (Exam,NumQst);
|
||||||
|
@ -1634,8 +1638,12 @@ static void TstExa_ShowExams (struct UsrData *UsrDat)
|
||||||
double TotalScoreOfAllTests = 0.0;
|
double TotalScoreOfAllTests = 0.0;
|
||||||
unsigned NumExamsVisibleByTchs = 0;
|
unsigned NumExamsVisibleByTchs = 0;
|
||||||
bool ItsMe = Usr_ItsMe (UsrDat->UsrCod);
|
bool ItsMe = Usr_ItsMe (UsrDat->UsrCod);
|
||||||
bool ICanViewTest;
|
struct
|
||||||
bool ICanViewScore;
|
{
|
||||||
|
bool NumQsts;
|
||||||
|
bool Score;
|
||||||
|
bool Exam;
|
||||||
|
} ICanView;
|
||||||
char *ClassDat;
|
char *ClassDat;
|
||||||
|
|
||||||
/***** Make database query *****/
|
/***** Make database query *****/
|
||||||
|
@ -1651,8 +1659,9 @@ static void TstExa_ShowExams (struct UsrData *UsrDat)
|
||||||
"UNIX_TIMESTAMP(EndTime)," // row[2]
|
"UNIX_TIMESTAMP(EndTime)," // row[2]
|
||||||
"NumQsts," // row[3]
|
"NumQsts," // row[3]
|
||||||
"NumQstsNotBlank," // row[4]
|
"NumQstsNotBlank," // row[4]
|
||||||
"AllowTeachers," // row[5]
|
"Sent," // row[5]
|
||||||
"Score" // row[6]
|
"AllowTeachers," // row[6]
|
||||||
|
"Score" // row[7]
|
||||||
" FROM tst_exams"
|
" FROM tst_exams"
|
||||||
" WHERE CrsCod=%ld AND UsrCod=%ld"
|
" WHERE CrsCod=%ld AND UsrCod=%ld"
|
||||||
" AND EndTime>=FROM_UNIXTIME(%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)
|
if ((Exam.ExaCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
|
||||||
Lay_ShowErrorAndExit ("Wrong code of test exam.");
|
Lay_ShowErrorAndExit ("Wrong code of test exam.");
|
||||||
|
|
||||||
/* Get if teachers are allowed to see this test exams (row[5]) */
|
/* Get if exam has been sent (row[5]) */
|
||||||
Exam.AllowTeachers = (row[5][0] == 'Y');
|
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" :
|
ClassDat = Exam.AllowTeachers ? "DAT" :
|
||||||
"DAT_LIGHT";
|
"DAT_LIGHT";
|
||||||
|
|
||||||
switch (Gbl.Usrs.Me.Role.Logged)
|
switch (Gbl.Usrs.Me.Role.Logged)
|
||||||
{
|
{
|
||||||
case Rol_STD:
|
case Rol_STD:
|
||||||
ICanViewTest = ItsMe;
|
ICanView.NumQsts = Exam.Sent && ItsMe;
|
||||||
ICanViewScore = ItsMe &&
|
ICanView.Score = Exam.Sent && ItsMe &&
|
||||||
TstVis_IsVisibleTotalScore (TstCfg_GetConfigVisibility ());
|
TstVis_IsVisibleTotalScore (TstCfg_GetConfigVisibility ());
|
||||||
|
ICanView.Exam = Exam.Sent && ItsMe;
|
||||||
break;
|
break;
|
||||||
case Rol_NET:
|
case Rol_NET:
|
||||||
case Rol_TCH:
|
case Rol_TCH:
|
||||||
case Rol_DEG_ADM:
|
case Rol_DEG_ADM:
|
||||||
case Rol_CTR_ADM:
|
case Rol_CTR_ADM:
|
||||||
case Rol_INS_ADM:
|
case Rol_INS_ADM:
|
||||||
ICanViewTest =
|
ICanView.NumQsts = Exam.Sent; // If the exam has been sent,
|
||||||
ICanViewScore = ItsMe ||
|
// teachers can see the number of questions
|
||||||
Exam.AllowTeachers;
|
ICanView.Score =
|
||||||
|
ICanView.Exam = Exam.Sent && (ItsMe || Exam.AllowTeachers);
|
||||||
break;
|
break;
|
||||||
case Rol_SYS_ADM:
|
case Rol_SYS_ADM:
|
||||||
ICanViewTest =
|
ICanView.NumQsts =
|
||||||
ICanViewScore = true;
|
ICanView.Score =
|
||||||
|
ICanView.Exam = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ICanViewTest =
|
ICanView.NumQsts =
|
||||||
ICanViewScore = false;
|
ICanView.Score =
|
||||||
|
ICanView.Exam = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1746,9 +1762,9 @@ static void TstExa_ShowExams (struct UsrData *UsrDat)
|
||||||
if (Exam.AllowTeachers)
|
if (Exam.AllowTeachers)
|
||||||
NumTotalQstsNotBlank += Exam.NumQstsNotBlank;
|
NumTotalQstsNotBlank += Exam.NumQstsNotBlank;
|
||||||
|
|
||||||
/* Get score (row[6]) */
|
/* Get score (row[7]) */
|
||||||
Str_SetDecimalPointToUS (); // To get the decimal point as a dot
|
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;
|
Exam.Score = 0.0;
|
||||||
Str_SetDecimalPointToLocal (); // Return to local system
|
Str_SetDecimalPointToLocal (); // Return to local system
|
||||||
if (Exam.AllowTeachers)
|
if (Exam.AllowTeachers)
|
||||||
|
@ -1756,25 +1772,25 @@ static void TstExa_ShowExams (struct UsrData *UsrDat)
|
||||||
|
|
||||||
/* Write number of questions */
|
/* Write number of questions */
|
||||||
HTM_TD_Begin ("class=\"%s RT COLOR%u\"",ClassDat,Gbl.RowEvenOdd);
|
HTM_TD_Begin ("class=\"%s RT COLOR%u\"",ClassDat,Gbl.RowEvenOdd);
|
||||||
if (ICanViewTest)
|
if (ICanView.NumQsts)
|
||||||
HTM_Unsigned (Exam.NumQsts);
|
HTM_Unsigned (Exam.NumQsts);
|
||||||
HTM_TD_End ();
|
HTM_TD_End ();
|
||||||
|
|
||||||
/* Write number of questions not blank */
|
/* Write number of questions not blank */
|
||||||
HTM_TD_Begin ("class=\"%s RT COLOR%u\"",ClassDat,Gbl.RowEvenOdd);
|
HTM_TD_Begin ("class=\"%s RT COLOR%u\"",ClassDat,Gbl.RowEvenOdd);
|
||||||
if (ICanViewTest)
|
if (ICanView.NumQsts)
|
||||||
HTM_Unsigned (Exam.NumQstsNotBlank);
|
HTM_Unsigned (Exam.NumQstsNotBlank);
|
||||||
HTM_TD_End ();
|
HTM_TD_End ();
|
||||||
|
|
||||||
/* Write score */
|
/* Write score */
|
||||||
HTM_TD_Begin ("class=\"%s RT COLOR%u\"",ClassDat,Gbl.RowEvenOdd);
|
HTM_TD_Begin ("class=\"%s RT COLOR%u\"",ClassDat,Gbl.RowEvenOdd);
|
||||||
if (ICanViewScore)
|
if (ICanView.Score)
|
||||||
HTM_Double2Decimals (Exam.Score);
|
HTM_Double2Decimals (Exam.Score);
|
||||||
HTM_TD_End ();
|
HTM_TD_End ();
|
||||||
|
|
||||||
/* Write average score per question */
|
/* Write average score per question */
|
||||||
HTM_TD_Begin ("class=\"%s RT COLOR%u\"",ClassDat,Gbl.RowEvenOdd);
|
HTM_TD_Begin ("class=\"%s RT COLOR%u\"",ClassDat,Gbl.RowEvenOdd);
|
||||||
if (ICanViewScore)
|
if (ICanView.Score)
|
||||||
HTM_Double2Decimals (Exam.NumQsts ? Exam.Score /
|
HTM_Double2Decimals (Exam.NumQsts ? Exam.Score /
|
||||||
(double) Exam.NumQsts :
|
(double) Exam.NumQsts :
|
||||||
0.0);
|
0.0);
|
||||||
|
@ -1782,7 +1798,7 @@ static void TstExa_ShowExams (struct UsrData *UsrDat)
|
||||||
|
|
||||||
/* Write grade */
|
/* Write grade */
|
||||||
HTM_TD_Begin ("class=\"%s RT COLOR%u\"",ClassDat,Gbl.RowEvenOdd);
|
HTM_TD_Begin ("class=\"%s RT COLOR%u\"",ClassDat,Gbl.RowEvenOdd);
|
||||||
if (ICanViewScore)
|
if (ICanView.Score)
|
||||||
TstExa_ComputeAndShowGrade (Exam.NumQsts,
|
TstExa_ComputeAndShowGrade (Exam.NumQsts,
|
||||||
Exam.Score,
|
Exam.Score,
|
||||||
TstExa_SCORE_MAX);
|
TstExa_SCORE_MAX);
|
||||||
|
@ -1790,7 +1806,7 @@ static void TstExa_ShowExams (struct UsrData *UsrDat)
|
||||||
|
|
||||||
/* Link to show this test exam */
|
/* Link to show this test exam */
|
||||||
HTM_TD_Begin ("class=\"RT COLOR%u\"",Gbl.RowEvenOdd);
|
HTM_TD_Begin ("class=\"RT COLOR%u\"",Gbl.RowEvenOdd);
|
||||||
if (ICanViewTest)
|
if (ICanView.Exam)
|
||||||
{
|
{
|
||||||
Frm_StartForm (Gbl.Action.Act == ActSeeMyTstRes ? ActSeeOneTstResMe :
|
Frm_StartForm (Gbl.Action.Act == ActSeeMyTstRes ? ActSeeOneTstResMe :
|
||||||
ActSeeOneTstResOth);
|
ActSeeOneTstResOth);
|
||||||
|
@ -2242,8 +2258,9 @@ void TstExa_GetExamDataByExaCod (struct TstExa_Exam *Exam)
|
||||||
"UNIX_TIMESTAMP(EndTime)," // row[2]
|
"UNIX_TIMESTAMP(EndTime)," // row[2]
|
||||||
"NumQsts," // row[3]
|
"NumQsts," // row[3]
|
||||||
"NumQstsNotBlank," // row[4]
|
"NumQstsNotBlank," // row[4]
|
||||||
"AllowTeachers," // row[5]
|
"Sent," // row[5]
|
||||||
"Score" // row[6]
|
"AllowTeachers," // row[6]
|
||||||
|
"Score" // row[7]
|
||||||
" FROM tst_exams"
|
" FROM tst_exams"
|
||||||
" WHERE ExaCod=%ld AND CrsCod=%ld",
|
" WHERE ExaCod=%ld AND CrsCod=%ld",
|
||||||
Exam->ExaCod,
|
Exam->ExaCod,
|
||||||
|
@ -2266,24 +2283,20 @@ void TstExa_GetExamDataByExaCod (struct TstExa_Exam *Exam)
|
||||||
if (sscanf (row[4],"%u",&Exam->NumQstsNotBlank) != 1)
|
if (sscanf (row[4],"%u",&Exam->NumQstsNotBlank) != 1)
|
||||||
Exam->NumQstsNotBlank = 0;
|
Exam->NumQstsNotBlank = 0;
|
||||||
|
|
||||||
/* Get if teachers are allowed to see this test exam (row[5]) */
|
/* Get if exam has been sent (row[5]) */
|
||||||
Exam->AllowTeachers = (row[5][0] == 'Y');
|
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
|
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;
|
Exam->Score = 0.0;
|
||||||
Str_SetDecimalPointToLocal (); // Return to local system
|
Str_SetDecimalPointToLocal (); // Return to local system
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
TstExa_ResetExamExceptExaCod (Exam);
|
||||||
Exam->TimeUTC[Dat_START_TIME] =
|
|
||||||
Exam->TimeUTC[Dat_END_TIME ] = 0;
|
|
||||||
Exam->NumQsts = 0;
|
|
||||||
Exam->NumQstsNotBlank = 0;
|
|
||||||
Exam->AllowTeachers = false;
|
|
||||||
Exam->Score = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***** Free structure that stores the query result *****/
|
/***** Free structure that stores the query result *****/
|
||||||
DB_FreeMySQLResult (&mysql_res);
|
DB_FreeMySQLResult (&mysql_res);
|
||||||
|
|
|
@ -51,6 +51,8 @@ struct TstExa_Exam
|
||||||
time_t TimeUTC[Dat_NUM_START_END_TIME];
|
time_t TimeUTC[Dat_NUM_START_END_TIME];
|
||||||
unsigned NumQsts; // Number of questions
|
unsigned NumQsts; // Number of questions
|
||||||
unsigned NumQstsNotBlank; // Number of questions not blank
|
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?
|
bool AllowTeachers; // Are teachers allowed to see this test exam?
|
||||||
double Score; // Total score of the test exam
|
double Score; // Total score of the test exam
|
||||||
struct
|
struct
|
||||||
|
|
63
swad_text.c
63
swad_text.c
|
@ -38201,6 +38201,27 @@ const char *Txt_ROOMS_HELP_ORDER[Roo_NUM_ORDERS] =
|
||||||
"Sortuj według piętrze"
|
"Sortuj według piętrze"
|
||||||
#elif L==9 // pt
|
#elif L==9 // pt
|
||||||
"Classificar por andar"
|
"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ług typ"
|
||||||
|
#elif L==9 // pt
|
||||||
|
"Classificar por tipo"
|
||||||
#endif
|
#endif
|
||||||
,
|
,
|
||||||
[Roo_ORDER_BY_SHRT_NAME] =
|
[Roo_ORDER_BY_SHRT_NAME] =
|
||||||
|
@ -38309,6 +38330,27 @@ const char *Txt_ROOMS_ORDER[Roo_NUM_ORDERS] =
|
||||||
"Piętrze"
|
"Piętrze"
|
||||||
#elif L==9 // pt
|
#elif L==9 // pt
|
||||||
"Andar"
|
"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
|
#endif
|
||||||
,
|
,
|
||||||
[Roo_ORDER_BY_SHRT_NAME] =
|
[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.";
|
"Ocorreu um problema ao enviar um email automaticamente.";
|
||||||
#endif
|
#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'è 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 =
|
const char *Txt_This_game_has_no_questions =
|
||||||
#if L==1 // ca
|
#if L==1 // ca
|
||||||
"Aquest joc no té preguntes.";
|
"Aquest joc no té preguntes.";
|
||||||
|
|
Loading…
Reference in New Issue
Block a user