Football Game CRUD Application in Javascript & LocalStorage

Total
0
Shares
football game crud application using javascript and localstorage

In this application we are not going to use any backend. Instead, we will use browser’s localstorage as our database. We will learn CRUD principles by developing football game application using javascript, html and css.

You may also like –

Learn creating Twitter feed CRUD app using React, Php and Mysql.

Football Game Demo

The final game will look like the below demo. It will finish in 6 turns but you can easily change it to run for more.

Open game in new tab.

Plan CRUD operations in football game

Rules of our football game –

  1. A player needs to create 2 teams. One of her and another for computer.
  2. She will then create 11 players for each teams.
  3. Our game will begin and there will be a button to hit a goal.
  4. After every turn, computer will hit a goal.
  5. Randomly system will decide if hit was successful or failed. Also it will show yellow and red cards and will penalize teams with 1 or 2 points accordingly.
  6. After 6 turns game will finish and winner will be declared.
  7. There will be extra features like commentary, turn counter, goal images, etc.

We are going to use these LocalStorage functions for CRUD operations –

CREATE

window.localStorage.setItem(key, value);

READ

window.localStorage.getItem(key);

UPDATE

window.localStorage.setItem(oldKey, newValue);

DELETE

window.localStorage.removeItem(oldKey);
window.localStorage.clear();

Part 1: Create Football Teams

First we will create football teams and store them in localstorage.

Create an html file. Let’s call it index.html.

In this file we are building a form to collect the names and players of both the teams. Also, we are setting default values for the ease of our users. These values will be stored in localstorage as soon as the page loads. Check out the code –

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Football Game</title>
  </head>
  <body>
    <h1 style="text-align: center;">Football Game</h1>
    <div id="teambox" style="max-width: 800px; margin: auto;">
      <h2>Select Teams</h2>
      <form onsubmit="storeTeamAndStartPlay(event)">
        <div style="display: flex;">
          <div style="background: darkred; flex-grow: 1; padding: 10px;">
            <h3 style="color: white;">Your Team</h3>
            <input
              type="text"
              required
              id="team1"
              name="team1"
              value=""
              style="width: 100%; padding: 5px; box-sizing: border-box;"
            />
            <h3 style="color: white;">Players</h3>
            <input
              type="text"
              required
              id="team1player1"
              name="team1player1"
              value=""
              style="width: 100%; padding: 5px; box-sizing: border-box;"
            />
            <input
              type="text"
              required
              id="team1player2"
              name="team1player2"
              value=""
              style="width: 100%; padding: 5px; box-sizing: border-box;"
            />
            <input
              type="text"
              required
              id="team1player3"
              name="team1player3"
              value=""
              style="width: 100%; padding: 5px; box-sizing: border-box;"
            />
            <input
              type="text"
              required
              id="team1player4"
              name="team1player4"
              value=""
              style="width: 100%; padding: 5px; box-sizing: border-box;"
            />
            <input
              type="text"
              required
              id="team1player5"
              name="team1player5"
              value=""
              style="width: 100%; padding: 5px; box-sizing: border-box;"
            />
            <input
              type="text"
              required
              id="team1player6"
              name="team1player6"
              value=""
              style="width: 100%; padding: 5px; box-sizing: border-box;"
            />
            <input
              type="text"
              required
              id="team1player7"
              name="team1player7"
              value=""
              style="width: 100%; padding: 5px; box-sizing: border-box;"
            />
            <input
              type="text"
              required
              id="team1player8"
              name="team1player8"
              value=""
              style="width: 100%; padding: 5px; box-sizing: border-box;"
            />
            <input
              type="text"
              required
              id="team1player9"
              name="team1player9"
              value=""
              style="width: 100%; padding: 5px; box-sizing: border-box;"
            />
            <input
              type="text"
              required
              id="team1player10"
              name="team1player10"
              value=""
              style="width: 100%; padding: 5px; box-sizing: border-box;"
            />
            <h6 style="color: white;">Goal Keeper</h6>
            <input
              type="text"
              required
              id="team1player11"
              name="team1player11"
              value=""
              style="width: 100%; padding: 5px; box-sizing: border-box;"
            />
          </div>
          <div style="background: blue; flex-grow: 1; padding: 10px;">
            <h3 style="color: white;">Computer's Team</h3>
            <input
              type="text"
              required
              id="team2"
              name="team2"
              value=""
              style="width: 100%; padding: 5px; box-sizing: border-box;"
            />
            <h3 style="color: white;">Players</h3>
            <input
              type="text"
              required
              id="team2player1"
              name="team2player1"
              value=""
              style="width: 100%; padding: 5px; box-sizing: border-box;"
            />
            <input
              type="text"
              required
              id="team2player2"
              name="team2player2"
              value=""
              style="width: 100%; padding: 5px; box-sizing: border-box;"
            />
            <input
              type="text"
              required
              id="team2player3"
              name="team2player3"
              value=""
              style="width: 100%; padding: 5px; box-sizing: border-box;"
            />
            <input
              type="text"
              required
              id="team2player4"
              name="team2player4"
              value=""
              style="width: 100%; padding: 5px; box-sizing: border-box;"
            />
            <input
              type="text"
              required
              id="team2player5"
              name="team2player5"
              value=""
              style="width: 100%; padding: 5px; box-sizing: border-box;"
            />
            <input
              type="text"
              required
              id="team2player6"
              name="team2player6"
              value=""
              style="width: 100%; padding: 5px; box-sizing: border-box;"
            />
            <input
              type="text"
              required
              id="team2player7"
              name="team2player7"
              value=""
              style="width: 100%; padding: 5px; box-sizing: border-box;"
            />
            <input
              type="text"
              required
              id="team2player8"
              name="team2player8"
              value=""
              style="width: 100%; padding: 5px; box-sizing: border-box;"
            />
            <input
              type="text"
              required
              id="team2player9"
              name="team2player9"
              value=""
              style="width: 100%; padding: 5px; box-sizing: border-box;"
            />
            <input
              type="text"
              required
              id="team2player10"
              name="team2player10"
              value=""
              style="width: 100%; padding: 5px; box-sizing: border-box;"
            />
            <h6 style="color: white;">Goal Keeper</h6>
            <input
              type="text"
              required
              id="team2player11"
              name="team2player11"
              value=""
              style="width: 100%; padding: 5px; box-sizing: border-box;"
            />
          </div>
        </div>
        <div style="text-align: center; padding: 20px;">
          <input
            style="width: 200px; height: 60px; font-size: 24px;"
            type="submit"
            value="Let's Play"
          />
        </div>
      </form>
    </div>
    <script>
      function storeOrDisplayTeams() {
        var teams = window.localStorage.getItem("teams");
        if (teams) {
          teams = JSON.parse(teams);
          Object.keys(teams).forEach(function (team) {
            document.getElementById(`${team}`).value = teams[team].name;
            Object.keys(teams[team].players).forEach(function (player) {
              document.getElementById(`${team}${player}`).value =
                teams[team].players[player];
            });
          });
        } else {
          window.localStorage.setItem(
            "teams",
            JSON.stringify({
              team1: {
                name: "FC Barcelona",
                players: {
                  player1: "Lionel Messi",
                  player2: "S. Dest",
                  player3: "Gerard P.",
                  player4: "Ronald A.",
                  player5: "Sergio B.",
                  player6: "Carles A.",
                  player7: "A. Griezmann",
                  player8: "Miralem P.",
                  player9: "M. Braithwaite",
                  player10: "Ousmane D.",
                  player11: "Neto"
                }
              },
              team2: {
                name: "Juventus F.C.",
                players: {
                  player1: "Giorgio Chiellini",
                  player2: "Matthijs de Ligt",
                  player3: "Arthur",
                  player4: "Sami Khedira",
                  player5: "Cristiano Ronaldo",
                  player6: "Aaron Ramsey",
                  player7: "Adrien Rabiot",
                  player8: "Alex Sandro",
                  player9: "Danilo",
                  player10: "Paulo Dybala",
                  player11: "Wojciech Szczęsny"
                }
              }
            })
          );

          storeOrDisplayTeams();
        }
      }

      function storeTeamAndStartPlay(ev) {
        ev.preventDefault();
        // Store current form values
        // Teams and Players

        var teams = {};

        ["team1", "team2"].forEach(function (team) {
          teams[team] = {
            name: document.getElementById(`${team}`).value,
            players: {}
          };
          for (var i = 1; i <= 11; i++) {
            teams[team].players["player" + i] = document.getElementById(
              `${team}player${i}`
            ).value;
          }
        });

        window.localStorage.setItem("teams", JSON.stringify(teams));
        location.href = "startGame.html";
      }

      storeOrDisplayTeams();
    </script>
  </body>
</html>

