Completed
Push — master ( 597f0f...0dd9ad )
by Tomáš
01:35
created

Tournament_DoubleElimination::generateLosingSide()   B

Complexity

Conditions 11
Paths 7

Size

Total Lines 59
Code Lines 46

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 46
c 0
b 0
f 0
nc 7
nop 9
dl 0
loc 59
rs 7.3166

How to fix   Long Method    Complexity    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace TournamentGenerator\Preset;
4
5
/**
6
 *
7
 */
8
class Tournament_DoubleElimination extends \TournamentGenerator\Tournament
9
{
10
11
	public function generate() {
12
		$this->allowSkip();
13
14
		$countTeams = count($this->getTeams());
15
16
		if ($countTeams < 3) throw new \Exception('Double elimination is possible for minimum of 3 teams - '.$countTeams.' teams given.');
17
18
19
		// CALCULATE BYES
20
		$nextPow = 0;
21
		$byes = $this->calcByes($countTeams, $nextPow);
22
23
		$startRound = $this->round('Start round');
24
25
		$roundsNum = log($nextPow, 2)*2;
26
27
		$startGroups = ($countTeams+$byes)/2;
28
29
		$previousGroups = [];
30
		$previousLosingGroups = [];
31
		$groupIds = [];
32
		$allGroups = [];
33
34
		for ($i=1; $i <= $startGroups; $i++) {
35
			$g = $startRound->group([
36
				'name' => 'Start group - '.$i,
37
				'inGame' => 2,
38
				'type' => \TWO_TWO,
39
			]);
40
			$allGroups[] = $g;
41
			$groupIds[] = $g->id;
42
			$previousGroups[] = $g;
43
		}
44
45
		// SPLIT TEAMS EVENLY
46
		$this->splitTeams();
47
48
		for ($r=2; $r <= $roundsNum-1; $r++) {
49
			$groups = [];
50
			$losingGroups = [];
51
			$round = $this->round('Round '.$r);
52
53
			// GENERATE GROUPS AND PROGRESSIONS
54
55
			// GENERATING LOSING AND WINNING SIDE
56
			$lastLosingGroup = $this->generateLosingSide($r, $byes, $countTeams, $round, $allGroups, $groups, $previousLosingGroups, $previousGroups, $losingGroups);
57
			$this->generateWinSide($r, $byes, $countTeams, $round, $allGroups, $groups, $lastWinningGroup, $previousGroups);
58
59
			$previousGroups = $groups;
60
			$previousLosingGroups = $losingGroups;
61
		}
62
63
		// LAST ROUND
64
		$round = $this->round('Round '.$roundsNum.' - Finale');
65
		$groupFinal = $round->group([
66
			'name' => 'Round '.$r.' - finale',
67
			'inGame' => 2,
68
			'type' => \TWO_TWO,
69
			'order' => 1,
70
		]);
71
		$allGroups[] = $groupFinal;
72
		$lastLosingGroup->progression($groupFinal, 0, 1);
73
		$lastWinningGroup->progression($groupFinal, 0, 1);
74
75
		// REPEAT GROUP IF LOSING TEAM WON
76
		$group = $round->group([
77
			'name' => 'Round '.$r.' - finale (2)',
78
			'inGame' => 2,
79
			'type' => \TWO_TWO,
80
			'order' => 1,
81
		]);
82
		$twoLoss = new \TournamentGenerator\TeamFilter('losses', '=', 1, $allGroups);
83
		$groupFinal->progression($group, 0, 2)->addFilter($twoLoss);
84
85
		return $this;
86
87
	}
88
89
	private function calcByes(int $countTeams, int &$nextPow) {
90
		$byes = 0;
91
		$nextPow = $countTeams;
92
		if ( !\TournamentGenerator\isPowerOf2($countTeams) ) {
93
			$nextPow = bindec(str_pad(1, strlen(decbin($countTeams))+1, 0, STR_PAD_RIGHT));
94
			$byes = $nextPow-$countTeams;
95
		}
96
		return $byes;
97
	}
98
	private function generateWinSide(int &$r, int &$byes, int &$countTeams, \TournamentGenerator\Round &$round, array &$allGroups, array &$groups, \TournamentGenerator\Group &$lastWinningGroup = null, array &$previousGroups = []) {
99
		$order = 1;
100
		for ($g=1; $g <= (($countTeams+$byes)/pow(2, $r)); $g++) {
101
			$group = $round->group([
102
				'name' => 'Round '.$r.' - win '.$g,
103
				'inGame' => 2,
104
				'type' => \TWO_TWO,
105
				'order' => $order,
106
			]);
107
			$allGroups[] = $group;
108
			$order += 2;
109
			$groups[] = $group;
110
			$lastWinningGroup = $group; // KEEP THE LAST GROUP FOR FINALE
111
			$previousGroups[2*($g-1)]->progression($group, 0, 1); // PROGRESS FROM GROUP BEFORE
112
			$previousGroups[(2*($g-1))+1]->progression($group, 0, 1); // PROGREESS FROM GROUP BEFORE
113
		}
114
		return $this;
115
	}
116
	private function generateLosingSide(int &$r, int &$byes, int &$countTeams, \TournamentGenerator\Round &$round, array &$allGroups, array &$groups, array &$previousLosingGroups = [], array &$previousGroups = [], array &$losingGroups = []) {
0 ignored issues
show
Unused Code introduced by
The parameter $byes is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

116
	private function generateLosingSide(int &$r, /** @scrutinizer ignore-unused */ int &$byes, int &$countTeams, \TournamentGenerator\Round &$round, array &$allGroups, array &$groups, array &$previousLosingGroups = [], array &$previousGroups = [], array &$losingGroups = []) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $countTeams is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

116
	private function generateLosingSide(int &$r, int &$byes, /** @scrutinizer ignore-unused */ int &$countTeams, \TournamentGenerator\Round &$round, array &$allGroups, array &$groups, array &$previousLosingGroups = [], array &$previousGroups = [], array &$losingGroups = []) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $groups is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

116
	private function generateLosingSide(int &$r, int &$byes, int &$countTeams, \TournamentGenerator\Round &$round, array &$allGroups, /** @scrutinizer ignore-unused */ array &$groups, array &$previousLosingGroups = [], array &$previousGroups = [], array &$losingGroups = []) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
117
		$losingGroupTeamsCount = count($previousLosingGroups)+count($previousGroups);
118
		$order = 2;
119
		if (\TournamentGenerator\isPowerOf2($losingGroupTeamsCount)) { // IF THE NUMBER OF TEAMS IS A POWER OF 2, GENERATE GROUPS WITHOUT BYES
120
			for ($g=1; $g <= $losingGroupTeamsCount/2; $g++) {
121
				$group = $round->group([
122
					'name' => 'Round '.$r.' - loss '.$g,
123
					'inGame' => 2,
124
					'type' => \TWO_TWO,
125
					'order' => $order,
126
				]);
127
				$allGroups[] = $group;
128
				$order += 2;
129
				$losingGroups[] = $group;
130
				$lastLosingGroup = $group; // KEEP THE LAST GROUP FOR FINALE
131
				if ($r === 2) { // FIRST LOSING ROUND
132
					$previousGroups[2*($g-1)]->progression($group, 1, 1); // PROGRESS FROM STARTING GROUP
133
					$previousGroups[(2*($g-1))+1]->progression($group, 1, 1); // PROGREESS FROM STARTING GROUP
134
				}
135
				elseif ($losingGroupTeamsCount >= 2) {
136
					$previousLosingGroups[$g-1]->progression($group, 0, 1); // PROGRESS FROM LOSING GROUP BEFORE
137
					if (isset(array_reverse($previousGroups)[$g-1])) array_reverse($previousGroups)[$g-1]->progression($group, 1, 1); // PROGREESS FROM WINNING GROUP BEFORE
138
					else $previousLosingGroups[$g]->progression($group, 0, 1); // PROGRESS OTHER TEAM FROM LOSING GROUP BEEFORE
139
				}
140
			}
141
		}
142
		else { // IF THE NUMBER OF TEAMS IS NOT A POWER OF 2, GENERATE GROUPS WITH BYES
143
			// LOOK FOR THE CLOSEST LOWER POWER OF 2
144
			$losingByes = $losingGroupTeamsCount-bindec(str_pad(1, strlen(decbin($losingGroupTeamsCount)), 0, STR_PAD_RIGHT));
145
			$n = (floor(count($previousLosingGroups)/2)+$losingByes);
146
			$byesGroupsNums = [];
147
			$byesProgressed = 0;
148
			for ($i=0; $i < $losingByes; $i++) {
149
				$byesGroupsNums[] = $n-($i*2);
150
			}
151
			$lastGroup = 0;
152
			for ($g=1; $g <= ((count($previousLosingGroups)/2)+$losingByes); $g++) {
153
				$group = $round->group([
154
					'name' => 'Round '.$r.' - loss '.$g,
155
					'inGame' => 2,
156
					'type' => \TWO_TWO,
157
					'order' => $order,
158
				]);
159
				$allGroups[] = $group;
160
				$order += 2;
161
				$losingGroups[] = $group;
162
				$lastLosingGroup = $group; // KEEP THE LAST GROUP FOR FINALE
163
				if (in_array($g, $byesGroupsNums) && isset($previousGroups[$byesProgressed])) { // EMPTY GROUP FROM BYE
164
					$previousGroups[$byesProgressed]->progression($group, 1, 1); // PROGRESS FROM WINNING GROUP BEFORE
165
					$byesProgressed++;
166
				}
167
				else {
168
					$previousLosingGroups[$lastGroup]->progression($group, 0, 1); // PROGRESS FROM LOSING GROUP BEFORE
169
					if (isset($previousLosingGroups[$lastGroup + 1])) $previousLosingGroups[$lastGroup + 1]->progression($group, 0, 1); // PROGREESS FROM LOSING GROUP BEFORE
170
					$lastGroup += 2;
171
				}
172
			}
173
		}
174
		return $lastLosingGroup;
1 ignored issue
show
Comprehensibility Best Practice introduced by
The variable $lastLosingGroup does not seem to be defined for all execution paths leading up to this point.
Loading history...
175
	}
176
177
}
178