Display median time instead of average (fixes #3399)

This commit is contained in:
def 2021-01-12 14:24:38 +01:00
parent 5d45f061fa
commit 39d06c5e85
6 changed files with 45 additions and 10 deletions

View file

@ -21,7 +21,7 @@ public:
virtual IDbConnection *Copy() = 0; virtual IDbConnection *Copy() = 0;
// returns the database prefix // returns the database prefix
const char *GetPrefix() { return m_aPrefix; } const char *GetPrefix() const { return m_aPrefix; }
virtual const char *BinaryCollate() const = 0; virtual const char *BinaryCollate() const = 0;
// can be inserted into queries to convert a timestamp variable to the unix timestamp // can be inserted into queries to convert a timestamp variable to the unix timestamp
virtual void ToUnixTimestamp(const char *pTimestamp, char *aBuf, unsigned int BufferSize) = 0; virtual void ToUnixTimestamp(const char *pTimestamp, char *aBuf, unsigned int BufferSize) = 0;
@ -35,6 +35,8 @@ public:
virtual const char *InsertIgnore() const = 0; virtual const char *InsertIgnore() const = 0;
// ORDER BY RANDOM()/RAND() // ORDER BY RANDOM()/RAND()
virtual const char *Random() const = 0; virtual const char *Random() const = 0;
// Get Median Map Time from l.Map
virtual const char *MedianMapTime(char *pBuffer, int BufferSize) const = 0;
enum Status enum Status
{ {

View file

@ -309,6 +309,18 @@ int CMysqlConnection::GetBlob(int Col, unsigned char *pBuffer, int BufferSize) c
#endif #endif
} }
const char *CMysqlConnection::MedianMapTime(char *pBuffer, int BufferSize) const
{
str_format(pBuffer, BufferSize,
"SELECT MEDIAN(Time) "
"OVER (PARTITION BY Map) "
"FROM %s_race "
"GROUP BY Map "
"HAVING Map = l.Map",
GetPrefix());
return pBuffer;
}
void CMysqlConnection::AddPoints(const char *pPlayer, int Points) void CMysqlConnection::AddPoints(const char *pPlayer, int Points)
{ {
char aBuf[512]; char aBuf[512];

View file

@ -35,6 +35,7 @@ public:
virtual const char *CollateNocase() const { return "CONVERT(? USING utf8mb4) COLLATE utf8mb4_general_ci"; } virtual const char *CollateNocase() const { return "CONVERT(? USING utf8mb4) COLLATE utf8mb4_general_ci"; }
virtual const char *InsertIgnore() const { return "INSERT IGNORE"; }; virtual const char *InsertIgnore() const { return "INSERT IGNORE"; };
virtual const char *Random() const { return "RAND()"; }; virtual const char *Random() const { return "RAND()"; };
virtual const char *MedianMapTime(char *pBuffer, int BufferSize) const;
virtual Status Connect(); virtual Status Connect();
virtual void Disconnect(); virtual void Disconnect();

View file

@ -214,6 +214,23 @@ int CSqliteConnection::GetBlob(int Col, unsigned char *pBuffer, int BufferSize)
return Size; return Size;
} }
const char *CSqliteConnection::MedianMapTime(char *pBuffer, int BufferSize) const
{
str_format(pBuffer, BufferSize,
"SELECT AVG("
" CASE counter %% 2 "
" WHEN 0 THEN CASE WHEN rn IN (counter / 2, counter / 2 + 1) THEN Time END "
" WHEN 1 THEN CASE WHEN rn = counter / 2 + 1 THEN Time END END) "
" OVER (PARTITION BY Map) AS Median "
"FROM ("
" SELECT *, ROW_NUMBER() "
" OVER (PARTITION BY Map ORDER BY Time) rn, COUNT(*) "
" OVER (PARTITION BY Map) counter "
" FROM %s_race where Map = l.Map) as r",
GetPrefix());
return pBuffer;
}
bool CSqliteConnection::Execute(const char *pQuery) bool CSqliteConnection::Execute(const char *pQuery)
{ {
char *pErrorMsg; char *pErrorMsg;

View file

@ -22,6 +22,7 @@ public:
virtual const char *CollateNocase() const { return "? COLLATE NOCASE"; } virtual const char *CollateNocase() const { return "? COLLATE NOCASE"; }
virtual const char *InsertIgnore() const { return "INSERT OR IGNORE"; }; virtual const char *InsertIgnore() const { return "INSERT OR IGNORE"; };
virtual const char *Random() const { return "RANDOM()"; }; virtual const char *Random() const { return "RANDOM()"; };
virtual const char *MedianMapTime(char *pBuffer, int BufferSize) const;
virtual Status Connect(); virtual Status Connect();
virtual void Disconnect(); virtual void Disconnect();

View file

@ -355,12 +355,13 @@ bool CScore::MapInfoThread(IDbConnection *pSqlServer, const ISqlData *pGameData)
char aTimestamp[512]; char aTimestamp[512];
pSqlServer->ToUnixTimestamp("l.Timestamp", aTimestamp, sizeof(aTimestamp)); pSqlServer->ToUnixTimestamp("l.Timestamp", aTimestamp, sizeof(aTimestamp));
char aBuf[1024]; char aMedianMapTime[2048];
char aBuf[4096];
str_format(aBuf, sizeof(aBuf), str_format(aBuf, sizeof(aBuf),
"SELECT l.Map, l.Server, Mapper, Points, Stars, " "SELECT l.Map, l.Server, Mapper, Points, Stars, "
" (SELECT COUNT(Name) FROM %s_race WHERE Map = l.Map) AS Finishes, " " (SELECT COUNT(Name) FROM %s_race WHERE Map = l.Map) AS Finishes, "
" (SELECT COUNT(DISTINCT Name) FROM %s_race WHERE Map = l.Map) AS Finishers, " " (SELECT COUNT(DISTINCT Name) FROM %s_race WHERE Map = l.Map) AS Finishers, "
" (SELECT ROUND(AVG(Time)) FROM %s_race WHERE Map = l.Map) AS Average, " " (%s) AS Median, "
" %s AS Stamp, " " %s AS Stamp, "
" %s-%s AS Ago, " " %s-%s AS Ago, "
" (SELECT MIN(Time) FROM %s_race WHERE Map = l.Map AND Name = ?) AS OwnTime " " (SELECT MIN(Time) FROM %s_race WHERE Map = l.Map AND Name = ?) AS OwnTime "
@ -374,7 +375,8 @@ bool CScore::MapInfoThread(IDbConnection *pSqlServer, const ISqlData *pGameData)
" Map " " Map "
" LIMIT 1" " LIMIT 1"
") as l;", ") as l;",
pSqlServer->GetPrefix(), pSqlServer->GetPrefix(), pSqlServer->GetPrefix(), pSqlServer->GetPrefix(), pSqlServer->GetPrefix(),
pSqlServer->MedianMapTime(aMedianMapTime, sizeof(aMedianMapTime)),
aTimestamp, aCurrentTimestamp, aTimestamp, aTimestamp, aCurrentTimestamp, aTimestamp,
pSqlServer->GetPrefix(), pSqlServer->GetPrefix(), pSqlServer->GetPrefix(), pSqlServer->GetPrefix(),
pSqlServer->CollateNocase()); pSqlServer->CollateNocase());
@ -396,7 +398,7 @@ bool CScore::MapInfoThread(IDbConnection *pSqlServer, const ISqlData *pGameData)
int Stars = pSqlServer->GetInt(5); int Stars = pSqlServer->GetInt(5);
int Finishes = pSqlServer->GetInt(6); int Finishes = pSqlServer->GetInt(6);
int Finishers = pSqlServer->GetInt(7); int Finishers = pSqlServer->GetInt(7);
int Average = pSqlServer->GetInt(8); float Median = pSqlServer->GetInt(8);
int Stamp = pSqlServer->GetInt(9); int Stamp = pSqlServer->GetInt(9);
int Ago = pSqlServer->GetInt(10); int Ago = pSqlServer->GetInt(10);
float OwnTime = pSqlServer->GetFloat(11); float OwnTime = pSqlServer->GetFloat(11);
@ -409,11 +411,11 @@ bool CScore::MapInfoThread(IDbConnection *pSqlServer, const ISqlData *pGameData)
str_format(aReleasedString, sizeof(aReleasedString), ", released %s ago", aAgoString); str_format(aReleasedString, sizeof(aReleasedString), ", released %s ago", aAgoString);
} }
char aAverageString[60] = "\0"; char aMedianString[60] = "\0";
if(Average > 0) if(Median > 0)
{ {
str_time((int64)Average * 100, TIME_HOURS, aBuf, sizeof(aBuf)); str_time((int64)Median * 100, TIME_HOURS, aBuf, sizeof(aBuf));
str_format(aAverageString, sizeof(aAverageString), " in %s average", aBuf); str_format(aMedianString, sizeof(aMedianString), " in %s median", aBuf);
} }
char aStars[20]; char aStars[20];
@ -443,7 +445,7 @@ bool CScore::MapInfoThread(IDbConnection *pSqlServer, const ISqlData *pGameData)
aReleasedString, aReleasedString,
Finishes, Finishes == 1 ? "finish" : "finishes", Finishes, Finishes == 1 ? "finish" : "finishes",
Finishers, Finishers == 1 ? "tee" : "tees", Finishers, Finishers == 1 ? "tee" : "tees",
aAverageString, aOwnFinishesString); aMedianString, aOwnFinishesString);
} }
else else
{ {