mirror of
https://github.com/acanas/swad-core.git
synced 2024-09-20 00:02:42 +02:00
Version19.241
This commit is contained in:
parent
86efca6412
commit
c100ca9af4
2
Makefile
2
Makefile
|
@ -35,7 +35,7 @@ OBJS = swad_account.o swad_action.o swad_agenda.o swad_alert.o \
|
|||
swad_course_config.o swad_cryptography.o \
|
||||
swad_database.o swad_date.o swad_degree.o swad_degree_config.o \
|
||||
swad_degree_type.o swad_department.o swad_duplicate.o \
|
||||
swad_enrolment.o swad_exam.o swad_exam_announcement.o \
|
||||
swad_enrolment.o swad_exam.o swad_exam_announcement.o swad_exam_log.o \
|
||||
swad_exam_print.o swad_exam_result.o swad_exam_session.o \
|
||||
swad_exam_set.o \
|
||||
swad_figure.o swad_figure_cache.o swad_file.o swad_file_browser.o \
|
||||
|
|
|
@ -13364,3 +13364,14 @@ SELECT institutions.InsCod,institutions.ShortName,institutions.FullName,centres.
|
|||
|
||||
|
||||
-------------------------------
|
||||
|
||||
SELECT * FROM
|
||||
(SELECT PrnCod,Score AS S FROM exa_prints ORDER BY PrnCod) AS ep
|
||||
LEFT JOIN
|
||||
(SELECT PrnCod,SUM(Score) AS S FROM exa_print_questions GROUP BY PrnCod ORDER BY PrnCod) AS epq
|
||||
ON ep.PrnCod=epq.PrnCod
|
||||
WHERE ABS(ep.S-epq.S)<0.001;
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
13
sql/swad.sql
13
sql/swad.sql
|
@ -484,6 +484,19 @@ CREATE TABLE IF NOT EXISTS exa_exams (
|
|||
UNIQUE INDEX(ExaCod),
|
||||
INDEX(CrsCod));
|
||||
--
|
||||
-- Table exa_log: stores the access log to exam prints
|
||||
--
|
||||
CREATE TABLE IF NOT EXISTS exa_log (
|
||||
LogCod INT NOT NULL,
|
||||
PrnCod INT NOT NULL,
|
||||
ActCod INT NOT NULL,
|
||||
ClickTime DATETIME NOT NULL,
|
||||
IP CHAR(15) NOT NULL,
|
||||
SessionId CHAR(43) NOT NULL,
|
||||
UNIQUE INDEX(LogCod),
|
||||
INDEX(PrnCod,ClickTime),
|
||||
INDEX(ClickTime));
|
||||
--
|
||||
-- Table exa_print_questions: stores the questions and answers in exam prints made by users
|
||||
--
|
||||
CREATE TABLE IF NOT EXISTS exa_print_questions (
|
||||
|
|
|
@ -727,11 +727,12 @@ const struct Act_Actions Act_Actions[Act_NUM_ACTIONS] =
|
|||
|
||||
[ActSeeExaPrn ] = {1904,-1,TabUnk,ActSeeAllExa ,0x238,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,ExaPrn_ShowExamPrint ,NULL},
|
||||
[ActAnsExaPrn ] = {1906,-1,TabUnk,ActSeeAllExa ,0x238,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_AJAX_NORMAL,NULL ,ExaPrn_ReceivePrintAnswer ,NULL},
|
||||
[ActEndExaPrn ] = {1908,-1,TabUnk,ActSeeAllExa ,0x238,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,ExaRes_ShowOneExaResult ,NULL},
|
||||
|
||||
[ActSeeMyExaResCrs ] = {1867,-1,TabUnk,ActSeeAllExa ,0x208,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,ExaRes_ShowMyResultsInCrs ,NULL},
|
||||
[ActSeeMyExaResExa ] = {1868,-1,TabUnk,ActSeeAllExa ,0x208,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,ExaRes_ShowMyResultsInExa ,NULL},
|
||||
[ActSeeMyExaResSes ] = {1869,-1,TabUnk,ActSeeAllExa ,0x208,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,ExaRes_ShowMyResultsInSes ,NULL},
|
||||
[ActSeeOneExaResMe ] = {1870,-1,TabUnk,ActSeeAllExa ,0x238,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,ExaRes_ShowOneExaResult ,NULL},
|
||||
[ActSeeOneExaResMe ] = {1870,-1,TabUnk,ActSeeAllExa ,0x208,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,ExaRes_ShowOneExaResult ,NULL},
|
||||
|
||||
[ActReqSeeUsrExaRes ] = {1871,-1,TabUnk,ActSeeAllExa ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,ExaRes_SelUsrsToViewResults ,NULL},
|
||||
[ActSeeUsrExaResCrs ] = {1872,-1,TabUnk,ActSeeAllExa ,0x230,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,ExaRes_ShowAllResultsInCrs ,NULL},
|
||||
|
@ -3716,6 +3717,7 @@ Act_Action_t Act_FromActCodToAction[1 + Act_MAX_ACTION_COD] = // Do not reuse un
|
|||
-1, // #1905 (obsolete action)
|
||||
ActAnsExaPrn, // #1906
|
||||
ActEdiTag, // #1907
|
||||
ActEndExaPrn, // #1908
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
141
swad_action.h
141
swad_action.h
|
@ -64,7 +64,7 @@ typedef enum
|
|||
|
||||
typedef signed int Act_Action_t; // Must be a signed type, because -1 is used to indicate obsolete action
|
||||
|
||||
#define Act_MAX_ACTION_COD 1907
|
||||
#define Act_MAX_ACTION_COD 1908
|
||||
|
||||
#define Act_MAX_OPTIONS_IN_MENU_PER_TAB 13
|
||||
|
||||
|
@ -692,83 +692,84 @@ typedef signed int Act_Action_t; // Must be a signed type, because -1 is used to
|
|||
|
||||
#define ActSeeExaPrn (ActChgCrsTT1stDay + 163)
|
||||
#define ActAnsExaPrn (ActChgCrsTT1stDay + 164)
|
||||
#define ActEndExaPrn (ActChgCrsTT1stDay + 165)
|
||||
|
||||
#define ActSeeMyExaResCrs (ActChgCrsTT1stDay + 165)
|
||||
#define ActSeeMyExaResExa (ActChgCrsTT1stDay + 166)
|
||||
#define ActSeeMyExaResSes (ActChgCrsTT1stDay + 167)
|
||||
#define ActSeeOneExaResMe (ActChgCrsTT1stDay + 168)
|
||||
#define ActReqSeeUsrExaRes (ActChgCrsTT1stDay + 169)
|
||||
#define ActSeeUsrExaResCrs (ActChgCrsTT1stDay + 170)
|
||||
#define ActSeeUsrExaResExa (ActChgCrsTT1stDay + 171)
|
||||
#define ActSeeUsrExaResSes (ActChgCrsTT1stDay + 172)
|
||||
#define ActSeeOneExaResOth (ActChgCrsTT1stDay + 173)
|
||||
#define ActChgVisExaRes (ActChgCrsTT1stDay + 174)
|
||||
#define ActSeeMyExaResCrs (ActChgCrsTT1stDay + 166)
|
||||
#define ActSeeMyExaResExa (ActChgCrsTT1stDay + 167)
|
||||
#define ActSeeMyExaResSes (ActChgCrsTT1stDay + 168)
|
||||
#define ActSeeOneExaResMe (ActChgCrsTT1stDay + 169)
|
||||
#define ActReqSeeUsrExaRes (ActChgCrsTT1stDay + 170)
|
||||
#define ActSeeUsrExaResCrs (ActChgCrsTT1stDay + 171)
|
||||
#define ActSeeUsrExaResExa (ActChgCrsTT1stDay + 172)
|
||||
#define ActSeeUsrExaResSes (ActChgCrsTT1stDay + 173)
|
||||
#define ActSeeOneExaResOth (ActChgCrsTT1stDay + 174)
|
||||
#define ActChgVisExaRes (ActChgCrsTT1stDay + 175)
|
||||
|
||||
#define ActSeeGam (ActChgCrsTT1stDay + 175)
|
||||
#define ActReqRemMch (ActChgCrsTT1stDay + 176)
|
||||
#define ActRemMch (ActChgCrsTT1stDay + 177)
|
||||
#define ActReqNewMch (ActChgCrsTT1stDay + 178)
|
||||
#define ActNewMch (ActChgCrsTT1stDay + 179)
|
||||
#define ActResMch (ActChgCrsTT1stDay + 180)
|
||||
#define ActBckMch (ActChgCrsTT1stDay + 181)
|
||||
#define ActPlyPauMch (ActChgCrsTT1stDay + 182)
|
||||
#define ActFwdMch (ActChgCrsTT1stDay + 183)
|
||||
#define ActChgNumColMch (ActChgCrsTT1stDay + 184)
|
||||
#define ActChgVisResMchQst (ActChgCrsTT1stDay + 185)
|
||||
#define ActMchCntDwn (ActChgCrsTT1stDay + 186)
|
||||
#define ActRefMchTch (ActChgCrsTT1stDay + 187)
|
||||
#define ActSeeGam (ActChgCrsTT1stDay + 176)
|
||||
#define ActReqRemMch (ActChgCrsTT1stDay + 177)
|
||||
#define ActRemMch (ActChgCrsTT1stDay + 178)
|
||||
#define ActReqNewMch (ActChgCrsTT1stDay + 179)
|
||||
#define ActNewMch (ActChgCrsTT1stDay + 180)
|
||||
#define ActResMch (ActChgCrsTT1stDay + 181)
|
||||
#define ActBckMch (ActChgCrsTT1stDay + 182)
|
||||
#define ActPlyPauMch (ActChgCrsTT1stDay + 183)
|
||||
#define ActFwdMch (ActChgCrsTT1stDay + 184)
|
||||
#define ActChgNumColMch (ActChgCrsTT1stDay + 185)
|
||||
#define ActChgVisResMchQst (ActChgCrsTT1stDay + 186)
|
||||
#define ActMchCntDwn (ActChgCrsTT1stDay + 187)
|
||||
#define ActRefMchTch (ActChgCrsTT1stDay + 188)
|
||||
|
||||
#define ActJoiMch (ActChgCrsTT1stDay + 188)
|
||||
#define ActSeeMchAnsQstStd (ActChgCrsTT1stDay + 189)
|
||||
#define ActRemMchAnsQstStd (ActChgCrsTT1stDay + 190)
|
||||
#define ActAnsMchQstStd (ActChgCrsTT1stDay + 191)
|
||||
#define ActRefMchStd (ActChgCrsTT1stDay + 192)
|
||||
#define ActJoiMch (ActChgCrsTT1stDay + 189)
|
||||
#define ActSeeMchAnsQstStd (ActChgCrsTT1stDay + 190)
|
||||
#define ActRemMchAnsQstStd (ActChgCrsTT1stDay + 191)
|
||||
#define ActAnsMchQstStd (ActChgCrsTT1stDay + 192)
|
||||
#define ActRefMchStd (ActChgCrsTT1stDay + 193)
|
||||
|
||||
#define ActSeeMyMchResCrs (ActChgCrsTT1stDay + 193)
|
||||
#define ActSeeMyMchResGam (ActChgCrsTT1stDay + 194)
|
||||
#define ActSeeMyMchResMch (ActChgCrsTT1stDay + 195)
|
||||
#define ActSeeOneMchResMe (ActChgCrsTT1stDay + 196)
|
||||
#define ActSeeMyMchResCrs (ActChgCrsTT1stDay + 194)
|
||||
#define ActSeeMyMchResGam (ActChgCrsTT1stDay + 195)
|
||||
#define ActSeeMyMchResMch (ActChgCrsTT1stDay + 196)
|
||||
#define ActSeeOneMchResMe (ActChgCrsTT1stDay + 197)
|
||||
|
||||
#define ActReqSeeUsrMchRes (ActChgCrsTT1stDay + 197)
|
||||
#define ActSeeUsrMchResCrs (ActChgCrsTT1stDay + 198)
|
||||
#define ActSeeUsrMchResGam (ActChgCrsTT1stDay + 199)
|
||||
#define ActSeeUsrMchResMch (ActChgCrsTT1stDay + 200)
|
||||
#define ActSeeOneMchResOth (ActChgCrsTT1stDay + 201)
|
||||
#define ActReqSeeUsrMchRes (ActChgCrsTT1stDay + 198)
|
||||
#define ActSeeUsrMchResCrs (ActChgCrsTT1stDay + 199)
|
||||
#define ActSeeUsrMchResGam (ActChgCrsTT1stDay + 200)
|
||||
#define ActSeeUsrMchResMch (ActChgCrsTT1stDay + 201)
|
||||
#define ActSeeOneMchResOth (ActChgCrsTT1stDay + 202)
|
||||
|
||||
#define ActChgVisResMchUsr (ActChgCrsTT1stDay + 202)
|
||||
#define ActChgVisResMchUsr (ActChgCrsTT1stDay + 203)
|
||||
|
||||
#define ActFrmNewGam (ActChgCrsTT1stDay + 203)
|
||||
#define ActEdiOneGam (ActChgCrsTT1stDay + 204)
|
||||
#define ActNewGam (ActChgCrsTT1stDay + 205)
|
||||
#define ActChgGam (ActChgCrsTT1stDay + 206)
|
||||
#define ActReqRemGam (ActChgCrsTT1stDay + 207)
|
||||
#define ActRemGam (ActChgCrsTT1stDay + 208)
|
||||
#define ActHidGam (ActChgCrsTT1stDay + 209)
|
||||
#define ActShoGam (ActChgCrsTT1stDay + 210)
|
||||
#define ActAddOneGamQst (ActChgCrsTT1stDay + 211)
|
||||
#define ActGamLstTstQst (ActChgCrsTT1stDay + 212)
|
||||
#define ActAddTstQstToGam (ActChgCrsTT1stDay + 213)
|
||||
#define ActReqRemGamQst (ActChgCrsTT1stDay + 214)
|
||||
#define ActRemGamQst (ActChgCrsTT1stDay + 215)
|
||||
#define ActUp_GamQst (ActChgCrsTT1stDay + 216)
|
||||
#define ActDwnGamQst (ActChgCrsTT1stDay + 217)
|
||||
#define ActFrmNewGam (ActChgCrsTT1stDay + 204)
|
||||
#define ActEdiOneGam (ActChgCrsTT1stDay + 205)
|
||||
#define ActNewGam (ActChgCrsTT1stDay + 206)
|
||||
#define ActChgGam (ActChgCrsTT1stDay + 207)
|
||||
#define ActReqRemGam (ActChgCrsTT1stDay + 208)
|
||||
#define ActRemGam (ActChgCrsTT1stDay + 209)
|
||||
#define ActHidGam (ActChgCrsTT1stDay + 210)
|
||||
#define ActShoGam (ActChgCrsTT1stDay + 211)
|
||||
#define ActAddOneGamQst (ActChgCrsTT1stDay + 212)
|
||||
#define ActGamLstTstQst (ActChgCrsTT1stDay + 213)
|
||||
#define ActAddTstQstToGam (ActChgCrsTT1stDay + 214)
|
||||
#define ActReqRemGamQst (ActChgCrsTT1stDay + 215)
|
||||
#define ActRemGamQst (ActChgCrsTT1stDay + 216)
|
||||
#define ActUp_GamQst (ActChgCrsTT1stDay + 217)
|
||||
#define ActDwnGamQst (ActChgCrsTT1stDay + 218)
|
||||
|
||||
#define ActSeeSvy (ActChgCrsTT1stDay + 218)
|
||||
#define ActAnsSvy (ActChgCrsTT1stDay + 219)
|
||||
#define ActFrmNewSvy (ActChgCrsTT1stDay + 220)
|
||||
#define ActEdiOneSvy (ActChgCrsTT1stDay + 221)
|
||||
#define ActNewSvy (ActChgCrsTT1stDay + 222)
|
||||
#define ActChgSvy (ActChgCrsTT1stDay + 223)
|
||||
#define ActReqRemSvy (ActChgCrsTT1stDay + 224)
|
||||
#define ActRemSvy (ActChgCrsTT1stDay + 225)
|
||||
#define ActReqRstSvy (ActChgCrsTT1stDay + 226)
|
||||
#define ActRstSvy (ActChgCrsTT1stDay + 227)
|
||||
#define ActHidSvy (ActChgCrsTT1stDay + 228)
|
||||
#define ActShoSvy (ActChgCrsTT1stDay + 229)
|
||||
#define ActEdiOneSvyQst (ActChgCrsTT1stDay + 230)
|
||||
#define ActRcvSvyQst (ActChgCrsTT1stDay + 231)
|
||||
#define ActReqRemSvyQst (ActChgCrsTT1stDay + 232)
|
||||
#define ActRemSvyQst (ActChgCrsTT1stDay + 233)
|
||||
#define ActSeeSvy (ActChgCrsTT1stDay + 219)
|
||||
#define ActAnsSvy (ActChgCrsTT1stDay + 220)
|
||||
#define ActFrmNewSvy (ActChgCrsTT1stDay + 221)
|
||||
#define ActEdiOneSvy (ActChgCrsTT1stDay + 222)
|
||||
#define ActNewSvy (ActChgCrsTT1stDay + 223)
|
||||
#define ActChgSvy (ActChgCrsTT1stDay + 224)
|
||||
#define ActReqRemSvy (ActChgCrsTT1stDay + 225)
|
||||
#define ActRemSvy (ActChgCrsTT1stDay + 226)
|
||||
#define ActReqRstSvy (ActChgCrsTT1stDay + 227)
|
||||
#define ActRstSvy (ActChgCrsTT1stDay + 228)
|
||||
#define ActHidSvy (ActChgCrsTT1stDay + 229)
|
||||
#define ActShoSvy (ActChgCrsTT1stDay + 230)
|
||||
#define ActEdiOneSvyQst (ActChgCrsTT1stDay + 231)
|
||||
#define ActRcvSvyQst (ActChgCrsTT1stDay + 232)
|
||||
#define ActReqRemSvyQst (ActChgCrsTT1stDay + 233)
|
||||
#define ActRemSvyQst (ActChgCrsTT1stDay + 234)
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************************** Files tab **********************************/
|
||||
|
|
|
@ -557,10 +557,16 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - *
|
|||
En OpenSWAD:
|
||||
ps2pdf source.ps destination.pdf
|
||||
*/
|
||||
#define Log_PLATFORM_VERSION "SWAD 19.239.9 (2020-05-21)"
|
||||
#define Log_PLATFORM_VERSION "SWAD 19.241 (2020-05-22)"
|
||||
#define CSS_FILE "swad19.238.2.css"
|
||||
#define JS_FILE "swad19.239.6.js"
|
||||
/*
|
||||
Version 19.241: May 22, 2020 Log in exams.
|
||||
Bug fixing and code refactoring in tests and exams. (301712 lines)
|
||||
1 change necessary in database:
|
||||
CREATE TABLE IF NOT EXISTS exa_log (LogCod INT NOT NULL,PrnCod INT NOT NULL,ActCod INT NOT NULL,ClickTime DATETIME NOT NULL,IP CHAR(15) NOT NULL,SessionId CHAR(43) NOT NULL,UNIQUE INDEX(LogCod),INDEX(PrnCod,ClickTime),INDEX(ClickTime));
|
||||
|
||||
Version 19.240: May 21, 2020 Code refactoring in tests and exams. (301428 lines)
|
||||
Version 19.239.9: May 21, 2020 Fixed issue in exam sessions: exam prints in sessions of hidden exams are no accesible. (301441 lines)
|
||||
Version 19.239.8: May 21, 2020 Fixed issue in exam sessions: a student can not see hidden sessions. (301433 lines)
|
||||
Version 19.239.7: May 21, 2020 Fixed bug in permissions to see exam results. Reported by Eduardo Ros Vidal. (301412 lines)
|
||||
|
|
|
@ -1044,6 +1044,33 @@ mysql> DESCRIBE exa_exams;
|
|||
"UNIQUE INDEX(ExaCod),"
|
||||
"INDEX(CrsCod))");
|
||||
|
||||
/***** Table exa_log *****/
|
||||
/*
|
||||
mysql> DESCRIBE exa_log;
|
||||
+-----------+----------+------+-----+---------+-------+
|
||||
| Field | Type | Null | Key | Default | Extra |
|
||||
+-----------+----------+------+-----+---------+-------+
|
||||
| LogCod | int(11) | NO | PRI | NULL | |
|
||||
| PrnCod | int(11) | NO | MUL | NULL | |
|
||||
| ActCod | int(11) | NO | | NULL | |
|
||||
| ClickTime | datetime | NO | MUL | NULL | |
|
||||
| IP | char(15) | NO | | NULL | |
|
||||
| SessionId | char(43) | NO | | NULL | |
|
||||
+-----------+----------+------+-----+---------+-------+
|
||||
6 rows in set (0.00 sec)
|
||||
*/
|
||||
// TODO: Change NtfCod and LogCod from INT to BIGINT in database tables.
|
||||
DB_CreateTable ("CREATE TABLE IF NOT EXISTS exa_log ("
|
||||
"LogCod INT NOT NULL,"
|
||||
"PrnCod INT NOT NULL,"
|
||||
"ActCod INT NOT NULL,"
|
||||
"ClickTime DATETIME NOT NULL,"
|
||||
"IP CHAR(15) NOT NULL," // Cns_MAX_BYTES_IP
|
||||
"SessionId CHAR(43) NOT NULL," // Cns_BYTES_SESSION_ID
|
||||
"UNIQUE INDEX(LogCod),"
|
||||
"INDEX(PrnCod,ClickTime),"
|
||||
"INDEX(ClickTime))");
|
||||
|
||||
/***** Table exa_print_questions *****/
|
||||
/*
|
||||
mysql> DESCRIBE exa_print_questions;
|
||||
|
|
99
swad_exam_log.c
Normal file
99
swad_exam_log.c
Normal file
|
@ -0,0 +1,99 @@
|
|||
// swad_exam_log.c: exam access log
|
||||
|
||||
/*
|
||||
SWAD (Shared Workspace At a Distance),
|
||||
is a web platform developed at the University of Granada (Spain),
|
||||
and used to support university teaching.
|
||||
|
||||
This file is part of SWAD core.
|
||||
Copyright (C) 1999-2020 Antonio Cañas Vargas
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
/********************************* Headers ***********************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
// #define _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_box.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"
|
||||
|
||||
/*****************************************************************************/
|
||||
/************** External global variables from others modules ****************/
|
||||
/*****************************************************************************/
|
||||
|
||||
extern struct Globals Gbl;
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Private constants *****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************************* Private types *******************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Private variables *****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Private prototypes ****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**************************** Log access in database *************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void ExaLog_LogAccess (long LogCod)
|
||||
{
|
||||
long PrnCod;
|
||||
|
||||
if (Gbl.Action.Act == ActAnsExaPrn || // Answer question
|
||||
Gbl.Action.Act == ActSeeExaPrn || // Create/resume print exam
|
||||
Gbl.Action.Act == ActEndExaPrn) // End print exam
|
||||
{
|
||||
PrnCod = ExaPrn_GetCurrentPrnCod ();
|
||||
|
||||
if (PrnCod > 0) // Only if exam print is accesible (visible, open...)
|
||||
/***** Insert access into database *****/
|
||||
/* Log access in exam log.
|
||||
Redundant data (also present in log table) are stored for speed */
|
||||
DB_QueryINSERT ("can not log exam access",
|
||||
"INSERT INTO exa_log "
|
||||
"(LogCod,PrnCod,ActCod,ClickTime,IP,SessionId)"
|
||||
" VALUES "
|
||||
"(%ld,%ld,%ld,NOW(),'%s','%s')",
|
||||
LogCod,
|
||||
PrnCod,
|
||||
Act_GetActCod (Gbl.Action.Act), // Redundant, for speed
|
||||
// NOW() Redundant, for speed
|
||||
Gbl.IP, // Redundant, for speed
|
||||
Gbl.Session.Id);
|
||||
}
|
||||
}
|
42
swad_exam_log.h
Normal file
42
swad_exam_log.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
// swad_exam_log.h: exam access log
|
||||
|
||||
#ifndef _SWAD_EXA_LOG
|
||||
#define _SWAD_EXA_LOG
|
||||
/*
|
||||
SWAD (Shared Workspace At a Distance in Spanish),
|
||||
is a web platform developed at the University of Granada (Spain),
|
||||
and used to support university teaching.
|
||||
|
||||
This file is part of SWAD core.
|
||||
Copyright (C) 1999-2020 Antonio Cañas Vargas
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
/********************************** Headers **********************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/************************* Public types and constants ************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Public prototypes *****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void ExaLog_LogAccess (long LogCod);
|
||||
|
||||
#endif
|
|
@ -61,6 +61,8 @@ extern struct Globals Gbl;
|
|||
/***************************** Private variables *****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static long ExaPrn_CurrentPrnCod = -1L;
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Private prototypes ****************************/
|
||||
/*****************************************************************************/
|
||||
|
@ -107,7 +109,6 @@ static unsigned ExaPrn_GetAnswerFromForm (struct ExaPrn_Print *Print);
|
|||
|
||||
static unsigned ExaPrn_GetParamQstInd (void);
|
||||
|
||||
static void ExaPrn_ComputeScoresAndStoreQuestionsOfPrint (struct ExaPrn_Print *Print);
|
||||
static void ExaPrn_ComputeScoreAndStoreQuestionOfPrint (struct ExaPrn_Print *Print,
|
||||
unsigned NumQst);
|
||||
|
||||
|
@ -141,6 +142,20 @@ static void ExaPrn_GetNumQstsNotBlank (struct ExaPrn_Print *Print);
|
|||
static void ExaPrn_ComputeTotalScoreOfPrint (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 *******************************/
|
||||
/*****************************************************************************/
|
||||
|
@ -201,13 +216,13 @@ void ExaPrn_ShowExamPrint (void)
|
|||
ExaPrn_GetQuestionsForNewPrintFromDB (&Print,Exam.ExaCod);
|
||||
|
||||
if (Print.NumQsts)
|
||||
{
|
||||
/***** Create/update new exam print in database *****/
|
||||
ExaPrn_CreatePrintInDB (&Print);
|
||||
ExaPrn_ComputeScoresAndStoreQuestionsOfPrint (&Print);
|
||||
}
|
||||
}
|
||||
|
||||
/***** Set current print code (to be used in log) *****/
|
||||
ExaPrn_SetCurrentPrnCod (Print.PrnCod);
|
||||
|
||||
/***** Show test exam to be answered *****/
|
||||
ExaPrn_ShowExamPrintToFillIt (&Exams,&Exam,&Print);
|
||||
}
|
||||
|
@ -417,6 +432,9 @@ static unsigned ExaPrn_GetSomeQstsFromSetToPrint (struct ExaPrn_Print *Print,
|
|||
If the user does not confirm the submission of their exam ==>
|
||||
==> the exam may be half filled ==> the answers displayed will be those selected by the user. */
|
||||
Print->PrintedQuestions[*NumQstInPrint].StrAnswers[0] = '\0';
|
||||
|
||||
/* Reset score of this question in print */
|
||||
Print->PrintedQuestions[*NumQstInPrint].Score = 0.0;
|
||||
}
|
||||
|
||||
return NumQstsInSet;
|
||||
|
@ -493,6 +511,8 @@ static void ExaPrn_GenerateChoiceIndexes (struct TstPrn_PrintedQuestion *Printed
|
|||
|
||||
static void ExaPrn_CreatePrintInDB (struct ExaPrn_Print *Print)
|
||||
{
|
||||
unsigned NumQst;
|
||||
|
||||
/***** Insert new exam print into table *****/
|
||||
Print->PrnCod =
|
||||
DB_QueryINSERTandReturnCode ("can not create new exam print",
|
||||
|
@ -503,6 +523,13 @@ static void ExaPrn_CreatePrintInDB (struct ExaPrn_Print *Print)
|
|||
Print->SesCod,
|
||||
Gbl.Usrs.Me.UsrDat.UsrCod,
|
||||
Print->NumQsts);
|
||||
|
||||
/***** Store all questions (with blank answers)
|
||||
of this exam print just generated in database *****/
|
||||
for (NumQst = 0;
|
||||
NumQst < Print->NumQsts;
|
||||
NumQst++)
|
||||
ExaPrn_StoreOneQstOfPrintInDB (Print,NumQst);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -599,7 +626,7 @@ static void ExaPrn_ShowExamPrintToFillIt (struct Exa_Exams *Exams,
|
|||
HTM_DIV_End (); // Used for AJAX based refresh
|
||||
|
||||
/***** Form to end/close this exam print *****/
|
||||
Frm_StartForm (ActSeeOneExaResMe);
|
||||
Frm_StartForm (ActEndExaPrn);
|
||||
ExaSes_PutParamsEdit (Exams);
|
||||
Btn_PutCreateButton (Txt_I_have_finished);
|
||||
Frm_EndForm ();
|
||||
|
@ -968,6 +995,9 @@ void ExaPrn_ReceivePrintAnswer (void)
|
|||
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);
|
||||
|
||||
|
@ -1023,33 +1053,6 @@ static unsigned ExaPrn_GetParamQstInd (void)
|
|||
return (unsigned) NumQst;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*********** Compute score of each question and store in database ************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void ExaPrn_ComputeScoresAndStoreQuestionsOfPrint (struct ExaPrn_Print *Print)
|
||||
{
|
||||
unsigned NumQst;
|
||||
|
||||
/***** Initialize total score *****/
|
||||
Print->Score = 0.0;
|
||||
Print->NumQstsNotBlank = 0;
|
||||
|
||||
/***** Compute and store scores of all questions *****/
|
||||
for (NumQst = 0;
|
||||
NumQst < Print->NumQsts;
|
||||
NumQst++)
|
||||
{
|
||||
/* Compute question score and store in database */
|
||||
ExaPrn_ComputeScoreAndStoreQuestionOfPrint (Print,NumQst);
|
||||
|
||||
/* Accumulate total score */
|
||||
Print->Score += Print->PrintedQuestions[NumQst].Score;
|
||||
if (Print->PrintedQuestions[NumQst].AnswerIsNotBlank)
|
||||
Print->NumQstsNotBlank++;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*********** Compute score of one question and store in database *************/
|
||||
/*****************************************************************************/
|
||||
|
@ -1074,7 +1077,12 @@ static void ExaPrn_ComputeScoreAndStoreQuestionOfPrint (struct ExaPrn_Print *Pri
|
|||
ExaPrn_GetAnswerFromDB (Print,Print->PrintedQuestions[NumQst].QstCod,
|
||||
CurrentStrAnswersInDB);
|
||||
if (!strcmp (Print->PrintedQuestions[NumQst].StrAnswers,CurrentStrAnswersInDB))
|
||||
Print->PrintedQuestions[NumQst].StrAnswers[0] = '\0';
|
||||
{
|
||||
/* The answer just clicked by user
|
||||
is the same as the last one checked and stored in database */
|
||||
Print->PrintedQuestions[NumQst].StrAnswers[0] = '\0'; // Uncheck option
|
||||
Print->PrintedQuestions[NumQst].Score = 0; // Clear question score
|
||||
}
|
||||
}
|
||||
|
||||
/***** Store test exam question in database *****/
|
||||
|
@ -1395,7 +1403,9 @@ static void ExaPrn_ComputeTotalScoreOfPrint (struct ExaPrn_Print *Print)
|
|||
|
||||
/***** Compute total score of exam print *****/
|
||||
if (DB_QuerySELECT (&mysql_res,"can not get score of exam print",
|
||||
"SELECT SUM(Score) FROM exa_print_questions WHERE PrnCod=%ld",
|
||||
"SELECT SUM(Score)"
|
||||
" FROM exa_print_questions"
|
||||
" WHERE PrnCod=%ld",
|
||||
Print->PrnCod))
|
||||
{
|
||||
/***** Get sum of individual scores (row[0]) *****/
|
||||
|
|
|
@ -53,6 +53,9 @@ struct ExaPrn_Print
|
|||
/***************************** Public prototypes *****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void ExaPrn_SetCurrentPrnCod (long PrnCod);
|
||||
long ExaPrn_GetCurrentPrnCod (void);
|
||||
|
||||
void ExaPrn_ResetPrint (struct ExaPrn_Print *Print);
|
||||
|
||||
void ExaPrn_ShowExamPrint (void);
|
||||
|
|
|
@ -1110,7 +1110,8 @@ void ExaRes_ShowOneExaResult (void)
|
|||
ExaSes_GetAndCheckParameters (&Exams,&Exam,&Session);
|
||||
|
||||
/***** Pointer to user's data *****/
|
||||
MeOrOther = (Gbl.Action.Act == ActSeeOneExaResMe) ? Usr_ME :
|
||||
MeOrOther = (Gbl.Action.Act == ActSeeOneExaResMe ||
|
||||
Gbl.Action.Act == ActEndExaPrn) ? Usr_ME :
|
||||
Usr_OTHER;
|
||||
switch (MeOrOther)
|
||||
{
|
||||
|
@ -1130,12 +1131,18 @@ void ExaRes_ShowOneExaResult (void)
|
|||
Print.UsrCod = UsrDat->UsrCod;
|
||||
ExaPrn_GetPrintDataBySesCodAndUsrCod (&Print);
|
||||
|
||||
/***** Set current print code (to be used in log) *****/
|
||||
ExaPrn_SetCurrentPrnCod (Print.PrnCod);
|
||||
|
||||
/***** Check if I can view this print result *****/
|
||||
switch (Gbl.Usrs.Me.Role.Logged)
|
||||
{
|
||||
case Rol_STD:
|
||||
// Depends on visibility of result for this session (eye icon)
|
||||
ICanViewResult = ExaRes_CheckIfICanSeePrintResult (&Session,UsrDat->UsrCod);
|
||||
|
||||
if (ICanViewResult)
|
||||
// Depends on 5 visibility icons
|
||||
ICanViewScore = TstVis_IsVisibleTotalScore (Exam.Visibility);
|
||||
else
|
||||
ICanViewScore = false;
|
||||
|
@ -1393,7 +1400,35 @@ static void ExaRes_WriteQstAndAnsExam (struct UsrData *UsrDat,
|
|||
unsigned Visibility)
|
||||
{
|
||||
extern const char *Txt_Score;
|
||||
bool IsVisibleQstAndAnsTxt = TstVis_IsVisibleQstAndAnsTxt (Visibility);
|
||||
bool IsVisible[TstVis_NUM_ITEMS_VISIBILITY];
|
||||
|
||||
/***** Check if I can view each part of the question *****/
|
||||
switch (Gbl.Usrs.Me.Role.Logged)
|
||||
{
|
||||
case Rol_STD:
|
||||
IsVisible[TstVis_VISIBLE_QST_ANS_TXT ] = TstVis_IsVisibleQstAndAnsTxt (Visibility);
|
||||
IsVisible[TstVis_VISIBLE_FEEDBACK_TXT ] = TstVis_IsVisibleFeedbackTxt (Visibility);
|
||||
IsVisible[TstVis_VISIBLE_CORRECT_ANSWER] = TstVis_IsVisibleCorrectAns (Visibility);
|
||||
IsVisible[TstVis_VISIBLE_EACH_QST_SCORE] = TstVis_IsVisibleEachQstScore (Visibility);
|
||||
break;
|
||||
case Rol_NET:
|
||||
case Rol_TCH:
|
||||
case Rol_DEG_ADM:
|
||||
case Rol_CTR_ADM:
|
||||
case Rol_INS_ADM:
|
||||
case Rol_SYS_ADM:
|
||||
IsVisible[TstVis_VISIBLE_QST_ANS_TXT ] =
|
||||
IsVisible[TstVis_VISIBLE_FEEDBACK_TXT ] =
|
||||
IsVisible[TstVis_VISIBLE_CORRECT_ANSWER] =
|
||||
IsVisible[TstVis_VISIBLE_EACH_QST_SCORE] = true;
|
||||
break;
|
||||
default:
|
||||
IsVisible[TstVis_VISIBLE_QST_ANS_TXT ] =
|
||||
IsVisible[TstVis_VISIBLE_FEEDBACK_TXT ] =
|
||||
IsVisible[TstVis_VISIBLE_CORRECT_ANSWER] =
|
||||
IsVisible[TstVis_VISIBLE_EACH_QST_SCORE] = false;
|
||||
break;
|
||||
}
|
||||
|
||||
/***** Begin row *****/
|
||||
HTM_TR_Begin (NULL);
|
||||
|
@ -1408,20 +1443,21 @@ static void ExaRes_WriteQstAndAnsExam (struct UsrData *UsrDat,
|
|||
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
|
||||
|
||||
/* Stem */
|
||||
Tst_WriteQstStem (Question->Stem,"TEST_EXA",IsVisibleQstAndAnsTxt);
|
||||
Tst_WriteQstStem (Question->Stem,"TEST_EXA",IsVisible[TstVis_VISIBLE_QST_ANS_TXT]);
|
||||
|
||||
/* Media */
|
||||
if (IsVisibleQstAndAnsTxt)
|
||||
if (IsVisible[TstVis_VISIBLE_QST_ANS_TXT])
|
||||
Med_ShowMedia (&Question->Media,
|
||||
"TEST_MED_SHOW_CONT",
|
||||
"TEST_MED_SHOW");
|
||||
|
||||
/* Answers */
|
||||
ExaPrn_ComputeAnswerScore (&Print->PrintedQuestions[NumQst],Question);
|
||||
TstPrn_WriteAnswersExam (UsrDat,&Print->PrintedQuestions[NumQst],Question,Visibility);
|
||||
TstPrn_WriteAnswersExam (UsrDat,&Print->PrintedQuestions[NumQst],Question,
|
||||
IsVisible);
|
||||
|
||||
/* Write score retrieved from database */
|
||||
if (TstVis_IsVisibleEachQstScore (Visibility))
|
||||
if (IsVisible[TstVis_VISIBLE_EACH_QST_SCORE])
|
||||
{
|
||||
HTM_DIV_Begin ("class=\"DAT_SMALL LM\"");
|
||||
HTM_TxtColonNBSP (Txt_Score);
|
||||
|
@ -1436,7 +1472,7 @@ static void ExaRes_WriteQstAndAnsExam (struct UsrData *UsrDat,
|
|||
}
|
||||
|
||||
/* Question feedback */
|
||||
if (TstVis_IsVisibleFeedbackTxt (Visibility))
|
||||
if (IsVisible[TstVis_VISIBLE_FEEDBACK_TXT])
|
||||
Tst_WriteQstFeedback (Question->Feedback,"TEST_EXA_LIGHT");
|
||||
|
||||
HTM_TD_End ();
|
||||
|
|
|
@ -1566,7 +1566,7 @@ static void ExaSet_ListQuestionForEdition (const struct Tst_Question *Question,
|
|||
Tst_WriteQstFeedback (Question->Feedback,"TEST_EDI_LIGHT");
|
||||
|
||||
/* Show answers */
|
||||
Tst_WriteAnswersListing (Question);
|
||||
Tst_WriteAnswersBank (Question);
|
||||
|
||||
HTM_ARTICLE_End ();
|
||||
HTM_TD_End ();
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "swad_banner.h"
|
||||
#include "swad_config.h"
|
||||
#include "swad_database.h"
|
||||
#include "swad_exam_log.h"
|
||||
#include "swad_global.h"
|
||||
#include "swad_HTML.h"
|
||||
#include "swad_log.h"
|
||||
|
@ -123,6 +124,9 @@ void Log_LogAccess (const char *Comments)
|
|||
Gbl.TimeSendInMicroseconds,
|
||||
Gbl.IP);
|
||||
|
||||
/* Log access while answering exam prints */
|
||||
ExaLog_LogAccess (LogCod);
|
||||
|
||||
/* Log comments */
|
||||
if (Comments)
|
||||
{
|
||||
|
|
|
@ -1181,8 +1181,11 @@ void MchRes_ShowOneMchResult (void)
|
|||
switch (Gbl.Usrs.Me.Role.Logged)
|
||||
{
|
||||
case Rol_STD:
|
||||
// Depends on visibility of result for this match (eye icon)
|
||||
ICanViewResult = MchRes_CheckIfICanSeeMatchResult (&Match,UsrDat->UsrCod);
|
||||
|
||||
if (ICanViewResult)
|
||||
// Depends on 5 visibility icons
|
||||
ICanViewScore = TstVis_IsVisibleTotalScore (Game.Visibility);
|
||||
else
|
||||
ICanViewScore = false;
|
||||
|
|
327
swad_test.c
327
swad_test.c
|
@ -183,25 +183,32 @@ static void TstPrn_WriteAnswersToFill (const struct TstPrn_PrintedQuestion *Prin
|
|||
unsigned NumQst,
|
||||
const struct Tst_Question *Question);
|
||||
|
||||
static void Tst_WriteIntAnsListing (const struct Tst_Question *Question);
|
||||
static void TstPrn_WriteIntAnsSeeing (const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
unsigned NumQst);
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static void Tst_WriteFloatAnsEdit (const struct Tst_Question *Question);
|
||||
static void TstPrn_WriteFloatAnsSeeing (const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
unsigned NumQst);
|
||||
static void Tst_WriteIntAnsBank (const struct Tst_Question *Question);
|
||||
static void Tst_WriteFltAnsBank (const struct Tst_Question *Question);
|
||||
static void Tst_WriteTF_AnsBank (const struct Tst_Question *Question);
|
||||
static void Tst_WriteChoAnsBank (const struct Tst_Question *Question);
|
||||
|
||||
static void Tst_WriteTFAnsListing (const struct Tst_Question *Question);
|
||||
static void TstPrn_WriteTFAnsSeeing (const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
unsigned NumQst);
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static void Tst_WriteChoiceAnsListing (const struct Tst_Question *Question);
|
||||
static void TstPrn_WriteChoiceAnsSeeing (const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
static void TstPrn_WriteIntAnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
unsigned NumQst,
|
||||
__attribute__((unused)) const struct Tst_Question *Question);
|
||||
static void TstPrn_WriteFltAnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
unsigned NumQst,
|
||||
__attribute__((unused)) const struct Tst_Question *Question);
|
||||
static void TstPrn_WriteTF_AnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
unsigned NumQst,
|
||||
__attribute__((unused)) const struct Tst_Question *Question);
|
||||
static void TstPrn_WriteChoAnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
unsigned NumQst,
|
||||
const struct Tst_Question *Question);
|
||||
static void TstPrn_WriteTxtAnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
unsigned NumQst,
|
||||
__attribute__((unused)) const struct Tst_Question *Question);
|
||||
|
||||
static void TstPrn_WriteTextAnsSeeing (const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
unsigned NumQst);
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static bool Tst_GetParamsTst (struct Tst_Test *Test,
|
||||
Tst_ActionToDoWithQuestions_t ActionToDoWithQuestions);
|
||||
|
@ -932,7 +939,7 @@ void Tst_ListQuestionForEdition (const struct Tst_Question *Question,
|
|||
Tst_WriteQstFeedback (Question->Feedback,"TEST_EDI_LIGHT");
|
||||
|
||||
/* Show answers */
|
||||
Tst_WriteAnswersListing (Question);
|
||||
Tst_WriteAnswersBank (Question);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2541,7 +2548,7 @@ static void Tst_WriteQuestionListing (struct Tst_Test *Test,unsigned NumQst)
|
|||
|
||||
/* Feedback (row[4]) and answers */
|
||||
Tst_WriteQstFeedback (Test->Question.Feedback,"TEST_EDI_LIGHT");
|
||||
Tst_WriteAnswersListing (&Test->Question);
|
||||
Tst_WriteAnswersBank (&Test->Question);
|
||||
HTM_TD_End ();
|
||||
|
||||
/* Number of times this question has been answered */
|
||||
|
@ -2820,7 +2827,7 @@ static void Tst_WriteQuestionRowForSelection (unsigned NumQst,
|
|||
Tst_WriteQstFeedback (Question->Feedback,"TEST_EDI_LIGHT");
|
||||
|
||||
/* Write answers */
|
||||
Tst_WriteAnswersListing (Question);
|
||||
Tst_WriteAnswersBank (Question);
|
||||
HTM_TD_End ();
|
||||
|
||||
/***** End table row *****/
|
||||
|
@ -2881,28 +2888,20 @@ void Tst_GetAnswersQst (struct Tst_Question *Question,MYSQL_RES **mysql_res,
|
|||
/**************** Get and write the answers of a test question ***************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void Tst_WriteAnswersListing (const struct Tst_Question *Question)
|
||||
void Tst_WriteAnswersBank (const struct Tst_Question *Question)
|
||||
{
|
||||
void (*TstPrn_WriteAnsBank[Tst_NUM_ANS_TYPES]) (const struct Tst_Question *Question) =
|
||||
{
|
||||
[Tst_ANS_INT ] = Tst_WriteIntAnsBank,
|
||||
[Tst_ANS_FLOAT ] = Tst_WriteFltAnsBank,
|
||||
[Tst_ANS_TRUE_FALSE ] = Tst_WriteTF_AnsBank,
|
||||
[Tst_ANS_UNIQUE_CHOICE ] = Tst_WriteChoAnsBank,
|
||||
[Tst_ANS_MULTIPLE_CHOICE] = Tst_WriteChoAnsBank,
|
||||
[Tst_ANS_TEXT ] = Tst_WriteChoAnsBank,
|
||||
};
|
||||
|
||||
/***** Write answers *****/
|
||||
switch (Question->Answer.Type)
|
||||
{
|
||||
case Tst_ANS_INT:
|
||||
Tst_WriteIntAnsListing (Question);
|
||||
break;
|
||||
case Tst_ANS_FLOAT:
|
||||
Tst_WriteFloatAnsEdit (Question);
|
||||
break;
|
||||
case Tst_ANS_TRUE_FALSE:
|
||||
Tst_WriteTFAnsListing (Question);
|
||||
break;
|
||||
case Tst_ANS_UNIQUE_CHOICE:
|
||||
case Tst_ANS_MULTIPLE_CHOICE:
|
||||
case Tst_ANS_TEXT:
|
||||
Tst_WriteChoiceAnsListing (Question);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
TstPrn_WriteAnsBank[Question->Answer.Type] (Question);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -2913,28 +2912,20 @@ static void TstPrn_WriteAnswersToFill (const struct TstPrn_PrintedQuestion *Prin
|
|||
unsigned NumQst,
|
||||
const struct Tst_Question *Question)
|
||||
{
|
||||
/***** Write answer depending on type *****/
|
||||
switch (Question->Answer.Type)
|
||||
void (*TstPrn_WriteAnsBank[Tst_NUM_ANS_TYPES]) (const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
unsigned NumQst,
|
||||
const struct Tst_Question *Question) =
|
||||
{
|
||||
case Tst_ANS_INT:
|
||||
TstPrn_WriteIntAnsSeeing (PrintedQuestion,NumQst);
|
||||
break;
|
||||
case Tst_ANS_FLOAT:
|
||||
TstPrn_WriteFloatAnsSeeing (PrintedQuestion,NumQst);
|
||||
break;
|
||||
case Tst_ANS_TRUE_FALSE:
|
||||
TstPrn_WriteTFAnsSeeing (PrintedQuestion,NumQst);
|
||||
break;
|
||||
case Tst_ANS_UNIQUE_CHOICE:
|
||||
case Tst_ANS_MULTIPLE_CHOICE:
|
||||
TstPrn_WriteChoiceAnsSeeing (PrintedQuestion,NumQst,Question);
|
||||
break;
|
||||
case Tst_ANS_TEXT:
|
||||
TstPrn_WriteTextAnsSeeing (PrintedQuestion,NumQst);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
[Tst_ANS_INT ] = TstPrn_WriteIntAnsToFill,
|
||||
[Tst_ANS_FLOAT ] = TstPrn_WriteFltAnsToFill,
|
||||
[Tst_ANS_TRUE_FALSE ] = TstPrn_WriteTF_AnsToFill,
|
||||
[Tst_ANS_UNIQUE_CHOICE ] = TstPrn_WriteChoAnsToFill,
|
||||
[Tst_ANS_MULTIPLE_CHOICE] = TstPrn_WriteChoAnsToFill,
|
||||
[Tst_ANS_TEXT ] = TstPrn_WriteTxtAnsToFill,
|
||||
};
|
||||
|
||||
/***** Write answers *****/
|
||||
TstPrn_WriteAnsBank[Question->Answer.Type] (PrintedQuestion,NumQst,Question);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -2955,36 +2946,18 @@ bool Tst_CheckIfQuestionIsValidForGame (long QstCod)
|
|||
/****************** Write integer answer when editing a test *****************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Tst_WriteIntAnsListing (const struct Tst_Question *Question)
|
||||
static void Tst_WriteIntAnsBank (const struct Tst_Question *Question)
|
||||
{
|
||||
HTM_SPAN_Begin ("class=\"TEST_EDI\"");
|
||||
HTM_TxtF ("(%ld)",Question->Answer.Integer);
|
||||
HTM_SPAN_End ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/****************** Write integer answer when seeing a test ******************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void TstPrn_WriteIntAnsSeeing (const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
unsigned NumQst)
|
||||
{
|
||||
char StrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x"
|
||||
|
||||
/***** Write input field for the answer *****/
|
||||
snprintf (StrAns,sizeof (StrAns),
|
||||
"Ans%010u",
|
||||
NumQst);
|
||||
HTM_INPUT_TEXT (StrAns,11,PrintedQuestion->StrAnswers,
|
||||
HTM_DONT_SUBMIT_ON_CHANGE,
|
||||
"size=\"11\"");
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/****************** Write float answer when editing a test *******************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Tst_WriteFloatAnsEdit (const struct Tst_Question *Question)
|
||||
static void Tst_WriteFltAnsBank (const struct Tst_Question *Question)
|
||||
{
|
||||
HTM_SPAN_Begin ("class=\"TEST_EDI\"");
|
||||
HTM_Txt ("([");
|
||||
|
@ -2995,29 +2968,11 @@ static void Tst_WriteFloatAnsEdit (const struct Tst_Question *Question)
|
|||
HTM_SPAN_End ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/****************** Write float answer when seeing a test ********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void TstPrn_WriteFloatAnsSeeing (const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
unsigned NumQst)
|
||||
{
|
||||
char StrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x"
|
||||
|
||||
/***** Write input field for the answer *****/
|
||||
snprintf (StrAns,sizeof (StrAns),
|
||||
"Ans%010u",
|
||||
NumQst);
|
||||
HTM_INPUT_TEXT (StrAns,Tst_MAX_BYTES_FLOAT_ANSWER,PrintedQuestion->StrAnswers,
|
||||
HTM_DONT_SUBMIT_ON_CHANGE,
|
||||
"size=\"11\"");
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*********** Write false / true answer when listing test questions ***********/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Tst_WriteTFAnsListing (const struct Tst_Question *Question)
|
||||
static void Tst_WriteTF_AnsBank (const struct Tst_Question *Question)
|
||||
{
|
||||
/***** Write answer *****/
|
||||
HTM_SPAN_Begin ("class=\"TEST_EDI\"");
|
||||
|
@ -3027,54 +2982,11 @@ static void Tst_WriteTFAnsListing (const struct Tst_Question *Question)
|
|||
HTM_SPAN_End ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/************** Write false / true answer when seeing a test ****************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void TstPrn_WriteTFAnsSeeing (const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
unsigned NumQst)
|
||||
{
|
||||
extern const char *Txt_TF_QST[2];
|
||||
|
||||
/***** Write selector for the answer *****/
|
||||
/* Initially user has not answered the question ==> initially all the answers will be blank.
|
||||
If the user does not confirm the submission of their exam ==>
|
||||
==> the exam may be half filled ==> the answers displayed will be those selected by the user. */
|
||||
HTM_SELECT_Begin (HTM_DONT_SUBMIT_ON_CHANGE,
|
||||
"name=\"Ans%010u\"",NumQst);
|
||||
HTM_OPTION (HTM_Type_STRING,"" ,PrintedQuestion->StrAnswers[0] == '\0',false," ");
|
||||
HTM_OPTION (HTM_Type_STRING,"T",PrintedQuestion->StrAnswers[0] == 'T' ,false,"%s",Txt_TF_QST[0]);
|
||||
HTM_OPTION (HTM_Type_STRING,"F",PrintedQuestion->StrAnswers[0] == 'F' ,false,"%s",Txt_TF_QST[1]);
|
||||
HTM_SELECT_End ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/************** Write false / true answer when seeing a test *****************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void Tst_WriteAnsTF (char AnsTF)
|
||||
{
|
||||
extern const char *Txt_TF_QST[2];
|
||||
|
||||
switch (AnsTF)
|
||||
{
|
||||
case 'T': // true
|
||||
HTM_Txt (Txt_TF_QST[0]);
|
||||
break;
|
||||
case 'F': // false
|
||||
HTM_Txt (Txt_TF_QST[1]);
|
||||
break;
|
||||
default: // no answer
|
||||
HTM_NBSP ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**** Write single or multiple choice answer when listing test questions *****/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Tst_WriteChoiceAnsListing (const struct Tst_Question *Question)
|
||||
static void Tst_WriteChoAnsBank (const struct Tst_Question *Question)
|
||||
{
|
||||
extern const char *Txt_TST_Answer_given_by_the_teachers;
|
||||
unsigned NumOpt;
|
||||
|
@ -3160,11 +3072,71 @@ static void Tst_WriteChoiceAnsListing (const struct Tst_Question *Question)
|
|||
HTM_TABLE_End ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/****************** Write integer answer when seeing a test ******************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void TstPrn_WriteIntAnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
unsigned NumQst,
|
||||
__attribute__((unused)) const struct Tst_Question *Question)
|
||||
{
|
||||
char StrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x"
|
||||
|
||||
/***** Write input field for the answer *****/
|
||||
snprintf (StrAns,sizeof (StrAns),
|
||||
"Ans%010u",
|
||||
NumQst);
|
||||
HTM_INPUT_TEXT (StrAns,11,PrintedQuestion->StrAnswers,
|
||||
HTM_DONT_SUBMIT_ON_CHANGE,
|
||||
"size=\"11\"");
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/****************** Write float answer when seeing a test ********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void TstPrn_WriteFltAnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
unsigned NumQst,
|
||||
__attribute__((unused)) const struct Tst_Question *Question)
|
||||
{
|
||||
char StrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x"
|
||||
|
||||
/***** Write input field for the answer *****/
|
||||
snprintf (StrAns,sizeof (StrAns),
|
||||
"Ans%010u",
|
||||
NumQst);
|
||||
HTM_INPUT_TEXT (StrAns,Tst_MAX_BYTES_FLOAT_ANSWER,PrintedQuestion->StrAnswers,
|
||||
HTM_DONT_SUBMIT_ON_CHANGE,
|
||||
"size=\"11\"");
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/************** Write false / true answer when seeing a test ****************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void TstPrn_WriteTF_AnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
unsigned NumQst,
|
||||
__attribute__((unused)) const struct Tst_Question *Question)
|
||||
{
|
||||
extern const char *Txt_TF_QST[2];
|
||||
|
||||
/***** Write selector for the answer *****/
|
||||
/* Initially user has not answered the question ==> initially all the answers will be blank.
|
||||
If the user does not confirm the submission of their exam ==>
|
||||
==> the exam may be half filled ==> the answers displayed will be those selected by the user. */
|
||||
HTM_SELECT_Begin (HTM_DONT_SUBMIT_ON_CHANGE,
|
||||
"name=\"Ans%010u\"",NumQst);
|
||||
HTM_OPTION (HTM_Type_STRING,"" ,PrintedQuestion->StrAnswers[0] == '\0',false," ");
|
||||
HTM_OPTION (HTM_Type_STRING,"T",PrintedQuestion->StrAnswers[0] == 'T' ,false,"%s",Txt_TF_QST[0]);
|
||||
HTM_OPTION (HTM_Type_STRING,"F",PrintedQuestion->StrAnswers[0] == 'F' ,false,"%s",Txt_TF_QST[1]);
|
||||
HTM_SELECT_End ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******** Write single or multiple choice answer when seeing a test **********/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void TstPrn_WriteChoiceAnsSeeing (const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
static void TstPrn_WriteChoAnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
unsigned NumQst,
|
||||
const struct Tst_Question *Question)
|
||||
{
|
||||
|
@ -3173,6 +3145,16 @@ static void TstPrn_WriteChoiceAnsSeeing (const struct TstPrn_PrintedQuestion *Pr
|
|||
bool UsrAnswers[Tst_MAX_OPTIONS_PER_QUESTION];
|
||||
char StrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x"
|
||||
|
||||
/***** Change format of answers text *****/
|
||||
for (NumOpt = 0;
|
||||
NumOpt < Question->Answer.NumOptions;
|
||||
NumOpt++)
|
||||
/* Convert answer text, that is in HTML, to rigorous HTML */
|
||||
if (Question->Answer.Options[NumOpt].Text[0])
|
||||
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
||||
Question->Answer.Options[NumOpt].Text,
|
||||
Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false);
|
||||
|
||||
/***** Get indexes for this question from string *****/
|
||||
TstPrn_GetIndexesFromStr (PrintedQuestion->StrIndexes,Indexes);
|
||||
|
||||
|
@ -3241,6 +3223,47 @@ static void TstPrn_WriteChoiceAnsSeeing (const struct TstPrn_PrintedQuestion *Pr
|
|||
HTM_TABLE_End ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************** Write text answer when seeing a test *******************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void TstPrn_WriteTxtAnsToFill (const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
unsigned NumQst,
|
||||
__attribute__((unused)) const struct Tst_Question *Question)
|
||||
{
|
||||
char StrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x"
|
||||
|
||||
/***** Write input field for the answer *****/
|
||||
snprintf (StrAns,sizeof (StrAns),
|
||||
"Ans%010u",
|
||||
NumQst);
|
||||
HTM_INPUT_TEXT (StrAns,Tst_MAX_CHARS_ANSWERS_ONE_QST,PrintedQuestion->StrAnswers,
|
||||
HTM_DONT_SUBMIT_ON_CHANGE,
|
||||
"size=\"40\"");
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/************** Write false / true answer when seeing a test *****************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void Tst_WriteAnsTF (char AnsTF)
|
||||
{
|
||||
extern const char *Txt_TF_QST[2];
|
||||
|
||||
switch (AnsTF)
|
||||
{
|
||||
case 'T': // true
|
||||
HTM_Txt (Txt_TF_QST[0]);
|
||||
break;
|
||||
case 'F': // false
|
||||
HTM_Txt (Txt_TF_QST[1]);
|
||||
break;
|
||||
default: // no answer
|
||||
HTM_NBSP ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/************************ Get choice answer from row *************************/
|
||||
/*****************************************************************************/
|
||||
|
@ -3301,24 +3324,6 @@ void Tst_GetChoiceAns (struct Tst_Question *Question,MYSQL_RES *mysql_res)
|
|||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************** Write text answer when seeing a test *******************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void TstPrn_WriteTextAnsSeeing (const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
unsigned NumQst)
|
||||
{
|
||||
char StrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Ansxx...x"
|
||||
|
||||
/***** Write input field for the answer *****/
|
||||
snprintf (StrAns,sizeof (StrAns),
|
||||
"Ans%010u",
|
||||
NumQst);
|
||||
HTM_INPUT_TEXT (StrAns,Tst_MAX_CHARS_ANSWERS_ONE_QST,PrintedQuestion->StrAnswers,
|
||||
HTM_DONT_SUBMIT_ON_CHANGE,
|
||||
"size=\"40\"");
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*************** Write parameter with the code of a question *****************/
|
||||
/*****************************************************************************/
|
||||
|
@ -5605,7 +5610,7 @@ void Tst_UpdateQstScoreInDB (struct TstPrn_PrintedQuestion *PrintedQuestion)
|
|||
{
|
||||
/***** Update number of clicks and score of the question *****/
|
||||
Str_SetDecimalPointToUS (); // To print the floating point as a dot
|
||||
if (PrintedQuestion->AnswerIsNotBlank)
|
||||
if (PrintedQuestion->StrAnswers[0]) // User's answer is not blank
|
||||
DB_QueryUPDATE ("can not update the score of a question",
|
||||
"UPDATE tst_questions"
|
||||
" SET NumHits=NumHits+1,NumHitsNotBlank=NumHitsNotBlank+1,"
|
||||
|
@ -5613,7 +5618,7 @@ void Tst_UpdateQstScoreInDB (struct TstPrn_PrintedQuestion *PrintedQuestion)
|
|||
" WHERE QstCod=%ld",
|
||||
PrintedQuestion->Score,
|
||||
PrintedQuestion->QstCod);
|
||||
else // The answer is blank
|
||||
else // User's answer is blank
|
||||
DB_QueryUPDATE ("can not update the score of a question",
|
||||
"UPDATE tst_questions"
|
||||
" SET NumHits=NumHits+1"
|
||||
|
|
|
@ -130,7 +130,7 @@ void Tst_WriteParamEditQst (const struct Tst_Test *Test);
|
|||
unsigned Tst_GetNumAnswersQst (long QstCod);
|
||||
void Tst_GetAnswersQst (struct Tst_Question *Question,MYSQL_RES **mysql_res,
|
||||
bool Shuffle);
|
||||
void Tst_WriteAnswersListing (const struct Tst_Question *Question);
|
||||
void Tst_WriteAnswersBank (const struct Tst_Question *Question);
|
||||
bool Tst_CheckIfQuestionIsValidForGame (long QstCod);
|
||||
void Tst_WriteAnsTF (char AnsTF);
|
||||
void Tst_GetChoiceAns (struct Tst_Question *Question,MYSQL_RES *mysql_res);
|
||||
|
|
|
@ -105,23 +105,23 @@ static void TstPrn_GetCorrectTxtAnswerFromDB (struct Tst_Question *Question);
|
|||
static void TstPrn_WriteIntAnsPrint (struct UsrData *UsrDat,
|
||||
const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
const struct Tst_Question *Question,
|
||||
unsigned Visibility);
|
||||
bool IsVisible[TstVis_NUM_ITEMS_VISIBILITY]);
|
||||
static void TstPrn_WriteFltAnsPrint (struct UsrData *UsrDat,
|
||||
const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
const struct Tst_Question *Question,
|
||||
unsigned Visibility);
|
||||
bool IsVisible[TstVis_NUM_ITEMS_VISIBILITY]);
|
||||
static void TstPrn_WriteTF_AnsPrint (struct UsrData *UsrDat,
|
||||
const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
const struct Tst_Question *Question,
|
||||
unsigned Visibility);
|
||||
bool IsVisible[TstVis_NUM_ITEMS_VISIBILITY]);
|
||||
static void TstPrn_WriteChoAnsPrint (struct UsrData *UsrDat,
|
||||
const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
const struct Tst_Question *Question,
|
||||
unsigned Visibility);
|
||||
bool IsVisible[TstVis_NUM_ITEMS_VISIBILITY]);
|
||||
static void TstPrn_WriteTxtAnsPrint (struct UsrData *UsrDat,
|
||||
const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
const struct Tst_Question *Question,
|
||||
unsigned Visibility);
|
||||
bool IsVisible[TstVis_NUM_ITEMS_VISIBILITY]);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
@ -250,7 +250,7 @@ void TstPrn_ShowPrintAfterAssess (struct TstPrn_Print *Print)
|
|||
|
||||
/***** Compute total score *****/
|
||||
Print->Score += Print->PrintedQuestions[NumQst].Score;
|
||||
if (Print->PrintedQuestions[NumQst].AnswerIsNotBlank)
|
||||
if (Print->PrintedQuestions[NumQst].StrAnswers[0]) // User's answer is not blank
|
||||
Print->NumQstsNotBlank++;
|
||||
|
||||
/***** Update the number of accesses and the score of this question *****/
|
||||
|
@ -280,7 +280,35 @@ static void TstPrn_WriteQstAndAnsExam (struct UsrData *UsrDat,
|
|||
extern const char *Txt_Question_removed;
|
||||
extern const char *Txt_Question_modified;
|
||||
bool QuestionUneditedAfterExam = false;
|
||||
bool IsVisibleQstAndAnsTxt = TstVis_IsVisibleQstAndAnsTxt (Visibility);
|
||||
bool IsVisible[TstVis_NUM_ITEMS_VISIBILITY];
|
||||
|
||||
/***** Check if I can view each part of the question *****/
|
||||
switch (Gbl.Usrs.Me.Role.Logged)
|
||||
{
|
||||
case Rol_STD:
|
||||
IsVisible[TstVis_VISIBLE_QST_ANS_TXT ] = TstVis_IsVisibleQstAndAnsTxt (Visibility);
|
||||
IsVisible[TstVis_VISIBLE_FEEDBACK_TXT ] = TstVis_IsVisibleFeedbackTxt (Visibility);
|
||||
IsVisible[TstVis_VISIBLE_CORRECT_ANSWER] = TstVis_IsVisibleCorrectAns (Visibility);
|
||||
IsVisible[TstVis_VISIBLE_EACH_QST_SCORE] = TstVis_IsVisibleEachQstScore (Visibility);
|
||||
break;
|
||||
case Rol_NET:
|
||||
case Rol_TCH:
|
||||
case Rol_DEG_ADM:
|
||||
case Rol_CTR_ADM:
|
||||
case Rol_INS_ADM:
|
||||
case Rol_SYS_ADM:
|
||||
IsVisible[TstVis_VISIBLE_QST_ANS_TXT ] =
|
||||
IsVisible[TstVis_VISIBLE_FEEDBACK_TXT ] =
|
||||
IsVisible[TstVis_VISIBLE_CORRECT_ANSWER] =
|
||||
IsVisible[TstVis_VISIBLE_EACH_QST_SCORE] = true;
|
||||
break;
|
||||
default:
|
||||
IsVisible[TstVis_VISIBLE_QST_ANS_TXT ] =
|
||||
IsVisible[TstVis_VISIBLE_FEEDBACK_TXT ] =
|
||||
IsVisible[TstVis_VISIBLE_CORRECT_ANSWER] =
|
||||
IsVisible[TstVis_VISIBLE_EACH_QST_SCORE] = false;
|
||||
break;
|
||||
}
|
||||
|
||||
/***** If this question has been edited later than test time
|
||||
==> don't show question ****/
|
||||
|
@ -306,17 +334,18 @@ static void TstPrn_WriteQstAndAnsExam (struct UsrData *UsrDat,
|
|||
if (QuestionUneditedAfterExam)
|
||||
{
|
||||
/* Stem */
|
||||
Tst_WriteQstStem (Question->Stem,"TEST_EXA",IsVisibleQstAndAnsTxt);
|
||||
Tst_WriteQstStem (Question->Stem,"TEST_EXA",IsVisible[TstVis_VISIBLE_QST_ANS_TXT]);
|
||||
|
||||
/* Media */
|
||||
if (IsVisibleQstAndAnsTxt)
|
||||
if (IsVisible[TstVis_VISIBLE_QST_ANS_TXT])
|
||||
Med_ShowMedia (&Question->Media,
|
||||
"TEST_MED_SHOW_CONT",
|
||||
"TEST_MED_SHOW");
|
||||
|
||||
/* Answers */
|
||||
TstPrn_ComputeAnswerScore (&Print->PrintedQuestions[NumQst],Question);
|
||||
TstPrn_WriteAnswersExam (UsrDat,&Print->PrintedQuestions[NumQst],Question,Visibility);
|
||||
TstPrn_WriteAnswersExam (UsrDat,&Print->PrintedQuestions[NumQst],Question,
|
||||
IsVisible);
|
||||
}
|
||||
else
|
||||
Ale_ShowAlert (Ale_WARNING,Txt_Question_modified);
|
||||
|
@ -325,7 +354,7 @@ static void TstPrn_WriteQstAndAnsExam (struct UsrData *UsrDat,
|
|||
Ale_ShowAlert (Ale_WARNING,Txt_Question_removed);
|
||||
|
||||
/* Write score retrieved from database */
|
||||
if (TstVis_IsVisibleEachQstScore (Visibility))
|
||||
if (IsVisible[TstVis_VISIBLE_EACH_QST_SCORE])
|
||||
{
|
||||
HTM_DIV_Begin ("class=\"DAT_SMALL LM\"");
|
||||
HTM_TxtColonNBSP (Txt_Score);
|
||||
|
@ -341,7 +370,7 @@ static void TstPrn_WriteQstAndAnsExam (struct UsrData *UsrDat,
|
|||
|
||||
/* Question feedback */
|
||||
if (QuestionUneditedAfterExam)
|
||||
if (TstVis_IsVisibleFeedbackTxt (Visibility))
|
||||
if (IsVisible[TstVis_VISIBLE_FEEDBACK_TXT])
|
||||
Tst_WriteQstFeedback (Question->Feedback,"TEST_EXA_LIGHT");
|
||||
|
||||
HTM_TD_End ();
|
||||
|
@ -382,7 +411,7 @@ void TstPrn_ComputeScoresAndStoreQuestionsOfPrint (struct TstPrn_Print *Print,
|
|||
|
||||
/* Accumulate total score */
|
||||
Print->Score += Print->PrintedQuestions[NumQst].Score;
|
||||
if (Print->PrintedQuestions[NumQst].AnswerIsNotBlank)
|
||||
if (Print->PrintedQuestions[NumQst].StrAnswers[0]) // User's answer is not blank
|
||||
Print->NumQstsNotBlank++;
|
||||
|
||||
/* Update the number of hits and the score of this question in tests database */
|
||||
|
@ -633,8 +662,7 @@ void TstPrn_ComputeIntAnsScore (struct TstPrn_PrintedQuestion *PrintedQuestion,
|
|||
long AnswerUsr;
|
||||
|
||||
PrintedQuestion->Score = 0.0; // Default score for blank or wrong answer
|
||||
PrintedQuestion->AnswerIsNotBlank = (PrintedQuestion->StrAnswers[0] != '\0');
|
||||
if (PrintedQuestion->AnswerIsNotBlank) // If user has answered the answer
|
||||
if (PrintedQuestion->StrAnswers[0]) // If user has answered the answer
|
||||
if (sscanf (PrintedQuestion->StrAnswers,"%ld",&AnswerUsr) == 1)
|
||||
if (AnswerUsr == Question->Answer.Integer) // Correct answer
|
||||
PrintedQuestion->Score = 1.0;
|
||||
|
@ -646,8 +674,7 @@ void TstPrn_ComputeFltAnsScore (struct TstPrn_PrintedQuestion *PrintedQuestion,
|
|||
double AnswerUsr;
|
||||
|
||||
PrintedQuestion->Score = 0.0; // Default score for blank or wrong answer
|
||||
PrintedQuestion->AnswerIsNotBlank = (PrintedQuestion->StrAnswers[0] != '\0');
|
||||
if (PrintedQuestion->AnswerIsNotBlank) // If user has answered the answer
|
||||
if (PrintedQuestion->StrAnswers[0]) // If user has answered the answer
|
||||
{
|
||||
AnswerUsr = Str_GetDoubleFromStr (PrintedQuestion->StrAnswers);
|
||||
|
||||
|
@ -661,8 +688,7 @@ void TstPrn_ComputeFltAnsScore (struct TstPrn_PrintedQuestion *PrintedQuestion,
|
|||
void TstPrn_ComputeTF_AnsScore (struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
const struct Tst_Question *Question)
|
||||
{
|
||||
PrintedQuestion->AnswerIsNotBlank = (PrintedQuestion->StrAnswers[0] != '\0');
|
||||
if (PrintedQuestion->AnswerIsNotBlank) // User has selected T or F
|
||||
if (PrintedQuestion->StrAnswers[0]) // If user has selected T or F
|
||||
PrintedQuestion->Score = (PrintedQuestion->StrAnswers[0] == Question->Answer.TF) ? 1.0 : // Correct
|
||||
-1.0; // Wrong
|
||||
else
|
||||
|
@ -705,8 +731,7 @@ void TstPrn_ComputeChoAnsScore (struct TstPrn_PrintedQuestion *PrintedQuestion,
|
|||
}
|
||||
|
||||
/* The answer is blank? */
|
||||
PrintedQuestion->AnswerIsNotBlank = NumAnsGood != 0 || NumAnsBad != 0;
|
||||
if (PrintedQuestion->AnswerIsNotBlank)
|
||||
if (NumAnsGood || NumAnsBad) // If user has answered the answer
|
||||
{
|
||||
/* Compute the score */
|
||||
if (Question->Answer.Type == Tst_ANS_UNIQUE_CHOICE)
|
||||
|
@ -748,8 +773,7 @@ void TstPrn_ComputeTxtAnsScore (struct TstPrn_PrintedQuestion *PrintedQuestion,
|
|||
char TextAnsOK[Tst_MAX_BYTES_ANSWERS_ONE_QST + 1];
|
||||
|
||||
PrintedQuestion->Score = 0.0; // Default score for blank or wrong answer
|
||||
PrintedQuestion->AnswerIsNotBlank = (PrintedQuestion->StrAnswers[0] != '\0');
|
||||
if (PrintedQuestion->AnswerIsNotBlank) // If user has answered the answer
|
||||
if (PrintedQuestion->StrAnswers[0]) // If user has answered the answer
|
||||
{
|
||||
/* Filter the user answer */
|
||||
Str_Copy (TextAnsUsr,PrintedQuestion->StrAnswers,
|
||||
|
@ -892,12 +916,12 @@ void TstPrn_ShowGrade (double Grade,double MaxGrade)
|
|||
void TstPrn_WriteAnswersExam (struct UsrData *UsrDat,
|
||||
const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
const struct Tst_Question *Question,
|
||||
unsigned Visibility)
|
||||
bool IsVisible[TstVis_NUM_ITEMS_VISIBILITY])
|
||||
{
|
||||
void (*TstPrn_WriteAnsExam[Tst_NUM_ANS_TYPES]) (struct UsrData *UsrDat,
|
||||
const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
const struct Tst_Question *Question,
|
||||
unsigned Visibility) =
|
||||
bool IsVisible[TstVis_NUM_ITEMS_VISIBILITY]) =
|
||||
{
|
||||
[Tst_ANS_INT ] = TstPrn_WriteIntAnsPrint,
|
||||
[Tst_ANS_FLOAT ] = TstPrn_WriteFltAnsPrint,
|
||||
|
@ -908,7 +932,8 @@ void TstPrn_WriteAnswersExam (struct UsrData *UsrDat,
|
|||
};
|
||||
|
||||
/***** Get correct answer and compute answer score depending on type *****/
|
||||
TstPrn_WriteAnsExam[Question->Answer.Type] (UsrDat,PrintedQuestion,Question,Visibility);
|
||||
TstPrn_WriteAnsExam[Question->Answer.Type] (UsrDat,PrintedQuestion,Question,
|
||||
IsVisible);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -918,7 +943,7 @@ void TstPrn_WriteAnswersExam (struct UsrData *UsrDat,
|
|||
static void TstPrn_WriteIntAnsPrint (struct UsrData *UsrDat,
|
||||
const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
const struct Tst_Question *Question,
|
||||
unsigned Visibility)
|
||||
bool IsVisible[TstVis_NUM_ITEMS_VISIBILITY])
|
||||
{
|
||||
long IntAnswerUsr;
|
||||
|
||||
|
@ -939,7 +964,7 @@ static void TstPrn_WriteIntAnsPrint (struct UsrData *UsrDat,
|
|||
if (sscanf (PrintedQuestion->StrAnswers,"%ld",&IntAnswerUsr) == 1)
|
||||
{
|
||||
HTM_TD_Begin ("class=\"%s CM\"",
|
||||
TstVis_IsVisibleCorrectAns (Visibility) ?
|
||||
IsVisible[TstVis_VISIBLE_CORRECT_ANSWER] ?
|
||||
(IntAnswerUsr == Question->Answer.Integer ? "ANS_OK" :
|
||||
"ANS_BAD") :
|
||||
"ANS_0");
|
||||
|
@ -958,8 +983,8 @@ static void TstPrn_WriteIntAnsPrint (struct UsrData *UsrDat,
|
|||
|
||||
/***** Write the correct answer *****/
|
||||
HTM_TD_Begin ("class=\"ANS_0 CM\"");
|
||||
if (TstVis_IsVisibleQstAndAnsTxt (Visibility) &&
|
||||
TstVis_IsVisibleCorrectAns (Visibility))
|
||||
if (IsVisible[TstVis_VISIBLE_QST_ANS_TXT] &&
|
||||
IsVisible[TstVis_VISIBLE_CORRECT_ANSWER])
|
||||
HTM_Long (Question->Answer.Integer);
|
||||
else
|
||||
Ico_PutIconNotVisible ();
|
||||
|
@ -977,7 +1002,7 @@ static void TstPrn_WriteIntAnsPrint (struct UsrData *UsrDat,
|
|||
static void TstPrn_WriteFltAnsPrint (struct UsrData *UsrDat,
|
||||
const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
const struct Tst_Question *Question,
|
||||
unsigned Visibility)
|
||||
bool IsVisible[TstVis_NUM_ITEMS_VISIBILITY])
|
||||
{
|
||||
double FloatAnsUsr = 0.0;
|
||||
|
||||
|
@ -999,7 +1024,7 @@ static void TstPrn_WriteFltAnsPrint (struct UsrData *UsrDat,
|
|||
FloatAnsUsr = Str_GetDoubleFromStr (PrintedQuestion->StrAnswers);
|
||||
// A bad formatted floating point answer will interpreted as 0.0
|
||||
HTM_TD_Begin ("class=\"%s CM\"",
|
||||
TstVis_IsVisibleCorrectAns (Visibility) ?
|
||||
IsVisible[TstVis_VISIBLE_CORRECT_ANSWER] ?
|
||||
((FloatAnsUsr >= Question->Answer.FloatingPoint[0] &&
|
||||
FloatAnsUsr <= Question->Answer.FloatingPoint[1]) ? "ANS_OK" :
|
||||
"ANS_BAD") :
|
||||
|
@ -1012,8 +1037,8 @@ static void TstPrn_WriteFltAnsPrint (struct UsrData *UsrDat,
|
|||
|
||||
/***** Write the correct answer *****/
|
||||
HTM_TD_Begin ("class=\"ANS_0 CM\"");
|
||||
if (TstVis_IsVisibleQstAndAnsTxt (Visibility) &&
|
||||
TstVis_IsVisibleCorrectAns (Visibility))
|
||||
if (IsVisible[TstVis_VISIBLE_QST_ANS_TXT] &&
|
||||
IsVisible[TstVis_VISIBLE_CORRECT_ANSWER])
|
||||
{
|
||||
HTM_Txt ("[");
|
||||
HTM_Double (Question->Answer.FloatingPoint[0]);
|
||||
|
@ -1037,7 +1062,7 @@ static void TstPrn_WriteFltAnsPrint (struct UsrData *UsrDat,
|
|||
static void TstPrn_WriteTF_AnsPrint (struct UsrData *UsrDat,
|
||||
const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
const struct Tst_Question *Question,
|
||||
unsigned Visibility)
|
||||
bool IsVisible[TstVis_NUM_ITEMS_VISIBILITY])
|
||||
{
|
||||
char AnsTFUsr;
|
||||
|
||||
|
@ -1057,7 +1082,7 @@ static void TstPrn_WriteTF_AnsPrint (struct UsrData *UsrDat,
|
|||
|
||||
/***** Write the user answer *****/
|
||||
HTM_TD_Begin ("class=\"%s CM\"",
|
||||
TstVis_IsVisibleCorrectAns (Visibility) ?
|
||||
IsVisible[TstVis_VISIBLE_CORRECT_ANSWER] ?
|
||||
(AnsTFUsr == Question->Answer.TF ? "ANS_OK" :
|
||||
"ANS_BAD") :
|
||||
"ANS_0");
|
||||
|
@ -1066,8 +1091,8 @@ static void TstPrn_WriteTF_AnsPrint (struct UsrData *UsrDat,
|
|||
|
||||
/***** Write the correct answer *****/
|
||||
HTM_TD_Begin ("class=\"ANS_0 CM\"");
|
||||
if (TstVis_IsVisibleQstAndAnsTxt (Visibility) &&
|
||||
TstVis_IsVisibleCorrectAns (Visibility))
|
||||
if (IsVisible[TstVis_VISIBLE_QST_ANS_TXT] &&
|
||||
IsVisible[TstVis_VISIBLE_CORRECT_ANSWER])
|
||||
Tst_WriteAnsTF (Question->Answer.TF);
|
||||
else
|
||||
Ico_PutIconNotVisible ();
|
||||
|
@ -1085,7 +1110,7 @@ static void TstPrn_WriteTF_AnsPrint (struct UsrData *UsrDat,
|
|||
static void TstPrn_WriteChoAnsPrint (struct UsrData *UsrDat,
|
||||
const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
const struct Tst_Question *Question,
|
||||
unsigned Visibility)
|
||||
bool IsVisible[TstVis_NUM_ITEMS_VISIBILITY])
|
||||
{
|
||||
extern const char *Txt_TST_Answer_given_by_the_user;
|
||||
extern const char *Txt_TST_Answer_given_by_the_teachers;
|
||||
|
@ -1098,6 +1123,26 @@ static void TstPrn_WriteChoAnsPrint (struct UsrData *UsrDat,
|
|||
char *Str;
|
||||
} Ans;
|
||||
|
||||
/***** Change format of answers text and feedback *****/
|
||||
for (NumOpt = 0;
|
||||
NumOpt < Question->Answer.NumOptions;
|
||||
NumOpt++)
|
||||
{
|
||||
/* Convert answer text, that is in HTML, to rigorous HTML */
|
||||
if (Question->Answer.Options[NumOpt].Text[0])
|
||||
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
||||
Question->Answer.Options[NumOpt].Text,
|
||||
Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false);
|
||||
|
||||
/* Convert answer feedback, that is in HTML, to rigorous HTML */
|
||||
if (IsVisible[TstVis_VISIBLE_FEEDBACK_TXT])
|
||||
if (Question->Answer.Options[NumOpt].Feedback)
|
||||
if (Question->Answer.Options[NumOpt].Feedback[0])
|
||||
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
||||
Question->Answer.Options[NumOpt].Feedback,
|
||||
Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false);
|
||||
}
|
||||
|
||||
/***** Get indexes for this question from string *****/
|
||||
TstPrn_GetIndexesFromStr (PrintedQuestion->StrIndexes,Indexes);
|
||||
|
||||
|
@ -1121,7 +1166,7 @@ static void TstPrn_WriteChoAnsPrint (struct UsrData *UsrDat,
|
|||
/* Draw icon depending on user's answer */
|
||||
if (UsrAnswers[Indexes[NumOpt]] == true) // This answer has been selected by the user
|
||||
{
|
||||
if (TstVis_IsVisibleCorrectAns (Visibility))
|
||||
if (IsVisible[TstVis_VISIBLE_CORRECT_ANSWER])
|
||||
{
|
||||
if (Question->Answer.Options[Indexes[NumOpt]].Correct)
|
||||
{
|
||||
|
@ -1149,7 +1194,7 @@ static void TstPrn_WriteChoAnsPrint (struct UsrData *UsrDat,
|
|||
HTM_TD_Empty (1);
|
||||
|
||||
/* Draw icon that indicates whether the answer is correct */
|
||||
if (TstVis_IsVisibleCorrectAns (Visibility))
|
||||
if (IsVisible[TstVis_VISIBLE_CORRECT_ANSWER])
|
||||
{
|
||||
if (Question->Answer.Options[Indexes[NumOpt]].Correct)
|
||||
{
|
||||
|
@ -1177,7 +1222,7 @@ static void TstPrn_WriteChoAnsPrint (struct UsrData *UsrDat,
|
|||
HTM_TD_Begin ("class=\"LT\"");
|
||||
|
||||
HTM_DIV_Begin ("class=\"ANS_TXT\"");
|
||||
if (TstVis_IsVisibleQstAndAnsTxt (Visibility))
|
||||
if (IsVisible[TstVis_VISIBLE_QST_ANS_TXT])
|
||||
{
|
||||
HTM_Txt (Question->Answer.Options[Indexes[NumOpt]].Text);
|
||||
Med_ShowMedia (&Question->Answer.Options[Indexes[NumOpt]].Media,
|
||||
|
@ -1188,7 +1233,7 @@ static void TstPrn_WriteChoAnsPrint (struct UsrData *UsrDat,
|
|||
Ico_PutIconNotVisible ();
|
||||
HTM_DIV_End ();
|
||||
|
||||
if (TstVis_IsVisibleCorrectAns (Visibility))
|
||||
if (IsVisible[TstVis_VISIBLE_CORRECT_ANSWER])
|
||||
if (Question->Answer.Options[Indexes[NumOpt]].Feedback)
|
||||
if (Question->Answer.Options[Indexes[NumOpt]].Feedback[0])
|
||||
{
|
||||
|
@ -1213,26 +1258,27 @@ static void TstPrn_WriteChoAnsPrint (struct UsrData *UsrDat,
|
|||
static void TstPrn_WriteTxtAnsPrint (struct UsrData *UsrDat,
|
||||
const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
const struct Tst_Question *Question,
|
||||
unsigned Visibility)
|
||||
bool IsVisible[TstVis_NUM_ITEMS_VISIBILITY])
|
||||
{
|
||||
unsigned NumOpt;
|
||||
char TextAnsUsr[Tst_MAX_BYTES_ANSWERS_ONE_QST + 1];
|
||||
char TextAnsOK[Tst_MAX_BYTES_ANSWERS_ONE_QST + 1];
|
||||
bool Correct = false;
|
||||
|
||||
/***** Get text and correctness of answers for this question from database (one row per answer) *****/
|
||||
/***** Change format of answers text and feedback *****/
|
||||
for (NumOpt = 0;
|
||||
NumOpt < Question->Answer.NumOptions;
|
||||
NumOpt++)
|
||||
{
|
||||
/***** Convert answer text, that is in HTML, to rigorous HTML ******/
|
||||
/* Convert answer text, that is in HTML, to rigorous HTML */
|
||||
if (Question->Answer.Options[NumOpt].Text[0])
|
||||
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
||||
Question->Answer.Options[NumOpt].Text,
|
||||
Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false);
|
||||
|
||||
/***** Convert answer feedback, that is in HTML, to rigorous HTML ******/
|
||||
if (TstVis_IsVisibleFeedbackTxt (Visibility))
|
||||
/* Convert answer feedback, that is in HTML, to rigorous HTML */
|
||||
if (IsVisible[TstVis_VISIBLE_FEEDBACK_TXT])
|
||||
if (Question->Answer.Options[NumOpt].Feedback)
|
||||
if (Question->Answer.Options[NumOpt].Feedback[0])
|
||||
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
||||
Question->Answer.Options[NumOpt].Feedback,
|
||||
|
@ -1277,8 +1323,7 @@ static void TstPrn_WriteTxtAnsPrint (struct UsrData *UsrDat,
|
|||
}
|
||||
}
|
||||
HTM_TD_Begin ("class=\"%s CT\"",
|
||||
TstVis_IsVisibleCorrectAns (Visibility) ?
|
||||
(Correct ? "ANS_OK" :
|
||||
IsVisible[TstVis_VISIBLE_CORRECT_ANSWER] ? (Correct ? "ANS_OK" :
|
||||
"ANS_BAD") :
|
||||
"ANS_0");
|
||||
HTM_Txt (PrintedQuestion->StrAnswers);
|
||||
|
@ -1288,8 +1333,8 @@ static void TstPrn_WriteTxtAnsPrint (struct UsrData *UsrDat,
|
|||
HTM_TD_End ();
|
||||
|
||||
/***** Write the correct answers *****/
|
||||
if (TstVis_IsVisibleQstAndAnsTxt (Visibility) &&
|
||||
TstVis_IsVisibleCorrectAns (Visibility))
|
||||
if (IsVisible[TstVis_VISIBLE_QST_ANS_TXT] &&
|
||||
IsVisible[TstVis_VISIBLE_CORRECT_ANSWER])
|
||||
{
|
||||
HTM_TD_Begin ("class=\"CT\"");
|
||||
HTM_TABLE_BeginPadding (2);
|
||||
|
@ -1312,7 +1357,7 @@ static void TstPrn_WriteTxtAnsPrint (struct UsrData *UsrDat,
|
|||
HTM_Txt (Question->Answer.Options[NumOpt].Text);
|
||||
HTM_DIV_End ();
|
||||
|
||||
if (TstVis_IsVisibleFeedbackTxt (Visibility))
|
||||
if (IsVisible[TstVis_VISIBLE_FEEDBACK_TXT])
|
||||
if (Question->Answer.Options[NumOpt].Feedback)
|
||||
if (Question->Answer.Options[NumOpt].Feedback[0])
|
||||
{
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "swad_test_config.h"
|
||||
#include "swad_test_type.h"
|
||||
#include "swad_test_visibility.h"
|
||||
#include "swad_user.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -46,7 +47,6 @@ struct TstPrn_PrintedQuestion
|
|||
char StrIndexes[Tst_MAX_BYTES_INDEXES_ONE_QST + 1]; // 0 1 2 3, 3 0 2 1, etc.
|
||||
char StrAnswers[Tst_MAX_BYTES_ANSWERS_ONE_QST + 1]; // Answers selected by user
|
||||
double Score; // Question score
|
||||
bool AnswerIsNotBlank; // Answer not blank?
|
||||
};
|
||||
|
||||
struct TstPrn_Print
|
||||
|
@ -103,7 +103,7 @@ void TstPrn_ShowGrade (double Grade,double MaxGrade);
|
|||
void TstPrn_WriteAnswersExam (struct UsrData *UsrDat,
|
||||
const struct TstPrn_PrintedQuestion *PrintedQuestion,
|
||||
const struct Tst_Question *Question,
|
||||
unsigned Visibility);
|
||||
bool IsVisible[TstVis_NUM_ITEMS_VISIBILITY]);
|
||||
|
||||
void TstPrn_SelUsrsToViewUsrsPrints (void);
|
||||
void TstPrn_SelDatesToSeeMyPrints (void);
|
||||
|
|
|
@ -10904,9 +10904,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] =
|
|||
#elif L==2 // de
|
||||
"" // Need Übersetzung
|
||||
#elif L==3 // en
|
||||
"See exam print"
|
||||
"Start / resume exam"
|
||||
#elif L==4 // es
|
||||
"Ver impresión de examen"
|
||||
"Comenzar / reanudar examen"
|
||||
#elif L==5 // fr
|
||||
"" // Besoin de traduction
|
||||
#elif L==6 // gn
|
||||
|
@ -10938,6 +10938,27 @@ const char *Txt_Actions[Act_NUM_ACTIONS] =
|
|||
"" // Potrzebujesz tlumaczenie
|
||||
#elif L==9 // pt
|
||||
"" // Precisa de tradução
|
||||
#endif
|
||||
,
|
||||
[ActEndExaPrn] =
|
||||
#if L==1 // ca
|
||||
"" // Necessita traducció
|
||||
#elif L==2 // de
|
||||
"" // Need Übersetzung
|
||||
#elif L==3 // en
|
||||
"End exam"
|
||||
#elif L==4 // es
|
||||
"Finalizar examen"
|
||||
#elif L==5 // fr
|
||||
"" // Besoin de traduction
|
||||
#elif L==6 // gn
|
||||
"" // Okoteve traducción
|
||||
#elif L==7 // it
|
||||
"" // Bisogno di traduzione
|
||||
#elif L==8 // pl
|
||||
"" // Potrzebujesz tlumaczenie
|
||||
#elif L==9 // pt
|
||||
"" // Precisa de tradução
|
||||
#endif
|
||||
,
|
||||
[ActSeeMyExaResCrs] =
|
||||
|
|
Loading…
Reference in New Issue
Block a user