The rendered output will look like this –

select football teams and players

Understanding index.html

Okay, so we have created a form with total 24 input fields –

  • 2 fields for team names.
  • 20 fields for middle forward, forward and defenders of both the teams.
  • 2 fields for goalkeepers.

When user submits the form (by clicking play button), we call a function storeTeamAndStartPlay(). This function stores the values into localStorage in the key, teams. The structure of this key is –

localStorage.setItem("teams", JSON.stringify(
{
  team1 : {
             name : '', // name of first team
             players : {
                player1 : '' // Player 1 of Team 1
                player2 : '' // Player 2 of Team 1
                ...
                player10: '' // Player 10 of Team 1
                player11: '' // Goalkeeper of Team 1
             },
          },
  team2 : {
            ... // Same as team 1 but for team 2
          }
}
));

Now we have the teams and the players. It’s time to build the game.

Part 2: Building Game

User Interface (Html & CSS)

First let’s define the total functionality of the game.

  1. Buttons for restarting the game and resetting the teams. (code)
    button for restarting the game and resetting the teams
  2. Team score cards which will display total points, goals, penalty, red cards and yellow cards. (code)
    team score card with total points, penalty, goals, red cards and yellow cards
  3. Section to show the total goals blocked and missed by goalkeepers. (code)
    goalkeeper stats of total blocked and missed goals
  4. Board, showing the list of all players along with their individual goals, penalty, red cards and yellow cards. (code)
    individual player stats table with goals, penalties, red and yellow cards got in the game
  5. Box to show whose turn it is (computer or your). It will also have the play button. (code)
    box showing turns and play button
  6. One box for commentary. (code)
    football commentary box
  7. A popup to show the outcome of each turn along with an image. (code)
    popup to display outcome of each turn in football
  8. Another popup to display the final results. (code)
    popup to show final results

Let’s pick these modules one by one and develop them. But first create a new page and call it startGame.html.

Buttons – Restart Game & Reset Teams

<h1 style="text-align: center;">
   Football Game
   <button onClick="window.location.reload()">Restart Game</button>
   <button onclick="resetTeams()">Reset Teams</button>
</h1>

<script>
  function resetTeams() {
     window.location.href = "/";
  }
</script>

Restart game button will reload the page using window.location.reload(). While, Reset Teams button will redirect the player to index.html.

Team Score Cards

<h3 id="team1name" style="color: white;"></h3>
<div style="background: black; margin-bottom: 20px;">
	<table style="width: 100%; color: white;">
	  <thead>
		<tr style="font-size: 24px; font-weight: bold;">
		  <th style="text-align: center;">SCORE</th>
		  <th id="team1score"></th>
		</tr>
	  </thead>
	  <tbody>
		<tr>
		  <td>Total Goals</td>
		  <td id="team1goals"></td>
		</tr>
		<tr>
		  <td>Total Penalty</td>
		  <td id="team1penalty"></td>
		</tr>
		<tr>
		  <td>Yellow Cards</td>
		  <td id="team1yellow"></td>
		</tr>
		<tr>
		  <td>Red Cards</td>
		  <td id="team1red"></td>
		</tr>
	  </tbody>
	</table>
</div>

This is the score card for a single team. We need to make the same card for second team too. Here we have created a table with rows for total score, penalty, goals, red cards and yellow cards.

Goalkeeper’s Stats

<table style="background: white; width: 100%; margin-bottom: 10px;">
	<thead>
	  <tr>
		<th>Goalkeeper</th>
		<th>Block</th>
		<th>Miss</th>
	  </tr>
	</thead>
	<tbody>
	  <tr>
		<td id="team1player11name"></td>
		<td id="team1goalsblock"></td>
		<td id="team1goalsmiss"></td>
	  </tr>
	</tbody>
</table>

This table will render the fields for stats related to Goalkeeper like number of goals missed and blocked by them.

Individual Player’s Stats

<table style="background: white; width: 100%;">
	<thead>
	  <tr>
		<th>Player</th>
		<th>Goal</th>
		<th>Penalty</th>
		<th>
		  <span
			style="
			  height: 25px;
			  width: 15px;
			  background: yellow;
			  display: block;
			  box-shadow: 0 0 2px rgba(0, 0, 0, 0.5);
			"
		  ></span>
		</th>
		<th>
		  <span
			style="
			  height: 25px;
			  width: 15px;
			  background: red;
			  display: block;
			  box-shadow: 0 0 2px rgba(0, 0, 0, 0.5);
			"
		  ></span>
		</th>
	  </tr>
	</thead>
	<tbody>
	  <tr>
		<td id="team1player1name"></td>
		<td id="team1player1goal"></td>
		<td id="team1player1penalty"></td>
		<td id="team1player1yellow"></td>
		<td id="team1player1red"></td>
	  </tr>
	  ...  // Same code for 8 other players with appropriate id.
	  <tr>
		<td id="team1player10name"></td>
		<td id="team1player10goal"></td>
		<td id="team1player10penalty"></td>
		<td id="team1player10yellow"></td>
		<td id="team1player10red"></td>
	  </tr>
	</tbody>
</table>

There are total 5 parameters related to a player – Name of player, Goals, Penalties, Yellow Card and Red Card. To fill in the table fields, we are setting ids using this format –

team player parameter like team1player1name.

Filling and Updating Cards

Goalkeeper stats, player stats and team score table needs to be updated with each turn. There are 4 different outcomes –

  • Player hit a goal – 1 count will increase in the goal stat of the player and miss stat of opposite team’s goalkeeper.
  • Blocked – 1 count will increase in block stat of opposite team’s goalkeeper.
  • Yellow Card – 1 count in yellow card stat and 1 count in penalty stat will increase for the player.
  • Red Card – 1 count in red card stat and 2 counts in penalty stat will increase for the player.

And the total score of a team = (Total goals x 3) – total penalty.

To maintain all these numbers, I am going to define a javascript object, stats. The structure of this variable will be –

var stats = { 
   turn  : 1,
   team1 : {
              goalkeeper : {
                  block : 0,  // Count of goalkeeper blocks
                  miss  : 0,  // Count of goalkeeper miss
              },
              player1 : {
                  goal    : 0, // Total goals by player 1
                  penalty : 0, // Total penalty points
                  yellow  : 0, // Total yellow cards received by player1
                  red     : 0, // Total red cards received by player 1
              },
              ....  // For all 10 players
           },
   team2 : {
              ...   // Same as team1 
           },
};

Now we need a function which can fill these fields with fresh data and can be called after each turn. Let’s call this function fillStatTable().

function fillStatTable() {
	["team1", "team2"].forEach(function (team) {
	  var totGoals = 0;
	  var totPenalty = 0;
	  var totYellow = 0;
	  var totRed = 0;
	  Object.keys(stats[`${team}`]).forEach(function (player) {
		if (player !== "goalkeeper") {
		  document.getElementById(`${team}${player}goal`).innerText =
			stats[`${team}`][`${player}`].goal;
		  document.getElementById(`${team}${player}penalty`).innerText =
			stats[`${team}`][`${player}`].penalty;
		  document.getElementById(`${team}${player}yellow`).innerText =
			stats[`${team}`][`${player}`].yellow;
		  document.getElementById(`${team}${player}red`).innerText =
			stats[`${team}`][`${player}`].red;

		  totGoals += stats[`${team}`][`${player}`].goal;
		  totPenalty += stats[`${team}`][`${player}`].penalty;
		  totYellow += stats[`${team}`][`${player}`].yellow;
		  totRed += stats[`${team}`][`${player}`].red;
		}
	  });

	  document.getElementById(`${team}goals`).innerText = totGoals;
	  document.getElementById(`${team}penalty`).innerText = totPenalty;
	  document.getElementById(`${team}yellow`).innerText = totYellow;
	  document.getElementById(`${team}red`).innerText = totRed;

	  document.getElementById(`${team}score`).innerText =
		totGoals * 3 - totPenalty;

	  document.getElementById(`${team}goalsblock`).innerText =
		stats[`${team}`].goalkeeper.block;
	  document.getElementById(`${team}goalsmiss`).innerText =
		stats[`${team}`].goalkeeper.miss;
	});
}

Turn Box and Play Button of Football Crud game

This component has 4 roles –

  • Display whose turn it is.
  • Total turns in game as well as the current turn. Game ends when current turn exceeds total turns.
  • Play button.
  • Ready counter (3.. 2.. 1..)

Design code for this component is –

<div
  style="
	width: 200px;
	border-left: 1px solid #000;
	border-right: 1px solid #000;
	background: pink;
	flex-shrink: 0;
  "
