Test Failed
Push — master ( dda96a...874268 )
by Julien
03:49
created

DirectEliminationTreeGen::run()   B

Complexity

Conditions 6
Paths 16

Size

Total Lines 53
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 53
rs 8.7155
cc 6
eloc 20
nc 16
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
use Xoco70\KendoTournaments\Models\Competitor;
7
use Xoco70\KendoTournaments\Models\Team;
8
9
class DirectEliminationTreeGen implements TreeGenerable
10
{
11
    public $firstRoundName;
12
    public $names;
13
    public $brackets = [];
14
    public $championship;
15
    public $noTeams;
16
    public $noRounds;
17
    public $playerWrapperHeight = 30;
18
    public $matchWrapperWidth = 150;
19
    public $roundSpacing = 40;
20
    public $matchSpacing = 42;
21
    public $borderWidth = 3;
22
23
    public function __construct($names, $championship)
24
    {
25
        $this->championship = $championship;
26
        $this->names = $names;
27
28
        $this->firstRoundName = $names->first()->map(function ($item, $key) use ($championship) {
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed.

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

Loading history...
29
            $fighters = $item->getFighters();
30
            $fighter1 = $fighters->get(0);
31
            $fighter2 = $fighters->get(1);
32
33
            return [$fighter1, $fighter2];
34
        })->flatten()->all();
35
36
        $this->run();
37
38
    }
39
40
    public function run()
41
    {
42
43
        $fighters = $this->firstRoundName;
44
        $this->noTeams = count($fighters);
45
46
47
        //Calculate the size of the first full round - for example if you have 5 fighters, then the first full round will consist of 4 fighters
48
//        $minimumFirstRoundSize = pow(2, ceil(log($this->noTeams) / log(2)));
49
//        dd($this->noTeams);
50
        $this->noRounds = log($this->noTeams, 2);
51
//        $noByesToAdd = $minimumFirstRoundSize - $this->noTeams;
0 ignored issues
show
Unused Code Comprehensibility introduced by
45% 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...
52
//        dd($noByesToAdd);
53
        //Add the byes to the fighters array
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% 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...
54
//        for ($i = 0; $i < $noByesToAdd; $i++) {
55
//            $fighters[] = null;
56
//        }
57
58
59
        //Order the fighters in a seeded order - this is required regardless of whether it is a seeded tournament or not, as it prevents BYEs playing eachother
60
//        $fighters = $this->orderTeamsInSeededOrder($fighters);
61
62
        $roundNumber = 1;
63
64
        //Group 2 fighters into a match
65
        $matches = array_chunk($fighters, 2);
66
67
        //If there's already a match in the match array, then that means the next round is round 2, so increase the round number
68
        if (count($this->brackets)) $roundNumber++;
69
70
        $countMatches = count($matches);
71
        //Create the first full round of fighters, some may be blank if waiting on the results of a previous round
72
        for ($i = 0; $i < $countMatches; $i++) {
73
            $this->brackets[$roundNumber][$i + 1] = $matches[$i];
74
        }
75
76
        //Create the result of the empty rows for this tournament
77
78
        for ($roundNumber += 1; $roundNumber <= $this->noRounds; $roundNumber++) {
79
            for ($matchNumber = 1; $matchNumber <= ($this->noTeams / pow(2, $roundNumber)); $matchNumber++) {
80
                if ($this->championship->category->isTeam()){
81
                    $fighter1 = $this->names->get($roundNumber)[0]->fights[$matchNumber-1]->team1;
82
                    $fighter2 = $this->names->get($roundNumber)[0]->fights[$matchNumber-1]->team2;
83
                }else{
84
                    $fighter1 = $this->names->get($roundNumber)[$matchNumber-1]->fights[0]->competitor1;
85
                    $fighter2 = $this->names->get($roundNumber)[$matchNumber-1]->fights[0]->competitor2;
86
                }
87
                $this->brackets[$roundNumber][$matchNumber] = [$fighter1, $fighter2];
88
            }
89
        }
90
91
        $this->assignPositions();
92
    }
93
94
    private function assignPositions()
95
    {
96
97
        //Variables required for figuring outing the height of the vertical connectors
98
99
        $matchSpacingMultiplier = 0.5;
100
        $playerWrapperHeightMultiplier = 1;
101
102
        foreach ($this->brackets as $roundNumber => &$round) {
103
104
            foreach ($round as $matchNumber => &$match) {
105
106
                //Give teams a nicer index
107
108
                $match['playerA'] = $match[0];
109
                $match['playerB'] = $match[1];
110
111
                unset($match[0]);
112
                unset($match[1]);
113
114
                //Figure out the bracket positions
115
116
                $match['matchWrapperTop'] = (((2 * $matchNumber) - 1) * (pow(2, ($roundNumber) - 1)) - 1) * (($this->matchSpacing / 2) + $this->playerWrapperHeight);
117
                $match['matchWrapperLeft'] = ($roundNumber - 1) * ($this->matchWrapperWidth + $this->roundSpacing - 1);
118
                $match['vConnectorLeft'] = floor($match['matchWrapperLeft'] + $this->matchWrapperWidth + ($this->roundSpacing / 2) - ($this->borderWidth / 2));
119
                $match['vConnectorHeight'] = ($matchSpacingMultiplier * $this->matchSpacing) + ($playerWrapperHeightMultiplier * $this->playerWrapperHeight) + $this->borderWidth;
120
                $match['vConnectorTop'] = $match['hConnectorTop'] = $match['matchWrapperTop'] + $this->playerWrapperHeight;
121
                $match['hConnectorLeft'] = ($match['vConnectorLeft'] - ($this->roundSpacing / 2)) + 2;
122
                $match['hConnector2Left'] = $match['matchWrapperLeft'] + $this->matchWrapperWidth + ($this->roundSpacing / 2);
123
124
                //Adjust the positions depending on the match number
125
126
                if (!($matchNumber % 2)) {
127
                    $match['hConnector2Top'] = $match['vConnectorTop'] -= ($match['vConnectorHeight'] - $this->borderWidth);
128
                } else {
129
                    $match['hConnector2Top'] = $match['vConnectorTop'] + ($match['vConnectorHeight'] - $this->borderWidth);
130
                }
131
132
            }
133
134
            //Update the spacing variables
135
136
            $matchSpacingMultiplier *= 2;
137
            $playerWrapperHeightMultiplier *= 2;
138
139
        }
140
141
    }
142
143
    public function printBrackets()
144
    {
145
146
        $this->printRoundTitles();
147
148
        echo '<div id="brackets-wrapper">';
149
150
        foreach ($this->brackets as $roundNumber => $round) {
151
152
            foreach ($round as $matchNumber => $match) {
153
154
                echo '<div class="match-wrapper" style="top: ' . $match['matchWrapperTop'] . 'px; left: ' . $match['matchWrapperLeft'] . 'px; width: ' . $this->matchWrapperWidth . 'px;">
155
                        <input type="text" class="score">'
156
                    . $this->getPlayerList($match['playerA']) .
157
                    '<div class="match-divider">
158
                        </div>
159
                        <input type="text" class="score">'
160
                    . $this->getPlayerList($match['playerB']) .
161
                    '</div>';
162
163
                if ($roundNumber != $this->noRounds) {
164
165
                    echo '<div class="vertical-connector" style="top: ' . $match['vConnectorTop'] . 'px; left: ' . $match['vConnectorLeft'] . 'px; height: ' . $match['vConnectorHeight'] . 'px;"></div>
166
                          <div class="horizontal-connector" style="top: ' . $match['hConnectorTop'] . 'px; left: ' . $match['hConnectorLeft'] . 'px;"></div>
167
                          <div class="horizontal-connector" style="top: ' . $match['hConnector2Top'] . 'px; left: ' . $match['hConnector2Left'] . 'px;"></div>';
168
169
                }
170
171
            }
172
173
        }
174
175
        echo '</div>';
176
177
    }
178
179
    /**
180
     * Print Round Titles
181
     */
182
    public function printRoundTitles()
183
    {
184
185
        if ($this->noTeams == 2) {
186
187
            $roundTitles = array('Final');
188
189
        } elseif ($this->noTeams <= 4) {
190
191
            $roundTitles = array('Semi-Finals', 'Final');
192
193
        } elseif ($this->noTeams <= 8) {
194
195
            $roundTitles = array('Quarter-Finals', 'Semi-Finals', 'Final');
196
197
        } else {
198
199
            $roundTitles = array('Quarter-Finals', 'Semi-Finals', 'Final');
200
            $noRounds = ceil(log($this->noTeams, 2));
201
            $noTeamsInFirstRound = pow(2, ceil(log($this->noTeams) / log(2)));
202
            $tempRounds = array();
203
204
            //The minus 3 is to ignore the final, semi final and quarter final rounds
205
206
            for ($i = 0; $i < $noRounds - 3; $i++) {
207
                $tempRounds[] = 'Last ' . $noTeamsInFirstRound;
208
                $noTeamsInFirstRound /= 2;
209
            }
210
211
            $roundTitles = array_merge($tempRounds, $roundTitles);
212
213
        }
214
215
        echo '<div id="round-titles-wrapper">';
216
217
        foreach ($roundTitles as $key => $roundTitle) {
218
219
            $left = $key * ($this->matchWrapperWidth + $this->roundSpacing - 1);
220
221
            echo '<div class="round-title" style="left: ' . $left . 'px;">' . $roundTitle . '</div>';
222
223
        }
224
225
        echo '</div>';
226
227
    }
228
229
    /**
230
     * @param $selected
231
     * @return string
232
     */
233
    public function getPlayerList($selected)
234
    {
235
236
        $html = '<select>
237
                <option' . ($selected == '' ? ' selected' : '') . '></option>';
238
        foreach (array_merge($this->brackets[1], $this->brackets[2]) as $bracket) { // Bug Fix 24-02-2017
239 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...
240
                $html .= '<option' . ($selected == $bracket['playerA'] ? ' selected' : '') . '>' . $bracket['playerA'] . '</option>';
241
            }
242
243 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...
244
                $html .= '<option' . ($selected == $bracket['playerB'] ? ' selected' : '') . '>' . $bracket['playerB'] . '</option>';
245
            }
246
        }
247
248
        $html .= '</select>';
249
250
        return $html;
251
252
    }
253
254
    /**
255
     * @param $teams
256
     * @return array
257
     */
258
    private function orderTeamsInSeededOrder($teams): array
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
259
    {
260
        $logNoTeam = log($this->noTeams / 2, 2);
261
262
        for ($i = 0; $i < $logNoTeam; $i++) {
263
264
            $out = [];
265
266
            foreach ($teams as $player) {
267
                $splice = pow(2, $i);
268
                $out = array_merge($out, array_splice($teams, 0, $splice));
269
                $out = array_merge($out, array_splice($teams, -$splice));
270
            }
271
272
            $teams = $out;
273
274
        }
275
        return $teams;
276
    }
277
278
    public function getNewFighter()
279
    {
280
        if ($this->championship->category->isTeam()) {
281
            return new Team;
282
        }
283
        return new Competitor;
284
    }
285
}
286