From ebf73792a5adc06e39a3f01921ad9af0e2991f62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Ca=C3=B1as=20Vargas?= Date: Sat, 7 Mar 2020 00:14:35 +0100 Subject: [PATCH] Version19.145 --- swad_changelog.h | 12 ++-- swad_enrolment.c | 2 +- swad_game.c | 173 ++++++++++++++++++++++++++++++----------------- swad_log.c | 27 ++++++-- swad_match.c | 114 ++++++++++++++++--------------- swad_test.c | 6 +- 6 files changed, 200 insertions(+), 134 deletions(-) diff --git a/swad_changelog.h b/swad_changelog.h index 15cc5c106..9a498a03b 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -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.144.3 (2020-03-06)" +#define Log_PLATFORM_VERSION "SWAD 19.145 (2020-03-07)" #define CSS_FILE "swad19.144.1.css" #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: 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: Comprobar los resultados de partidas de juegos con preguntas eliminadas -// TODO: URGENTE: Reportado por Eva Martínez Ortigosa - Sea un juego tiene dos preguntas: 1 y 2 - 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.145: Mar 07, 2020 Fixed bug in log. + Fixed bug in matches, reported by Eva Martínez Ortigosa. (282346 lines) Version 19.144.3: Mar 06, 2020 New social network: twitch. (282286 lines) 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; diff --git a/swad_enrolment.c b/swad_enrolment.c index b2b413777..7b1a26cfe 100644 --- a/swad_enrolment.c +++ b/swad_enrolment.c @@ -4140,7 +4140,7 @@ static void Enr_EffectivelyRemUsrFromCrs (struct UsrData *UsrDat, } 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->Roles.InCurrentCrs.Role = Rol_USR; UsrDat->Roles.InCurrentCrs.Valid = false; diff --git a/swad_game.c b/swad_game.c index 7afee0202..80a18dd63 100644 --- a/swad_game.c +++ b/swad_game.c @@ -151,6 +151,7 @@ static void Gam_ListGameQuestions (struct Game *Game); static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts, MYSQL_RES *mysql_res, bool ICanEditQuestions); +static void Gam_ListQuestionForEdition (const char *StrQstInd); static void Gam_PutIconToAddNewQuestions (void); static void Gam_PutButtonToAddNewQuestions (void); @@ -1746,7 +1747,7 @@ unsigned Gam_GetNextQuestionIndexInGame (long GamCod,unsigned QstInd) { MYSQL_RES *mysql_res; 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 *****/ // Although indexes are always continuous... @@ -1784,18 +1785,14 @@ static void Gam_ListGameQuestions (struct Game *Game) bool ICanEditQuestions = Gam_CheckIfEditable (Game); /***** Get data of questions from database *****/ - NumQsts = (unsigned) DB_QuerySELECT (&mysql_res,"can not get data of a question", - "SELECT gam_questions.QstInd," // row[0] - "gam_questions.QstCod," // row[1] - "tst_questions.AnsType," // row[2] - "tst_questions.Stem," // row[3] - "tst_questions.Feedback," // row[4] - "tst_questions.MedCod" // row[5] - " FROM gam_questions,tst_questions" - " WHERE gam_questions.GamCod=%ld" - " AND gam_questions.QstCod=tst_questions.QstCod" - " ORDER BY gam_questions.QstInd", - Game->GamCod); + NumQsts = (unsigned) + DB_QuerySELECT (&mysql_res,"can not get game questions", + "SELECT QstInd," // row[0] + "QstCod" // row[1] + " FROM gam_questions" + " WHERE GamCod=%ld" + " ORDER BY QstInd", + Game->GamCod); /***** Begin box *****/ 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_down_X; extern const char *Txt_Movement_not_allowed; - extern const char *Txt_TST_STR_ANSWER_TYPES[Tst_NUM_ANS_TYPES]; unsigned NumQst; MYSQL_ROW row; unsigned QstInd; @@ -1871,10 +1867,6 @@ static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts, /* row[0] QstInd row[1] QstCod - row[2] AnsType - row[3] Stem - row[4] Feedback - row[5] MedCod */ /***** Create test question *****/ Tst_QstConstructor (); @@ -1937,52 +1929,9 @@ static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts, 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 (); /***** Destroy test question *****/ @@ -1993,6 +1942,104 @@ static void Gam_ListOneOrMoreQuestionsForEdition (long GamCod,unsigned NumQsts, 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 *******************/ /*****************************************************************************/ diff --git a/swad_log.c b/swad_log.c index 8848f6357..e59d0d59a 100644 --- a/swad_log.c +++ b/swad_log.c @@ -25,6 +25,8 @@ /*********************************** Headers *********************************/ /*****************************************************************************/ +#include // For strlen + #include "swad_action.h" #include "swad_config.h" #include "swad_database.h" @@ -71,6 +73,8 @@ void Log_LogAccess (const char *Comments) { long LogCod; 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 : Gbl.Usrs.Me.Role.Logged; @@ -118,12 +122,23 @@ void Log_LogAccess (const char *Comments) /* Log comments */ if (Comments) - DB_QueryINSERT ("can not log access (comments)", - "INSERT INTO log_comments" - " (LogCod,Comments)" - " VALUES" - " (%ld,'%s')", - LogCod,Comments); + { + MaxLength = strlen (Comments) * Str_MAX_BYTES_PER_CHAR; + if ((CommentsDB = (char *) malloc (MaxLength + 1)) != NULL) + { + Str_Copy (CommentsDB,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 */ if (Gbl.Search.LogSearch && Gbl.Search.Str[0]) diff --git a/swad_match.c b/swad_match.c index a549a2356..a2ae0a33f 100644 --- a/swad_match.c +++ b/swad_match.c @@ -2852,6 +2852,7 @@ static void Mch_ShowMatchTitle (const struct Match *Match) static void Mch_ShowQuestionAndAnswersTch (const struct Match *Match) { extern const char *Txt_MATCH_Paused; + extern const char *Txt_Question_removed; MYSQL_RES *mysql_res; MYSQL_ROW row; @@ -2866,64 +2867,69 @@ static void Mch_ShowQuestionAndAnswersTch (const struct Match *Match) } /***** Get data of question from database *****/ - if (!DB_QuerySELECT (&mysql_res,"can not get data of a question", - "SELECT AnsType," // row[0] - "Stem," // row[1] - "MedCod" // row[2] - " FROM tst_questions" - " WHERE QstCod=%ld", - 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) + if (DB_QuerySELECT (&mysql_res,"can not get data of a question", + "SELECT AnsType," // row[0] + "Stem," // row[1] + "MedCod" // row[2] + " FROM tst_questions" + " WHERE QstCod=%ld", + Match->Status.QstCod)) { - case Mch_ANSWERS: - if (Match->Status.Playing) // Match is being played - /* Write answers */ + 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."); + + /* 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_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_TCH_ANS", - true); // Show result - break; - default: - /* Don't write anything */ - break; - } + 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); } /*****************************************************************************/ diff --git a/swad_test.c b/swad_test.c index 0a1ab1e17..b15216f89 100644 --- a/swad_test.c +++ b/swad_test.c @@ -1616,7 +1616,9 @@ static unsigned long Tst_GetEnabledTagsFromThisCrs (MYSQL_RES **mysql_res) { /***** Get available not hidden tags from database *****/ 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'" " ORDER BY TagTxt", Gbl.Hierarchy.Crs.CrsCod); @@ -6552,7 +6554,7 @@ void Tst_RemoveQst (void) Gbl.Test.QstCod,Gbl.Hierarchy.Crs.CrsCod); 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 *****/ Ale_ShowAlert (Ale_SUCCESS,Txt_Question_removed);