>
  <span
	id="turnString"
	style="
	  text-align: center;
	  font-size: 20px;
	  display: block;
	  font-family: Helvetica;
	  font-weight: bold;
	  color: yellow;
	  text-shadow: 1px 1px 0px black, -1px 1px 0px black,
		1px -1px 0 black, -1px -1px 0px black;
	"
	>Your Turn</span
  >
  <div style="display: flex;">
	<div
	  style="
		width: 50px;
		text-align: center;
		font-size: 24px;
		line-height: 15px;
		font-weight: bold;
	  "
	>
	  <span id="totalTurnCounter"></span><br />----<br />6
	</div>
	<div style="flex-grow: 1;">
	  <span
		id="turnCounter"
		style="
		  font-size: 50px;
		  text-align: center;
		  font-family: Helvetica;
		  font-weight: bold;
		  color: #0d2534;
		  text-shadow: 0 0 3px white;
		  display: none;
		"
	  ></span>
	  <div id="playButton" style="text-align: center;">
		<button
		  style="
			font-size: 30px;
			font-family: Helvetica;
			font-weight: bold;
			box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
			background: green;
			color: white;
			cursor: pointer;
			border-radius: 8px;
		  "
		  onClick="playTurn()"
		>
		  Press !!!
		</button>
	  </div>
	</div>
  </div>
</div>

The play button will call the function playTurn() after getting pressed. This function holds the major portion of logic and we will implement it later.

Commentary Box

It’s a simple box where a title and comment will be shown. Here is the code for that –

<div style="flex-grow: 1; background: gainsboro; padding: 0 10px;">
    <span style="font-weight: bold;">Commentator: </span>
    <span id="commentaryText"></span>
</div>

Popup for turn outcome

When a user (or computer) plays their turn then they should know what happened. This popup will display that. Since our outcomes are 4 so we need 4 different images and message variants. But that we will see later. Right not, let’s create the popup structure.

<div
	id="outcomeBlock"
	style="
	  position: fixed;
	  z-index: 2;
	  top: 0;
	  left: 0;
	  width: 100%;
	  height: 100%;
	  background: rgba(0, 0, 0, 0.5);
	  text-align: center;
	"
>
	<img id="outcomeImage" src="" style="width: 500px; margin: auto;" />
	<h2
	  id="outcomeMessage"
	  style="color: #e5e5e5; background: black; padding: 20px;"
	></h2>
</div>

Popup for final result

The last component of our crud football game is the popup of final result. It will display the winner and by how many points they won.

<div
	id="resultBlock"
	style="
	  position: fixed;
	  z-index: 2;
	  top: 0;
	  left: 0;
	  width: 100%;
	  height: 100%;
	  background: rgba(0, 0, 0, 0.5);
	  text-align: center;
	"
  >
	<div
	  style="
		max-width: 400px;
		background: white;
		padding: 20px;
		border-radius: 8px;
		margin: auto;
	  "
	>
	  <h1
		id="resultHeading"
		style="text-align: center; font-family: Helvetica; color: red;"
	  ></h1>
	  <h3 id="resultOutcome"></h3>
	  <blockquote
		style="
		  background: #f0f0f0;
		  padding: 10px;
		  display: block;
		  font-style: italic;
		  font-size: 20px;
		"
	  >
		<b>Commentators Views:</b>
		<br /><br /><span id="resultCommentary"></span>
	  </blockquote>
	  <p>
		Later, commentator was found in garbage truck. We suspect,
		<span id="resultteam1name"></span> fans were behind it.
	  </p>
	  <div>
		<button onClick="window.location.reload()">Restart Game</button>
		<button onclick="resetTeams()">Reset Teams</button>
	  </div>
	  <h2 style="font-size: 30px;">Help by 1 Share Please !! <br />??</h2>
	  <a
		href="http://twitter.com/share?text=M[email protected][email protected][email protected]+%23football+%23Messi+%23Ronaldo+%23100DaysOfCode+%23javascript+%23reactjs+%23localstorage+%23programming+%23coding&url=https://akashmittal.com/football-crud-application-javascript-localstorage/"
		target="_blank"
	  >
		<img
		  style="width: 100%;"
		  src="https://findmymarathon.com/images/Twitter-Social-Share-Button.png"
		/>
	  </a>
	</div>
</div>

Connecting all components

We are expecting to render something like this –

Football game with score cards, commentary and play button

Let’s design the structure. I will write comments where we need to replace those with components.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Football Game</title>
  </head>
  <body>
    <script>
      if (!window.localStorage.getItem("teams")) window.location.href = "/";
    </script>
    <div style="max-width: 800px; margin: auto;">
	
      <!-- Buttons - Restart Game and Reset Teams -->
	  
      <!-- Popup for turn outcome. Make it display none. -->
	  
	  <!-- Popup for final result. Make it display none. -->
      
      <div style="display: flex; margin-bottom: 90px;">
        <div style="background: darkred; flex-grow: 1; padding: 10px;">
          
		  <!-- Team1 Score Card -->
		  
          <!-- Team1 Goalkeeper's Stats -->
		  
		  <!-- Team1 Individual Player's Stats -->
          
        </div>
		
        <div style="background: blue; flex-grow: 1; padding: 10px;">
          
          <!-- Team2 Score Card -->
		  
          <!-- Team2 Goalkeeper's Stats -->
		  
		  <!-- Team2 Individual Player's Stats -->
		  
        </div>
      </div>

      <div
        id="commentaryBox"
        style="
          position: fixed;
          bottom: 0;
          height: 80px;
          background: #aaa;
          width: 100%;
          left: 0;
          display: flex;
          border-top: 1px solid #000;
          box-shadow: 0 0px 10px rgba(0, 0, 0, 0.3);
        "
      >
        
		<!-- Extra feature - Share box -->
		
		<!-- Turn box with play button -->
        
        <!-- Commentary Box -->
		
      </div>
    </div>
	
	<script>
		// All functions and scripts goes here
	</script>
	
  </body>
</html>

