Version19.157

This commit is contained in:
acanas 2020-04-01 03:11:05 +02:00
parent 2603e5a906
commit d8233a0aa8
10 changed files with 1396 additions and 928 deletions

View File

@ -13250,6 +13250,7 @@ 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; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20140101' AND ClickTime<'20140201'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20140201' AND ClickTime<'20140301'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20140301' AND ClickTime<'20140401'; Hecho
@ -13259,13 +13260,38 @@ INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20140601' AND ClickTime
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20140701' AND ClickTime<'20140801'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20140801' AND ClickTime<'20140901'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20140901' AND ClickTime<'20141001'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20141001' AND ClickTime<'20141101';
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20141101' AND ClickTime<'20141201';
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20141201' AND ClickTime<'20150101';
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 ClickTime>='20141001' AND ClickTime<'20141101'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20141101' AND ClickTime<'20141201'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20141201' AND ClickTime<'20150101'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20150101' AND ClickTime<'20150201'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20150201' AND ClickTime<'20150301'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20150301' AND ClickTime<'20150401'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20150401' AND ClickTime<'20150501'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20150501' AND ClickTime<'20150601'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20150601' AND ClickTime<'20150701'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20150701' AND ClickTime<'20150801'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20150801' AND ClickTime<'20150901'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20150901' AND ClickTime<'20151001'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20151001' AND ClickTime<'20151101'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20151101' AND ClickTime<'20151201'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20151201' AND ClickTime<'20160101'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20160101' AND ClickTime<'20160201'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20160201' AND ClickTime<'20160301'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20160301' AND ClickTime<'20160401'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20160401' AND ClickTime<'20160501'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20160501' AND ClickTime<'20160601'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20160601' AND ClickTime<'20160701'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20160701' AND ClickTime<'20160801'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20160801' AND ClickTime<'20160901'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20160901' AND ClickTime<'20161001'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20161001' AND ClickTime<'20161101'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20161101' AND ClickTime<'20161201'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE ClickTime>='20161201' AND ClickTime<'20170101'; Hecho
INSERT INTO log SELECT * FROM log_full WHERE YEAR(ClickTime) = 2017; Hecho
INSERT INTO log SELECT * FROM log_full WHERE YEAR(ClickTime) = 2018; Hecho
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

View File

@ -4,20 +4,16 @@
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/>.
*/

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.156.4 (2020-03-29)"
#define Log_PLATFORM_VERSION "SWAD 19.157 (2020-04-01)"
#define CSS_FILE "swad19.146.css"
#define JS_FILE "swad19.153.js"
/*
@ -528,7 +528,8 @@ Param
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.
Version 19.156.5: Mar 29, 2020 Test exam is stored in database when it's generated. (? lines)
Version 19.157: Apr 01, 2020 Code refactoring in tests.
Test exam is stored in database when it's generated. Not tested. (285023 lines)
Version 19.156.4: Mar 29, 2020 Code refactoring in tests. (284657 lines)
Version 19.156.3: Mar 29, 2020 Code refactoring in tests. (284585 lines)
Version 19.156.2: Mar 29, 2020 Test exam with start date and end date. (284568 lines)

View File

@ -3956,10 +3956,6 @@ static void Mch_ComputeScore (struct TsR_Result *Result)
{
unsigned NumQst;
struct Tst_Question Question;
double ScoreThisQst;
bool AnswerIsNotBlank;
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION]; // Indexes of all answers of this question
bool AnswersUsr[Tst_MAX_OPTIONS_PER_QUESTION];
for (NumQst = 0, Result->Score = 0.0;
NumQst < Result->NumQsts;
@ -3967,20 +3963,14 @@ static void Mch_ComputeScore (struct TsR_Result *Result)
{
/***** Create test question *****/
Tst_QstConstructor (&Question);
Question.QstCod = Result->QstCodes[NumQst];
Question.QstCod = Result->Questions[NumQst].QstCod;
Question.Answer.Type = Tst_ANS_UNIQUE_CHOICE;
/***** Get correct answers of test question from database *****/
Tst_GetCorrectAnswersFromDB (&Question);
/***** Compute the score of this question *****/
Tst_GetIndexesFromStr (Result->StrIndexes[NumQst],Indexes);
Tst_GetAnswersFromStr (Result->StrAnswers[NumQst],AnswersUsr);
Tst_ComputeScoreQst (&Question,
Indexes,AnswersUsr,&ScoreThisQst,&AnswerIsNotBlank);
/***** Compute score for this answer ******/
Tst_ComputeChoiceAnsScore (Result,NumQst,&Question);
/***** Update total score *****/
Result->Score += ScoreThisQst;
Result->Score += Result->Questions[NumQst].Score;
/***** Destroy test question *****/
Tst_QstDestructor (&Question);

