3392: Add /top5team s?i command to show all team ranks of a player r=def- a=Zwelf

I like to see whom I have finished a map with. `/teamrank` only provides one result. With this command I can request all teams I finished a map with.

## Checklist

- [x] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test if it works standalone, system.c especially
- [ ] Considered possible null pointers and out of bounds array indexing
- [x] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


Co-authored-by: Zwelf <zwelf@strct.cc>
This commit is contained in:
bors[bot] 2020-12-12 11:42:26 +00:00 committed by GitHub
commit 13762aa197
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 121 additions and 5 deletions

View file

@ -387,10 +387,37 @@ void CGameContext::ConTeamTop5(IConsole::IResult *pResult, void *pUserData)
return;
}
if(pResult->NumArguments() > 0)
pSelf->Score()->ShowTeamTop5(pResult->m_ClientID, pResult->GetInteger(0));
if(pResult->NumArguments() == 0)
{
pSelf->Score()->ShowTeamTop5(pResult->m_ClientID, 1);
}
else if(pResult->NumArguments() == 1)
{
if(pResult->GetInteger(0) != 0)
{
pSelf->Score()->ShowTeamTop5(pResult->m_ClientID, pResult->GetInteger(0));
}
else
{
const char *pRequestedName = (str_comp(pResult->GetString(0), "me") == 0) ?
pSelf->Server()->ClientName(pResult->m_ClientID) :
pResult->GetString(0);
pSelf->Score()->ShowTeamTop5(pResult->m_ClientID, pRequestedName, 0);
}
}
else if(pResult->NumArguments() == 2 && pResult->GetInteger(1) != 0)
{
const char *pRequestedName = (str_comp(pResult->GetString(0), "me") == 0) ?
pSelf->Server()->ClientName(pResult->m_ClientID) :
pResult->GetString(0);
pSelf->Score()->ShowTeamTop5(pResult->m_ClientID, pRequestedName, pResult->GetInteger(1));
}
else
pSelf->Score()->ShowTeamTop5(pResult->m_ClientID);
{
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "teamtop5", "/top5team needs 0, 1 or 2 parameter. 1. = name, 2. = start number");
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "teamtop5", "Example: /top5team, /top5team me, /top5team Hans, /top5team \"Papa Smurf\" 5");
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "teamtop5", "Bad: /top5team Papa Smurf 5 # Good: /top5team \"Papa Smurf\" 5 ");
}
}
void CGameContext::ConTop5(IConsole::IResult *pResult, void *pUserData)

View file