Now you know where each component will fit. Just replace the comments, and html structure of our application will be ready. Here is the updated code –

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Football Game</title>
  </head>
  <body>
    <script>
      if (!window.localStorage.getItem("teams")) window.location.href = "/";
    </script>
    <div style="max-width: 800px; margin: auto;">
      <h1 style="text-align: center;">
        Football Game
        <button onClick="window.location.reload()">Restart Game</button>
        <button onclick="resetTeams()">Reset Teams</button>
      </h1>
      <div
        id="outcomeBlock"
        style="
          display: none;
          position: fixed;
          z-index: 2;
          top: 0;
          left: 0;
          width: 100%;
          height: 100%;
          background: rgba(0, 0, 0, 0.5);
          text-align: center;
        "
      >
        <img id="outcomeImage" src="" style="width: 500px; margin: auto;" />
        <h2
          id="outcomeMessage"
          style="color: #e5e5e5; background: black; padding: 20px;"
        ></h2>
      </div>
      <div
        id="resultBlock"
        style="
          display: none;
          position: fixed;
          z-index: 2;
          top: 0;
          left: 0;
          width: 100%;
          height: 100%;
          background: rgba(0, 0, 0, 0.5);
          text-align: center;
        "
      >
        <div
          style="
            max-width: 400px;
            background: white;
            padding: 20px;
            border-radius: 8px;
            margin: auto;
          "
        >
          <h1
            id="resultHeading"
            style="text-align: center; font-family: Helvetica; color: red;"
          ></h1>
          <h3 id="resultOutcome"></h3>
          <blockquote
            style="
              background: #f0f0f0;
              padding: 10px;
              display: block;
              font-style: italic;
              font-size: 20px;
            "
          >
            <b>Commentators Views:</b>
            <br /><br /><span id="resultCommentary"></span>
          </blockquote>
          <p>
            Later, commentator was found in garbage truck. We suspect,
            <span id="resultteam1name"></span> fans were behind it.
          </p>
          <div>
            <button onClick="window.location.reload()">Restart Game</button>
            <button onclick="resetTeams()">Reset Teams</button>
          </div>
          <h2 style="font-size: 30px;">Help by 1 Share Please !! <br />??</h2>
          <a
            href="http://twitter.com/share?text=M[email protected][email protected][email protected]+%23football+%23Messi+%23Ronaldo+%23100DaysOfCode+%23javascript+%23reactjs+%23localstorage+%23programming+%23coding&url=https://akashmittal.com/football-crud-application-javascript-localstorage/"
            target="_blank"
          >
            <img
              style="width: 100%;"
              src="https://findmymarathon.com/images/Twitter-Social-Share-Button.png"
            />
          </a>
        </div>
      </div>
      <div style="display: flex; margin-bottom: 90px;">
        <div style="background: darkred; flex-grow: 1; padding: 10px;">
          <h3 id="team1name" style="color: white;"></h3>
          <div style="background: black; margin-bottom: 20px;">
            <table style="width: 100%; color: white;">
              <thead>
                <tr style="font-size: 24px; font-weight: bold;">
                  <th style="text-align: center;">SCORE</th>
                  <th id="team1score"></th>
                </tr>
              </thead>
              <tbody>
                <tr>
                  <td>Total Goals</td>
                  <td id="team1goals"></td>
                </tr>
                <tr>
                  <td>Total Penalty</td>
                  <td id="team1penalty"></td>
                </tr>
                <tr>
                  <td>Yellow Cards</td>
                  <td id="team1yellow"></td>
                </tr>
                <tr>
                  <td>Red Cards</td>
                  <td id="team1red"></td>
                </tr>
              </tbody>
            </table>
          </div>
          <table style="background: white; width: 100%; margin-bottom: 10px;">
            <thead>
              <tr>
                <th>Goalkeeper</th>
                <th>Block</th>
                <th>Miss</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td id="team1player11name"></td>
                <td id="team1goalsblock"></td>
                <td id="team1goalsmiss"></td>
              </tr>
            </tbody>
          </table>
          <table style="background: white; width: 100%;">
            <thead>
              <tr>
                <th>Player</th>
                <th>Goal</th>
                <th>Penalty</th>
                <th>
                  <span
                    style="
                      height: 25px;
                      width: 15px;
                      background: yellow;
                      display: block;
                      box-shadow: 0 0 2px rgba(0, 0, 0, 0.5);
                    "
                  ></span>
                </th>
                <th>
                  <span
                    style="
                      height: 25px;
                      width: 15px;
                      background: red;
                      display: block;
                      box-shadow: 0 0 2px rgba(0, 0, 0, 0.5);
                    "
                  ></span>
                </th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td id="team1player1name"></td>
                <td id="team1player1goal"></td>
                <td id="team1player1penalty"></td>
                <td id="team1player1yellow"></td>
                <td id="team1player1red"></td>
              </tr>
              <tr>
                <td id="team1player2name"></td>
                <td id="team1player2goal"></td>
                <td id="team1player2penalty"></td>
                <td id="team1player2yellow"></td>
                <td id="team1player2red"></td>
              </tr>
              <tr>
                <td id="team1player3name"></td>
                <td id="team1player3goal"></td>
                <td id="team1player3penalty"></td>
                <td id="team1player3yellow"></td>
                <td id="team1player3red"></td>
              </tr>
              <tr>
                <td id="team1player4name"></td>
                <td id="team1player4goal"></td>
                <td id="team1player4penalty"></td>
                <td id="team1player4yellow"></td>
                <td id="team1player4red"></td>
              </tr>
              <tr>
                <td id="team1player5name"></td>
                <td id="team1player5goal"></td>
                <td id="team1player5penalty"></td>
                <td id="team1player5yellow"></td>
                <td id="team1player5red"></td>
              </tr>
              <tr>
                <td id="team1player6name"></td>
                <td id="team1player6goal"></td>
                <td id="team1player6penalty"></td>
                <td id="team1player6yellow"></td>
                <td id="team1player6red"></td>
              </tr>
              <tr>
                <td id="team1player7name"></td>
                <td id="team1player7goal"></td>
                <td id="team1player7penalty"></td>
                <td id="team1player7yellow"></td>
                <td id="team1player7red"></td>
              </tr>
              <tr>
                <td id="team1player8name"></td>
                <td id="team1player8goal"></td>
                <td id="team1player8penalty"></td>
                <td id="team1player8yellow"></td>
                <td id="team1player8red"></td>
              </tr>
              <tr>
                <td id="team1player9name"></td>
                <td id="team1player9goal"></td>
                <td id="team1player9penalty"></td>
                <td id="team1player9yellow"></td>
                <td id="team1player9red"></td>
              </tr>
              <tr>
                <td id="team1player10name"></td>
                <td id="team1player10goal"></td>
                <td id="team1player10penalty"></td>
                <td id="team1player10yellow"></td>
                <td id="team1player10red"></td>
              </tr>
            </tbody>
          </table>
        </div>
        <div style="background: blue; flex-grow: 1; padding: 10px;">
          <h3 id="team2name" style="color: white;"></h3>
          <div style="background: black; margin-bottom: 20px;">
            <table style="width: 100%; color: white;">
              <thead>
                <tr style="font-size: 24px; font-weight: bold;">
                  <th style="text-align: center;">SCORE</th>
                  <th id="team2score"></th>
                </tr>
              </thead>
              <tbody>
                <tr>
                  <td>Total Goals</td>
                  <td id="team2goals"></td>
                </tr>
                <tr>
                  <td>Total Penalty</td>
                  <td id="team2penalty"></td>
                </tr>
                <tr>
                  <td>Yellow Cards</td>
                  <td id="team2yellow"></td>
                </tr>
                <tr>
                  <td>Red Cards</td>
                  <td id="team2red"></td>
                </tr>
              </tbody>
            </table>
          </div>
          <table style="background: white; width: 100%; margin-bottom: 10px;">
            <thead>
              <tr>
                <th>Goalkeeper</th>
                <th>Block</th>
                <th>Miss</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td id="team2player11name"></td>
                <td id="team2goalsblock"></td>
                <td id="team2goalsmiss"></td>
              </tr>
            </tbody>
          </table>
          <table style="background: white; width: 100%;">
            <thead>
              <tr>
                <th>Player</th>
                <th>Goal</th>
                <th>Penalty</th>
                <th>
                  <span
                    style="
                      height: 25px;
                      width: 15px;
                      background: yellow;
                      display: block;
                      box-shadow: 0 0 2px rgba(0, 0, 0, 0.5);
                    "
                  ></span>
                </th>
                <th>
                  <span
                    style="
                      height: 25px;
                      width: 15px;
                      background: red;
                      display: block;
                      box-shadow: 0 0 2px rgba(0, 0, 0, 0.5);
                    "
                  ></span>
                </th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td id="team2player1name"></td>
                <td id="team2player1goal"></td>
                <td id="team2player1penalty"></td>
                <td id="team2player1yellow"></td>
                <td id="team2player1red"></td>
              </tr>
              <tr>
                <td id="team2player2name"></td>
                <td id="team2player2goal"></td>
                <td id="team2player2penalty"></td>
                <td id="team2player2yellow"></td>
                <td id="team2player2red"></td>
              </tr>
              <tr>
                <td id="team2player3name"></td>
                <td id="team2player3goal"></td>
                <td id="team2player3penalty"></td>
                <td id="team2player3yellow"></td>
                <td id="team2player3red"></td>
              </tr>
              <tr>
                <td id="team2player4name"></td>
                <td id="team2player4goal"></td>
                <td id="team2player4penalty"></td>
                <td id="team2player4yellow"></td>
                <td id="team2player4red"></td>
              </tr>
              <tr>
                <td id="team2player5name"></td>
                <td id="team2player5goal"></td>
                <td id="team2player5penalty"></td>
                <td id="team2player5yellow"></td>
                <td id="team2player5red"></td>
              </tr>
              <tr>
                <td id="team2player6name"></td>
                <td id="team2player6goal"></td>
                <td id="team2player6penalty"></td>
                <td id="team2player6yellow"></td>
                <td id="team2player6red"></td>
              </tr>
              <tr>
                <td id="team2player7name"></td>
                <td id="team2player7goal"></td>
                <td id="team2player7penalty"></td>
                <td id="team2player7yellow"></td>
                <td id="team2player7red"></td>
              </tr>
              <tr>
                <td id="team2player8name"></td>
                <td id="team2player8goal"></td>
                <td id="team2player8penalty"></td>
                <td id="team2player8yellow"></td>
                <td id="team2player8red"></td>
              </tr>
              <tr>
                <td id="team2player9name"></td>
                <td id="team2player9goal"></td>
                <td id="team2player9penalty"></td>
                <td id="team2player9yellow"></td>
                <td id="team2player9red"></td>
              </tr>
              <tr>
                <td id="team2player10name"></td>
                <td id="team2player10goal"></td>
                <td id="team2player10penalty"></td>
                <td id="team2player10yellow"></td>
                <td id="team2player10red"></td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>

      <div
        id="commentaryBox"
        style="
          position: fixed;
          bottom: 0;
          height: 80px;
          background: #aaa;
          width: 100%;
          left: 0;
          display: flex;
          border-top: 1px solid #000;
          box-shadow: 0 0px 10px rgba(0, 0, 0, 0.3);
        "
      >
        <div style="width: 100px; background: cyan; flex-shrink: 0;">
          <span style="text-align: center; display: block; font-weight: bold;"
            >Help Us! ?</span
          >
          <div>
            <a
              href="http://twitter.com/share?text=M[email protected][email protected][email protected]+%23football+%23Messi+%23Ronaldo+%23100DaysOfCode+%23javascript+%23reactjs+%23localstorage+%23programming+%23coding&url=https://akashmittal.com/football-crud-application-javascript-localstorage/"
              target="_blank"
            >
              <img
                style="width: 100%; margin-top: 10px;"
                src="https://www.nextgenerationchiropractor.com/wp-content/uploads/2010/08/TweetButton-300x128.png"
              />
            </a>
          </div>
        </div>
        <div
          style="
            width: 200px;
            border-left: 1px solid #000;
            border-right: 1px solid #000;
            background: pink;
            flex-shrink: 0;
          "
        >
          <span
            id="turnString"
            style="
              text-align: center;
              font-size: 20px;
              display: block;
              font-family: Helvetica;
              font-weight: bold;
              color: yellow;
              text-shadow: 1px 1px 0px black, -1px 1px 0px black,
                1px -1px 0 black, -1px -1px 0px black;
            "
            >Your Turn</span
          >
          <div style="display: flex;">
            <div
              style="
                width: 50px;
                text-align: center;
                font-size: 24px;
                line-height: 15px;
                font-weight: bold;
              "
            >
              <span id="totalTurnCounter"></span><br />----<br />6
            </div>
            <div style="flex-grow: 1;">
              <span
                id="turnCounter"
                style="
                  font-size: 50px;
                  text-align: center;
                  font-family: Helvetica;
                  font-weight: bold;
                  color: #0d2534;
                  text-shadow: 0 0 3px white;
                  display: none;
                "
              ></span>
              <div id="playButton" style="text-align: center;">
                <button
                  style="
                    font-size: 30px;
                    font-family: Helvetica;
                    font-weight: bold;
                    box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
                    background: green;
                    color: white;
                    cursor: pointer;
                    border-radius: 8px;
                  "
                  onClick="playTurn()"
                >
                  Press !!!
                </button>
              </div>
            </div>
          </div>
        </div>
        <div style="flex-grow: 1; background: gainsboro; padding: 0 10px;">
          <span style="font-weight: bold;">Commentator: </span>
          <span id="commentaryText"></span>
        </div>
      </div>
    </div>

    <script>
      // All scripts will come here
    </script>
  </body>
