diff --git a/sql/cambios.sql b/sql/cambios.sql index 794480c1..2f66076e 100644 --- a/sql/cambios.sql +++ b/sql/cambios.sql @@ -13157,4 +13157,110 @@ SELECT LogCod,ActCod,UNIX_TIMESTAMP()-UNIX_TIMESTAMP(ClickTime),Role,CtyCod,InsC + + + + + +----------------- + + +CREATE TABLE IF NOT EXISTS log ( + LogCod INT NOT NULL AUTO_INCREMENT, + ActCod INT NOT NULL DEFAULT -1, + CtyCod INT NOT NULL DEFAULT -1, + InsCod INT NOT NULL DEFAULT -1, + CtrCod INT NOT NULL DEFAULT -1, + DegCod INT NOT NULL DEFAULT -1, + CrsCod INT NOT NULL DEFAULT -1, + UsrCod INT NOT NULL DEFAULT -1, + Role TINYINT NOT NULL, + ClickTime DATETIME NOT NULL, + TimeToGenerate INT NOT NULL, + TimeToSend INT NOT NULL, + IP CHAR(15) NOT NULL, + PRIMARY KEY(LogCod,ClickTime), + INDEX(ActCod), + INDEX(CtyCod), + INDEX(InsCod), + INDEX(CtrCod), + INDEX(DegCod), + INDEX(CrsCod), + INDEX(UsrCod), + INDEX(ClickTime,Role) +) ENGINE=InnoDB +PARTITION BY RANGE (YEAR(ClickTime)) +( + PARTITION p2004 VALUES LESS THAN (2005), + PARTITION p2005 VALUES LESS THAN (2006), + PARTITION p2006 VALUES LESS THAN (2007), + PARTITION p2007 VALUES LESS THAN (2008), + PARTITION p2008 VALUES LESS THAN (2009), + PARTITION p2009 VALUES LESS THAN (2010), + PARTITION p2010 VALUES LESS THAN (2011), + PARTITION p2011 VALUES LESS THAN (2012), + PARTITION p2012 VALUES LESS THAN (2013), + PARTITION p2013 VALUES LESS THAN (2014), + PARTITION p2014 VALUES LESS THAN (2015), + PARTITION p2015 VALUES LESS THAN (2016), + PARTITION p2016 VALUES LESS THAN (2017), + PARTITION p2017 VALUES LESS THAN (2018), + PARTITION p2018 VALUES LESS THAN (2019), + PARTITION p2019 VALUES LESS THAN (2020), + PARTITION p2020 VALUES LESS THAN (2021), + PARTITION p2021 VALUES LESS THAN (2022), + PARTITION p2022 VALUES LESS THAN (2023), + PARTITION p2023 VALUES LESS THAN (2024), + PARTITION p2024 VALUES LESS THAN (2025), + PARTITION p2025 VALUES LESS THAN (2026), + PARTITION p2026 VALUES LESS THAN (2027), + PARTITION p2027 VALUES LESS THAN (2028), + PARTITION p2028 VALUES LESS THAN (2029), + PARTITION p2029 VALUES LESS THAN (2030), + PARTITION p2030 VALUES LESS THAN (2031), + PARTITION p2031 VALUES LESS THAN (2032), + PARTITION p2032 VALUES LESS THAN (2033), + PARTITION p2033 VALUES LESS THAN (2034), + PARTITION p2034 VALUES LESS THAN (2035), + PARTITION p2035 VALUES LESS THAN (2036), + PARTITION p2036 VALUES LESS THAN (2037), + PARTITION p2037 VALUES LESS THAN (2038), + PARTITION p2038 VALUES LESS THAN (2039), + PARTITION p2039 VALUES LESS THAN (2040), + PARTITION p2040 VALUES LESS THAN (2041), + PARTITION p2041 VALUES LESS THAN (2042), + PARTITION p2042 VALUES LESS THAN (2043), + PARTITION p2043 VALUES LESS THAN (2044), + PARTITION p2044 VALUES LESS THAN (2045), + PARTITION p2045 VALUES LESS THAN (2046), + PARTITION p2046 VALUES LESS THAN (2047), + PARTITION p2047 VALUES LESS THAN (2048), + PARTITION p2048 VALUES LESS THAN (2049), + PARTITION p2049 VALUES LESS THAN (2050), + PARTITION p2050 VALUES LESS THAN MAXVALUE +); + +INSERT INTO log SELECT * FROM log_full WHERE YEAR(ClickTime) < 2005; Hecho +INSERT INTO log SELECT * FROM log_full WHERE YEAR(ClickTime) = 2005; Hecho +INSERT INTO log SELECT * FROM log_full WHERE YEAR(ClickTime) = 2006; Hecho +INSERT INTO log SELECT * FROM log_full WHERE YEAR(ClickTime) = 2007; Hecho +INSERT INTO log SELECT * FROM log_full WHERE YEAR(ClickTime) = 2008; Hecho +INSERT INTO log SELECT * FROM log_full WHERE YEAR(ClickTime) = 2009; Hecho +INSERT INTO log SELECT * FROM log_full WHERE YEAR(ClickTime) = 2010; Hecho +INSERT INTO log SELECT * FROM log_full WHERE YEAR(ClickTime) = 2011; Hecho +INSERT INTO log SELECT * FROM log_full WHERE YEAR(ClickTime) = 2012; Hecho +INSERT INTO log SELECT * FROM log_full WHERE YEAR(ClickTime) = 2013; +INSERT INTO log SELECT * FROM log_full WHERE YEAR(ClickTime) = 2014; +INSERT INTO log SELECT * FROM log_full WHERE YEAR(ClickTime) = 2015; +INSERT INTO log SELECT * FROM log_full WHERE YEAR(ClickTime) = 2016; +INSERT INTO log SELECT * FROM log_full WHERE YEAR(ClickTime) = 2017; +INSERT INTO log SELECT * FROM log_full WHERE YEAR(ClickTime) = 2018; +INSERT INTO log SELECT * FROM log_full WHERE YEAR(ClickTime) = 2019; +# hasta aquí ya hecho en openswad.org, aún no en swad.ugr.es + +# Actualizar los últimos antes de dar el cambiazo: +INSERT INTO log SELECT * FROM log_full WHERE YEAR(ClickTime) = 2020; +INSERT INTO log SELECT * FROM log_full WHERE YEAR(ClickTime) > 2020; + + \ No newline at end of file diff --git a/sql/swad.sql b/sql/swad.sql index e775e516..c9463f43 100644 --- a/sql/swad.sql +++ b/sql/swad.sql @@ -1318,12 +1318,14 @@ CREATE TABLE IF NOT EXISTS tst_exams ( TstCod INT NOT NULL AUTO_INCREMENT, CrsCod INT NOT NULL, UsrCod INT NOT NULL, - AllowTeachers ENUM('N','Y') NOT NULL DEFAULT 'N', - TstTime DATETIME NOT NULL, + StartTime DATETIME NOT NULL, + EndTime DATETIME NOT NULL, NumQsts INT NOT NULL DEFAULT 0, NumQstsNotBlank INT NOT NULL DEFAULT 0, + AllowTeachers ENUM('N','Y') NOT NULL DEFAULT 'N', Score DOUBLE PRECISION NOT NULL DEFAULT 0, - UNIQUE INDEX(TstCod),INDEX(CrsCod,UsrCod)); + UNIQUE INDEX(TstCod), + INDEX(CrsCod,UsrCod)); -- -- Table tst_question_tags: stores the tags associated to each test question -- diff --git a/swad_action.c b/swad_action.c index 8d99d2a7..d46b04b1 100644 --- a/swad_action.c +++ b/swad_action.c @@ -627,6 +627,7 @@ const struct Act_Actions Act_Actions[Act_NUM_ACTIONS] = [ActDowAssPrj ] = {1734,-1,TabUnk,ActSeePrj ,0x238,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_DOWNLD_FILE,Brw_DownloadFile ,NULL ,NULL}, [ActSeeTst ] = { 29,-1,TabUnk,ActReqTst ,0x238,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Tst_ShowNewTest ,NULL}, + [ActReqAssTst ] = {1837,-1,TabUnk,ActReqTst ,0x238,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Tst_RequestAssessTest ,NULL}, [ActAssTst ] = { 98,-1,TabUnk,ActReqTst ,0x238,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Tst_AssessTest ,NULL}, [ActEdiTstQst ] = { 104,-1,TabUnk,ActReqTst ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,Dat_SetIniEndDates ,Tst_RequestEditTests ,NULL}, @@ -3568,6 +3569,7 @@ Act_Action_t Act_FromActCodToAction[1 + Act_MAX_ACTION_COD] = // Do not reuse un ActLftPrgItm, // #1834 ActReqRemSevTstQst, // #1835 ActRemSevTstQst, // #1836 + ActReqAssTst, // #1837 }; /*****************************************************************************/ diff --git a/swad_action.h b/swad_action.h index 72898c9e..464b6514 100644 --- a/swad_action.h +++ b/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 1836 +#define Act_MAX_ACTION_COD 1837 #define Act_MAX_OPTIONS_IN_MENU_PER_TAB 13 @@ -606,106 +606,107 @@ typedef signed int Act_Action_t; // Must be a signed type, because -1 is used to #define ActDowAssPrj (ActChgCrsTT1stDay + 96) #define ActSeeTst (ActChgCrsTT1stDay + 97) -#define ActAssTst (ActChgCrsTT1stDay + 98) -#define ActEdiTstQst (ActChgCrsTT1stDay + 99) -#define ActEdiOneTstQst (ActChgCrsTT1stDay + 100) -#define ActReqImpTstQst (ActChgCrsTT1stDay + 101) -#define ActImpTstQst (ActChgCrsTT1stDay + 102) -#define ActLstTstQst (ActChgCrsTT1stDay + 103) -#define ActRcvTstQst (ActChgCrsTT1stDay + 104) -#define ActReqRemSevTstQst (ActChgCrsTT1stDay + 105) -#define ActRemSevTstQst (ActChgCrsTT1stDay + 106) -#define ActReqRemOneTstQst (ActChgCrsTT1stDay + 107) -#define ActRemOneTstQst (ActChgCrsTT1stDay + 108) -#define ActChgShfTstQst (ActChgCrsTT1stDay + 109) -#define ActCfgTst (ActChgCrsTT1stDay + 110) -#define ActEnableTag (ActChgCrsTT1stDay + 111) -#define ActDisableTag (ActChgCrsTT1stDay + 112) -#define ActRenTag (ActChgCrsTT1stDay + 113) -#define ActRcvCfgTst (ActChgCrsTT1stDay + 114) +#define ActReqAssTst (ActChgCrsTT1stDay + 98) +#define ActAssTst (ActChgCrsTT1stDay + 99) +#define ActEdiTstQst (ActChgCrsTT1stDay + 100) +#define ActEdiOneTstQst (ActChgCrsTT1stDay + 101) +#define ActReqImpTstQst (ActChgCrsTT1stDay + 102) +#define ActImpTstQst (ActChgCrsTT1stDay + 103) +#define ActLstTstQst (ActChgCrsTT1stDay + 104) +#define ActRcvTstQst (ActChgCrsTT1stDay + 105) +#define ActReqRemSevTstQst (ActChgCrsTT1stDay + 106) +#define ActRemSevTstQst (ActChgCrsTT1stDay + 107) +#define ActReqRemOneTstQst (ActChgCrsTT1stDay + 108) +#define ActRemOneTstQst (ActChgCrsTT1stDay + 109) +#define ActChgShfTstQst (ActChgCrsTT1stDay + 110) +#define ActCfgTst (ActChgCrsTT1stDay + 111) +#define ActEnableTag (ActChgCrsTT1stDay + 112) +#define ActDisableTag (ActChgCrsTT1stDay + 113) +#define ActRenTag (ActChgCrsTT1stDay + 114) +#define ActRcvCfgTst (ActChgCrsTT1stDay + 115) -#define ActReqSeeMyTstRes (ActChgCrsTT1stDay + 115) -#define ActSeeMyTstRes (ActChgCrsTT1stDay + 116) -#define ActSeeOneTstResMe (ActChgCrsTT1stDay + 117) -#define ActReqSeeUsrTstRes (ActChgCrsTT1stDay + 118) -#define ActSeeUsrTstRes (ActChgCrsTT1stDay + 119) -#define ActSeeOneTstResOth (ActChgCrsTT1stDay + 120) +#define ActReqSeeMyTstRes (ActChgCrsTT1stDay + 116) +#define ActSeeMyTstRes (ActChgCrsTT1stDay + 117) +#define ActSeeOneTstResMe (ActChgCrsTT1stDay + 118) +#define ActReqSeeUsrTstRes (ActChgCrsTT1stDay + 119) +#define ActSeeUsrTstRes (ActChgCrsTT1stDay + 120) +#define ActSeeOneTstResOth (ActChgCrsTT1stDay + 121) -#define ActSeeGam (ActChgCrsTT1stDay + 121) -#define ActReqRemMch (ActChgCrsTT1stDay + 122) -#define ActRemMch (ActChgCrsTT1stDay + 123) -#define ActReqNewMch (ActChgCrsTT1stDay + 124) -#define ActNewMch (ActChgCrsTT1stDay + 125) -#define ActResMch (ActChgCrsTT1stDay + 126) -#define ActBckMch (ActChgCrsTT1stDay + 127) -#define ActPlyPauMch (ActChgCrsTT1stDay + 128) -#define ActFwdMch (ActChgCrsTT1stDay + 129) -#define ActChgNumColMch (ActChgCrsTT1stDay + 130) -#define ActChgVisResMchQst (ActChgCrsTT1stDay + 131) -#define ActMchCntDwn (ActChgCrsTT1stDay + 132) -#define ActRefMchTch (ActChgCrsTT1stDay + 133) +#define ActSeeGam (ActChgCrsTT1stDay + 122) +#define ActReqRemMch (ActChgCrsTT1stDay + 123) +#define ActRemMch (ActChgCrsTT1stDay + 124) +#define ActReqNewMch (ActChgCrsTT1stDay + 125) +#define ActNewMch (ActChgCrsTT1stDay + 126) +#define ActResMch (ActChgCrsTT1stDay + 127) +#define ActBckMch (ActChgCrsTT1stDay + 128) +#define ActPlyPauMch (ActChgCrsTT1stDay + 129) +#define ActFwdMch (ActChgCrsTT1stDay + 130) +#define ActChgNumColMch (ActChgCrsTT1stDay + 131) +#define ActChgVisResMchQst (ActChgCrsTT1stDay + 132) +#define ActMchCntDwn (ActChgCrsTT1stDay + 133) +#define ActRefMchTch (ActChgCrsTT1stDay + 134) -#define ActJoiMch (ActChgCrsTT1stDay + 134) -#define ActSeeMchAnsQstStd (ActChgCrsTT1stDay + 135) -#define ActRemMchAnsQstStd (ActChgCrsTT1stDay + 136) -#define ActAnsMchQstStd (ActChgCrsTT1stDay + 137) -#define ActRefMchStd (ActChgCrsTT1stDay + 138) +#define ActJoiMch (ActChgCrsTT1stDay + 135) +#define ActSeeMchAnsQstStd (ActChgCrsTT1stDay + 136) +#define ActRemMchAnsQstStd (ActChgCrsTT1stDay + 137) +#define ActAnsMchQstStd (ActChgCrsTT1stDay + 138) +#define ActRefMchStd (ActChgCrsTT1stDay + 139) -#define ActSeeMyMchResCrs (ActChgCrsTT1stDay + 139) -#define ActSeeMyMchResGam (ActChgCrsTT1stDay + 140) -#define ActSeeMyMchResMch (ActChgCrsTT1stDay + 141) -#define ActSeeOneMchResMe (ActChgCrsTT1stDay + 142) +#define ActSeeMyMchResCrs (ActChgCrsTT1stDay + 140) +#define ActSeeMyMchResGam (ActChgCrsTT1stDay + 141) +#define ActSeeMyMchResMch (ActChgCrsTT1stDay + 142) +#define ActSeeOneMchResMe (ActChgCrsTT1stDay + 143) -#define ActReqSeeAllMchRes (ActChgCrsTT1stDay + 143) -#define ActSeeAllMchResCrs (ActChgCrsTT1stDay + 144) -#define ActSeeAllMchResGam (ActChgCrsTT1stDay + 145) -#define ActSeeAllMchResMch (ActChgCrsTT1stDay + 146) -#define ActSeeOneMchResOth (ActChgCrsTT1stDay + 147) +#define ActReqSeeAllMchRes (ActChgCrsTT1stDay + 144) +#define ActSeeAllMchResCrs (ActChgCrsTT1stDay + 145) +#define ActSeeAllMchResGam (ActChgCrsTT1stDay + 146) +#define ActSeeAllMchResMch (ActChgCrsTT1stDay + 147) +#define ActSeeOneMchResOth (ActChgCrsTT1stDay + 148) -#define ActChgVisResMchUsr (ActChgCrsTT1stDay + 148) +#define ActChgVisResMchUsr (ActChgCrsTT1stDay + 149) -#define ActFrmNewGam (ActChgCrsTT1stDay + 149) -#define ActEdiOneGam (ActChgCrsTT1stDay + 150) -#define ActNewGam (ActChgCrsTT1stDay + 151) -#define ActChgGam (ActChgCrsTT1stDay + 152) -#define ActReqRemGam (ActChgCrsTT1stDay + 153) -#define ActRemGam (ActChgCrsTT1stDay + 154) -#define ActHidGam (ActChgCrsTT1stDay + 155) -#define ActShoGam (ActChgCrsTT1stDay + 156) -#define ActAddOneGamQst (ActChgCrsTT1stDay + 157) -#define ActGamLstTstQst (ActChgCrsTT1stDay + 158) -#define ActAddTstQstToGam (ActChgCrsTT1stDay + 159) -#define ActReqRemGamQst (ActChgCrsTT1stDay + 160) -#define ActRemGamQst (ActChgCrsTT1stDay + 161) -#define ActUp_GamQst (ActChgCrsTT1stDay + 162) -#define ActDwnGamQst (ActChgCrsTT1stDay + 163) +#define ActFrmNewGam (ActChgCrsTT1stDay + 150) +#define ActEdiOneGam (ActChgCrsTT1stDay + 151) +#define ActNewGam (ActChgCrsTT1stDay + 152) +#define ActChgGam (ActChgCrsTT1stDay + 153) +#define ActReqRemGam (ActChgCrsTT1stDay + 154) +#define ActRemGam (ActChgCrsTT1stDay + 155) +#define ActHidGam (ActChgCrsTT1stDay + 156) +#define ActShoGam (ActChgCrsTT1stDay + 157) +#define ActAddOneGamQst (ActChgCrsTT1stDay + 158) +#define ActGamLstTstQst (ActChgCrsTT1stDay + 159) +#define ActAddTstQstToGam (ActChgCrsTT1stDay + 160) +#define ActReqRemGamQst (ActChgCrsTT1stDay + 161) +#define ActRemGamQst (ActChgCrsTT1stDay + 162) +#define ActUp_GamQst (ActChgCrsTT1stDay + 163) +#define ActDwnGamQst (ActChgCrsTT1stDay + 164) -#define ActSeeSvy (ActChgCrsTT1stDay + 164) -#define ActAnsSvy (ActChgCrsTT1stDay + 165) -#define ActFrmNewSvy (ActChgCrsTT1stDay + 166) -#define ActEdiOneSvy (ActChgCrsTT1stDay + 167) -#define ActNewSvy (ActChgCrsTT1stDay + 168) -#define ActChgSvy (ActChgCrsTT1stDay + 169) -#define ActReqRemSvy (ActChgCrsTT1stDay + 170) -#define ActRemSvy (ActChgCrsTT1stDay + 171) -#define ActReqRstSvy (ActChgCrsTT1stDay + 172) -#define ActRstSvy (ActChgCrsTT1stDay + 173) -#define ActHidSvy (ActChgCrsTT1stDay + 174) -#define ActShoSvy (ActChgCrsTT1stDay + 175) -#define ActEdiOneSvyQst (ActChgCrsTT1stDay + 176) -#define ActRcvSvyQst (ActChgCrsTT1stDay + 177) -#define ActReqRemSvyQst (ActChgCrsTT1stDay + 178) -#define ActRemSvyQst (ActChgCrsTT1stDay + 179) +#define ActSeeSvy (ActChgCrsTT1stDay + 165) +#define ActAnsSvy (ActChgCrsTT1stDay + 166) +#define ActFrmNewSvy (ActChgCrsTT1stDay + 167) +#define ActEdiOneSvy (ActChgCrsTT1stDay + 168) +#define ActNewSvy (ActChgCrsTT1stDay + 169) +#define ActChgSvy (ActChgCrsTT1stDay + 170) +#define ActReqRemSvy (ActChgCrsTT1stDay + 171) +#define ActRemSvy (ActChgCrsTT1stDay + 172) +#define ActReqRstSvy (ActChgCrsTT1stDay + 173) +#define ActRstSvy (ActChgCrsTT1stDay + 174) +#define ActHidSvy (ActChgCrsTT1stDay + 175) +#define ActShoSvy (ActChgCrsTT1stDay + 176) +#define ActEdiOneSvyQst (ActChgCrsTT1stDay + 177) +#define ActRcvSvyQst (ActChgCrsTT1stDay + 178) +#define ActReqRemSvyQst (ActChgCrsTT1stDay + 179) +#define ActRemSvyQst (ActChgCrsTT1stDay + 180) -#define ActSeeOneExaAnn (ActChgCrsTT1stDay + 180) -#define ActSeeDatExaAnn (ActChgCrsTT1stDay + 181) -#define ActEdiExaAnn (ActChgCrsTT1stDay + 182) -#define ActRcvExaAnn (ActChgCrsTT1stDay + 183) -#define ActPrnExaAnn (ActChgCrsTT1stDay + 184) -#define ActReqRemExaAnn (ActChgCrsTT1stDay + 185) -#define ActRemExaAnn (ActChgCrsTT1stDay + 186) -#define ActHidExaAnn (ActChgCrsTT1stDay + 187) -#define ActShoExaAnn (ActChgCrsTT1stDay + 188) +#define ActSeeOneExaAnn (ActChgCrsTT1stDay + 181) +#define ActSeeDatExaAnn (ActChgCrsTT1stDay + 182) +#define ActEdiExaAnn (ActChgCrsTT1stDay + 183) +#define ActRcvExaAnn (ActChgCrsTT1stDay + 184) +#define ActPrnExaAnn (ActChgCrsTT1stDay + 185) +#define ActReqRemExaAnn (ActChgCrsTT1stDay + 186) +#define ActRemExaAnn (ActChgCrsTT1stDay + 187) +#define ActHidExaAnn (ActChgCrsTT1stDay + 188) +#define ActShoExaAnn (ActChgCrsTT1stDay + 189) /*****************************************************************************/ /******************************** Files tab **********************************/ diff --git a/swad_changelog.h b/swad_changelog.h index b359d4ab..bb97dd97 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -523,8 +523,19 @@ Param // TODO: Miguel Damas: al principio de los exámenes tendría que poner cuánto resta cada pregunta // TODO: Oresti Baños: cambiar ojos por candados en descriptores para prohibir/permitir y dejar los ojos para poder elegir descriptores // TODO: Si el alumno ha marcado "Permitir que los profesores...", entonces pedir confirmación al pulsar el botón azul, para evitar que se envíe por error antes de tiempo +// TODO: Tener en cuenta en los resultados de test (exámenes) el tiempo de inicio y el tiempo de fin + Cuando el alumno ve un test, se crea un examen (en la base de datos), aunque no se conteste, a partir de los datos del formulario. + El examen se muestra en pantalla tomándolo del examen en la base de datos, no del formulario. + Cuando el alumno pulsa en "He terminado" se le pregunta si está seguro y se vuelve a mostrar el examen cogiéndolo de la base de datos. -// TODO: URGENT: Fix bug while playing match. + Version 19.156: Mar 28, 2020 New action to confirm assessment of test exam. + Code refactoring in test and matches. (284544 lines) + 5 changes necessary in database: +ALTER TABLE tst_exams CHANGE COLUMN AllowTeachers AllowTeachers ENUM('N','Y') NOT NULL DEFAULT 'N' AFTER NumQstsNotBlank; +ALTER TABLE tst_exams CHANGE COLUMN TstTime StartTime DATETIME NOT NULL; +ALTER TABLE tst_exams ADD COLUMN EndTime DATETIME NOT NULL DEFAULT '1970-01-01 01:00:00' AFTER StartTime; +UPDATE tst_exams SET EndTime=StartTime; +ALTER TABLE tst_exams CHANGE COLUMN EndTime EndTime DATETIME NOT NULL; Version 19.155.6: Mar 26, 2020 Code refactoring in matches. (284479 lines) Version 19.155.5: Mar 26, 2020 Code refactoring in tests. (284480 lines) diff --git a/swad_database.c b/swad_database.c index 17423b5c..d7232b58 100644 --- a/swad_database.c +++ b/swad_database.c @@ -2795,22 +2795,24 @@ mysql> DESCRIBE tst_exams; | TstCod | int(11) | NO | PRI | NULL | auto_increment | | CrsCod | int(11) | NO | MUL | NULL | | | UsrCod | int(11) | NO | | NULL | | -| AllowTeachers | enum('N','Y') | NO | | N | | -| TstTime | datetime | NO | | NULL | | +| StartTime | datetime | NO | | NULL | | +| EndTime | datetime | NO | | NULL | | | NumQsts | int(11) | NO | | 0 | | | NumQstsNotBlank | int(11) | NO | | 0 | | +| AllowTeachers | enum('N','Y') | NO | | N | | | Score | double | NO | | 0 | | +-----------------+---------------+------+-----+---------+----------------+ -8 rows in set (0.05 sec) +9 rows in set (0.00 sec) */ DB_CreateTable ("CREATE TABLE IF NOT EXISTS tst_exams (" "TstCod INT NOT NULL AUTO_INCREMENT," "CrsCod INT NOT NULL," "UsrCod INT NOT NULL," - "AllowTeachers ENUM('N','Y') NOT NULL DEFAULT 'N'," - "TstTime DATETIME NOT NULL," + "StartTime DATETIME NOT NULL," + "EndTime DATETIME NOT NULL," "NumQsts INT NOT NULL DEFAULT 0," "NumQstsNotBlank INT NOT NULL DEFAULT 0," + "AllowTeachers ENUM('N','Y') NOT NULL DEFAULT 'N'," "Score DOUBLE PRECISION NOT NULL DEFAULT 0," "UNIQUE INDEX(TstCod)," "INDEX(CrsCod,UsrCod))"); diff --git a/swad_match_result.c b/swad_match_result.c index 6e5849ac..99c2fa02 100644 --- a/swad_match_result.c +++ b/swad_match_result.c @@ -95,7 +95,6 @@ static void McR_ShowMchResultsSummaryRow (unsigned NumResults, double TotalScoreOfAllResults, double TotalGrade); static void McR_GetMatchResultDataByMchCod (long MchCod,long UsrCod, - time_t TimeUTC[Dat_NUM_START_END_TIME], struct TsR_Result *Result); static bool McR_CheckIfICanSeeMatchResult (struct Match *Match,long UsrCod); @@ -1004,7 +1003,6 @@ void McR_ShowOneMchResult (void) struct Match Match; Usr_MeOrOther_t MeOrOther; struct UsrData *UsrDat; - time_t TimeUTC[Dat_NUM_START_END_TIME]; // Match result UTC date-time Dat_StartEndTime_t StartEndTime; char *Id; struct TsR_Result Result; @@ -1033,7 +1031,6 @@ void McR_ShowOneMchResult (void) /***** Get match result data *****/ McR_GetMatchResultDataByMchCod (Match.MchCod,UsrDat->UsrCod, - TimeUTC, &Result); /***** Check if I can view this match result *****/ @@ -1123,7 +1120,7 @@ void McR_ShowOneMchResult (void) if (asprintf (&Id,"match_%u",(unsigned) StartEndTime) < 0) Lay_NotEnoughMemoryExit (); HTM_TD_Begin ("id=\"%s\" class=\"DAT LT\"",Id); - Dat_WriteLocalDateHMSFromUTC (Id,TimeUTC[StartEndTime], + Dat_WriteLocalDateHMSFromUTC (Id,Result.TimeUTC[StartEndTime], Gbl.Prefs.DateFormat,Dat_SEPARATOR_COMMA, true,true,true,0x7); HTM_TD_End (); @@ -1195,8 +1192,7 @@ void McR_ShowOneMchResult (void) HTM_TR_End (); /***** Write answers and solutions *****/ - TsR_ShowTestResult (UsrDat,&Result,TimeUTC[Dat_START_TIME], - Game.Visibility); + TsR_ShowTestResult (UsrDat,&Result,Game.Visibility); /***** End table *****/ HTM_TABLE_End (); @@ -1293,7 +1289,6 @@ void McR_GetMatchResultQuestionsFromDB (long MchCod,long UsrCod, /*****************************************************************************/ static void McR_GetMatchResultDataByMchCod (long MchCod,long UsrCod, - time_t TimeUTC[Dat_NUM_START_END_TIME], struct TsR_Result *Result) { MYSQL_RES *mysql_res; @@ -1323,7 +1318,7 @@ static void McR_GetMatchResultDataByMchCod (long MchCod,long UsrCod, for (StartEndTime = (Dat_StartEndTime_t) 0; StartEndTime <= (Dat_StartEndTime_t) (Dat_NUM_START_END_TIME - 1); StartEndTime++) - TimeUTC[StartEndTime] = Dat_GetUNIXTimeFromStr (row[StartEndTime]); + Result->TimeUTC[StartEndTime] = Dat_GetUNIXTimeFromStr (row[StartEndTime]); /* Get number of questions (row[2]) */ if (sscanf (row[2],"%u",&Result->NumQsts) != 1) diff --git a/swad_test.c b/swad_test.c index 20990404..0e87c48d 100644 --- a/swad_test.c +++ b/swad_test.c @@ -564,6 +564,55 @@ void Tst_ShowNewTest (void) Tst_TstDestructor (&Test); } +/*****************************************************************************/ +/********************* Request the assessment of a test **********************/ +/*****************************************************************************/ + +void Tst_RequestAssessTest (void) + { + extern const char *Txt_The_test_X_has_already_been_assessed_previously; + extern const char *Txt_There_was_an_error_in_assessing_the_test_X; + unsigned NumTst; + // long TstCod = -1L; // Initialized to avoid warning + struct TsR_Result Result; + + /***** Read test configuration from database *****/ + TstCfg_GetConfigFromDB (); + + /***** Get number of this test from form *****/ + NumTst = Tst_GetAndCheckParamNumTst (); + + /****** Get test status in database for this session-course-num.test *****/ + switch (Tst_GetTstStatus (NumTst)) + { + case Tst_STATUS_SHOWN_BUT_NOT_ASSESSED: + /***** Get parameters from the form *****/ + /* Get questions and answers from form to assess a test */ + Tst_GetQuestionsAndAnswersFromForm (&Result); + + /***** Show question and button to send the test *****/ + /* Start alert */ + Ale_ShowAlertAndButton1 (Ale_INFO,"Por favor, revise el test antes de enviarlo"); + + /* Show test again */ + + + /* End alert */ + Ale_ShowAlertAndButton2 (ActAssTst,NULL,NULL, + NULL,NULL, + Btn_CONFIRM_BUTTON,"Enviar test"); + break; + case Tst_STATUS_ASSESSED: + Ale_ShowAlert (Ale_WARNING,Txt_The_test_X_has_already_been_assessed_previously, + NumTst); + break; + case Tst_STATUS_ERROR: + Ale_ShowAlert (Ale_WARNING,Txt_There_was_an_error_in_assessing_the_test_X, + NumTst); + break; + } + } + /*****************************************************************************/ /******************************** Assess a test ******************************/ /*****************************************************************************/ @@ -578,7 +627,6 @@ void Tst_AssessTest (void) extern const char *Txt_The_test_X_has_already_been_assessed_previously; extern const char *Txt_There_was_an_error_in_assessing_the_test_X; unsigned NumTst; - bool AllowTeachers; // Can teachers of this course see the test result? long TstCod = -1L; // Initialized to avoid warning struct TsR_Result Result; @@ -592,18 +640,12 @@ void Tst_AssessTest (void) switch (Tst_GetTstStatus (NumTst)) { case Tst_STATUS_SHOWN_BUT_NOT_ASSESSED: - /***** Get the parameters of the form *****/ - /* Get number of questions */ - Result.NumQsts = Tst_GetParamNumQsts (); - - /***** Get if test will be visible by teachers *****/ - AllowTeachers = Par_GetParToBool ("AllowTchs"); - - /***** Get questions and answers from form to assess a test *****/ + /***** Get parameters from the form *****/ + /* Get questions and answers from form to assess a test */ Tst_GetQuestionsAndAnswersFromForm (&Result); /***** Create new test in database to store the result *****/ - TstCod = TsR_CreateTestResultInDB (AllowTeachers,Result.NumQsts); + TstCod = TsR_CreateTestResultInDB (&Result); /***** Begin box *****/ Box_BoxBegin (NULL,Txt_Test_result, @@ -670,6 +712,9 @@ static void Tst_GetQuestionsAndAnswersFromForm (struct TsR_Result *Result) unsigned NumQst; char StrQstIndOrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Qstxx...x", "Indxx...x" or "Ansxx...x" + /***** Get number of questions *****/ + Result->NumQsts = Tst_GetParamNumQsts (); + /***** Get questions and answers *****/ for (NumQst = 0; NumQst < Result->NumQsts; @@ -677,25 +722,28 @@ static void Tst_GetQuestionsAndAnswersFromForm (struct TsR_Result *Result) { /* Get question code */ snprintf (StrQstIndOrAns,sizeof (StrQstIndOrAns), - "Qst%03u", + "Qst%010u", NumQst); if ((Result->QstCodes[NumQst] = Par_GetParToLong (StrQstIndOrAns)) <= 0) Lay_ShowErrorAndExit ("Code of question is missing."); /* Get indexes for this question */ snprintf (StrQstIndOrAns,sizeof (StrQstIndOrAns), - "Ind%03u", + "Ind%010u", NumQst); Par_GetParMultiToText (StrQstIndOrAns,Result->StrIndexes[NumQst], Tst_MAX_BYTES_INDEXES_ONE_QST); /* If choice ==> "0", "1", "2",... */ /* Get answers selected by user for this question */ snprintf (StrQstIndOrAns,sizeof (StrQstIndOrAns), - "Ans%03u", + "Ans%010u", NumQst); Par_GetParMultiToText (StrQstIndOrAns,Result->StrAnswers[NumQst], Tst_MAX_BYTES_ANSWERS_ONE_QST); /* If answer type == T/F ==> " ", "T", "F"; if choice ==> "0", "2",... */ } + + /***** Get if test result will be visible by teachers *****/ + Result->AllowTeachers = Par_GetParToBool ("AllowTchs"); } /*****************************************************************************/ @@ -3601,7 +3649,7 @@ static void Tst_WriteTFAnsViewTest (unsigned NumQst) /***** Write selector for the answer *****/ HTM_SELECT_Begin (false, - "name=\"Ans%03u\"",NumQst); + "name=\"Ans%010u\"",NumQst); HTM_OPTION (HTM_Type_STRING,"" ,true ,false," "); HTM_OPTION (HTM_Type_STRING,"T",false,false,"%s",Txt_TF_QST[0]); HTM_OPTION (HTM_Type_STRING,"F",false,false,"%s",Txt_TF_QST[1]); @@ -3741,8 +3789,7 @@ static void Tst_WriteChoiceAnsViewTest (unsigned NumQst, MYSQL_ROW row; unsigned Index; bool ErrorInIndex = false; - char ParamName[3 + 6 + 1]; - char StrAns[32]; + char StrQstIndOrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Qstxx...x", "Indxx...x" or "Ansxx...x" /***** Get answers of a question from database *****/ Tst_GetAnswersQst (Question,&mysql_res,Shuffle); @@ -3797,36 +3844,36 @@ static void Tst_WriteChoiceAnsViewTest (unsigned NumQst, /***** Write selectors and letter of this option *****/ HTM_TD_Begin ("class=\"LT\""); - snprintf (ParamName,sizeof (ParamName), - "Ind%03u", + snprintf (StrQstIndOrAns,sizeof (StrQstIndOrAns), + "Ind%010u", NumQst); - Par_PutHiddenParamUnsigned (NULL,ParamName,Index); - snprintf (StrAns,sizeof (StrAns), - "Ans%03u", + Par_PutHiddenParamUnsigned (NULL,StrQstIndOrAns,Index); + snprintf (StrQstIndOrAns,sizeof (StrQstIndOrAns), + "Ans%010u", NumQst); if (Question->Answer.Type == Tst_ANS_UNIQUE_CHOICE) - HTM_INPUT_RADIO (StrAns,false, - "id=\"Ans%06u_%u\" value=\"%u\"" - " onclick=\"selectUnselectRadio(this,this.form.Ans%03u,%u);\"", + HTM_INPUT_RADIO (StrQstIndOrAns,false, + "id=\"Ans%010u_%u\" value=\"%u\"" + " onclick=\"selectUnselectRadio(this,this.form.Ans%010u,%u);\"", NumQst,NumOpt, Index, NumQst,Question->Answer.NumOptions); else // Answer.Type == Tst_ANS_MULTIPLE_CHOICE - HTM_INPUT_CHECKBOX (StrAns,HTM_DONT_SUBMIT_ON_CHANGE, - "id=\"Ans%06u_%u\" value=\"%u\"", + HTM_INPUT_CHECKBOX (StrQstIndOrAns,HTM_DONT_SUBMIT_ON_CHANGE, + "id=\"Ans%010u_%u\" value=\"%u\"", NumQst,NumOpt, Index); HTM_TD_End (); HTM_TD_Begin ("class=\"LT\""); - HTM_LABEL_Begin ("for=\"Ans%06u_%u\" class=\"ANS_TXT\"",NumQst,NumOpt); + HTM_LABEL_Begin ("for=\"Ans%010u_%u\" class=\"ANS_TXT\"",NumQst,NumOpt); HTM_TxtF ("%c) ",'a' + (char) NumOpt); HTM_LABEL_End (); HTM_TD_End (); /***** Write the option text *****/ HTM_TD_Begin ("class=\"LT\""); - HTM_LABEL_Begin ("for=\"Ans%06u_%u\" class=\"ANS_TXT\"",NumQst,NumOpt); + HTM_LABEL_Begin ("for=\"Ans%010u_%u\" class=\"ANS_TXT\"",NumQst,NumOpt); HTM_Txt (Question->Answer.Options[NumOpt].Text); HTM_LABEL_End (); Med_ShowMedia (&Question->Answer.Options[NumOpt].Media, @@ -4200,13 +4247,13 @@ void Tst_ComputeScoreQst (const struct Tst_Question *Question, static void Tst_WriteTextAnsViewTest (unsigned NumQst) { - char StrAns[3 + 6 + 1]; + char StrQstIndOrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Qstxx...x", "Indxx...x" or "Ansxx...x" /***** Write input field for the answer *****/ - snprintf (StrAns,sizeof (StrAns), - "Ans%03u", + snprintf (StrQstIndOrAns,sizeof (StrQstIndOrAns), + "Ans%010u", NumQst); - HTM_INPUT_TEXT (StrAns,Tst_MAX_BYTES_ANSWERS_ONE_QST,"",false, + HTM_INPUT_TEXT (StrQstIndOrAns,Tst_MAX_BYTES_ANSWERS_ONE_QST,"",false, "size=\"40\""); } @@ -4416,13 +4463,13 @@ static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat, static void Tst_WriteIntAnsViewTest (unsigned NumQst) { - char StrAns[3 + 6 + 1]; + char StrQstIndOrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Qstxx...x", "Indxx...x" or "Ansxx...x" /***** Write input field for the answer *****/ - snprintf (StrAns,sizeof (StrAns), - "Ans%03u", + snprintf (StrQstIndOrAns,sizeof (StrQstIndOrAns), + "Ans%010u", NumQst); - HTM_INPUT_TEXT (StrAns,11,"",false, + HTM_INPUT_TEXT (StrQstIndOrAns,11,"",false, "size=\"11\""); } @@ -4546,13 +4593,13 @@ static void Tst_WriteIntAnsAssessTest (struct UsrData *UsrDat, static void Tst_WriteFloatAnsViewTest (unsigned NumQst) { - char StrAns[3 + 6 + 1]; + char StrQstIndOrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Qstxx...x", "Indxx...x" or "Ansxx...x" /***** Write input field for the answer *****/ - snprintf (StrAns,sizeof (StrAns), - "Ans%03u", + snprintf (StrQstIndOrAns,sizeof (StrQstIndOrAns), + "Ans%010u", NumQst); - HTM_INPUT_TEXT (StrAns,Tst_MAX_BYTES_FLOAT_ANSWER,"",false, + HTM_INPUT_TEXT (StrQstIndOrAns,Tst_MAX_BYTES_FLOAT_ANSWER,"",false, "size=\"11\""); } @@ -4736,12 +4783,12 @@ static void Tst_WriteScoreEnd (void) static void Tst_WriteParamQstCod (unsigned NumQst,long QstCod) { - char ParamName[3 + 6 + 1]; + char StrQstIndOrAns[3 + Cns_MAX_DECIMAL_DIGITS_UINT + 1]; // "Qstxx...x", "Indxx...x" or "Ansxx...x" - snprintf (ParamName,sizeof (ParamName), - "Qst%03u", + snprintf (StrQstIndOrAns,sizeof (StrQstIndOrAns), + "Qst%010u", NumQst); - Par_PutHiddenParamLong (NULL,ParamName,QstCod); + Par_PutHiddenParamLong (NULL,StrQstIndOrAns,QstCod); } /*****************************************************************************/ diff --git a/swad_test.h b/swad_test.h index da10b0db..f4004644 100644 --- a/swad_test.h +++ b/swad_test.h @@ -152,6 +152,7 @@ struct Tst_Stats void Tst_RequestTest (void); void Tst_ShowNewTest (void); +void Tst_RequestAssessTest (void); void Tst_AssessTest (void); void Tst_ComputeAndShowGrade (unsigned NumQsts,double Score,double MaxGrade); diff --git a/swad_test_result.c b/swad_test_result.c index dd4b7a0b..292ddb6c 100644 --- a/swad_test_result.c +++ b/swad_test_result.c @@ -86,10 +86,7 @@ static void TsR_ShowTestResultsSummaryRow (bool ItsMe, unsigned NumTotalQstsNotBlank, double TotalScoreOfAllTests); static void TsR_ShowTstTagsPresentInATestResult (long TstCod); -static void TsR_GetTestResultDataByTstCod (long TstCod, - bool *AllowTeachers, - time_t *TstTimeUTC, - struct TsR_Result *Result); +static void TsR_GetTestResultDataByTstCod (long TstCod,struct TsR_Result *Result); static void TsR_GetTestResultQuestionsFromDB (long TstCod,struct TsR_Result *Result); /*****************************************************************************/ @@ -174,20 +171,20 @@ void TsR_ShowMyTstResults (void) /********************* Store test result in database *************************/ /*****************************************************************************/ -long TsR_CreateTestResultInDB (bool AllowTeachers,unsigned NumQsts) +long TsR_CreateTestResultInDB (const struct TsR_Result *Result) { /***** Insert new test result into table *****/ return DB_QueryINSERTandReturnCode ("can not create new test result", "INSERT INTO tst_exams" - " (CrsCod,UsrCod,AllowTeachers,TstTime,NumQsts)" + " (CrsCod,UsrCod,StartTime,EndTime,NumQsts,AllowTeachers)" " VALUES" - " (%ld,%ld,'%c',NOW(),%u)", + " (%ld,%ld,NOW(),NOW(),%u,'%c')", Gbl.Hierarchy.Crs.CrsCod, Gbl.Usrs.Me.UsrDat.UsrCod, - AllowTeachers ? 'Y' : - 'N', - NumQsts); + Result->NumQsts, + Result->AllowTeachers ? 'Y' : + 'N'); } /*****************************************************************************/ @@ -199,7 +196,7 @@ void TsR_StoreScoreOfTestResultInDB (long TstCod, { /***** Update score in test result *****/ Str_SetDecimalPointToUS (); // To print the floating point as a dot - DB_QueryUPDATE ("can not update result of test result", + DB_QueryUPDATE ("can not update test result", "UPDATE tst_exams" " SET NumQstsNotBlank=%u," "Score='%.15lg'" @@ -304,29 +301,26 @@ static void TsR_ShowTstResults (struct UsrData *UsrDat) static unsigned UniqueId = 0; char *Id; long TstCod; - unsigned NumQstsInThisTest; - unsigned NumQstsNotBlankInThisTest; + struct TsR_Result Result; unsigned NumTotalQsts = 0; unsigned NumTotalQstsNotBlank = 0; - double ScoreInThisTest; double TotalScoreOfAllTests = 0.0; unsigned NumExamsVisibleByTchs = 0; - bool AllowTeachers; // Can teachers of this course see the test result? bool ItsMe = Usr_ItsMe (UsrDat->UsrCod); bool ICanViewTest; bool ICanViewScore; - time_t TimeUTC; char *ClassDat; /***** Make database query *****/ NumExams = (unsigned) DB_QuerySELECT (&mysql_res,"can not get test exams of a user", - "SELECT TstCod," // row[0] - "AllowTeachers," // row[1] - "UNIX_TIMESTAMP(TstTime)," // row[2] - "NumQsts," // row[3] - "NumQstsNotBlank," // row[4] - "Score" // row[5] + "SELECT TstCod," // row[0] + "UNIX_TIMESTAMP(StartTime)," // row[1] + "UNIX_TIMESTAMP(EndTime)," // row[2] + "NumQsts," // row[3] + "NumQstsNotBlank," // row[4] + "AllowTeachers," // row[5] + "Score" // row[6] " FROM tst_exams" " WHERE CrsCod=%ld AND UsrCod=%ld" " AND TstTime>=FROM_UNIXTIME(%ld)" @@ -354,10 +348,10 @@ static void TsR_ShowTstResults (struct UsrData *UsrDat) if ((TstCod = Str_ConvertStrCodToLongCod (row[0])) < 0) Lay_ShowErrorAndExit ("Wrong code of test result."); - /* Get if teachers are allowed to see this test result (row[1]) */ - AllowTeachers = (row[1][0] == 'Y'); - ClassDat = AllowTeachers ? "DAT" : - "DAT_LIGHT"; + /* Get if teachers are allowed to see this test result (row[5]) */ + Result.AllowTeachers = (row[5][0] == 'Y'); + ClassDat = Result.AllowTeachers ? "DAT" : + "DAT_LIGHT"; switch (Gbl.Usrs.Me.Role.Logged) { @@ -373,7 +367,7 @@ static void TsR_ShowTstResults (struct UsrData *UsrDat) case Rol_INS_ADM: ICanViewTest = ICanViewScore = ItsMe || - AllowTeachers; + Result.AllowTeachers; break; case Rol_SYS_ADM: ICanViewTest = @@ -388,70 +382,71 @@ static void TsR_ShowTstResults (struct UsrData *UsrDat) if (NumTest) HTM_TR_Begin (NULL); - /* Write date and time (row[2] holds UTC date-time) */ - TimeUTC = Dat_GetUNIXTimeFromStr (row[2]); + /* Write date and time (row[1] and row[2] hold UTC date-times) */ + Result.TimeUTC[Dat_START_TIME] = Dat_GetUNIXTimeFromStr (row[1]); + Result.TimeUTC[Dat_END_TIME ] = Dat_GetUNIXTimeFromStr (row[2]); UniqueId++; if (asprintf (&Id,"tst_date_%u",UniqueId) < 0) Lay_NotEnoughMemoryExit (); HTM_TD_Begin ("id=\"%s\" class=\"%s RT COLOR%u\"", Id,ClassDat,Gbl.RowEvenOdd); - Dat_WriteLocalDateHMSFromUTC (Id,TimeUTC, + Dat_WriteLocalDateHMSFromUTC (Id,Result.TimeUTC[Dat_END_TIME], Gbl.Prefs.DateFormat,Dat_SEPARATOR_COMMA, true,true,false,0x7); HTM_TD_End (); free (Id); /* Get number of questions (row[3]) */ - if (sscanf (row[3],"%u",&NumQstsInThisTest) != 1) - NumQstsInThisTest = 0; - if (AllowTeachers) - NumTotalQsts += NumQstsInThisTest; + if (sscanf (row[3],"%u",&Result.NumQsts) != 1) + Result.NumQsts = 0; + if (Result.AllowTeachers) + NumTotalQsts += Result.NumQsts; /* Get number of questions not blank (row[4]) */ - if (sscanf (row[4],"%u",&NumQstsNotBlankInThisTest) != 1) - NumQstsNotBlankInThisTest = 0; - if (AllowTeachers) - NumTotalQstsNotBlank += NumQstsNotBlankInThisTest; + if (sscanf (row[4],"%u",&Result.NumQstsNotBlank) != 1) + Result.NumQstsNotBlank = 0; + if (Result.AllowTeachers) + NumTotalQstsNotBlank += Result.NumQstsNotBlank; - /* Get score (row[5]) */ - Str_SetDecimalPointToUS (); // To get the decimal point as a dot - if (sscanf (row[5],"%lf",&ScoreInThisTest) != 1) - ScoreInThisTest = 0.0; + /* Get score (row[6]) */ + Str_SetDecimalPointToUS (); // To get the decimal point as a dot + if (sscanf (row[6],"%lf",&Result.Score) != 1) + Result.Score = 0.0; Str_SetDecimalPointToLocal (); // Return to local system - if (AllowTeachers) - TotalScoreOfAllTests += ScoreInThisTest; + if (Result.AllowTeachers) + TotalScoreOfAllTests += Result.Score; /* Write number of questions */ HTM_TD_Begin ("class=\"%s RT COLOR%u\"",ClassDat,Gbl.RowEvenOdd); if (ICanViewTest) - HTM_Unsigned (NumQstsInThisTest); + HTM_Unsigned (Result.NumQsts); HTM_TD_End (); /* Write number of questions not blank */ HTM_TD_Begin ("class=\"%s RT COLOR%u\"",ClassDat,Gbl.RowEvenOdd); if (ICanViewTest) - HTM_Unsigned (NumQstsNotBlankInThisTest); + HTM_Unsigned (Result.NumQstsNotBlank); HTM_TD_End (); /* Write score */ HTM_TD_Begin ("class=\"%s RT COLOR%u\"",ClassDat,Gbl.RowEvenOdd); if (ICanViewScore) - HTM_Double2Decimals (ScoreInThisTest); + HTM_Double2Decimals (Result.Score); HTM_TD_End (); /* Write average score per question */ HTM_TD_Begin ("class=\"%s RT COLOR%u\"",ClassDat,Gbl.RowEvenOdd); if (ICanViewScore) - HTM_Double2Decimals (NumQstsInThisTest ? ScoreInThisTest / - (double) NumQstsInThisTest : - 0.0); + HTM_Double2Decimals (Result.NumQsts ? Result.Score / + (double) Result.NumQsts : + 0.0); HTM_TD_End (); /* Write grade */ HTM_TD_Begin ("class=\"%s RT COLOR%u\"",ClassDat,Gbl.RowEvenOdd); if (ICanViewScore) - Tst_ComputeAndShowGrade (NumQstsInThisTest, - ScoreInThisTest, + Tst_ComputeAndShowGrade (Result.NumQsts, + Result.Score, TsR_SCORE_MAX); HTM_TD_End (); @@ -468,7 +463,7 @@ static void TsR_ShowTstResults (struct UsrData *UsrDat) HTM_TD_End (); HTM_TR_End (); - if (AllowTeachers) + if (Result.AllowTeachers) NumExamsVisibleByTchs++; } @@ -610,8 +605,6 @@ void TsR_ShowOneTstResult (void) extern const char *Txt_Grade; extern const char *Txt_Tags; long TstCod; - bool AllowTeachers = false; // Initialized to avoid warning - time_t TstTimeUTC = 0; // Test result UTC date-time, initialized to avoid warning struct TsR_Result Result; bool ShowPhoto; char PhotoURL[PATH_MAX + 1]; @@ -624,10 +617,7 @@ void TsR_ShowOneTstResult (void) Lay_ShowErrorAndExit ("Code of test is missing."); /***** Get test result data *****/ - TsR_GetTestResultDataByTstCod (TstCod, - &AllowTeachers, - &TstTimeUTC, - &Result); + TsR_GetTestResultDataByTstCod (TstCod,&Result); TstCfg_SetConfigVisibility (TsV_MAX_VISIBILITY); /***** Check if I can view this test result *****/ @@ -657,7 +647,7 @@ void TsR_ShowOneTstResult (void) case ActSeeOneTstResOth: ICanViewTest = ICanViewScore = ItsMe || - AllowTeachers; + Result.AllowTeachers; break; default: ICanViewTest = @@ -730,7 +720,7 @@ void TsR_ShowOneTstResult (void) HTM_TD_End (); HTM_TD_Begin ("id=\"test\" class=\"DAT LT\""); - Dat_WriteLocalDateHMSFromUTC ("test",TstTimeUTC, + Dat_WriteLocalDateHMSFromUTC ("test",Result.TimeUTC[Dat_END_TIME], Gbl.Prefs.DateFormat,Dat_SEPARATOR_COMMA, true,true,true,0x7); HTM_TD_End (); @@ -800,7 +790,6 @@ void TsR_ShowOneTstResult (void) /***** Write answers and solutions *****/ TsR_ShowTestResult (&Gbl.Usrs.Other.UsrDat, &Result, - TstTimeUTC, TstCfg_GetConfigVisibility ()); /***** End table *****/ @@ -862,7 +851,6 @@ static void TsR_ShowTstTagsPresentInATestResult (long TstCod) void TsR_ShowTestResult (struct UsrData *UsrDat, const struct TsR_Result *Result, - time_t TstTimeUTC, unsigned Visibility) { extern const char *Txt_Question_modified; @@ -891,7 +879,7 @@ void TsR_ShowTestResult (struct UsrData *UsrDat, ==> don't show question ****/ EditTimeUTC = Dat_GetUNIXTimeFromStr (row[0]); ThisQuestionHasBeenEdited = false; - if (EditTimeUTC > TstTimeUTC) + if (EditTimeUTC > Result->TimeUTC[Dat_START_TIME]) ThisQuestionHasBeenEdited = true; if (ThisQuestionHasBeenEdited) @@ -944,10 +932,7 @@ void TsR_ShowTestResult (struct UsrData *UsrDat, /********* Get data of a test result using its test result code **************/ /*****************************************************************************/ -static void TsR_GetTestResultDataByTstCod (long TstCod, - bool *AllowTeachers, - time_t *TstTimeUTC, - struct TsR_Result *Result) +static void TsR_GetTestResultDataByTstCod (long TstCod,struct TsR_Result *Result) { MYSQL_RES *mysql_res; MYSQL_ROW row; @@ -956,11 +941,12 @@ static void TsR_GetTestResultDataByTstCod (long TstCod, if (DB_QuerySELECT (&mysql_res,"can not get data" " of a test result of a user", "SELECT UsrCod," // row[0] - "AllowTeachers," // row[1] - "UNIX_TIMESTAMP(TstTime)," // row[2] + "UNIX_TIMESTAMP(StartTime)," // row[1] + "UNIX_TIMESTAMP(EndTime)," // row[2] "NumQsts," // row[3] "NumQstsNotBlank," // row[4] - "Score" // row[5] + "AllowTeachers," // row[5] + "Score" // row[6] " FROM tst_exams" " WHERE TstCod=%ld AND CrsCod=%ld", TstCod, @@ -971,11 +957,9 @@ static void TsR_GetTestResultDataByTstCod (long TstCod, /* Get user code (row[0]) */ Gbl.Usrs.Other.UsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[0]); - /* Get if teachers are allowed to see this test result (row[1]) */ - *AllowTeachers = (row[1][0] == 'Y'); - - /* Get date-time (row[2] holds UTC date-time) */ - *TstTimeUTC = Dat_GetUNIXTimeFromStr (row[2]); + /* Get date-time (row[1] and row[2] hold UTC date-time) */ + Result->TimeUTC[Dat_START_TIME] = Dat_GetUNIXTimeFromStr (row[1]); + Result->TimeUTC[Dat_END_TIME ] = Dat_GetUNIXTimeFromStr (row[2]); /* Get number of questions (row[3]) */ if (sscanf (row[3],"%u",&Result->NumQsts) != 1) @@ -985,17 +969,23 @@ static void TsR_GetTestResultDataByTstCod (long TstCod, if (sscanf (row[4],"%u",&Result->NumQstsNotBlank) != 1) Result->NumQstsNotBlank = 0; - /* Get score (row[5]) */ + /* Get if teachers are allowed to see this test result (row[5]) */ + Result->AllowTeachers = (row[5][0] == 'Y'); + + /* Get score (row[6]) */ Str_SetDecimalPointToUS (); // To get the decimal point as a dot - if (sscanf (row[5],"%lf",&Result->Score) != 1) + if (sscanf (row[6],"%lf",&Result->Score) != 1) Result->Score = 0.0; Str_SetDecimalPointToLocal (); // Return to local system } else { - Result->NumQsts = 0; - Result->NumQstsNotBlank = 0; - Result->Score = 0.0; + Result->TimeUTC[Dat_START_TIME] = + Result->TimeUTC[Dat_END_TIME ] = 0; + Result->NumQsts = 0; + Result->NumQstsNotBlank = 0; + Result->AllowTeachers = false; + Result->Score = 0.0; } /***** Free structure that stores the query result *****/ @@ -1051,7 +1041,8 @@ static void TsR_GetTestResultQuestionsFromDB (long TstCod,struct TsR_Result *Res "Indexes," // row[1] "Answers" // row[2] " FROM tst_exam_questions" - " WHERE TstCod=%ld ORDER BY QstInd", + " WHERE TstCod=%ld" + " ORDER BY QstInd", TstCod); /***** Get questions codes *****/ diff --git a/swad_test_result.h b/swad_test_result.h index d7e56ffb..0bea442a 100644 --- a/swad_test_result.h +++ b/swad_test_result.h @@ -45,14 +45,16 @@ struct TsR_Result { + time_t TimeUTC[Dat_NUM_START_END_TIME]; unsigned NumQsts; unsigned NumQstsNotBlank; - double Score; long QstCodes[TstCfg_MAX_QUESTIONS_PER_TEST]; // Codes of the sent/received questions in a test char StrIndexes[TstCfg_MAX_QUESTIONS_PER_TEST] [Tst_MAX_BYTES_INDEXES_ONE_QST + 1]; // 0 1 2 3, 3 0 2 1, etc. char StrAnswers[TstCfg_MAX_QUESTIONS_PER_TEST] [Tst_MAX_BYTES_ANSWERS_ONE_QST + 1]; // Answers selected by user + bool AllowTeachers; // Are teachers allowed to see this test result? + double Score; // Total score of the test result }; /*****************************************************************************/ @@ -62,14 +64,13 @@ struct TsR_Result void TsR_SelUsrsToViewUsrsTstResults (void); void TsR_SelDatesToSeeMyTstResults (void); void TsR_ShowMyTstResults (void); -long TsR_CreateTestResultInDB (bool AllowTeachers,unsigned NumQsts); +long TsR_CreateTestResultInDB (const struct TsR_Result *Result); void TsR_StoreScoreOfTestResultInDB (long TstCod, const struct TsR_Result *Result); void TsR_GetUsrsAndShowTstResults (void); void TsR_ShowOneTstResult (void); void TsR_ShowTestResult (struct UsrData *UsrDat, const struct TsR_Result *Result, - time_t TstTimeUTC, unsigned Visibility); void TsR_StoreOneTestResultQstInDB (long TstCod, const struct TsR_Result *Result, diff --git a/swad_text_action.c b/swad_text_action.c index c513a319..b55400f2 100644 --- a/swad_text_action.c +++ b/swad_text_action.c @@ -9350,9 +9350,30 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "Show the seft-assessment test" + "See a test" #elif L==4 // es - "" + "Ver un test" +#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 + , + [ActReqAssTst] = +#if L==1 // ca + "" // Necessita traducció +#elif L==2 // de + "" // Need Übersetzung +#elif L==3 // en + "Request assessment of a test" +#elif L==4 // es + "Solicitar evaluación de un test" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9371,9 +9392,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "Assess a self-assessment test" + "Assess a test" #elif L==4 // es - "" + "Evaluar un test" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9392,9 +9413,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "Request the edition of self-assessment questions" + "Request the edition of test questions" #elif L==4 // es - "" + "Solicitar la edición de preguntas de test" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9413,9 +9434,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "Edit one self-assesment test question" + "Edit a test question" #elif L==4 // es - "" + "Editar una pregunta de test" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9434,9 +9455,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "Put form to ask for an XML with test questions to import" + "Request an XML file with test questions to import" #elif L==4 // es - "" + "Solicitar un archivo XML con preguntas de test para importar" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9457,7 +9478,7 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==3 // en "Import test questions from XML file" #elif L==4 // es - "" + "Importar preguntas de test de un archivo XML" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9476,9 +9497,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "List for edition several self-assessment test questions" + "List test questions for edition" #elif L==4 // es - "" + "Listar preguntas de test para edición" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9497,9 +9518,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "Receive a question of self-assessment" + "Create/Modify a test question" #elif L==4 // es - "" + "Crear/Modificar una pregunta de test" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9602,9 +9623,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "Change shuffle of of a question of self-assessment" + "Change shuffle of a test question" #elif L==4 // es - "" + "Cambiar baraje de una pregunta de test" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9623,9 +9644,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "Request renaming of tags of questions of self-assesment" + "See test configuration" #elif L==4 // es - "" + "Ver configuración de test" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9644,9 +9665,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "Enable a tag" + "Enable a test tag" #elif L==4 // es - "" + "Habilitar un descriptor de test" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9665,9 +9686,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "Disable a tag" + "Disable a test tag" #elif L==4 // es - "" + "Inhabilitar un descriptor de test" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9686,9 +9707,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "Rename a tag" + "Rename a test tag" #elif L==4 // es - "" + "Renombrar un descriptor de test" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9707,9 +9728,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "Receive configuration of test" + "Modify test configuration" #elif L==4 // es - "" + "Modificar configuración de test" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9728,9 +9749,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "Select range of dates to see my test results" + "Request to see my test results" #elif L==4 // es - "" + "Solicitar ver mis resultados de test" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9749,9 +9770,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "Show my test results" + "See my test results" #elif L==4 // es - "" + "Ver mis resultados de test" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9770,9 +9791,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "Select users and range of dates to see test results" + "See one of my test results" #elif L==4 // es - "" + "Ver uno de mis resultados de test" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9791,9 +9812,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "Show test results of several users" + "Request test results of several users" #elif L==4 // es - "" + "Solicitar resultados de test de varios usuarios" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9812,9 +9833,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "Show one test result of me as student" + "See test results of several users" #elif L==4 // es - "" + "Ver resultados de test de varios usuarios" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9833,9 +9854,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "Show one test result of other user" + "See one test result of another user" #elif L==4 // es - "" + "Ver un resultado de test de otro usuario" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9854,9 +9875,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "Show one game" + "See a game" #elif L==4 // es - "" + "Ver un juego" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9877,7 +9898,7 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==3 // en "Request the removal of a match" #elif L==4 // es - "" + "Solicitar eliminación de una partida" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9898,7 +9919,7 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==3 // en "Confirm the removal of a match" #elif L==4 // es - "" + "Confirmar la eliminación de una partida" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9917,9 +9938,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "Put form to create a new match" + "Request the creation of a new match" #elif L==4 // es - "" + "Solicitar la creación de una nueva partida" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9938,9 +9959,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "Create a new match showing first question in a new browser tab" + "Create a new match show it in a new tab" #elif L==4 // es - "" + "Crear una nueva partida y mostrarla en una nueva pestaña" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9959,9 +9980,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "Resume an unfinished match showing current question in a new browser tab" + "Resume a match showing current question in a new tab" #elif L==4 // es - "" + "Reanudar una partida mostrando la pregunta actual en una nueva pestaña" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -9982,7 +10003,7 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==3 // en "Go back when playing a match" #elif L==4 // es - "" + "Ir atrás mientras se juega una partida" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -10003,7 +10024,7 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==3 // en "Play/pause current match" #elif L==4 // es - "" + "Jugar/pausar partida actual" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -10024,7 +10045,7 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==3 // en "Go forward when playing a match" #elif L==4 // es - "" + "Ir adelante mientras se juega una partida" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -10045,7 +10066,7 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==3 // en "Change number of columns when playing a match" #elif L==4 // es - "" + "Cambiar número de columnas mientras se juega una partida" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -10066,7 +10087,7 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==3 // en "Change visibility of question results when playing a match" #elif L==4 // es - "" + "Cambiar visibilidad de los resultados de una pregunta mientras se juega una partida" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -10087,7 +10108,7 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==3 // en "Start match countdown" #elif L==4 // es - "" + "Comenzar la cuenta atrás en una partida" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -10108,7 +10129,7 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==3 // en "Refresh current question when playing a match (as teacher)" #elif L==4 // es - "" + "Refrescar pregunta actual mientras se juega una partida (como profesor)" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -10129,7 +10150,7 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==3 // en "Show current question when playing a game (as student)" #elif L==4 // es - "" + "Refrescar pregunta actual mientras se juega una partida (como estudiante)" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -10148,9 +10169,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "View my answer to a match question (as student)" + "View my answer to a match question" #elif L==4 // es - "" + "Ver mi respuesta a una pregunta en una partida" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -10169,9 +10190,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "Remove my answer to a match question (as student)" + "Remove my answer to a match question" #elif L==4 // es - "" + "Eliminar mi respuesta a una pregunta de una partida" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn @@ -10190,9 +10211,9 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = #elif L==2 // de "" // Need Übersetzung #elif L==3 // en - "Answer a match question (as student)" + "Answer a match question" #elif L==4 // es - "" + "Responder una pregunta de una partida" #elif L==5 // fr "" // Besoin de traduction #elif L==6 // gn