Version19.151

This commit is contained in:
acanas 2020-03-21 15:41:25 +01:00
parent 919ab2eeeb
commit 71aa5870b4
16 changed files with 921 additions and 526 deletions

View File

@ -57,7 +57,8 @@ OBJS = swad_account.o swad_action.o swad_agenda.o swad_alert.o \
swad_scope.o swad_search.o swad_session.o swad_setting.o \
swad_statistic.o swad_string.o swad_survey.o swad_syllabus.o \
swad_system_config.o \
swad_tab.o swad_test.o swad_test_import.o swad_test_result.o \
swad_tab.o swad_test.o swad_test_config.o swad_test_import.o \
swad_test_result.o \
swad_test_visibility.o swad_theme.o swad_timeline.o swad_timetable.o \
swad_user.o \
swad_xml.o \

View File

@ -113,6 +113,7 @@ cp -f /home/acanas/swad/swad/swad /var/www/cgi-bin/
#include "swad_notification.h"
#include "swad_password.h"
#include "swad_search.h"
#include "swad_test_config.h"
#include "swad_test_visibility.h"
#include "swad_user.h"
#include "swad_xml.h"
@ -4009,28 +4010,28 @@ int swad__getTestConfig (struct soap *soap,
/***** Get test configuration *****/
if ((ReturnCode = API_GetTstConfig ((long) courseCode)) != SOAP_OK)
return ReturnCode;
getTestConfigOut->pluggable = (Gbl.Test.Config.Pluggable == Tst_PLUGGABLE_YES) ? 1 :
0;
getTestConfigOut->minQuestions = (int) Gbl.Test.Config.Min;
getTestConfigOut->defQuestions = (int) Gbl.Test.Config.Def;
getTestConfigOut->maxQuestions = (int) Gbl.Test.Config.Max;
getTestConfigOut->visibility = (int) Gbl.Test.Config.Visibility;
getTestConfigOut->pluggable = (TstCfg_GetConfigPluggable () == TstCfg_PLUGGABLE_YES) ? 1 :
0;
getTestConfigOut->minQuestions = (int) TstCfg_GetConfigMin ();
getTestConfigOut->defQuestions = (int) TstCfg_GetConfigDef ();
getTestConfigOut->maxQuestions = (int) TstCfg_GetConfigMax ();
getTestConfigOut->visibility = (int) TstCfg_GetConfigVisibility ();
/* Convert from visibility to old feedback */
/* TODO: Remove these lines in 2021 */
if (!TsV_IsVisibleTotalScore (Gbl.Test.Config.Visibility))
if (!TsV_IsVisibleTotalScore (TstCfg_GetConfigVisibility ()))
Str_Copy (getTestConfigOut->feedback,
"nothing",
TsR_MAX_BYTES_FEEDBACK_TYPE);
else if (!TsV_IsVisibleEachQstScore (Gbl.Test.Config.Visibility))
else if (!TsV_IsVisibleEachQstScore (TstCfg_GetConfigVisibility ()))
Str_Copy (getTestConfigOut->feedback,
"totalResult",
TsR_MAX_BYTES_FEEDBACK_TYPE);
else if (!TsV_IsVisibleCorrectAns (Gbl.Test.Config.Visibility))
else if (!TsV_IsVisibleCorrectAns (TstCfg_GetConfigVisibility ()))
Str_Copy (getTestConfigOut->feedback,
"eachResult",
TsR_MAX_BYTES_FEEDBACK_TYPE);
else if (!TsV_IsVisibleFeedbackTxt (Gbl.Test.Config.Visibility))
else if (!TsV_IsVisibleFeedbackTxt (TstCfg_GetConfigVisibility ()))
Str_Copy (getTestConfigOut->feedback,
"eachGoodBad",
TsR_MAX_BYTES_FEEDBACK_TYPE);
@ -4040,8 +4041,8 @@ int swad__getTestConfig (struct soap *soap,
TsR_MAX_BYTES_FEEDBACK_TYPE);
/***** Get number of tests *****/
if (Gbl.Test.Config.Pluggable == Tst_PLUGGABLE_YES &&
Gbl.Test.Config.Max > 0)
if (TstCfg_GetConfigPluggable () == TstCfg_PLUGGABLE_YES &&
TstCfg_GetConfigMax () > 0)
getTestConfigOut->numQuestions = API_GetNumTestQuestionsInCrs ((long) courseCode);
return SOAP_OK;
@ -4064,13 +4065,15 @@ static int API_GetTstConfig (long CrsCod)
{
/***** Get minimun, default and maximum *****/
row = mysql_fetch_row (mysql_res);
Tst_GetConfigFromRow (row);
TstCfg_GetConfigFromRow (row);
}
else // NumRows == 0
{
Gbl.Test.Config.Pluggable = Tst_PLUGGABLE_UNKNOWN;
Gbl.Test.Config.Min = Gbl.Test.Config.Def = Gbl.Test.Config.Max = 0;
Gbl.Test.Config.Visibility = TsV_VISIBILITY_DEFAULT;
TstCfg_SetConfigPluggable (TstCfg_PLUGGABLE_UNKNOWN);
TstCfg_SetConfigMin (0);
TstCfg_SetConfigDef (0);
TstCfg_SetConfigMax (0);
TstCfg_SetConfigVisibility (TsV_VISIBILITY_DEFAULT);
}
/***** Free structure that stores the query result *****/
@ -4170,7 +4173,7 @@ int swad__getTests (struct soap *soap,
if ((ReturnCode = API_GetTstConfig ((long) courseCode)) != SOAP_OK)
return ReturnCode;
if (Gbl.Test.Config.Pluggable == Tst_PLUGGABLE_YES)
if (TstCfg_GetConfigPluggable () == TstCfg_PLUGGABLE_YES)
{
/***** Get tags *****/
if ((ReturnCode = API_GetTstTags (soap,

View File

@ -526,7 +526,7 @@ const struct Act_Actions Act_Actions[Act_NUM_ACTIONS] =
[ActSeeAss ] = { 15, 0,TabAss,ActSeeAss ,0x3F8,0x3C7, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Inf_ShowInfo ,"info" },
[ActSeeAsg ] = { 801, 1,TabAss,ActSeeAsg ,0x238,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Asg_SeeAssignments ,"edit" },
[ActSeePrj ] = {1674, 2,TabAss,ActSeePrj ,0x238,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Prj_SeeProjects ,"file-alt" },
[ActReqTst ] = { 103, 3,TabAss,ActReqTst ,0x238,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Tst_ShowFormAskTst ,"check" },
[ActReqTst ] = { 103, 3,TabAss,ActReqTst ,0x238,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Tst_RequestTest ,"check" },
[ActSeeAllGam ] = {1649, 4,TabAss,ActSeeAllGam ,0x238,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Gam_SeeAllGames ,"gamepad" },
[ActSeeAllSvy ] = { 966, 5,TabAss,ActSeeAllSvy ,0x3F8,0x3C0,0x3C0,0x3C0,0x3C0,0x3C0,0x3C0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Svy_SeeAllSurveys ,"poll" },
[ActSeeAllExaAnn ] = { 85, 6,TabAss,ActSeeAllExaAnn ,0x3F8,0x3C7, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Exa_ListExamAnnouncementsSee ,"bullhorn" },
@ -629,7 +629,7 @@ const struct Act_Actions Act_Actions[Act_NUM_ACTIONS] =
[ActSeeTst ] = { 29,-1,TabUnk,ActReqTst ,0x238,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Tst_ShowNewTest ,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_ShowFormAskEditTsts ,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},
[ActEdiOneTstQst ] = { 105,-1,TabUnk,ActReqTst ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Tst_ShowFormEditOneQst ,NULL},
[ActReqImpTstQst ] = {1007,-1,TabUnk,ActReqTst ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,TsI_ShowFormImportQstsFromXML ,NULL},
[ActImpTstQst ] = {1008,-1,TabUnk,ActReqTst ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_DATA,Act_BRW_1ST_TAB,NULL ,TsI_ImportQstsFromXML ,NULL},
@ -645,7 +645,7 @@ const struct Act_Actions Act_Actions[Act_NUM_ACTIONS] =
[ActEnableTag ] = { 453,-1,TabUnk,ActReqTst ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Tst_EnableTag ,NULL},
[ActDisableTag ] = { 452,-1,TabUnk,ActReqTst ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Tst_DisableTag ,NULL},
[ActRenTag ] = { 143,-1,TabUnk,ActReqTst ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Tst_RenameTag ,NULL},
[ActRcvCfgTst ] = { 454,-1,TabUnk,ActReqTst ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Tst_ReceiveConfigTst ,NULL},
[ActRcvCfgTst ] = { 454,-1,TabUnk,ActReqTst ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,TstCfg_ReceiveConfigTst ,NULL},
[ActReqSeeMyTstRes ] = {1083,-1,TabUnk,ActReqTst ,0x208,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,Dat_SetIniEndDates ,TsR_SelDatesToSeeMyTstResults ,NULL},
[ActSeeMyTstRes ] = {1084,-1,TabUnk,ActReqTst ,0x208,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,TsR_ShowMyTstResults ,NULL},

View File

@ -497,7 +497,7 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - *
En OpenSWAD:
ps2pdf source.ps destination.pdf
*/
#define Log_PLATFORM_VERSION "SWAD 19.149.2 (2020-03-19)"
#define Log_PLATFORM_VERSION "SWAD 19.151 (2020-03-21)"
#define CSS_FILE "swad19.146.css"
#define JS_FILE "swad19.91.1.js"
/*
@ -524,6 +524,8 @@ Param
// 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
Version 19.151: Mar 21, 2020 Code refactoring in tests.
New module swad_test_config for test configuration. (283349 lines)
Version 19.150: Mar 19, 2020 Code refactoring in tests. (283031 lines)
Version 19.149.2: Mar 19, 2020 Code refactoring in tests. (283062 lines)
Version 19.149.1: Mar 18, 2020 Code refactoring in tests. (283094 lines)

View File

@ -1608,7 +1608,7 @@ void Gam_RequestNewQuestion (void)
{
/***** Show form to create a new question in this game *****/
Gam_SetCurrentGamCod (Game.GamCod); // Used to pass parameter
Tst_ShowFormAskSelectTstsForGame ();
Tst_RequestSelectTestsForGame ();
}
else
Lay_NoPermissionExit ();

View File

@ -48,6 +48,7 @@
#include "swad_project.h"
#include "swad_role.h"
#include "swad_setting.h"
#include "swad_test_config.h"
#include "swad_test_visibility.h"
#include "swad_theme.h"
@ -357,17 +358,13 @@ void Gbl_InitializeGlobals (void)
Gbl.Usrs.Connected.TimeToRefreshInMs = Con_MAX_TIME_TO_REFRESH_CONNECTED_IN_MS;
/* Tests */
Gbl.Test.Config.Pluggable = Tst_PLUGGABLE_UNKNOWN;
Gbl.Test.Config.Visibility = TsV_VISIBILITY_DEFAULT;
Gbl.Test.NumQsts = Tst_CONFIG_DEFAULT_DEF_QUESTIONS;
// Tst_SetConfigPluggable (TstCfg_PLUGGABLE_UNKNOWN);
// Tst_SetConfigVisibility (TsV_VISIBILITY_DEFAULT);
Gbl.Test.NumQsts = TstCfg_DEFAULT_DEF_QUESTIONS;
Gbl.Test.AllowTeachers = true; // Test result will be visible by teachers?
Gbl.Test.AllAnsTypes = false;
Gbl.Test.ListAnsTypes[0] = '\0';
Gbl.Test.Tags.Num = 0;
Gbl.Test.Tags.All = false;
Gbl.Test.Tags.List = NULL;
/* Games for remote control */
Gbl.Games.ListQuestions = NULL;
@ -491,7 +488,6 @@ void Gbl_Cleanup (void)
Usr_FreeListOtherRecipients ();
Usr_FreeListsSelectedEncryptedUsrsCods (&Gbl.Usrs.Selected);
Syl_FreeListItemsSyllabus ();
Tst_FreeTagsList ();
Exa_FreeMemExamAnnouncement ();
Exa_FreeListExamAnnouncements ();
if (Gbl.F.Tmp)

View File

@ -651,18 +651,10 @@ struct Globals
} TimeTable;
struct
{
struct Tst_Config Config;
struct
{
unsigned Num;
bool All;
char *List;
char Txt[Tst_MAX_TAGS_PER_QUESTION][Tst_MAX_BYTES_TAG + 1];
} Tags;
unsigned NumQsts;
long QstCodes[Tst_MAX_QUESTIONS_PER_TEST]; // Codes of the sent/received questions in a test
char StrIndexesOneQst[Tst_MAX_QUESTIONS_PER_TEST][Tst_MAX_BYTES_INDEXES_ONE_QST + 1]; // 0 1 2 3, 3 0 2 1, etc.
char StrAnswersOneQst[Tst_MAX_QUESTIONS_PER_TEST][Tst_MAX_BYTES_ANSWERS_ONE_QST + 1]; // Answers selected by user
long QstCodes[TstCfg_MAX_QUESTIONS_PER_TEST]; // Codes of the sent/received questions in a test
char StrIndexesOneQst[TstCfg_MAX_QUESTIONS_PER_TEST][Tst_MAX_BYTES_INDEXES_ONE_QST + 1]; // 0 1 2 3, 3 0 2 1, etc.
char StrAnswersOneQst[TstCfg_MAX_QUESTIONS_PER_TEST][Tst_MAX_BYTES_ANSWERS_ONE_QST + 1]; // Answers selected by user
bool AllowTeachers; // Can teachers of this course see the test result?
bool AllAnsTypes;
char ListAnsTypes[Tst_MAX_BYTES_LIST_ANSWER_TYPES + 1];

View File

@ -151,7 +151,7 @@ static void McR_ListMyMchResultsInCrs (void)
McR_ShowHeaderMchResults (Usr_ME);
/***** List my matches results in the current course *****/
Tst_GetConfigTstFromDB (); // Get feedback type
TstCfg_GetConfigFromDB (); // Get feedback type
McR_BuildGamesSelectedCommas (&GamesSelectedCommas);
McR_ShowMchResults (Usr_ME,-1L,-1L,GamesSelectedCommas);
free (GamesSelectedCommas);
@ -193,7 +193,7 @@ static void McR_ListMyMchResultsInGam (long GamCod)
McR_ShowHeaderMchResults (Usr_ME);
/***** List my matches results in game *****/
Tst_GetConfigTstFromDB (); // Get feedback type
TstCfg_GetConfigFromDB (); // Get feedback type
McR_ShowMchResults (Usr_ME,-1L,GamCod,NULL);
}
@ -237,7 +237,7 @@ static void McR_ListMyMchResultsInMch (long MchCod)
McR_ShowHeaderMchResults (Usr_ME);
/***** List my matches results in game *****/
Tst_GetConfigTstFromDB (); // Get feedback type
TstCfg_GetConfigFromDB (); // Get feedback type
McR_ShowMchResults (Usr_ME,MchCod,-1L,NULL);
}

File diff suppressed because it is too large Load Diff

View File

@ -29,13 +29,13 @@
#include "swad_game.h"
#include "swad_media.h"
#include "swad_test_config.h"
#include "swad_test_result.h"
/*****************************************************************************/
/***************************** Public constants ******************************/
/*****************************************************************************/
#define Tst_MAX_QUESTIONS_PER_TEST 100 // Absolute maximum number of questions in a test
#define Tst_MAX_TAGS_PER_QUESTION 5
#define Tst_MAX_CHARS_TAG (128 - 1) // 127
@ -48,16 +48,20 @@
#define Tst_MAX_CHARS_ANSWER_OR_FEEDBACK (1024 - 1) // 1023
#define Tst_MAX_BYTES_ANSWER_OR_FEEDBACK ((Tst_MAX_CHARS_ANSWER_OR_FEEDBACK + 1) * Str_MAX_BYTES_PER_CHAR - 1) // 16383
#define Tst_CONFIG_DEFAULT_MIN_QUESTIONS 1
#define Tst_CONFIG_DEFAULT_DEF_QUESTIONS 20 // Number of questions to be generated by default in a self-assessment test
#define Tst_CONFIG_DEFAULT_MAX_QUESTIONS 30 // Maximum number of questions to be generated in a self-assessment test
#define Tst_MAX_BYTES_ANSWER_TYPE 32
/*****************************************************************************/
/******************************* Public types ********************************/
/*****************************************************************************/
struct Tst_Tags
{
unsigned Num;
bool All;
char *List;
char Txt[Tst_MAX_TAGS_PER_QUESTION][Tst_MAX_BYTES_TAG + 1];
};
#define Tst_NUM_ANS_TYPES 6
#define Tst_MAX_BYTES_LIST_ANSWER_TYPES (Tst_NUM_ANS_TYPES * (Cns_MAX_DECIMAL_DIGITS_UINT + 1))
typedef enum
@ -71,6 +75,29 @@ typedef enum
Tst_ANS_ALL = 6, // All/any type of answer
} Tst_AnswerType_t;
#define Tst_NUM_TYPES_ORDER_QST 5
typedef enum
{
Tst_ORDER_STEM = 0,
Tst_ORDER_NUM_HITS = 1,
Tst_ORDER_AVERAGE_SCORE = 2,
Tst_ORDER_NUM_HITS_NOT_BLANK = 3,
Tst_ORDER_AVERAGE_SCORE_NOT_BLANK = 4,
} Tst_QuestionsOrder_t;
struct Tst_Test
{
struct Tst_Tags Tags;
unsigned NumQsts;
long QstCodes[TstCfg_MAX_QUESTIONS_PER_TEST]; // Codes of the sent/received questions in a test
char StrIndexesOneQst[TstCfg_MAX_QUESTIONS_PER_TEST][Tst_MAX_BYTES_INDEXES_ONE_QST + 1]; // 0 1 2 3, 3 0 2 1, etc.
char StrAnswersOneQst[TstCfg_MAX_QUESTIONS_PER_TEST][Tst_MAX_BYTES_ANSWERS_ONE_QST + 1]; // Answers selected by user
bool AllowTeachers; // Can teachers of this course see the test result?
bool AllAnsTypes;
char ListAnsTypes[Tst_MAX_BYTES_LIST_ANSWER_TYPES + 1];
Tst_QuestionsOrder_t SelectedOrder;
};
struct Tst_Question
{
struct
@ -97,14 +124,6 @@ struct Tst_Question
} Answer;
};
#define Tst_NUM_OPTIONS_PLUGGABLE 3
typedef enum
{
Tst_PLUGGABLE_UNKNOWN = 0,
Tst_PLUGGABLE_NO = 1,
Tst_PLUGGABLE_YES = 2,
} Tst_Pluggable_t;
typedef enum
{
Tst_SHOW_TEST_TO_ANSWER, // Showing a test to a student
@ -113,26 +132,6 @@ typedef enum
Tst_SELECT_QUESTIONS_FOR_GAME, // Selecting test questions for a game
} Tst_ActionToDoWithQuestions_t;
struct Tst_Config
{
Tst_Pluggable_t Pluggable;
unsigned Min; // Minimum number of questions
unsigned Def; // Default number of questions
unsigned Max; // Maximum number of questions
unsigned long MinTimeNxtTstPerQst;
unsigned Visibility; // One bit for each visibility item
};
#define Tst_NUM_TYPES_ORDER_QST 5
typedef enum
{
Tst_ORDER_STEM = 0,
Tst_ORDER_NUM_HITS = 1,
Tst_ORDER_AVERAGE_SCORE = 2,
Tst_ORDER_NUM_HITS_NOT_BLANK = 3,
Tst_ORDER_AVERAGE_SCORE_NOT_BLANK = 4,
} Tst_QuestionsOrder_t;
struct Tst_Stats
{
unsigned NumCoursesWithQuestions;
@ -150,7 +149,7 @@ struct Tst_Stats
/***************************** Public prototypes *****************************/
/*****************************************************************************/
void Tst_ShowFormAskTst (void);
void Tst_RequestTest (void);
void Tst_ShowNewTest (void);
void Tst_AssessTest (void);
@ -170,12 +169,18 @@ void Tst_WriteQstAndAnsTest (Tst_ActionToDoWithQuestions_t ActionToDoWithQuestio
void Tst_WriteQstStem (const char *Stem,const char *ClassStem,bool Visible);
void Tst_WriteQstFeedback (const char *Feedback,const char *ClassFeedback);
void Tst_ShowFormAskEditTsts (void);
void Tst_ShowFormAskSelectTstsForGame (void);
void Tst_RequestEditTests (void);
void Tst_RequestSelectTestsForGame (void);
void Tst_ListQuestionsToEdit (void);
void Tst_ListQuestionsToSelect (void);
bool Tst_GetOneQuestionByCod (long QstCod,MYSQL_RES **mysql_res);
void Tst_WriteParamEditQst (void);
void Tst_ResetGblTags (void);
void Tst_SetParamGblTags (const struct Tst_Tags *TagsSrc);
void Tst_GetParamGblTags (struct Tst_Tags *TagsDst);
unsigned Tst_GetNumAnswersQst (long QstCod);
unsigned Tst_GetAnswersQst (long QstCod,MYSQL_RES **mysql_res,bool Shuffle);
void Tst_GetCorrectAnswersFromDB (long QstCod,struct Tst_Question *Question);
@ -196,18 +201,14 @@ void Tst_CheckIfNumberOfAnswersIsOne (const struct Tst_Question *Question);
unsigned long Tst_GetTagsQst (long QstCod,MYSQL_RES **mysql_res);
void Tst_GetAndWriteTagsQst (long QstCod);
void Tst_FreeTagsList (void);
void Tst_ShowFormConfig (void);
void Tst_EnableTag (void);
void Tst_DisableTag (void);
void Tst_RenameTag (void);
void Tst_GetConfigTstFromDB (void);
void Tst_GetConfigFromRow (MYSQL_ROW row);
bool Tst_CheckIfCourseHaveTestsAndPluggableIsUnknown (void);
void Tst_ReceiveConfigTst (void);
void Tst_ShowFormEditOneQst (void);
void Tst_QstConstructor (struct Tst_Question *Question);
@ -217,7 +218,8 @@ int Tst_AllocateTextChoiceAnswer (struct Tst_Question *Question,unsigned NumOpt)
Tst_AnswerType_t Tst_ConvertFromStrAnsTypDBToAnsTyp (const char *StrAnsTypeBD);
void Tst_ReceiveQst (void);
bool Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (struct Tst_Question *Question);
bool Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (struct Tst_Question *Question,
const struct Tst_Tags *Tags);
bool Tst_CheckIfQuestionExistsInDB (const struct Tst_Question *Question);
@ -236,7 +238,8 @@ void Tst_PutParamGblQstCod (void);
void Tst_PutParamQstCod (long QstCod);
long Tst_InsertOrUpdateQstTagsAnsIntoDB (long QstCod,
struct Tst_Question *Question);
struct Tst_Question *Question,
const struct Tst_Tags *Tags);
void Tst_RemoveCrsTests (long CrsCod);

373
swad_test_config.c Normal file
View File

@ -0,0 +1,373 @@
// swad_test_config.c: self-assessment tests configuration
/*
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 <limits.h> // For UINT_MAX
// #include <linux/limits.h> // For PATH_MAX
// #include <mysql/mysql.h> // To access MySQL databases
// #include <stdbool.h> // For boolean type
// #include <stddef.h> // For NULL
// #include <stdio.h> // For asprintf
// #include <stdlib.h> // For exit, system, malloc, free, etc
#include <string.h> // For string functions
// #include <sys/stat.h> // For mkdir
// #include <sys/types.h> // For mkdir
// #include "swad_action.h"
// #include "swad_box.h"
#include "swad_database.h"
// #include "swad_form.h"
#include "swad_global.h"
// #include "swad_HTML.h"
// #include "swad_ID.h"
// #include "swad_language.h"
// #include "swad_match.h"
// #include "swad_media.h"
// #include "swad_parameter.h"
// #include "swad_theme.h"
// #include "swad_test.h"
#include "swad_test_config.h"
// #include "swad_test_import.h"
#include "swad_test_visibility.h"
// #include "swad_user.h"
// #include "swad_xml.h"
/*****************************************************************************/
/***************************** Public constants ******************************/
/*****************************************************************************/
const char *TstCfg_PluggableDB[TstCfg_NUM_OPTIONS_PLUGGABLE] =
{
[TstCfg_PLUGGABLE_UNKNOWN] = "unknown",
[TstCfg_PLUGGABLE_NO ] = "N",
[TstCfg_PLUGGABLE_YES ] = "Y",
};
/*****************************************************************************/
/**************************** Private constants ******************************/
/*****************************************************************************/
/*****************************************************************************/
/******************************* Private types *******************************/
/*****************************************************************************/
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
extern struct Globals Gbl;
/*****************************************************************************/
/************************* Private global variables **************************/
/*****************************************************************************/
struct TstCfg_Config
{
TstCfg_Pluggable_t Pluggable;
unsigned Min; // Minimum number of questions
unsigned Def; // Default number of questions
unsigned Max; // Maximum number of questions
unsigned long MinTimeNxtTstPerQst;
unsigned Visibility; // One bit for each visibility item
};
struct TstCfg_Config TstCfg_Config;
/*****************************************************************************/
/***************************** Private prototypes ****************************/
/*****************************************************************************/
static TstCfg_Pluggable_t TstCfg_GetPluggableFromForm (void);
static void TstCfg_CheckAndCorrectMinDefMax (void);
/*****************************************************************************/
/*************** Get configuration of test for current course ****************/
/*****************************************************************************/
void TstCfg_GetConfigFromDB (void)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned long NumRows;
/***** Get configuration of test for current course from database *****/
NumRows = DB_QuerySELECT (&mysql_res,"can not get configuration of test",
"SELECT Pluggable," // row[0]
"Min," // row[1]
"Def," // row[2]
"Max," // row[3]
"MinTimeNxtTstPerQst," // row[4]
"Visibility" // row[5]
" FROM tst_config"
" WHERE CrsCod=%ld",
Gbl.Hierarchy.Crs.CrsCod);
TstCfg_SetConfigMinTimeNxtTstPerQst (0UL);
TstCfg_SetConfigVisibility (TsV_VISIBILITY_DEFAULT);
if (NumRows == 0)
{
TstCfg_SetConfigPluggable (TstCfg_PLUGGABLE_UNKNOWN);
TstCfg_SetConfigMin (TstCfg_DEFAULT_MIN_QUESTIONS);
TstCfg_SetConfigDef (TstCfg_DEFAULT_DEF_QUESTIONS);
TstCfg_SetConfigMax (TstCfg_DEFAULT_MAX_QUESTIONS);
}
else // NumRows == 1
{
/***** Get minimun, default and maximum *****/
row = mysql_fetch_row (mysql_res);
TstCfg_GetConfigFromRow (row);
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
/*****************************************************************************/
/************ Get configuration values from a database table row *************/
/*****************************************************************************/
void TstCfg_GetConfigFromRow (MYSQL_ROW row)
{
int IntNum;
long LongNum;
TstCfg_Pluggable_t Pluggable;
/***** Get whether test are visible via plugins or not *****/
TstCfg_SetConfigPluggable (TstCfg_PLUGGABLE_UNKNOWN);
for (Pluggable = TstCfg_PLUGGABLE_NO;
Pluggable <= TstCfg_PLUGGABLE_YES;
Pluggable++)
if (!strcmp (row[0],TstCfg_PluggableDB[Pluggable]))
{
TstCfg_SetConfigPluggable (Pluggable);
break;
}
/***** Get number of questions *****/
if (sscanf (row[1],"%d",&IntNum) == 1)
TstCfg_SetConfigMin ((IntNum < 1) ? 1 :
(unsigned) IntNum);
else
TstCfg_SetConfigMin (TstCfg_DEFAULT_MIN_QUESTIONS);
if (sscanf (row[2],"%d",&IntNum) == 1)
TstCfg_SetConfigDef ((IntNum < 1) ? 1 :
(unsigned) IntNum);
else
TstCfg_SetConfigDef (TstCfg_DEFAULT_DEF_QUESTIONS);
if (sscanf (row[3],"%d",&IntNum) == 1)
TstCfg_SetConfigMax ((IntNum < 1) ? 1 :
(unsigned) IntNum);
else
TstCfg_SetConfigMax (TstCfg_DEFAULT_MAX_QUESTIONS);
/***** Check and correct numbers *****/
TstCfg_CheckAndCorrectMinDefMax ();
/***** Get minimum time between consecutive tests, per question (row[4]) *****/
if (sscanf (row[4],"%ld",&LongNum) == 1)
TstCfg_SetConfigMinTimeNxtTstPerQst ((LongNum < 1L) ? 0UL :
(unsigned long) LongNum);
else
TstCfg_SetConfigMinTimeNxtTstPerQst (0UL);
/***** Get visibility (row[5]) *****/
TstCfg_SetConfigVisibility (TsV_GetVisibilityFromStr (row[5]));
}
/*****************************************************************************/
/************* Receive configuration of test for current course **************/
/*****************************************************************************/
void TstCfg_ReceiveConfigTst (void)
{
extern const char *Txt_The_test_configuration_has_been_updated;
/***** Get whether test are visible via plugins or not *****/
TstCfg_SetConfigPluggable (TstCfg_GetPluggableFromForm ());
/***** Get number of questions *****/
/* Get minimum number of questions */
TstCfg_SetConfigMin ((unsigned)
Par_GetParToUnsignedLong ("NumQstMin",
1,
UINT_MAX,
1));
/* Get default number of questions */
TstCfg_SetConfigDef ((unsigned)
Par_GetParToUnsignedLong ("NumQstDef",
1,
UINT_MAX,
1));
/* Get maximum number of questions */
TstCfg_SetConfigMax ((unsigned)
Par_GetParToUnsignedLong ("NumQstMax",
1,
UINT_MAX,
1));
/* Check and correct numbers */
TstCfg_CheckAndCorrectMinDefMax ();
/***** Get minimum time between consecutive tests, per question *****/
TstCfg_SetConfigMinTimeNxtTstPerQst (Par_GetParToUnsignedLong ("MinTimeNxtTstPerQst",
0,
ULONG_MAX,
0));
/***** Get visibility from form *****/
TstCfg_SetConfigVisibility (TsV_GetVisibilityFromForm ());
/***** Update database *****/
DB_QueryREPLACE ("can not save configuration of tests",
"REPLACE INTO tst_config"
" (CrsCod,Pluggable,Min,Def,Max,MinTimeNxtTstPerQst,Visibility)"
" VALUES"
" (%ld,'%s',%u,%u,%u,'%lu',%u)",
Gbl.Hierarchy.Crs.CrsCod,
TstCfg_PluggableDB[TstCfg_GetConfigPluggable ()],
TstCfg_GetConfigMin (),
TstCfg_GetConfigDef (),
TstCfg_GetConfigMax (),
TstCfg_GetConfigMinTimeNxtTstPerQst (),
TstCfg_GetConfigVisibility ());
/***** Show confirmation message *****/
Ale_ShowAlert (Ale_SUCCESS,Txt_The_test_configuration_has_been_updated);
/***** Show again the form to configure test *****/
Tst_ShowFormConfig ();
}
/*****************************************************************************/
/******************* Get if tests are pluggable from form ********************/
/*****************************************************************************/
static TstCfg_Pluggable_t TstCfg_GetPluggableFromForm (void)
{
return (TstCfg_Pluggable_t)
Par_GetParToUnsignedLong ("Pluggable",
0,
TstCfg_NUM_OPTIONS_PLUGGABLE - 1,
(unsigned long) TstCfg_PLUGGABLE_UNKNOWN);
}
/*****************************************************************************/
/**** Check and correct minimum, default and maximum numbers of questions ****/
/*****************************************************************************/
static void TstCfg_CheckAndCorrectMinDefMax (void)
{
/***** Check if minimum is correct *****/
if (TstCfg_GetConfigMin () < 1)
TstCfg_SetConfigMin (1);
else if (TstCfg_GetConfigMin () > TstCfg_MAX_QUESTIONS_PER_TEST)
TstCfg_SetConfigMin (TstCfg_MAX_QUESTIONS_PER_TEST);
/***** Check if maximum is correct *****/
if (TstCfg_GetConfigMax () < 1)
TstCfg_SetConfigMax (1);
else if (TstCfg_GetConfigMax () > TstCfg_MAX_QUESTIONS_PER_TEST)
TstCfg_SetConfigMax (TstCfg_MAX_QUESTIONS_PER_TEST);
/***** Check if minimum is lower than maximum *****/
if (TstCfg_GetConfigMin () > TstCfg_GetConfigMax ())
TstCfg_SetConfigMin (TstCfg_GetConfigMax ());
/***** Check if default is correct *****/
if (TstCfg_GetConfigDef () < TstCfg_GetConfigMin ())
TstCfg_SetConfigDef (TstCfg_GetConfigMin ());
else if (TstCfg_GetConfigDef () > TstCfg_GetConfigMax ())
TstCfg_SetConfigDef (TstCfg_GetConfigMax ());
}
/*****************************************************************************/
/********* Get fields of current test configuration for this course **********/
/*****************************************************************************/
void TstCfg_SetConfigPluggable (TstCfg_Pluggable_t Pluggable)
{
TstCfg_Config.Pluggable = Pluggable;
}
TstCfg_Pluggable_t TstCfg_GetConfigPluggable (void)
{
return TstCfg_Config.Pluggable;
}
void TstCfg_SetConfigMin (unsigned Min)
{
TstCfg_Config.Min = Min;
}
unsigned TstCfg_GetConfigMin (void)
{
return TstCfg_Config.Min;
}
void TstCfg_SetConfigDef (unsigned Def)
{
TstCfg_Config.Def = Def;
}
unsigned TstCfg_GetConfigDef (void)
{
return TstCfg_Config.Def;
}
void TstCfg_SetConfigMax (unsigned Max)
{
TstCfg_Config.Max = Max;
}
unsigned TstCfg_GetConfigMax (void)
{
return TstCfg_Config.Max;
}
void TstCfg_SetConfigMinTimeNxtTstPerQst (unsigned long MinTimeNxtTstPerQst)
{
TstCfg_Config.MinTimeNxtTstPerQst = MinTimeNxtTstPerQst;
}
unsigned long TstCfg_GetConfigMinTimeNxtTstPerQst (void)
{
return TstCfg_Config.MinTimeNxtTstPerQst;
}
void TstCfg_SetConfigVisibility (unsigned Visibility)
{
TstCfg_Config.Visibility = Visibility;
}
unsigned TstCfg_GetConfigVisibility (void)
{
return TstCfg_Config.Visibility;
}

81
swad_test_config.h Normal file
View File

@ -0,0 +1,81 @@
// swad_test_config.h: self-assessment tests configuration
#ifndef _SWAD_TST_CFG
#define _SWAD_TST_CFG
/*
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 ***********************************/
/*****************************************************************************/
#include <mysql/mysql.h> // To access MySQL databases
#include <stdbool.h> // For boolean type
// #include "swad_game.h"
// #include "swad_media.h"
// #include "swad_test_result.h"
/*****************************************************************************/
/***************************** Public constants ******************************/
/*****************************************************************************/
#define TstCfg_MAX_QUESTIONS_PER_TEST 100 // Absolute maximum number of questions in a test
#define TstCfg_DEFAULT_MIN_QUESTIONS 1
#define TstCfg_DEFAULT_DEF_QUESTIONS 20 // Number of questions to be generated by default in a self-assessment test
#define TstCfg_DEFAULT_MAX_QUESTIONS 30 // Maximum number of questions to be generated in a self-assessment test
/*****************************************************************************/
/******************************* Public types ********************************/
/*****************************************************************************/
#define TstCfg_NUM_OPTIONS_PLUGGABLE 3
typedef enum
{
TstCfg_PLUGGABLE_UNKNOWN = 0,
TstCfg_PLUGGABLE_NO = 1,
TstCfg_PLUGGABLE_YES = 2,
} TstCfg_Pluggable_t;
/*****************************************************************************/
/***************************** Public prototypes *****************************/
/*****************************************************************************/
void TstCfg_GetConfigFromDB (void);
void TstCfg_GetConfigFromRow (MYSQL_ROW row);
void TstCfg_ReceiveConfigTst (void);
void TstCfg_SetConfigPluggable (TstCfg_Pluggable_t Pluggable);
TstCfg_Pluggable_t TstCfg_GetConfigPluggable (void);
void TstCfg_SetConfigMin (unsigned Min);
unsigned TstCfg_GetConfigMin (void);
void TstCfg_SetConfigDef (unsigned Def);
unsigned TstCfg_GetConfigDef (void);
void TstCfg_SetConfigMax (unsigned Max);
unsigned TstCfg_GetConfigMax (void);
void TstCfg_SetConfigMinTimeNxtTstPerQst (unsigned long MinTimeNxtTstPerQst);
unsigned long TstCfg_GetConfigMinTimeNxtTstPerQst (void);
void TstCfg_SetConfigVisibility (unsigned Visibility);
unsigned TstCfg_GetConfigVisibility (void);
#endif

View File

@ -81,6 +81,7 @@ static void TsI_GetAnswerFromXML (struct XMLElement *AnswerElem,
static void TsI_WriteHeadingListImportedQst (void);
static void TsI_WriteRowImportedQst (struct XMLElement *StemElem,
struct XMLElement *FeedbackElem,
const struct Tst_Tags *Tags,
const struct Tst_Question *Question,
bool QuestionExists);
@ -88,11 +89,12 @@ static void TsI_WriteRowImportedQst (struct XMLElement *StemElem,
/**************** Put a link (form) to export test questions *****************/
/*****************************************************************************/
void TsI_PutFormToExportQuestions (void)
void TsI_PutFormToExportQuestions (const struct Tst_Tags *Tags)
{
extern const char *Txt_Export_questions;
/***** Put a link to create a file with questions *****/
Tst_SetParamGblTags (Tags);
Lay_PutContextualLinkIconText (ActLstTstQst,NULL,TsI_PutParamsExportQsts,
"file-import.svg",
Txt_Export_questions);
@ -536,6 +538,7 @@ static void TsI_ImportQuestionsFromXMLBuffer (const char *XMLBuffer)
struct XMLElement *FeedbackElem;
struct XMLElement *AnswerElem;
struct XMLAttribute *Attribute;
struct Tst_Tags Tags;
bool AnswerTypeFound;
bool QuestionExists;
struct Tst_Question Question;
@ -599,22 +602,22 @@ static void TsI_ImportQuestionsFromXMLBuffer (const char *XMLBuffer)
if (AnswerTypeFound)
{
/* Get tags */
for (TagsElem = QuestionElem->FirstChild, Gbl.Test.Tags.Num = 0;
for (TagsElem = QuestionElem->FirstChild, Tags.Num = 0;
TagsElem != NULL;
TagsElem = TagsElem->NextBrother)
if (!strcmp (TagsElem->TagName,"tags"))
{
for (TagElem = TagsElem->FirstChild;
TagElem != NULL && Gbl.Test.Tags.Num < Tst_MAX_TAGS_PER_QUESTION;
TagElem != NULL && Tags.Num < Tst_MAX_TAGS_PER_QUESTION;
TagElem = TagElem->NextBrother)
if (!strcmp (TagElem->TagName,"tag"))
{
if (TagElem->Content)
{
Str_Copy (Gbl.Test.Tags.Txt[Gbl.Test.Tags.Num],
Str_Copy (Tags.Txt[Tags.Num],
TagElem->Content,
Tst_MAX_BYTES_TAG);
Gbl.Test.Tags.Num++;
Tags.Num++;
}
}
break; // Only first element "tags"
@ -685,18 +688,18 @@ static void TsI_ImportQuestionsFromXMLBuffer (const char *XMLBuffer)
TsI_GetAnswerFromXML (AnswerElem,&Question);
/* Make sure that tags, text and answer are not empty */
if (Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (&Question))
if (Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (&Question,&Tags))
{
/* Check if question already exists in database */
QuestionExists = Tst_CheckIfQuestionExistsInDB (&Question);
/* Write row with this imported question */
TsI_WriteRowImportedQst (StemElem,FeedbackElem,
&Question,QuestionExists);
&Tags,&Question,QuestionExists);
/***** If a new question ==> insert question, tags and answer in the database *****/
if (!QuestionExists)
if (Tst_InsertOrUpdateQstTagsAnsIntoDB (-1L,&Question) <= 0)
if (Tst_InsertOrUpdateQstTagsAnsIntoDB (-1L,&Question,&Tags) <= 0)
Lay_ShowErrorAndExit ("Can not create question.");
}
}
@ -917,6 +920,7 @@ static void TsI_WriteHeadingListImportedQst (void)
static void TsI_WriteRowImportedQst (struct XMLElement *StemElem,
struct XMLElement *FeedbackElem,
const struct Tst_Tags *Tags,
const struct Tst_Question *Question,
bool QuestionExists)
{
@ -964,12 +968,12 @@ static void TsI_WriteRowImportedQst (struct XMLElement *StemElem,
/***** Write the question tags *****/
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
if (Gbl.Test.Tags.Num)
if (Tags->Num)
{
/***** Write the tags *****/
HTM_TABLE_Begin (NULL);
for (NumTag = 0;
NumTag < Gbl.Test.Tags.Num;
NumTag < Tags->Num;
NumTag++)
{
HTM_TR_Begin (NULL);
@ -979,7 +983,7 @@ static void TsI_WriteRowImportedQst (struct XMLElement *StemElem,
HTM_TD_End ();
HTM_TD_Begin ("class=\"%s LT\"",ClassData);
HTM_Txt (Gbl.Test.Tags.Txt[NumTag]);
HTM_Txt (Tags->Txt[NumTag]);
HTM_TD_End ();
HTM_TR_End ();

View File

@ -39,7 +39,7 @@
/***************************** Public prototypes *****************************/
/*****************************************************************************/
void TsI_PutFormToExportQuestions (void);
void TsI_PutFormToExportQuestions (const struct Tst_Tags *Tags);
bool TsI_GetCreateXMLParamFromForm (void);
void TsI_PutFormToImportQuestions (void);
void TsI_CreateXML (unsigned long NumRows,MYSQL_RES *mysql_res);

View File

@ -158,7 +158,7 @@ void TsR_ShowMyTstResults (void)
TsR_ShowHeaderTestResults ();
/***** List my test results *****/
Tst_GetConfigTstFromDB (); // To get feedback type
TstCfg_GetConfigFromDB (); // To get feedback type
TsR_ShowTstResults (&Gbl.Usrs.Me.UsrDat);
/***** End table and box *****/
@ -355,7 +355,7 @@ static void TsR_ShowTstResults (struct UsrData *UsrDat)
case Rol_STD:
ICanViewTest = ItsMe;
ICanViewScore = ItsMe &&
TsV_IsVisibleTotalScore (Gbl.Test.Config.Visibility);
TsV_IsVisibleTotalScore (TstCfg_GetConfigVisibility ());
break;
case Rol_NET:
case Rol_TCH:
@ -514,7 +514,7 @@ static void TsR_ShowTestResultsSummaryRow (bool ItsMe,
{
case Rol_STD:
ICanViewTotalScore = ItsMe &&
TsV_IsVisibleTotalScore (Gbl.Test.Config.Visibility);
TsV_IsVisibleTotalScore (TstCfg_GetConfigVisibility ());
break;
case Rol_NET:
case Rol_TCH:
@ -613,7 +613,7 @@ void TsR_ShowOneTstResult (void)
/***** Get test result data *****/
TsR_GetTestResultDataByTstCod (TstCod,&TstTimeUTC,
&NumQstsNotBlank,&TotalScore);
Gbl.Test.Config.Visibility = TsV_MAX_VISIBILITY;
TstCfg_SetConfigVisibility (TsV_MAX_VISIBILITY);
/***** Check if I can view this test result *****/
ItsMe = Usr_ItsMe (Gbl.Usrs.Other.UsrDat.UsrCod);
@ -623,8 +623,8 @@ void TsR_ShowOneTstResult (void)
ICanViewTest = ItsMe;
if (ItsMe)
{
Tst_GetConfigTstFromDB (); // To get feedback type
ICanViewScore = TsV_IsVisibleTotalScore (Gbl.Test.Config.Visibility);
TstCfg_GetConfigFromDB (); // To get feedback type
ICanViewScore = TsV_IsVisibleTotalScore (TstCfg_GetConfigVisibility ());
}
else
ICanViewScore = false;
@ -781,7 +781,7 @@ void TsR_ShowOneTstResult (void)
/***** Write answers and solutions *****/
TsR_ShowTestResult (&Gbl.Usrs.Other.UsrDat,
Gbl.Test.NumQsts,TstTimeUTC,
Gbl.Test.Config.Visibility);
TstCfg_GetConfigVisibility ());
/***** End table *****/
HTM_TABLE_End ();

View File

@ -51445,11 +51445,11 @@ const char *Txt_TST_HIDDEN_VISIBLE[2] =
#endif
};
const char *Txt_TST_PLUGGABLE[Tst_NUM_OPTIONS_PLUGGABLE] =
const char *Txt_TST_PLUGGABLE[TstCfg_NUM_OPTIONS_PLUGGABLE] =
{
[Tst_PLUGGABLE_UNKNOWN] =
[TstCfg_PLUGGABLE_UNKNOWN] =
"",
[Tst_PLUGGABLE_NO] =
[TstCfg_PLUGGABLE_NO] =
#if L==1 // ca
"Tests no visibles des de m&ograve;bils (SWADroid, TriSWADos)"
#elif L==2 // de
@ -51470,7 +51470,7 @@ const char *Txt_TST_PLUGGABLE[Tst_NUM_OPTIONS_PLUGGABLE] =
"Testes n&atilde;o para download de celulares (SWADroid, TriSWADos)"
#endif
,
[Tst_PLUGGABLE_YES] =
[TstCfg_PLUGGABLE_YES] =
#if L==1 // ca
"Tests visibles des de m&ograve;bils (SWADroid, TriSWADos), opci&oacute; recomanada"
#elif L==2 // de