Building A Simple Betting Score App

Building A Simple Betting Score App

A fun side project each year is to create a little front facing web application for a Champions League Betting Pool.

Each year 8 of us choose 6 players from the teams in the qualifying rounds of Champions League. The total goals per group of picks win. But a challenge each year is to not sure organize the picking, but keep up with all the goals throughout the challenge. So I offered to automate this task. Below is a quick outline of how I built this small tool to save the group time.

The main components

  • Latest Score Data - Access to an API to continuously get the latest champions league scorer
  • The players bets - The list of betters and their pick
  • Update Logic - The logic to update the latest data over time
  • Display - The ability to display this data on the page

Latest Score Data

We need a way to get the latest score data. A quick google search brings up several options, some of which are free. After a quick glimpse of the docs and pricing, I choose [football-data.org - API Quickstart](https://www.football-data.org/documentation/quickstart)

The reason why is it’s a very lightweight, free option. It also provides a very easy API endpoint to get all ‘Scorers’ with a competition.  We just need to plugin the code for Champions League.

Scorers: https://api.football-data.org/v2/competitions/SA/scorers

Bets Details

Now that I know I can compare all the scores versus the bets. It’s time to organize all the bets. For this small app, I’ve chosen to simply manually create a array of all the betters and their picks. This will allow me to reference the bets and update the scores each time I fetch new data from the API. Here’s an example:


   {
           name: 'Carty',
           totalGoals: 0,
           picks: [
                {'pick': 1, 'player': 'Robert Lewandowski', 'goals': 0},
                {'pick': 2, 'player': 'João Félix', 'goals':  0},
                {'pick': 3, 'player': 'Paulo Dybala', 'goals': 0},
                {'pick': 4, 'player': 'Philippe Coutinho','goals': 0},
                {'pick': 5, 'player': 'Roberto Firmino', 'goals': 0},
                {'pick': 6, 'player': 'Tammy Abraham', 'goals': 0}

           ]

This I’ll put at the top of my JavaScript file. If I were to automate this later, perhaps I’d fetch all the available players and create a simple interface for each player to choose his or her player.

Now that I have all the bets and all the players, it’s time to create the logic to update the scores and add those to the page.

Update Logic


Below is the logic used to fetch new bets, compare the bets of each better, and calculate the totals. So what this is doing is:

  • Iterating through each better
  • For each better, I’m then iterating through each pick
  • For each pick, I’m then iterating through the entire scores feed to look for any matches. If there are matches I’m updating the players total goals in the betters data
  • After checking for each player, I then sum the total goals for each player and storing it on the ‘totalGoals’ attribute for each better


  // Iterate through each persons bets

       bets.forEach(function(person) {
         
         // For each person betting, loop through each of their bets
 
           person.picks.forEach(function(pick) {
             
             // Search players bets in the entire API feed containing all scorers

               playerArray.forEach(function(t) {
               
               // If a match is found by name, add players goals to persons goal totals
               // If no match is found, do nothing
               
               if(pick.player === t.player.name) {
                   
                   pick.goals += t.numberOfGoals;
                   
               }
           })
           })
         
        // After grabbing all players goals from feed...
        // Sum up total number of players goals and store on 'totalGoals' attribute
         
        person.picks.forEach(function(pick) {
          person.totalGoals += pick.goals;
        })
})

At the end of this entire code block, my betters data should now be completely updated with the latest scoring data.

Adding to the Page
Now that we have the final data stored, it’s time to add it to the page. This is the important of the “separation of concerns”. It is far easier to fetch and manipulate our data separately from adding it to the page. The method I’m using here is to create one function called “addToDom” that runs /after/ the initial data load. Now, we can solely focus on the display of this data, rather than doing it together.

Below you’ll see I do some simple tasks to organize and pass data into HTML templates.

First, I sort my data by total goals to ensure the data is in a leaderboard format

Second, I create each individual player “panel”.  I store this value in a ‘pickList’ variable and pass the template variables to it. It returns the panel HTML. I then add join(‘’), to return a full string of HTML.

Lastly, I pass this entire string of HTML into the better “block” template, which includes the better name and total goals. I then append this entire block, including each of it’s child panels to the DOM.


function addToDom() {

   // Sort playerArray by total goals to create leaderboard
     
      var a = bets.sort(function(a, b) {
           return b.totalGoals - a.totalGoals
       })
 
      // Add the players picks and totals to the DO<

       a.forEach(function(person) {
         
           var pickList = person.picks.map(function(pick) {
             
             // If a player has a goal, highlight the color blue using the info class
             
             var color = pick.goals > 0 ? 'info' : ''
             
               return `<div class="panel-block">
                          <div class="pull-left"> ${pick.player}</div>
                           <div class="pull-right"><span class="tag is-${color}">${pick.goals}</span></div>
                       </div>
                       `
           }).join('')

As a result, I get something like this:

I don't consider myself a developer. But I do enjoy creating these little apps. It’s a fun very small side hobby and it’s great to know that I can at least scrape together an MVP for a small tool. These little projects are also a great outlet for thinking clearly and solving problems.