Version19.145

This commit is contained in:
Antonio Cañas Vargas 2020-03-07 00:14:35 +01:00
parent 68b1949a42
commit ebf73792a5
6 changed files with 200 additions and 134 deletions

View File

@ -497,7 +497,7 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - *
En OpenSWAD: En OpenSWAD:
ps2pdf source.ps destination.pdf ps2pdf source.ps destination.pdf
*/ */
#define Log_PLATFORM_VERSION "SWAD 19.144.3 (2020-03-06)" #define Log_PLATFORM_VERSION "SWAD 19.145 (2020-03-07)"
#define CSS_FILE "swad19.144.1.css" #define CSS_FILE "swad19.144.1.css"
#define JS_FILE "swad19.91.1.js" #define JS_FILE "swad19.91.1.js"
/* /*
@ -524,14 +524,10 @@ Param
// TODO: Miguel Damas: al principio de los exámenes tendría que poner cuánto resta cada pregunta // TODO: Miguel Damas: al principio de los exámenes tendría que poner cuánto resta cada pregunta
// 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: 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: Oresti Baños: cambiar ojos por candados en descriptores para prohibir/permitir y dejar los ojos para poder elegir descriptores // TODO: Oresti Baños: cambiar ojos por candados en descriptores para prohibir/permitir y dejar los ojos para poder elegir descriptores
// TODO: Comprobar los resultados de partidas de juegos con preguntas eliminadas
// TODO: URGENTE: Reportado por Eva Martínez Ortigosa Version 19.145: Mar 07, 2020 Fixed bug in log.
Sea un juego tiene dos preguntas: 1 y 2 Fixed bug in matches, reported by Eva Martínez Ortigosa. (282346 lines)
Se elimina la pregunta 1 de los test ==> ahora no sale la pregunta 1 al editar el juego
==> DEBERÍA SALIR el número 1 indicando que la pregunta no existe
Al intentar jugar una partida y pasar por la pregunta 1 ==> Ahora se cuelga
==> DEBERÍA SALIR un mensaje de que la pregunta no existe
Version 19.144.3: Mar 06, 2020 New social network: twitch. (282286 lines) Version 19.144.3: Mar 06, 2020 New social network: twitch. (282286 lines)
2 changes necessary in database: 2 changes necessary in database:
ALTER TABLE usr_webs CHANGE Web Web ENUM('www', '500px', 'delicious', 'deviantart', 'diaspora', 'edmodo', 'facebook', 'flickr', 'foursquare', 'github', 'gnusocial', 'googleplus', 'googlescholar', 'identica', 'instagram', 'linkedin', 'orcid', 'paperli', 'pinterest', 'researchgate', 'researcherid', 'scoopit', 'slideshare', 'stackoverflow', 'storify', 'tumblr', 'twitch', 'twitter', 'wikipedia', 'youtube') NOT NULL; ALTER TABLE usr_webs CHANGE Web Web ENUM('www', '500px', 'delicious', 'deviantart', 'diaspora', 'edmodo', 'facebook', 'flickr', 'foursquare', 'github', 'gnusocial', 'googleplus', 'googlescholar', 'identica', 'instagram', 'linkedin', 'orcid', 'paperli', 'pinterest', 'researchgate', 'researcherid', 'scoopit', 'slideshare', 'stackoverflow', 'storify', 'tumblr', 'twitch', 'twitter', 'wikipedia', 'youtube') NOT NULL;

View File

@ -4140,7 +4140,7 @@ static void Enr_EffectivelyRemUsrFromCrs (struct UsrData *UsrDat,
} }
else // Not me else // Not me
{ {
/* Now he/she doesn't belong to current course */ /* Now he/she does not belong to current course */
UsrDat->Accepted = false; UsrDat->Accepted = false;
UsrDat->Roles.InCurrentCrs.Role = Rol_USR; UsrDat->Roles.InCurrentCrs.Role = Rol_USR;
UsrDat->Roles.InCurrentCrs.Valid = false; UsrDat->Roles.InCurrentCrs.Valid = false;

View File

