Passed
Branch master (7949ab)
by Tomáš
02:07
created

DoubleElimination::generateWinSide()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 10
nc 2
nop 8
dl 0
loc 12
ccs 11
cts 11
cp 1
crap 2
rs 9.9332
c 0
b 0
f 0

How to fix   Many Parameters   

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 DoubleElimination extends \TournamentGenerator\Tournament
9
{
10
11 2
	public function generate() {
12 2
		$this->allowSkip();
13
14 2
		$countTeams = count($this->getTeams());
15
16 2
		if ($countTeams < 3) throw new \Exception('Double elimination is possible for minimum of 3 teams - '.$countTeams.' teams given.');
17
18
19
		// CALCULATE BYES
20 2
		$nextPow = 0;
21 2
		$byes = $this->calcByes($countTeams, $nextPow);
22
23 2
		$startRound = $this->round('Start round');
24
25 2
		$roundsNum = log($nextPow, 2)*2;
26
27 2
		$startGroups = ($countTeams+$byes)/2;
28
29 2
		$previousGroups = [];
30 2
		$previousLosingGroups = [];
31 2
		$groupIds = [];
32 2
		$allGroups = [];
33
34 2
		for ($i=1; $i <= $startGroups; $i++) {
35 2
			$g = $startRound->group('Start group - '.$i)->setInGame(2)->setType(\TournamentGenerator\Constants::ROUND_TWO);
36 2
			$allGroups[] = $g;
37 2
			$groupIds[] = $g->getId();
38 2
			$previousGroups[] = $g;
39
		}
40
41
		// SPLIT TEAMS EVENLY
42 2
		$this->splitTeams();
43
44 2
		for ($r=2; $r <= $roundsNum-1; $r++) {
45 2
			$groups = [];
46 2
			$losingGroups = [];
47 2
			$round = $this->round('Round '.$r);
48
49
			// GENERATE GROUPS AND PROGRESSIONS
50
51
			// GENERATING LOSING AND WINNING SIDE
52 2
			$lastLosingGroup = $this->generateLosingSide($r, $round, $allGroups, $previousLosingGroups, $previousGroups, $losingGroups);
53 2
			$this->generateWinSide($r, $byes, $countTeams, $round, $allGroups, $groups, $lastWinningGroup, $previousGroups);
54
55 2
			$previousGroups = $groups;
56 2
			$previousLosingGroups = $losingGroups;
57
		}
58
59
		// LAST ROUND
60 2
		$round = $this->round('Round '.$roundsNum.' - Finale');
61 2
		$groupFinal = $round->group('Round '.$r.' - finale')->setInGame(2)->setType(\TournamentGenerator\Constants::ROUND_TWO)->setOrder(1);
62 2
		$allGroups[] = $groupFinal;
63 2
		$lastLosingGroup->progression($groupFinal, 0, 1);
64 2
		$lastWinningGroup->progression($groupFinal, 0, 1);
65
66
		// REPEAT GROUP IF LOSING TEAM WON
67 2
		$group = $round->group('Round '.$r.' - finale (2)')->setInGame(2)->setType(\TournamentGenerator\Constants::ROUND_TWO)->setOrder(1);
68 2
		$twoLoss = new \TournamentGenerator\TeamFilter('losses', '=', 1, $allGroups);
69 2
		$groupFinal->progression($group, 0, 2)->addFilter($twoLoss);
70
71 2
		return $this;
72
73
	}
74
75 2
	private function calcByes(int $countTeams, int &$nextPow) {
76 2
		$byes = 0;
77 2
		$nextPow = $countTeams;
78 2
		if ( !\TournamentGenerator\isPowerOf2($countTeams) ) {
79 1
			$nextPow = bindec(str_pad(1, strlen(decbin($countTeams))+1, 0, STR_PAD_RIGHT));
80 1
			$byes = $nextPow-$countTeams;
81
		}
82 2
		return $byes;
83
	}
84 2
	private function generateWinSide(int &$r, int &$byes, int &$countTeams, \TournamentGenerator\Round &$round, array &$allGroups, array &$groups, \TournamentGenerator\Group &$lastWinningGroup = null, array &$previousGroups = []) {
85 2
		$order = 1;
86 2
		for ($g=1; $g <= (($countTeams+$byes)/pow(2, $r)); $g++) {
87 2
			$group = $round->group('Round '.$r.' - win '.$g)->setInGame(2)->setType(\TournamentGenerator\Constants::ROUND_TWO)->setOrder($order);
88 2
			$allGroups[] = $group;
89 2
			$order += 2;
90 2
			$groups[] = $group;
91 2
			$lastWinningGroup = $group; // KEEP THE LAST GROUP FOR FINALE
92 2
			$previousGroups[2*($g-1)]->progression($group, 0, 1); // PROGRESS FROM GROUP BEFORE
93 2
			$previousGroups[(2*($g-1))+1]->progression($group, 0, 1); // PROGREESS FROM GROUP BEFORE
94
		}
95 2
		return $this;
96
	}
97 2
	private function generateLosingSide(int &$r, \TournamentGenerator\Round &$round, array &$allGroups, array &$previousLosingGroups = [], array &$previousGroups = [], array &$losingGroups = []) {
98 2
		$losingGroupTeamsCount = count($previousLosingGroups)+count($previousGroups);
99 2
		$order = 2;
100 2
		if (\TournamentGenerator\isPowerOf2($losingGroupTeamsCount)) { // IF THE NUMBER OF TEAMS IS A POWER OF 2, GENERATE GROUPS WITHOUT BYES
101 2
			for ($g=1; $g <= $losingGroupTeamsCount/2; $g++) {
102 2
				$group = $round->group('Round '.$r.' - loss '.$g)->setInGame(2)->setType(\TournamentGenerator\Constants::ROUND_TWO)->setOrder($order);
103 2
				$allGroups[] = $group;
104 2
				$order += 2;
105 2
				$losingGroups[] = $group;
106 2
				$lastLosingGroup = $group; // KEEP THE LAST GROUP FOR FINALE
107 2
				if ($r === 2) { // FIRST LOSING ROUND
108 2
					$previousGroups[2*($g-1)]->progression($group, 1, 1); // PROGRESS FROM STARTING GROUP
109 2
					$previousGroups[(2*($g-1))+1]->progression($group, 1, 1); // PROGREESS FROM STARTING GROUP
110
				}
111 2
				elseif ($losingGroupTeamsCount >= 2) {
112 2
					$previousLosingGroups[$g-1]->progression($group, 0, 1); // PROGRESS FROM LOSING GROUP BEFORE
113 2
					if (isset(array_reverse($previousGroups)[$g-1])) array_reverse($previousGroups)[$g-1]->progression($group, 1, 1); // PROGREESS FROM WINNING GROUP BEFORE
114 2
					else $previousLosingGroups[$g]->progression($group, 0, 1); // PROGRESS OTHER TEAM FROM LOSING GROUP BEEFORE
115
				}
116
			}
117
		}
118
		else { // IF THE NUMBER OF TEAMS IS NOT A POWER OF 2, GENERATE GROUPS WITH BYES
119
			// LOOK FOR THE CLOSEST LOWER POWER OF 2
120 2
			$losingByes = $losingGroupTeamsCount-bindec(str_pad(1, strlen(decbin($losingGroupTeamsCount)), 0, STR_PAD_RIGHT));
121 2
			$n = (floor(count($previousLosingGroups)/2)+$losingByes);
122 2
			$byesGroupsNums = [];
123 2
			$byesProgressed = 0;
124 2
			for ($i=0; $i < $losingByes; $i++) {
125 2
				$byesGroupsNums[] = $n-($i*2);
126
			}
127 2
			$lastGroup = 0;
128 2
			for ($g=1; $g <= ((count($previousLosingGroups)/2)+$losingByes); $g++) {
129 2
				$group = $round->group('Round '.$r.' - loss '.$g)->setInGame(2)->setType(\TournamentGenerator\Constants::ROUND_TWO)->setOrder($order);
130 2
				$allGroups[] = $group;
131 2
				$order += 2;
132 2
				$losingGroups[] = $group;
133 2
				$lastLosingGroup = $group; // KEEP THE LAST GROUP FOR FINALE
134 2
				if (in_array($g, $byesGroupsNums) && isset($previousGroups[$byesProgressed])) { // EMPTY GROUP FROM BYE
135 2
					$previousGroups[$byesProgressed]->progression($group, 1, 1); // PROGRESS FROM WINNING GROUP BEFORE
136 2
					$byesProgressed++;
137
				}
138
				else {
139 2
					$previousLosingGroups[$lastGroup]->progression($group, 0, 1); // PROGRESS FROM LOSING GROUP BEFORE
140 2
					if (isset($previousLosingGroups[$lastGroup + 1])) $previousLosingGroups[$lastGroup + 1]->progression($group, 0, 1); // PROGREESS FROM LOSING GROUP BEFORE
141 2
					$lastGroup += 2;
142
				}
143
			}
144
		}
145 2
		return $lastLosingGroup;
146
	}
147
148
}
149