Test Failed
Push — master ( 42684e...2841c5 )
by Julien
11:02
created

DirectEliminationTreeGen::run()   C

Complexity

Conditions 7
Paths 48

Size

Total Lines 70
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 70
rs 6.8519
cc 7
eloc 20
nc 48
nop 0

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 Xoco70\KendoTournaments\TreeGen;
4
5
use Xoco70\KendoTournaments\Contracts\TreeGenerable;
6
7
class DirectEliminationTreeGen implements TreeGenerable
8
{
9
    public $names;
10
    public $brackets = array();
11
    public $noTeams;
12
    public $noRounds;
13
    public $playerWrapperHeight = 30;
14
    public $matchWrapperWidth = 150;
15
    public $roundSpacing = 40;
16
    public $matchSpacing = 42;
17
    public $borderWidth = 3;
18
19
    public function __construct($names)
20
    {
21
22
        $this->names = $names;
23
24
        $this->run();
25
26
    }
27
28
    public function run()
29
    {
30
        $teams = [];
31
        //If no names have been entered, then use numbers
32
33
        if ($this->names != '') {
34
            $teams = $this->names;
35
            $this->noTeams = count($teams);
36
        }
37
38
39
        //Calculate the size of the first full round - for example if you have 5 teams, then the first full round will consist of 4 teams
40
        $minimumFirstRoundSize = pow(2, ceil(log($this->noTeams) / log(2)));
41
        $this->noRounds = log($minimumFirstRoundSize, 2);
42
        $noByesToAdd = $minimumFirstRoundSize - $this->noTeams;
43
44
        //Add the byes to the teams array
45
        for ($i = 0; $i < $noByesToAdd; $i++) {
46
            $teams[] = null;
47
        }
48
49
50
        //Order the teams in a seeded order - this is required regardless of whether it is a seeded tournament or not, as it prevents BYEs playing eachother
51
//        $teams = $this->orderTeamsInSeededOrder($teams);
52
53
        $roundNumber = 1;
54
55
        //Group 2 teams into a match
56
        $matches = array_chunk($teams, 2);
57
58
//        if ($this->noTeams > 2) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
42% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
59
//
60
//            foreach ($matches as $key => &$match) {
61
//
62
//                $matchNumber = $key + 1;
63
//
64
//
65
//                //Add the match to the first round
66
//                $this->brackets[$roundNumber][$matchNumber] = $match;
67
//
68
//                //Set the match to null as the result of the above match hasn't yet been determined
69
//                $match = null;
70
//
71
//
72
//            }
73
//
74
//            //Now all of the blank spaces except the ones awaiting first round results have gone, group the single dimension array into a multiple dimensional array, so opponents share the same parent array
75
//            $matches = array_chunk($matches, 2);
76
//
77
//        }
78
79
80
        //If there's already a match in the match array, then that means the next round is round 2, so increase the round number
81
        if (count($this->brackets)) $roundNumber++;
82
83
        $countMatches = count($matches);
84
        //Create the first full round of teams, some may be blank if waiting on the results of a previous round
85
        for ($i = 0; $i < $countMatches; $i++) {
86
            $this->brackets[$roundNumber][$i + 1] = $matches[$i];
87
        }
88
89
        //Create the result of the empty rows for this tournament
90
91
        for ($roundNumber += 1; $roundNumber <= $this->noRounds; $roundNumber++) {
92
            for ($matchNumber = 1; $matchNumber <= ($minimumFirstRoundSize / pow(2, $roundNumber)); $matchNumber++) {
93
                $this->brackets[$roundNumber][$matchNumber] = array(null, null);
94
            }
95
        }
96
        $this->assignPositions();
97
    }
98
99
    private function assignPositions()
100
    {
101
102
        //Variables required for figuring outing the height of the vertical connectors
103
104
        $matchSpacingMultiplier = 0.5;
105
        $playerWrapperHeightMultiplier = 1;
106
107
        foreach ($this->brackets as $roundNumber => &$round) {
108
109
            foreach ($round as $matchNumber => &$match) {
110
111
                //Give teams a nicer index
112
113
                $match['playerA'] = $match[0];
114
                $match['playerB'] = $match[1];
115
116
                unset($match[0]);
117
                unset($match[1]);
118
119
                //Figure out the bracket positions
120
121
                $match['matchWrapperTop'] = (((2 * $matchNumber) - 1) * (pow(2, ($roundNumber) - 1)) - 1) * (($this->matchSpacing / 2) + $this->playerWrapperHeight);
122
                $match['matchWrapperLeft'] = ($roundNumber - 1) * ($this->matchWrapperWidth + $this->roundSpacing - 1);
123
                $match['vConnectorLeft'] = floor($match['matchWrapperLeft'] + $this->matchWrapperWidth + ($this->roundSpacing / 2) - ($this->borderWidth / 2));
124
                $match['vConnectorHeight'] = ($matchSpacingMultiplier * $this->matchSpacing) + ($playerWrapperHeightMultiplier * $this->playerWrapperHeight) + $this->borderWidth;
125
                $match['vConnectorTop'] = $match['hConnectorTop'] = $match['matchWrapperTop'] + $this->playerWrapperHeight;
126
                $match['hConnectorLeft'] = ($match['vConnectorLeft'] - ($this->roundSpacing / 2)) + 2;
127
                $match['hConnector2Left'] = $match['matchWrapperLeft'] + $this->matchWrapperWidth + ($this->roundSpacing / 2);
128
129
                //Adjust the positions depending on the match number
130
131
                if (!($matchNumber % 2)) {
132
                    $match['hConnector2Top'] = $match['vConnectorTop'] -= ($match['vConnectorHeight'] - $this->borderWidth);
133
                } else {
134
                    $match['hConnector2Top'] = $match['vConnectorTop'] + ($match['vConnectorHeight'] - $this->borderWidth);
135
                }
136
137
            }
138
139
            //Update the spacing variables
140
141
            $matchSpacingMultiplier *= 2;
142
            $playerWrapperHeightMultiplier *= 2;
143
144
        }
145
146
    }
147
148
    public function printBrackets()
149
    {
150
151
//        $this->printRoundTitles();
0 ignored issues
show
Unused Code Comprehensibility introduced by
47% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
152
//
153
//        echo '<div id="brackets-wrapper">';
154
//
155
//        foreach ($this->brackets as $roundNumber => $round) {
156
//
157
//            foreach ($round as $matchNumber => $match) {
158
//
159
//                echo '<div class="match-wrapper" style="top: ' . $match['matchWrapperTop'] . 'px; left: ' . $match['matchWrapperLeft'] . 'px; width: ' . $this->matchWrapperWidth . 'px;">
160
//                        <input type="text" class="score">'
161
//                    . $this->getPlayerList($match['playerA']) .
162
//                    '<div class="match-divider">
163
//                        </div>
164
//                        <input type="text" class="score">'
165
//                    . $this->getPlayerList($match['playerB']) .
166
//                    '</div>';
167
//
168
//                if ($roundNumber != $this->noRounds) {
169
//
170
//                    echo '<div class="vertical-connector" style="top: ' . $match['vConnectorTop'] . 'px; left: ' . $match['vConnectorLeft'] . 'px; height: ' . $match['vConnectorHeight'] . 'px;"></div>
171
//                          <div class="horizontal-connector" style="top: ' . $match['hConnectorTop'] . 'px; left: ' . $match['hConnectorLeft'] . 'px;"></div>
172
//                          <div class="horizontal-connector" style="top: ' . $match['hConnector2Top'] . 'px; left: ' . $match['hConnector2Left'] . 'px;"></div>';
173
//
174
//                }
175
//
176
//            }
177
//
178
//        }
179
//
180
//        echo '</div>';
181
182
    }
183
184
    /**
185
     * Print Round Titles
186
     */
187
    public function printRoundTitles()
188
    {
189
190
        if ($this->noTeams == 2) {
191
192
            $roundTitles = array('Final');
193
194
        } elseif ($this->noTeams <= 4) {
195
196
            $roundTitles = array('Semi-Finals', 'Final');
197
198
        } elseif ($this->noTeams <= 8) {
199
200
            $roundTitles = array('Quarter-Finals', 'Semi-Finals', 'Final');
201
202
        } else {
203
204
            $roundTitles = array('Quarter-Finals', 'Semi-Finals', 'Final');
205
            $noRounds = ceil(log($this->noTeams, 2));
206
            $noTeamsInFirstRound = pow(2, ceil(log($this->noTeams) / log(2)));
207
            $tempRounds = array();
208
209
            //The minus 3 is to ignore the final, semi final and quarter final rounds
210
211
            for ($i = 0; $i < $noRounds - 3; $i++) {
212
                $tempRounds[] = 'Last ' . $noTeamsInFirstRound;
213
                $noTeamsInFirstRound /= 2;
214
            }
215
216
            $roundTitles = array_merge($tempRounds, $roundTitles);
217
218
        }
219
220
        echo '<div id="round-titles-wrapper">';
221
222
        foreach ($roundTitles as $key => $roundTitle) {
223
224
            $left = $key * ($this->matchWrapperWidth + $this->roundSpacing - 1);
225
226
            echo '<div class="round-title" style="left: ' . $left . 'px;">' . $roundTitle . '</div>';
227
228
        }
229
230
        echo '</div>';
231
232
    }
233
234
    /**
235
     * @param $selected
236
     * @return string
237
     */
238
    public function getPlayerList($selected)
239
    {
240
241
        $html = '<select>
242
                <option' . ($selected == '' ? ' selected' : '') . '></option>';
243
        foreach (array_merge($this->brackets[1]) as $bracket) { // Bug Fix 24-02-2017 , $this->brackets[2]
0 ignored issues
show
Unused Code Comprehensibility introduced by
48% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
244 View Code Duplication
            if ($bracket['playerA'] != '') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
245
                $html .= '<option' . ($selected == $bracket['playerA'] ? ' selected' : '') . '>' . $bracket['playerA'] . '</option>';
246
            }
247
248 View Code Duplication
            if ($bracket['playerB'] != '') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
249
                $html .= '<option' . ($selected == $bracket['playerB'] ? ' selected' : '') . '>' . $bracket['playerB'] . '</option>';
250
            }
251
        }
252
253
        $html .= '</select>';
254
255
        return $html;
256
257
    }
258
259
    /**
260
     * @param $teams
261
     * @return array
262
     */
263
    private function orderTeamsInSeededOrder($teams): array
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
264
    {
265
        $logNoTeam = log($this->noTeams / 2, 2);
266
267
        for ($i = 0; $i < $logNoTeam; $i++) {
268
269
            $out = [];
270
271
            foreach ($teams as $player) {
272
                $splice = pow(2, $i);
273
                $out = array_merge($out, array_splice($teams, 0, $splice));
274
                $out = array_merge($out, array_splice($teams, -$splice));
275
            }
276
277
            $teams = $out;
278
279
        }
280
        return $teams;
281
    }
282
}
283