</html>

Building logic

This is the final and the most important part of the application. Building logic is difficult but if we know the steps then it will be a piece of cake.

So, logic of the game will be –

  1. After page load finished (init()) –
    • Display both team names on their score tables.
    • Fill stats object with default values i.e. all zeroes.
    • Display player names in tables.
    • Display turn counter to be 1.
    • Create an object with commentary texts for all 4 outcomes, wins, ties and game start. Display game start commentary in the box.
    • Run fillStatTable() function.
  2. When Play button is pressed (playTurn()) –
    • Hide the play button.
    • Create random variable to decide outcome. Probabilities are –
      • 5% for getting red card.
      • 5% for getting yellow card.
      • 35% for a goal.
      • 55% for a block.
    • According to outcome, select commentary.
    • Set appropriate image url and message for turn popup and display it.
    • Close popup after 5 seconds.
    • After closing popup –
      • Add commentary to the commentary box. Wait for it to finish.
      • Update the stats object according to the outcome and call fillStatTable().
      • Toggle turn string from “Your Turn” to “Computer’s Turn” or vice versa.
      • Run turn counter (3… 2… 1…) with delay of 1.2 seconds.
      • When counter is 0, hide it.
      • Increase turn by 1 and display it.
      • Check if played turns exceeds maximum turns. If yes, then calculate scores for both teams; decide winner and display final popup.
      • Otherwise, check if its computer’s turn. If it is then call play button but for team 2.
      • If it’s user’s turn then unhide play button.

After page load finished (init())

init() function will be immediately called after page load. The structure will look like this –

// global objects and variables

function init() {

	// display team names

	// default stats object

	// display player names

	// display game start commentary

	// setting turn counter to 1

	fillStatTable();
}
init();

Let’s create all these code snippets and complete our init() function.

Global objects and variables
var stats = { turn: 1 };
var teams = JSON.parse(window.localStorage.getItem("teams"));
var commentaries = {
	goal: {
	  team1: [
		"Oh comeon {team2goalkeeper}, this should not be missed.",
		....  // other commentaries for goals of team 1
	  ],
	  team2: [
		"GOALLLLLL!!!!! More points for mighty {team2}",
		....  // other commentaries for goals of team 2
	  ]
	},
	block: {
	  team1: [
		"What a wonderful block. {team1} should learn from {team2}",
		....  // other commentaries for blocks of team 1
	  ],
	  team2: [
		"ohhh!! Just...",
		....  // other commentaries for blocks of team 2
	  ]
	},
	yellow: {
	  team1: [
		"I Love It.",
		....  // commentaries for team 1 player receiving yellow card
	  ],
	  team2: [
		"I am very angry with this behavior.",
		....  // commentaries for team 2 player receiving yellow card
	  ]
	},
	red: {
	  team1: [
		"Ha Ha Ha.. How'z that, {team1}?",
		....  // commentaries for team 1 player receiving red card
	  ],
	  team2: [
		"Hey! Hey! Hey! How is this a red card penalty?",
		....  // commentaries for team 2 player receiving red card
	  ]
	},
	gamestart: [
	  "Greetings!!! It's a sunny day. We are having a game between {team1} and {team2}. Hope better team ({team2}) win.",
	  ....  // commentaries for game start
	],
	win: {
	  team1: [
		"This whole game was biased. Actual winner is {team2}",
		....  // commentaries when team 1 wins
	  ],
	  team2: [
		"Yes! Yes! YESSSS! {team2} Won!!",
		....  // commentaries when team 2 wins
	  ],
	  tie: [
		"Let {team2} hit one more time and you will see who is the winner. This tie is BS."
	  ]
	}
  };

teams object will contain details of teams and their players. We set these values in index.html. (Check)

We have included some keys in commentary text like {team1goalkeeper}, {team2goalkeeper}, {team1}, {team2}, {team1player}, and {team2player}. The purpose is to replace these keys with the names of players and teams so that commentary will become interactive.

Display Team Names
document.getElementById("team1name").innerText =
  teams.team1.name + " (Your Team)";
document.getElementById("team2name").innerText =
  teams.team2.name + " (Computer's Team)";
Default stats object
["team1", "team2"].forEach(function (team) {
  stats[`${team}`] = {};
  for (var i = 1; i <= 10; i++) {
	stats[`${team}`]["player" + i] = {
	  goal: 0,
	  penalty: 0,
	  yellow: 0,
	  red: 0
	};
  }
  stats[`${team}`]["goalkeeper"] = {
	block: 0,
	miss: 0
  };
});
Display player names
Object.keys(teams).forEach(function (team) {
  Object.keys(teams[team].players).forEach(function (player) {
	document.getElementById(`${team}${player}name`).innerText =
	  teams[team].players[player];
  });
});

teams object structure is this.

Setting turn counter to 1
document.getElementById("totalTurnCounter").innerHTML = stats.turn;
Display game start commentary
document.getElementById(
  "commentaryText"
).innerText = commentaries.gamestart[
  Math.floor(Math.random() * commentaries.gamestart.length)
]
  .replace(/{team1}/gi, teams.team1.name)
  .replace(/{team2}/gi, teams.team2.name);
Finishing init()

Let’s combine all the above code snippets and finish our function.

