#include
using namespace std;
const int INF = 1000000000; // A very large number.
// Store the file names in a vector.
const vector file_names = vector({
"Wolves.csv",
"Newcastle.csv",
"Man_City.csv",
"Leicester.csv",
"Norwich.csv",
"Crystal_Palace.csv",
"Watford.csv",
"Brighton.csv",
"Spurs.csv",
"Sheffield_Utd.csv",
"West_Ham.csv",
"Arsenal.csv",
"Everton.csv",
"Aston_Villa.csv",
"Man_Utd.csv",
"Bournemouth.csv",
"Burnley.csv",
"Chelsea.csv",
"Liverpool.csv",
"Southampton.csv",
});
// Store the valid 20 team names in a vector.
const vector team_names = vector({
"Leicester",
"Wolves",
"Everton",
"Crystal Palace",
"Man City",
"Newcastle",
"Arsenal",
"Bournemouth",
"Brighton",
"Norwich",
"Liverpool",
"Watford",
"Southampton",
"Man Utd",
"Spurs",
"West Ham",
"Aston Villa",
"Sheffield Utd",
"Burnley",
"Chelsea",
});
// class Match. Stores the names and the corresponding scores of each match.
class Match{
public:
Match(string name1, string name2, int score1, int score2)
: name1(name1), name2(name2), score1(score1), score2(score2) {}
string get_name1(){
return name1;
}
string get_name2(){
return name2;
}
int get_score1(){
return score1;
}
int get_score2(){
return score2;
}
private:
string name1, name2; // `name1` represents Home Team, `name2` represents Away Team.
int score1, score2; // `score1` represents score of Home Team, `score2` represents score of Away Team.
};
// class Team. Stores the total matches of a team.
class Team{
public:
Team(){}
vector get_matches(){
return matches;
}
void set_matches(Match& m){
matches.push_back(m);
}
private:
vector matches;
};
// Code to read a csv file and parse the inputs.
string strip(string& s){
s = regex_replace(s, regex("^ +"), "");
s = regex_replace(s, regex(" +$"), "");
return s;
}
bool check(const string& s){
for(const auto e : team_names){
if(e == s) return true;
}
return false;
}
void read_csv(string file_name, Team& t){
fstream fin;
fin.open(file_name, ios::in);
vector row;
string line, word, temp;
bool flag = false;
while(fin >> temp){
row.clear();
getline(fin, line);
stringstream s(line);
while(getline(s, word, '\t')){
row.push_back(strip(word));
}
if(flag && row.size() == 6 && check(row[3]) && check(row[4])){ // Discarding inconsistent data. Some data is inconsistent because of misplaced tabs.
if(row[5].find('-') != -1){
Match m(row[3], row[4], row[5][0]-'0', row[5][4]-'0'); // For played matches store the original score.
t.set_matches(m);
}
else{
Match m(row[3], row[4], -1, -1); // For unplayed matches store -1 in the respective scores.
t.set_matches(m);
}
}
flag = true;
}
}
// class EPL. Stores the total data of each and every team.
class EPL{
public:
EPL(){
for(const auto file_name : file_names){
Team t;
string path = "Data/" + file_name;
read_csv(path, t);
teams.push_back(t);
}
}
vector get_teams(){
return teams;
}
private:
vector teams;
};
// cout all team parameters. Just to check.
void print(EPL& epl){
vector teams = epl.get_teams();
cout << "Total number of teams : " << teams.size() << endl;
for(auto& team : teams){
vector matches = team.get_matches();
cout << "-----------------------------------------------------------\n";
cout << "Total matches for this team : " << matches.size() << endl;
for(auto& match : matches){
cout << match.get_name1() << " " << match.get_name2() << " " << match.get_score1() << " " << match.get_score2() << endl;
}
cout << "-----------------------------------------------------------\n";
}
}
// The Matrix class. Stores the Home Team in the row index and the Away Team in the column index.
// The corresponding index stores the score of Home Team - Away Team.
// The matches which are not played are represented with INF.
class Matrix{
public:
Matrix(int size=20){
N = size;
NNZ = 0;
matrix.assign(N, vector(N, INF));
I.assign(N, 0);
J.assign(N, 0);
}
int get_size(){ // Returns the size of the matrix.
return N;
}
void set_ij(int i, int j, int s1, int s2){
assert(i < N && j < N);
matrix[i][j] = s1-s2;
if(s1 != s2) NNZ++;
if(s1 > s2) I[i] += 1;
else if (s1 < s2) J[j] += 1;
}
double get_ij(int i, int j){
assert(i < N && j < N);
return matrix[i][j];
}
void print_matrix(){
for(int i=0; i for(int j=0;j cout << matrix[i][j] << "\t";
}
cout << endl;
}
}
int get_I(int i){
return I[i];
}
int get_J(int j){
return J[j];
}
private:
vector> matrix;
vector I; // i'th element stores the number of times team i won in Home play.
vector J; // i'th element stores the number of times team i won in Away play.
int N;
int NNZ;
};
// Returns the index of the position of the team name in `team_names`.
int index(string team_name){
for(int i=0; i if(team_names[i] == team_name) return i;
}
return -1; // This will not occur. Just for error checking.
}
template void printElement(T t, const int& width){
char separator = ' ';
cout << left << setw(width) << setfill(separator) << t;
}
int main(){
EPL epl;
//print(epl);
Matrix matrix;
// Fill the matrix.
vector teams = epl.get_teams();
set> predict;
//cout << "Total number of teams : " << teams.size() << endl;
for(auto& team : teams){
vector matches = team.get_matches();
for(auto& match : matches){
const int i = index(match.get_name1()), j = index(match.get_name2()), s1 = match.get_score1(), s2 = match.get_score2();
if(s1 != -1 && s2 != -1)
matrix.set_ij(i, j, s1, s2);
else predict.insert({i, j});
}
}
//matrix.print_matrix();
vector count(20, 0);
// Now predicting.
cout << "Prediction Table : \n";
ofstream fout;
fout.open("prediction.csv");
cout << "HOME TEAM\t\t\tAWAY TEAM\t\t\tPREDICTION\n";
fout << "HOME TEAM\tAWAY TEAM\tPREDICTION\n";
cout << "-----------------------------------------------------------------------------------------------------" << endl;
for(const auto& p : predict){
int i = p.first, j = p.second;
printElement(team_names[i], 32);
printElement(team_names[j], 32);
fout << team_names[i] << "\t" << team_names[j] << "\t";
int team1_h = matrix.get_I(i)/2, team1_a = matrix.get_J(i)/2, team2_h = matrix.get_I(j)/2, team2_a = matrix.get_J(j)/2;
if(team1_h > team2_a){
cout << team_names[i] << " is predicted to win." << endl;
fout << team_names[i] << " is predicted to win." << endl;
count[i]++;
}
else if(team1_h < team2_a){
cout << team_names[j] << " is predicted to win." << endl;
fout << team_names[j] << " is predicted to win." << endl;
count[j]++;
}
else{
cout << "This match is predicted to be a draw." << endl;
fout << "This match is predicted to be a draw." << endl;
}
cout << "-----------------------------------------------------------------------------------------------------" << endl;
}
fout.close();
vector> standing;
for(int i=0; i<20; i++){
count[i] += (matrix.get_I(i) / 2) + (matrix.get_J(i) / 2);
standing.push_back({-count[i], i});
}
sort(standing.begin(), standing.end());
fout.open("standings.csv");
cout << "STANDINGS - " << endl;
printElement("TEAM NAME : ", 32);
printElement("WINS : ", 32);
printElement("LOST / DRAW : ", 32);
cout << endl;
fout << "TEAM NAME\tWINS\tLOST / DRAW\n";
cout << "==============================================================================\n";
for(const auto& p : standing){
printElement(team_names[p.second], 32);
printElement(to_string(-p.first), 32);
printElement(to_string(38+p.first), 32);
cout << endl;
fout << team_names[p.second] << "\t" << -p.first << "\t" << 38+p.first << endl;
}
cout << "==============================================================================\n";
fout.close();
return 0;
}
// Run as :
// $ g++ -std=c++17 -o main main.cpp
// $ ./main
// We can see in the output, in every instance where Liverpool is a Home Team it is expected to win.