Passed
Push — master ( 795926...7012fc )
by Tomáš
11:11
created

Games::orderGames()   B

Complexity

Conditions 9
Paths 15

Size

Total Lines 55
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 9.0076

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 9
eloc 21
c 1
b 0
f 0
nc 15
nop 0
dl 0
loc 55
ccs 21
cts 22
cp 0.9545
crap 9.0076
rs 8.0555

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace TournamentGenerator\Helpers\Sorter;
4
5
use TournamentGenerator\Game;
6
use TournamentGenerator\Group;
7
8
/**
9
 * Tournament generator sorter for games
10
 *
11
 * WORKS BY COMPARING AVAILABLE GAMES BY THEIR TEAMS
12
 * TEAMS FROM LAST 3 GAMES
13
 * 1 = PLAYED ONLY 3RD GAME FROM END
14
 * 2 = PLAYED ONLY 2ND GAME FROM END
15
 * 3 = PLAYED 3RD AND 2ND GAME FROM END
16
 * 4 = PLAYED ONLY THE LAST GAME
17
 * 5 = PLAYED 3RD AND 1ST GAME FROM END
18
 * 6 = PLAYED 2ND ANS 1ST GAME FROM END
19
 * 7 = PLAYED ALL 3 LAST GAMES
20
 *
21
 * @author  Tomáš Vojík <[email protected]>
22
 *
23
 * @package TournamentGenerator\Helpers\Sorter
24
 * @since   0.3
25
 */