@ -151,6 +151,7 @@ static void Gam_ListGameQuestions (struct Game *Game);
static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts, static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts,
MYSQL_RES *mysql_res, MYSQL_RES *mysql_res,
bool ICanEditQuestions); bool ICanEditQuestions);
static void Gam_ListQuestionForEdition (const char *StrQstInd);
static void Gam_PutIconToAddNewQuestions (void); static void Gam_PutIconToAddNewQuestions (void);
static void Gam_PutButtonToAddNewQuestions (void); static void Gam_PutButtonToAddNewQuestions (void);
@ -1746,7 +1747,7 @@ unsigned Gam_GetNextQuestionIndexInGame (long GamCod,unsigned QstInd)
{ {
MYSQL_RES *mysql_res; MYSQL_RES *mysql_res;
MYSQL_ROW row; MYSQL_ROW row;
unsigned NextQstInd = 0; unsigned NextQstInd = Mch_AFTER_LAST_QUESTION; // End of questions has been reached
/***** Get next question index in a game from database *****/ /***** Get next question index in a game from database *****/
// Although indexes are always continuous... // Although indexes are always continuous...
@ -1784,18 +1785,14 @@ static void Gam_ListGameQuestions (struct Game *Game)
bool ICanEditQuestions = Gam_CheckIfEditable (Game); bool ICanEditQuestions = Gam_CheckIfEditable (Game);
/***** Get data of questions from database *****/ /***** Get data of questions from database *****/
NumQsts = (unsigned) DB_QuerySELECT (&mysql_res,"can not get data of a question", NumQsts = (unsigned)
"SELECT gam_questions.QstInd," // row[0] DB_QuerySELECT (&mysql_res,"can not get game questions",
"gam_questions.QstCod," // row[1] "SELECT QstInd," // row[0]
"tst_questions.AnsType," // row[2] "QstCod" // row[1]
"tst_questions.Stem," // row[3] " FROM gam_questions"
"tst_questions.Feedback," // row[4] " WHERE GamCod=%ld"
"tst_questions.MedCod" // row[5] " ORDER BY QstInd",
" FROM gam_questions,tst_questions" Game->GamCod);
" WHERE gam_questions.GamCod=%ld"
" AND gam_questions.QstCod=tst_questions.QstCod"
" ORDER BY gam_questions.QstInd",
Game->GamCod);
/***** Begin box *****/ /***** Begin box *****/
Gam_SetCurrentGamCod (Game->GamCod); // Used to pass parameter Gam_SetCurrentGamCod (Game->GamCod); // Used to pass parameter
@ -1837,7 +1834,6 @@ static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts,
extern const char *Txt_Move_up_X; extern const char *Txt_Move_up_X;
extern const char *Txt_Move_down_X; extern const char *Txt_Move_down_X;
extern const char *Txt_Movement_not_allowed; extern const char *Txt_Movement_not_allowed;
extern const char *Txt_TST_STR_ANSWER_TYPES[Tst_NUM_ANS_TYPES];
unsigned NumQst; unsigned NumQst;
MYSQL_ROW row; MYSQL_ROW row;
unsigned QstInd; unsigned QstInd;
@ -1871,10 +1867,6 @@ static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts,
/* /*
row[0] QstInd row[0] QstInd
row[1] QstCod row[1] QstCod
row[2] AnsType
row[3] Stem
row[4] Feedback
row[5] MedCod
*/ */
/***** Create test question *****/ /***** Create test question *****/
Tst_QstConstructor (); Tst_QstConstructor ();
@ -1937,52 +1929,9 @@ static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts,
HTM_TD_End (); HTM_TD_End ();
HTM_TD_Begin ("class=\"RT COLOR%u\"",Gbl.RowEvenOdd); /***** Question *****/
Gam_ListQuestionForEdition (StrQstInd);
/* Write number of question */
HTM_DIV_Begin ("class=\"BIG_INDEX\"");
HTM_Txt (StrQstInd);
HTM_DIV_End ();
/* Write answer type (row[2]) */
Gbl.Test.AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[2]);
HTM_DIV_Begin ("class=\"DAT_SMALL\"");
HTM_Txt (Txt_TST_STR_ANSWER_TYPES[Gbl.Test.AnswerType]);
HTM_DIV_End ();
HTM_TD_End ();
/* Write question code */
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
HTM_TxtF ("%ld ",Gbl.Test.QstCod);
HTM_TD_End ();
/* Write the question tags */
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
Tst_GetAndWriteTagsQst (Gbl.Test.QstCod);
HTM_TD_End ();
/* Write stem (row[3]) */
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
Tst_WriteQstStem (row[3],"TEST_EDI",
true); // Visible
/* Get media (row[5]) */
Gbl.Test.Media.MedCod = Str_ConvertStrCodToLongCod (row[5]);
Med_GetMediaDataByCod (&Gbl.Test.Media);
/* Show media */
Med_ShowMedia (&Gbl.Test.Media,
"TEST_MED_EDIT_LIST_STEM_CONTAINER",
"TEST_MED_EDIT_LIST_STEM");
/* Show feedback (row[4]) */
Tst_WriteQstFeedback (row[4],"TEST_EDI_LIGHT");
/* Show answers */
Tst_WriteAnswersEdit (Gbl.Test.QstCod);
HTM_TD_End ();
HTM_TR_End (); HTM_TR_End ();
/***** Destroy test question *****/ /***** Destroy test question *****/
@ -1993,6 +1942,104 @@ static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts,
HTM_TABLE_End (); HTM_TABLE_End ();
} }
/*****************************************************************************/
/********************** List game question for edition ***********************/
/*****************************************************************************/
static void Gam_ListQuestionForEdition (const char *StrQstInd)
{
extern const char *Txt_TST_STR_ANSWER_TYPES[Tst_NUM_ANS_TYPES];
extern const char *Txt_Question_removed;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
bool QstExists;
/***** Get question from database *****/
QstExists = Tst_GetOneQuestionByCod (Gbl.Test.QstCod,&mysql_res); // Question exists?
if (QstExists)
{
/***** Get row of the result of the query *****/
row = mysql_fetch_row (mysql_res);
/*
row[0] QstCod
row[1] UNIX_TIMESTAMP(EditTime)
row[2] AnsType
row[3] Shuffle
row[4] Stem
row[5] Feedback
row[6] MedCod
row[7] NumHits
row[8] NumHitsNotBlank
row[9] Score
*/
}
/***** Number of question and answer type *****/
HTM_TD_Begin ("class=\"RT COLOR%u\"",Gbl.RowEvenOdd);
/* Write number of question */
HTM_DIV_Begin ("class=\"BIG_INDEX\"");
HTM_Txt (StrQstInd);
HTM_DIV_End ();
/* Write answer type (row[2]) */
HTM_DIV_Begin ("class=\"DAT_SMALL\"");
if (QstExists)
{
Gbl.Test.AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[2]);
HTM_Txt (Txt_TST_STR_ANSWER_TYPES[Gbl.Test.AnswerType]);
}
HTM_DIV_End ();
HTM_TD_End ();
/***** Write question code *****/
HTM_TD_Begin ("class=\"DAT_SMALL CT COLOR%u\"",Gbl.RowEvenOdd);
HTM_TxtF ("%ld ",Gbl.Test.QstCod);
HTM_TD_End ();
/***** Write the question tags *****/
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
if (QstExists)
Tst_GetAndWriteTagsQst (Gbl.Test.QstCod);
HTM_TD_End ();
/***** Write stem and media (row[4]) *****/
HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
if (QstExists)
{
/* Write stem */
Tst_WriteQstStem (row[4],"TEST_EDI",
true); // Visible
/* Get media (row[6]) */
Gbl.Test.Media.MedCod = Str_ConvertStrCodToLongCod (row[6]);
Med_GetMediaDataByCod (&Gbl.Test.Media);
/* Show media */
Med_ShowMedia (&Gbl.Test.Media,
"TEST_MED_EDIT_LIST_STEM_CONTAINER",
"TEST_MED_EDIT_LIST_STEM");
/* Show feedback (row[5]) */
Tst_WriteQstFeedback (row[5],"TEST_EDI_LIGHT");
/* Show answers */
Tst_WriteAnswersEdit (Gbl.Test.QstCod);
}
else
{
HTM_SPAN_Begin ("class=\"DAT_LIGHT\"");
HTM_Txt (Txt_Question_removed);
HTM_SPAN_End ();
}
HTM_TD_End ();
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
/*****************************************************************************/ /*****************************************************************************/
/***************** Put icon to add a new questions to game *******************/ /***************** Put icon to add a new questions to game *******************/
/*****************************************************************************/ /*****************************************************************************/