@ -33,8 +33,8 @@ CHAT_COMMAND("map", "?r[map]", CFGFLAG_CHAT | CFGFLAG_SERVER | CFGFLAG_NONTEEHIS
CHAT_COMMAND("rankteam", "?r[player name]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConTeamRank, this, "Shows the team rank of player with name r (your team rank by default)")
CHAT_COMMAND("teamrank", "?r[player name]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConTeamRank, this, "Shows the team rank of player with name r (your team rank by default)")
CHAT_COMMAND("rank", "?r[player name]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConRank, this, "Shows the rank of player with name r (your rank by default)")
CHAT_COMMAND("top5team", "?i[rank to start with]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConTeamTop5, this, "Shows five team ranks of the ladder beginning with rank i (1 by default, -1 for worst)")
CHAT_COMMAND("teamtop5", "?i[rank to start with]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConTeamTop5, this, "Shows five team ranks of the ladder beginning with rank i (1 by default, -1 for worst)")
CHAT_COMMAND("top5team", "?s[player name] ?i[rank to start with]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConTeamTop5, this, "Shows five team ranks of the ladder or of a player beginning with rank i (1 by default, -1 for worst)")
CHAT_COMMAND("teamtop5", "?s[player name] ?i[rank to start with]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConTeamTop5, this, "Shows five team ranks of the ladder or of a player beginning with rank i (1 by default, -1 for worst)")
CHAT_COMMAND("top5", "?i[rank to start with]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConTop5, this, "Shows five ranks of the ladder beginning with rank i (1 by default, -1 for worst)")
CHAT_COMMAND("times", "?s[player name] ?i[number of times to skip]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConTimes, this, "/times ?s?i shows last 5 times of the server or of a player beginning with name s starting with time i (i = 1 by default, -1 for first)")
CHAT_COMMAND("points", "?r[player name]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConPoints, this, "Shows the global points of a player beginning with name r (your rank by default)")

View file

@ -918,6 +918,93 @@ bool CScore::ShowTeamTop5Thread(IDbConnection *pSqlServer, const ISqlData *pGame
return true;
}
void CScore::ShowTeamTop5(int ClientID, const char *pName, int Offset)
{
if(RateLimitPlayer(ClientID))
return;
ExecPlayerThread(ShowPlayerTeamTop5Thread, "show team top5 player", ClientID, pName, Offset);
}
bool CScore::ShowPlayerTeamTop5Thread(IDbConnection *pSqlServer, const ISqlData *pGameData)
{
const CSqlPlayerRequest *pData = dynamic_cast<const CSqlPlayerRequest *>(pGameData);
CScorePlayerResult *pResult = dynamic_cast<CScorePlayerResult *>(pGameData->m_pResult.get());
auto *paMessages = pResult->m_Data.m_aaMessages;
int LimitStart = maximum(abs(pData->m_Offset) - 1, 0);
const char *pOrder = pData->m_Offset >= 0 ? "ASC" : "DESC";
// check sort method
char aBuf[2400];
str_format(aBuf, sizeof(aBuf),
"SELECT l.ID, Name, Time, Rank "
"FROM (" // teamrank score board
" SELECT RANK() OVER w AS Rank, ID "
" FROM %s_teamrace "
" WHERE Map = ? "
" GROUP BY ID "
" WINDOW w AS (ORDER BY Time)"
") AS TeamRank INNER JOIN (" // select rank with Name in team
" SELECT ID "
" FROM %s_teamrace "
" WHERE Map = ? AND Name = ? "
" ORDER BY Time %s "
" LIMIT %d, 5 "
") AS l ON TeamRank.ID = l.ID "
"INNER JOIN %s_teamrace AS r ON l.ID = r.ID "
"ORDER BY Time %s, l.ID ",
pSqlServer->GetPrefix(), pSqlServer->GetPrefix(), pOrder, LimitStart, pSqlServer->GetPrefix(), pOrder);
pSqlServer->PrepareStatement(aBuf);
pSqlServer->BindString(1, pData->m_Map);
pSqlServer->BindString(2, pData->m_Map);
pSqlServer->BindString(3, pData->m_Name);
if(pSqlServer->Step())
{
// show teamtop5
int Line = 0;
str_copy(paMessages[Line++], "------- Team Top 5 -------", sizeof(paMessages[Line]));
for(Line = 1; Line < 6; Line++) // print
{
float Time = pSqlServer->GetFloat(3);
str_time_float(Time, TIME_HOURS_CENTISECS, aBuf, sizeof(aBuf));
int Rank = pSqlServer->GetInt(4);
CTeamrank Teamrank;
bool Last = !Teamrank.NextSqlResult(pSqlServer);
char aFormattedNames[512] = "";
for(unsigned int Name = 0; Name < Teamrank.m_NumNames; Name++)
{
str_append(aFormattedNames, Teamrank.m_aaNames[Name], sizeof(aFormattedNames));
if(Name < Teamrank.m_NumNames - 2)
str_append(aFormattedNames, ", ", sizeof(aFormattedNames));
else if(Name < Teamrank.m_NumNames - 1)
str_append(aFormattedNames, " & ", sizeof(aFormattedNames));
}
str_format(paMessages[Line], sizeof(paMessages[Line]), "%d. %s Team Time: %s",
Rank, aFormattedNames, aBuf);
if(Last)
{
Line++;
break;
}
}
str_copy(paMessages[Line], "-------------------------------", sizeof(paMessages[Line]));
}
else
{
if(pData->m_Offset == 0)
str_format(paMessages[0], sizeof(paMessages[0]), "%s has no team ranks", pData->m_Name);
else
str_format(paMessages[0], sizeof(paMessages[0]), "%s has no team ranks in the specified range", pData->m_Name);
}
return true;
}
void CScore::ShowTimes(int ClientID, int Offset)
{
if(RateLimitPlayer(ClientID))

View file

@ -290,6 +290,7 @@ class CScore
static bool ShowTeamRankThread(IDbConnection *pSqlServer, const ISqlData *pGameData);
static bool ShowTop5Thread(IDbConnection *pSqlServer, const ISqlData *pGameData);
static bool ShowTeamTop5Thread(IDbConnection *pSqlServer, const ISqlData *pGameData);
static bool ShowPlayerTeamTop5Thread(IDbConnection *pSqlServer, const ISqlData *pGameData);
static bool ShowTimesThread(IDbConnection *pSqlServer, const ISqlData *pGameData);
static bool ShowPointsThread(IDbConnection *pSqlServer, const ISqlData *pGameData);
static bool ShowTopPointsThread(IDbConnection *pSqlServer, const ISqlData *pGameData);
@ -340,6 +341,7 @@ public:
void ShowRank(int ClientID, const char *pName);
void ShowTeamTop5(int ClientID, int Offset = 1);
void ShowTeamTop5(int ClientID, const char *pName, int Offset = 1);
void ShowTeamRank(int ClientID, const char *pName);
void ShowTopPoints(int ClientID, int Offset = 1);