var stats = { turn: 1 };
var teams = JSON.parse(window.localStorage.getItem("teams"));
var commentaries = {
	goal: {
	  team1: [
		"Oh comeon {team2goalkeeper}, this should not be missed.",
		"It was not a goal. This was a foul. Ref. pay attention.",
		"Damn it.",
		"Man! What's going on? {team2goalkeeper}... seriously?",
		"{team1} is on fire. But they will never win.",
		"Yeah Yeah.. Enjoy",
		"This was a perfect goal... for a kid.",
		"oops!! {team2goalkeeper} slipped. Ref should declare this goal invalid.",
		"I am not happy. This way {team2} could lose.",
		"Sometimes the wall like {team2goalkeeper} got penetrated too. But don't be too happy."
	  ],
	  team2: [
		"GOALLLLLL!!!!! More points for mighty {team2}",
		"Did you see anything more beautiful than this goal?",
		"{team2}, you deserve this goal.",
		"{team1}, only magic can save you from the wrath of {team2}",
		"{team1goalkeeper} can only block a goal of {team2player} in DREAMS..",
		"This goal increased my life by 5 years.",
		"When there is {team2} on grounds, you can expect goals all around.",
		"Ref.. please grant {team2player} 10 more points for such a wonderful goal.",
		"{team1}, you should be proud to lose with {team2}",
		"No one can stop the bullet. This goal was one of it."
	  ]
	},
	block: {
	  team1: [
		"What a wonderful block. {team1} should learn from {team2}",
		"Hey ref. look... {team2player} should be awarded 10 points for such fantastic block.",
		"Go go go {team2}. Don't let {team1} goal.",
		"You have to admit {team1}, you need a player like {team2player}",
		"Believe That!!!",
		"Beautiful block. Muahh {team2player}",
		"Oooh it was tough block. Only player like {team2player} could block it.",
		"Every team needs players like {team2player}",
		"{team1player}, its not easy to penetrate the wall of {team2player}",
		"Better luck next time, {team1player}"
	  ],
	  team2: [
		"ohhh!! Just...",
		"What are you doing, {team2player}? Don't let {team1player} block it.",
		"I have nothing to say.",
		"Comeon {team2player}!!!",
		"I should appreciate this block.",
		"It doesn't seems right. How can {team1player} block {team2player}?",
		"Get out of the way {team1player}.",
		"{team2player}, you need to make your way. It's easy. {team1} can't block you.",
		"Hey!! Make way {team1player}. Won't complaint if {team2player} hit you.",
		"Not a fine block but it worked."
	  ]
	},
	yellow: {
	  team1: [
		"I Love It.",
		"There is a saying, 'Yellow yellow dirty fellow'",
		"{team1player}, you should pay attention on your game and not hitting {team2player}",
		"Justice is served.",
		"Yeah {team1}, Yellow is your favorite color.",
		"Your deserve this, {team1player}.",
		"Don't worry {team1player}. I wish you all the best in next hit.",
		"Once more {team1player}. Once more please.",
		"Ref. you are awesome. Now you are doing the right thing.",
		"So sorry {team1player}, (for my happiness)"
	  ],
	  team2: [
		"I am very angry with this behavior.",
		"{team2player} did nothing wrong yet got the card.",
		"Card!!!! For what? Ref. you need to explain.",
		"I am definitely not liking it.",
		"Oh man! {team2player}, what have you done?",
		"No problem. Just a yellow card.",
		"This is the height. Ref should take a break from game. Never ending.",
		"Can you believe it? Can you? CAN YOUUU?",
		"{team2}, I know what's going on with you guys. But keep playing your best.",
		"Take care {team2}. Ref has decided to turn your win into loss by giving you these cards."
	  ]
	},
	red: {
	  team1: [
		"Ha Ha Ha.. How'z that, {team1}?",
		"Good job ref. Finally you did something right.",
		"I can not hold my laughter anymore. Heehaa.",
		"Hey!! stop injuring players of {team2}. Win with decency if you can.",
		"No no! not only red card. Throw {team1player} out of this game permanently.",
		"This is awesome.",
		"Good job {team1}. May you get all the red cards. He he.",
		"I am sad for you {team1}. *Giggle*",
		"Now you will understand the value of fair play.",
		"Ladies and Gentlemen, bottoms up."
	  ],
	  team2: [
		"Hey! Hey! Hey! How is this a red card penalty?",
		"OH MY GOD! Seriously! Red Card?",
		"Ref. you are disgusting.",
		"I can smell conspiracy. {team1}, you can not win by cheating.",
		"How much did you get in bribe, Ref.?",
		"Everybody knows, what is going on in here. Board does not want {team2} to win.",
		"Ref. use your eyes. {team1player} came in the path of {team2player} intentionally.",
		"Yeah why not! Give away all your red cards to {team2}. People will remember this corruption day.",
		"@#%$^# you ref. @&&#@ @^$&#^$",
		"I will resign if any more cheating happen with {team2}. I will protest. I will send ref to jail."
	  ]
	},
	gamestart: [
	  "Greetings!!! It's a sunny day. We are having a game between {team1} and {team2}. Hope better team ({team2}) win.",
	  "Yuhuuu! Welcome all. Today we will witness the war between {team1} and {team2}. It's going to be bloody.",
	  "Welcome! Quite a gathering. People are here to see {team2} and their victim {team1}."
	],
	win: {
	  team1: [
		"This whole game was biased. Actual winner is {team2}",
		"I am leaving commentary. My favorite team lost.",
		"Yeah! You won. Cheaters.",
		"This is unacceptable. UEFA should discard this result."
	  ],
	  team2: [
		"Yes! Yes! YESSSS! {team2} Won!!",
		"Drinks on me. It's a happy happy day.",
		"And that's how you win the game.",
		"Cry {team1} but actually you had no chance against {team2}."
	  ],
	  tie: [
		"Let {team2} hit one more time and you will see who is the winner. This tie is BS."
	  ]
	}
};


function init() {
	document.getElementById("team1name").innerText =
	  teams.team1.name + " (Your Team)";
	document.getElementById("team2name").innerText =
	  teams.team2.name + " (Computer's Team)";

	["team1", "team2"].forEach(function (team) {
	  stats[`${team}`] = {};
	  for (var i = 1; i <= 10; i++) {
		stats[`${team}`]["player" + i] = {
		  goal: 0,
		  penalty: 0,
		  yellow: 0,
		  red: 0
		};
	  }
	  stats[`${team}`]["goalkeeper"] = {
		block: 0,
		miss: 0
	  };
	});

	Object.keys(teams).forEach(function (team) {
	  Object.keys(teams[team].players).forEach(function (player) {
		document.getElementById(`${team}${player}name`).innerText =
		  teams[team].players[player];
	  });
	});

	document.getElementById(
	  "commentaryText"
	).innerText = commentaries.gamestart[
	  Math.floor(Math.random() * commentaries.gamestart.length)
	]
	  .replace(/{team1}/gi, teams.team1.name)
	  .replace(/{team2}/gi, teams.team2.name);

	document.getElementById("totalTurnCounter").innerHTML = stats.turn;

	fillStatTable();
}
init();

Now let’s design the play button.

Play button code structure (playTurn())

We already defined the steps in play button. Here is the structure –

function playTurn(){
	// Hide play button
	// Create random variable to decide outcome
	// Select commentary based on outcome
	// Display turn outcome popup
	
	setTimeout(function () {
		
		// Close turn outcome popup
		// Add commentary to commentary box
		// Update stats object and call fillStatTable()
		// Toggle turn string 

		
var turnCounterEle = document.getElementById("turnCounter");
		var cou = 3;  // counter variable to start from 3.
		function turnCounter() {
			if(cou > 0){
			
				// Run turn counter with delay of 1.2 seconds
				
			} else {
			
				// Hide turn counter
				// Increase turn by 1 in stat object and display
				
				if (stats.turn > 6) {	// check if current turn is more than maximum game turns.
				
					// Calculate scores for both teams and display final popup
				
				} else {
					
					// if computer's turn then call playTurn()
					
					// else display play button
				
				}
				
			
			}
		
		}
		
	}, 5000); // Run function after 5 seconds
}

Now we will create code snippets for each step of playTurn() and combine them in the end.

Hide play button
document.getElementById("playButton").style.display = "none";
Create random variable to decide outcome
var randomVal = Math.random();
var outcome; // goal, block, yellow, red
if (randomVal < 0.05) {
  outcome = "red";
} else if (randomVal < 0.1) {
  outcome = "yellow";
} else if (randomVal < 0.45) {
  outcome = "goal";
} else {
  outcome = "block";
}
Select commentary based on outcome
var commentaryArr =
  commentaries[`${outcome}`][stats.turn % 2 === 1 ? "team1" : "team2"];
var commentIndex = Math.floor(Math.random() * commentaryArr.length);
var comment = commentaryArr[commentIndex];
commentaryArr.splice(commentIndex, 1);

var team1playerIndex = Math.floor(Math.random() * 10) + 1;
var team2playerIndex = Math.floor(Math.random() * 10) + 1;

var team1playername = teams.team1.players["player" + team1playerIndex];
var team2playername = teams.team2.players["player" + team2playerIndex];
var team1goalkeeper = teams.team1.players["player11"];
var team2goalkeeper = teams.team2.players["player11"];

comment = comment
  .replace(/{team1player}/gi, team1playername)
  .replace(/{team2player}/gi, team2playername)
  .replace(/{team1goalkeeper}/gi, team1goalkeeper)
  .replace(/{team2goalkeeper}/gi, team2goalkeeper)
  .replace(/{team1}/gi, teams.team1.name)
  .replace(/{team2}/gi, teams.team2.name);
Display turn outcome popup
var imgurl = "";
var outcomeMessage = "";