View File

@ -25,6 +25,8 @@
/*********************************** Headers *********************************/ /*********************************** Headers *********************************/
/*****************************************************************************/ /*****************************************************************************/
#include <string.h> // For strlen
#include "swad_action.h" #include "swad_action.h"
#include "swad_config.h" #include "swad_config.h"
#include "swad_database.h" #include "swad_database.h"
@ -71,6 +73,8 @@ void Log_LogAccess (const char *Comments)
{ {
long LogCod; long LogCod;
long ActCod = Act_GetActCod (Gbl.Action.Act); long ActCod = Act_GetActCod (Gbl.Action.Act);
size_t MaxLength;
char *CommentsDB;
Rol_Role_t RoleToStore = (Gbl.Action.Act == ActLogOut) ? Gbl.Usrs.Me.Role.LoggedBeforeCloseSession : Rol_Role_t RoleToStore = (Gbl.Action.Act == ActLogOut) ? Gbl.Usrs.Me.Role.LoggedBeforeCloseSession :
Gbl.Usrs.Me.Role.Logged; Gbl.Usrs.Me.Role.Logged;
@ -118,12 +122,23 @@ void Log_LogAccess (const char *Comments)
/* Log comments */ /* Log comments */
if (Comments) if (Comments)
DB_QueryINSERT ("can not log access (comments)", {
"INSERT INTO log_comments" MaxLength = strlen (Comments) * Str_MAX_BYTES_PER_CHAR;
" (LogCod,Comments)" if ((CommentsDB = (char *) malloc (MaxLength + 1)) != NULL)
" VALUES" {
" (%ld,'%s')", Str_Copy (CommentsDB,Comments,
LogCod,Comments); MaxLength);
Str_ChangeFormat (Str_FROM_TEXT,Str_TO_TEXT,
CommentsDB,MaxLength,true); // Avoid SQL injection
DB_QueryINSERT ("can not log access (comments)",
"INSERT INTO log_comments"
" (LogCod,Comments)"
" VALUES"
" (%ld,'%s')",
LogCod,CommentsDB);
free (CommentsDB);
}
}
/* Log search string */ /* Log search string */
if (Gbl.Search.LogSearch && Gbl.Search.Str[0]) if (Gbl.Search.LogSearch && Gbl.Search.Str[0])

View File

@ -2852,6 +2852,7 @@ static void Mch_ShowMatchTitle (const struct Match *Match)
static void Mch_ShowQuestionAndAnswersTch (const struct Match *Match) static void Mch_ShowQuestionAndAnswersTch (const struct Match *Match)
{ {
extern const char *Txt_MATCH_Paused; extern const char *Txt_MATCH_Paused;
extern const char *Txt_Question_removed;
MYSQL_RES *mysql_res; MYSQL_RES *mysql_res;
MYSQL_ROW row; MYSQL_ROW row;
@ -2866,64 +2867,69 @@ static void Mch_ShowQuestionAndAnswersTch (const struct Match *Match)
} }
/***** Get data of question from database *****/ /***** Get data of question from database *****/
if (!DB_QuerySELECT (&mysql_res,"can not get data of a question", if (DB_QuerySELECT (&mysql_res,"can not get data of a question",
"SELECT AnsType," // row[0] "SELECT AnsType," // row[0]
"Stem," // row[1] "Stem," // row[1]
"MedCod" // row[2] "MedCod" // row[2]
" FROM tst_questions" " FROM tst_questions"
" WHERE QstCod=%ld", " WHERE QstCod=%ld",
Match->Status.QstCod)) Match->Status.QstCod))
Ale_ShowAlert (Ale_ERROR,"Question doesn't exist.");
row = mysql_fetch_row (mysql_res);
/***** Show question *****/
/* Get answer type (row[0]) */
Gbl.Test.AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[0]);
if (Gbl.Test.AnswerType != Tst_ANS_UNIQUE_CHOICE)
Lay_ShowErrorAndExit ("Wrong answer type.");
HTM_DIV_Begin ("class=\"MCH_BOTTOM\""); // Bottom
/* Write stem (row[1]) */
Tst_WriteQstStem (row[1],"MCH_TCH_STEM",
true); // Visible
/* Get media (row[2]) */
Gbl.Test.Media.MedCod = Str_ConvertStrCodToLongCod (row[2]);
Med_GetMediaDataByCod (&Gbl.Test.Media);
/* Show media */
Med_ShowMedia (&Gbl.Test.Media,
"TEST_MED_EDIT_LIST_STEM_CONTAINER",
"TEST_MED_EDIT_LIST_STEM");
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
/***** Write answers? *****/
switch (Match->Status.Showing)
{ {
case Mch_ANSWERS: row = mysql_fetch_row (mysql_res);
if (Match->Status.Playing) // Match is being played
/* Write answers */ /***** Show question *****/
/* Get answer type (row[0]) */
Gbl.Test.AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[0]);
if (Gbl.Test.AnswerType != Tst_ANS_UNIQUE_CHOICE)
Lay_ShowErrorAndExit ("Wrong answer type.");
/* Begin container */
HTM_DIV_Begin ("class=\"MCH_BOTTOM\""); // Bottom
/* Write stem (row[1]) */
Tst_WriteQstStem (row[1],"MCH_TCH_STEM",
true); // Visible
/* Get media (row[2]) */
Gbl.Test.Media.MedCod = Str_ConvertStrCodToLongCod (row[2]);
Med_GetMediaDataByCod (&Gbl.Test.Media);
/* Show media */
Med_ShowMedia (&Gbl.Test.Media,
"TEST_MED_EDIT_LIST_STEM_CONTAINER",
"TEST_MED_EDIT_LIST_STEM");
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
/***** Write answers? *****/
switch (Match->Status.Showing)
{
case Mch_ANSWERS:
if (Match->Status.Playing) // Match is being played
/* Write answers */
Mch_WriteAnswersMatchResult (Match,
"MCH_TCH_ANS",
false); // Don't show result
else // Match is paused, not being played
Mch_ShowWaitImage (Txt_MATCH_Paused);
break;
case Mch_RESULTS:
/* Write answers with results */
Mch_WriteAnswersMatchResult (Match, Mch_WriteAnswersMatchResult (Match,
"MCH_TCH_ANS", "MCH_TCH_ANS",
false); // Don't show result true); // Show result
else // Match is paused, not being played break;
Mch_ShowWaitImage (Txt_MATCH_Paused); default:
break; /* Don't write anything */
case Mch_RESULTS: break;
/* Write answers with results */ }
Mch_WriteAnswersMatchResult (Match,
"MCH_TCH_ANS",
true); // Show result
break;
default:
/* Don't write anything */
break;
}
HTM_DIV_End (); // Bottom /* End container */
HTM_DIV_End (); // Bottom
}
else
Ale_ShowAlert (Ale_WARNING,Txt_Question_removed);
} }
/*****************************************************************************/ /*****************************************************************************/

