Home

Algorithmic Advent: 20 – League tables with PHP

Published on 20 Dec 2010. Tagged with php, algorithmicadvent.

index.php

<?php

require_once './League.php';
require_once './Match.php';
require_once './Team.php';

$league = new League();

$teams = array(
    0 => $league->createTeam('Manchester City'),
    1 => $league->createTeam('Chelsea'),
    2 => $league->createTeam('Arsenal'),
    3 => $league->createTeam('Blackburn Rovers')
);

$league->addMatch(new Match($teams[0], $teams[1], 2, 0))
       ->addMatch(new Match($teams[0], $teams[2], 2, 1))
       ->addMatch(new Match($teams[0], $teams[3], 2, 0))

       ->addMatch(new Match($teams[1], $teams[0], 2, 0))
       ->addMatch(new Match($teams[1], $teams[2], 3, 5))
       ->addMatch(new Match($teams[1], $teams[3], 2, 0))

       ->addMatch(new Match($teams[2], $teams[0], 2, 0))
       ->addMatch(new Match($teams[2], $teams[1], 3, 0))
       ->addMatch(new Match($teams[2], $teams[3], 2, 0))

       ->addMatch(new Match($teams[3], $teams[0], 2, 0))
       ->addMatch(new Match($teams[3], $teams[1], 1, 1))
       ->addMatch(new Match($teams[3], $teams[2], 2, 0));

$table = $league->getTable();


echo '<table border="1">';

echo '<tr>';
echo '<td>Rank</td>';
echo '<td>Team</td>';
echo '<td>Games</td>';
echo '<td>W</td>';
echo '<td>D</td>';
echo '<td>L</td>';
echo '<td>Goals</td>';
echo '<td>Goals Diff</td>';
echo '<td>Points</td>';

echo '</tr>';
$i = 1;
foreach ($table as $team) {
    echo '<tr>';
    echo '<td>' . $i++ . '</td>';
    echo '<td>' . $team->teamname . '</td>';
    echo '<td>' . $team->gamesPlayed . '</td>';
    echo '<td>' . $team->wins . '</td>';
    echo '<td>' . $team->draws . '</td>';
    echo '<td>' . $team->losses . '</td>';
    echo '<td>' . ($team->hgoals + $team->agoals) . ':' . ($team->hgoalsAgainst + $team->agoalsAgainst) . '</td>';
    echo '<td>' . (($team->hgoals + $team->agoals) - ($team->hgoalsAgainst + $team->agoalsAgainst)) . '</td>';
    echo '<td>' . $team->points . '</td>';
    echo '</tr>';
}

echo '</table>';

Team.php

<?php

class Team
{
    public $teamname;
    public $agoals = 0;
    public $hgoals = 0;
    public $agoalsAgainst = 0;
    public $hgoalsAgainst = 0;

    public $gamesPlayed = 0;

    public $wins = 0;
    public $draws = 0;
    public $losses = 0;

    public $points = 0;

    public function __construct($teamname)
    {
        $this->teamname     = $teamname;
    }
}

Match.php

<?php

class Match
{
    /** @var Team Home team */
    public $hteam;

    /**@var Team Away team */
    public $ateam;

    /**@var int Home team goals */
    public $hgoals;

    /** @var int Away team goals */
    public $agoals;

    public function __construct(Team $hteam, Team $ateam, $hgoals, $agoals)
    {
        $this->hteam = $hteam;
        $this->ateam = $ateam;
        $this->hgoals = $hgoals;
        $this->agoals = $agoals;
    }
}

League.php

<?php

class League
{
    protected $_matches = array();
    protected $_teams   = array();
    
    public function addMatch(Match $match)
    {
        $this->_matches[] = $match;
        return $this;
    }

    public function createTeam($teamname)
    {
        $team = new Team($teamname);
        $this->_teams[] = $team;

        return $team;
    }

    protected function _sortTeams(Team $a, Team $b)
    {
        // Absolute number of points
        if ($a->points != $b->points) {
            return ($a->points < $b->points);
        }

        // Direct comparison and away goals

        // Goals first team (x=a)
        $xgoals = 0;

        // Goals second team (y=b)
        $ygoals = 0;

        // Away goals team a
        $xagoals = 0;

        // Away goals team b
        $yagoals = 0;

        foreach ($this->_matches as $match) {
            if ($match->hteam === $a && $match->ateam === $b) {
                $xgoals += $match->hgoals;
                $ygoals += $match->agoals;
                $yagoals = $match->agoals;
            } else if ($match->hteam === $b && $match->ateam === $a) {
                $ygoals += $match->hgoals;
                $xgoals += $match->agoals;
                $xagoals = $match->agoals;
            }
        }

        /*
        if ($xgoals != $ygoals) {
            return ($xgoals < $ygoals);
        }

        if ($xagoals != $yagoals) {
            return ($xagoals < $yagoals);
        }
        */

        // Goal difference
        $adiff = ($a->hgoals + $a->agoals) - ($a->hgoalsAgainst + $a->agoalsAgainst);
        $bdiff = ($b->hgoals + $b->agoals) - ($b->hgoalsAgainst + $b->agoalsAgainst);

        if ($adiff != $bdiff) {
            return ($adiff < $bdiff);
        }

        // Absolute number of goals scored during season
        if (($a->hgoals + $a->agoals) != ($b->hgoals + $b->agoals)) {
            return (($a->hgoals + $a->agoals) < ($b->hgoals + $b->agoals));
        }

        // Team order undefined (possibly same rank)
        //throw new Exception('Couldn\'t determine team order.');
    }

    public function getTable()
    {
        foreach ($this->_matches as $match) {
            if ($match->hgoals > $match->agoals) {
                $match->hteam->points += 3;

                $match->hteam->wins++;
                $match->ateam->losses++;
            } else if ($match->hgoals == $match->agoals) {
                $match->hteam->points += 1;
                $match->ateam->points += 1;

                $match->hteam->draws++;
                $match->ateam->draws++;
            } else {
                $match->ateam->points += 3;

                $match->hteam->losses++;
                $match->ateam->wins++;
            }

            $match->hteam->hgoals += $match->hgoals;
            $match->hteam->hgoalsAgainst += $match->agoals;

            $match->ateam->agoals += $match->agoals;
            $match->ateam->agoalsAgainst += $match->hgoals;

            $match->hteam->gamesPlayed++;
            $match->ateam->gamesPlayed++;
        }

        $teamsSorted = $this->_teams;

        usort($teamsSorted, array($this, '_sortTeams'));

        return $teamsSorted;
    }
}