mirror of
https://github.com/acanas/swad-core.git
synced 2024-06-08 01:35:32 +02:00
Version 21.6: Sep 18, 2021 New module swad_game_database for database queries related to games.
This commit is contained in:
parent
01b03ada43
commit
179fc2b6a0
6
Makefile
6
Makefile
|
@ -51,9 +51,9 @@ OBJS = swad_account.o swad_account_database.o swad_action.o swad_admin.o \
|
|||
swad_file_extension.o swad_file_MIME.o swad_firewall.o \
|
||||
swad_firewall_database.o swad_follow.o swad_follow_database.o \
|
||||
swad_form.o swad_forum.o swad_forum_database.o \
|
||||
swad_game.o swad_global.o swad_group.o swad_group_database.o \
|
||||
swad_help.o swad_hierarchy.o swad_hierarchy_config.o swad_holiday.o \
|
||||
swad_HTML.o \
|
||||
swad_game.o swad_game_database.o swad_global.o swad_group.o \
|
||||
swad_group_database.o swad_help.o swad_hierarchy.o \
|
||||
swad_hierarchy_config.o swad_holiday.o swad_HTML.o \
|
||||
swad_icon.o swad_ID.o swad_indicator.o swad_info.o swad_institution.o \
|
||||
swad_institution_config.o swad_institution_database.o \
|
||||
swad_language.o swad_layout.o swad_link.o swad_log.o swad_logo.o \
|
||||
|
|
|
@ -602,13 +602,14 @@ TODO: FIX BUG, URGENT! En las fechas como par
|
|||
|
||||
TODO: En las encuestas, que los estudiantes no puedan ver los resultados hasta que no finalice el plazo.
|
||||
*/
|
||||
#define Log_PLATFORM_VERSION "SWAD 21.5.3 (2021-09-16)"
|
||||
#define Log_PLATFORM_VERSION "SWAD 21.6 (2021-09-18)"
|
||||
#define CSS_FILE "swad20.45.css"
|
||||
#define JS_FILE "swad20.69.1.js"
|
||||
/*
|
||||
TODO: Rename CENTRE to CENTER in help wiki.
|
||||
TODO: Rename ASSESSMENT.Announcements to ASSESSMENT.Calls_for_exams
|
||||
|
||||
Version 21.6: Sep 18, 2021 New module swad_game_database for database queries related to games. (315565 lines)
|
||||
Version 21.5.3: Sep 16, 2021 Queries moved to module swad_forum_database. (315431 lines)
|
||||
Version 21.5.2: Sep 16, 2021 Queries moved to module swad_forum_database. (315403 lines)
|
||||
Version 21.5.1: Sep 15, 2021 Queries moved to module swad_forum_database. (315348 lines)
|
||||
|
|
381
swad_game.c
381
swad_game.c
|
@ -38,6 +38,7 @@
|
|||
#include "swad_figure.h"
|
||||
#include "swad_form.h"
|
||||
#include "swad_game.h"
|
||||
#include "swad_game_database.h"
|
||||
#include "swad_global.h"
|
||||
#include "swad_hierarchy_level.h"
|
||||
#include "swad_HTML.h"
|
||||
|
@ -867,63 +868,16 @@ static Gam_Order_t Gam_GetParamOrder (void)
|
|||
|
||||
void Gam_GetListGames (struct Gam_Games *Games,Gam_Order_t SelectedOrder)
|
||||
{
|
||||
static const char *OrderBySubQuery[Gam_NUM_ORDERS] =
|
||||
{
|
||||
[Gam_ORDER_BY_START_DATE] = "StartTime DESC,EndTime DESC,gam_games.Title DESC",
|
||||
[Gam_ORDER_BY_END_DATE ] = "EndTime DESC,StartTime DESC,gam_games.Title DESC",
|
||||
[Gam_ORDER_BY_TITLE ] = "gam_games.Title",
|
||||
};
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
char *HiddenSubQuery;
|
||||
unsigned NumGame;
|
||||
|
||||
/***** Free list of games *****/
|
||||
if (Games->LstIsRead)
|
||||
Gam_FreeListGames (Games);
|
||||
|
||||
/***** Subquery: get hidden games depending on user's role *****/
|
||||
switch (Gbl.Usrs.Me.Role.Logged)
|
||||
{
|
||||
case Rol_STD:
|
||||
if (asprintf (&HiddenSubQuery," AND gam_games.Hidden='N'") < 0)
|
||||
Err_NotEnoughMemoryExit ();
|
||||
break;
|
||||
case Rol_NET:
|
||||
case Rol_TCH:
|
||||
case Rol_DEG_ADM:
|
||||
case Rol_CTR_ADM:
|
||||
case Rol_INS_ADM:
|
||||
case Rol_SYS_ADM:
|
||||
if (asprintf (&HiddenSubQuery,"%s","") < 0)
|
||||
Err_NotEnoughMemoryExit ();
|
||||
break;
|
||||
default:
|
||||
Err_WrongRoleExit ();
|
||||
break;
|
||||
}
|
||||
|
||||
/***** Get list of games from database *****/
|
||||
Games->Num = (unsigned)
|
||||
DB_QuerySELECT (&mysql_res,"can not get games",
|
||||
"SELECT gam_games.GamCod," // row[0]
|
||||
"MIN(mch_matches.StartTime) AS StartTime," // row[1]
|
||||
"MAX(mch_matches.EndTime) AS EndTime" // row[2]
|
||||
" FROM gam_games"
|
||||
" LEFT JOIN mch_matches"
|
||||
" ON gam_games.GamCod=mch_matches.GamCod"
|
||||
" WHERE gam_games.CrsCod=%ld"
|
||||
"%s"
|
||||
" GROUP BY gam_games.GamCod"
|
||||
" ORDER BY %s",
|
||||
Gbl.Hierarchy.Crs.CrsCod,
|
||||
HiddenSubQuery,
|
||||
OrderBySubQuery[SelectedOrder]);
|
||||
|
||||
/***** Free allocated memory for subquery *****/
|
||||
free (HiddenSubQuery);
|
||||
|
||||
if (Games->Num) // Games found...
|
||||
if ((Games->Num = Gam_DB_GetListGames (&mysql_res,SelectedOrder))) // Games found...
|
||||
{
|
||||
/***** Create list of games *****/
|
||||
if ((Games->Lst = malloc ((size_t) Games->Num *
|
||||
|
@ -1026,21 +980,7 @@ void Gam_GetDataOfGameByCod (struct Gam_Game *Game)
|
|||
MYSQL_ROW row;
|
||||
|
||||
/***** Get data of game from database *****/
|
||||
if (DB_QuerySELECT (&mysql_res,"can not get game data",
|
||||
"SELECT gam_games.GamCod," // row[0]
|
||||
"gam_games.CrsCod," // row[1]
|
||||
"gam_games.Hidden," // row[2]
|
||||
"gam_games.UsrCod," // row[3]
|
||||
"gam_games.MaxGrade," // row[4]
|
||||
"gam_games.Visibility," // row[5]
|
||||
"gam_games.Title" // row[6]
|
||||
" FROM gam_games"
|
||||
" LEFT JOIN mch_matches"
|
||||
" ON gam_games.GamCod=mch_matches.GamCod"
|
||||
" WHERE gam_games.GamCod=%ld"
|
||||
" AND gam_games.CrsCod='%ld'", // Extra check
|
||||
Game->GamCod,
|
||||
Gbl.Hierarchy.Crs.CrsCod)) // Game found...
|
||||
if (Gam_DB_GetDataOfGameByCod (&mysql_res,Game->GamCod)) // Game found...
|
||||
{
|
||||
/* Get row */
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
|
@ -1072,10 +1012,10 @@ void Gam_GetDataOfGameByCod (struct Gam_Game *Game)
|
|||
Game->NumQsts = Gam_DB_GetNumQstsGame (Game->GamCod);
|
||||
|
||||
/* Get number of matches */
|
||||
Game->NumMchs = Mch_GetNumMchsInGame (Game->GamCod);
|
||||
Game->NumMchs = Mch_DB_GetNumMchsInGame (Game->GamCod);
|
||||
|
||||
/* Get number of unfinished matches */
|
||||
Game->NumUnfinishedMchs = Mch_GetNumUnfinishedMchsInGame (Game->GamCod);
|
||||
Game->NumUnfinishedMchs = Mch_DB_GetNumUnfinishedMchsInGame (Game->GamCod);
|
||||
}
|
||||
else
|
||||
/* Initialize to empty game */
|
||||
|
@ -1087,20 +1027,14 @@ void Gam_GetDataOfGameByCod (struct Gam_Game *Game)
|
|||
if (Game->GamCod > 0)
|
||||
{
|
||||
/***** Get start and end times from database *****/
|
||||
if (DB_QuerySELECT (&mysql_res,"can not get game data",
|
||||
"SELECT UNIX_TIMESTAMP(MIN(StartTime))," // row[0]
|
||||
"UNIX_TIMESTAMP(MAX(EndTime))" // row[1]
|
||||
" FROM mch_matches"
|
||||
" WHERE GamCod=%ld",
|
||||
Game->GamCod))
|
||||
if (Mch_DB_GetStartEndMatchesInGame (&mysql_res,Game->GamCod))
|
||||
{
|
||||
/* Get row */
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
|
||||
/* Get start date (row[0] holds the start UTC time) */
|
||||
/* Get start date (row[0] holds the start UTC time)
|
||||
and end date (row[1] holds the end UTC time) */
|
||||
Game->TimeUTC[Dat_START_TIME] = Dat_GetUNIXTimeFromStr (row[0]);
|
||||
|
||||
/* Get end date (row[1] holds the end UTC time) */
|
||||
Game->TimeUTC[Dat_END_TIME ] = Dat_GetUNIXTimeFromStr (row[1]);
|
||||
}
|
||||
|
||||
|
@ -1715,21 +1649,6 @@ static void Gam_UpdateGame (struct Gam_Game *Game,const char *Txt)
|
|||
Ale_ShowAlert (Ale_SUCCESS,Txt_The_game_has_been_modified);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************* Get number of questions of a game *********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
unsigned Gam_DB_GetNumQstsGame (long GamCod)
|
||||
{
|
||||
/***** Get nuumber of questions in a game from database *****/
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of questions of a game",
|
||||
"SELECT COUNT(*)"
|
||||
" FROM gam_questions"
|
||||
" WHERE GamCod=%ld",
|
||||
GamCod);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*************** Put a form to edit/create a question in game ****************/
|
||||
/*****************************************************************************/
|
||||
|
@ -1889,47 +1808,6 @@ static unsigned Gam_DB_GetMaxQuestionIndexInGame (long GamCod)
|
|||
GamCod);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*********** Get previous question index to a given index in a game **********/
|
||||
/*****************************************************************************/
|
||||
// Input question index can be 1, 2, 3... n-1
|
||||
// Return question index will be 1, 2, 3... n if previous question exists, or 0 if no previous question
|
||||
|
||||
unsigned Gam_DB_GetPrevQuestionIndexInGame (long GamCod,unsigned QstInd)
|
||||
{
|
||||
/***** Get previous question index in a game from database *****/
|
||||
// Although indexes are always continuous...
|
||||
// ...this implementation works even with non continuous indexes
|
||||
return DB_QuerySELECTUnsigned ("can not get previous question index",
|
||||
"SELECT COALESCE(MAX(QstInd),0)"
|
||||
" FROM gam_questions"
|
||||
" WHERE GamCod=%ld"
|
||||
" AND QstInd<%u",
|
||||
GamCod,
|
||||
QstInd);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/************* Get next question index to a given index in a game ************/
|
||||
/*****************************************************************************/
|
||||
// Input question index can be 0, 1, 2, 3... n-1
|
||||
// Return question index will be 1, 2, 3... n if next question exists, or big number if no next question
|
||||
|
||||
unsigned Gam_DB_GetNextQuestionIndexInGame (long GamCod,unsigned QstInd)
|
||||
{
|
||||
/***** Get next question index in a game from database *****/
|
||||
// Although indexes are always continuous...
|
||||
// ...this implementation works even with non continuous indexes
|
||||
return DB_QuerySELECTUnsigned ("can not get next question index",
|
||||
"SELECT COALESCE(MIN(QstInd),%u)"
|
||||
" FROM gam_questions"
|
||||
" WHERE GamCod=%ld"
|
||||
" AND QstInd>%u",
|
||||
Gam_AFTER_LAST_QUESTION, // End of questions has been reached
|
||||
GamCod,
|
||||
QstInd);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/************************ List the questions of a game ***********************/
|
||||
/*****************************************************************************/
|
||||
|
@ -2614,249 +2492,6 @@ void Gam_RequestNewMatch (void)
|
|||
true); // Put form to start new match
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/********************* Get number of courses with games **********************/
|
||||
/*****************************************************************************/
|
||||
// Returns the number of courses with games in this location
|
||||
|
||||
unsigned Gam_DB_GetNumCoursesWithGames (HieLvl_Level_t Scope)
|
||||
{
|
||||
/***** Get number of courses with games from database *****/
|
||||
switch (Scope)
|
||||
{
|
||||
case HieLvl_SYS:
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of courses with games",
|
||||
"SELECT COUNT(DISTINCT CrsCod)"
|
||||
" FROM gam_games");
|
||||
case HieLvl_CTY:
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of courses with games",
|
||||
"SELECT COUNT(DISTINCT gam_games.CrsCod)"
|
||||
" FROM ins_instits,"
|
||||
"ctr_centers,"
|
||||
"deg_degrees,"
|
||||
"crs_courses,"
|
||||
"gam_games"
|
||||
" WHERE ins_instits.CtyCod=%ld"
|
||||
" AND ins_instits.InsCod=ctr_centers.InsCod"
|
||||
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
|
||||
" AND deg_degrees.DegCod=crs_courses.DegCod"
|
||||
" AND crs_courses.CrsCod=gam_games.CrsCod",
|
||||
Gbl.Hierarchy.Ins.InsCod);
|
||||
case HieLvl_INS:
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of courses with games",
|
||||
"SELECT COUNT(DISTINCT gam_games.CrsCod)"
|
||||
" FROM ctr_centers,"
|
||||
"deg_degrees,"
|
||||
"crs_courses,"
|
||||
"gam_games"
|
||||
" WHERE ctr_centers.InsCod=%ld"
|
||||
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
|
||||
" AND deg_degrees.DegCod=crs_courses.DegCod"
|
||||
" AND crs_courses.CrsCod=gam_games.CrsCod",
|
||||
Gbl.Hierarchy.Ins.InsCod);
|
||||
case HieLvl_CTR:
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of courses with games",
|
||||
"SELECT COUNT(DISTINCT gam_games.CrsCod)"
|
||||
" FROM deg_degrees,"
|
||||
"crs_courses,"
|
||||
"gam_games"
|
||||
" WHERE deg_degrees.CtrCod=%ld"
|
||||
" AND deg_degrees.DegCod=crs_courses.DegCod"
|
||||
" AND crs_courses.CrsCod=gam_games.CrsCod",
|
||||
Gbl.Hierarchy.Ctr.CtrCod);
|
||||
case HieLvl_DEG:
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of courses with games",
|
||||
"SELECT COUNT(DISTINCT gam_games.CrsCod)"
|
||||
" FROM crs_courses,"
|
||||
"gam_games"
|
||||
" WHERE crs_courses.DegCod=%ld"
|
||||
" AND crs_courses.CrsCod=gam_games.CrsCod",
|
||||
Gbl.Hierarchy.Deg.DegCod);
|
||||
case HieLvl_CRS:
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of courses with games",
|
||||
"SELECT COUNT(DISTINCT CrsCod)"
|
||||
" FROM gam_games"
|
||||
" WHERE CrsCod=%ld",
|
||||
Gbl.Hierarchy.Crs.CrsCod);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**************************** Get number of games ****************************/
|
||||
/*****************************************************************************/
|
||||
// Returns the number of games in this location
|
||||
|
||||
unsigned Gam_DB_GetNumGames (HieLvl_Level_t Scope)
|
||||
{
|
||||
/***** Get number of games from database *****/
|
||||
switch (Scope)
|
||||
{
|
||||
case HieLvl_SYS:
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of games",
|
||||
"SELECT COUNT(*)"
|
||||
" FROM gam_games");
|
||||
case HieLvl_CTY:
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of games",
|
||||
"SELECT COUNT(*)"
|
||||
" FROM ins_instits,"
|
||||
"ctr_centers,"
|
||||
"deg_degrees,"
|
||||
"crs_courses,"
|
||||
"gam_games"
|
||||
" WHERE ins_instits.CtyCod=%ld"
|
||||
" AND ins_instits.InsCod=ctr_centers.InsCod"
|
||||
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
|
||||
" AND deg_degrees.DegCod=crs_courses.DegCod"
|
||||
" AND crs_courses.CrsCod=gam_games.CrsCod",
|
||||
Gbl.Hierarchy.Cty.CtyCod);
|
||||
case HieLvl_INS:
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of games",
|
||||
"SELECT COUNT(*)"
|
||||
" FROM ctr_centers,"
|
||||
"deg_degrees,"
|
||||
"crs_courses,"
|
||||
"gam_games"
|
||||
" WHERE ctr_centers.InsCod=%ld"
|
||||
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
|
||||
" AND deg_degrees.DegCod=crs_courses.DegCod"
|
||||
" AND crs_courses.CrsCod=gam_games.CrsCod",
|
||||
Gbl.Hierarchy.Ins.InsCod);
|
||||
case HieLvl_CTR:
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of games",
|
||||
"SELECT COUNT(*)"
|
||||
" FROM deg_degrees,"
|
||||
"crs_courses,"
|
||||
"gam_games"
|
||||
" WHERE deg_degrees.CtrCod=%ld"
|
||||
" AND deg_degrees.DegCod=crs_courses.DegCod"
|
||||
" AND crs_courses.CrsCod=gam_games.CrsCod",
|
||||
Gbl.Hierarchy.Ctr.CtrCod);
|
||||
case HieLvl_DEG:
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of games",
|
||||
"SELECT COUNT(*)"
|
||||
" FROM crs_courses,"
|
||||
"gam_games"
|
||||
" WHERE crs_courses.DegCod=%ld"
|
||||
" AND crs_courses.CrsCod=gam_games.CrsCod",
|
||||
Gbl.Hierarchy.Deg.DegCod);
|
||||
case HieLvl_CRS:
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of games",
|
||||
"SELECT COUNT(*)"
|
||||
" FROM gam_games"
|
||||
" WHERE CrsCod=%ld",
|
||||
Gbl.Hierarchy.Crs.CrsCod);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************** Get average number of questions per game ******************/
|
||||
/*****************************************************************************/
|
||||
|
||||
double Gam_DB_GetNumQstsPerGame (HieLvl_Level_t Scope)
|
||||
{
|
||||
/***** Get number of questions per game from database *****/
|
||||
switch (Scope)
|
||||
{
|
||||
case HieLvl_SYS:
|
||||
return DB_QuerySELECTDouble ("can not get number of questions per game",
|
||||
"SELECT AVG(NumQsts)"
|
||||
" FROM (SELECT COUNT(gam_questions.QstCod) AS NumQsts"
|
||||
" FROM gam_games,"
|
||||
"gam_questions"
|
||||
" WHERE gam_games.GamCod=gam_questions.GamCod"
|
||||
" GROUP BY gam_questions.GamCod) AS NumQstsTable");
|
||||
case HieLvl_CTY:
|
||||
return DB_QuerySELECTDouble ("can not get number of questions per game",
|
||||
"SELECT AVG(NumQsts)"
|
||||
" FROM (SELECT COUNT(gam_questions.QstCod) AS NumQsts"
|
||||
" FROM ins_instits,"
|
||||
"ctr_centers,"
|
||||
"deg_degrees,"
|
||||
"crs_courses,"
|
||||
"gam_games,"
|
||||
"gam_questions"
|
||||
" WHERE ins_instits.CtyCod=%ld"
|
||||
" AND ins_instits.InsCod=ctr_centers.InsCod"
|
||||
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
|
||||
" AND deg_degrees.DegCod=crs_courses.DegCod"
|
||||
" AND crs_courses.CrsCod=gam_games.CrsCod"
|
||||
" AND gam_games.GamCod=gam_questions.GamCod"
|
||||
" GROUP BY gam_questions.GamCod) AS NumQstsTable",
|
||||
Gbl.Hierarchy.Cty.CtyCod);
|
||||
case HieLvl_INS:
|
||||
return DB_QuerySELECTDouble ("can not get number of questions per game",
|
||||
"SELECT AVG(NumQsts)"
|
||||
" FROM (SELECT COUNT(gam_questions.QstCod) AS NumQsts"
|
||||
" FROM ctr_centers,"
|
||||
"deg_degrees,"
|
||||
"crs_courses,"
|
||||
"gam_games,"
|
||||
"gam_questions"
|
||||
" WHERE ctr_centers.InsCod=%ld"
|
||||
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
|
||||
" AND deg_degrees.DegCod=crs_courses.DegCod"
|
||||
" AND crs_courses.CrsCod=gam_games.CrsCod"
|
||||
" AND gam_games.GamCod=gam_questions.GamCod"
|
||||
" GROUP BY gam_questions.GamCod) AS NumQstsTable",
|
||||
Gbl.Hierarchy.Ins.InsCod);
|
||||
case HieLvl_CTR:
|
||||
return DB_QuerySELECTDouble ("can not get number of questions per game",
|
||||
"SELECT AVG(NumQsts)"
|
||||
" FROM (SELECT COUNT(gam_questions.QstCod) AS NumQsts"
|
||||
" FROM deg_degrees,"
|
||||
"crs_courses,"
|
||||
"gam_games,"
|
||||
"gam_questions"
|
||||
" WHERE deg_degrees.CtrCod=%ld"
|
||||
" AND deg_degrees.DegCod=crs_courses.DegCod"
|
||||
" AND crs_courses.CrsCod=gam_games.CrsCod"
|
||||
" AND gam_games.GamCod=gam_questions.GamCod"
|
||||
" GROUP BY gam_questions.GamCod) AS NumQstsTable",
|
||||
Gbl.Hierarchy.Ctr.CtrCod);
|
||||
case HieLvl_DEG:
|
||||
return DB_QuerySELECTDouble ("can not get number of questions per game",
|
||||
"SELECT AVG(NumQsts)"
|
||||
" FROM (SELECT COUNT(gam_questions.QstCod) AS NumQsts"
|
||||
" FROM crs_courses,"
|
||||
"gam_games,"
|
||||
"gam_questions"
|
||||
" WHERE crs_courses.DegCod=%ld"
|
||||
" AND crs_courses.CrsCod=gam_games.CrsCod"
|
||||
" AND gam_games.GamCod=gam_questions.GamCod"
|
||||
" GROUP BY gam_questions.GamCod) AS NumQstsTable",
|
||||
Gbl.Hierarchy.Deg.DegCod);
|
||||
case HieLvl_CRS:
|
||||
return DB_QuerySELECTDouble ("can not get number of questions per game",
|
||||
"SELECT AVG(NumQsts)"
|
||||
" FROM (SELECT COUNT(gam_questions.QstCod) AS NumQsts"
|
||||
" FROM gam_games,"
|
||||
"gam_questions"
|
||||
" WHERE gam_games.Cod=%ld"
|
||||
" AND gam_games.GamCod=gam_questions.GamCod"
|
||||
" GROUP BY gam_questions.GamCod) AS NumQstsTable",
|
||||
Gbl.Hierarchy.Crs.CrsCod);
|
||||
default:
|
||||
Err_WrongScopeExit ();
|
||||
return 0.0; // Not reached
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/************************* Show test tags in a game **************************/
|
||||
/*****************************************************************************/
|
||||
|
|
|
@ -143,16 +143,12 @@ void Gam_RequestCreatOrEditGame (void);
|
|||
|
||||
void Gam_ReceiveFormGame (void);
|
||||
|
||||
unsigned Gam_DB_GetNumQstsGame (long GamCod);
|
||||
|
||||
void Gam_ReqSelectQstsToAddToGame (void);
|
||||
void Gam_ListQstsToAddToGame (void);
|
||||
|
||||
void Gam_PutParamQstInd (unsigned QstInd);
|
||||
unsigned Gam_GetParamQstInd (void);
|
||||
long Gam_GetQstCodFromQstInd (long GamCod,unsigned QstInd);
|
||||
unsigned Gam_DB_GetPrevQuestionIndexInGame (long GamCod,unsigned QstInd);
|
||||
unsigned Gam_DB_GetNextQuestionIndexInGame (long GamCod,unsigned QstInd);
|
||||
|
||||
void Gam_AddQstsToGame (void);
|
||||
|
||||
|
@ -165,10 +161,6 @@ void Gam_MoveDownQst (void);
|
|||
void Gam_PutButtonNewMatch (struct Gam_Games *Games,long GamCod);
|
||||
void Gam_RequestNewMatch (void);
|
||||
|
||||
unsigned Gam_DB_GetNumCoursesWithGames (HieLvl_Level_t Scope);
|
||||
unsigned Gam_DB_GetNumGames (HieLvl_Level_t Scope);
|
||||
double Gam_DB_GetNumQstsPerGame (HieLvl_Level_t Scope);
|
||||
|
||||
void Gam_ShowTstTagsPresentInAGame (long GamCod);
|
||||
|
||||
void Gam_GetScoreRange (long GamCod,double *MinScore,double *MaxScore);
|
||||
|
|
465
swad_game_database.c
Normal file
465
swad_game_database.c
Normal file
|
@ -0,0 +1,465 @@
|
|||
// swad_game_database.c: games using remote control, operations with database
|
||||
|
||||
/*
|
||||
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-2021 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 <float.h> // For DBL_MAX
|
||||
// #include <linux/limits.h> // For PATH_MAX
|
||||
// #include <stddef.h> // For NULL
|
||||
#include <stdio.h> // For asprintf
|
||||
// #include <stdlib.h> // For free
|
||||
// #include <string.h> // For string functions
|
||||
|
||||
#include "swad_database.h"
|
||||
#include "swad_error.h"
|
||||
// #include "swad_figure.h"
|
||||
// #include "swad_form.h"
|
||||
#include "swad_game.h"
|
||||
#include "swad_game_database.h"
|
||||
#include "swad_global.h"
|
||||
// #include "swad_hierarchy_level.h"
|
||||
// #include "swad_HTML.h"
|
||||
// #include "swad_match.h"
|
||||
// #include "swad_match_result.h"
|
||||
// #include "swad_pagination.h"
|
||||
// #include "swad_role.h"
|
||||
// #include "swad_test.h"
|
||||
// #include "swad_test_visibility.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/************** External global variables from others modules ****************/
|
||||
/*****************************************************************************/
|
||||
|
||||
extern struct Globals Gbl;
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Private constants *****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************************* Private types *******************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Private variables *****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Private prototypes ****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/************* Get list of all the games in the current course ***************/
|
||||
/*****************************************************************************/
|
||||
|
||||
unsigned Gam_DB_GetListGames (MYSQL_RES **mysql_res,Gam_Order_t SelectedOrder)
|
||||
{
|
||||
static const char *OrderBySubQuery[Gam_NUM_ORDERS] =
|
||||
{
|
||||
[Gam_ORDER_BY_START_DATE] = "StartTime DESC,"
|
||||
"EndTime DESC,"
|
||||
"gam_games.Title DESC",
|
||||
[Gam_ORDER_BY_END_DATE ] = "EndTime DESC,"
|
||||
"StartTime DESC,"
|
||||
"gam_games.Title DESC",
|
||||
[Gam_ORDER_BY_TITLE ] = "gam_games.Title",
|
||||
};
|
||||
;
|
||||
char *HiddenSubQuery;
|
||||
unsigned NumGames;
|
||||
|
||||
/***** Subquery: get hidden games depending on user's role *****/
|
||||
switch (Gbl.Usrs.Me.Role.Logged)
|
||||
{
|
||||
case Rol_STD:
|
||||
if (asprintf (&HiddenSubQuery," AND gam_games.Hidden='N'") < 0)
|
||||
Err_NotEnoughMemoryExit ();
|
||||
break;
|
||||
case Rol_NET:
|
||||
case Rol_TCH:
|
||||
case Rol_DEG_ADM:
|
||||
case Rol_CTR_ADM:
|
||||
case Rol_INS_ADM:
|
||||
case Rol_SYS_ADM:
|
||||
if (asprintf (&HiddenSubQuery,"%s","") < 0)
|
||||
Err_NotEnoughMemoryExit ();
|
||||
break;
|
||||
default:
|
||||
Err_WrongRoleExit ();
|
||||
break;
|
||||
}
|
||||
|
||||
/***** Get list of games from database *****/
|
||||
NumGames = (unsigned)
|
||||
DB_QuerySELECT (mysql_res,"can not get games",
|
||||
"SELECT gam_games.GamCod," // row[0]
|
||||
"MIN(mch_matches.StartTime) AS StartTime," // row[1]
|
||||
"MAX(mch_matches.EndTime) AS EndTime" // row[2]
|
||||
" FROM gam_games"
|
||||
" LEFT JOIN mch_matches"
|
||||
" ON gam_games.GamCod=mch_matches.GamCod"
|
||||
" WHERE gam_games.CrsCod=%ld"
|
||||
"%s"
|
||||
" GROUP BY gam_games.GamCod"
|
||||
" ORDER BY %s",
|
||||
Gbl.Hierarchy.Crs.CrsCod,
|
||||
HiddenSubQuery,
|
||||
OrderBySubQuery[SelectedOrder]);
|
||||
|
||||
/***** Free allocated memory for subquery *****/
|
||||
free (HiddenSubQuery);
|
||||
|
||||
return NumGames;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/********************** Get game data using its code *************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
unsigned Gam_DB_GetDataOfGameByCod (MYSQL_RES **mysql_res,long GamCod)
|
||||
{
|
||||
return (unsigned)
|
||||
DB_QuerySELECT (mysql_res,"can not get game data",
|
||||
"SELECT gam_games.GamCod," // row[0]
|
||||
"gam_games.CrsCod," // row[1]
|
||||
"gam_games.Hidden," // row[2]
|
||||
"gam_games.UsrCod," // row[3]
|
||||
"gam_games.MaxGrade," // row[4]
|
||||
"gam_games.Visibility," // row[5]
|
||||
"gam_games.Title" // row[6]
|
||||
" FROM gam_games"
|
||||
" LEFT JOIN mch_matches"
|
||||
" ON gam_games.GamCod=mch_matches.GamCod"
|
||||
" WHERE gam_games.GamCod=%ld"
|
||||
" AND gam_games.CrsCod='%ld'", // Extra check
|
||||
GamCod,
|
||||
Gbl.Hierarchy.Crs.CrsCod);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************* Get number of questions of a game *********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
unsigned Gam_DB_GetNumQstsGame (long GamCod)
|
||||
{
|
||||
/***** Get nuumber of questions in a game from database *****/
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of questions of a game",
|
||||
"SELECT COUNT(*)"
|
||||
" FROM gam_questions"
|
||||
" WHERE GamCod=%ld",
|
||||
GamCod);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*********** Get previous question index to a given index in a game **********/
|
||||
/*****************************************************************************/
|
||||
// Input question index can be 1, 2, 3... n-1
|
||||
// Return question index will be 1, 2, 3... n if previous question exists, or 0 if no previous question
|
||||
|
||||
unsigned Gam_DB_GetPrevQuestionIndexInGame (long GamCod,unsigned QstInd)
|
||||
{
|
||||
/***** Get previous question index in a game from database *****/
|
||||
// Although indexes are always continuous...
|
||||
// ...this implementation works even with non continuous indexes
|
||||
return DB_QuerySELECTUnsigned ("can not get previous question index",
|
||||
"SELECT COALESCE(MAX(QstInd),0)"
|
||||
" FROM gam_questions"
|
||||
" WHERE GamCod=%ld"
|
||||
" AND QstInd<%u",
|
||||
GamCod,
|
||||
QstInd);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/************* Get next question index to a given index in a game ************/
|
||||
/*****************************************************************************/
|
||||
// Input question index can be 0, 1, 2, 3... n-1
|
||||
// Return question index will be 1, 2, 3... n if next question exists, or big number if no next question
|
||||
|
||||
unsigned Gam_DB_GetNextQuestionIndexInGame (long GamCod,unsigned QstInd)
|
||||
{
|
||||
/***** Get next question index in a game from database *****/
|
||||
// Although indexes are always continuous...
|
||||
// ...this implementation works even with non continuous indexes
|
||||
return DB_QuerySELECTUnsigned ("can not get next question index",
|
||||
"SELECT COALESCE(MIN(QstInd),%u)"
|
||||
" FROM gam_questions"
|
||||
" WHERE GamCod=%ld"
|
||||
" AND QstInd>%u",
|
||||
Gam_AFTER_LAST_QUESTION, // End of questions has been reached
|
||||
GamCod,
|
||||
QstInd);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/********************* Get number of courses with games **********************/
|
||||
/*****************************************************************************/
|
||||
// Returns the number of courses with games in this location
|
||||
|
||||
unsigned Gam_DB_GetNumCoursesWithGames (HieLvl_Level_t Scope)
|
||||
{
|
||||
/***** Get number of courses with games from database *****/
|
||||
switch (Scope)
|
||||
{
|
||||
case HieLvl_SYS:
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of courses with games",
|
||||
"SELECT COUNT(DISTINCT CrsCod)"
|
||||
" FROM gam_games");
|
||||
case HieLvl_CTY:
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of courses with games",
|
||||
"SELECT COUNT(DISTINCT gam_games.CrsCod)"
|
||||
" FROM ins_instits,"
|
||||
"ctr_centers,"
|
||||
"deg_degrees,"
|
||||
"crs_courses,"
|
||||
"gam_games"
|
||||
" WHERE ins_instits.CtyCod=%ld"
|
||||
" AND ins_instits.InsCod=ctr_centers.InsCod"
|
||||
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
|
||||
" AND deg_degrees.DegCod=crs_courses.DegCod"
|
||||
" AND crs_courses.CrsCod=gam_games.CrsCod",
|
||||
Gbl.Hierarchy.Ins.InsCod);
|
||||
case HieLvl_INS:
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of courses with games",
|
||||
"SELECT COUNT(DISTINCT gam_games.CrsCod)"
|
||||
" FROM ctr_centers,"
|
||||
"deg_degrees,"
|
||||
"crs_courses,"
|
||||
"gam_games"
|
||||
" WHERE ctr_centers.InsCod=%ld"
|
||||
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
|
||||
" AND deg_degrees.DegCod=crs_courses.DegCod"
|
||||
" AND crs_courses.CrsCod=gam_games.CrsCod",
|
||||
Gbl.Hierarchy.Ins.InsCod);
|
||||
case HieLvl_CTR:
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of courses with games",
|
||||
"SELECT COUNT(DISTINCT gam_games.CrsCod)"
|
||||
" FROM deg_degrees,"
|
||||
"crs_courses,"
|
||||
"gam_games"
|
||||
" WHERE deg_degrees.CtrCod=%ld"
|
||||
" AND deg_degrees.DegCod=crs_courses.DegCod"
|
||||
" AND crs_courses.CrsCod=gam_games.CrsCod",
|
||||
Gbl.Hierarchy.Ctr.CtrCod);
|
||||
case HieLvl_DEG:
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of courses with games",
|
||||
"SELECT COUNT(DISTINCT gam_games.CrsCod)"
|
||||
" FROM crs_courses,"
|
||||
"gam_games"
|
||||
" WHERE crs_courses.DegCod=%ld"
|
||||
" AND crs_courses.CrsCod=gam_games.CrsCod",
|
||||
Gbl.Hierarchy.Deg.DegCod);
|
||||
case HieLvl_CRS:
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of courses with games",
|
||||
"SELECT COUNT(DISTINCT CrsCod)"
|
||||
" FROM gam_games"
|
||||
" WHERE CrsCod=%ld",
|
||||
Gbl.Hierarchy.Crs.CrsCod);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**************************** Get number of games ****************************/
|
||||
/*****************************************************************************/
|
||||
// Returns the number of games in this location
|
||||
|
||||
unsigned Gam_DB_GetNumGames (HieLvl_Level_t Scope)
|
||||
{
|
||||
/***** Get number of games from database *****/
|
||||
switch (Scope)
|
||||
{
|
||||
case HieLvl_SYS:
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of games",
|
||||
"SELECT COUNT(*)"
|
||||
" FROM gam_games");
|
||||
case HieLvl_CTY:
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of games",
|
||||
"SELECT COUNT(*)"
|
||||
" FROM ins_instits,"
|
||||
"ctr_centers,"
|
||||
"deg_degrees,"
|
||||
"crs_courses,"
|
||||
"gam_games"
|
||||
" WHERE ins_instits.CtyCod=%ld"
|
||||
" AND ins_instits.InsCod=ctr_centers.InsCod"
|
||||
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
|
||||
" AND deg_degrees.DegCod=crs_courses.DegCod"
|
||||
" AND crs_courses.CrsCod=gam_games.CrsCod",
|
||||
Gbl.Hierarchy.Cty.CtyCod);
|
||||
case HieLvl_INS:
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of games",
|
||||
"SELECT COUNT(*)"
|
||||
" FROM ctr_centers,"
|
||||
"deg_degrees,"
|
||||
"crs_courses,"
|
||||
"gam_games"
|
||||
" WHERE ctr_centers.InsCod=%ld"
|
||||
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
|
||||
" AND deg_degrees.DegCod=crs_courses.DegCod"
|
||||
" AND crs_courses.CrsCod=gam_games.CrsCod",
|
||||
Gbl.Hierarchy.Ins.InsCod);
|
||||
case HieLvl_CTR:
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of games",
|
||||
"SELECT COUNT(*)"
|
||||
" FROM deg_degrees,"
|
||||
"crs_courses,"
|
||||
"gam_games"
|
||||
" WHERE deg_degrees.CtrCod=%ld"
|
||||
" AND deg_degrees.DegCod=crs_courses.DegCod"
|
||||
" AND crs_courses.CrsCod=gam_games.CrsCod",
|
||||
Gbl.Hierarchy.Ctr.CtrCod);
|
||||
case HieLvl_DEG:
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of games",
|
||||
"SELECT COUNT(*)"
|
||||
" FROM crs_courses,"
|
||||
"gam_games"
|
||||
" WHERE crs_courses.DegCod=%ld"
|
||||
" AND crs_courses.CrsCod=gam_games.CrsCod",
|
||||
Gbl.Hierarchy.Deg.DegCod);
|
||||
case HieLvl_CRS:
|
||||
return (unsigned)
|
||||
DB_QueryCOUNT ("can not get number of games",
|
||||
"SELECT COUNT(*)"
|
||||
" FROM gam_games"
|
||||
" WHERE CrsCod=%ld",
|
||||
Gbl.Hierarchy.Crs.CrsCod);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************** Get average number of questions per game ******************/
|
||||
/*****************************************************************************/
|
||||
|
||||
double Gam_DB_GetNumQstsPerGame (HieLvl_Level_t Scope)
|
||||
{
|
||||
/***** Get number of questions per game from database *****/
|
||||
switch (Scope)
|
||||
{
|
||||
case HieLvl_SYS:
|
||||
return
|
||||
DB_QuerySELECTDouble ("can not get number of questions per game",
|
||||
"SELECT AVG(NumQsts)"
|
||||
" FROM (SELECT COUNT(gam_questions.QstCod) AS NumQsts"
|
||||
" FROM gam_games,"
|
||||
"gam_questions"
|
||||
" WHERE gam_games.GamCod=gam_questions.GamCod"
|
||||
" GROUP BY gam_questions.GamCod) AS NumQstsTable");
|
||||
case HieLvl_CTY:
|
||||
return
|
||||
DB_QuerySELECTDouble ("can not get number of questions per game",
|
||||
"SELECT AVG(NumQsts)"
|
||||
" FROM (SELECT COUNT(gam_questions.QstCod) AS NumQsts"
|
||||
" FROM ins_instits,"
|
||||
"ctr_centers,"
|
||||
"deg_degrees,"
|
||||
"crs_courses,"
|
||||
"gam_games,"
|
||||
"gam_questions"
|
||||
" WHERE ins_instits.CtyCod=%ld"
|
||||
" AND ins_instits.InsCod=ctr_centers.InsCod"
|
||||
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
|
||||
" AND deg_degrees.DegCod=crs_courses.DegCod"
|
||||
" AND crs_courses.CrsCod=gam_games.CrsCod"
|
||||
" AND gam_games.GamCod=gam_questions.GamCod"
|
||||
" GROUP BY gam_questions.GamCod) AS NumQstsTable",
|
||||
Gbl.Hierarchy.Cty.CtyCod);
|
||||
case HieLvl_INS:
|
||||
return
|
||||
DB_QuerySELECTDouble ("can not get number of questions per game",
|
||||
"SELECT AVG(NumQsts)"
|
||||
" FROM (SELECT COUNT(gam_questions.QstCod) AS NumQsts"
|
||||
" FROM ctr_centers,"
|
||||
"deg_degrees,"
|
||||
"crs_courses,"
|
||||
"gam_games,"
|
||||
"gam_questions"
|
||||
" WHERE ctr_centers.InsCod=%ld"
|
||||
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
|
||||
" AND deg_degrees.DegCod=crs_courses.DegCod"
|
||||
" AND crs_courses.CrsCod=gam_games.CrsCod"
|
||||
" AND gam_games.GamCod=gam_questions.GamCod"
|
||||
" GROUP BY gam_questions.GamCod) AS NumQstsTable",
|
||||
Gbl.Hierarchy.Ins.InsCod);
|
||||
case HieLvl_CTR:
|
||||
return
|
||||
DB_QuerySELECTDouble ("can not get number of questions per game",
|
||||
"SELECT AVG(NumQsts)"
|
||||
" FROM (SELECT COUNT(gam_questions.QstCod) AS NumQsts"
|
||||
" FROM deg_degrees,"
|
||||
"crs_courses,"
|
||||
"gam_games,"
|
||||
"gam_questions"
|
||||
" WHERE deg_degrees.CtrCod=%ld"
|
||||
" AND deg_degrees.DegCod=crs_courses.DegCod"
|
||||
" AND crs_courses.CrsCod=gam_games.CrsCod"
|
||||
" AND gam_games.GamCod=gam_questions.GamCod"
|
||||
" GROUP BY gam_questions.GamCod) AS NumQstsTable",
|
||||
Gbl.Hierarchy.Ctr.CtrCod);
|
||||
case HieLvl_DEG:
|
||||
return
|
||||
DB_QuerySELECTDouble ("can not get number of questions per game",
|
||||
"SELECT AVG(NumQsts)"
|
||||
" FROM (SELECT COUNT(gam_questions.QstCod) AS NumQsts"
|
||||
" FROM crs_courses,"
|
||||
"gam_games,"
|
||||
"gam_questions"
|
||||
" WHERE crs_courses.DegCod=%ld"
|
||||
" AND crs_courses.CrsCod=gam_games.CrsCod"
|
||||
" AND gam_games.GamCod=gam_questions.GamCod"
|
||||
" GROUP BY gam_questions.GamCod) AS NumQstsTable",
|
||||
Gbl.Hierarchy.Deg.DegCod);
|
||||
case HieLvl_CRS:
|
||||
return
|
||||
DB_QuerySELECTDouble ("can not get number of questions per game",
|
||||
"SELECT AVG(NumQsts)"
|
||||
" FROM (SELECT COUNT(gam_questions.QstCod) AS NumQsts"
|
||||
" FROM gam_games,"
|
||||
"gam_questions"
|
||||
" WHERE gam_games.Cod=%ld"
|
||||
" AND gam_games.GamCod=gam_questions.GamCod"
|
||||
" GROUP BY gam_questions.GamCod) AS NumQstsTable",
|
||||
Gbl.Hierarchy.Crs.CrsCod);
|
||||
default:
|
||||
Err_WrongScopeExit ();
|
||||
return 0.0; // Not reached
|
||||
}
|
||||
}
|
53
swad_game_database.h
Normal file
53
swad_game_database.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
// swad_game_database.h: games using remote control, operations with database
|
||||
|
||||
#ifndef _SWAD_GAM_DB
|
||||
#define _SWAD_GAM_DB
|
||||
/*
|
||||
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-2021 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 "swad_date.h"
|
||||
#include "swad_hierarchy_level.h"
|
||||
// #include "swad_scope.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/************************** Public types and constants ***********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Public prototypes *****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
unsigned Gam_DB_GetListGames (MYSQL_RES **mysql_res,Gam_Order_t SelectedOrder);
|
||||
unsigned Gam_DB_GetDataOfGameByCod (MYSQL_RES **mysql_res,long GamCod);
|
||||
unsigned Gam_DB_GetNumQstsGame (long GamCod);
|
||||
|
||||
unsigned Gam_DB_GetPrevQuestionIndexInGame (long GamCod,unsigned QstInd);
|
||||
unsigned Gam_DB_GetNextQuestionIndexInGame (long GamCod,unsigned QstInd);
|
||||
|
||||
unsigned Gam_DB_GetNumCoursesWithGames (HieLvl_Level_t Scope);
|
||||
unsigned Gam_DB_GetNumGames (HieLvl_Level_t Scope);
|
||||
double Gam_DB_GetNumQstsPerGame (HieLvl_Level_t Scope);
|
||||
|
||||
#endif
|
102
swad_match.c
102
swad_match.c
|
@ -37,6 +37,7 @@
|
|||
#include "swad_error.h"
|
||||
#include "swad_form.h"
|
||||
#include "swad_game.h"
|
||||
#include "swad_game_database.h"
|
||||
#include "swad_global.h"
|
||||
#include "swad_group_database.h"
|
||||
#include "swad_HTML.h"
|
||||
|
@ -142,7 +143,7 @@ static void Mch_DB_RemoveMatchFromTable (long MchCod,const char *TableName);
|
|||
static void Mch_DB_RemoveMatchesInGameFromTable (long GamCod,const char *TableName);
|
||||
static void Mch_DB_RemoveMatchesInCourseFromTable (long CrsCod,const char *TableName);
|
||||
static void Mch_DB_RemoveMatchesMadeByUsrFromTable (long UsrCod,const char *TableName);
|
||||
static void Mch_RemoveMatchesMadeByUsrInCrsFromTable (long UsrCod,long CrsCod,const char *TableName);
|
||||
static void Mch_DB_RemoveMatchesMadeByUsrInCrsFromTable (long UsrCod,long CrsCod,const char *TableName);
|
||||
|
||||
static void Mch_PutParamsPlay (void *MchCod);
|
||||
static void Mch_PutParamMchCod (long MchCod);
|
||||
|
@ -234,17 +235,17 @@ static void Mch_PutBigButtonClose (void);
|
|||
|
||||
static void Mch_ShowWaitImage (const char *Txt);
|
||||
|
||||
static void Mch_RemoveOldPlayers (void);
|
||||
static void Mch_UpdateMatchAsBeingPlayed (long MchCod);
|
||||
static void Mch_SetMatchAsNotBeingPlayed (long MchCod);
|
||||
static bool Mch_GetIfMatchIsBeingPlayed (long MchCod);
|
||||
static void Mch_GetNumPlayers (struct Mch_Match *Match);
|
||||
static void Mch_DB_RemoveOldPlayers (void);
|
||||
static void Mch_DB_UpdateMatchAsBeingPlayed (long MchCod);
|
||||
static void Mch_DB_SetMatchAsNotBeingPlayed (long MchCod);
|
||||
static bool Mch_DB_GetIfMatchIsBeingPlayed (long MchCod);
|
||||
static void Mch_DB_GetNumPlayers (struct Mch_Match *Match);
|
||||
|
||||
static void Mch_UpdateMyAnswerToMatchQuestion (const struct Mch_Match *Match,
|
||||
static void Mch_DB_UpdateMyAnswerToMatchQuestion (const struct Mch_Match *Match,
|
||||
const struct Mch_UsrAnswer *UsrAnswer);
|
||||
static void Mch_RemoveMyAnswerToMatchQuestion (const struct Mch_Match *Match);
|
||||
static void Mch_DB_RemoveMyAnswerToMatchQuestion (const struct Mch_Match *Match);
|
||||
|
||||
static unsigned Mch_GetNumUsrsWhoHavePlayedMch (long MchCod);
|
||||
static unsigned Mch_DB_GetNumUsrsWhoHavePlayedMch (long MchCod);
|
||||
|
||||
/*****************************************************************************/
|
||||
/*************** Set/Get match code of the match being played ****************/
|
||||
|
@ -837,7 +838,7 @@ static void Mch_ListOneOrMoreMatchesNumPlayers (const struct Mch_Match *Match)
|
|||
{
|
||||
/***** Number of players who have answered any question in the match ******/
|
||||
HTM_TD_Begin ("class=\"DAT RT COLOR%u\"",Gbl.RowEvenOdd);
|
||||
HTM_Unsigned (Mch_GetNumUsrsWhoHavePlayedMch (Match->MchCod));
|
||||
HTM_Unsigned (Mch_DB_GetNumUsrsWhoHavePlayedMch (Match->MchCod));
|
||||
HTM_TD_End ();
|
||||
}
|
||||
|
||||
|
@ -1080,7 +1081,7 @@ static void Mch_GetMatchDataFromRow (MYSQL_RES *mysql_res,
|
|||
if (Match->Status.Showing == Mch_END) // Match over
|
||||
Match->Status.Playing = false;
|
||||
else // Match not over
|
||||
Match->Status.Playing = Mch_GetIfMatchIsBeingPlayed (Match->MchCod);
|
||||
Match->Status.Playing = Mch_DB_GetIfMatchIsBeingPlayed (Match->MchCod);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -1315,12 +1316,12 @@ static void Mch_DB_RemoveMatchesMadeByUsrFromTable (long UsrCod,const char *Tabl
|
|||
void Mch_RemoveMatchesMadeByUsrInCrs (long UsrCod,long CrsCod)
|
||||
{
|
||||
/***** Remove student from secondary tables *****/
|
||||
Mch_RemoveMatchesMadeByUsrInCrsFromTable (UsrCod,CrsCod,"mch_players");
|
||||
Mch_RemoveMatchesMadeByUsrInCrsFromTable (UsrCod,CrsCod,"mch_results");
|
||||
Mch_RemoveMatchesMadeByUsrInCrsFromTable (UsrCod,CrsCod,"mch_answers");
|
||||
Mch_DB_RemoveMatchesMadeByUsrInCrsFromTable (UsrCod,CrsCod,"mch_players");
|
||||
Mch_DB_RemoveMatchesMadeByUsrInCrsFromTable (UsrCod,CrsCod,"mch_results");
|
||||
Mch_DB_RemoveMatchesMadeByUsrInCrsFromTable (UsrCod,CrsCod,"mch_answers");
|
||||
}
|
||||
|
||||
static void Mch_RemoveMatchesMadeByUsrInCrsFromTable (long UsrCod,long CrsCod,const char *TableName)
|
||||
static void Mch_DB_RemoveMatchesMadeByUsrInCrsFromTable (long UsrCod,long CrsCod,const char *TableName)
|
||||
{
|
||||
/***** Remove matches in course from secondary table *****/
|
||||
DB_QueryDELETE ("can not remove matches of a user from table",
|
||||
|
@ -1727,7 +1728,7 @@ void Mch_ResumeMatch (void)
|
|||
/***** Remove old players.
|
||||
This function must be called by a teacher
|
||||
before getting match status. *****/
|
||||
Mch_RemoveOldPlayers ();
|
||||
Mch_DB_RemoveOldPlayers ();
|
||||
|
||||
/***** Get data of the match from database *****/
|
||||
Match.MchCod = Mch_GetMchCodBeingPlayed ();
|
||||
|
@ -2053,10 +2054,10 @@ static void Mch_UpdateMatchStatusInDB (const struct Mch_Match *Match)
|
|||
|
||||
if (Match->Status.Playing) // Match is being played
|
||||
/* Update match as being played */
|
||||
Mch_UpdateMatchAsBeingPlayed (Match->MchCod);
|
||||
Mch_DB_UpdateMatchAsBeingPlayed (Match->MchCod);
|
||||
else // Match is paused, not being played
|
||||
/* Update match as not being played */
|
||||
Mch_SetMatchAsNotBeingPlayed (Match->MchCod);
|
||||
Mch_DB_SetMatchAsNotBeingPlayed (Match->MchCod);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -2179,7 +2180,7 @@ void Mch_PlayPauseMatch (void)
|
|||
/***** Remove old players.
|
||||
This function must be called by a teacher
|
||||
before getting match status. *****/
|
||||
Mch_RemoveOldPlayers ();
|
||||
Mch_DB_RemoveOldPlayers ();
|
||||
|
||||
/***** Get data of the match from database *****/
|
||||
Match.MchCod = Mch_GetMchCodBeingPlayed ();
|
||||
|
@ -2216,7 +2217,7 @@ void Mch_ChangeNumColsMch (void)
|
|||
/***** Remove old players.
|
||||
This function must be called by a teacher
|
||||
before getting match status. *****/
|
||||
Mch_RemoveOldPlayers ();
|
||||
Mch_DB_RemoveOldPlayers ();
|
||||
|
||||
/***** Get data of the match from database *****/
|
||||
Match.MchCod = Mch_GetMchCodBeingPlayed ();
|
||||
|
@ -2252,7 +2253,7 @@ void Mch_ToggleVisResultsMchQst (void)
|
|||
/***** Remove old players.
|
||||
This function must be called by a teacher
|
||||
before getting match status. *****/
|
||||
Mch_RemoveOldPlayers ();
|
||||
Mch_DB_RemoveOldPlayers ();
|
||||
|
||||
/***** Get data of the match from database *****/
|
||||
Match.MchCod = Mch_GetMchCodBeingPlayed ();
|
||||
|
@ -2287,7 +2288,7 @@ void Mch_BackMatch (void)
|
|||
/***** Remove old players.
|
||||
This function must be called by a teacher
|
||||
before getting match status. *****/
|
||||
Mch_RemoveOldPlayers ();
|
||||
Mch_DB_RemoveOldPlayers ();
|
||||
|
||||
/***** Get data of the match from database *****/
|
||||
Match.MchCod = Mch_GetMchCodBeingPlayed ();
|
||||
|
@ -2319,7 +2320,7 @@ void Mch_ForwardMatch (void)
|
|||
/***** Remove old players.
|
||||
This function must be called by a teacher
|
||||
before getting match status. *****/
|
||||
Mch_RemoveOldPlayers ();
|
||||
Mch_DB_RemoveOldPlayers ();
|
||||
|
||||
/***** Get data of the match from database *****/
|
||||
Match.MchCod = Mch_GetMchCodBeingPlayed ();
|
||||
|
@ -2507,7 +2508,7 @@ static void Mch_ShowMatchStatusForStd (struct Mch_Match *Match,Mch_Update_t Upda
|
|||
/********************** Get number of matches in a game **********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
unsigned Mch_GetNumMchsInGame (long GamCod)
|
||||
unsigned Mch_DB_GetNumMchsInGame (long GamCod)
|
||||
{
|
||||
/***** Trivial check *****/
|
||||
if (GamCod < 0) // A non-existing game...
|
||||
|
@ -2526,7 +2527,7 @@ unsigned Mch_GetNumMchsInGame (long GamCod)
|
|||
/*************** Get number of unfinished matches in a game ******************/
|
||||
/*****************************************************************************/
|
||||
|
||||
unsigned Mch_GetNumUnfinishedMchsInGame (long GamCod)
|
||||
unsigned Mch_DB_GetNumUnfinishedMchsInGame (long GamCod)
|
||||
{
|
||||
/***** Trivial check *****/
|
||||
if (GamCod < 0) // A non-existing game...
|
||||
|
@ -2703,7 +2704,7 @@ static void Mch_WriteNumRespondersQst (struct Mch_Match *Match)
|
|||
HTM_Hyphen (); // Do not write number of responders
|
||||
break;
|
||||
default:
|
||||
HTM_Unsigned (Mch_GetNumUsrsWhoAnsweredQst (Match->MchCod,
|
||||
HTM_Unsigned (Mch_DB_GetNumUsrsWhoAnsweredQst (Match->MchCod,
|
||||
Match->Status.QstInd));
|
||||
break;
|
||||
}
|
||||
|
@ -2712,7 +2713,7 @@ static void Mch_WriteNumRespondersQst (struct Mch_Match *Match)
|
|||
if (Match->Status.Playing) // Match is being played
|
||||
{
|
||||
/* Get current number of players */
|
||||
Mch_GetNumPlayers (Match);
|
||||
Mch_DB_GetNumPlayers (Match);
|
||||
|
||||
/* Show current number of players */
|
||||
HTM_TxtF ("/%u",Match->Status.NumPlayers);
|
||||
|
@ -3363,7 +3364,7 @@ static void Mch_WriteChoiceAnsViewMatch (const struct Mch_Match *Match,
|
|||
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION]; // Indexes of all answers of this question
|
||||
|
||||
/***** Get number of users who have answered this question from database *****/
|
||||
NumRespondersQst = Mch_GetNumUsrsWhoAnsweredQst (Match->MchCod,Match->Status.QstInd);
|
||||
NumRespondersQst = Mch_DB_GetNumUsrsWhoAnsweredQst (Match->MchCod,Match->Status.QstInd);
|
||||
|
||||
/***** Change format of answers text *****/
|
||||
Tst_ChangeFormatAnswersText (Question);
|
||||
|
@ -3406,7 +3407,7 @@ static void Mch_WriteChoiceAnsViewMatch (const struct Mch_Match *Match,
|
|||
if (ShowResult)
|
||||
{
|
||||
/* Get number of users who selected this answer */
|
||||
NumRespondersAns = Mch_GetNumUsrsWhoHaveChosenAns (Match->MchCod,Match->Status.QstInd,Indexes[NumOpt]);
|
||||
NumRespondersAns = Mch_DB_GetNumUsrsWhoHaveChosenAns (Match->MchCod,Match->Status.QstInd,Indexes[NumOpt]);
|
||||
|
||||
/* Draw proportional bar for this answer */
|
||||
Mch_DrawBarNumUsrs (NumRespondersAns,NumRespondersQst,
|
||||
|
@ -3811,7 +3812,7 @@ static void Mch_ShowWaitImage (const char *Txt)
|
|||
/**************************** Remove old players *****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Mch_RemoveOldPlayers (void)
|
||||
static void Mch_DB_RemoveOldPlayers (void)
|
||||
{
|
||||
/***** Delete matches not being played by teacher *****/
|
||||
DB_QueryDELETE ("can not update matches as not being played",
|
||||
|
@ -3830,7 +3831,7 @@ static void Mch_RemoveOldPlayers (void)
|
|||
/********************** Update match as being played *************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Mch_UpdateMatchAsBeingPlayed (long MchCod)
|
||||
static void Mch_DB_UpdateMatchAsBeingPlayed (long MchCod)
|
||||
{
|
||||
/***** Insert match as being played *****/
|
||||
DB_QueryREPLACE ("can not set match as being played",
|
||||
|
@ -3845,7 +3846,7 @@ static void Mch_UpdateMatchAsBeingPlayed (long MchCod)
|
|||
/**************** Update match as paused, not being played *******************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Mch_SetMatchAsNotBeingPlayed (long MchCod)
|
||||
static void Mch_DB_SetMatchAsNotBeingPlayed (long MchCod)
|
||||
{
|
||||
/***** Delete all match players ******/
|
||||
DB_QueryDELETE ("can not update match players",
|
||||
|
@ -3864,7 +3865,7 @@ static void Mch_SetMatchAsNotBeingPlayed (long MchCod)
|
|||
/*********************** Get if match is being played ************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static bool Mch_GetIfMatchIsBeingPlayed (long MchCod)
|
||||
static bool Mch_DB_GetIfMatchIsBeingPlayed (long MchCod)
|
||||
{
|
||||
/***** Get if a match is being played or not *****/
|
||||
return (DB_QueryCOUNT ("can not get if match is being played",
|
||||
|
@ -3878,7 +3879,7 @@ static bool Mch_GetIfMatchIsBeingPlayed (long MchCod)
|
|||
/*************************** Get number of players ***************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Mch_GetNumPlayers (struct Mch_Match *Match)
|
||||
static void Mch_DB_GetNumPlayers (struct Mch_Match *Match)
|
||||
{
|
||||
/***** Get number of players who are playing a match *****/
|
||||
Match->Status.NumPlayers = (unsigned)
|
||||
|
@ -4000,7 +4001,7 @@ void Mch_RemoveMyQuestionAnswer (const struct Mch_Match *Match,unsigned QstInd)
|
|||
QstInd == Match->Status.QstInd) // Removing answer to the current question being played
|
||||
{
|
||||
/***** Remove my answer to this question *****/
|
||||
Mch_RemoveMyAnswerToMatchQuestion (Match);
|
||||
Mch_DB_RemoveMyAnswerToMatchQuestion (Match);
|
||||
|
||||
/***** Compute score and update my match result *****/
|
||||
MchPrn_ComputeScoreAndUpdateMyMatchPrintInDB (Match->MchCod);
|
||||
|
@ -4025,7 +4026,7 @@ void Mch_StartCountdown (void)
|
|||
/***** Remove old players.
|
||||
This function must be called by a teacher
|
||||
before getting match status. *****/
|
||||
Mch_RemoveOldPlayers ();
|
||||
Mch_DB_RemoveOldPlayers ();
|
||||
|
||||
/***** Get data of the match from database *****/
|
||||
Match.MchCod = Mch_GetMchCodBeingPlayed ();
|
||||
|
@ -4059,7 +4060,7 @@ void Mch_RefreshMatchTch (void)
|
|||
/***** Remove old players.
|
||||
This function must be called by a teacher
|
||||
before getting match status. *****/
|
||||
Mch_RemoveOldPlayers ();
|
||||
Mch_DB_RemoveOldPlayers ();
|
||||
|
||||
/***** Get data of the match from database *****/
|
||||
Match.MchCod = Mch_GetMchCodBeingPlayed ();
|
||||
|
@ -4248,7 +4249,7 @@ void Mch_StoreQuestionAnswer (const struct Mch_Match *Match,unsigned QstInd,
|
|||
UsrAnswer->AnsInd != PreviousUsrAnswer.AnsInd)
|
||||
{
|
||||
/***** Update my answer to this question *****/
|
||||
Mch_UpdateMyAnswerToMatchQuestion (Match,UsrAnswer);
|
||||
Mch_DB_UpdateMyAnswerToMatchQuestion (Match,UsrAnswer);
|
||||
|
||||
/***** Compute score and update my match result *****/
|
||||
MchPrn_ComputeScoreAndUpdateMyMatchPrintInDB (Match->MchCod);
|
||||
|
@ -4260,7 +4261,7 @@ void Mch_StoreQuestionAnswer (const struct Mch_Match *Match,unsigned QstInd,
|
|||
/******************** Update my answer to match question *********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Mch_UpdateMyAnswerToMatchQuestion (const struct Mch_Match *Match,
|
||||
static void Mch_DB_UpdateMyAnswerToMatchQuestion (const struct Mch_Match *Match,
|
||||
const struct Mch_UsrAnswer *UsrAnswer)
|
||||
{
|
||||
DB_QueryREPLACE ("can not register your answer to the match question",
|
||||
|
@ -4279,7 +4280,7 @@ static void Mch_UpdateMyAnswerToMatchQuestion (const struct Mch_Match *Match,
|
|||
/******************* Remove my answer to match question **********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Mch_RemoveMyAnswerToMatchQuestion (const struct Mch_Match *Match)
|
||||
static void Mch_DB_RemoveMyAnswerToMatchQuestion (const struct Mch_Match *Match)
|
||||
{
|
||||
DB_QueryDELETE ("can not remove your answer to the match question",
|
||||
"DELETE FROM mch_answers"
|
||||
|
@ -4384,7 +4385,7 @@ void Mch_ComputeScore (struct MchPrn_Print *Print)
|
|||
/********** Get number of users who answered a question in a match ***********/
|
||||
/*****************************************************************************/
|
||||
|
||||
unsigned Mch_GetNumUsrsWhoAnsweredQst (long MchCod,unsigned QstInd)
|
||||
unsigned Mch_DB_GetNumUsrsWhoAnsweredQst (long MchCod,unsigned QstInd)
|
||||
{
|
||||
/***** Get number of users who answered
|
||||
a question in a match from database *****/
|
||||
|
@ -4402,7 +4403,7 @@ unsigned Mch_GetNumUsrsWhoAnsweredQst (long MchCod,unsigned QstInd)
|
|||
/*** Get number of users who have chosen a given answer of a game question ***/
|
||||
/*****************************************************************************/
|
||||
|
||||
unsigned Mch_GetNumUsrsWhoHaveChosenAns (long MchCod,unsigned QstInd,unsigned AnsInd)
|
||||
unsigned Mch_DB_GetNumUsrsWhoHaveChosenAns (long MchCod,unsigned QstInd,unsigned AnsInd)
|
||||
{
|
||||
/***** Get number of users who have chosen
|
||||
an answer of a question from database *****/
|
||||
|
@ -4422,7 +4423,7 @@ unsigned Mch_GetNumUsrsWhoHaveChosenAns (long MchCod,unsigned QstInd,unsigned An
|
|||
/************ Get number of users who have played a given match **************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static unsigned Mch_GetNumUsrsWhoHavePlayedMch (long MchCod)
|
||||
static unsigned Mch_DB_GetNumUsrsWhoHavePlayedMch (long MchCod)
|
||||
{
|
||||
/***** Get number of users who have played the match
|
||||
(users who have a result for this match, even blank result)
|
||||
|
@ -4483,3 +4484,18 @@ void Mch_DrawBarNumUsrs (unsigned NumRespondersAns,unsigned NumRespondersQst,boo
|
|||
/***** End container *****/
|
||||
HTM_DIV_End ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/********* Get start of first match and end of last match in a game **********/
|
||||
/*****************************************************************************/
|
||||
|
||||
unsigned Mch_DB_GetStartEndMatchesInGame (MYSQL_RES **mysql_res,long GamCod)
|
||||
{
|
||||
return (unsigned)
|
||||
DB_QuerySELECT (mysql_res,"can not get game data",
|
||||
"SELECT UNIX_TIMESTAMP(MIN(StartTime))," // row[0]
|
||||
"UNIX_TIMESTAMP(MAX(EndTime))" // row[1]
|
||||
" FROM mch_matches"
|
||||
" WHERE GamCod=%ld",
|
||||
GamCod);
|
||||
}
|
||||
|
|
10
swad_match.h
10
swad_match.h
|
@ -128,8 +128,8 @@ void Mch_ToggleVisResultsMchQst (void);
|
|||
void Mch_BackMatch (void);
|
||||
void Mch_ForwardMatch (void);
|
||||
|
||||
unsigned Mch_GetNumMchsInGame (long GamCod);
|
||||
unsigned Mch_GetNumUnfinishedMchsInGame (long GamCod);
|
||||
unsigned Mch_DB_GetNumMchsInGame (long GamCod);
|
||||
unsigned Mch_DB_GetNumUnfinishedMchsInGame (long GamCod);
|
||||
|
||||
bool Mch_CheckIfICanPlayThisMatchBasedOnGrps (const struct Mch_Match *Match);
|
||||
|
||||
|
@ -154,8 +154,10 @@ void Mch_GetMatchQuestionsFromDB (struct MchPrn_Print *Print);
|
|||
|
||||
void Mch_ComputeScore (struct MchPrn_Print *Print);
|
||||
|
||||
unsigned Mch_GetNumUsrsWhoAnsweredQst (long MchCod,unsigned QstInd);
|
||||
unsigned Mch_GetNumUsrsWhoHaveChosenAns (long MchCod,unsigned QstInd,unsigned AnsInd);
|
||||
unsigned Mch_DB_GetNumUsrsWhoAnsweredQst (long MchCod,unsigned QstInd);
|
||||
unsigned Mch_DB_GetNumUsrsWhoHaveChosenAns (long MchCod,unsigned QstInd,unsigned AnsInd);
|
||||
void Mch_DrawBarNumUsrs (unsigned NumRespondersAns,unsigned NumRespondersQst,bool Correct);
|
||||
|
||||
unsigned Mch_DB_GetStartEndMatchesInGame (MYSQL_RES **mysql_res,long GamCod);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue
Block a user