Creating a dynamic football table
It works no matter if it is real, FIFA, or eFootball
Good day, fellow reader. Football is by far the most popular sport in the world. From the World Cup to regional leagues, this game of low scores, team game, and angry fans, has evolved from the 16th century. Its rules had been changed several times, the target audience has spread, and the system of registering and pointing the results from matches has also not been a universal format. To avoid further discussions, we are going to elaborate an automatic positions table.
The problem
For the most part of the world, a game in a league can have three outcomes: win, draw or loss. A winning team gets 3 points, a losing team gets 0, and a draw awards each team with 1 point. We will create a simple script using JavaScript that will process a set of matches and will provide as output a nifty table like this
Reference
- PL: Played (matches)
- W: Wins
- D: Draws
- L: Losses
- GF: Goals for
- GA: Goals against
- GD: Goal difference (GF - GA)
- P: Points
Dynamically generating an HTML table
With aid from the HTMLTableElement interface, you can follow this tutorial from Valentino Gagliardi to grasp an idea of how are we going to modify the DOM dynamically using JavaScript. The main purpose of this article is not how to introduce the data, but how to process and get the needed information for the sports objective.
Storing the data
We are going to store the matches in an array of objects. Each object will contain the basic information about the match the simplest way possible
{
home: "Home Team Name",
away: "Away Team Name",
result: "1-2"
}
Input for the table
We will provide the insertTableBody
and insertTableHead
function with the data, with the following format example.
{NAME: "River Plate" , PL: 14, W: 7, D: 6, L: 1, GF: 19, GA: 9, GD: 10, P: 27}
Processing the input
So, we must build an array with that information, but how do we convert an array of matches to that? We are going to use two functions, one to prepare the info and get the participating teams, and another one to calculate the amounts of every property. The basic pseudocode is
data = []
getDataFromMatches(matches)
foreach match from matches
getHomeTeam of match
getAwayTeam of match
getHomeGoals of match
getAwayGoals of match
if homeTeam is not in data
add homeTeam to data with empty scores
if awayTeam is not in data
add awayTeam to data with empty scores
processMatchResult(data, homeTeam, awayTeam, homeGoals, awayGoals)
sort data by points, if equal, by goal difference, if equal, by goals for
In the above function, we only get the data from the object, and we initialize the scores with the team names. Then, it's all up to processMatchResult to fill the scores for every match. In this case, the winning, draw, lose, and points depend on the comparison of the scores, but the played, goals for, goals against, and goal difference only represent simple additions.
processMatchResult(data, homeTeam, awayTeam, homeGoals, awayGoals)
homeTeam.PLAYED = homeTeam.PLAYED + 1
awayTeam.PLAYED = awayTeam.PLAYED + 1
homeTeam.GF = homeTeam.GF + homeGoals
awayTeam.GF = awayTeam.GF + awayGoals
homeTeam.GA = homeTeam.GA + awayGoals
awayTeam.GA = awayTeam.GA + homeGoals
homeTeam.GD = homeTeam.GF - homeTeam.GA
awayTeam.GD = awayTeam.GF - awayTeam.GA
if homeGoals == awayGoals
homeTeam.D = homeTeam.D + 1
homeTeam.P = homeTeam.P + 1
awayTeam.D = awayTeam.D + 1
awayTeam.P = awayTeam.P + 1
if homeGoals > awayGoals
homeTeam.W = homeTeam.W + 1
homeTeam.P = homeTeam.P + 3
awayTeam.L = awayTeam.L + 1
awayTeam.P = awayTeam.P + 0
if homeGoals < awayGoals
awayTeam.W = awayTeam.W + 1
awayTeam.P = awayTeam.P + 3
homeTeam.L = homeTeam.L + 1
homeTeam.P = homeTeam.P + 0
JavaScript code
Now let's just write those functions in JavaScript.
let data = [];
function getDataFromMatches(matches) {
matches.forEach((match) => {
let homeTeam = match.home;
let awayTeam = match.away;
let homeGoals = match.result.split("-")[0];
let awayGoals = match.result.split("-")[1];
let index = data.findIndex(team => team.NAME === homeTeam);
// Home team non-existant in array, let's create it with default scores
if (index === -1) {
data.push({NAME: homeTeam, PL: 0, W: 0, D: 0, L: 0, GF: 0, GA: 0, GD: 0, P: 0});
}
index = data.findIndex(team => team.NAME === awayTeam);
// Away team non-existant in array, let's create it with default scores
if (index === -1) {
data.push({NAME: awayTeam, PL: 0, W: 0, D: 0, L: 0, GF: 0, GA: 0, GD: 0, P: 0});
}
// parseInt is neccesary because goals are strings at this point
processMatchResult(data, homeTeam, awayTeam, parseInt(homeGoals, 10), parseInt(awayGoals, 10));
});
// data is filled, let's sort it by points, goal difference, goals for.
data.sort((teamA,teamB)=>(teamA.P - teamB.P || teamA.GD - teamB.GD || teamA.GF - teamB.GF));
// sort gets ascending order, we need to reverse it for a normal league table
data.reverse();
}
function processMatchResult(data, homeTeam, awayTeam, homeGoals, awayGoals) {
// We get the reference to each team object
let indexHT = data.findIndex(team => team.NAME === homeTeam);
let indexAT = data.findIndex(team => team.NAME === awayTeam);
// Common data (home) - plus one played and registering the goals
data[indexHT].PL += 1;
data[indexHT].GF += homeGoals;
data[indexHT].GA += awayGoals;
data[indexHT].GD = data[indexHT].GF - data[indexHT].GA;
// Common data (away) - plus one played and registering the goals
data[indexAT].PL += 1;
data[indexAT].GF += awayGoals;
data[indexAT].GA += homeGoals;
data[indexAT].GD = data[indexAT].GF - data[indexAT].GA;
// Draw
if (homeGoals === awayGoals) {
// Home team register a draw
data[indexHT].D += 1;
data[indexHT].P += 1;
// Away team register a draw
data[indexAT].D += 1;
data[indexAT].P += 1;
}
// Home win
if (homeGoals > awayGoals) {
// Home team register a win
data[indexHT].W += 1;
data[indexHT].P += 3;
// Away team register a loss
data[indexAT].L += 1;
}
// Away win
if (homeGoals < awayGoals) {
// Away team register a win
data[indexAT].W += 1;
data[indexAT].P += 3;
// Home team register a loss
data[indexHT].L += 1;
}
}
Now, we just need to add the data to the table, and we're done!
Note: I added some tailwind classes to make it look better,
Play around with the code snippet, modifying the matches, you will see instant changes in the table without further actions. Sweet!
See you around!