View File

@ -1616,7 +1616,9 @@ static unsigned long Tst_GetEnabledTagsFromThisCrs (MYSQL_RES **mysql_res)
{ {
/***** Get available not hidden tags from database *****/ /***** Get available not hidden tags from database *****/
return DB_QuerySELECT (mysql_res,"can not get available enabled tags", return DB_QuerySELECT (mysql_res,"can not get available enabled tags",
"SELECT TagCod,TagTxt FROM tst_tags" "SELECT TagCod," // row[0]
"TagTxt" // row[1]
" FROM tst_tags"
" WHERE CrsCod=%ld AND TagHidden='N'" " WHERE CrsCod=%ld AND TagHidden='N'"
" ORDER BY TagTxt", " ORDER BY TagTxt",
Gbl.Hierarchy.Crs.CrsCod); Gbl.Hierarchy.Crs.CrsCod);
@ -6552,7 +6554,7 @@ void Tst_RemoveQst (void)
Gbl.Test.QstCod,Gbl.Hierarchy.Crs.CrsCod); Gbl.Test.QstCod,Gbl.Hierarchy.Crs.CrsCod);
if (!mysql_affected_rows (&Gbl.mysql)) if (!mysql_affected_rows (&Gbl.mysql))
Lay_ShowErrorAndExit ("The question to be removed does not exist or belongs to another course."); Lay_ShowErrorAndExit ("Wrong question.");
/***** Write message *****/ /***** Write message *****/
Ale_ShowAlert (Ale_SUCCESS,Txt_Question_removed); Ale_ShowAlert (Ale_SUCCESS,Txt_Question_removed);