/lib/IBL/Standings.php

https://github.com/chartjes/building-testable-applications · PHP · 356 lines · 286 code · 49 blank · 21 comment · 31 complexity · 511d710cc5545d4b311f959f3430f090 MD5 · raw file

  1. <?php
  2. /**
  3. * Model for generating standards
  4. */
  5. namespace IBL;
  6. class Standings
  7. {
  8. protected $_conferences = array();
  9. protected $_divisions = array();
  10. protected $_franchises = array();
  11. protected $_games = array();
  12. protected $_names = array();
  13. protected $_nicknames = array();
  14. public function __construct($games, $franchises, $week = null)
  15. {
  16. if ($week === null) {
  17. $this->_games = $games;
  18. } else {
  19. foreach ($games as $game) {
  20. if ($game->getWeek() <= $week) {
  21. $this->_games[] = $game;
  22. }
  23. }
  24. }
  25. $this->_franchises = $franchises;
  26. foreach ($franchises as $franchise) {
  27. $id = $franchise->getId();
  28. $this->_conferences[$id] = $franchise->getConference();
  29. $this->_divisions[$id] = $franchise->getDivision();
  30. $this->_names[$id] = $franchise->getName();
  31. $this->_nicknames[$id] = $franchise->getNickname();
  32. }
  33. }
  34. public function generateBreakdown()
  35. {
  36. $wins = array();
  37. $losses = array();
  38. $standingsData = array();
  39. // Initialize all our variables, except we don't need to set
  40. // any values where the home team and road team are equal
  41. foreach ($this->_franchises as $awayTeam) {
  42. foreach ($this->_franchises as $homeTeam) {
  43. if ($awayTeam->getId() !== $homeTeam->getId()) {
  44. $wins[$awayTeam->getId()][$homeTeam->getId()] = 0;
  45. $losses[$awayTeam->getId()][$homeTeam->getId()] = 0;
  46. }
  47. }
  48. }
  49. // Calculate the breakdown wins and losses
  50. foreach ($this->_games as $game) {
  51. $homeTeamId = $game->getHomeTeamId();
  52. $awayTeamId = $game->getAwayTeamId();
  53. if ($game->getHomeScore() > $game->getAwayScore()) {
  54. $wins[$homeTeamId][$awayTeamId]++;
  55. $losses[$awayTeamId][$homeTeamId]++;
  56. } else {
  57. $wins[$awayTeamId][$homeTeamId]++;
  58. $losses[$homeTeamId][$awayTeamId]++;
  59. }
  60. }
  61. // Sort the arrays so that they match up nicely
  62. arsort($wins);
  63. arsort($losses);
  64. return array(
  65. 'wins' => $wins,
  66. 'losses' => $losses
  67. );
  68. }
  69. public function generatePlayoff()
  70. {
  71. $regularStandings = $this->generateRegular();
  72. $leaders = array();
  73. $magicNumber = array();
  74. $wildCard = array();
  75. $lead = array();
  76. foreach ($regularStandings as $conference => $confTeams) {
  77. foreach ($confTeams as $division => $teams) {
  78. $leader = array_slice($teams, 0, 1);
  79. $secondTeam = array_slice($teams, 1, 1);
  80. $leaders[$conference][$division] = $leader[0];
  81. $x = $leader[0]['wins'];
  82. $y = $secondTeam[0]['losses'];
  83. $magicNumber[$conference][$division] = $secondTeam[0]['gb'];
  84. if ($magicNumber[$conference][$division] <= 0) {
  85. $magicNumber[$conference][$division] = 'Clinched';
  86. }
  87. $lead[$conference][$division] = $secondTeam[0]['gb'];
  88. // Add the teams that are not division leaders to
  89. // the list of wild card teams
  90. $chaseTeams = array_slice($teams, 1);
  91. foreach ($chaseTeams as $team) {
  92. $wildCard[$conference][] = $team;
  93. }
  94. }
  95. }
  96. // Sort all our teams in order of winning percentage
  97. // so we can figure out who the wild card leaders are
  98. foreach ($wildCard as $conference => $teamStandings) {
  99. $pct = array();
  100. $wins = array();
  101. $losses = array();
  102. $firstWins = 0;
  103. $firstLosses = 0;
  104. $secondWins = 0;
  105. $secondLosses = 0;
  106. $firstGb = array();
  107. $secondGb = array();
  108. $firstWc = "";
  109. $secondWc = "";
  110. foreach ($teamStandings as $teamStanding) {
  111. $pct[$teamStanding['teamId']] = $teamStanding['pct'];
  112. $wins[$teamStanding['teamId']] = $teamStanding['wins'];
  113. $losses[$teamStanding['teamId']] = $teamStanding['losses'];
  114. }
  115. arsort($pct);
  116. // Build our result array of where a team sits in the
  117. // wild card races
  118. foreach ($pct as $team => $tPct) {
  119. if (!$firstWc) {
  120. $firstWc = $team;
  121. $firstGb[$team] = '--';
  122. $secondGb[$team] = '--';
  123. $firstWins = $wins[$team];
  124. $firstLosses = $losses[$team];
  125. } else {
  126. if (!$secondWc) {
  127. $secondWc = $team;
  128. $secondGb[$team] = '--';
  129. $firstGb[$team] = (
  130. ($firstWins - $wins[$team]) +
  131. ($losses[$team] - $firstLosses))
  132. / 2;
  133. $secondW = $wins[$team];
  134. $secondL = $wins[$team];
  135. } else {
  136. $firstGb[$team] = (
  137. ($firstWins - $wins[$team]) +
  138. ($losses[$team] - $firstLosses))
  139. / 2;
  140. $secondGb[$team] = (
  141. ($secondWins - $wins[$team]) +
  142. ($losses[$team] - $secondLosses))
  143. / 2;
  144. }
  145. if ($firstGb[$team] == 0) {
  146. $firstGb[$team] = '--';
  147. }
  148. if ($secondGb[$team] == 0) {
  149. $secondGb[$team] = '--';
  150. }
  151. }
  152. }
  153. $wildCardStandings[$conference] = array();
  154. foreach ($pct as $team => $tPct) {
  155. $wildCardStandings[$conference][] = array(
  156. $team,
  157. $wins[$team],
  158. $losses[$team],
  159. $pct[$team],
  160. $firstGb[$team],
  161. $secondGb[$team]
  162. );
  163. }
  164. }
  165. return array(
  166. 'leaders' => $leaders,
  167. 'wildCardStandings' => $wildCardStandings,
  168. 'magicNumber' => $magicNumber,
  169. 'lead' => $lead
  170. );
  171. }
  172. public function generateRegular()
  173. {
  174. $wins = array();
  175. $losses = array();
  176. $homeWins = array();
  177. $homeLosses = array();
  178. $awayWins = array();
  179. $awayLosses = array();
  180. $confWins = array();
  181. $confLosses = array();
  182. $divWins = array();
  183. $divLosses = array();
  184. // Initialize all our standings variables
  185. foreach ($this->_conferences as $teamId => $value) {
  186. $wins[$teamId] = 0;
  187. $losses[$teamId] = 0;
  188. $homeWins[$teamId] = 0;
  189. $homeLosses[$teamId] = 0;
  190. $awayWins[$teamId] = 0;
  191. $awayLosses[$teamId] = 0;
  192. $confWins[$teamId] = 0;
  193. $confLosses[$teamId] = 0;
  194. $divWins[$teamId] = 0;
  195. $divLosses[$teamId] = 0;
  196. }
  197. // Now loop through each game
  198. foreach ($this->_games as $game) {
  199. $homeTeamId = $game->getHomeTeamId();
  200. $awayTeamId = $game->getAwayTeamId();
  201. if ($game->getHomeScore() > $game->getAwayScore()) {
  202. $wins[$homeTeamId]++;
  203. $losses[$awayTeamId]++;
  204. $homeWins[$homeTeamId]++;
  205. $awayLosses[$awayTeamId]++;
  206. if ($this->_conferences[$homeTeamId] == $this->_conferences[$awayTeamId]) {
  207. $confWins[$homeTeamId]++;
  208. $confLosses[$awayTeamId]++;
  209. }
  210. if ($this->_divisions[$homeTeamId] == $this->_divisions[$awayTeamId]) {
  211. $divWins[$homeTeamId]++;
  212. $divLosses[$awayTeamId]++;
  213. }
  214. } else {
  215. $wins[$awayTeamId] += 1;
  216. $losses[$homeTeamId] += 1;
  217. $awayWins[$awayTeamId] += 1;
  218. $homeLosses[$homeTeamId] += 1;
  219. if ($this->_conferences[$homeTeamId] == $this->_conferences[$awayTeamId]) {
  220. $confWins[$awayTeamId]++;
  221. $confLosses[$homeTeamId]++;
  222. }
  223. if ($this->_divisions[$homeTeamId] == $this->_divisions[$awayTeamId]) {
  224. $divWins[$awayTeamId]++;
  225. $divLosses[$homeTeamId]++;
  226. }
  227. }
  228. }
  229. // Build our standings result, grouping teams by conference
  230. // and division
  231. $standingsData = array();
  232. $conferences = array('AC', 'NC');
  233. $divisions = array('West', 'Central', 'East');
  234. foreach ($conferences as $conference) {
  235. foreach ($divisions as $division) {
  236. // Figure out what teams belong to this combo of conference
  237. // and division
  238. $confTeams = array_keys($this->_conferences, $conference);
  239. $divisionTeams = array_keys($this->_divisions, $division);
  240. $teams = array_intersect($confTeams, $divisionTeams);
  241. foreach ($teams as $teamId) {
  242. $winCount = $wins[$teamId];
  243. $lossCount = $losses[$teamId];
  244. if (($winCount + $lossCount) != 0) {
  245. $pct = $winCount / ($winCount + $lossCount);
  246. } else {
  247. $pct = 0;
  248. }
  249. $rawData[$conference][$division][$teamId] = array(
  250. 'teamId' => $teamId,
  251. 'nickname' => $this->_nicknames[$teamId],
  252. 'name' => $this->_names[$teamId],
  253. 'wins' => $winCount,
  254. 'losses' => $lossCount,
  255. 'homeWins' => $homeWins[$teamId],
  256. 'homeLosses' => $homeLosses[$teamId],
  257. 'awayWins' => $awayWins[$teamId],
  258. 'awayLosses' => $awayLosses[$teamId],
  259. 'confWins' => $confWins[$teamId],
  260. 'confLosses' => $confLosses[$teamId],
  261. 'divWins' => $divWins[$teamId],
  262. 'divLosses' => $divLosses[$teamId],
  263. 'pct' => $pct
  264. );
  265. }
  266. }
  267. }
  268. return $this->_sort($rawData);
  269. }
  270. protected function _sort($standingsData)
  271. {
  272. $newStandingsData = array();
  273. foreach ($standingsData as $conference => $confTeams) {
  274. foreach ($confTeams as $division => $teams) {
  275. // Sort teams by winning percentage in their division
  276. $sortedData = $teams;
  277. $column = array();
  278. foreach ($sortedData as $tmp) {
  279. $column[] = $tmp['pct'];
  280. }
  281. array_multisort($column, SORT_DESC, $sortedData);
  282. $tmp = $sortedData;
  283. // Determine how many games teams are behind the leader
  284. $leader = true;
  285. foreach ($tmp as $idx => $info) {
  286. $teamId = $info['teamId'];
  287. if ($leader == true) {
  288. $leader = false;
  289. $sortedData[$idx]['gb']
  290. = '--';
  291. $leadW = $info['wins'];
  292. $leadL = $info['losses'];
  293. } else {
  294. $x = $leadW - $info['wins'];
  295. $y = $info['losses'] - $leadL;
  296. $sortedData[$idx]['gb']
  297. = ($x + $y) / 2;
  298. }
  299. }
  300. foreach ($sortedData as $team) {
  301. $newStandingsData[$conference][$division][] = $team;
  302. }
  303. }
  304. }
  305. return $newStandingsData;
  306. }
  307. }