PHP Classes

PHP Football Simulation: Compute football teams attack and defense strength

Recommend this page to a friend!
  Info   View files Example   View files View files (14)   DownloadInstall with Composer Download .zip   Reputation   Support forum   Blog    
Ratings Unique User Downloads Download Rankings
Not yet rated by the usersTotal: 143 All time: 9,136 This week: 124Up
Version License PHP version Categories
php-football-simulat 1.0.0MIT/X Consortium ...5Algorithms, PHP 5, Games
Description 

Author

This package can compute football teams attack and defense strength.

It takes as parameters the football country teams, total games played, wins, draws, losses, scored and missed goals.

The package takes the parameters about the teams and calculates their strength and defense levels by determining games results using Poisson distribution.

Innovation Award
PHP Programming Innovation award nominee
December 2017
Number 4
Football is a very popular sport that is often used to create simulation games.

This package can perform several types of calculations related with the attack and defense of simulated football game.

Manuel Lemos
Picture of Aleksey
  Performance   Level  
Name: Aleksey <contact>
Classes: 3 packages by
Country: Russian Federation Russian Federation
Age: ???
All time rank: 330690 in Russian Federation Russian Federation
Week rank: 609 Up29 in Russian Federation Russian Federation Up
Innovation award
Innovation award
Nominee: 1x

Example

<?php
/*
 * Copyright (c) 2017 @meet-aleksey <https://github.com/meet-aleksey>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
 
Error('POST request method is expected.');
  return;
}

// get request body:
$requestBody = file_get_contents('php://input');

// check type of content:
if (strrpos($_SERVER['HTTP_CONTENT_TYPE'], '/json') !== FALSE || strrpos($_SERVER['CONTENT_TYPE'], '/json') !== FALSE) {
 
// json:
 
$query = json_decode($requestBody, true);
} else {
 
// file:
 
$query = array('method' => 'upload');
}

if (empty(
$query['method'])) {
 
Error('The "method" is required. Value cannot be empty.');
  return;
}

require_once
'team.php';
require_once
'match.php';
require_once
'stage.php';

switch (
strtolower($query['method'])) {
  case
'example':
   
// return example data:
   
OutputExampleData();
    break;

  case
'simulate':
   
// return results of simulation:
   
OutputSimulationResult($query['teams']);
    break;

  case
'upload':
   
OutputData($requestBody);
    break;

  default:
   
Error('Unknown method.');
    break;
}

/**
 * Gets data from data.csv.
 *
 * @return void
 */
function OutputExampleData() {
  if ((
$data = file_get_contents('data.csv')) !== FALSE) {
   
OutputData($data);
  }
  else {
   
Error('Cannot open file data.csv. Check the existence of "data.csv" and the permission to read it.');
  }
}

/**
 * Outputs the specified data.
 *
 * @param string $data
 * CSV data to parse and output.
 *
 * @return void
 */
function OutputData($data) {
  if (empty(
$data)) {
   
Error('Data is required.');
    return;
  }

 
$skip = TRUE;
 
$teams = array();

 
$total = new Team();
 
$total->Name = 'Total';
 
$total->Games = $total->Goals = $total->Losses =
 
$total->Missed = $total->Draw = $total->Wins = 0;

 
$rows = split("\n", preg_replace('~\R~u', "\n", $data));

  foreach (
$rows as $row) {
    if (empty(
$row)) {
      continue;
    }

   
$row = str_getcsv($row, ';');

    if (
count($row) < 6) {
     
Error('Wrong data. Please check the file format.');
      return;
    }

    if (
$skip) {
     
$skip = FALSE;
      continue;
    }

   
$team = new Team();

   
$team->Name = trim($row[0]);
   
$total->Games += ($team->Games = (int)$row[1]);
   
$total->Wins += ($team->Wins = (int)$row[2]);
   
$total->Losses += ($team->Losses = (int)$row[3]);
   
$total->Draw += ($team->Draw = (int)$row[4]);

   
$balls = split('-', $row[5]);

   
$total->Goals += ($team->Goals = (int)trim($balls[0]));
   
$total->Missed += ($team->Missed = (int)trim($balls[1]));

   
// add team to list
   
$teams[] = $team;
  }

 
// add total results
 
$teams[] = $total;

 
Output($teams);
}

/**
 * Outputs simulations result.
 *
 * @param array $teams
 * List of teams.
 *
 * @return void
 */
function OutputSimulationResult($teams) {
 
$result = array();

 
Play($result, $teams);
 
Output($result);
}

/**
 * Simulates a stage of football matches.
 *
 * @param Stage[] &$writer
 * List of stages for output.
 *
 * @param array $teams
 * List of teams.
 *
 * @param int $stageNumber
 * Stage number. Default: 1.
 *
 * @return void
 */