View File

@ -1251,7 +1251,7 @@ void McR_GetMatchResultQuestionsFromDB (long MchCod,long UsrCod,
row = mysql_fetch_row (mysql_res);
/* Get question code (row[0]) */
if ((Result->QstCodes[NumQst] = Str_ConvertStrCodToLongCod (row[0])) < 0)
if ((Result->Questions[NumQst].QstCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
Lay_ShowErrorAndExit ("Wrong code of question.");
/* Get question index (row[1]) */
@ -1260,24 +1260,24 @@ void McR_GetMatchResultQuestionsFromDB (long MchCod,long UsrCod,
QstInd = (unsigned) LongNum;
/* Get indexes for this question (row[2]) */
Str_Copy (Result->StrIndexes[NumQst],row[2],
Str_Copy (Result->Questions[NumQst].StrIndexes,row[2],
Tst_MAX_BYTES_INDEXES_ONE_QST);
/* Get answers selected by user for this question */
Mch_GetQstAnsFromDB (MchCod,UsrCod,QstInd,&UsrAnswer);
if (UsrAnswer.AnsInd >= 0) // UsrAnswer.AnsInd >= 0 ==> answer selected
{
snprintf (Result->StrAnswers[NumQst],Tst_MAX_BYTES_ANSWERS_ONE_QST + 1,
snprintf (Result->Questions[NumQst].StrAnswers,Tst_MAX_BYTES_ANSWERS_ONE_QST + 1,
"%d",UsrAnswer.AnsInd);
Result->NumQstsNotBlank++;
}
else // UsrAnswer.AnsInd < 0 ==> no answer selected
Result->StrAnswers[NumQst][0] = '\0'; // Empty answer
Result->Questions[NumQst].StrAnswers[0] = '\0'; // Empty answer
/* Replace each comma by a separator of multiple parameters */
/* In database commas are used as separators instead of special chars */
Par_ReplaceCommaBySeparatorMultiple (Result->StrIndexes[NumQst]);
Par_ReplaceCommaBySeparatorMultiple (Result->StrAnswers[NumQst]);
Par_ReplaceCommaBySeparatorMultiple (Result->Questions[NumQst].StrIndexes);
Par_ReplaceCommaBySeparatorMultiple (Result->Questions[NumQst].StrAnswers);
}
/***** Free structure that stores the query result *****/

View File

@ -267,7 +267,7 @@ void Med_GetMediaDataByCod (struct Media *Media)
size_t Length;
/***** Get data of a media from database *****/
NumRows = DB_QuerySELECT (&mysql_res,"can not get data of a post",
NumRows = DB_QuerySELECT (&mysql_res,"can not get media",
"SELECT Type," // row[0]
"Name," // row[1]
"URL," // row[2]

File diff suppressed because it is too large Load Diff

View File

@ -155,6 +155,12 @@ void Tst_ShowNewTest (void);
void Tst_RequestAssessTest (void);
void Tst_AssessTest (void);
void Tst_ComputeChoiceAnsScore (struct TsR_Result *Result,
unsigned NumQst,
struct Tst_Question *Question);
void Tst_GetIndexesFromStr (const char StrIndexesOneQst[Tst_MAX_BYTES_INDEXES_ONE_QST + 1], // 0 1 2 3, 3 0 2 1, etc.
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION]);
void Tst_ComputeAndShowGrade (unsigned NumQsts,double Score,double MaxGrade);
double Tst_ComputeGrade (unsigned NumQsts,double Score,double MaxGrade);
void Tst_ShowGrade (double Grade,double MaxGrade);
@ -162,11 +168,10 @@ void Tst_ShowGrade (double Grade,double MaxGrade);
void Tst_ShowTagList (unsigned NumTags,MYSQL_RES *mysql_res);
void Tst_WriteQstAndAnsTestResult (struct UsrData *UsrDat,
const struct TsR_Result *Result,
struct TsR_Result *Result,
unsigned NumQst,
MYSQL_ROW row,
unsigned Visibility,
double *ScoreThisQst,bool *AnswerIsNotBlank);
unsigned Visibility);
void Tst_WriteNumQst (unsigned NumQst);
void Tst_WriteAnswerType (Tst_AnswerType_t AnswerType);
void Tst_WriteQstStem (const char *Stem,const char *ClassStem,bool Visible);
@ -183,18 +188,9 @@ void Tst_WriteParamEditQst (const struct Tst_Test *Test);
unsigned Tst_GetNumAnswersQst (long QstCod);
void Tst_GetAnswersQst (struct Tst_Question *Question,MYSQL_RES **mysql_res,
bool Shuffle);
void Tst_GetCorrectAnswersFromDB (struct Tst_Question *Question);
void Tst_WriteAnswersListing (struct Tst_Question *Question);
bool Tst_CheckIfQuestionIsValidForGame (long QstCod);
void Tst_WriteAnsTF (char AnsTF);
void Tst_GetIndexesFromStr (const char StrIndexesOneQst[Tst_MAX_BYTES_INDEXES_ONE_QST + 1], // 0 1 2 3, 3 0 2 1, etc.
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION]);
void Tst_GetAnswersFromStr (const char StrAnswersOneQst[Tst_MAX_BYTES_ANSWERS_ONE_QST + 1],
bool AnswersUsr[Tst_MAX_OPTIONS_PER_QUESTION]);
void Tst_ComputeScoreQst (const struct Tst_Question *Question,
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION],
bool AnswersUsr[Tst_MAX_OPTIONS_PER_QUESTION],
double *ScoreThisQst,bool *AnswerIsNotBlank);
void Tst_CheckIfNumberOfAnswersIsOne (const struct Tst_Question *Question);
unsigned long Tst_GetTagsQst (long QstCod,MYSQL_RES **mysql_res);

View File

@ -168,13 +168,13 @@ void TsR_ShowMyTstResults (void)
}
/*****************************************************************************/
/********************* Store test result in database *************************/
/**************** Create new blank test result in database *******************/
/*****************************************************************************/
long TsR_CreateTestResultInDB (const struct TsR_Result *Result)
void TsR_CreateTestResultInDB (struct TsR_Result *Result)
{
/***** Insert new test result into table *****/
return
Result->TstCod =
DB_QueryINSERTandReturnCode ("can not create new test result",
"INSERT INTO tst_exams"
" (CrsCod,UsrCod,StartTime,EndTime,NumQsts,AllowTeachers)"
@ -191,19 +191,22 @@ long TsR_CreateTestResultInDB (const struct TsR_Result *Result)
/********************* Store test result in database *************************/
/*****************************************************************************/
void TsR_StoreScoreOfTestResultInDB (long TstCod,
const struct TsR_Result *Result)
void TsR_UpdateScoreOfTestResultInDB (const struct TsR_Result *Result)
{
/***** Update score in test result *****/
Str_SetDecimalPointToUS (); // To print the floating point as a dot
Str_SetDecimalPointToUS (); // To print the floating point as a dot
DB_QueryUPDATE ("can not update test result",
"UPDATE tst_exams"
" SET NumQstsNotBlank=%u,"
" SET EndTime=NOW(),"
"NumQstsNotBlank=%u,"
"Score='%.15lg'"
" WHERE TstCod=%ld",
" WHERE TstCod=%ld"
" AND CrsCod=%ld AND UsrCod=%ld", // Extra checks
Result->NumQstsNotBlank,
Result->Score,
TstCod);
Result->TstCod,
Gbl.Hierarchy.Crs.CrsCod,
Gbl.Usrs.Me.UsrDat.UsrCod);
Str_SetDecimalPointToLocal (); // Return to local system
}
@ -847,7 +850,7 @@ void TsR_ShowOneTstResult (void)
static void TsR_ShowTstTagsPresentInATestResult (long TstCod)
{
MYSQL_RES *mysql_res;
unsigned long NumTags;
unsigned NumTags;
/***** Get all tags of questions in this test *****/
NumTags = (unsigned)
@ -874,7 +877,7 @@ static void TsR_ShowTstTagsPresentInATestResult (long TstCod)
/*****************************************************************************/
void TsR_ShowTestResult (struct UsrData *UsrDat,
const struct TsR_Result *Result,
struct TsR_Result *Result,
unsigned Visibility)
{
extern const char *Txt_Question_modified;
@ -882,8 +885,6 @@ void TsR_ShowTestResult (struct UsrData *UsrDat,
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumQst;
double ScoreThisQst;
bool AnswerIsNotBlank;
bool ThisQuestionHasBeenEdited;
time_t EditTimeUTC;
@ -894,7 +895,7 @@ void TsR_ShowTestResult (struct UsrData *UsrDat,
Gbl.RowEvenOdd = NumQst % 2;
/***** Query database *****/
if (Tst_GetOneQuestionByCod (Result->QstCodes[NumQst],&mysql_res)) // Question exists
if (Tst_GetOneQuestionByCod (Result->Questions[NumQst].QstCod,&mysql_res)) // Question exists
{
/***** Get row of the result of the query *****/
row = mysql_fetch_row (mysql_res);
@ -927,9 +928,7 @@ void TsR_ShowTestResult (struct UsrData *UsrDat,
Result,
NumQst,
row,
Visibility,
&ScoreThisQst, // Not used here
&AnswerIsNotBlank); // Not used here
Visibility);
}
else
{
@ -1020,17 +1019,16 @@ static void TsR_GetTestResultDataByTstCod (long TstCod,struct TsR_Result *Result
/************ Store user's answers of an test result into database ***********/
/*****************************************************************************/
void TsR_StoreOneTestResultQstInDB (long TstCod,
const struct TsR_Result *Result,
unsigned NumQst,double ScoreThisQst)
void TsR_StoreOneTestResultQstInDB (const struct TsR_Result *Result,
unsigned NumQst)
{
char Indexes[Tst_MAX_BYTES_INDEXES_ONE_QST + 1];
char Answers[Tst_MAX_BYTES_ANSWERS_ONE_QST + 1];
char StrIndexes[Tst_MAX_BYTES_INDEXES_ONE_QST + 1];
char StrAnswers[Tst_MAX_BYTES_ANSWERS_ONE_QST + 1];
/***** Replace each separator of multiple parameters by a comma *****/
/* In database commas are used as separators instead of special chars */
Par_ReplaceSeparatorMultipleByComma (Result->StrIndexes[NumQst],Indexes);
Par_ReplaceSeparatorMultipleByComma (Result->StrAnswers[NumQst],Answers);
Par_ReplaceSeparatorMultipleByComma (Result->Questions[NumQst].StrIndexes,StrIndexes);
Par_ReplaceSeparatorMultipleByComma (Result->Questions[NumQst].StrAnswers,StrAnswers);
/***** Insert question and user's answers into database *****/
Str_SetDecimalPointToUS (); // To print the floating point as a dot
@ -1039,11 +1037,11 @@ void TsR_StoreOneTestResultQstInDB (long TstCod,
" (TstCod,QstCod,QstInd,Score,Indexes,Answers)"
" VALUES"
" (%ld,%ld,%u,'%.15lg','%s','%s')",
TstCod,Result->QstCodes[NumQst],
Result->TstCod,Result->Questions[NumQst].QstCod,
NumQst, // 0, 1, 2, 3...
ScoreThisQst,
Indexes,
Answers);
Result->Questions[NumQst].Score,
StrIndexes,
StrAnswers);
Str_SetDecimalPointToLocal (); // Return to local system
}
@ -1077,21 +1075,21 @@ static void TsR_GetTestResultQuestionsFromDB (long TstCod,struct TsR_Result *Res
row = mysql_fetch_row (mysql_res);
/* Get question code */
if ((Result->QstCodes[NumQst] = Str_ConvertStrCodToLongCod (row[0])) < 0)
if ((Result->Questions[NumQst].QstCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
Lay_ShowErrorAndExit ("Wrong code of question.");
/* Get indexes for this question (row[1]) */
Str_Copy (Result->StrIndexes[NumQst],row[1],
Str_Copy (Result->Questions[NumQst].StrIndexes,row[1],
Tst_MAX_BYTES_INDEXES_ONE_QST);
/* Get answers selected by user for this question (row[2]) */
Str_Copy (Result->StrAnswers[NumQst],row[2],
Str_Copy (Result->Questions[NumQst].StrAnswers,row[2],
Tst_MAX_BYTES_ANSWERS_ONE_QST);
/* Replace each comma by a separator of multiple parameters */
/* In database commas are used as separators instead of special chars */
Par_ReplaceCommaBySeparatorMultiple (Result->StrIndexes[NumQst]);
Par_ReplaceCommaBySeparatorMultiple (Result->StrAnswers[NumQst]);
Par_ReplaceCommaBySeparatorMultiple (Result->Questions[NumQst].StrIndexes);
Par_ReplaceCommaBySeparatorMultiple (Result->Questions[NumQst].StrAnswers);
}
/***** Free structure that stores the query result *****/

View File

@ -45,16 +45,20 @@
struct TsR_Result
{
long TstCod; // Exam code
time_t TimeUTC[Dat_NUM_START_END_TIME];
unsigned NumQsts;
unsigned NumQstsNotBlank;
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
unsigned NumQsts; // Number of questions
unsigned NumQstsNotBlank; // Number of questions not blank
bool AllowTeachers; // Are teachers allowed to see this test result?
double Score; // Total score of the test result
struct
{
long QstCod; // Question code
char StrIndexes[Tst_MAX_BYTES_INDEXES_ONE_QST + 1]; // 0 1 2 3, 3 0 2 1, etc.
char StrAnswers[Tst_MAX_BYTES_ANSWERS_ONE_QST + 1]; // Answers selected by user
double Score; // Question score
bool AnswerIsNotBlank; // Answer not blank?
} Questions[TstCfg_MAX_QUESTIONS_PER_TEST];
};
/*****************************************************************************/
@ -64,17 +68,15 @@ struct TsR_Result
void TsR_SelUsrsToViewUsrsTstResults (void);
void TsR_SelDatesToSeeMyTstResults (void);
void TsR_ShowMyTstResults (void);
long TsR_CreateTestResultInDB (const struct TsR_Result *Result);
void TsR_StoreScoreOfTestResultInDB (long TstCod,
const struct TsR_Result *Result);
void TsR_CreateTestResultInDB (struct TsR_Result *Result);
void TsR_UpdateScoreOfTestResultInDB (const struct TsR_Result *Result);
void TsR_GetUsrsAndShowTstResults (void);
void TsR_ShowOneTstResult (void);
void TsR_ShowTestResult (struct UsrData *UsrDat,
const struct TsR_Result *Result,
struct TsR_Result *Result,
unsigned Visibility);
void TsR_StoreOneTestResultQstInDB (long TstCod,
const struct TsR_Result *Result,
unsigned NumQst,double ScoreThisQst);
void TsR_StoreOneTestResultQstInDB (const struct TsR_Result *Result,
unsigned NumQst);
void TsR_RemoveTestResultsMadeByUsrInAllCrss (long UsrCod);
void TsR_RemoveTestResultsMadeByUsrInCrs (long UsrCod,long CrsCod);
void TsR_RemoveCrsTestResults (long CrsCod);