From 9164c0c8a409795dc9fa4324338f8c90e92dfd5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Ca=C3=B1as=20Vargas?= Date: Mon, 16 Sep 2019 00:15:40 +0200 Subject: [PATCH] Version19.3 --- css/{swad18.138.css => swad19.3.css} | 43 ++++++- sql/swad.sql | 2 +- swad_changelog.h | 9 +- swad_database.c | 32 +++--- swad_match.c | 161 ++++++++++++++------------- swad_match.h | 4 +- swad_test.c | 75 +++++++------ 7 files changed, 193 insertions(+), 133 deletions(-) rename css/{swad18.138.css => swad19.3.css} (99%) diff --git a/css/swad18.138.css b/css/swad19.3.css similarity index 99% rename from css/swad18.138.css rename to css/swad19.3.css index 785403a91..d7d511461 100644 --- a/css/swad18.138.css +++ b/css/swad19.3.css @@ -2705,7 +2705,13 @@ a:hover img.CENTRE_PHOTO_SHOW opacity:0.1; } -.MATCH_TCH_QST +.MATCH_TCH_STEM + { + color:#202020; + font-size:24pt; + padding-bottom:12pt; + } +.MATCH_TCH_ANS { color:#202020; font-size:24pt; @@ -2728,6 +2734,13 @@ a:hover img.CENTRE_PHOTO_SHOW font-size:24pt; } +.MATCH_TCH_BUTTON_TD + { + box-sizing:border-box; + width:84px; + text-align:center; + vertical-align:middle; + } .MATCH_TCH_BUTTON { box-sizing:border-box; @@ -2770,6 +2783,34 @@ a:hover img.CENTRE_PHOTO_SHOW box-shadow: 0px 0px 18px 12px rgba(0,128,0,1); } +.MATCH_RESULT + { + padding:10px 0; + color:#606060; + font-size:16pt; + text-align:left; + vertical-align:top; + } +.MATCH_RES_TR + { + height:24px; + } +.MATCH_RES_CORRECT + { + width:1%; + background:green; + } +.MATCH_RES_WRONG + { + width:1%; + background:red; + } +.MATCH_RES_VOID + { + width:1%; + background:white; + } + .BT_A {background-color:#e21c3d; border-color:#a9152d;} /* red */ .BT_B {background-color:#1369ce; border-color:#0e519c;} /* blue */ .BT_C {background-color:#d89e00; border-color:#a27600;} /* yellow */ diff --git a/sql/swad.sql b/sql/swad.sql index 639d97da5..d4d9e5dd0 100644 --- a/sql/swad.sql +++ b/sql/swad.sql @@ -640,7 +640,7 @@ CREATE TABLE IF NOT EXISTS gam_matches ( QstCod INT NOT NULL DEFAULT -1, QstStartTime DATETIME NOT NULL, ShowResults ENUM('N','Y') NOT NULL DEFAULT 'Y', - Showing ENUM('wording','answers','results') NOT NULL DEFAULT 'wording', + Showing ENUM('stem','answers','results') NOT NULL DEFAULT 'stem', UNIQUE INDEX(MchCod), INDEX(GamCod)); -- diff --git a/swad_changelog.h b/swad_changelog.h index 6577249ea..c0ea53d21 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -460,10 +460,15 @@ En OpenSWAD: ps2pdf source.ps destination.pdf */ -#define Log_PLATFORM_VERSION "SWAD 19.2.1 (2019-09-14)" -#define CSS_FILE "swad18.138.css" +#define Log_PLATFORM_VERSION "SWAD 19.3 (2019-09-15)" +#define CSS_FILE "swad19.3.css" #define JS_FILE "swad18.130.2.js" /* + Version 19.3: Sep 15, 2019 Changes in match results. (244680 lines) + 2 changes necessary in database: +ALTER TABLE gam_matches DROP COLUMN Showing; +ALTER TABLE gam_matches ADD COLUMN Showing ENUM('stem','answers','results') NOT NULL DEFAULT 'stem' AFTER ShowResults; + Version 19.2.1: Sep 14, 2019 Show results in match is the default. (244630 lines) 1 change necessary in database: ALTER TABLE gam_matches CHANGE COLUMN ShowResults ShowResults ENUM('N','Y') NOT NULL DEFAULT 'Y'; diff --git a/swad_database.c b/swad_database.c index c6dd33fa9..09d32d423 100644 --- a/swad_database.c +++ b/swad_database.c @@ -1369,21 +1369,21 @@ mysql> DESCRIBE gam_grp; /***** Table gam_matches *****/ /* mysql> DESCRIBE gam_matches; -+--------------+-------------------------------------+------+-----+---------+----------------+ -| Field | Type | Null | Key | Default | Extra | -+--------------+-------------------------------------+------+-----+---------+----------------+ -| MchCod | int(11) | NO | PRI | NULL | auto_increment | -| GamCod | int(11) | NO | MUL | NULL | | -| UsrCod | int(11) | NO | | NULL | | -| StartTime | datetime | NO | | NULL | | -| EndTime | datetime | NO | | NULL | | -| Title | varchar(2047) | NO | | NULL | | -| QstInd | int(11) | NO | | 0 | | -| QstCod | int(11) | NO | | -1 | | -| QstStartTime | datetime | NO | | NULL | | -| ShowResults | enum('N','Y') | NO | | Y | | -| Showing | enum('wording','answers','results') | NO | | wording | | -+--------------+-------------------------------------+------+-----+---------+----------------+ ++--------------+----------------------------------+------+-----+---------+----------------+ +| Field | Type | Null | Key | Default | Extra | ++--------------+----------------------------------+------+-----+---------+----------------+ +| MchCod | int(11) | NO | PRI | NULL | auto_increment | +| GamCod | int(11) | NO | MUL | NULL | | +| UsrCod | int(11) | NO | | NULL | | +| StartTime | datetime | NO | | NULL | | +| EndTime | datetime | NO | | NULL | | +| Title | varchar(2047) | NO | | NULL | | +| QstInd | int(11) | NO | | 0 | | +| QstCod | int(11) | NO | | -1 | | +| QstStartTime | datetime | NO | | NULL | | +| ShowResults | enum('N','Y') | NO | | Y | | +| Showing | enum('stem','answers','results') | NO | | stem | | ++--------------+----------------------------------+------+-----+---------+----------------+ 11 rows in set (0.00 sec) */ DB_CreateTable ("CREATE TABLE IF NOT EXISTS gam_matches (" @@ -1397,7 +1397,7 @@ mysql> DESCRIBE gam_matches; "QstCod INT NOT NULL DEFAULT -1," "QstStartTime DATETIME NOT NULL," "ShowResults ENUM('N','Y') NOT NULL DEFAULT 'Y'," - "Showing ENUM('wording','answers','request','results') NOT NULL DEFAULT 'wording'," + "Showing ENUM('stem','answers','request','results') NOT NULL DEFAULT 'stem'," "UNIQUE INDEX(MchCod)," "INDEX(GamCod)"); diff --git a/swad_match.c b/swad_match.c index aec8b9e1a..fa149c5bb 100644 --- a/swad_match.c +++ b/swad_match.c @@ -71,11 +71,11 @@ extern struct Globals Gbl; #define Mch_NUM_SHOWING 3 typedef enum { - Mch_WORDING, // Showing only the question wording - Mch_ANSWERS, // Showing the question wording and the answers + Mch_STEM, // Showing only the question stem + Mch_ANSWERS, // Showing the question stem and the answers Mch_RESULTS, // Showing the results } Mch_Showing_t; -#define Mch_SHOWING_DEFAULT Mch_WORDING +#define Mch_SHOWING_DEFAULT Mch_STEM struct Match { @@ -102,7 +102,7 @@ struct Match const char *Mch_ShowingStringsDB[Mch_NUM_SHOWING] = { - "wording", + "stem", "answers", "results", }; @@ -183,9 +183,8 @@ static void Mch_GetNumPlayers (struct Match *Match); static int Mch_GetQstAnsFromDB (long MchCod,unsigned QstInd); -static unsigned Mch_GetNumAnswerers (struct Match *Match); -static unsigned Mch_GetNumUsrsWhoAnswered (long MchCod,unsigned QstInd,unsigned AnsInd); -static void Mch_DrawBarNumUsrs (unsigned NumUsrs,unsigned MaxUsrs); +static unsigned Mch_GetNumUsrsWhoHaveChosenAns (long MchCod,unsigned QstInd,unsigned AnsInd); +static void Mch_DrawBarNumUsrs (unsigned NumAnswerersAns,unsigned NumAnswerersQst,bool Correct); /*****************************************************************************/ /************************* List the matches of a game ************************/ @@ -318,7 +317,7 @@ static void Mch_GetDataOfMatchByCod (struct Match *Match) Match->Status.QstCod = -1L; Match->Status.QstStartTimeUTC = (time_t) 0; Match->Status.ShowResults = true; - Match->Status.Showing = Mch_WORDING; + Match->Status.Showing = Mch_STEM; Match->Status.BeingPlayed = false; } @@ -1335,7 +1334,7 @@ static void Mch_SetMatchStatusToPrev (struct Match *Match) /***** What to show *****/ switch (Match->Status.Showing) { - case Mch_WORDING: + case Mch_STEM: Match->Status.Showing = Match->Status.ShowResults ? Mch_RESULTS : Mch_ANSWERS; @@ -1352,7 +1351,7 @@ static void Mch_SetMatchStatusToPrev (struct Match *Match) Match->Status.QstInd); break; case Mch_ANSWERS: - Match->Status.Showing = Mch_WORDING; + Match->Status.Showing = Mch_STEM; break; case Mch_RESULTS: Match->Status.Showing = Mch_ANSWERS; @@ -1369,20 +1368,20 @@ static void Mch_SetMatchStatusToNext (struct Match *Match) /***** What to show *****/ switch (Match->Status.Showing) { - case Mch_WORDING: + case Mch_STEM: Match->Status.Showing = Mch_ANSWERS; break; case Mch_ANSWERS: Match->Status.Showing = Match->Status.ShowResults ? Mch_RESULTS : - Mch_WORDING; + Mch_STEM; break; case Mch_RESULTS: - Match->Status.Showing = Mch_WORDING; + Match->Status.Showing = Mch_STEM; break; } /***** Go to next question? *****/ - if (Match->Status.Showing == Mch_WORDING) + if (Match->Status.Showing == Mch_STEM) { /***** Get index of the next question *****/ Match->Status.QstInd = Gam_GetNextQuestionIndexInGame (Match->GamCod, @@ -1498,7 +1497,7 @@ static void Mch_ShowLeftColumnTch (struct Match *Match) { extern const char *Txt_MATCH_respond; struct Time Time; - unsigned NumAnswerers; + unsigned NumAnswerersQst; /***** Start left container *****/ fprintf (Gbl.F.Out,"
"); @@ -1536,16 +1535,17 @@ static void Mch_ShowLeftColumnTch (struct Match *Match) /***** Number of players *****/ Mch_ShowNumPlayers (Match); - /***** Number of users who have answered *****/ + /***** Number of users who have answered this question *****/ if (Match->Status.BeingPlayed) { - NumAnswerers = Mch_GetNumAnswerers (Match); + NumAnswerersQst = Mch_GetNumUsrsWhoHaveAnswerQst (Match->MchCod, + Match->Status.QstInd); fprintf (Gbl.F.Out,"
" "%s
" "%u/%u" "
", Txt_MATCH_respond, - NumAnswerers,Match->Status.NumPlayers); + NumAnswerersQst,Match->Status.NumPlayers); } /***** End left container *****/ @@ -1751,10 +1751,10 @@ static void Mch_ShowQuestionAndAnswersTch (struct Match *Match) Gbl.Test.AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[0]); // TODO: Check that answer type is correct (unique choice) - fprintf (Gbl.F.Out,"
"); + fprintf (Gbl.F.Out,"
"); // Bottom /* Write stem (row[1]) */ - Tst_WriteQstStem (row[1],"MATCH_TCH_QST"); + Tst_WriteQstStem (row[1],"MATCH_TCH_STEM"); /* Get media (row[2]) */ Gbl.Test.Media.MedCod = Str_ConvertStrCodToLongCod (row[2]); @@ -1768,17 +1768,18 @@ static void Mch_ShowQuestionAndAnswersTch (struct Match *Match) /* Write answers? */ switch (Match->Status.Showing) { - case Mch_WORDING: + case Mch_STEM: /* Don't write anything */ break; case Mch_ANSWERS: - if (Match->Status.BeingPlayed) + if (Match->Status.BeingPlayed) // Being played /* Write answers */ Tst_WriteAnswersMatchResult (Match->MchCod, Match->Status.QstInd, Match->Status.QstCod, - "MATCH_TCH_QST",false); // Don't show result - else // Not being played + "MATCH_TCH_ANS", + false); // Don't show result + else // Not being played Mch_ShowWaitImage (Txt_MATCH_Paused); break; case Mch_RESULTS: @@ -1786,11 +1787,12 @@ static void Mch_ShowQuestionAndAnswersTch (struct Match *Match) Tst_WriteAnswersMatchResult (Match->MchCod, Match->Status.QstInd, Match->Status.QstCod, - "MATCH_TCH_QST",true); // Show result + "MATCH_TCH_ANS", + true); // Show result break; } - fprintf (Gbl.F.Out,"
"); + fprintf (Gbl.F.Out,"
"); // Bottom } /*****************************************************************************/ @@ -2259,92 +2261,101 @@ void Mch_ReceiveQstAnsFromStd (void) fprintf (Gbl.F.Out,"
"); } -/*****************************************************************************/ -/***** Get number of users who have answered current question in a match *****/ -/*****************************************************************************/ - -static unsigned Mch_GetNumAnswerers (struct Match *Match) - { - /***** Get number of users who have answered the current question in a match from database *****/ - return - (unsigned) DB_QueryCOUNT ("can not get number of questions of a game", - "SELECT COUNT(*) FROM gam_answers" - " WHERE MchCod=%ld AND QstInd=%u", - Match->MchCod, - Match->Status.QstInd); - } - /*****************************************************************************/ /*** Get number of users who selected this answer and draw proportional bar **/ /*****************************************************************************/ -void Mch_GetAndDrawBarNumUsrsWhoAnswered (long MchCod,unsigned QstInd,unsigned AnsInd,unsigned NumUsrs) +void Mch_GetAndDrawBarNumUsrsWhoHaveChosenAns (long MchCod,unsigned QstInd,unsigned AnsInd, + unsigned NumAnswerersQst,bool Correct) { - unsigned NumUsrsThisAnswer; + unsigned NumAnswerersAns; /***** Get number of users who selected this answer *****/ - NumUsrsThisAnswer = Mch_GetNumUsrsWhoAnswered (MchCod,QstInd,AnsInd); + NumAnswerersAns = Mch_GetNumUsrsWhoHaveChosenAns (MchCod,QstInd,AnsInd); /***** Show stats of this answer *****/ - Mch_DrawBarNumUsrs (NumUsrsThisAnswer,NumUsrs); + Mch_DrawBarNumUsrs (NumAnswerersAns,NumAnswerersQst,Correct); } /*****************************************************************************/ -/**** Get number of users who selected a given answer of a game question *****/ +/******* Get number of users who have answered a question in a match *********/ /*****************************************************************************/ -static unsigned Mch_GetNumUsrsWhoAnswered (long MchCod,unsigned QstInd,unsigned AnsInd) +unsigned Mch_GetNumUsrsWhoHaveAnswerQst (long MchCod,unsigned QstInd) + { + /***** Get number of users who have answered + a question in a match from database *****/ + return + (unsigned) DB_QueryCOUNT ("can not get number of users who hasve answered a question", + "SELECT COUNT(*) FROM gam_answers" + " WHERE MchCod=%ld AND QstInd=%u", + MchCod,QstInd); + } + +/*****************************************************************************/ +/*** Get number of users who have chosen a given answer of a game question ***/ +/*****************************************************************************/ + +static unsigned Mch_GetNumUsrsWhoHaveChosenAns (long MchCod,unsigned QstInd,unsigned AnsInd) { /***** Get number of users who have chosen an answer of a question from database *****/ - return (unsigned) DB_QueryCOUNT ("can not get number of users who answered", - "SELECT COUNT(*)" - " FROM gam_answers" - " WHERE MchCod=%ld" - " AND QstInd=%u" - " AND AnsInd=%u", - MchCod,QstInd,AnsInd); + return + (unsigned) DB_QueryCOUNT ("can not get number of users who have chosen an answer", + "SELECT COUNT(*) FROM gam_answers" + " WHERE MchCod=%ld AND QstInd=%u AND AnsInd=%u", + MchCod,QstInd,AnsInd); } /*****************************************************************************/ /***************** Draw a bar with the percentage of answers *****************/ /*****************************************************************************/ -#define Gam_MAX_BAR_WIDTH 125 +// #define Mch_MAX_BAR_WIDTH 400 +#define Mch_MAX_BAR_WIDTH 100 -static void Mch_DrawBarNumUsrs (unsigned NumUsrs,unsigned MaxUsrs) +static void Mch_DrawBarNumUsrs (unsigned NumAnswerersAns,unsigned NumAnswerersQst,bool Correct) { extern const char *Txt_of_PART_OF_A_TOTAL; + unsigned i; unsigned BarWidth = 0; /***** String with the number of users *****/ - if (MaxUsrs) + if (NumAnswerersQst) snprintf (Gbl.Title,sizeof (Gbl.Title), "%u (%u%% %s %u)", - NumUsrs, - (unsigned) ((((float) NumUsrs * 100.0) / (float) MaxUsrs) + 0.5), - Txt_of_PART_OF_A_TOTAL,MaxUsrs); + NumAnswerersAns, + (unsigned) ((((float) NumAnswerersAns * 100.0) / (float) NumAnswerersQst) + 0.5), + Txt_of_PART_OF_A_TOTAL,NumAnswerersQst); else snprintf (Gbl.Title,sizeof (Gbl.Title), "0 (0%% %s %u)", - Txt_of_PART_OF_A_TOTAL,MaxUsrs); + Txt_of_PART_OF_A_TOTAL,NumAnswerersQst); + + /***** Start container *****/ + fprintf (Gbl.F.Out,"
"); /***** Draw bar with a with proportional to the number of clicks *****/ - if (NumUsrs && MaxUsrs) - BarWidth = (unsigned) ((((float) NumUsrs * (float) Gam_MAX_BAR_WIDTH) / - (float) MaxUsrs) + 0.5); - if (BarWidth < 2) - BarWidth = 2; - fprintf (Gbl.F.Out,"\"%s\"" - " ", - Cfg_URL_ICON_PUBLIC, - Gbl.Title, - Gbl.Title, - BarWidth); + if (NumAnswerersAns && NumAnswerersQst) + BarWidth = (unsigned) ((((float) NumAnswerersAns * (float) Mch_MAX_BAR_WIDTH) / + (float) NumAnswerersQst) + 0.5); + + /***** Bar proportional to number of users *****/ + Tbl_StartTableWide (0); + fprintf (Gbl.F.Out,""); + for (i = 0; + i < 100; + i++) + fprintf (Gbl.F.Out,"", + (i < BarWidth) ? (Correct ? "MATCH_RES_CORRECT" : + "MATCH_RES_WRONG") : + "MATCH_RES_VOID"); + fprintf (Gbl.F.Out,""); + Tbl_EndTable (); /***** Write the number of users *****/ fprintf (Gbl.F.Out,"%s",Gbl.Title); + + /***** End container *****/ + fprintf (Gbl.F.Out,"
"); } diff --git a/swad_match.h b/swad_match.h index 638ac9f89..492e73c82 100644 --- a/swad_match.h +++ b/swad_match.h @@ -63,6 +63,8 @@ void Mch_RefreshMatchStd (void); void Mch_ReceiveQstAnsFromStd (void); -void Mch_GetAndDrawBarNumUsrsWhoAnswered (long MchCod,unsigned QstInd,unsigned AnsInd,unsigned NumUsrs); +void Mch_GetAndDrawBarNumUsrsWhoHaveChosenAns (long MchCod,unsigned QstInd,unsigned AnsInd, + unsigned NumAnswerersQst,bool Correct); +unsigned Mch_GetNumUsrsWhoHaveAnswerQst (long MchCod,unsigned QstInd); #endif diff --git a/swad_test.c b/swad_test.c index 8e9de988c..718874a74 100644 --- a/swad_test.c +++ b/swad_test.c @@ -210,9 +210,9 @@ static void Tst_WriteChoiceAnsViewTest (unsigned NumQst,long QstCod,bool Shuffle static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat, unsigned NumQst,MYSQL_RES *mysql_res, double *ScoreThisQst,bool *AnswerIsNotBlank); -static void Tst_WriteChoiceAnsViewGame (long MchCod,unsigned QstInd,long QstCod, - const char *Class, - bool ShowResult); +static void Tst_WriteChoiceAnsViewMatch (long MchCod,unsigned QstInd,long QstCod, + const char *Class, + bool ShowResult); static void Tst_WriteTextAnsViewTest (unsigned NumQst); static void Tst_WriteTextAnsAssessTest (struct UsrData *UsrDat, @@ -3531,8 +3531,8 @@ void Tst_WriteAnswersMatchResult (long MchCod,unsigned QstInd,long QstCod, { /***** Write answer depending on type *****/ if (Gbl.Test.AnswerType == Tst_ANS_UNIQUE_CHOICE) - Tst_WriteChoiceAnsViewGame (MchCod,QstInd,QstCod, - Class,ShowResult); + Tst_WriteChoiceAnsViewMatch (MchCod,QstInd,QstCod, + Class,ShowResult); else Ale_ShowAlert (Ale_ERROR,"Type of answer not valid in a game."); } @@ -4042,19 +4042,24 @@ static void Tst_WriteChoiceAnsAssessTest (struct UsrData *UsrDat, } /*****************************************************************************/ -/******** Write single or multiple choice answer when viewing a test *********/ +/******** Write single or multiple choice answer when viewing a match ********/ /*****************************************************************************/ -static void Tst_WriteChoiceAnsViewGame (long MchCod,unsigned QstInd,long QstCod, - const char *Class, - bool ShowResult) +static void Tst_WriteChoiceAnsViewMatch (long MchCod,unsigned QstInd,long QstCod, + const char *Class, + bool ShowResult) { unsigned NumOpt; MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned AnsInd; + unsigned NumAnswerersQst; + bool Correct; bool ErrorInIndex = false; + /***** Get number of users who hasve answered this question from database *****/ + NumAnswerersQst = Mch_GetNumUsrsWhoHaveAnswerQst (MchCod,QstInd); + /***** Get answers of a question from database *****/ Gbl.Test.Answer.NumOptions = Tst_GetAnswersQst (QstCod,&mysql_res,false); /* @@ -4066,7 +4071,7 @@ static void Tst_WriteChoiceAnsViewGame (long MchCod,unsigned QstInd,long QstCod, */ /***** Start table *****/ - Tbl_StartTable (2); + Tbl_StartTableWide (2); for (NumOpt = 0; NumOpt < Gbl.Test.Answer.NumOptions; @@ -4104,24 +4109,19 @@ static void Tst_WriteChoiceAnsViewGame (long MchCod,unsigned QstInd,long QstCod, Gbl.Test.Answer.Options[NumOpt].Media.MedCod = Str_ConvertStrCodToLongCod (row[3]); Med_GetMediaDataByCod (&Gbl.Test.Answer.Options[NumOpt].Media); - /***** Write letter for this option *****/ - fprintf (Gbl.F.Out,"" - "" - "
" - "%c) ", - Class, - 'a' + (char) NumOpt); - else - fprintf (Gbl.F.Out,"MATCH_TCH_BUTTON BT_%c\">" - "%c", - 'A' + (char) NumOpt, - 'a' + (char) NumOpt); - fprintf (Gbl.F.Out,"
" - ""); + /***** Start row for this option *****/ + fprintf (Gbl.F.Out,""); - /***** Write the option text *****/ + /***** Write letter for this option *****/ + fprintf (Gbl.F.Out,"" + "
" + "%c" + "
" + "", + 'A' + (char) NumOpt, + 'a' + (char) NumOpt); + + /***** Write the option text and the result *****/ fprintf (Gbl.F.Out,"" "