function Play(&$writer, $teams, $stageNumber = 1) {
  if (!isset(
$stageNumber)) {
   
$stageNumber = 1;
  }

 
// create new stage:
 
$writer[] = $stage = new Stage();
 
$stage->Matches = array();

 
// teams count:
 
$totalTeams = count($teams);

 
// mix the array:
 
shuffle($teams);

 
// losers to remove:
 
$losers = array();

 
// simulate
 
for ($i = 0; $i < $totalTeams; $i += 2) {
   
$goalsAvg = array(
     
$teams[$i]['Goals'] / $teams[$i]['Games'],
     
$teams[$i + 1]['Goals'] / $teams[$i + 1]['Games']
    );
   
$missedAvg = array(
     
$teams[$i]['Missed'] / $teams[$i]['Games'],
     
$teams[$i + 1]['Missed'] / $teams[$i + 1]['Games']
    );

   
$stage->Matches[] = $match = new Match();

   
$match->Teams = array($teams[$i]['Name'], $teams[$i + 1]['Name']);
   
$match->Results = array(
     
Poisson(
        (
$goalsAvg[0] / $missedAvg[0]) * ($missedAvg[0] / $goalsAvg[0]) * $goalsAvg[0],
        (
$goalsAvg[1] / $missedAvg[1]) * ($missedAvg[1] / $goalsAvg[1]) * $goalsAvg[1]
      ),
     
Poisson(
        (
$goalsAvg[1] / $missedAvg[1]) * ($missedAvg[1] / $goalsAvg[1]) * $goalsAvg[1],
        (
$goalsAvg[0] / $missedAvg[0]) * ($missedAvg[0] / $goalsAvg[0]) * $goalsAvg[0]
      )
    );

    if (
$match->Results[0] > $match->Results[1]) {
     
$losers[] = $teams[$i + 1]['Name'];
    }
    else if (
$match->Results[1] > $match->Results[0]) {
     
$losers[] = $teams[$i]['Name'];
    }
    else {
     
$losers[] = $teams[rand($i, $i + 1)]['Name'];
    }
  }

 
// names of all teams to search index by name:
 
$namesOfAllTeams = array_map(function($itm) { return $itm['Name']; }, $teams);

 
// remove losers:
 
foreach ($losers as $teamName) {
    if ((
$index = array_search($teamName, $namesOfAllTeams)) !== FALSE) {
      unset(
$teams[$index]);
    }
  }

 
// next stage:
 
if (count($teams) >= 2) {
   
Play($writer, $teams, $stageNumber + 1);
  }
}

/**
 * Calculates factorial.
 *
 * @param double|integer $number
 *
 * @return double|integer
 */
function Factorial($number)
{
  if (
$number < 2) {
    return
1;
  } else {
    return (
$number * Factorial($number - 1));
  }
}

/**
 * Poisson Distribution.
 *
 * @param mixed $chance
 * The probability value.
 *
 * @param mixed $occurrence
 * The number of occurances.
 *
 * @return double
 */
function Poisson($chance, $occurrence)
{
  return
round((exp(-$chance) * pow($chance, $occurrence) / Factorial($occurrence)) * 100, 2);
}

/**
 * Outputs error message.
 *
 * @param string $message
 * Text of error message.
 *
 * @return void
 */
function Error($message) {
 
Output(array('Error' => array('Text' => $message)), 500);
}

/**
 * Outputs response.
 *
 * @param mixed $data
 * Data to output.
 *
 * @param int $status
 * The HTTP status code. Default: 200 (OK).
 *
 * @return void
 */
function Output($data, $status = 200) {
 
header('Content-Type: application/json');
 
http_response_code($status);

 
$result = json_encode($data);

  if (
$result === FALSE)
  {
    throw new
ErrorException('JSON encode error #' . json_last_error() . ': ' . json_last_error_msg());
  }

  echo
$result;
}


Details

?# Football simulation

This is a simple simulator of football matches on PHP.

Input data

At the input, a CSV file with the following structure is expected:

Country;Total games;Wins;Draws;Losses;Scored and missed goals
Brazil;104;70;17;17;221 - 102
Germany;106;66;20;20;224 - 121
Italy;83;45;21;17;128 - 77
Argentina;77;42;14;21;131 - 84

Columns delimiter - ;.

Total columns - 6.

The 2-5 columns must contain integer values.

The last column expects two numeric values separated by a hyphen.

First line - is header.

After the first line a list of football teams is expected. The number of teams must be divisible by two.

Preview

Requirements

  • PHP 5.x/7.x

License

The MIT License (MIT)

Copyright 2017, @meet-aleksey


  Files folder image Files  
File Role Description
Accessible without login Plain text file api.php Example Example script
Accessible without login Plain text file client.js Data Auxiliary data
Accessible without login Plain text file data.csv Data Auxiliary data
Accessible without login Plain text file FootballSimulation.phpproj Data Auxiliary data
Accessible without login Plain text file FootballSimulation.sln Data Auxiliary data
Accessible without login Plain text file index.php Aux. Auxiliary script
Accessible without login Plain text file LICENSE Lic. License text
Plain text file match.php Class Class source
Accessible without login Image file preview.gif Output Output results
Accessible without login Plain text file README.md Doc. Documentation
Accessible without login Plain text file README.ru.md Doc. Documentation
Plain text file stage.php Class Class source
Accessible without login Plain text file styles.css Data Auxiliary data
Plain text file team.php Class Class source

 Version Control Unique User Downloads Download Rankings  
 100%
Total:143
This week:0
All time:9,136
This week:124Up