26
class Games
27
{
28
29
	/** @var Group */
30
	private Group $group;
31
	/** @var Game[] */
32
	private array $games = [];
33
34
	/**
35
	 * Orders games from group
36
	 *
37
	 * @param Group $group
38
	 */
39 23
	public function __construct(Group $group) {
40 23
		$this->group = $group;
41 23
	}
42
43
	/**
44
	 * Orders games from group
45
	 *
46
	 * @return array
47
	 */
48 23
	public function orderGames() : array {
49
50 23
		$games = $this->group->getGames();
51
52 23
		if (count($games) <= 4) {
53
			return $games;
54
		}
55
56 23
		$this->games = [];
57
58 23
		$teams = [];
59 23
		foreach ($this->group->getTeams() as $team) {
60 23
			$teams[$team->getId()] = 0;
61
		}
62
63 23
		$this->moveCalculatedGames(array_shift($games), $teams);
64
65 23
		while (count($games) > 0) {
66
			// CYCLE 1
67
			// TEAM WHICH DIDN'T PLAY IN LAST GAME (< 4)
68 23
			if ($this->cycle1($games, $teams)) {
69 23
				continue;
70
			}
71
72
			// CYCLE 2
73
			// NOT TEAM WHICH PLAYED IN LAST TWO GAMES (NOT 6 or 7)
74 23
			if ($this->cycle2($games, $teams)) {
75 23
				continue;
76
			}
77
78
			// CYCLE 3
79
			// NOT TEAM WHICH PLAYED IN LAST THREE GAMES (NOT 7)
80
			// TEAMS THAT DIDN'T PLAY IN LAST GAME WILL PLAY THIS GAME (< 4)
81 3
			if ($this->cycle3($games, $teams)) {
82 1
				continue;
83
			}
84
85
			// CYCLE 4
86
			// NOT TEAM WHICH PLAYED IN LAST THREE GAMES (NOT 7)
87 3
			if ($this->cycle4($games, $teams)) {
88 3
				continue;
89
			}
90
91
			// CYCLE 5
92
			// TEAMS THAT DIDN'T PLAY IN LAST GAME WILL PLAY THIS GAME (< 4)
93 2
			if ($this->cycle5($games, $teams)) {
94 2
				continue;
95
			}
96
97
			// CYCLE 6
98
			// FIRST AVAILABLE GAME
99 1
			$this->moveCalculatedGames(array_shift($games), $teams);
100
		}
101
102 23
		return $this->games;
103
	}
104
105
	/**
106
	 * Move teams that did not play in the last game (< 4)
107
	 *
108
	 * @param Game  $game
109
	 * @param array $teams
110
	 */
111 23
	private function moveCalculatedGames(Game $game, array &$teams) : void {
112
113 23
		$this->games[] = $game;
114
115 23
		foreach (end($this->games)->getTeamsIds() as $tid) {
116 23
			$teams[$tid] += 4;
117
		}
118
119 23
		if (count($this->games) > 1) {
120 23
			foreach (prev($this->games)->getTeamsIds() as $tid) {
121 23
				$teams[$tid] -= 2;
122
			}
123
		}
124 23
		if (count($this->games) > 2) {
125 23
			foreach (prev($this->games)->getTeamsIds() as $tid) {
126 23
				--$teams[$tid];
127
			}
128
		}
129 23
		if (count($this->games) > 3) {
130 23
			foreach (prev($this->games)->getTeamsIds() as $tid) {
131 23
				--$teams[$tid];
132
			}
133
		}
134
135 23
	}
136
137
	/**
138
	 * Teams that did not play in the last game (< 4)
139
	 *
140
	 * @param array $games
141
	 * @param array $teams
142
	 *
143
	 * @return bool
144
	 */
145 23
	private function cycle1(array &$games, array &$teams) : bool {
146 23
		$found = false;
147 23
		foreach ($games as $key => $game) {
148 23
			if ($this->orderCheckTeamsVal($game, $teams, [4, 5, 6, 7])) {
149 23
				$this->moveCalculatedGames($game, $teams);
150 23
				unset($games[$key]);
151 23
				$found = true;
152 23
				break;
153
			}
154
		}
155 23
		return $found;
156
	}
157
158
	/**
159
	 * Get first available game
160
	 *
161
	 * @param Game  $game
162
	 * @param array $teams
163
	 * @param array $checkVals
164
	 * @param array $required
165
	 *
166
	 * @return bool
167
	 */
168 23
	private function orderCheckTeamsVal(Game $game, array $teams, array $checkVals, array $required = []) : bool {
169
170 23
		$requiredTeams = array_filter($teams, static function($a) use ($required) {
171 23
			return in_array($a, $required, true);
172 23
		});
173
174 23
		foreach ($game->getTeamsIds() as $tid) {
175 23
			if (in_array($teams[$tid], $checkVals, true)) {
176 23
				return false;
177
			}
178 23
			if (isset($requiredTeams[$tid])) {
179 3
				unset($requiredTeams[$tid]);
180
			}
181
		}
182
183 23
		return !(count($requiredTeams) > 0);
184
185
	}
186
187
	/**
188
	 * Teams that did not play in the last two games (not 6 or 7)
189
	 *
190
	 * @param array $games
191
	 * @param array $teams
192
	 *
193
	 * @return bool
194
	 */
195 23
	private function cycle2(array &$games, array &$teams) : bool {
196 23
		$found = false;
197 23
		foreach ($games as $key => $game) {
198 23
			if ($this->orderCheckTeamsVal($game, $teams, [6, 7])) {
199 23
				$this->moveCalculatedGames($game, $teams);
200 23
				unset($games[$key]);
201 23
				$found = true;
202 23
				break;
203
			}
204
		}
205 23
		return $found;
206
	}
207
208
	/**
209
	 * Teams that did not play in the last three games (not 7) and teams that did not play in the last game (< 4)
210
	 *
211
	 * @param array $games
212
	 * @param array $teams
213
	 *
214
	 * @return bool
215
	 */
216 3
	private function cycle3(array &$games, array &$teams) : bool {
217 3
		$found = false;
218 3
		foreach ($games as $key => $game) {
219 3
			if ($this->orderCheckTeamsVal($game, $teams, [7], [1, 2, 3])) {
220 1
				$this->moveCalculatedGames($game, $teams);
221 1
				unset($games[$key]);
222 1
				$found = true;
223 1
				break;
224
			}
225
		}
226 3
		return $found;
227
	}
228
229
	/**
230
	 * Teams that did not play in the last three games (not 7)
231
	 *
232
	 * @param array $games
233
	 * @param array $teams
234
	 *
235
	 * @return bool
236
	 */
237 3
	private function cycle4(array &$games, array &$teams) : bool {
238 3
		$found = false;
239 3
		foreach ($games as $key => $game) {
240 3
			if ($this->orderCheckTeamsVal($game, $teams, [7])) {
241 3
				$this->moveCalculatedGames($game, $teams);
242 3
				unset($games[$key]);
243 3
				$found = true;
244 3
				break;
245
			}
246
		}
247 3
		return $found;
248
	}
249
250
	/**
251
	 * Teams that did not play in the last game will play this game (< 4)
252
	 *
253
	 * @param array $games
254
	 * @param array $teams
255
	 *
256
	 * @return bool
257
	 */
258 2
	private function cycle5(array &$games, array &$teams) : bool {
259 2
		$found = false;
260 2
		foreach ($games as $key => $game) {
261 2
			if ($this->orderCheckTeamsVal($game, $teams, [], [1, 2, 3])) {
262 2
				$this->moveCalculatedGames($game, $teams);
263 2
				unset($games[$key]);
264 2
				$found = true;
265 2
				break;
266
			}
267
		}
268 2
		return $found;
269
	}
270
271
}
272