if (outcome === "goal") {
  imgurl =
	"https://www.incimages.com/uploaded_files/image/1920x1080/goal-soccer_36915.jpg";
  outcomeMessage =
	'<span style="font-size: 35px; color: white;">' +
	(stats.turn % 2 === 1 ? team1playername : team2playername) +
	'</span> hit the ball and <span style="font-size: 35px; color: white;">' +
	(stats.turn % 2 === 1 ? team2goalkeeper : team1goalkeeper) +
	'</span> could not block it. It\'s a GOAL. <br /><br />+3 points for <span style="font-size: 35px; color: white;">' +
	(stats.turn % 2 === 1 ? teams.team1.name : teams.team2.name) +
	"</span>.";
} else if (outcome === "block") {
  imgurl = "https://www.ussportscamps.com/media/images/goalie-save.jpg";
  outcomeMessage =
	'<span style="font-size: 35px; color: white;">' +
	(stats.turn % 2 === 1 ? team1playername : team2playername) +
	'</span> hit the ball but <span style="font-size: 35px; color: white;">' +
	(stats.turn % 2 === 1 ? team2playername : team1playername) +
	'</span> blocked it. <br /><br />No points for <span style="font-size: 35px; color: white;">' +
	(stats.turn % 2 === 1 ? teams.team1.name : teams.team2.name) +
	"</span>.";
} else if (outcome === "red") {
  imgurl =
	"https://worldsoccertalk.com/wp-content/uploads/2017/10/343c701fce7775e37eb140ae9acac36ba78e07bd.jpg";
  outcomeMessage =
	'<span style="font-size: 35px; color: white;">' +
	(stats.turn % 2 === 1 ? team1playername : team2playername) +
	'</span> hit <span style="font-size: 35px; color: white;">' +
	(stats.turn % 2 === 1 ? team2playername : team1playername) +
	'</span> badly. Red card. <br /><br />-2 points for <span style="font-size: 35px; color: white;">' +
	(stats.turn % 2 === 1 ? teams.team1.name : teams.team2.name) +
	"</span>.";
} else if (outcome === "yellow") {
  imgurl =
	"https://soccerlifestyle.com/wp-content/uploads/2019/05/What-Does-A-Yellow-Card-Mean-in-Soccer-soccerlifestyle.jpeg";
  outcomeMessage =
	'<span style="font-size: 35px; color: white;">' +
	(stats.turn % 2 === 1 ? team1playername : team2playername) +
	'</span> pushed <span style="font-size: 35px; color: white;">' +
	(stats.turn % 2 === 1 ? team2playername : team1playername) +
	'</span> while blocking. Yellow card. <br /><br />-1 points for <span style="font-size: 35px; color: white;">' +
	(stats.turn % 2 === 1 ? teams.team1.name : teams.team2.name) +
	"</span>.";
}
document.getElementById("outcomeImage").src = imgurl;
document.getElementById("outcomeMessage").innerHTML = outcomeMessage;
document.getElementById("outcomeBlock").style.display = "block";
Close turn outcome popup
document.getElementById("outcomeBlock").style.display = "none";
Add commentary to commentary box
var ct = 0;
var commentTextElement = document.getElementById("commentaryText");
commentTextElement.innerHTML = "";
function typeWriter() {
	if (ct < comment.length) {
	  commentTextElement.innerHTML += comment.charAt(ct);
	  ct++;
	  setTimeout(typeWriter, 50);
	} else {
	  turnCounterEle.style.display = "block";
	  turnCounter();
	}
}
typeWriter();
Update stats object and call fillStatTable()
if (outcome === "goal") {
	stats[stats.turn % 2 === 1 ? "team1" : "team2"][
	  "player" +
		(stats.turn % 2 === 1 ? team1playerIndex : team2playerIndex)
	].goal += 1;
	stats[
	  stats.turn % 2 === 1 ? "team2" : "team1"
	].goalkeeper.miss += 1;
} else if (outcome === "block") {
	stats[
	  stats.turn % 2 === 1 ? "team2" : "team1"
	].goalkeeper.block += 1;
} else if (outcome === "yellow") {
	stats[stats.turn % 2 === 1 ? "team1" : "team2"][
	  "player" +
		(stats.turn % 2 === 1 ? team1playerIndex : team2playerIndex)
	].yellow += 1;
	stats[stats.turn % 2 === 1 ? "team1" : "team2"][
	  "player" +
		(stats.turn % 2 === 1 ? team1playerIndex : team2playerIndex)
	].penalty += 1;
} else if (outcome === "red") {
	stats[stats.turn % 2 === 1 ? "team1" : "team2"][
	  "player" +
		(stats.turn % 2 === 1 ? team1playerIndex : team2playerIndex)
	].red += 1;
	stats[stats.turn % 2 === 1 ? "team1" : "team2"][
	  "player" +
		(stats.turn % 2 === 1 ? team1playerIndex : team2playerIndex)
	].penalty += 2;
}

fillStatTable();
Toggle turn string
if (stats.turn % 2 === 1) {
	document.getElementById("turnString").innerText = "Computer's Turn";
} else {
	document.getElementById("turnString").innerText = "Your Turn";
}
Run turn counter with delay of 1.2 seconds
turnCounterEle.innerText = cou;
cou--;
setTimeout(turnCounter, 1200);
Hide turn counter
turnCounterEle.style.display = "none";
Increase turn by 1 in stat object and display
stats.turn += 1;
document.getElementById("totalTurnCounter").innerHTML =
	stats.turn;
Calculate scores for both teams and display final popup
var scoreTeam1 = 0;
var scoreTeam2 = 0;
["team1", "team2"].forEach(function (team) {
  var totGoals = 0;
  var totPenalty = 0;

  Object.keys(stats[`${team}`]).forEach(function (player) {
	if (player !== "goalkeeper") {
	  totGoals += stats[`${team}`][`${player}`].goal;
	  totPenalty += stats[`${team}`][`${player}`].penalty;
	}
  });

  if (team === "team1") scoreTeam1 = totGoals * 3 - totPenalty;
  else scoreTeam2 = totGoals * 3 - totPenalty;
});
document.getElementById("resultHeading").innerText =
  scoreTeam1 > scoreTeam2
	? "You Won!!!"
	: scoreTeam1 < scoreTeam2
	? "Computer Won!!!"
	: "It's A Tie!!!";
document.getElementById("resultOutcome").innerHTML =
  scoreTeam1 === scoreTeam2
	? '<span style="color: darkred">' +
	  teams.team1.name +
	  '</span> Ties with <span style="color: blue">' +
	  teams.team2.name +
	  "</span>"
	: (scoreTeam1 > scoreTeam2
		? '<span style="color: darkred">' +
		  teams.team1.name +
		  "</span>"
		: '<span style="color: blue">' +
		  teams.team2.name +
		  "</span>") +
	  " beats " +
	  (scoreTeam1 > scoreTeam2
		? '<span style="color: blue">' +
		  teams.team2.name +
		  "</span>"
		: '<span style="color: darkred">' +
		  teams.team1.name +
		  "</span>") +
	  " by " +
	  Math.abs(scoreTeam1 - scoreTeam2) +
	  " Points.";
document.getElementById(
  "resultCommentary"
).innerText = commentaries.win[
  scoreTeam1 === scoreTeam2
	? "tie"
	: scoreTeam1 > scoreTeam2
	? "team1"
	: "team2"
][
  Math.floor(
	Math.random() *
	  commentaries.win[
		scoreTeam1 === scoreTeam2
		  ? "tie"
		  : scoreTeam1 > scoreTeam2
		  ? "team1"
		  : "team2"
	  ].length
  )
]
  .replace(/{team1}/gi, teams.team1.name)
  .replace(/{team2}/gi, teams.team2.name);
document.getElementById("resultteam1name").innerText =
  teams.team1.name;

document.getElementById("resultBlock").style.display = "block";

Now let’s combine all these code snippets and complete our playTurn() function.

