Version19.241.1

This commit is contained in:
acanas 2020-05-23 13:24:08 +02:00
parent c100ca9af4
commit 0a90198755
8 changed files with 131 additions and 78 deletions

View File

@ -490,6 +490,8 @@ CREATE TABLE IF NOT EXISTS exa_log (
LogCod INT NOT NULL, LogCod INT NOT NULL,
PrnCod INT NOT NULL, PrnCod INT NOT NULL,
ActCod INT NOT NULL, ActCod INT NOT NULL,
QstInd INT NOT NULL DEFAULT -1,
Saved ENUM('N','Y') NOT NULL DEFAULT 'N',
ClickTime DATETIME NOT NULL, ClickTime DATETIME NOT NULL,
IP CHAR(15) NOT NULL, IP CHAR(15) NOT NULL,
SessionId CHAR(43) NOT NULL, SessionId CHAR(43) NOT NULL,

View File

@ -557,10 +557,17 @@ 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.241 (2020-05-22)" #define Log_PLATFORM_VERSION "SWAD 19.241.1 (2020-05-22)"
#define CSS_FILE "swad19.238.2.css" #define CSS_FILE "swad19.238.2.css"
#define JS_FILE "swad19.239.6.js" #define JS_FILE "swad19.239.6.js"
/* /*
Version 19.241.1: May 23, 2020 Question index added to exam log. (301756 lines)
2 changes necessary in database:
ALTER TABLE exa_log ADD COLUMN QstInd INT NOT NULL DEFAULT -1 AFTER ActCod;
ALTER TABLE exa_log ADD COLUMN Saved ENUM('N','Y') NOT NULL DEFAULT 'N' AFTER QstInd;
If you want to use MyISAM:
ALTER TABLE exa_log ENGINE=MyISAM;
Version 19.241: May 22, 2020 Log in exams. Version 19.241: May 22, 2020 Log in exams.
Bug fixing and code refactoring in tests and exams. (301712 lines) Bug fixing and code refactoring in tests and exams. (301712 lines)
1 change necessary in database: 1 change necessary in database:

View File

@ -1047,23 +1047,27 @@ mysql> DESCRIBE exa_exams;
/***** Table exa_log *****/ /***** Table exa_log *****/
/* /*
mysql> DESCRIBE exa_log; mysql> DESCRIBE exa_log;
+-----------+----------+------+-----+---------+-------+ +-----------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra | | Field | Type | Null | Key | Default | Extra |
+-----------+----------+------+-----+---------+-------+ +-----------+---------------+------+-----+---------+-------+
| LogCod | int(11) | NO | PRI | NULL | | | LogCod | int(11) | NO | PRI | NULL | |
| PrnCod | int(11) | NO | MUL | NULL | | | PrnCod | int(11) | NO | MUL | NULL | |
| ActCod | int(11) | NO | | NULL | | | ActCod | int(11) | NO | | NULL | |
| ClickTime | datetime | NO | MUL | NULL | | | QstInd | int(11) | NO | | -1 | |
| IP | char(15) | NO | | NULL | | | Saved | enum('N','Y') | NO | | N | |
| SessionId | char(43) | NO | | NULL | | | ClickTime | datetime | NO | MUL | NULL | |
+-----------+----------+------+-----+---------+-------+ | IP | char(15) | NO | | NULL | |
6 rows in set (0.00 sec) | SessionId | char(43) | NO | | NULL | |
+-----------+---------------+------+-----+---------+-------+
8 rows in set (0.00 sec)
*/ */
// TODO: Change NtfCod and LogCod from INT to BIGINT in database tables. // TODO: Change NtfCod and LogCod from INT to BIGINT in database tables.
DB_CreateTable ("CREATE TABLE IF NOT EXISTS exa_log (" DB_CreateTable ("CREATE TABLE IF NOT EXISTS exa_log ("
"LogCod INT NOT NULL," "LogCod INT NOT NULL,"
"PrnCod INT NOT NULL," "PrnCod INT NOT NULL,"
"ActCod INT NOT NULL," "ActCod INT NOT NULL,"
"QstInd INT NOT NULL DEFAULT -1,"
"Saved ENUM('N','Y') NOT NULL DEFAULT 'N',"
"ClickTime DATETIME NOT NULL," "ClickTime DATETIME NOT NULL,"
"IP CHAR(15) NOT NULL," // Cns_MAX_BYTES_IP "IP CHAR(15) NOT NULL," // Cns_MAX_BYTES_IP
"SessionId CHAR(43) NOT NULL," // Cns_BYTES_SESSION_ID "SessionId CHAR(43) NOT NULL," // Cns_BYTES_SESSION_ID

View File

@ -25,23 +25,8 @@
/********************************* Headers ***********************************/ /********************************* Headers ***********************************/
/*****************************************************************************/ /*****************************************************************************/
// #define _GNU_SOURCE // For asprintf
// #include <linux/limits.h> // For PATH_MAX
// #include <stddef.h> // For NULL
// #include <stdio.h> // For asprintf
// #include <stdlib.h> // For calloc
// #include <string.h> // For string functions
#include "swad_action.h" #include "swad_action.h"
// #include "swad_box.h"
#include "swad_database.h" #include "swad_database.h"
// #include "swad_exam.h"
#include "swad_exam_print.h"
// #include "swad_exam_result.h"
// #include "swad_exam_session.h"
// #include "swad_exam_set.h"
// #include "swad_exam_type.h"
// #include "swad_form.h"
#include "swad_global.h" #include "swad_global.h"
/*****************************************************************************/ /*****************************************************************************/
@ -62,10 +47,64 @@ extern struct Globals Gbl;
/***************************** Private variables *****************************/ /***************************** Private variables *****************************/
/*****************************************************************************/ /*****************************************************************************/
static struct
{
long PrnCod;
int QstInd;
bool AnswerIsSaved;
} ExaLog_CurrentPrint =
{
.PrnCod = -1L, // -1 means no print code set
.QstInd = -1, // -1 means no question index set
.AnswerIsSaved = false, // By default, answer is not saved
};
/*****************************************************************************/ /*****************************************************************************/
/***************************** Private prototypes ****************************/ /***************************** Private prototypes ****************************/
/*****************************************************************************/ /*****************************************************************************/
/*****************************************************************************/
/************* Set and get current exam print code (used in log) *************/
/*****************************************************************************/
void ExaLog_SetCurrentPrnCod (long PrnCod)
{
ExaLog_CurrentPrint.PrnCod = PrnCod;
}
long ExaLog_GetCurrentPrnCod (void)
{
return ExaLog_CurrentPrint.PrnCod;
}
/*****************************************************************************/
/****** Set and get current question index in exam print (used in log) *******/
/*****************************************************************************/
void ExaLog_SetCurrentQstInd (unsigned QstInd)
{
ExaLog_CurrentPrint.QstInd = (int) QstInd;
}
int ExaLog_GetCurrentQstInd (void)
{
return ExaLog_CurrentPrint.QstInd;
}
/*****************************************************************************/
/******** Set and get if answer is saved in exam print (used in log) *********/
/*****************************************************************************/
void ExaLog_SetAnswerIsSaved (void)
{
ExaLog_CurrentPrint.AnswerIsSaved = true;
}
bool ExaLog_GetAnswerIsSaved (void)
{
return ExaLog_CurrentPrint.AnswerIsSaved;
}
/*****************************************************************************/ /*****************************************************************************/
/**************************** Log access in database *************************/ /**************************** Log access in database *************************/
/*****************************************************************************/ /*****************************************************************************/
@ -74,11 +113,13 @@ void ExaLog_LogAccess (long LogCod)
{ {
long PrnCod; long PrnCod;
/* WARNING: Don't change the codes os the actions.
If the codes of the actions change ==> change them in exam log table */
if (Gbl.Action.Act == ActAnsExaPrn || // Answer question if (Gbl.Action.Act == ActAnsExaPrn || // Answer question
Gbl.Action.Act == ActSeeExaPrn || // Create/resume print exam Gbl.Action.Act == ActSeeExaPrn || // Create/resume print exam
Gbl.Action.Act == ActEndExaPrn) // End print exam Gbl.Action.Act == ActEndExaPrn) // End print exam
{ {
PrnCod = ExaPrn_GetCurrentPrnCod (); PrnCod = ExaLog_GetCurrentPrnCod ();
if (PrnCod > 0) // Only if exam print is accesible (visible, open...) if (PrnCod > 0) // Only if exam print is accesible (visible, open...)
/***** Insert access into database *****/ /***** Insert access into database *****/
@ -86,12 +127,15 @@ void ExaLog_LogAccess (long LogCod)
Redundant data (also present in log table) are stored for speed */ Redundant data (also present in log table) are stored for speed */
DB_QueryINSERT ("can not log exam access", DB_QueryINSERT ("can not log exam access",
"INSERT INTO exa_log " "INSERT INTO exa_log "
"(LogCod,PrnCod,ActCod,ClickTime,IP,SessionId)" "(LogCod,PrnCod,ActCod,QstInd,Saved,ClickTime,IP,SessionId)"
" VALUES " " VALUES "
"(%ld,%ld,%ld,NOW(),'%s','%s')", "(%ld,%ld,%ld,%d,'%c',NOW(),'%s','%s')",
LogCod, LogCod,
PrnCod, PrnCod,
Act_GetActCod (Gbl.Action.Act), // Redundant, for speed Act_GetActCod (Gbl.Action.Act), // Redundant, for speed
ExaLog_GetCurrentQstInd (),
ExaLog_GetAnswerIsSaved () ? 'Y' :
'N',
// NOW() Redundant, for speed // NOW() Redundant, for speed
Gbl.IP, // Redundant, for speed Gbl.IP, // Redundant, for speed
Gbl.Session.Id); Gbl.Session.Id);

View File

@ -27,16 +27,21 @@
/********************************** Headers **********************************/ /********************************** Headers **********************************/
/*****************************************************************************/ /*****************************************************************************/
/*****************************************************************************/ /*****************************************************************************/
/************************* Public types and constants ************************/ /************************* Public types and constants ************************/
/*****************************************************************************/ /*****************************************************************************/
/*****************************************************************************/ /*****************************************************************************/
/***************************** Public prototypes *****************************/ /***************************** Public prototypes *****************************/
/*****************************************************************************/ /*****************************************************************************/
void ExaLog_SetCurrentPrnCod (long PrnCod);
long ExaLog_GetCurrentPrnCod (void);
void ExaLog_SetCurrentQstInd (unsigned QstInd);
int ExaLog_GetCurrentQstInd (void);
void ExaLog_SetAnswerIsSaved (void);
bool ExaLog_GetAnswerIsSaved (void);
void ExaLog_LogAccess (long LogCod); void ExaLog_LogAccess (long LogCod);
#endif #endif

View File

@ -35,6 +35,7 @@
#include "swad_box.h" #include "swad_box.h"
#include "swad_database.h" #include "swad_database.h"
#include "swad_exam.h" #include "swad_exam.h"
#include "swad_exam_log.h"
#include "swad_exam_print.h" #include "swad_exam_print.h"
#include "swad_exam_result.h" #include "swad_exam_result.h"
#include "swad_exam_session.h" #include "swad_exam_session.h"
@ -61,8 +62,6 @@ extern struct Globals Gbl;
/***************************** Private variables *****************************/ /***************************** Private variables *****************************/
/*****************************************************************************/ /*****************************************************************************/
static long ExaPrn_CurrentPrnCod = -1L;
/*****************************************************************************/ /*****************************************************************************/
/***************************** Private prototypes ****************************/ /***************************** Private prototypes ****************************/
/*****************************************************************************/ /*****************************************************************************/
@ -88,7 +87,9 @@ static void ExaPrn_WriteQstAndAnsToFill (const struct ExaPrn_Print *Print,
static void ExaPrn_WriteAnswersToFill (const struct ExaPrn_Print *Print, static void ExaPrn_WriteAnswersToFill (const struct ExaPrn_Print *Print,
unsigned NumQst, unsigned NumQst,
const struct Tst_Question *Question); const struct Tst_Question *Question);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static void ExaPrn_WriteIntAnsToFill (const struct ExaPrn_Print *Print, static void ExaPrn_WriteIntAnsToFill (const struct ExaPrn_Print *Print,
unsigned NumQst); unsigned NumQst);
static void ExaPrn_WriteFloAnsToFill (const struct ExaPrn_Print *Print, static void ExaPrn_WriteFloAnsToFill (const struct ExaPrn_Print *Print,
@ -100,12 +101,14 @@ static void ExaPrn_WriteChoAnsToFill (const struct ExaPrn_Print *Print,
const struct Tst_Question *Question); const struct Tst_Question *Question);
static void ExaPrn_WriteTxtAnsToFill (const struct ExaPrn_Print *Print, static void ExaPrn_WriteTxtAnsToFill (const struct ExaPrn_Print *Print,
unsigned NumQst); unsigned NumQst);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static void ExaPrn_WriteJSToUpdateExamPrint (const struct ExaPrn_Print *Print, static void ExaPrn_WriteJSToUpdateExamPrint (const struct ExaPrn_Print *Print,
unsigned NumQst, unsigned NumQst,
const char *Id,int NumOpt); const char *Id,int NumOpt);
static unsigned ExaPrn_GetAnswerFromForm (struct ExaPrn_Print *Print); static void ExaPrn_GetAnswerFromForm (struct ExaPrn_Print *Print,unsigned QstInd);
static unsigned ExaPrn_GetParamQstInd (void); static unsigned ExaPrn_GetParamQstInd (void);
@ -125,6 +128,8 @@ static void ExaPrn_GetCorrectAndComputeChoAnsScore (struct TstPrn_PrintedQuestio
static void ExaPrn_GetCorrectAndComputeTxtAnsScore (struct TstPrn_PrintedQuestion *PrintedQuestion, static void ExaPrn_GetCorrectAndComputeTxtAnsScore (struct TstPrn_PrintedQuestion *PrintedQuestion,
struct Tst_Question *Question); struct Tst_Question *Question);
//-----------------------------------------------------------------------------
static void ExaPrn_GetCorrectIntAnswerFromDB (struct Tst_Question *Question); static void ExaPrn_GetCorrectIntAnswerFromDB (struct Tst_Question *Question);
static void ExaPrn_GetCorrectFltAnswerFromDB (struct Tst_Question *Question); static void ExaPrn_GetCorrectFltAnswerFromDB (struct Tst_Question *Question);
static void ExaPrn_GetCorrectTF_AnswerFromDB (struct Tst_Question *Question); static void ExaPrn_GetCorrectTF_AnswerFromDB (struct Tst_Question *Question);
@ -142,20 +147,6 @@ static void ExaPrn_GetNumQstsNotBlank (struct ExaPrn_Print *Print);
static void ExaPrn_ComputeTotalScoreOfPrint (struct ExaPrn_Print *Print); static void ExaPrn_ComputeTotalScoreOfPrint (struct ExaPrn_Print *Print);
static void ExaPrn_UpdatePrintInDB (const struct ExaPrn_Print *Print); static void ExaPrn_UpdatePrintInDB (const struct ExaPrn_Print *Print);
/*****************************************************************************/
/************* Set and get current exam print code (used in log) *************/
/*****************************************************************************/
void ExaPrn_SetCurrentPrnCod (long PrnCod)
{
ExaPrn_CurrentPrnCod = PrnCod;
}
long ExaPrn_GetCurrentPrnCod (void)
{
return ExaPrn_CurrentPrnCod;
}
/*****************************************************************************/ /*****************************************************************************/
/**************************** Reset exam print *******************************/ /**************************** Reset exam print *******************************/
/*****************************************************************************/ /*****************************************************************************/
@ -221,7 +212,7 @@ void ExaPrn_ShowExamPrint (void)
} }
/***** Set current print code (to be used in log) *****/ /***** Set current print code (to be used in log) *****/
ExaPrn_SetCurrentPrnCod (Print.PrnCod); ExaLog_SetCurrentPrnCod (Print.PrnCod);
/***** Show test exam to be answered *****/ /***** Show test exam to be answered *****/
ExaPrn_ShowExamPrintToFillIt (&Exams,&Exam,&Print); ExaPrn_ShowExamPrintToFillIt (&Exams,&Exam,&Print);
@ -978,7 +969,7 @@ void ExaPrn_ReceivePrintAnswer (void)
{ {
extern const char *Txt_You_dont_have_access_to_the_exam; extern const char *Txt_You_dont_have_access_to_the_exam;
struct ExaPrn_Print Print; struct ExaPrn_Print Print;
unsigned NumQst; unsigned QstInd;
/***** Reset print *****/ /***** Reset print *****/
ExaPrn_ResetPrint (&Print); ExaPrn_ResetPrint (&Print);
@ -986,33 +977,42 @@ void ExaPrn_ReceivePrintAnswer (void)
/***** Get session code *****/ /***** Get session code *****/
Print.SesCod = ExaSes_GetParamSesCod (); Print.SesCod = ExaSes_GetParamSesCod ();
/***** Get print data *****/
Print.UsrCod = Gbl.Usrs.Me.UsrDat.UsrCod;
ExaPrn_GetPrintDataBySesCodAndUsrCod (&Print);
if (Print.PrnCod <= 0)
Lay_WrongExamExit ();
/***** Set current print code (to be used in log) *****/
ExaLog_SetCurrentPrnCod (Print.PrnCod);
/***** Get questions and current user's answers of exam print from database *****/
ExaPrn_GetPrintQuestionsFromDB (&Print);
/***** Get question index from form *****/
QstInd = ExaPrn_GetParamQstInd ();
/***** Set current question index (to be used in log) *****/
ExaLog_SetCurrentQstInd (QstInd);
/***** Check if session if visible and open *****/ /***** Check if session if visible and open *****/
if (ExaSes_CheckIfSessionIsVisibleAndOpen (Print.SesCod)) if (ExaSes_CheckIfSessionIsVisibleAndOpen (Print.SesCod))
{ {
/***** Get print data *****/
Print.UsrCod = Gbl.Usrs.Me.UsrDat.UsrCod;
ExaPrn_GetPrintDataBySesCodAndUsrCod (&Print);
if (Print.PrnCod <= 0)
Lay_WrongExamExit ();
/***** Set current print code (to be used in log) *****/
ExaPrn_SetCurrentPrnCod (Print.PrnCod);
/***** Get questions and user's answers of exam print from database *****/
ExaPrn_GetPrintQuestionsFromDB (&Print);
/***** Get answers from form to assess a test *****/ /***** Get answers from form to assess a test *****/
NumQst = ExaPrn_GetAnswerFromForm (&Print); ExaPrn_GetAnswerFromForm (&Print,QstInd);
/***** Update answer in database *****/ /***** Update answer in database *****/
/* Compute question score and store in database */ /* Compute question score and store in database */
ExaPrn_ComputeScoreAndStoreQuestionOfPrint (&Print,NumQst); ExaPrn_ComputeScoreAndStoreQuestionOfPrint (&Print,QstInd);
/* Update exam print in database */ /* Update exam print in database */
ExaPrn_GetNumQstsNotBlank (&Print); ExaPrn_GetNumQstsNotBlank (&Print);
ExaPrn_ComputeTotalScoreOfPrint (&Print); ExaPrn_ComputeTotalScoreOfPrint (&Print);
ExaPrn_UpdatePrintInDB (&Print); ExaPrn_UpdatePrintInDB (&Print);
/***** Set success saving answer (to be used in log) *****/
ExaLog_SetAnswerIsSaved ();
/***** Show table with questions to answer *****/ /***** Show table with questions to answer *****/
ExaPrn_ShowTableWithQstsToFill (&Print); ExaPrn_ShowTableWithQstsToFill (&Print);
} }
@ -1024,18 +1024,11 @@ void ExaPrn_ReceivePrintAnswer (void)
/******** Get questions and answers from form to assess an exam print ********/ /******** Get questions and answers from form to assess an exam print ********/
/*****************************************************************************/ /*****************************************************************************/
static unsigned ExaPrn_GetAnswerFromForm (struct ExaPrn_Print *Print) static void ExaPrn_GetAnswerFromForm (struct ExaPrn_Print *Print,unsigned QstInd)
{ {
unsigned NumQst;
/***** Get question index from form *****/
NumQst = ExaPrn_GetParamQstInd ();
/***** Get answers selected by user for this question *****/ /***** Get answers selected by user for this question *****/
Par_GetParToText ("Ans",Print->PrintedQuestions[NumQst].StrAnswers, Par_GetParToText ("Ans",Print->PrintedQuestions[QstInd].StrAnswers,
Tst_MAX_BYTES_ANSWERS_ONE_QST); /* If answer type == T/F ==> " ", "T", "F"; if choice ==> "0", "2",... */ Tst_MAX_BYTES_ANSWERS_ONE_QST); /* If answer type == T/F ==> " ", "T", "F"; if choice ==> "0", "2",... */
return NumQst;
} }
/*****************************************************************************/ /*****************************************************************************/

View File

@ -53,9 +53,6 @@ struct ExaPrn_Print
/***************************** Public prototypes *****************************/ /***************************** Public prototypes *****************************/
/*****************************************************************************/ /*****************************************************************************/
void ExaPrn_SetCurrentPrnCod (long PrnCod);
long ExaPrn_GetCurrentPrnCod (void);
void ExaPrn_ResetPrint (struct ExaPrn_Print *Print); void ExaPrn_ResetPrint (struct ExaPrn_Print *Print);
void ExaPrn_ShowExamPrint (void); void ExaPrn_ShowExamPrint (void);

View File

@ -36,6 +36,7 @@
#include "swad_database.h" #include "swad_database.h"
#include "swad_date.h" #include "swad_date.h"
#include "swad_exam.h" #include "swad_exam.h"
#include "swad_exam_log.h"
#include "swad_exam_print.h" #include "swad_exam_print.h"
#include "swad_exam_result.h" #include "swad_exam_result.h"
#include "swad_exam_session.h" #include "swad_exam_session.h"
@ -1132,7 +1133,7 @@ void ExaRes_ShowOneExaResult (void)
ExaPrn_GetPrintDataBySesCodAndUsrCod (&Print); ExaPrn_GetPrintDataBySesCodAndUsrCod (&Print);
/***** Set current print code (to be used in log) *****/ /***** Set current print code (to be used in log) *****/
ExaPrn_SetCurrentPrnCod (Print.PrnCod); ExaLog_SetCurrentPrnCod (Print.PrnCod);
/***** Check if I can view this print result *****/ /***** Check if I can view this print result *****/
switch (Gbl.Usrs.Me.Role.Logged) switch (Gbl.Usrs.Me.Role.Logged)