#include <stdio.h>
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
#include <stdlib.h>
using namespace std;
#define PUNISH_TIME 20
class Team
{
public:
Team(int no) : m_No (no), m_solvedProblems(0), m_totalTime(0)
{
}
~Team()
{
map<int, Issue*>::iterator iter = m_IssueCol.begin();
while(iter != m_IssueCol.end())
{
delete iter->second;
++iter;
}
}
void Calculate()
{
m_solvedProblems = 0;
m_totalTime = 0;
map<int, Issue*>::iterator iter = m_IssueCol.begin();
while(iter != m_IssueCol.end())
{
if (iter->second->m_totalTime >= 0) // Solved Issue
{
++m_solvedProblems;
m_totalTime += iter->second->m_totalTime + iter->second->m_FailedTimes * PUNISH_TIME;
}
++iter;
}
}
void AddIssue(int no, int time, char status)
{
if ((status == 'R') || (status == 'U') || (status == 'E'))
return;
map<int, Issue*>::iterator iter = m_IssueCol.find(no);
if (iter == m_IssueCol.end())
{
m_IssueCol.insert(pair<int, Issue*>(no, new Issue()));
iter = m_IssueCol.find(no);
}
Issue* pIssue = iter->second;
if (status == 'I')
{
if (pIssue->m_totalTime < 0)
++(pIssue->m_FailedTimes);
}
else if (status == 'C')
{
if ((pIssue->m_totalTime > time) || (pIssue->m_totalTime < 0))
pIssue->m_totalTime = time;
}
}
void Output()
{
cout << m_No << ' ' << m_solvedProblems << ' ' << m_totalTime << endl;
}
bool operator > (const Team& other) const
{
if (m_solvedProblems < other.m_solvedProblems)
return false;
if (m_solvedProblems > other.m_solvedProblems)
return true;
if (m_totalTime > other.m_totalTime)
return false;
if (m_totalTime < other.m_totalTime)
return true;
return (m_No < other.m_No);
}
private:
struct Issue
{
Issue() : m_FailedTimes (0), m_totalTime (-1) {}
int m_FailedTimes;
int m_totalTime;
};
int m_No;
int m_solvedProblems;
int m_totalTime;
map<int, Issue*> m_IssueCol;
};
class TeamCol
{
public:
~TeamCol()
{
map<int, Team*>::iterator iter = m_TeamCol.begin();
while(iter != m_TeamCol.end())
{
delete iter->second;
++iter;
}
}
bool AddTeamInfo(char* line)
{
if ((line == NULL) || (line[0] == '\0') || (line[0] == '\n'))
return false;
int teamNo, issueNo, time;
char status;
int start = 0;
if (!GetIntFromLine(line, start, teamNo))
return false;
line += start;
if (!GetIntFromLine(line, start, issueNo))
return false;
line += start;
if (!GetIntFromLine(line, start, time))
return false;
line += start;
if (!GetCharFromLine(line, status))
return false;
AddTeamInfo(teamNo, issueNo, time, status);
return true;
}
void OutputSortedResult()
{
vector<Team*> resultVec;
map<int, Team*>::iterator iter = m_TeamCol.begin();
while(iter != m_TeamCol.end())
{
iter->second->Calculate();
resultVec.push_back(iter->second);
++iter;
}
std::sort(resultVec.begin(), resultVec.end(), TeamGreater());
for (size_t i = 0; i < resultVec.size(); ++i)
resultVec[i]->Output();
}
private:
bool GetCharFromLine(char* line, char& result)
{
int i = 0;
while(line[i] == ' ')
++i;
if((line[i] == '\n') || (line[i] == '\0'))
return false;
result = line[i];
return true;
}
bool GetIntFromLine(char* line, int& newStart, int& result)
{
int start = 0, i = 0;
while(line[i] == ' ')
{
++start;
++i;
}
while((line[i] != '\n') && (line[i] != '\0') && (line[i] != ' '))
{
++i;
}
if (start == i)
return false;
line[i] = '\0';
result = atoi(line + start);
newStart = i + 1;
return true;
}
typedef Team* TeamPtr;
class TeamGreater
{
public:
bool operator()(const TeamPtr& _Left, const TeamPtr& _Right) const
{ // apply operator> to operands
return ((*_Left)>(*_Right));
}
};
void AddTeamInfo(int teamNo, int issueNo, int time, char status)
{
map<int, Team*>::iterator iter = m_TeamCol.find(teamNo);
if (iter == m_TeamCol.end())
{
m_TeamCol.insert(pair<int, Team*>(teamNo, new Team(teamNo)));
iter = m_TeamCol.find(teamNo);
}
iter->second->AddIssue(issueNo, time, status);
}
map<int, Team*> m_TeamCol;
};
#define MAX_BUF_SIZE 1024
static char buf[MAX_BUF_SIZE];
static void DoTestCase()
{
TeamCol teamCol;
while(true)
{
if (!fgets(buf, MAX_BUF_SIZE, stdin))
break;
if (!teamCol.AddTeamInfo(buf))
break;
}
teamCol.OutputSortedResult();
}
static void DoTest()
{
int cnt;
cin >> cnt;
fgets(buf, MAX_BUF_SIZE, stdin); // Consume the '\n' after the test case count.
fgets(buf, MAX_BUF_SIZE, stdin); // Consume the empty line.
for (int i = 0; i < cnt; ++i)
{
DoTestCase();
if (i < (cnt - 1))
cout << endl;
}
}
int main(int argc, char* argv[])
{
DoTest();
return 0;
}