function playTurn() {
	document.getElementById("playButton").style.display = "none";
	var randomVal = Math.random();
	var outcome; // goal, block, yellow, red
	if (randomVal < 0.05) {
	  outcome = "red";
	} else if (randomVal < 0.1) {
	  outcome = "yellow";
	} else if (randomVal < 0.45) {
	  outcome = "goal";
	} else {
	  outcome = "block";
	}

	var commentaryArr =
	  commentaries[`${outcome}`][stats.turn % 2 === 1 ? "team1" : "team2"];
	var commentIndex = Math.floor(Math.random() * commentaryArr.length);
	var comment = commentaryArr[commentIndex];
	commentaryArr.splice(commentIndex, 1);

	var team1playerIndex = Math.floor(Math.random() * 10) + 1;
	var team2playerIndex = Math.floor(Math.random() * 10) + 1;

	var team1playername = teams.team1.players["player" + team1playerIndex];
	var team2playername = teams.team2.players["player" + team2playerIndex];
	var team1goalkeeper = teams.team1.players["player11"];
	var team2goalkeeper = teams.team2.players["player11"];

	comment = comment
	  .replace(/{team1player}/gi, team1playername)
	  .replace(/{team2player}/gi, team2playername)
	  .replace(/{team1goalkeeper}/gi, team1goalkeeper)
	  .replace(/{team2goalkeeper}/gi, team2goalkeeper)
	  .replace(/{team1}/gi, teams.team1.name)
	  .replace(/{team2}/gi, teams.team2.name);

	var imgurl = "";
	var outcomeMessage = "";

	if (outcome === "goal") {
	  imgurl =
		"https://www.incimages.com/uploaded_files/image/1920x1080/goal-soccer_36915.jpg";
	  outcomeMessage =
		'<span style="font-size: 35px; color: white;">' +
		(stats.turn % 2 === 1 ? team1playername : team2playername) +
		'</span> hit the ball and <span style="font-size: 35px; color: white;">' +
		(stats.turn % 2 === 1 ? team2goalkeeper : team1goalkeeper) +
		'</span> could not block it. It\'s a GOAL. <br /><br />+3 points for <span style="font-size: 35px; color: white;">' +
		(stats.turn % 2 === 1 ? teams.team1.name : teams.team2.name) +
		"</span>.";
	} else if (outcome === "block") {
	  imgurl = "https://www.ussportscamps.com/media/images/goalie-save.jpg";
	  outcomeMessage =
		'<span style="font-size: 35px; color: white;">' +
		(stats.turn % 2 === 1 ? team1playername : team2playername) +
		'</span> hit the ball but <span style="font-size: 35px; color: white;">' +
		(stats.turn % 2 === 1 ? team2playername : team1playername) +
		'</span> blocked it. <br /><br />No points for <span style="font-size: 35px; color: white;">' +
		(stats.turn % 2 === 1 ? teams.team1.name : teams.team2.name) +
		"</span>.";
	} else if (outcome === "red") {
	  imgurl =
		"https://worldsoccertalk.com/wp-content/uploads/2017/10/343c701fce7775e37eb140ae9acac36ba78e07bd.jpg";
	  outcomeMessage =
		'<span style="font-size: 35px; color: white;">' +
		(stats.turn % 2 === 1 ? team1playername : team2playername) +
		'</span> hit <span style="font-size: 35px; color: white;">' +
		(stats.turn % 2 === 1 ? team2playername : team1playername) +
		'</span> badly. Red card. <br /><br />-2 points for <span style="font-size: 35px; color: white;">' +
		(stats.turn % 2 === 1 ? teams.team1.name : teams.team2.name) +
		"</span>.";
	} else if (outcome === "yellow") {
	  imgurl =
		"https://soccerlifestyle.com/wp-content/uploads/2019/05/What-Does-A-Yellow-Card-Mean-in-Soccer-soccerlifestyle.jpeg";
	  outcomeMessage =
		'<span style="font-size: 35px; color: white;">' +
		(stats.turn % 2 === 1 ? team1playername : team2playername) +
		'</span> pushed <span style="font-size: 35px; color: white;">' +
		(stats.turn % 2 === 1 ? team2playername : team1playername) +
		'</span> while blocking. Yellow card. <br /><br />-1 points for <span style="font-size: 35px; color: white;">' +
		(stats.turn % 2 === 1 ? teams.team1.name : teams.team2.name) +
		"</span>.";
	}
	document.getElementById("outcomeImage").src = imgurl;
	document.getElementById("outcomeMessage").innerHTML = outcomeMessage;
	document.getElementById("outcomeBlock").style.display = "block";

	setTimeout(function () {
	  document.getElementById("outcomeBlock").style.display = "none";

	  var ct = 0;
	  var commentTextElement = document.getElementById("commentaryText");
	  commentTextElement.innerHTML = "";
	  function typeWriter() {
		if (ct < comment.length) {
		  commentTextElement.innerHTML += comment.charAt(ct);
		  ct++;
		  setTimeout(typeWriter, 50);
		} else {
		  turnCounterEle.style.display = "block";
		  turnCounter();
		}
	  }
	  typeWriter();

	  if (outcome === "goal") {
		stats[stats.turn % 2 === 1 ? "team1" : "team2"][
		  "player" +
			(stats.turn % 2 === 1 ? team1playerIndex : team2playerIndex)
		].goal += 1;
		stats[
		  stats.turn % 2 === 1 ? "team2" : "team1"
		].goalkeeper.miss += 1;
	  } else if (outcome === "block") {
		stats[
		  stats.turn % 2 === 1 ? "team2" : "team1"
		].goalkeeper.block += 1;
	  } else if (outcome === "yellow") {
		stats[stats.turn % 2 === 1 ? "team1" : "team2"][
		  "player" +
			(stats.turn % 2 === 1 ? team1playerIndex : team2playerIndex)
		].yellow += 1;
		stats[stats.turn % 2 === 1 ? "team1" : "team2"][
		  "player" +
			(stats.turn % 2 === 1 ? team1playerIndex : team2playerIndex)
		].penalty += 1;
	  } else if (outcome === "red") {
		stats[stats.turn % 2 === 1 ? "team1" : "team2"][
		  "player" +
			(stats.turn % 2 === 1 ? team1playerIndex : team2playerIndex)
		].red += 1;
		stats[stats.turn % 2 === 1 ? "team1" : "team2"][
		  "player" +
			(stats.turn % 2 === 1 ? team1playerIndex : team2playerIndex)
		].penalty += 2;
	  }

	  fillStatTable();

	  if (stats.turn % 2 === 1) {
		document.getElementById("turnString").innerText = "Computer's Turn";
	  } else {
		document.getElementById("turnString").innerText = "Your Turn";
	  }

	  var turnCounterEle = document.getElementById("turnCounter");

	  var cou = 3;
	  function turnCounter() {
		if (cou > 0) {
		  turnCounterEle.innerText = cou;
		  cou--;
		  setTimeout(turnCounter, 1200);
		} else {
		  turnCounterEle.style.display = "none";
		  stats.turn += 1;
		  document.getElementById("totalTurnCounter").innerHTML =
			stats.turn;
		  if (stats.turn > 6) {
			var scoreTeam1 = 0;
			var scoreTeam2 = 0;
			["team1", "team2"].forEach(function (team) {
			  var totGoals = 0;
			  var totPenalty = 0;

			  Object.keys(stats[`${team}`]).forEach(function (player) {
				if (player !== "goalkeeper") {
				  totGoals += stats[`${team}`][`${player}`].goal;
				  totPenalty += stats[`${team}`][`${player}`].penalty;
				}
			  });

			  if (team === "team1") scoreTeam1 = totGoals * 3 - totPenalty;
			  else scoreTeam2 = totGoals * 3 - totPenalty;
			});
			document.getElementById("resultHeading").innerText =
			  scoreTeam1 > scoreTeam2
				? "You Won!!!"
				: scoreTeam1 < scoreTeam2
				? "Computer Won!!!"
				: "It's A Tie!!!";
			document.getElementById("resultOutcome").innerHTML =
			  scoreTeam1 === scoreTeam2
				? '<span style="color: darkred">' +
				  teams.team1.name +
				  '</span> Ties with <span style="color: blue">' +
				  teams.team2.name +
				  "</span>"
				: (scoreTeam1 > scoreTeam2
					? '<span style="color: darkred">' +
					  teams.team1.name +
					  "</span>"
					: '<span style="color: blue">' +
					  teams.team2.name +
					  "</span>") +
				  " beats " +
				  (scoreTeam1 > scoreTeam2
					? '<span style="color: blue">' +
					  teams.team2.name +
					  "</span>"
					: '<span style="color: darkred">' +
					  teams.team1.name +
					  "</span>") +
				  " by " +
				  Math.abs(scoreTeam1 - scoreTeam2) +
				  " Points.";
			document.getElementById(
			  "resultCommentary"
			).innerText = commentaries.win[
			  scoreTeam1 === scoreTeam2
				? "tie"
				: scoreTeam1 > scoreTeam2
				? "team1"
				: "team2"
			][
			  Math.floor(
				Math.random() *
				  commentaries.win[
					scoreTeam1 === scoreTeam2
					  ? "tie"
					  : scoreTeam1 > scoreTeam2
					  ? "team1"
					  : "team2"
				  ].length
			  )
			]
			  .replace(/{team1}/gi, teams.team1.name)
			  .replace(/{team2}/gi, teams.team2.name);
			document.getElementById("resultteam1name").innerText =
			  teams.team1.name;

			document.getElementById("resultBlock").style.display = "block";
		  } else {
			if (stats.turn % 2 === 0) {
			  playTurn();
			} else {
			  document.getElementById("playButton").style.display = "block";
			}
		  }
		}
	  }
	}, 5000);
}

This is the end of our Football game crud application. We saw a lot of code and learned different principles of localStorage. See you in the next articles. Bye.