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

Tournament_DoubleElimination::calcByes()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 6
c 0
b 0
f 0
nc 2
nop 2
dl 0
loc 8
rs 10
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